Manage keybindings directly in guile!
This commit is contained in:
parent
bebd8165ba
commit
56c30d5e3e
|
@ -1,2 +1,3 @@
|
|||
SCM guile_split(SCM direction);
|
||||
bool guile_hook(char * name, SCM params);
|
||||
SCM guile_register_keyboard_key(SCM modifier, SCM keycode);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* bindings.c: Functions for configuring, finding and, running bindings.
|
||||
*/
|
||||
#include "all.h"
|
||||
#include "guile.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) {
|
||||
printf("OK\n");
|
||||
/* Grab the key in all combinations */
|
||||
#define GRAB_KEY(modifier) \
|
||||
do { \
|
||||
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)
|
||||
const int mods = (bind->event_state_mask & 0xFFFF);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
*
|
||||
|
@ -167,7 +190,7 @@ void grab_all_keys(xcb_connection_t *conn) {
|
|||
TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
|
||||
const int keycode = binding_keycode->keycode;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -319,8 +319,9 @@ void handle_button_press(xcb_button_press_event_t *event) {
|
|||
// Click hook
|
||||
if (!guile_hook
|
||||
("click-hook", scm_list_3
|
||||
(scm_from_utf8_string(i3string_as_utf8(con->window->name)),
|
||||
scm_from_int(event->root_x), scm_from_int(event->root_y)))) {
|
||||
(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)))) {
|
||||
// Ignore the click
|
||||
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
|
||||
xcb_flush(conn);
|
||||
|
|
10
src/guile.c
10
src/guile.c
|
@ -4,8 +4,14 @@
|
|||
#include "guile.h"
|
||||
|
||||
bool guile_hook(char * name, SCM params) {
|
||||
SCM hook = scm_variable_ref(scm_c_lookup(name));
|
||||
if (scm_is_true(hook)) {
|
||||
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));
|
||||
/* if (scm_is_true(hook)) { */
|
||||
/* } */
|
||||
return scm_to_bool(scm_call_1(hook, params));
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -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) {
|
||||
puts("handle_event");
|
||||
|
||||
if (type != XCB_MOTION_NOTIFY)
|
||||
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) {
|
||||
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;
|
||||
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);
|
||||
keysyms = xcb_key_symbols_alloc(conn);
|
||||
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);
|
||||
} else if (state->xkbType == XCB_XKB_MAP_NOTIFY) {
|
||||
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 {
|
||||
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);
|
||||
xcb_key_symbols_free(keysyms);
|
||||
keysyms = xcb_key_symbols_alloc(conn);
|
||||
|
@ -1312,7 +1314,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
|
|||
(void)load_keymap();
|
||||
}
|
||||
} 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)
|
||||
return;
|
||||
xkb_current_group = state->group;
|
||||
|
@ -1344,43 +1346,52 @@ void handle_event(int type, xcb_generic_event_t *event) {
|
|||
return;
|
||||
}
|
||||
|
||||
puts("switch");
|
||||
switch (type) {
|
||||
case XCB_KEY_PRESS:
|
||||
case XCB_KEY_RELEASE:
|
||||
puts("handle_key_press");
|
||||
handle_key_press((xcb_key_press_event_t *)event);
|
||||
break;
|
||||
|
||||
case XCB_BUTTON_PRESS:
|
||||
case XCB_BUTTON_RELEASE:
|
||||
puts("handle_button_press");
|
||||
handle_button_press((xcb_button_press_event_t *)event);
|
||||
break;
|
||||
|
||||
case XCB_MAP_REQUEST:
|
||||
puts("handle_map_request");
|
||||
handle_map_request((xcb_map_request_event_t *)event);
|
||||
break;
|
||||
|
||||
case XCB_UNMAP_NOTIFY:
|
||||
handle_unmap_notify_event((xcb_unmap_notify_event_t *)event);
|
||||
puts("handle_unmap_notify_event");
|
||||
handle_unmap_notify_event((xcb_unmap_notify_event_t *)event);
|
||||
break;
|
||||
|
||||
case XCB_DESTROY_NOTIFY:
|
||||
handle_destroy_notify_event((xcb_destroy_notify_event_t *)event);
|
||||
puts("handle_destroy_notify_event");
|
||||
handle_destroy_notify_event((xcb_destroy_notify_event_t *)event);
|
||||
break;
|
||||
|
||||
case XCB_EXPOSE:
|
||||
puts("handle_expose_event");
|
||||
if (((xcb_expose_event_t *)event)->count == 0) {
|
||||
handle_expose_event((xcb_expose_event_t *)event);
|
||||
handle_expose_event((xcb_expose_event_t *)event);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case XCB_MOTION_NOTIFY:
|
||||
handle_motion_notify((xcb_motion_notify_event_t *)event);
|
||||
puts("handle_motion_notify");
|
||||
handle_motion_notify((xcb_motion_notify_event_t *)event);
|
||||
break;
|
||||
|
||||
/* Enter window = user moved their mouse over the window */
|
||||
case XCB_ENTER_NOTIFY:
|
||||
handle_enter_notify((xcb_enter_notify_event_t *)event);
|
||||
puts("handle_enter_notify");
|
||||
handle_enter_notify((xcb_enter_notify_event_t *)event);
|
||||
break;
|
||||
|
||||
/* Client message are sent to the root window. The only interesting
|
||||
|
@ -1416,7 +1427,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
|
|||
break;
|
||||
|
||||
default:
|
||||
//DLOG("Unhandled event of type %d\n", type);
|
||||
printf("Unhandled event of type %d\n", type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*
|
||||
*/
|
||||
#include "all.h"
|
||||
#include "guile.h"
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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)));
|
||||
|
||||
/* Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); */
|
||||
|
||||
/* /\* if we couldn't find a binding, we are done *\/ */
|
||||
/* if (bind == NULL) */
|
||||
/* return; */
|
||||
|
||||
/* if we couldn't find a binding, we are done */
|
||||
if (bind == NULL)
|
||||
return;
|
||||
|
||||
CommandResult *result = run_binding(bind, NULL);
|
||||
command_result_free(result);
|
||||
/* CommandResult *result = run_binding(bind, NULL); */
|
||||
/* command_result_free(result); */
|
||||
}
|
||||
|
|
20
src/main.c
20
src/main.c
|
@ -265,23 +265,6 @@ void set_defaults(void){
|
|||
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) {
|
||||
const char * which = scm_to_locale_string(g_which);
|
||||
|
||||
|
@ -330,8 +313,7 @@ SCM guile_refresh() {
|
|||
static void*
|
||||
register_functions (void* data) {
|
||||
set_defaults();
|
||||
define_objects();
|
||||
scm_c_define_gsubr ("set-binding", 8, 0, 0, &guile_binding);
|
||||
scm_c_define_gsubr ("bind-key", 2, 0, 0, &guile_register_keyboard_key);
|
||||
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 ("kill", 0, 0, 0, &guile_kill);
|
||||
|
|
Loading…
Reference in New Issue