Track keyboard modifiers on a per-seat basis

* seat.c (MakeSeatForDevicePair): Get keyboard state and select
for events from the master keyboard.
(UpdateModifiersForSeats): Rename to UpdateModifierForSeat.
Accept seat arg.
(SetupKeymap): Stop selecting for state changes here.
(HandleXkbEvent): Associate each XkbStateNotify with an
extension device's keyboard.
This commit is contained in:
hujianwei 2022-11-13 03:00:08 +00:00
parent 442f80b667
commit 3244ab82f2

77
seat.c
View file

@ -1790,6 +1790,7 @@ MakeSeatForDevicePair (int master_keyboard, int master_pointer,
{ {
Seat *seat; Seat *seat;
XkbStateRec state; XkbStateRec state;
unsigned long mask;
seat = XLCalloc (1, sizeof *seat); seat = XLCalloc (1, sizeof *seat);
seat->master_keyboard = master_keyboard; seat->master_keyboard = master_keyboard;
@ -1811,7 +1812,16 @@ MakeSeatForDevicePair (int master_keyboard, int master_pointer,
live_seats = XLListPrepend (live_seats, seat); live_seats = XLListPrepend (live_seats, seat);
/* Now update the seat state from the X server. */ /* Now update the seat state from the X server. */
XkbGetState (compositor.display, XkbUseCoreKbd, &state); CatchXErrors ();
XkbGetState (compositor.display, master_keyboard, &state);
if (UncatchXErrors (NULL))
/* If the device was disabled or removed, a HierarchyChange event
will be sent shortly afterwards, causing the seat to be
destroyed. In that case, not selecting for modifier changes
will be inconsequential. */
return;
seat->base = state.base_mods; seat->base = state.base_mods;
seat->locked = state.locked_mods; seat->locked = state.locked_mods;
@ -1821,6 +1831,27 @@ MakeSeatForDevicePair (int master_keyboard, int master_pointer,
seat->latched_group = state.latched_group; seat->latched_group = state.latched_group;
seat->effective_group = state.group; seat->effective_group = state.group;
/* And select for XKB events from the master keyboard device. If
the server does not support accessing input extension devices
with Xkb, an error will result. */
mask = 0;
mask |= XkbModifierStateMask;
mask |= XkbModifierBaseMask;
mask |= XkbModifierLatchMask;
mask |= XkbModifierLockMask;
mask |= XkbGroupStateMask;
mask |= XkbGroupBaseMask;
mask |= XkbGroupLatchMask;
mask |= XkbGroupLockMask;
CatchXErrors ();
XkbSelectEventDetails (compositor.display, master_keyboard,
/* Now enable everything in that mask. */
XkbStateNotify, mask, mask);
UncatchXErrors (NULL);
UpdateValuators (seat, pointer_info); UpdateValuators (seat, pointer_info);
RetainSeat (seat); RetainSeat (seat);
} }
@ -2873,22 +2904,12 @@ SendUpdatedModifiers (Seat *seat)
} }
static void static void
UpdateModifiersForSeats (unsigned int base, unsigned int locked, UpdateModifiersForSeat (Seat *seat,
unsigned int base, unsigned int locked,
unsigned int latched, int base_group, unsigned int latched, int base_group,
int locked_group, int latched_group, int locked_group, int latched_group,
int effective_group) int effective_group)
{ {
Seat *seat;
XLList *tem;
for (tem = live_seats; tem; tem = tem->next)
{
seat = tem->data;
/* If the seat is a test seat, ignore. */
if (seat->flags & IsTestSeat)
continue;
seat->base = base; seat->base = base;
seat->locked = locked; seat->locked = locked;
seat->latched = latched; seat->latched = latched;
@ -2899,7 +2920,6 @@ UpdateModifiersForSeats (unsigned int base, unsigned int locked,
SendUpdatedModifiers (seat); SendUpdatedModifiers (seat);
} }
}
static void static void
SetFocusSurface (Seat *seat, Surface *focus) SetFocusSurface (Seat *seat, Surface *focus)
@ -4833,7 +4853,7 @@ UpdateKeymapInfo (void)
static void static void
SetupKeymap (void) SetupKeymap (void)
{ {
int xkb_major, xkb_minor, xkb_op, xkb_error_code, mask; int xkb_major, xkb_minor, xkb_op, xkb_error_code;
xkb_major = XkbMajorVersion; xkb_major = XkbMajorVersion;
xkb_minor = XkbMinorVersion; xkb_minor = XkbMinorVersion;
@ -4861,29 +4881,14 @@ SetupKeymap (void)
XkbSelectEvents (compositor.display, XkbUseCoreKbd, XkbSelectEvents (compositor.display, XkbUseCoreKbd,
XkbMapNotifyMask | XkbNewKeyboardNotifyMask, XkbMapNotifyMask | XkbNewKeyboardNotifyMask,
XkbMapNotifyMask | XkbNewKeyboardNotifyMask); XkbMapNotifyMask | XkbNewKeyboardNotifyMask);
/* Select for keyboard state changes too. */
mask = 0;
mask |= XkbModifierStateMask;
mask |= XkbModifierBaseMask;
mask |= XkbModifierLatchMask;
mask |= XkbModifierLockMask;
mask |= XkbGroupStateMask;
mask |= XkbGroupBaseMask;
mask |= XkbGroupLatchMask;
mask |= XkbGroupLockMask;
XkbSelectEventDetails (compositor.display, XkbUseCoreKbd,
/* Now enable everything in that mask. */
XkbStateNotify, mask, mask);
UpdateKeymapInfo (); UpdateKeymapInfo ();
} }
static Bool static Bool
HandleXkbEvent (XkbEvent *event) HandleXkbEvent (XkbEvent *event)
{ {
Seat *seat;
if (event->any.xkb_type == XkbMapNotify if (event->any.xkb_type == XkbMapNotify
|| event->any.xkb_type == XkbNewKeyboardNotify) || event->any.xkb_type == XkbNewKeyboardNotify)
{ {
@ -4909,7 +4914,13 @@ HandleXkbEvent (XkbEvent *event)
} }
else if (event->any.xkb_type == XkbStateNotify) else if (event->any.xkb_type == XkbStateNotify)
{ {
UpdateModifiersForSeats (event->state.base_mods, /* Look up the seat to which this event corresponds. */
seat = XLLookUpAssoc (seats, event->state.device);
/* And update the modifiers for that seat. */
if (seat)
UpdateModifiersForSeat (seat,
event->state.base_mods,
event->state.locked_mods, event->state.locked_mods,
event->state.latched_mods, event->state.latched_mods,
event->state.base_group, event->state.base_group,