diff options
author | Jari Vetoniemi <mailroxas@gmail.com> | 2015-01-16 01:59:09 +0200 |
---|---|---|
committer | Jari Vetoniemi <mailroxas@gmail.com> | 2015-01-16 01:59:09 +0200 |
commit | ada6edc175eb89d318e55204368e2ba5dad07b1b (patch) | |
tree | 035ff1c1db386e48135705b5c663060248b3fa66 /lib/renderers/x11/x11.c | |
parent | 0cd1c991d20c5c10190e520071691e849541f619 (diff) | |
download | bemenu-ada6edc175eb89d318e55204368e2ba5dad07b1b.tar.gz bemenu-ada6edc175eb89d318e55204368e2ba5dad07b1b.tar.bz2 bemenu-ada6edc175eb89d318e55204368e2ba5dad07b1b.zip |
Add X11 renderer.
Diffstat (limited to 'lib/renderers/x11/x11.c')
-rw-r--r-- | lib/renderers/x11/x11.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/lib/renderers/x11/x11.c b/lib/renderers/x11/x11.c new file mode 100644 index 0000000..3e9ced9 --- /dev/null +++ b/lib/renderers/x11/x11.c @@ -0,0 +1,235 @@ +#define _DEFAULT_SOURCE +#include "internal.h" +#include "version.h" +#include "x11.h" +#include "xkb_unicode.h" + +#include <stdlib.h> +#include <unistd.h> + +static void +render(const struct bm_menu *menu) +{ + struct x11 *x11 = menu->renderer->internal; + + bm_x11_window_render(&x11->window, menu); + XFlush(x11->display); + + XEvent ev; + if (XNextEvent(x11->display, &ev) || XFilterEvent(&ev, x11->window.drawable)) + return; + + switch (ev.type) { + case KeyPress: + bm_x11_window_key_press(&x11->window, &ev.xkey); + break; + case SelectionNotify: + // paste here + break; + case VisibilityNotify: + if (ev.xvisibility.state != VisibilityUnobscured) { + XRaiseWindow(x11->display, x11->window.drawable); + XFlush(x11->display); + } + break; + } +} + +static enum bm_key +poll_key(const struct bm_menu *menu, unsigned int *unicode) +{ + struct x11 *x11 = menu->renderer->internal; + assert(x11 && unicode); + + if (x11->window.keysym == NoSymbol) + return BM_KEY_UNICODE; + + KeySym sym = x11->window.keysym; + uint32_t mods = x11->window.mods; + *unicode = bm_x11_key_sym2unicode(sym); + + x11->window.keysym = NoSymbol; + + switch (sym) { + case XK_Up: + return BM_KEY_UP; + + case XK_Down: + return BM_KEY_DOWN; + + case XK_Left: + return BM_KEY_LEFT; + + case XK_Right: + return BM_KEY_RIGHT; + + case XK_Home: + return BM_KEY_HOME; + + case XK_End: + return BM_KEY_END; + + case XK_Page_Up: + return (mods & MOD_SHIFT ? BM_KEY_SHIFT_PAGE_UP : BM_KEY_PAGE_UP); + + case XK_Page_Down: + return (mods & MOD_SHIFT ? BM_KEY_SHIFT_PAGE_DOWN : BM_KEY_PAGE_DOWN); + + case XK_BackSpace: + return BM_KEY_BACKSPACE; + + case XK_Delete: + return (mods & MOD_SHIFT ? BM_KEY_LINE_DELETE_LEFT : BM_KEY_DELETE); + + case XK_Tab: + return (mods & MOD_SHIFT ? BM_KEY_SHIFT_TAB : BM_KEY_TAB); + + case XK_ISO_Left_Tab: + return BM_KEY_SHIFT_TAB; + + case XK_Insert: + return BM_KEY_SHIFT_RETURN; + + case XK_Return: + return (mods & MOD_CTRL ? BM_KEY_CONTROL_RETURN : (mods & MOD_SHIFT ? BM_KEY_SHIFT_RETURN : BM_KEY_RETURN)); + + case XK_Escape: + return BM_KEY_ESCAPE; + + case XK_p: + return (mods & MOD_CTRL ? BM_KEY_UP : BM_KEY_UNICODE); + + case XK_n: + return (mods & MOD_CTRL ? BM_KEY_DOWN : BM_KEY_UNICODE); + + case XK_l: + return (mods & MOD_CTRL ? BM_KEY_LEFT : BM_KEY_UNICODE); + + case XK_f: + return (mods & MOD_CTRL ? BM_KEY_RIGHT : BM_KEY_UNICODE); + + case XK_a: + return (mods & MOD_CTRL ? BM_KEY_HOME : BM_KEY_UNICODE); + + case XK_e: + return (mods & MOD_CTRL ? BM_KEY_END : BM_KEY_UNICODE); + + case XK_h: + return (mods & MOD_CTRL ? BM_KEY_BACKSPACE : BM_KEY_UNICODE); + + case XK_u: + return (mods & MOD_CTRL ? BM_KEY_LINE_DELETE_LEFT : BM_KEY_UNICODE); + + case XK_k: + return (mods & MOD_CTRL ? BM_KEY_LINE_DELETE_RIGHT : BM_KEY_UNICODE); + + case XK_w: + return (mods & MOD_CTRL ? BM_KEY_WORD_DELETE : BM_KEY_UNICODE); + + default: break; + } + + return BM_KEY_UNICODE; +} + +static uint32_t +get_displayed_count(const struct bm_menu *menu) +{ + struct x11 *x11 = menu->renderer->internal; + assert(x11); + return x11->window.displayed; +} + +static void +set_bottom(const struct bm_menu *menu, bool bottom) +{ + struct x11 *x11 = menu->renderer->internal; + assert(x11); + bm_x11_window_set_bottom(&x11->window, bottom); +} + +static void +set_monitor(const struct bm_menu *menu, uint32_t monitor) +{ + struct x11 *x11 = menu->renderer->internal; + assert(x11); + bm_x11_window_set_monitor(&x11->window, monitor); +} + +static void +grab_keyboard(const struct bm_menu *menu, bool grab) +{ + struct x11 *x11 = menu->renderer->internal; + assert(x11); + + if (grab) { + for (uint32_t i = 0; i < 1000; ++i) { + if (XGrabKeyboard(x11->display, DefaultRootWindow(x11->display), True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) + return; + usleep(1000); + } + + fprintf(stderr, "x11: cannot grab keyboard\n"); + } else { + XUngrabKeyboard(x11->display, CurrentTime); + } +} + +static void +destructor(struct bm_menu *menu) +{ + struct x11 *x11 = menu->renderer->internal; + + if (!x11) + return; + + bm_x11_window_destroy(&x11->window); + + if (x11->display) + XCloseDisplay(x11->display); + + free(x11); + menu->renderer->internal = NULL; +} + +static bool +constructor(struct bm_menu *menu) +{ + struct x11 *x11; + if (!(menu->renderer->internal = x11 = calloc(1, sizeof(struct x11)))) + goto fail; + + if (!(x11->display = XOpenDisplay(NULL))) + goto fail; + + if (!bm_x11_window_create(&x11->window, x11->display)) + goto fail; + + x11->window.bottom = menu->bottom; + bm_x11_window_set_monitor(&x11->window, menu->monitor); + + x11->window.notify.render = bm_cairo_paint; + return true; + +fail: + destructor(menu); + return false; +} + +extern const char* +register_renderer(struct render_api *api) +{ + api->constructor = constructor; + api->destructor = destructor; + api->get_displayed_count = get_displayed_count; + api->poll_key = poll_key; + api->render = render; + api->set_bottom = set_bottom; + api->set_monitor = set_monitor; + api->grab_keyboard = grab_keyboard; + api->prioritory = BM_PRIO_GUI; + api->version = BM_PLUGIN_VERSION; + return "x11"; +} + +/* vim: set ts=8 sw=4 tw=0 :*/ |