dix: Force update LEDs after device state update in EnableDevice

This is to make sure the hardware gets the device states regardless
whether the internal state has changed or not, to overcome situations
that device LEDs are out of sync e.g. switching between VTs.

Signed-off-by: Yao Wei (魏銘廷) <yao.wei@canonical.com>
This commit is contained in:
Yao Wei 2023-02-21 03:43:05 +00:00 committed by Peter Hutterer
parent d2158d4063
commit 7ce57e179b
3 changed files with 44 additions and 0 deletions

View File

@ -422,6 +422,10 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent)
if (!IsMaster(dev) && !IsFloating(dev))
XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0);
/* Now make sure our LEDs are in sync with the locked state */
XkbForceUpdateDeviceLEDs(dev);
RecalculateMasterButtons(dev);
/* initialise an idle timer for this device*/

View File

@ -505,6 +505,8 @@ extern _X_EXPORT void XkbUpdateIndicators(DeviceIntPtr /* keybd */ ,
XkbEventCausePtr /* cause */
);
extern void XkbForceUpdateDeviceLEDs(DeviceIntPtr /* keybd */);
extern _X_EXPORT void XkbUpdateAllDeviceIndicators(XkbChangesPtr /* changes */,
XkbEventCausePtr /* cause */
);

View File

@ -434,6 +434,44 @@ XkbUpdateIndicators(DeviceIntPtr dev,
/***====================================================================***/
/*
* void
* XkbForceUpdateDeviceLEDs(DeviceIntPtr dev)
*
* Force update LED states to the hardware from the device state
* specified by 'dev'.
*
* If 'dev' is a master device, this function will also force update
* its slave devices.
*
* Used if the actual LED state was externally set and need to push
* current state to the hardware e.g. switching between VTs.
*/
void
XkbForceUpdateDeviceLEDs(DeviceIntPtr dev)
{
DeviceIntPtr master;
XkbSrvLedInfoPtr sli;
if (!dev->key)
return;
sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState);
if (IsMaster(dev)) {
master = dev;
nt_list_for_each_entry(dev, inputInfo.devices, next) {
if (!dev->key || GetMaster(dev, MASTER_KEYBOARD) != master)
continue;
sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState);
}
}
}
/***====================================================================***/
/*