Implement Wayland hotkeys
parent
c80c2093cc
commit
7ec38bb0b0
@ -0,0 +1,59 @@
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <dlfcn.h>
|
||||
#include <cstdio>
|
||||
#include "real_dlsym.h"
|
||||
#include "wayland_hook.h"
|
||||
|
||||
EXPORT_C_(struct wl_display*) wl_display_connect(const char *name);
|
||||
EXPORT_C_(struct wl_display*) wl_display_connect_to_fd(int fd);
|
||||
|
||||
typedef struct wl_display* (*pwl_display_connect)(const char *name);
|
||||
typedef struct wl_display* (*pwl_display_connect_to_fd)(int fd);
|
||||
|
||||
pwl_display_connect wl_display_connect_ptr = nullptr;
|
||||
pwl_display_connect_to_fd wl_display_connect_to_fd_ptr = nullptr;
|
||||
void* wl_handle = nullptr;
|
||||
struct wl_display* wl_display_ptr = nullptr;
|
||||
|
||||
EXPORT_C_(struct wl_display*) wl_display_connect(const char *name)
|
||||
{
|
||||
struct wl_display *ret = NULL;
|
||||
|
||||
if(!wl_handle)
|
||||
{
|
||||
wl_handle = real_dlopen("libwayland-client.so", RTLD_LAZY);
|
||||
wl_display_connect_ptr = (pwl_display_connect)real_dlsym(wl_handle, "wl_display_connect");
|
||||
wl_display_connect_to_fd_ptr = (pwl_display_connect_to_fd)real_dlsym(wl_handle, "wl_display_connect_to_fd");
|
||||
}
|
||||
|
||||
ret = wl_display_connect_ptr(name);
|
||||
|
||||
if(!wl_display_ptr)
|
||||
wl_display_ptr = ret;
|
||||
|
||||
init_wayland_data();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_C_(struct wl_display*) wl_display_connect_to_fd(int fd)
|
||||
{
|
||||
struct wl_display *ret = NULL;
|
||||
|
||||
if(!wl_handle)
|
||||
{
|
||||
wl_handle = real_dlopen("libwayland-client.so", RTLD_LAZY);
|
||||
wl_display_connect_to_fd_ptr = (pwl_display_connect_to_fd)real_dlsym(wl_handle, "wl_display_connect_to_fd");
|
||||
wl_display_connect_ptr = (pwl_display_connect)real_dlsym(wl_handle, "wl_display_connect");
|
||||
}
|
||||
|
||||
ret = wl_display_connect_to_fd_ptr(fd);
|
||||
|
||||
if(!wl_display_ptr)
|
||||
wl_display_ptr = ret;
|
||||
|
||||
init_wayland_data();
|
||||
|
||||
return ret;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#include <wayland-client.h>
|
||||
#include <vector>
|
||||
|
||||
#ifndef KeySym
|
||||
typedef unsigned long KeySym;
|
||||
#endif
|
||||
|
||||
extern void* wl_handle;
|
||||
extern struct wl_display* wl_display_ptr;
|
||||
extern std::vector<KeySym> wl_pressed_keys;
|
||||
|
||||
void init_wayland_data();
|
||||
void update_wl_queue();
|
@ -0,0 +1,115 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <wayland-client.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <sys/mman.h>
|
||||
#include "wayland_hook.h"
|
||||
#include "timing.hpp"
|
||||
#include "keybinds.h"
|
||||
|
||||
struct wl_seat* seat = nullptr;
|
||||
struct wl_keyboard* keyboard = nullptr;
|
||||
struct xkb_context *context_xkb = nullptr;
|
||||
struct xkb_keymap *keymap_xkb = nullptr;
|
||||
struct xkb_state *state_xkb = nullptr;
|
||||
struct wl_event_queue* queue = nullptr;
|
||||
std::vector<KeySym> wl_pressed_keys {};
|
||||
|
||||
static void registry_handle_global(void *data, struct wl_registry* registry, uint32_t name, const char *interface, uint32_t version)
|
||||
{
|
||||
if(strcmp(interface, wl_seat_interface.name) == 0)
|
||||
{
|
||||
seat = (struct wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, 7);
|
||||
}
|
||||
}
|
||||
|
||||
static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name){}
|
||||
|
||||
static void wl_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size)
|
||||
{
|
||||
char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if(!context_xkb)
|
||||
context_xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
if(keymap_xkb && state_xkb)
|
||||
{
|
||||
xkb_keymap_unref(keymap_xkb);
|
||||
xkb_state_unref(state_xkb);
|
||||
}
|
||||
|
||||
keymap_xkb = xkb_keymap_new_from_string(
|
||||
context_xkb, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
state_xkb = xkb_state_new(keymap_xkb);
|
||||
|
||||
munmap((void*)map_shm, size);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void wl_keyboard_enter(void *user_data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys){}
|
||||
|
||||
static void wl_keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface)
|
||||
{
|
||||
wl_pressed_keys.clear();
|
||||
}
|
||||
|
||||
static void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
|
||||
{
|
||||
xkb_keycode_t keycode = key + 8;
|
||||
xkb_keysym_t keysym = xkb_state_key_get_one_sym(state_xkb, keycode);
|
||||
|
||||
if(state)
|
||||
{
|
||||
wl_pressed_keys.push_back(keysym);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = std::find(wl_pressed_keys.begin(), wl_pressed_keys.end(), keysym);
|
||||
if(it != wl_pressed_keys.end())
|
||||
wl_pressed_keys.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
static void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group){}
|
||||
|
||||
static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay){}
|
||||
|
||||
struct wl_registry_listener registry_listener {
|
||||
.global = registry_handle_global,
|
||||
.global_remove = registry_handle_global_remove
|
||||
};
|
||||
|
||||
struct wl_keyboard_listener keyboard_listener {
|
||||
.keymap = wl_keyboard_keymap,
|
||||
.enter = wl_keyboard_enter,
|
||||
.leave = wl_keyboard_leave,
|
||||
.key = wl_keyboard_key,
|
||||
.modifiers = wl_keyboard_modifiers,
|
||||
.repeat_info = wl_keyboard_repeat_info
|
||||
};
|
||||
|
||||
void update_wl_queue()
|
||||
{
|
||||
wl_display_roundtrip_queue(wl_display_ptr, queue);
|
||||
}
|
||||
|
||||
void init_wayland_data()
|
||||
{
|
||||
struct wl_display *display_wrapped = (struct wl_display*)wl_proxy_create_wrapper(wl_display_ptr);
|
||||
queue = wl_display_create_queue(wl_display_ptr);
|
||||
wl_proxy_set_queue((struct wl_proxy*)display_wrapped, queue);
|
||||
wl_registry *registry = wl_display_get_registry(display_wrapped);
|
||||
wl_proxy_wrapper_destroy(display_wrapped);
|
||||
wl_registry_add_listener(registry, ®istry_listener, NULL);
|
||||
update_wl_queue();
|
||||
update_wl_queue();
|
||||
keyboard = wl_seat_get_keyboard(seat);
|
||||
wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL);
|
||||
update_wl_queue();
|
||||
}
|
Loading…
Reference in New Issue