remove deps on libx11; move to a pure xcb solution for keylayout
This commit is contained in:
parent
8f7ae46752
commit
dfcb1f9359
|
@ -21,8 +21,7 @@ i3lock_CFLAGS = \
|
||||||
$(XCB_UTIL_CFLAGS) \
|
$(XCB_UTIL_CFLAGS) \
|
||||||
$(XKBCOMMON_CFLAGS) \
|
$(XKBCOMMON_CFLAGS) \
|
||||||
$(CAIRO_CFLAGS) \
|
$(CAIRO_CFLAGS) \
|
||||||
$(CODE_COVERAGE_CFLAGS) \
|
$(CODE_COVERAGE_CFLAGS)
|
||||||
$(X11_CFLAGS)
|
|
||||||
|
|
||||||
i3lock_CPPFLAGS = \
|
i3lock_CPPFLAGS = \
|
||||||
$(AM_CPPFLAGS) \
|
$(AM_CPPFLAGS) \
|
||||||
|
@ -34,8 +33,7 @@ i3lock_LDADD = \
|
||||||
$(XCB_UTIL_LIBS) \
|
$(XCB_UTIL_LIBS) \
|
||||||
$(XKBCOMMON_LIBS) \
|
$(XKBCOMMON_LIBS) \
|
||||||
$(CAIRO_LIBS) \
|
$(CAIRO_LIBS) \
|
||||||
$(CODE_COVERAGE_LDFLAGS) \
|
$(CODE_COVERAGE_LDFLAGS)
|
||||||
$(X11_LIBS)
|
|
||||||
|
|
||||||
i3lock_SOURCES = \
|
i3lock_SOURCES = \
|
||||||
cursors.h \
|
cursors.h \
|
||||||
|
|
|
@ -87,8 +87,6 @@ PKG_CHECK_MODULES([XCB_IMAGE], [xcb-image])
|
||||||
PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util xcb-atom])
|
PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util xcb-atom])
|
||||||
PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon xkbcommon-x11])
|
PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon xkbcommon-x11])
|
||||||
PKG_CHECK_MODULES([CAIRO], [cairo])
|
PKG_CHECK_MODULES([CAIRO], [cairo])
|
||||||
PKG_CHECK_MODULES([X11], [x11])
|
|
||||||
|
|
||||||
|
|
||||||
# Checks for programs.
|
# Checks for programs.
|
||||||
AC_PROG_AWK
|
AC_PROG_AWK
|
||||||
|
|
73
i3lock.c
73
i3lock.c
|
@ -45,7 +45,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include <xcb/xcb_aux.h>
|
#include <xcb/xcb_aux.h>
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
#include <X11/XKBlib.h>
|
|
||||||
|
|
||||||
#include "i3lock.h"
|
#include "i3lock.h"
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
@ -132,6 +131,7 @@ double ring_width = 7.0;
|
||||||
|
|
||||||
char* verif_text = "verifying…";
|
char* verif_text = "verifying…";
|
||||||
char* wrong_text = "wrong!";
|
char* wrong_text = "wrong!";
|
||||||
|
int keylayout_mode = -1;
|
||||||
char* layout_text = NULL;
|
char* layout_text = NULL;
|
||||||
|
|
||||||
/* opts for blurring */
|
/* opts for blurring */
|
||||||
|
@ -219,51 +219,23 @@ void u8_dec(char *s, int *i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loads the XKB keymap from the X11 server and feeds it to xkbcommon.
|
* fetches the keylayout name
|
||||||
* Necessary so that we can properly let xkbcommon track the keyboard state and
|
* -1 (do not)
|
||||||
* translate keypresses to utf-8.
|
|
||||||
* arg: 0 (show full string returned)
|
* arg: 0 (show full string returned)
|
||||||
* 1 (show the text, sans parenthesis)
|
* 1 (show the text, sans parenthesis)
|
||||||
* 2 (show just what's in the parenthesis)
|
* 2 (show just what's in the parenthesis)
|
||||||
|
*
|
||||||
|
* credit to the XKB/xcb implementation (no libx11) from https://gist.github.com/bluetech/6061368
|
||||||
|
* docs are really sparse, so finding some random implementation was nice
|
||||||
*/
|
*/
|
||||||
|
char* get_keylayoutname(int mode, xcb_connection_t* conn) {
|
||||||
char* get_keylayoutname(int mode) {
|
if (mode < 0 || mode > 2) return NULL;
|
||||||
|
char* newans = NULL, *answer = xcb_get_key_group_names(conn);
|
||||||
Display *display;
|
|
||||||
XkbDescPtr keyboard;
|
|
||||||
XkbStateRec state;
|
|
||||||
char* answer;
|
|
||||||
char* newans = NULL;
|
|
||||||
int res, i;
|
|
||||||
|
|
||||||
display = XkbOpenDisplay(getenv("DISPLAY"), NULL, NULL, NULL, NULL, &res);
|
|
||||||
if(!display) {
|
|
||||||
DEBUG("X server unreachable\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard = XkbAllocKeyboard();
|
|
||||||
|
|
||||||
if (XkbGetNames(display, XkbGroupNamesMask, keyboard) != Success ) {
|
|
||||||
DEBUG("Error obtaining symbolic names");
|
|
||||||
XCloseDisplay(display);
|
|
||||||
XkbFreeClientMap(keyboard, 0, true);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(XkbGetState(display, XkbUseCoreKbd, &state) != Success) {
|
|
||||||
DEBUG("Error getting keyboard state");
|
|
||||||
XCloseDisplay(display);
|
|
||||||
XkbFreeClientMap(keyboard, 0, true);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
answer = XGetAtomName(display, keyboard->names->groups[state.group]);
|
|
||||||
DEBUG("keylayout answer is: [%s]\n", answer);
|
DEBUG("keylayout answer is: [%s]\n", answer);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 1:
|
case 1:
|
||||||
// truncate the string at the first parens
|
// truncate the string at the first parens
|
||||||
for(i = 0; answer[i] != '\0'; ++i) {
|
for(int i = 0; answer[i] != '\0'; ++i) {
|
||||||
if (answer[i] == '(') {
|
if (answer[i] == '(') {
|
||||||
if (i != 0 && answer[i - 1] == ' ') {
|
if (i != 0 && answer[i - 1] == ' ') {
|
||||||
answer[i - 1] = '\0';
|
answer[i - 1] = '\0';
|
||||||
|
@ -276,7 +248,7 @@ char* get_keylayoutname(int mode) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for(i = 0; answer[i] != '\0'; ++i) {
|
for(int i = 0; answer[i] != '\0'; ++i) {
|
||||||
if (answer[i] == '(') {
|
if (answer[i] == '(') {
|
||||||
newans = &answer[i + 1];
|
newans = &answer[i + 1];
|
||||||
} else if (answer[i] == ')' && newans != NULL) {
|
} else if (answer[i] == ')' && newans != NULL) {
|
||||||
|
@ -292,15 +264,17 @@ char* get_keylayoutname(int mode) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// note: this is called in option parsing, so this debug() may not trigger unless --debug is the first option
|
|
||||||
DEBUG("answer after mode parsing: [%s]\n", answer);
|
DEBUG("answer after mode parsing: [%s]\n", answer);
|
||||||
// Free symbolic names structures
|
// Free symbolic names structures
|
||||||
XkbFreeClientMap(keyboard, 0, true);
|
|
||||||
XCloseDisplay(display);
|
|
||||||
display = NULL;
|
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads the XKB keymap from the X11 server and feeds it to xkbcommon.
|
||||||
|
* Necessary so that we can properly let xkbcommon track the keyboard state and
|
||||||
|
* translate keypresses to utf-8.
|
||||||
|
*/
|
||||||
|
|
||||||
static bool load_keymap(void) {
|
static bool load_keymap(void) {
|
||||||
if (xkb_context == NULL) {
|
if (xkb_context == NULL) {
|
||||||
if ((xkb_context = xkb_context_new(0)) == NULL) {
|
if ((xkb_context = xkb_context_new(0)) == NULL) {
|
||||||
|
@ -1337,9 +1311,7 @@ int main(int argc, char *argv[]) {
|
||||||
// if layout is NULL, do nothing
|
// if layout is NULL, do nothing
|
||||||
// if not NULL, attempt to display stuff
|
// if not NULL, attempt to display stuff
|
||||||
// need to code some sane defaults for it
|
// need to code some sane defaults for it
|
||||||
layout_text = get_keylayoutname(atoi(optarg));
|
keylayout_mode = atoi(optarg);
|
||||||
if (layout_text)
|
|
||||||
show_clock = true;
|
|
||||||
}
|
}
|
||||||
else if (strcmp(longopts[longoptind].name, "timestr") == 0) {
|
else if (strcmp(longopts[longoptind].name, "timestr") == 0) {
|
||||||
//read in to timestr
|
//read in to timestr
|
||||||
|
@ -1645,8 +1617,10 @@ int main(int argc, char *argv[]) {
|
||||||
int screennr;
|
int screennr;
|
||||||
if ((conn = xcb_connect(NULL, &screennr)) == NULL ||
|
if ((conn = xcb_connect(NULL, &screennr)) == NULL ||
|
||||||
xcb_connection_has_error(conn))
|
xcb_connection_has_error(conn))
|
||||||
errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?");
|
errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (xkb_x11_setup_xkb_extension(conn,
|
if (xkb_x11_setup_xkb_extension(conn,
|
||||||
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||||
XKB_X11_MIN_MINOR_XKB_VERSION,
|
XKB_X11_MIN_MINOR_XKB_VERSION,
|
||||||
|
@ -1656,7 +1630,10 @@ int main(int argc, char *argv[]) {
|
||||||
&xkb_base_event,
|
&xkb_base_event,
|
||||||
&xkb_base_error) != 1)
|
&xkb_base_error) != 1)
|
||||||
errx(EXIT_FAILURE, "Could not setup XKB extension.");
|
errx(EXIT_FAILURE, "Could not setup XKB extension.");
|
||||||
|
|
||||||
|
layout_text = get_keylayoutname(keylayout_mode, conn);
|
||||||
|
if (layout_text)
|
||||||
|
show_clock = true;
|
||||||
static const xcb_xkb_map_part_t required_map_parts =
|
static const xcb_xkb_map_part_t required_map_parts =
|
||||||
(XCB_XKB_MAP_PART_KEY_TYPES |
|
(XCB_XKB_MAP_PART_KEY_TYPES |
|
||||||
XCB_XKB_MAP_PART_KEY_SYMS |
|
XCB_XKB_MAP_PART_KEY_SYMS |
|
||||||
|
|
104
xcb.c
104
xcb.c
|
@ -12,6 +12,9 @@
|
||||||
#include <xcb/xcb_atom.h>
|
#include <xcb/xcb_atom.h>
|
||||||
#include <xcb/xcb_aux.h>
|
#include <xcb/xcb_aux.h>
|
||||||
#include <xcb/composite.h>
|
#include <xcb/composite.h>
|
||||||
|
#include <xcb/xkb.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <xkbcommon/xkbcommon-x11.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -23,10 +26,13 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "cursors.h"
|
#include "cursors.h"
|
||||||
|
#include "i3lock.h"
|
||||||
|
#include "xcb.h"
|
||||||
#include "unlock_indicator.h"
|
#include "unlock_indicator.h"
|
||||||
|
|
||||||
extern auth_state_t auth_state;
|
extern auth_state_t auth_state;
|
||||||
extern bool composite;
|
extern bool composite;
|
||||||
|
extern bool debug_mode;
|
||||||
|
|
||||||
xcb_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
xcb_screen_t *screen;
|
xcb_screen_t *screen;
|
||||||
|
@ -427,3 +433,101 @@ xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int3
|
||||||
xcb_free_gc(conn, gc);
|
xcb_free_gc(conn, gc);
|
||||||
return bg_pixmap;
|
return bg_pixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char * get_atom_name(xcb_connection_t* conn, xcb_atom_t atom) {
|
||||||
|
xcb_get_atom_name_reply_t *reply = NULL;
|
||||||
|
char *name;
|
||||||
|
int length;
|
||||||
|
char* answer = NULL;
|
||||||
|
|
||||||
|
if (atom == 0)
|
||||||
|
return "<empty>";
|
||||||
|
|
||||||
|
xcb_get_atom_name_cookie_t cookie;
|
||||||
|
xcb_generic_error_t *error = NULL;
|
||||||
|
|
||||||
|
cookie = xcb_get_atom_name(conn, atom);
|
||||||
|
|
||||||
|
reply = xcb_get_atom_name_reply(conn, cookie, &error);
|
||||||
|
if (!reply || error)
|
||||||
|
return "<invalid>";
|
||||||
|
|
||||||
|
length = xcb_get_atom_name_name_length(reply);
|
||||||
|
name = xcb_get_atom_name_name(reply);
|
||||||
|
|
||||||
|
answer = malloc(sizeof(char) * (length + 1));
|
||||||
|
strncpy(answer, name, length);
|
||||||
|
answer[length] = '\0';
|
||||||
|
free(error);
|
||||||
|
free(reply);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* xcb_get_key_group_names(xcb_connection_t *conn) {
|
||||||
|
uint8_t xkb_base_event;
|
||||||
|
uint8_t xkb_base_error;
|
||||||
|
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.");
|
||||||
|
|
||||||
|
|
||||||
|
xcb_xkb_get_names_reply_t *reply = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
xcb_generic_error_t *error = NULL;
|
||||||
|
xcb_xkb_get_names_cookie_t cookie;
|
||||||
|
|
||||||
|
cookie = xcb_xkb_get_names(conn,
|
||||||
|
XCB_XKB_ID_USE_CORE_KBD,
|
||||||
|
all_name_details);
|
||||||
|
|
||||||
|
reply = xcb_xkb_get_names_reply(conn, cookie, &error);
|
||||||
|
if (!reply || error)
|
||||||
|
errx(1, "couldn't get reply for get_names");
|
||||||
|
|
||||||
|
xcb_xkb_get_names_value_list_t list;
|
||||||
|
|
||||||
|
void *buffer;
|
||||||
|
|
||||||
|
buffer = xcb_xkb_get_names_value_list(reply);
|
||||||
|
xcb_xkb_get_names_value_list_unpack(buffer,
|
||||||
|
reply->nTypes,
|
||||||
|
reply->indicators,
|
||||||
|
reply->virtualMods,
|
||||||
|
reply->groupNames,
|
||||||
|
reply->nKeys,
|
||||||
|
reply->nKeyAliases,
|
||||||
|
reply->nRadioGroups,
|
||||||
|
reply->which,
|
||||||
|
&list);
|
||||||
|
|
||||||
|
/* dump group names. */
|
||||||
|
|
||||||
|
int length;
|
||||||
|
xcb_atom_t *iter;
|
||||||
|
char* answer = NULL;
|
||||||
|
length = xcb_xkb_get_names_value_list_groups_length(reply, &list);
|
||||||
|
iter = xcb_xkb_get_names_value_list_groups(&list);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
xcb_atom_t group_name = *iter;
|
||||||
|
char* name = get_atom_name(conn, group_name);
|
||||||
|
DEBUG("group_name %d: %s\n", i, name);
|
||||||
|
if (i == 0) {
|
||||||
|
answer = name;
|
||||||
|
} else {
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
free(reply);
|
||||||
|
free(error);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
18
xcb.h
18
xcb.h
|
@ -3,6 +3,23 @@
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
|
#define all_name_details \
|
||||||
|
(XCB_XKB_NAME_DETAIL_KEYCODES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_GEOMETRY | \
|
||||||
|
XCB_XKB_NAME_DETAIL_SYMBOLS | \
|
||||||
|
XCB_XKB_NAME_DETAIL_PHYS_SYMBOLS | \
|
||||||
|
XCB_XKB_NAME_DETAIL_TYPES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_COMPAT | \
|
||||||
|
XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_INDICATOR_NAMES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_KEY_NAMES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_KEY_ALIASES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_GROUP_NAMES | \
|
||||||
|
XCB_XKB_NAME_DETAIL_RG_NAMES)
|
||||||
|
|
||||||
|
|
||||||
extern xcb_connection_t *conn;
|
extern xcb_connection_t *conn;
|
||||||
extern xcb_screen_t *screen;
|
extern xcb_screen_t *screen;
|
||||||
|
|
||||||
|
@ -14,5 +31,6 @@ xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_win
|
||||||
xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t root);
|
xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t root);
|
||||||
void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const xcb_window_t window);
|
void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const xcb_window_t window);
|
||||||
xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t* resolution);
|
xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t* resolution);
|
||||||
|
char* xcb_get_key_group_names(xcb_connection_t *conn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue