Manage keybindings directly in guile!

This commit is contained in:
nixo 2020-05-11 17:44:53 +02:00
parent bebd8165ba
commit 56c30d5e3e
7 changed files with 74 additions and 43 deletions

View File

@ -1,2 +1,3 @@
SCM guile_split(SCM direction); SCM guile_split(SCM direction);
bool guile_hook(char * name, SCM params); bool guile_hook(char * name, SCM params);
SCM guile_register_keyboard_key(SCM modifier, SCM keycode);

View File

@ -7,6 +7,7 @@
* bindings.c: Functions for configuring, finding and, running bindings. * bindings.c: Functions for configuring, finding and, running bindings.
*/ */
#include "all.h" #include "all.h"
#include "guile.h"
#include <math.h> #include <math.h>
@ -127,10 +128,12 @@ static bool binding_in_current_group(const Binding *bind) {
} }
static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint32_t keycode) { static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint32_t keycode) {
printf("OK\n");
/* Grab the key in all combinations */ /* Grab the key in all combinations */
#define GRAB_KEY(modifier) \ #define GRAB_KEY(modifier) \
do { \ do { \
xcb_grab_key(conn, 0, root, modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \ xcb_grab_key(conn, 0, root, modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \
printf("Register key: %d, modifier: %d\n", keycode, modifier); \
} while (0) } while (0)
const int mods = (bind->event_state_mask & 0xFFFF); const int mods = (bind->event_state_mask & 0xFFFF);
DLOG("Binding %p Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n", DLOG("Binding %p Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n",
@ -144,6 +147,26 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint
GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK); GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
} }
SCM guile_register_keyboard_key(SCM keycode, SCM modifier) {
// keycode
printf("Register key: %d, modifier: %d\n", scm_to_int(keycode), scm_to_int(modifier));
xcb_grab_key(conn, 0, root,
scm_to_int(modifier),
scm_to_int(keycode),
XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC);
/* const int mods = (bind->event_state_mask & 0xFFFF); */
/* DLOG("Binding %p Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n", */
/* bind, keycode, bind->event_state_mask, mods); */
/* GRAB_KEY(mods); */
/* /\* Also bind the key with active NumLock *\/ */
/* GRAB_KEY(mods | xcb_numlock_mask); */
/* /\* Also bind the key with active CapsLock *\/ */
/* GRAB_KEY(mods | XCB_MOD_MASK_LOCK); */
/* /\* Also bind the key with active NumLock+CapsLock *\/ */
/* GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK); */
return SCM_BOOL_T;
}
/* /*
* Grab the bound keys (tell X to send us keypress events for those keycodes) * Grab the bound keys (tell X to send us keypress events for those keycodes)
* *
@ -167,7 +190,7 @@ void grab_all_keys(xcb_connection_t *conn) {
TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) { TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
const int keycode = binding_keycode->keycode; const int keycode = binding_keycode->keycode;
const int mods = (binding_keycode->modifiers & 0xFFFF); const int mods = (binding_keycode->modifiers & 0xFFFF);
DLOG("Binding %p Grabbing keycode %d with mods %d\n", bind, keycode, mods); printf("Binding %p Grabbing keycode %d with mods %d\n", bind, keycode, mods);
xcb_grab_key(conn, 0, root, mods, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); xcb_grab_key(conn, 0, root, mods, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC);
} }
} }

View File

@ -319,7 +319,8 @@ void handle_button_press(xcb_button_press_event_t *event) {
// Click hook // Click hook
if (!guile_hook if (!guile_hook
("click-hook", scm_list_3 ("click-hook", scm_list_3
(scm_from_utf8_string(i3string_as_utf8(con->window->name)), (scm_from_utf8_string
((con != NULL && con->window != NULL && con->window->name != NULL) ? i3string_as_utf8(con->window->name) : ""),
scm_from_int(event->root_x), scm_from_int(event->root_y)))) { scm_from_int(event->root_x), scm_from_int(event->root_y)))) {
// Ignore the click // Ignore the click
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time); xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);

View File

@ -4,8 +4,14 @@
#include "guile.h" #include "guile.h"
bool guile_hook(char * name, SCM params) { bool guile_hook(char * name, SCM params) {
SCM var = scm_defined_p
(scm_string_to_symbol
(scm_from_utf8_string(name)), SCM_UNDEFINED);
// Bound, call it
if (scm_from_bool(var)) {
SCM hook = scm_variable_ref(scm_c_lookup(name)); SCM hook = scm_variable_ref(scm_c_lookup(name));
if (scm_is_true(hook)) { /* if (scm_is_true(hook)) { */
/* } */
return scm_to_bool(scm_call_1(hook, params)); return scm_to_bool(scm_call_1(hook, params));
} }
return true; return true;

