mirror of https://github.com/i3/i3lock.git
use libxkbcommon-x11 instead of libX11
parent
6191590e5c
commit
0beb9a47b1
4
Makefile
4
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
|
||||
|
|
88
i3lock.c
88
i3lock.c
|
@ -17,14 +17,12 @@
|
|||
#include <err.h>
|
||||
#include <assert.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <ev.h>
|
||||
#include <sys/mman.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBfile.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
#include <cairo.h>
|
||||
#include <cairo/cairo-xcb.h>
|
||||
|
||||
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue