Xnest: use xcb for retrieving keymap controls

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
Enrico Weigelt, metux IT consult 2024-08-13 14:18:35 +02:00
parent 261d22a444
commit e5eec08f33
4 changed files with 125 additions and 18 deletions

View File

@ -21,6 +21,7 @@ is" without express or implied warranty.
#include <X11/Xdefs.h> #include <X11/Xdefs.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <xcb/xkb.h>
#include "screenint.h" #include "screenint.h"
#include "inputstr.h" #include "inputstr.h"
@ -103,8 +104,6 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
CARD8 modmap[MAP_LENGTH]; CARD8 modmap[MAP_LENGTH];
int i, j; int i, j;
XKeyboardState values; XKeyboardState values;
XkbDescPtr xkb;
int op, event, error, major, minor;
switch (onoff) { switch (onoff) {
case DEVICE_INIT: case DEVICE_INIT:
@ -154,20 +153,6 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
keySyms.mapWidth = mapWidth; keySyms.mapWidth = mapWidth;
keySyms.map = keymap; keySyms.map = keymap;
if (XkbQueryExtension(xnestDisplay, &op, &event, &error, &major, &minor)
== 0) {
ErrorF("Unable to initialize XKEYBOARD extension.\n");
goto XkbError;
}
xkb =
XkbGetKeyboard(xnestDisplay, XkbGBN_AllComponentsMask,
XkbUseCoreKbd);
if (xkb == NULL || xkb->geom == NULL) {
ErrorF("Couldn't get keyboard.\n");
goto XkbError;
}
XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb);
InitKeyboardDeviceStruct(pDev, NULL, InitKeyboardDeviceStruct(pDev, NULL,
xnestBell, xnestChangeKeyboardControl); xnestBell, xnestChangeKeyboardControl);
@ -175,8 +160,61 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
keySyms.maxKeyCode - keySyms.minKeyCode + 1, keySyms.maxKeyCode - keySyms.minKeyCode + 1,
modmap, serverClient); modmap, serverClient);
XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls); xnest_xkb_init(xnestUpstreamInfo.conn);
XkbFreeKeyboard(xkb, 0, FALSE);
int device_id = xnest_xkb_device_id(xnestUpstreamInfo.conn);
xcb_generic_error_t *err = NULL;
xcb_xkb_get_controls_reply_t *reply = xcb_xkb_get_controls_reply(
xnestUpstreamInfo.conn,
xcb_xkb_get_controls(xnestUpstreamInfo.conn, device_id),
&err);
if (err) {
ErrorF("Couldn't get keyboard controls for %d: error %d\n", device_id, err->error_code);
free(err);
goto XkbError;
}
if (!reply) {
ErrorF("Couldn't get keyboard controls for %d: no reply", device_id);
goto XkbError;
}
XkbControlsRec ctrls = {
.mk_dflt_btn = reply->mouseKeysDfltBtn,
.num_groups = reply->numGroups,
.groups_wrap = reply->groupsWrap,
.internal = (XkbModsRec) {
.mask = reply->internalModsMask,
.real_mods = reply->internalModsRealMods,
.vmods = reply->internalModsVmods,
},
.ignore_lock = (XkbModsRec) {
.mask = reply->ignoreLockModsMask,
.real_mods = reply->ignoreLockModsRealMods,
.vmods = reply->ignoreLockModsVmods,
},
.enabled_ctrls = reply->enabledControls,
.repeat_delay = reply->repeatDelay,
.repeat_interval = reply->repeatInterval,
.slow_keys_delay = reply->slowKeysDelay,
.debounce_delay = reply->debounceDelay,
.mk_delay = reply->mouseKeysDelay,
.mk_interval = reply->mouseKeysInterval,
.mk_time_to_max = reply->mouseKeysTimeToMax,
.mk_max_speed = reply->mouseKeysMaxSpeed,
.mk_curve = reply->mouseKeysCurve,
.ax_options = reply->accessXOption,
.ax_timeout = reply->accessXTimeout,
.axt_opts_mask = reply->accessXTimeoutOptionsMask,
.axt_opts_values = reply->accessXTimeoutOptionsValues,
.axt_ctrls_mask = reply->accessXTimeoutMask,
.axt_ctrls_values = reply->accessXTimeoutValues,
};
memcpy(&ctrls.per_key_repeat, reply->perKeyRepeat, sizeof(ctrls.per_key_repeat));
XkbDDXChangeControls(pDev, &ctrls, &ctrls);
free(keymap); free(keymap);
break; break;
} }

