commit dfcb1f9359a70ff29a39471bd27c61232c65f126
parent 8f7ae46752ff3d701860f685e9241fcb376a3cd3
Author: Pandora <pandora@techfo.xyz>
Date: Fri, 8 Dec 2017 15:06:08 -0500
remove deps on libx11; move to a pure xcb solution for keylayout
Diffstat:
| M | Makefile.am | | | 6 | ++---- |
| M | configure.ac | | | 2 | -- |
| M | i3lock.c | | | 73 | +++++++++++++++++++++++++------------------------------------------------ |
| M | xcb.c | | | 104 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | xcb.h | | | 18 | ++++++++++++++++++ |
5 files changed, 149 insertions(+), 54 deletions(-)
diff --git a/Makefile.am b/Makefile.am
@@ -21,8 +21,7 @@ i3lock_CFLAGS = \
$(XCB_UTIL_CFLAGS) \
$(XKBCOMMON_CFLAGS) \
$(CAIRO_CFLAGS) \
- $(CODE_COVERAGE_CFLAGS) \
- $(X11_CFLAGS)
+ $(CODE_COVERAGE_CFLAGS)
i3lock_CPPFLAGS = \
$(AM_CPPFLAGS) \
@@ -34,8 +33,7 @@ i3lock_LDADD = \
$(XCB_UTIL_LIBS) \
$(XKBCOMMON_LIBS) \
$(CAIRO_LIBS) \
- $(CODE_COVERAGE_LDFLAGS) \
- $(X11_LIBS)
+ $(CODE_COVERAGE_LDFLAGS)
i3lock_SOURCES = \
cursors.h \
diff --git a/configure.ac b/configure.ac
@@ -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([XKBCOMMON], [xkbcommon xkbcommon-x11])
PKG_CHECK_MODULES([CAIRO], [cairo])
-PKG_CHECK_MODULES([X11], [x11])
-
# Checks for programs.
AC_PROG_AWK
diff --git a/i3lock.c b/i3lock.c
@@ -45,7 +45,6 @@
#endif
#include <xcb/xcb_aux.h>
#include <xcb/randr.h>
-#include <X11/XKBlib.h>
#include "i3lock.h"
#include "xcb.h"
@@ -132,6 +131,7 @@ double ring_width = 7.0;
char* verif_text = "verifying…";
char* wrong_text = "wrong!";
+int keylayout_mode = -1;
char* layout_text = NULL;
/* 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.
- * Necessary so that we can properly let xkbcommon track the keyboard state and
- * translate keypresses to utf-8.
+ * fetches the keylayout name
+ * -1 (do not)
* arg: 0 (show full string returned)
* 1 (show the text, sans 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) {
-
- 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]);
+char* get_keylayoutname(int mode, xcb_connection_t* conn) {
+ if (mode < 0 || mode > 2) return NULL;
+ char* newans = NULL, *answer = xcb_get_key_group_names(conn);
DEBUG("keylayout answer is: [%s]\n", answer);
switch (mode) {
case 1:
// 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 (i != 0 && answer[i - 1] == ' ') {
answer[i - 1] = '\0';
@@ -276,7 +248,7 @@ char* get_keylayoutname(int mode) {
}
break;
case 2:
- for(i = 0; answer[i] != '\0'; ++i) {
+ for(int i = 0; answer[i] != '\0'; ++i) {
if (answer[i] == '(') {
newans = &answer[i + 1];
} else if (answer[i] == ')' && newans != NULL) {
@@ -292,15 +264,17 @@ char* get_keylayoutname(int mode) {
default:
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);
// Free symbolic names structures
- XkbFreeClientMap(keyboard, 0, true);
- XCloseDisplay(display);
- display = NULL;
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) {
if (xkb_context == 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 not NULL, attempt to display stuff
// need to code some sane defaults for it
- layout_text = get_keylayoutname(atoi(optarg));
- if (layout_text)
- show_clock = true;
+ keylayout_mode = atoi(optarg);
}
else if (strcmp(longopts[longoptind].name, "timestr") == 0) {
//read in to timestr
@@ -1645,8 +1617,10 @@ int main(int argc, char *argv[]) {
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?");
+ 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,
@@ -1656,7 +1630,10 @@ int main(int argc, char *argv[]) {
&xkb_base_event,
&xkb_base_error) != 1)
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 =
(XCB_XKB_MAP_PART_KEY_TYPES |
XCB_XKB_MAP_PART_KEY_SYMS |
diff --git a/xcb.c b/xcb.c
@@ -12,6 +12,9 @@
#include <xcb/xcb_atom.h>
#include <xcb/xcb_aux.h>
#include <xcb/composite.h>
+#include <xcb/xkb.h>
+#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-x11.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
@@ -23,10 +26,13 @@
#include <sys/time.h>
#include "cursors.h"
+#include "i3lock.h"
+#include "xcb.h"
#include "unlock_indicator.h"
extern auth_state_t auth_state;
extern bool composite;
+extern bool debug_mode;
xcb_connection_t *conn;
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);
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;
+}
diff --git a/xcb.h b/xcb.h
@@ -3,6 +3,23 @@
#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_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);
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);
+char* xcb_get_key_group_names(xcb_connection_t *conn);
#endif