summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@users.noreply.github.com>2015-02-12 23:08:35 +0100
committerMichael Stapelberg <stapelberg@users.noreply.github.com>2015-02-12 23:08:35 +0100
commit783509b872726627c7c0d65e092e265c5e2f0201 (patch)
tree4eceeab61792acda7ca64a74c33add7fd40a5bad
parent3898f75672dd2318d836ccfab06ed00fa3c39558 (diff)
parent86323f6e042a3d22218f64eba9c97c3cc0d4b04b (diff)
Merge pull request #6 from danielotero/master
Add support for Compose and dead-keys with libxkbcommon
-rw-r--r--README.md4
-rw-r--r--i3lock.c65
2 files changed, 66 insertions, 3 deletions
diff --git a/README.md b/README.md
index b587c27..6965a38 100644
--- a/README.md
+++ b/README.md
@@ -29,8 +29,8 @@ Requirements
- libx11-dev
- libx11-xcb-dev
- libxkbfile-dev
-- libxkbcommon >= 0.4.0
-- libxkbcommon-x11 >= 0.4.0
+- libxkbcommon >= 0.5.0
+- libxkbcommon-x11 >= 0.5.0
Running i3lock
-------------
diff --git a/i3lock.c b/i3lock.c
index 942781a..7f8218e 100644
--- a/i3lock.c
+++ b/i3lock.c
@@ -25,6 +25,7 @@
#include <ev.h>
#include <sys/mman.h>
#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-compose.h>
#include <xkbcommon/xkbcommon-x11.h>
#include <cairo.h>
#include <cairo/cairo-xcb.h>
@@ -72,6 +73,8 @@ bool show_failed_attempts = false;
static struct xkb_state *xkb_state;
static struct xkb_context *xkb_context;
static struct xkb_keymap *xkb_keymap;
+static struct xkb_compose_table *xkb_compose_table;
+static struct xkb_compose_state *xkb_compose_state;
static uint8_t xkb_base_event;
static uint8_t xkb_base_error;
@@ -138,6 +141,30 @@ static bool load_keymap(void) {
}
/*
+ * Loads the XKB compose table from the given locale.
+ *
+ */
+static bool load_compose_table(const char *locale) {
+ xkb_compose_table_unref(xkb_compose_table);
+
+ if ((xkb_compose_table = xkb_compose_table_new_from_locale(xkb_context, locale, 0)) == NULL) {
+ fprintf(stderr, "[i3lock] xkb_compose_table_new_from_locale failed\n");
+ return false;
+ }
+
+ struct xkb_compose_state *new_compose_state = xkb_compose_state_new(xkb_compose_table, 0);
+ if (new_compose_state == NULL) {
+ fprintf(stderr, "[i3lock] xkb_compose_state_new failed\n");
+ return false;
+ }
+
+ xkb_compose_state_unref(xkb_compose_state);
+ xkb_compose_state = new_compose_state;
+
+ return true;
+}
+
+/*
* Clears the memory which stored the password to be a bit safer against
* cold-boot attacks.
*
@@ -289,13 +316,36 @@ static void handle_key_press(xcb_key_press_event_t *event) {
char buffer[128];
int n;
bool ctrl;
+ bool composed = false;
ksym = xkb_state_key_get_one_sym(xkb_state, event->detail);
ctrl = xkb_state_mod_name_is_active(xkb_state, "Control", XKB_STATE_MODS_DEPRESSED);
/* The buffer will be null-terminated, so n >= 2 for 1 actual character. */
memset(buffer, '\0', sizeof(buffer));
- n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer));
+
+ if (xkb_compose_state && xkb_compose_state_feed(xkb_compose_state, ksym) == XKB_COMPOSE_FEED_ACCEPTED) {
+ switch (xkb_compose_state_get_status(xkb_compose_state)) {
+ case XKB_COMPOSE_NOTHING:
+ break;
+ case XKB_COMPOSE_COMPOSING:
+ return;
+ case XKB_COMPOSE_COMPOSED:
+ /* xkb_compose_state_get_utf8 doesn't include the terminating byte in the return value
+ * as xkb_keysym_to_utf8 does. Adding one makes the variable n consistent. */
+ n = xkb_compose_state_get_utf8(xkb_compose_state, buffer, sizeof(buffer)) + 1;
+ ksym = xkb_compose_state_get_one_sym(xkb_compose_state);
+ composed = true;
+ break;
+ case XKB_COMPOSE_CANCELLED:
+ xkb_compose_state_reset(xkb_compose_state);
+ return;
+ }
+ }
+
+ if (!composed) {
+ n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer));
+ }
switch (ksym) {
case XKB_KEY_Return:
@@ -824,6 +874,19 @@ int main(int argc, char *argv[]) {
if (!load_keymap())
errx(EXIT_FAILURE, "Could not load keymap");
+ const char *locale = getenv("LC_ALL");
+ if (!locale)
+ locale = getenv("LC_CTYPE");
+ if (!locale)
+ locale = getenv("LANG");
+ if (!locale) {
+ if (debug_mode)
+ fprintf(stderr, "Can't detect your locale, fallback to C\n");
+ locale = "C";
+ }
+
+ load_compose_table(locale);
+
xinerama_init();
xinerama_query_screens();