91 lines
3.1 KiB
Diff
91 lines
3.1 KiB
Diff
From 0d2fea8a8ce5e1d2693c25dbeff00461c72427a2 Mon Sep 17 00:00:00 2001
|
|
From: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Date: Fri, 29 Apr 2016 15:56:03 +1000
|
|
Subject: [PATCH xserver] 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=1047151
|
|
|
|
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
|
|
---
|
|
include/xkbsrv.h | 4 ++++
|
|
xkb/xkb.c | 3 ++-
|
|
xkb/xkbLEDs.c | 2 +-
|
|
3 files changed, 7 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
|
|
index cc6307a..7e71089 100644
|
|
--- a/include/xkbsrv.h
|
|
+++ b/include/xkbsrv.h
|
|
@@ -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 */ ,
|
|
diff --git a/xkb/xkb.c b/xkb/xkb.c
|
|
index 294cdf8..3a6ad65 100644
|
|
--- a/xkb/xkb.c
|
|
+++ b/xkb/xkb.c
|
|
@@ -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;
|
|
}
|
|
|
|
diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c
|
|
index 4e16002..5792d9f 100644
|
|
--- a/xkb/xkbLEDs.c
|
|
+++ b/xkb/xkbLEDs.c
|
|
@@ -304,7 +304,7 @@ XkbUpdateLedAutoState(DeviceIntPtr dev,
|
|
return;
|
|
}
|
|
|
|
-static void
|
|
+void
|
|
XkbUpdateAllDeviceIndicators(XkbChangesPtr changes, XkbEventCausePtr cause)
|
|
{
|
|
DeviceIntPtr edev;
|
|
--
|
|
2.7.4
|
|
|