mirror of https://github.com/i3/i3lock.git
listen for XKB events instead of the MappingNotify event (Thanks Ran)
parent
7eb43aeabd
commit
1b89709ae7
4
Makefile
4
Makefile
|
@ -11,8 +11,8 @@ CFLAGS += -std=c99
|
||||||
CFLAGS += -pipe
|
CFLAGS += -pipe
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CPPFLAGS += -D_GNU_SOURCE
|
CPPFLAGS += -D_GNU_SOURCE
|
||||||
CFLAGS += $(shell pkg-config --cflags cairo xcb-dpms xcb-xinerama xcb-atom xkbcommon xkbcommon-x11)
|
CFLAGS += $(shell pkg-config --cflags cairo xcb-dpms xcb-xinerama xcb-atom xcb-image xcb-xkb xkbcommon xkbcommon-x11)
|
||||||
LIBS += $(shell pkg-config --libs cairo xcb-dpms xcb-xinerama xcb-atom xcb-image xkbcommon xkbcommon-x11)
|
LIBS += $(shell pkg-config --libs cairo xcb-dpms xcb-xinerama xcb-atom xcb-image xcb-xkb xkbcommon xkbcommon-x11)
|
||||||
LIBS += -lpam
|
LIBS += -lpam
|
||||||
LIBS += -lev
|
LIBS += -lev
|
||||||
LIBS += -lm
|
LIBS += -lm
|
||||||
|
|
85
i3lock.c
85
i3lock.c
|
@ -13,6 +13,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xkb.h>
|
||||||
#include <xcb/dpms.h>
|
#include <xcb/dpms.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -402,11 +403,54 @@ static void handle_visibility_notify(xcb_connection_t *conn,
|
||||||
/*
|
/*
|
||||||
* Called when the keyboard mapping changes. We update our symbols.
|
* Called when the keyboard mapping changes. We update our symbols.
|
||||||
*
|
*
|
||||||
|
* We ignore errors — if the new keymap cannot be loaded it’s better if the
|
||||||
|
* screen stays locked and the user intervenes by using killall i3lock.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_mapping_notify(xcb_mapping_notify_event_t *event) {
|
static void process_xkb_event(xcb_generic_event_t *gevent) {
|
||||||
/* We ignore errors — if the new keymap cannot be loaded it’s better if the
|
union xkb_event {
|
||||||
* screen stays locked and the user intervenes by using killall i3lock. */
|
struct {
|
||||||
(void)load_keymap();
|
uint8_t response_type;
|
||||||
|
uint8_t xkbType;
|
||||||
|
uint16_t sequence;
|
||||||
|
xcb_timestamp_t time;
|
||||||
|
uint8_t deviceID;
|
||||||
|
} any;
|
||||||
|
xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify;
|
||||||
|
xcb_xkb_map_notify_event_t map_notify;
|
||||||
|
xcb_xkb_state_notify_event_t state_notify;
|
||||||
|
} *event = (union xkb_event*)gevent;
|
||||||
|
|
||||||
|
DEBUG("process_xkb_event for device %d\n", event->any.deviceID);
|
||||||
|
|
||||||
|
if (event->any.deviceID != xkb_x11_get_core_keyboard_device_id(conn))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap
|
||||||
|
* updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent
|
||||||
|
* recompilations.
|
||||||
|
*/
|
||||||
|
switch (event->any.xkbType) {
|
||||||
|
case XCB_XKB_NEW_KEYBOARD_NOTIFY:
|
||||||
|
if (event->new_keyboard_notify.changed & XCB_XKB_NKN_DETAIL_KEYCODES)
|
||||||
|
(void)load_keymap();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_XKB_MAP_NOTIFY:
|
||||||
|
(void)load_keymap();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_XKB_STATE_NOTIFY:
|
||||||
|
xkb_state_update_mask(xkb_state,
|
||||||
|
event->state_notify.baseMods,
|
||||||
|
event->state_notify.latchedMods,
|
||||||
|
event->state_notify.lockedMods,
|
||||||
|
event->state_notify.baseGroup,
|
||||||
|
event->state_notify.latchedGroup,
|
||||||
|
event->state_notify.lockedGroup);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -512,6 +556,7 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
||||||
|
|
||||||
/* Strip off the highest bit (set if the event is generated) */
|
/* Strip off the highest bit (set if the event is generated) */
|
||||||
int type = (event->response_type & 0x7F);
|
int type = (event->response_type & 0x7F);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
handle_key_press((xcb_key_press_event_t*)event);
|
handle_key_press((xcb_key_press_event_t*)event);
|
||||||
|
@ -546,13 +591,13 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_MAPPING_NOTIFY:
|
|
||||||
handle_mapping_notify((xcb_mapping_notify_event_t*)event);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XCB_CONFIGURE_NOTIFY:
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
handle_screen_resize();
|
handle_screen_resize();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (type == xkb_base_event)
|
||||||
|
process_xkb_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(event);
|
free(event);
|
||||||
|
@ -745,6 +790,30 @@ int main(int argc, char *argv[]) {
|
||||||
&xkb_base_error) != 1)
|
&xkb_base_error) != 1)
|
||||||
errx(EXIT_FAILURE, "Could not setup XKB extension.");
|
errx(EXIT_FAILURE, "Could not setup XKB extension.");
|
||||||
|
|
||||||
|
static const xcb_xkb_map_part_t required_map_parts =
|
||||||
|
(XCB_XKB_MAP_PART_KEY_TYPES |
|
||||||
|
XCB_XKB_MAP_PART_KEY_SYMS |
|
||||||
|
XCB_XKB_MAP_PART_MODIFIER_MAP |
|
||||||
|
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
|
||||||
|
XCB_XKB_MAP_PART_KEY_ACTIONS |
|
||||||
|
XCB_XKB_MAP_PART_VIRTUAL_MODS |
|
||||||
|
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
|
||||||
|
|
||||||
|
static const xcb_xkb_event_type_t required_events =
|
||||||
|
(XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
|
||||||
|
XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
|
||||||
|
XCB_XKB_EVENT_TYPE_STATE_NOTIFY);
|
||||||
|
|
||||||
|
xcb_xkb_select_events(
|
||||||
|
conn,
|
||||||
|
xkb_x11_get_core_keyboard_device_id(conn),
|
||||||
|
required_events,
|
||||||
|
0,
|
||||||
|
required_events,
|
||||||
|
required_map_parts,
|
||||||
|
required_map_parts,
|
||||||
|
0);
|
||||||
|
|
||||||
/* When we cannot initially load the keymap, we better exit */
|
/* When we cannot initially load the keymap, we better exit */
|
||||||
if (!load_keymap())
|
if (!load_keymap())
|
||||||
errx(EXIT_FAILURE, "Could not load keymap");
|
errx(EXIT_FAILURE, "Could not load keymap");
|
||||||
|
|
Loading…
Reference in New Issue