View File

@ -25,6 +25,7 @@ xcb_dep = dependency('xcb', required: true)
xcb_aux_dep = dependency('xcb-aux', required: true) xcb_aux_dep = dependency('xcb-aux', required: true)
xcb_shape_dep = dependency('xcb-shape', required: true) xcb_shape_dep = dependency('xcb-shape', required: true)
xcb_icccm_dep = dependency('xcb-icccm', required: true) xcb_icccm_dep = dependency('xcb-icccm', required: true)
xcb_xkb_dep = dependency('xcb-xkb', required: true)
executable( executable(
'Xnest', 'Xnest',
@ -37,6 +38,7 @@ executable(
xcb_aux_dep, xcb_aux_dep,
xcb_shape_dep, xcb_shape_dep,
xcb_icccm_dep, xcb_icccm_dep,
xcb_xkb_dep,
x11_xcb_dep, x11_xcb_dep,
], ],
link_with: [ link_with: [

View File

@ -11,6 +11,7 @@
#include <X11/X.h> #include <X11/X.h>
#include <X11/Xdefs.h> #include <X11/Xdefs.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
#include <xcb/xkb.h>
#include "include/gc.h" #include "include/gc.h"
#include "include/servermd.h" #include "include/servermd.h"
@ -180,3 +181,66 @@ void xnest_set_command(
nbytes, nbytes,
buf); buf);
} }
void xnest_xkb_init(xcb_connection_t *conn)
{
xcb_generic_error_t *err = NULL;
xcb_xkb_use_extension_reply_t *reply = xcb_xkb_use_extension_reply(
xnestUpstreamInfo.conn,
xcb_xkb_use_extension(
xnestUpstreamInfo.conn,
XCB_XKB_MAJOR_VERSION,
XCB_XKB_MINOR_VERSION),
&err);
if (err) {
ErrorF("failed query xkb extension: %d\n", err->error_code);
free(err);
} else {
free(reply);
}
}
#define XkbGBN_AllComponentsMask_2 ( \
XCB_XKB_GBN_DETAIL_TYPES | \
XCB_XKB_GBN_DETAIL_COMPAT_MAP | \
XCB_XKB_GBN_DETAIL_CLIENT_SYMBOLS | \
XCB_XKB_GBN_DETAIL_SERVER_SYMBOLS | \
XCB_XKB_GBN_DETAIL_INDICATOR_MAPS | \
XCB_XKB_GBN_DETAIL_KEY_NAMES | \
XCB_XKB_GBN_DETAIL_GEOMETRY | \
XCB_XKB_GBN_DETAIL_OTHER_NAMES)
int xnest_xkb_device_id(xcb_connection_t *conn)
{
int device_id = -1;
uint8_t xlen[6] = { 0 };
xcb_generic_error_t *err = NULL;
xcb_xkb_get_kbd_by_name_reply_t *reply = xcb_xkb_get_kbd_by_name_reply(
xnestUpstreamInfo.conn,
xcb_xkb_get_kbd_by_name(
xnestUpstreamInfo.conn,
XCB_XKB_ID_USE_CORE_KBD,
XkbGBN_AllComponentsMask_2,
XkbGBN_AllComponentsMask_2,
0,
sizeof(xlen),
xlen),
&err);
if (err) {
ErrorF("failed retrieving core keyboard: %d\n", err->error_code);
free(err);
return -1;
}
if (!reply) {
ErrorF("failed retrieving core keyboard: no reply");
return -1;
}
device_id = reply->deviceID;
free(reply);
return device_id;
}

View File

@ -34,4 +34,7 @@ uint32_t xnest_create_pixmap_from_bitmap_data(xcb_connection_t *conn, uint32_t d
void xnest_set_command(xcb_connection_t *conn, xcb_window_t window, char ** argv, int argc); void xnest_set_command(xcb_connection_t *conn, xcb_window_t window, char ** argv, int argc);
void xnest_xkb_init(xcb_connection_t *conn);
int xnest_xkb_device_id(xcb_connection_t *conn);
#endif /* __XNEST__XCB_H */ #endif /* __XNEST__XCB_H */