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) \
|
||||
$(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 \
|
||||
|
|
|
@ -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
|
||||
|
|
73
i3lock.c
73
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 |
|
||||
|
|
104
xcb.c
104
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;
|
||||
}
|
||||
|
|
18
xcb.h
18
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
|
||||
|
|
Loading…
Reference in New Issue