diff --git a/Makefile b/Makefile index ea3b89d..9443e97 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,8 @@ CFLAGS += -std=c99 CFLAGS += -pipe CFLAGS += -Wall CPPFLAGS += -D_GNU_SOURCE -CFLAGS += $(shell pkg-config --cflags cairo xcb-dpms xcb-xinerama xcb-atom xkbcommon xkbfile x11 x11-xcb) -LIBS += $(shell pkg-config --libs cairo xcb-dpms xcb-xinerama xcb-atom xcb-image xkbcommon xkbfile x11 x11-xcb) +CFLAGS += $(shell pkg-config --cflags cairo xcb-dpms xcb-xinerama xcb-atom xkbcommon xkbcommon-x11 xkbfile) +LIBS += $(shell pkg-config --libs cairo xcb-dpms xcb-xinerama xcb-atom xcb-image xkbcommon xkbcommon-x11 xkbfile) LIBS += -lpam LIBS += -lev LIBS += -lm diff --git a/i3lock.c b/i3lock.c index 682f162..f81ea18 100644 --- a/i3lock.c +++ b/i3lock.c @@ -17,14 +17,12 @@ #include #include #include -#include #include #include #include #include -#include -#include #include +#include #include #include @@ -44,7 +42,6 @@ typedef void (*ev_callback_t)(EV_P_ ev_timer *w, int revents); /* We need this for libxkbfile */ -static Display *display; char color[7] = "ffffff"; int inactivity_timeout = 30; uint32_t last_resolution[2]; @@ -70,6 +67,8 @@ extern pam_state_t pam_state; static struct xkb_state *xkb_state; static struct xkb_context *xkb_context; static struct xkb_keymap *xkb_keymap; +static uint8_t xkb_base_event; +static uint8_t xkb_base_error; cairo_surface_t *img = NULL; bool tile = false; @@ -102,77 +101,44 @@ static void turn_monitors_off(void) { * Necessary so that we can properly let xkbcommon track the keyboard state and * translate keypresses to utf-8. * - * Ideally, xkbcommon would ship something like this itself, but as of now - * (version 0.2.0), it doesn’t. - * - * TODO: Once xcb-xkb is enabled by default and released, we should port this - * code to xcb-xkb. See also https://github.com/xkbcommon/libxkbcommon/issues/1 - * */ static bool load_keymap(void) { - bool ret = false; - XkbFileInfo result; - memset(&result, '\0', sizeof(result)); - result.xkb = XkbGetKeyboard(display, XkbAllMapComponentsMask, XkbUseCoreKbd); - if (result.xkb == NULL) { - fprintf(stderr, "[i3lock] XKB: XkbGetKeyboard failed\n"); - return false; - } - - FILE *temp = tmpfile(); - if (temp == NULL) { - fprintf(stderr, "[i3lock] could not create tempfile\n"); - return false; - } - - bool ok = XkbWriteXKBKeymap(temp, &result, false, false, NULL, NULL); - if (!ok) { - fprintf(stderr, "[i3lock] XkbWriteXKBKeymap failed\n"); - goto out; - } - - rewind(temp); - if (xkb_context == NULL) { if ((xkb_context = xkb_context_new(0)) == NULL) { fprintf(stderr, "[i3lock] could not create xkbcommon context\n"); - goto out; + return false; } } if (xkb_keymap != NULL) xkb_keymap_unref(xkb_keymap); - if ((xkb_keymap = xkb_keymap_new_from_file(xkb_context, temp, XKB_KEYMAP_FORMAT_TEXT_V1, 0)) == NULL) { - fprintf(stderr, "[i3lock] xkb_keymap_new_from_file failed\n"); - goto out; + int32_t device_id = xkb_x11_get_core_keyboard_device_id(conn); + DEBUG("device = %d\n", device_id); + if ((xkb_keymap = xkb_x11_keymap_new_from_device(xkb_context, conn, device_id, 0)) == NULL) { + fprintf(stderr, "[i3lock] xkb_x11_keymap_new_from_device failed\n"); + return false; } - struct xkb_state *new_state = xkb_state_new(xkb_keymap); + struct xkb_state *new_state = + xkb_x11_state_new_from_device(xkb_keymap, conn, device_id); if (new_state == NULL) { - fprintf(stderr, "[i3lock] xkb_state_new failed\n"); - goto out; + fprintf(stderr, "[i3lock] xkb_x11_state_new_from_device failed\n"); + return false; } /* Get the initial modifier state to be in sync with the X server. * See https://github.com/xkbcommon/libxkbcommon/issues/1 for why we ignore * the base and latched fields. */ - XkbStateRec state_rec; - XkbGetState(display, XkbUseCoreKbd, &state_rec); - - xkb_state_update_mask(new_state, - 0, 0, state_rec.locked_mods, - 0, 0, state_rec.locked_group); + //xkb_state_update_mask(new_state, + // 0, 0, new_state->components.locked_mods, + // 0, 0, new_state->components.locked_group); if (xkb_state != NULL) xkb_state_unref(xkb_state); xkb_state = new_state; - ret = true; -out: - XkbFreeKeyboard(result.xkb, XkbAllComponentsMask, true); - fclose(temp); - return ret; + return true; } /* @@ -772,16 +738,22 @@ int main(int argc, char *argv[]) { err(EXIT_FAILURE, "Could not lock page in memory, check RLIMIT_MEMLOCK"); #endif - /* Initialize connection to X11 */ - if ((display = XOpenDisplay(NULL)) == NULL) - errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); - XSetEventQueueOwner(display, XCBOwnsEventQueue); - conn = XGetXCBConnection(display); - /* Double checking that connection is good and operatable with xcb */ - if (xcb_connection_has_error(conn)) + int screennr; + if ((conn = xcb_connect(NULL, &screennr)) == NULL || + xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); + if (xkb_x11_setup_xkb_extension(conn, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION, + 0, + NULL, + NULL, + &xkb_base_event, + &xkb_base_error) != 1) + errx(EXIT_FAILURE, "Could not setup XKB extension."); + /* When we cannot initially load the keymap, we better exit */ if (!load_keymap()) errx(EXIT_FAILURE, "Could not load keymap");