windowmaker-wl/src/backend/wayland/wl_keyboard.c

113 lines
4.1 KiB
C

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/util/log.h>
#include <wlr/backend/session.h>
#include <xkbcommon/xkbcommon.h>
#include "../../screen.h"
/* Forward declarations */
int wWaylandKeyPress(unsigned int keycode, unsigned int modifiers);
#include "wl_types.h"
#include <WINGs/WINGsP.h>
/* Forward declarations */
WMScreen *wl_get_wmscreen(void);
void W_WL_EnqueueEvent(struct W_Screen *scr, const WMEvent *ev, struct W_View *target);
void
handle_keyboard_key(struct wl_listener *listener, void *data)
{
struct wlr_keyboard_key_event *event = data;
(void)listener;
if (!wl_state.seat)
return;
struct wlr_keyboard *kb = wl_state.seat->keyboard_state.keyboard;
if (!kb) {
wwarning("handle_keyboard_key: no seat keyboard for event keycode=%u dev=%p", event->keycode, (void*)wl_state.keyboard_dev);
return;
}
wlr_seat_keyboard_notify_modifiers(wl_state.seat, &kb->modifiers);
uint32_t keycode = event->keycode + 8;
uint32_t modifiers = wlr_keyboard_get_modifiers(kb);
if (wl_state.session && event->state == WL_KEYBOARD_KEY_STATE_PRESSED &&
(modifiers & (WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT)) ==
(WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT)) {
xkb_keysym_t sym = xkb_state_key_get_one_sym(kb->xkb_state, keycode);
if (sym >= XKB_KEY_XF86Switch_VT_1 && sym <= XKB_KEY_XF86Switch_VT_12) {
wlr_session_change_vt(wl_state.session, sym - XKB_KEY_XF86Switch_VT_1 + 1);
return;
}
}
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
if (!wl_state.keyboard_grabbed && wWaylandKeyPress((unsigned int)keycode, (unsigned int)modifiers))
return;
}
WMScreen *wmscr = wl_get_wmscreen();
if (wmscr) {
WMEvent ev;
memset(&ev, 0, sizeof(ev));
ev.type = (event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
? WME_KEY_PRESS : WME_KEY_RELEASE;
W_FocusInfo *finfo = wmscr->focusInfo;
W_View *target = (finfo && finfo->focused) ? finfo->focused
: (finfo && finfo->toplevel) ? finfo->toplevel : NULL;
if (!target && wmscr->modalView)
target = wmscr->modalView;
ev.window = target ? (WNativeWindow)target->window : WNATIVE_NONE;
ev.u.key.keycode = keycode;
ev.u.key.state = modifiers;
ev.u.key.time = event->time_msec;
ev.u.key.x = wl_state.pointer_x;
ev.u.key.y = wl_state.pointer_y;
ev.u.key.x_root = wl_state.pointer_x;
ev.u.key.y_root = wl_state.pointer_y;
if (kb->xkb_state) {
ev.u.key.keysym = xkb_state_key_get_one_sym(kb->xkb_state, keycode);
ev.u.key.utf8_len = xkb_state_key_get_utf8(kb->xkb_state, keycode,
ev.u.key.utf8, sizeof(ev.u.key.utf8));
if (ev.u.key.utf8_len >= (int)sizeof(ev.u.key.utf8))
ev.u.key.utf8_len = 0;
} else {
wwarning("handle_keyboard_key: kb->xkb_state is NULL, dropping key event (keycode=%u dev=%p seat_kb=%p)",
keycode, (void*)wl_state.keyboard_dev, (void*)kb);
return;
}
W_WL_EnqueueEvent(wmscr, &ev, NULL);
}
if (!wl_state.keyboard_grabbed && wl_state.seat->keyboard_state.focused_surface)
wlr_seat_keyboard_notify_key(wl_state.seat,
event->time_msec, event->keycode, event->state);
}
void
handle_keyboard_modifiers(struct wl_listener *listener, void *data)
{
(void)listener; (void)data;
if (!wl_state.seat) return;
struct wlr_keyboard *kb = wl_state.seat->keyboard_state.keyboard;
if (!kb) return;
wlr_seat_keyboard_notify_modifiers(wl_state.seat, &kb->modifiers);
/* Cache the real keyboard's depressed modifiers so pointer button
* handlers can read them regardless of which keyboard the seat
* currently has focused (e.g. XWayland virtual keyboard). */
wl_state.current_mods = kb->modifiers.depressed;
}