xwayland: don't allow clients to modify the keymap

Xwayland has no way to affect the keymap of the compositor. If clients
modify the keymap, it will stay out of sync with the compositor until
some unspecified time in the future when the compositor sends the keymap
again, which might be never, requiring Xwayland to be restarted.

Signed-off-by: Julian Orth <ju.orth@gmail.com>
This commit is contained in:
Julian Orth 2025-05-05 13:56:27 +02:00
parent 37b7ea8f8a
commit fc8e14a5bb
4 changed files with 24 additions and 2 deletions

View file

@ -75,7 +75,7 @@
*/
#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(27, 0)
#define ABI_XINPUT_VERSION SET_ABI_VERSION(25, 0)
#define ABI_XINPUT_VERSION SET_ABI_VERSION(26, 0)
#define ABI_EXTENSION_VERSION SET_ABI_VERSION(10, 0)
#define MODINFOSTRING1 0xef23fdc5

View file

@ -1205,10 +1205,13 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
}
XkbDeviceApplyKeymap(xwl_seat->keyboard, xkb);
xwl_seat->keyboard->hasDdxKeymap = TRUE;
master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD);
if (master)
if (master) {
XkbDeviceApplyKeymap(master, xkb);
master->hasDdxKeymap = TRUE;
}
XkbFreeKeyboard(xkb, XkbAllComponentsMask, TRUE);

View file

@ -620,6 +620,7 @@ typedef struct _DeviceIntRec {
struct _SyncCounter *idle_counter;
Bool ignoreXkbActionsBehaviors; /* TRUE if keys don't trigger behaviors and actions */
Bool hasDdxKeymap; /* TRUE if clients cannot modify the keymap */
} DeviceIntRec;
typedef struct {

View file

@ -2726,6 +2726,9 @@ ProcXkbSetMap(ClientPtr client)
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
if (dev->hasDdxKeymap)
return BadAccess;
/* first verify the request length carefully */
rc = _XkbSetMapCheckLength(stuff);
if (rc != Success)
@ -3109,6 +3112,9 @@ ProcXkbSetCompatMap(ClientPtr client)
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
if (dev->hasDdxKeymap)
return BadAccess;
data = (char *) &stuff[1];
/* check first using a dry-run */
@ -3366,6 +3372,9 @@ ProcXkbSetIndicatorMap(ClientPtr client)
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
if (dev->hasDdxKeymap)
return BadAccess;
if (stuff->which == 0)
return Success;
@ -4461,6 +4470,9 @@ ProcXkbSetNames(ClientPtr client)
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
if (dev->hasDdxKeymap)
return BadAccess;
/* check device-independent stuff */
tmp = (CARD32 *) &stuff[1];
@ -5676,6 +5688,9 @@ ProcXkbSetGeometry(ClientPtr client)
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_ATOM_OR_NONE(stuff->name);
if (dev->hasDdxKeymap)
return BadAccess;
rc = _XkbSetGeometry(client, dev, stuff);
if (rc != Success)
return rc;
@ -5981,6 +5996,9 @@ ProcXkbGetKbdByName(ClientPtr client)
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
master = GetMaster(dev, MASTER_KEYBOARD);
if (stuff->load && dev->hasDdxKeymap)
return BadAccess;
xkb = dev->key->xkbInfo->desc;
status = Success;
str = (unsigned char *) &stuff[1];