From 5aa1fb5eb558f58f0bcfe495b8f49414aa6d88a2 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Thu, 26 Oct 2017 22:18:26 +0200 Subject: [PATCH] Add indicator to show current indicator using `libxkbcommon` The indicator is based on XCB-XKB and `libxkbcommon`. It can be tested using the following configuration: ``` bar-list = ["bar"]; bar: { position: "top"; block-list: ["ya_xkb"]; ya_xkb: { exec: "YABAR_KEYBOARD_LAYOUT"; interval: 1; }; } ``` The followinng new dependencies have been introduced: - libxkbcommon-dev - libxkbcommon-x11-dev - libxcb-xkb-dev Both work with libxcb and allow the usage of XKB through an XCB session. In this case the session `ya.c` created by `src/ya_exec.c` can be used for this indicator, so no extra X11 logic is needed. --- .travis.yml | 6 ++++ Makefile | 2 +- README.md | 4 +-- doc/yabar.1.asciidoc | 5 ++++ examples/example.config | 4 +++ include/yabar.h | 9 +++--- shell.nix | 1 + src/intern_blks/ya_intern.c | 55 +++++++++++++++++++++++++++++++++++++ 8 files changed, 79 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index ba0ba15..6291c27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,9 @@ matrix: - libasound2-dev - libiw-dev - wget + - libxkbcommon-dev + - libxkbcommon-x11-dev + - libxcb-xkb-dev before_install: - wget https://github.com/acrisci/playerctl/releases/download/v0.5.0/playerctl-0.5.0_amd64.deb -O playerctl.deb - sudo dpkg -i playerctl.deb @@ -37,6 +40,9 @@ matrix: - libxcb-icccm4-dev - libasound2-dev - libiw-dev + - libxkbcommon-dev + - libxkbcommon-x11-dev + - libxcb-xkb-dev - script: make docs language: generic addons: diff --git a/Makefile b/Makefile index 8a9df29..b86001a 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ DEPS += playerctl-1.0 endif LDFLAGS += -flto -O2 -LDLIBS += -liw -lxcb -lpthread -lxcb-randr -lxcb-ewmh -lxcb-icccm -lm `pkg-config --libs $(DEPS)` +LDLIBS += -liw -lxcb -lpthread -lxcb-randr -lxcb-ewmh -lxcb-icccm -lxkbcommon -lxkbcommon-x11 -lxcb-xkb -lm `pkg-config --libs $(DEPS)` PROGRAM := yabar DOCS := $(PROGRAM).1 PREFIX ?= /usr diff --git a/README.md b/README.md index b1dee28..ba10b6e 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,8 @@ AUR: [yabar](https://aur.archlinux.org/packages/yabar/) and [yabar-git](https:// ### From Source Yabar initially requires a C compiler (e.g. gcc or clang), make as well as the libraries libconfig, cairo, pango and alsa. The feature `DYA_INTERNAL_EWMH` in `Makefile` additionaly xcb-ewmh (or xcb-util-wm in some distros) and the feature `-DYA_ICON` requires gdk-pixbuf2. These dependencies can be installed through your distribution's package manager: -* Fedora: `dnf install libconfig-devel cairo-devel pango-devel gdk-pixbuf2-devel alsa-lib-devel xcb-util-wm-devel wireless-tools-devel` -* Debian / Ubuntu: `apt-get install libcairo2-dev libpango1.0-dev libconfig-dev libxcb-randr0-dev libxcb-ewmh-dev libxcb-icccm4-dev libgdk-pixbuf2.0-dev libasound2-dev libiw-dev` +* Fedora: `dnf install libconfig-devel cairo-devel pango-devel gdk-pixbuf2-devel alsa-lib-devel xcb-util-wm-devel wireless-tools-devel libxkbcommon-devel libxkbcommon-x11-devel` +* Debian / Ubuntu: `apt-get install libcairo2-dev libpango1.0-dev libconfig-dev libxcb-randr0-dev libxcb-ewmh-dev libxcb-icccm4-dev libgdk-pixbuf2.0-dev libasound2-dev libiw-dev libxkbcommon-dev libxkbcommon-x11-dev libxcb-xkb-dev` You can install yabar as follows: diff --git a/doc/yabar.1.asciidoc b/doc/yabar.1.asciidoc index 6d034c3..0a2e9f3 100644 --- a/doc/yabar.1.asciidoc +++ b/doc/yabar.1.asciidoc @@ -368,6 +368,11 @@ internal-option1: "/dev/sda"; ** "/dev/mapper/vgc-" all mounted logical volumes of volume group vgc ** "/dev" all mounted partitions / logical volumes +* *YABAR_KEYBOARD_LAYOUT* - *XKB layout*: Retrieves the uppercased layout string from libxkb. Example: +--- +exec: "YABAR_KEYBOARD_LAYOUT"; +--- + LICENSE ------- Yabar is licensed under the *MIT license*. For more info check out the file 'LICENSE'. diff --git a/examples/example.config b/examples/example.config index 19d6958..c2f971c 100644 --- a/examples/example.config +++ b/examples/example.config @@ -205,4 +205,8 @@ topbar:{ type: "periodic"; internal-option1: "spotify"; } + keyboard: { + exec: "YABAR_KEYBOARD_LAYOUT"; + interval: 1; + } } diff --git a/include/yabar.h b/include/yabar.h index 5757c86..8a45c93 100644 --- a/include/yabar.h +++ b/include/yabar.h @@ -120,15 +120,15 @@ enum { #ifdef YA_INTERNAL_EWMH #ifdef PLAYERCTL -#define YA_INTERNAL_LEN 17 +#define YA_INTERNAL_LEN 18 #else -#define YA_INTERNAL_LEN 16 +#define YA_INTERNAL_LEN 17 #endif #else #ifdef PLAYERCTL -#define YA_INTERNAL_LEN 15 +#define YA_INTERNAL_LEN 16 #else -#define YA_INTERNAL_LEN 14 +#define YA_INTERNAL_LEN 15 #endif #endif enum { @@ -146,6 +146,7 @@ enum { YA_INT_VOLUME, YA_INT_WIFI, YA_INT_DISKSPACE, + YA_INT_KEYBOARD_LAYOUT, #ifdef PLAYERCTL YA_INT_SONG, #endif diff --git a/shell.nix b/shell.nix index d0f8f53..bd8711b 100644 --- a/shell.nix +++ b/shell.nix @@ -5,5 +5,6 @@ with import {}; stdenv.mkDerivation { buildInputs = [ cairo gdk_pixbuf libconfig pango pkgconfig xorg.xcbutilwm docbook_xsl alsaLib wirelesstools asciidoc libxslt makeWrapper libxml2 playerctl + libxkbcommon ]; } diff --git a/src/intern_blks/ya_intern.c b/src/intern_blks/ya_intern.c index 616921e..0a35f6a 100644 --- a/src/intern_blks/ya_intern.c +++ b/src/intern_blks/ya_intern.c @@ -22,6 +22,7 @@ void ya_int_battery(ya_block_t *blk); void ya_int_volume(ya_block_t *blk); void ya_int_wifi(ya_block_t *blk); void ya_int_diskspace(ya_block_t *blk); +void ya_int_keyboard_layout(ya_block_t *blk); #ifdef PLAYERCTL void ya_int_song(ya_block_t *blk); @@ -45,6 +46,7 @@ struct reserved_blk ya_reserved_blks[YA_INTERNAL_LEN] = { {"YABAR_VOLUME", ya_int_volume}, {"YABAR_WIFI", ya_int_wifi}, {"YABAR_DISKSPACE", ya_int_diskspace}, + {"YABAR_KEYBOARD_LAYOUT", ya_int_keyboard_layout}, #ifdef YA_INTERNAL_EWMH {"YABAR_TITLE", NULL}, {"YABAR_WORKSPACE", NULL} @@ -136,6 +138,59 @@ __attribute__ ((gnu_inline)) inline void ya_setup_prefix_suffix(ya_block_t *blk, } } +#include +#include +#include + +void ya_int_keyboard_layout(ya_block_t *blk) { + char *startstr = blk->buf; + size_t prflen = 0, suflen = 0; + ya_setup_prefix_suffix(blk, &prflen, &suflen, &startstr); + + struct xkb_keymap *keymap; + struct xkb_state *state; + int32_t device_id; + struct xkb_context *ctx; + const char* name; + xkb_layout_index_t layout; + + static uint8_t xkb_base_event; + static uint8_t xkb_base_error; + + int ret = xkb_x11_setup_xkb_extension( + ya.c, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION, + 0, + NULL, + NULL, + &xkb_base_event, + &xkb_base_error); + if (!ret) + ya_block_error(blk, "Unable to register XKB extension!"); + + ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!ctx) ya_block_error(blk, "Cannot create new XCB context!"); + device_id = xkb_x11_get_core_keyboard_device_id(ya.c); + if (device_id == -1) ya_block_error(blk, "Empty reply, cannot get device id!"); + + while (1) { + keymap = xkb_x11_keymap_new_from_device(ctx, ya.c, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!keymap) ya_block_error(blk, "Cannot find keymap!"); + state = xkb_state_new(keymap); + + layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); + name = xkb_keymap_layout_get_name(keymap, layout); + sprintf(startstr, "%s", name); + + xkb_state_unref(state); + xkb_keymap_unref(keymap); + + ya_draw_pango_text(blk); + sleep(blk->sleep); + } +} + #ifdef PLAYERCTL #include #define CHECK_PLAYER_ERROR(PREFIX) \