1
0
Fork 0
mirror of https://github.com/Cloudef/bemenu synced 2024-06-01 04:16:21 +02:00
bemenu/lib/renderers/wayland/wayland.c

244 lines
6.6 KiB
C
Raw Normal View History

2014-11-02 05:48:53 +01:00
#define _DEFAULT_SOURCE
2014-10-23 01:11:10 +02:00
#include "internal.h"
#include "version.h"
#include "wayland.h"
2014-10-23 01:11:10 +02:00
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
2014-11-02 05:48:53 +01:00
#include <unistd.h>
#include <errno.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
static int efd;
2014-10-23 01:11:10 +02:00
static void
render(const struct bm_menu *menu)
{
struct wayland *wayland = menu->renderer->internal;
2014-11-02 05:48:53 +01:00
wl_display_dispatch_pending(wayland->display);
if (wl_display_flush(wayland->display) < 0 && errno != EAGAIN) {
wayland->input.sym = XKB_KEY_Escape;
return;
}
struct epoll_event ep[16];
uint32_t num = epoll_wait(efd, ep, 16, -1);
for (uint32_t i = 0; i < num; ++i) {
if (ep[i].data.ptr == &wayland->fds.display) {
if (ep[i].events & EPOLLERR || ep[i].events & EPOLLHUP ||
((ep[i].events & EPOLLIN) && wl_display_dispatch(wayland->display) < 0))
wayland->input.sym = XKB_KEY_Escape;
} else if (ep[i].data.ptr == &wayland->fds.repeat) {
bm_wl_repeat(wayland);
}
}
uint32_t count;
bm_menu_get_filtered_items(menu, &count);
uint32_t lines = (count < menu->lines ? count : menu->lines) + 1;
bm_wl_window_render(&wayland->window, menu, lines);
2014-10-23 01:11:10 +02:00
}
static enum bm_key
poll_key(const struct bm_menu *menu, unsigned int *unicode)
{
struct wayland *wayland = menu->renderer->internal;
assert(wayland && unicode);
2014-10-23 01:11:10 +02:00
*unicode = 0;
if (wayland->input.sym == XKB_KEY_NoSymbol)
2014-10-23 01:11:10 +02:00
return BM_KEY_UNICODE;
2014-11-02 05:48:53 +01:00
xkb_keysym_t sym = wayland->input.sym;
uint32_t mods = wayland->input.modifiers;
*unicode = xkb_state_key_get_utf32(wayland->input.xkb.state, wayland->input.code);
2014-10-23 01:11:10 +02:00
if (!*unicode && wayland->input.code == 23 && (mods & MOD_SHIFT))
return BM_KEY_SHIFT_TAB;
2014-11-02 05:48:53 +01:00
wayland->input.sym = XKB_KEY_NoSymbol;
wayland->input.code = 0;
switch (sym) {
2014-10-23 01:11:10 +02:00
case XKB_KEY_Up:
return BM_KEY_UP;
case XKB_KEY_Down:
return BM_KEY_DOWN;
case XKB_KEY_Left:
return BM_KEY_LEFT;
case XKB_KEY_Right:
return BM_KEY_RIGHT;
case XKB_KEY_Home:
return BM_KEY_HOME;
case XKB_KEY_End:
return BM_KEY_END;
case XKB_KEY_SunPageUp:
return (mods & MOD_SHIFT ? BM_KEY_SHIFT_PAGE_UP : BM_KEY_PAGE_UP);
2014-10-23 01:11:10 +02:00
case XKB_KEY_SunPageDown:
return (mods & MOD_SHIFT ? BM_KEY_SHIFT_PAGE_DOWN : BM_KEY_PAGE_DOWN);
2014-10-23 01:11:10 +02:00
case XKB_KEY_BackSpace:
return BM_KEY_BACKSPACE;
case XKB_KEY_Delete:
return (mods & MOD_SHIFT ? BM_KEY_LINE_DELETE_LEFT : BM_KEY_DELETE);
2014-10-23 01:11:10 +02:00
case XKB_KEY_Tab:
return (mods & MOD_SHIFT ? BM_KEY_SHIFT_TAB : BM_KEY_TAB);
2014-10-23 01:11:10 +02:00
case XKB_KEY_Insert:
return BM_KEY_SHIFT_RETURN;
case XKB_KEY_Return:
return (mods & MOD_CTRL ? BM_KEY_CONTROL_RETURN : (mods & MOD_SHIFT ? BM_KEY_SHIFT_RETURN : BM_KEY_RETURN));
2014-10-23 01:11:10 +02:00
case XKB_KEY_Escape:
return BM_KEY_ESCAPE;
case XKB_KEY_p:
return (mods & MOD_CTRL ? BM_KEY_UP : BM_KEY_UNICODE);
case XKB_KEY_n:
return (mods & MOD_CTRL ? BM_KEY_DOWN : BM_KEY_UNICODE);
case XKB_KEY_l:
return (mods & MOD_CTRL ? BM_KEY_LEFT : BM_KEY_UNICODE);
case XKB_KEY_f:
return (mods & MOD_CTRL ? BM_KEY_RIGHT : BM_KEY_UNICODE);
case XKB_KEY_a:
return (mods & MOD_CTRL ? BM_KEY_HOME : BM_KEY_UNICODE);
case XKB_KEY_e:
return (mods & MOD_CTRL ? BM_KEY_END : BM_KEY_UNICODE);
case XKB_KEY_h:
return (mods & MOD_CTRL ? BM_KEY_BACKSPACE : BM_KEY_UNICODE);
case XKB_KEY_u:
return (mods & MOD_CTRL ? BM_KEY_LINE_DELETE_LEFT : BM_KEY_UNICODE);
case XKB_KEY_k:
return (mods & MOD_CTRL ? BM_KEY_LINE_DELETE_RIGHT : BM_KEY_UNICODE);
case XKB_KEY_w:
return (mods & MOD_CTRL ? BM_KEY_WORD_DELETE : BM_KEY_UNICODE);
2014-10-23 01:11:10 +02:00
default: break;
}
return BM_KEY_UNICODE;
}
static uint32_t
get_displayed_count(const struct bm_menu *menu)
{
struct wayland *wayland = menu->renderer->internal;
assert(wayland);
return wayland->window.displayed;
2014-10-23 01:11:10 +02:00
}
static void
destructor(struct bm_menu *menu)
{
struct wayland *wayland = menu->renderer->internal;
2014-10-23 01:11:10 +02:00
if (!wayland)
return;
2014-10-23 01:11:10 +02:00
bm_wl_window_destroy(&wayland->window);
bm_wl_registry_destroy(wayland);
2014-10-23 01:11:10 +02:00
xkb_context_unref(wayland->input.xkb.context);
if (wayland->display) {
2014-11-02 05:48:53 +01:00
epoll_ctl(efd, EPOLL_CTL_DEL, wayland->fds.repeat, NULL);
epoll_ctl(efd, EPOLL_CTL_DEL, wayland->fds.display, NULL);
close(wayland->fds.repeat);
wl_display_flush(wayland->display);
wl_display_disconnect(wayland->display);
2014-10-23 01:11:10 +02:00
}
free(wayland);
menu->renderer->internal = NULL;
2014-10-23 01:11:10 +02:00
}
static bool
constructor(struct bm_menu *menu)
{
struct wayland *wayland;
if (!(menu->renderer->internal = wayland = calloc(1, sizeof(struct wayland))))
2014-10-23 01:11:10 +02:00
goto fail;
2014-11-02 06:58:34 +01:00
wayland->window.width = 800;
wayland->window.height = 14;
if (!(wayland->display = wl_display_connect(NULL)))
2014-10-23 01:11:10 +02:00
goto fail;
if (!(wayland->input.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS)))
2014-10-23 01:11:10 +02:00
goto fail;
if (!bm_wl_registry_register(wayland))
2014-10-23 01:11:10 +02:00
goto fail;
struct wl_surface *surface;
if (!(surface = wl_compositor_create_surface(wayland->compositor)))
2014-10-23 01:11:10 +02:00
goto fail;
if (!bm_wl_window_create(&wayland->window, wayland->shm, wayland->shell, wayland->xdg_shell, surface))
2014-10-23 01:11:10 +02:00
goto fail;
2014-11-02 05:48:53 +01:00
if (!efd && (efd = epoll_create(EPOLL_CLOEXEC)) < 0)
goto fail;
wayland->fds.display = wl_display_get_fd(wayland->display);
wayland->fds.repeat = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
struct epoll_event ep;
ep.events = EPOLLIN | EPOLLERR | EPOLLHUP;
ep.data.ptr = &wayland->fds.display;
epoll_ctl(efd, EPOLL_CTL_ADD, wayland->fds.display, &ep);
struct epoll_event ep2;
ep2.events = EPOLLIN;
ep2.data.ptr = &wayland->fds.repeat;
epoll_ctl(efd, EPOLL_CTL_ADD, wayland->fds.repeat, &ep2);
wayland->window.notify.render = bm_cairo_paint;
2014-11-02 05:48:53 +01:00
wayland->input.repeat_fd = &wayland->fds.repeat;
2014-10-23 01:11:10 +02:00
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->prioritory = BM_PRIO_GUI;
2014-10-25 15:39:39 +02:00
api->version = BM_PLUGIN_VERSION;
2014-10-23 01:11:10 +02:00
return "wayland";
}
/* vim: set ts=8 sw=4 tw=0 :*/