Commit cc7c0b0e authored by Peter Hutterer's avatar Peter Hutterer Committed by Hans de Goede

xkb: after changing the keymap, force an indicator update

When NumLock is on and a new keymap is applied, the next modifier state
change will turn off that LED (but leave the state enabled). The cause
for this is a bit convoluted:

* the SLI explicitState is copied from the current state in
  ProcXkbGetKbdByName. Thus, if NumLock is on, that state is 0x2.
* on the next modifier key press (e.g. Shift), XkbApplyState() calls into
  XkbUpdateIndicators() -> XkbUpdateLedAutoState() to update SLIs (if any)
  for the currently changed modifier. But it does so with a mask only for
  the changed modifier (i.e. for Shift).
* XkbUpdateLedAutoState() calculates the state based on this mask and
  ends up with 0 because we don't have a Shift LED and we masked out the
  others.
* XkbUpdateLedAutoState() compares that state with the previous state
  (which is still 0x2) and then proceeds to turn the LED off

This doesn't happen in the normal case because either the mask
encompasses all modifiers or the state matches of the masked-out
modifiers matches the old state.

Avoid this issue by forcing an SLI update after changing the keymap.
This updates the sli->effectiveState and thus restores everything to
happy working order.

https://bugzilla.redhat.com/show_bug.cgi?id=1047151Signed-off-by: 's avatarPeter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: 's avatarDaniel Stone <daniels@collabora.com>
(cherry picked from commit ac164e58)
parent bcb633ca
......@@ -496,6 +496,10 @@ extern _X_EXPORT void XkbUpdateIndicators(DeviceIntPtr /* keybd */ ,
XkbEventCausePtr /* cause */
);
extern _X_EXPORT void XkbUpdateAllDeviceIndicators(XkbChangesPtr /* changes */,
XkbEventCausePtr /* cause */
);
extern _X_EXPORT XkbSrvLedInfoPtr XkbAllocSrvLedInfo(DeviceIntPtr /* dev */ ,
KbdFeedbackPtr /* kf */ ,
LedFeedbackPtr /* lf */ ,
......
......@@ -5692,7 +5692,6 @@ ProcXkbListComponents(ClientPtr client)
}
/***====================================================================***/
int
ProcXkbGetKbdByName(ClientPtr client)
{
......@@ -6017,6 +6016,8 @@ ProcXkbGetKbdByName(ClientPtr client)
new = NULL;
}
XkbFreeComponentNames(&names, FALSE);
XkbUpdateAllDeviceIndicators(NULL, NULL);
return Success;
}
......
......@@ -304,7 +304,7 @@ XkbUpdateLedAutoState(DeviceIntPtr dev,
return;
}
static void
void
XkbUpdateAllDeviceIndicators(XkbChangesPtr changes, XkbEventCausePtr cause)
{
DeviceIntPtr edev;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment