dix: pick the right keyboard for focus FollowKeyboard
This fixes a crash when we try to send focus events and dereference
FollowKeyboardWin (0x3) as WindowPtr.
A device set to XSetDeviceFocus(FollowKeyboard) is supposed to follow
the focus of the corresponding master device. During ActivateKeyboard
a slave device is detached from the master for the duration for the grab
so we don't actually have a master to follow - leaving our oldWin set to
the FollowKeyboardWin constant. This later crashes when we try to
dereference it.
Fix this by getting the current master (if any), or the saved master (if
temporarily detached due to a grab). And if failing that, use the VCK
as fallback device - that is technically wrong but it's such a niche use
case that it shouldn't matter.
Reproducer:
window = XCreateSimpleWindow(...)
deviceid = any device that is IsXExtensionKeyboard device
XSetDeviceFocus(deviceid, FollowKeyboard, ...)
XGrabDevice(deviceid, window, ...)
Fixes: f01ee198ff
("dix: don't use inputInfo.keyboard to get the focus window in ActivateKbdGrab")
Found-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Tested-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1870>
This commit is contained in:
parent
c445167da6
commit
cab9017485
36
dix/events.c
36
dix/events.c
|
@ -1479,6 +1479,30 @@ ReattachToOldMaster(DeviceIntPtr dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current master keyboard or, if we're temporarily detached, the one
|
||||||
|
* we've been attached to previously.
|
||||||
|
*/
|
||||||
|
static DeviceIntPtr
|
||||||
|
CurrentOrOldMasterKeyboard(DeviceIntPtr dev)
|
||||||
|
{
|
||||||
|
DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
|
||||||
|
|
||||||
|
if (kbd)
|
||||||
|
return kbd;
|
||||||
|
|
||||||
|
if (dev->saved_master_id) {
|
||||||
|
dixLookupDevice(&kbd, dev->saved_master_id, serverClient, DixUseAccess);
|
||||||
|
if (!kbd)
|
||||||
|
return NULL;
|
||||||
|
/* if dev is a pointer the saved master is a master pointer,
|
||||||
|
* we want the keybard */
|
||||||
|
return GetMaster(kbd, MASTER_KEYBOARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update touch records when an explicit grab is activated. Any touches owned by
|
* Update touch records when an explicit grab is activated. Any touches owned by
|
||||||
* the grabbing client are updated so the listener state reflects the new grab.
|
* the grabbing client are updated so the listener state reflects the new grab.
|
||||||
|
@ -1703,6 +1727,10 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
|
||||||
GrabInfoPtr grabinfo = &keybd->deviceGrab;
|
GrabInfoPtr grabinfo = &keybd->deviceGrab;
|
||||||
GrabPtr oldgrab = grabinfo->grab;
|
GrabPtr oldgrab = grabinfo->grab;
|
||||||
WindowPtr oldWin;
|
WindowPtr oldWin;
|
||||||
|
DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd);
|
||||||
|
|
||||||
|
if (!master_keyboard)
|
||||||
|
master_keyboard = inputInfo.keyboard;
|
||||||
|
|
||||||
/* slave devices need to float for the duration of the grab. */
|
/* slave devices need to float for the duration of the grab. */
|
||||||
if (grab->grabtype == XI2 && keybd->enabled &&
|
if (grab->grabtype == XI2 && keybd->enabled &&
|
||||||
|
@ -1718,7 +1746,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
|
||||||
else
|
else
|
||||||
oldWin = keybd->spriteInfo->sprite->win;
|
oldWin = keybd->spriteInfo->sprite->win;
|
||||||
if (oldWin == FollowKeyboardWin)
|
if (oldWin == FollowKeyboardWin)
|
||||||
oldWin = keybd->focus->win;
|
oldWin = master_keyboard->focus->win;
|
||||||
if (keybd->valuator)
|
if (keybd->valuator)
|
||||||
keybd->valuator->motionHintWindow = NullWindow;
|
keybd->valuator->motionHintWindow = NullWindow;
|
||||||
if (oldWin &&
|
if (oldWin &&
|
||||||
|
@ -1748,6 +1776,10 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
|
||||||
WindowPtr focusWin;
|
WindowPtr focusWin;
|
||||||
Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
|
Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
|
||||||
keybd->deviceGrab.implicitGrab);
|
keybd->deviceGrab.implicitGrab);
|
||||||
|
DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd);
|
||||||
|
|
||||||
|
if (!master_keyboard)
|
||||||
|
master_keyboard = inputInfo.keyboard;
|
||||||
|
|
||||||
if (keybd->valuator)
|
if (keybd->valuator)
|
||||||
keybd->valuator->motionHintWindow = NullWindow;
|
keybd->valuator->motionHintWindow = NullWindow;
|
||||||
|
@ -1768,7 +1800,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
|
||||||
focusWin = NullWindow;
|
focusWin = NullWindow;
|
||||||
|
|
||||||
if (focusWin == FollowKeyboardWin)
|
if (focusWin == FollowKeyboardWin)
|
||||||
focusWin = inputInfo.keyboard->focus->win;
|
focusWin = master_keyboard->focus->win;
|
||||||
|
|
||||||
DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
|
DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue