diff options
Diffstat (limited to 'bin')
-rw-r--r-- | bin/.gitignore | 1 | ||||
-rw-r--r-- | bin/Makefile | 3 | ||||
-rwxr-xr-x | bin/i3status.py | 63 | ||||
-rw-r--r-- | bin/kbdlayout.c | 57 |
4 files changed, 124 insertions, 0 deletions
diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..95d9967 --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1 @@ +kbdlayout diff --git a/bin/Makefile b/bin/Makefile new file mode 100644 index 0000000..221dde7 --- /dev/null +++ b/bin/Makefile @@ -0,0 +1,3 @@ +kbdlayout: kbdlayout.c + $(CC) $(CCFLAGS) -lX11 $< -o $@ + diff --git a/bin/i3status.py b/bin/i3status.py new file mode 100755 index 0000000..421317e --- /dev/null +++ b/bin/i3status.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +import json +from select import select +from subprocess import Popen, PIPE +import sys + +def remove_empty_outputs(obj): + return [o for o in obj if o['full_text'].strip() != ''] + +first = True +def print_i3stat(j): + global first + j = remove_empty_outputs(j) + sys.stdout.write(('' if first else ',') + json.dumps(j) + '\n') + sys.stdout.flush() + first = False + +def parse_i3stat(s): + if s[0] == ',': + s = s[1:] + j = json.loads(s) + return j + +def parse_kbdlayout(s): + colors = { 'us(intl)' : '#66ccff', + 'us(dvorak-intl)' : '#dc68fc', + 'ru(phonetic)' : '#ff3300', + 'il(biblicalSIL)' : '#66ff66' + } + return [{'full_text': s, 'color': colors[s]}] + +def merge_status_items(*args): + return [item for sublist in args for item in sublist] + +if __name__ == '__main__': + timeout = 0.1 + + # open subprocesses + i3stat = Popen(['i3status'], stdout=PIPE, bufsize=1, close_fds=True) + kbdlayout = Popen(['unbuffer', 'kbdlayout'], + stdout=PIPE, bufsize=1, close_fds=True) + + # skip i3status header + sys.stdout.write(i3stat.stdout.readline()) + sys.stdout.write(i3stat.stdout.readline()) + + stat, kbd = [], [] + try: + while True: + fs = select([p.stdout for p in [i3stat, kbdlayout]], [], [])[0] + for f in fs: + line = f.readline()[:-1] + if f == kbdlayout.stdout: + kbd = parse_kbdlayout(line) + else: + stat = parse_i3stat(line) + + print_i3stat(merge_status_items(kbd, stat)) + + except: + i3stat.kill() + kbdlayout.kill() + diff --git a/bin/kbdlayout.c b/bin/kbdlayout.c new file mode 100644 index 0000000..7cdd97e --- /dev/null +++ b/bin/kbdlayout.c @@ -0,0 +1,57 @@ +#include <X11/XKBlib.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +char* getActiveLayout(char* names, unsigned char active) { + int i; + for (i = 0; names[i]; i++) { + if (names[i] == '+') { + if (active <= 0) { + int j = ++i; + for (; names[j] && names[j] != '+' && names[j] != ':'; j++); + char* ret = malloc(j - i + 1); + strncpy(ret, names + i, j - i); + ret[j - i] = '\0'; + return ret; + } else { + active--; + } + } + } + return NULL; +} + +int main(void) { + + int evCode, errRet, rsnRet; + int maj = XkbMajorVersion; + int min = XkbMinorVersion; + + Display* disp = XkbOpenDisplay("", &evCode, &errRet, &maj, &min, &rsnRet); + + // State + XkbStatePtr state = calloc(1, sizeof(XkbStateRec)); + XkbGetState(disp, 0x100, state); + + // Names + XkbDescPtr desc = XkbAllocKeyboard(); + XkbGetNames(disp, XkbSymbolsNameMask, desc); + + Atom symNameAtom = desc->names->symbols; + char* layouts = XGetAtomName(disp, symNameAtom); + + printf("%s\n", getActiveLayout(layouts, state->group)); + + unsigned int mask = XkbStateNotifyMask; + XkbSelectEvents(disp, XkbUseCoreKbd, mask, mask); + + XkbEvent event; + while (1) { + XNextEvent(disp, &event.core); + if (event.state.changed & 0x90) + printf("%s\n", getActiveLayout(layouts, event.state.group)); + } + +} + |