feat: add xorg backend (#1)
* Xorg backend * Xorg backend hotfix * xorg.c: issues fixed; ukb.c: xorg backend added * \t replacement * ukb.c fromatting improved * ukb.c typo fix * fix: include order --------- Co-authored-by: mrsobakin <68982655+mrsobakin@users.noreply.github.com>
This commit is contained in:
parent
9b34bfc435
commit
4bbcfb2f10
2 changed files with 126 additions and 1 deletions
124
src/backends/xorg.c
Normal file
124
src/backends/xorg.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "ukb.h"
|
||||
#include "../utils.h"
|
||||
|
||||
|
||||
static char current_layout[128] = {0};
|
||||
|
||||
|
||||
static Display *x_display = 0;
|
||||
|
||||
static ukb_err_t update_current_layout() {
|
||||
XkbStateRec xkb_state;
|
||||
if (XkbGetState(x_display, XkbUseCoreKbd, &xkb_state) != Success) {
|
||||
UKB_ERR("Failed to get keyboard state.");
|
||||
}
|
||||
|
||||
XkbDescPtr desc_ptr = XkbGetKeyboard(x_display, XkbAllComponentsMask, XkbUseCoreKbd);
|
||||
if (!desc_ptr) {
|
||||
UKB_ERR("Failed to get keyboard description.");
|
||||
}
|
||||
if (!desc_ptr->names) {
|
||||
UKB_ERR("Failed to get keyboard names.");
|
||||
}
|
||||
|
||||
Status error_get_controls = XkbGetControls(x_display, XkbAllComponentsMask, desc_ptr);
|
||||
if (error_get_controls != Success || !desc_ptr->ctrls) {
|
||||
UKB_ERR("Failed to get keyboard controls.");
|
||||
}
|
||||
|
||||
int num_groups = desc_ptr->ctrls->num_groups;
|
||||
if (xkbState.group >= num_groups) {
|
||||
UKB_ERR("Group index out of range.");
|
||||
}
|
||||
|
||||
char *name_ptr = XGetAtomName(x_display, desc_ptr->names->groups[xkb_state.group]);
|
||||
if (!name_ptr) {
|
||||
UKB_ERR("Failed to get group name.");
|
||||
}
|
||||
|
||||
if (strncmp(current_layout, name_ptr, sizeof(current_layout)) != 0) {
|
||||
strncpy(current_layout, name_ptr, sizeof(current_layout) - 1);
|
||||
}
|
||||
|
||||
XkbFreeKeyboard(desc_ptr, 0, True);
|
||||
XFree(name_ptr);
|
||||
|
||||
UKB_OK();
|
||||
}
|
||||
|
||||
static ukb_err_t xorg_wait_event() {
|
||||
Bool bret = XkbSelectEventDetails(x_display, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
|
||||
if (!bret) {
|
||||
UKB_ERR("XkbSelectEventDetails failed")
|
||||
}
|
||||
|
||||
XEvent event;
|
||||
int iret = XNextEvent(x_display, &event);
|
||||
if (!iret) {
|
||||
UKB_ERR("XNextEvent failed");
|
||||
}
|
||||
|
||||
UKB_OK();
|
||||
}
|
||||
|
||||
static ukb_err_t xorg_listen_loop(ukb_layout_cb_t cb) {
|
||||
while(1) {
|
||||
UKB_PROPAGATE(xorg_wait_event());
|
||||
UKB_PROPAGATE(update_current_layout());
|
||||
cb(current_layout);
|
||||
}
|
||||
UKB_OK();
|
||||
}
|
||||
|
||||
static int xorg_open_display() {
|
||||
int event_code;
|
||||
int error_return;
|
||||
int major = XkbMajorVersion;
|
||||
int minor = XkbMinorVersion;
|
||||
int reason_return;
|
||||
|
||||
x_display = XkbOpenDisplay(NULL, &event_code, &error_return, &major, &minor, &reason_return);
|
||||
return reason_return;
|
||||
}
|
||||
|
||||
/********************************* BACKEND ***********************************/
|
||||
|
||||
static bool xorg_can_use(void) {
|
||||
int reason_return = xorg_open_display();
|
||||
XCloseDisplay(x_display);
|
||||
return reason_return == XkbOD_Success;
|
||||
}
|
||||
|
||||
static ukb_err_t xorg_listen(ukb_layout_cb_t cb) {
|
||||
int reason_return = xorg_open_display();
|
||||
|
||||
switch (reason_return) {
|
||||
case XkbOD_Success:
|
||||
break;
|
||||
case XkbOD_BadLibraryVersion:
|
||||
UKB_ERR("Bad XKB library version.");
|
||||
case XkbOD_ConnectionRefused:
|
||||
UKB_ERR("Connection to X server refused.");
|
||||
case XkbOD_BadServerVersion:
|
||||
UKB_ERR("Bad X11 server version.");
|
||||
case XkbOD_NonXkbServer:
|
||||
UKB_ERR("XKB not present.");
|
||||
default:
|
||||
UKB_ERR("XKB refused to open the display.");
|
||||
}
|
||||
|
||||
ukb_err_t err = xorg_listen_loop(cb);
|
||||
XCloseDisplay(x_display);
|
||||
return err;
|
||||
}
|
||||
|
||||
const ukb_backend_t ukb_backend_xorg = {
|
||||
.name = "xorg",
|
||||
.can_use = xorg_can_use,
|
||||
.listen = xorg_listen,
|
||||
};
|
|
@ -12,7 +12,8 @@
|
|||
/********************************* BACKENDS **********************************/
|
||||
|
||||
#define UKB_BACKENDS(M) \
|
||||
M(ukb_backend_sway)
|
||||
M(ukb_backend_sway) \
|
||||
M(ukb_backend_xorg)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue