Bug 1792676 [Wayland] Set modifiers according to key press/release r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D184228
This commit is contained in:
stransky 2023-07-24 09:11:57 +00:00
parent c6f8729f11
commit f62c9fb763
2 changed files with 77 additions and 27 deletions

View File

@ -1734,6 +1734,79 @@ bool KeymapWrapper::HandleKeyReleaseEvent(nsWindow* aWindow,
return true;
}
guint KeymapWrapper::GetModifierState(GdkEventKey* aGdkKeyEvent,
KeymapWrapper* aWrapper) {
guint state = aGdkKeyEvent->state;
if (!aGdkKeyEvent->is_modifier) {
return state;
}
#ifdef MOZ_X11
// NOTE: The state of given key event indicates adjacent state of
// modifier keys. E.g., even if the event is Shift key press event,
// the bit for Shift is still false. By the same token, even if the
// event is Shift key release event, the bit for Shift is still true.
// Unfortunately, gdk_keyboard_get_modifiers() returns current modifier
// state. It means if there're some pending modifier key press or
// key release events, the result isn't what we want.
GdkDisplay* gdkDisplay = gdk_display_get_default();
if (GdkIsX11Display(gdkDisplay)) {
GdkDisplay* gdkDisplay = gdk_display_get_default();
Display* display = gdk_x11_display_get_xdisplay(gdkDisplay);
if (XEventsQueued(display, QueuedAfterReading)) {
XEvent nextEvent;
XPeekEvent(display, &nextEvent);
if (nextEvent.type == aWrapper->mXKBBaseEventCode) {
XkbEvent* XKBEvent = (XkbEvent*)&nextEvent;
if (XKBEvent->any.xkb_type == XkbStateNotify) {
XkbStateNotifyEvent* stateNotifyEvent =
(XkbStateNotifyEvent*)XKBEvent;
state &= ~0xFF;
state |= stateNotifyEvent->lookup_mods;
}
}
}
return state;
}
#endif
#ifdef MOZ_WAYLAND
int mask = 0;
switch (aGdkKeyEvent->keyval) {
case GDK_Shift_L:
case GDK_Shift_R:
mask = aWrapper->GetModifierMask(SHIFT);
break;
case GDK_Control_L:
case GDK_Control_R:
mask = aWrapper->GetModifierMask(CTRL);
break;
case GDK_Alt_L:
case GDK_Alt_R:
mask = aWrapper->GetModifierMask(ALT);
break;
case GDK_Super_L:
case GDK_Super_R:
mask = aWrapper->GetModifierMask(SUPER);
break;
case GDK_Hyper_L:
case GDK_Hyper_R:
mask = aWrapper->GetModifierMask(HYPER);
break;
case GDK_Meta_L:
case GDK_Meta_R:
mask = aWrapper->GetModifierMask(META);
break;
default:
break;
}
if (aGdkKeyEvent->type == GDK_KEY_PRESS) {
state |= mask;
} else {
state &= ~mask;
}
return state;
#endif
}
/* static */
void KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
GdkEventKey* aGdkKeyEvent,
@ -1771,33 +1844,7 @@ void KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
aKeyEvent.mKeyCode = 0;
}
// NOTE: The state of given key event indicates adjacent state of
// modifier keys. E.g., even if the event is Shift key press event,
// the bit for Shift is still false. By the same token, even if the
// event is Shift key release event, the bit for Shift is still true.
// Unfortunately, gdk_keyboard_get_modifiers() returns current modifier
// state. It means if there're some pending modifier key press or
// key release events, the result isn't what we want.
guint modifierState = aGdkKeyEvent->state;
GdkDisplay* gdkDisplay = gdk_display_get_default();
#ifdef MOZ_X11
if (aGdkKeyEvent->is_modifier && GdkIsX11Display(gdkDisplay)) {
Display* display = gdk_x11_display_get_xdisplay(gdkDisplay);
if (XEventsQueued(display, QueuedAfterReading)) {
XEvent nextEvent;
XPeekEvent(display, &nextEvent);
if (nextEvent.type == keymapWrapper->mXKBBaseEventCode) {
XkbEvent* XKBEvent = (XkbEvent*)&nextEvent;
if (XKBEvent->any.xkb_type == XkbStateNotify) {
XkbStateNotifyEvent* stateNotifyEvent =
(XkbStateNotifyEvent*)XKBEvent;
modifierState &= ~0xFF;
modifierState |= stateNotifyEvent->lookup_mods;
}
}
}
}
#endif
const guint modifierState = GetModifierState(aGdkKeyEvent, keymapWrapper);
InitInputEvent(aKeyEvent, modifierState);
switch (aGdkKeyEvent->keyval) {

View File

@ -492,6 +492,9 @@ class KeymapWrapper {
void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent,
GdkEventKey* aGdkKeyEvent);
static guint GetModifierState(GdkEventKey* aGdkKeyEvent,
KeymapWrapper* aWrapper);
#ifdef MOZ_WAYLAND
/**
* Utility function to set Xkb modifier key mask.