View File

@ -1276,6 +1276,8 @@ static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom)
* *
*/ */
void handle_event(int type, xcb_generic_event_t *event) { void handle_event(int type, xcb_generic_event_t *event) {
puts("handle_event");
if (type != XCB_MOTION_NOTIFY) if (type != XCB_MOTION_NOTIFY)
DLOG("event type %d, xkb_base %d\n", type, xkb_base); DLOG("event type %d, xkb_base %d\n", type, xkb_base);
@ -1286,11 +1288,11 @@ void handle_event(int type, xcb_generic_event_t *event) {
} }
if (xkb_base > -1 && type == xkb_base) { if (xkb_base > -1 && type == xkb_base) {
DLOG("xkb event, need to handle it.\n"); puts("xkb event, need to handle it.");
xcb_xkb_state_notify_event_t *state = (xcb_xkb_state_notify_event_t *)event; xcb_xkb_state_notify_event_t *state = (xcb_xkb_state_notify_event_t *)event;
if (state->xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) { if (state->xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) {
DLOG("xkb new keyboard notify, sequence %d, time %d\n", state->sequence, state->time); printf("xkb new keyboard notify, sequence %d, time %d\n", state->sequence, state->time);
xcb_key_symbols_free(keysyms); xcb_key_symbols_free(keysyms);
keysyms = xcb_key_symbols_alloc(conn); keysyms = xcb_key_symbols_alloc(conn);
if (((xcb_xkb_new_keyboard_notify_event_t *)event)->changed & XCB_XKB_NKN_DETAIL_KEYCODES) if (((xcb_xkb_new_keyboard_notify_event_t *)event)->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
@ -1300,9 +1302,9 @@ void handle_event(int type, xcb_generic_event_t *event) {
grab_all_keys(conn); grab_all_keys(conn);
} else if (state->xkbType == XCB_XKB_MAP_NOTIFY) { } else if (state->xkbType == XCB_XKB_MAP_NOTIFY) {
if (event_is_ignored(event->sequence, type)) { if (event_is_ignored(event->sequence, type)) {
DLOG("Ignoring map notify event for sequence %d.\n", state->sequence); printf("Ignoring map notify event for sequence %d.\n", state->sequence);
} else { } else {
DLOG("xkb map notify, sequence %d, time %d\n", state->sequence, state->time); printf("xkb map notify, sequence %d, time %d\n", state->sequence, state->time);
add_ignore_event(event->sequence, type); add_ignore_event(event->sequence, type);
xcb_key_symbols_free(keysyms); xcb_key_symbols_free(keysyms);
keysyms = xcb_key_symbols_alloc(conn); keysyms = xcb_key_symbols_alloc(conn);
@ -1312,7 +1314,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
(void)load_keymap(); (void)load_keymap();
} }
} else if (state->xkbType == XCB_XKB_STATE_NOTIFY) { } else if (state->xkbType == XCB_XKB_STATE_NOTIFY) {
DLOG("xkb state group = %d\n", state->group); printf("xkb state group = %d, current = %d\n", state->group, xkb_current_group);
if (xkb_current_group == state->group) if (xkb_current_group == state->group)
return; return;
xkb_current_group = state->group; xkb_current_group = state->group;
@ -1344,30 +1346,37 @@ void handle_event(int type, xcb_generic_event_t *event) {
return; return;
} }
puts("switch");
switch (type) { switch (type) {
case XCB_KEY_PRESS: case XCB_KEY_PRESS:
case XCB_KEY_RELEASE: case XCB_KEY_RELEASE:
puts("handle_key_press");
handle_key_press((xcb_key_press_event_t *)event); handle_key_press((xcb_key_press_event_t *)event);
break; break;
case XCB_BUTTON_PRESS: case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE: case XCB_BUTTON_RELEASE:
puts("handle_button_press");
handle_button_press((xcb_button_press_event_t *)event); handle_button_press((xcb_button_press_event_t *)event);
break; break;
case XCB_MAP_REQUEST: case XCB_MAP_REQUEST:
puts("handle_map_request");
handle_map_request((xcb_map_request_event_t *)event); handle_map_request((xcb_map_request_event_t *)event);
break; break;
case XCB_UNMAP_NOTIFY: case XCB_UNMAP_NOTIFY:
puts("handle_unmap_notify_event");
handle_unmap_notify_event((xcb_unmap_notify_event_t *)event); handle_unmap_notify_event((xcb_unmap_notify_event_t *)event);
break; break;
case XCB_DESTROY_NOTIFY: case XCB_DESTROY_NOTIFY:
puts("handle_destroy_notify_event");
handle_destroy_notify_event((xcb_destroy_notify_event_t *)event); handle_destroy_notify_event((xcb_destroy_notify_event_t *)event);
break; break;
case XCB_EXPOSE: case XCB_EXPOSE:
puts("handle_expose_event");
if (((xcb_expose_event_t *)event)->count == 0) { if (((xcb_expose_event_t *)event)->count == 0) {
handle_expose_event((xcb_expose_event_t *)event); handle_expose_event((xcb_expose_event_t *)event);
} }
@ -1375,11 +1384,13 @@ void handle_event(int type, xcb_generic_event_t *event) {
break; break;
case XCB_MOTION_NOTIFY: case XCB_MOTION_NOTIFY:
puts("handle_motion_notify");
handle_motion_notify((xcb_motion_notify_event_t *)event); handle_motion_notify((xcb_motion_notify_event_t *)event);
break; break;
/* Enter window = user moved their mouse over the window */ /* Enter window = user moved their mouse over the window */
case XCB_ENTER_NOTIFY: case XCB_ENTER_NOTIFY:
puts("handle_enter_notify");
handle_enter_notify((xcb_enter_notify_event_t *)event); handle_enter_notify((xcb_enter_notify_event_t *)event);
break; break;
@ -1416,7 +1427,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
break; break;
default: default:
//DLOG("Unhandled event of type %d\n", type); printf("Unhandled event of type %d\n", type);
break; break;
} }
} }

View File

@ -8,6 +8,7 @@
* *
*/ */
#include "all.h" #include "all.h"
#include "guile.h"
/* /*
* There was a KeyPress or KeyRelease (both events have the same fields). We * There was a KeyPress or KeyRelease (both events have the same fields). We
@ -20,14 +21,20 @@ void handle_key_press(xcb_key_press_event_t *event) {
last_timestamp = event->time; last_timestamp = event->time;
DLOG("%s %d, state raw = 0x%x\n", (key_release ? "KeyRelease" : "KeyPress"), event->detail, event->state); printf("%s %d, state raw = 0x%x\n", (key_release ? "KeyRelease" : "KeyPress"), event->detail, event->state);
Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); // Let guile resolve the binding for us
guile_hook("key-press-hook",
scm_list_3(scm_from_int(event->response_type),
scm_from_int(event->detail),
scm_from_int(event->state)));
/* if we couldn't find a binding, we are done */ /* Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); */
if (bind == NULL)
return;
CommandResult *result = run_binding(bind, NULL); /* /\* if we couldn't find a binding, we are done *\/ */
command_result_free(result); /* if (bind == NULL) */
/* return; */
/* CommandResult *result = run_binding(bind, NULL); */
/* command_result_free(result); */
} }

View File

@ -265,23 +265,6 @@ void set_defaults(void){
scm_c_define("font", scm_from_locale_string("fixed")); scm_c_define("font", scm_from_locale_string("fixed"));
} }
void define_objects(void) { }
SCM guile_binding(SCM g_bindtype, SCM g_modifiers, SCM g_key, SCM g_release,
SCM g_border, SCM g_whole_window, SCM g_exclude_titlebar,
SCM g_command) {
const char * bindtype = scm_to_locale_string (g_bindtype);
const char * modifiers = scm_to_locale_string (g_modifiers);
const char * key = scm_to_locale_string (g_key);
const char * release = scm_to_locale_string (g_release);
const char * border = scm_to_locale_string (g_border);
const char * whole_window = scm_to_locale_string (g_whole_window);
const char * exclude_titlebar = scm_to_locale_string (g_exclude_titlebar);
// procedure
configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, g_command, DEFAULT_BINDING_MODE, false);
return SCM_BOOL_T;
}
SCM guile_change_workspace(SCM g_which) { SCM guile_change_workspace(SCM g_which) {
const char * which = scm_to_locale_string(g_which); const char * which = scm_to_locale_string(g_which);
@ -330,8 +313,7 @@ SCM guile_refresh() {
static void* static void*
register_functions (void* data) { register_functions (void* data) {
set_defaults(); set_defaults();
define_objects(); scm_c_define_gsubr ("bind-key", 2, 0, 0, &guile_register_keyboard_key);
scm_c_define_gsubr ("set-binding", 8, 0, 0, &guile_binding);
scm_c_define_gsubr ("change-workspace", 1, 0, 0, &guile_change_workspace); scm_c_define_gsubr ("change-workspace", 1, 0, 0, &guile_change_workspace);
scm_c_define_gsubr ("refresh", 0, 0, 0, &guile_refresh); scm_c_define_gsubr ("refresh", 0, 0, 0, &guile_refresh);
scm_c_define_gsubr ("kill", 0, 0, 0, &guile_kill); scm_c_define_gsubr ("kill", 0, 0, 0, &guile_kill);