Manage keybindings directly in guile!
This commit is contained in:
parent
bebd8165ba
commit
56c30d5e3e
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,8 +319,9 @@ 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
|
||||||
scm_from_int(event->root_x), scm_from_int(event->root_y)))) {
|
((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
|
// Ignore the click
|
||||||
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
|
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
|
|
10
src/guile.c
10
src/guile.c
|
@ -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 hook = scm_variable_ref(scm_c_lookup(name));
|
SCM var = scm_defined_p
|
||||||
if (scm_is_true(hook)) {
|
(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 scm_to_bool(scm_call_1(hook, params));
|
||||||
}
|
}
|
||||||
return true;
|
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) {
|
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,43 +1346,52 @@ 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:
|
||||||
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;
|
break;
|
||||||
|
|
||||||
case XCB_DESTROY_NOTIFY:
|
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;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_MOTION_NOTIFY:
|
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;
|
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:
|
||||||
handle_enter_notify((xcb_enter_notify_event_t *)event);
|
puts("handle_enter_notify");
|
||||||
|
handle_enter_notify((xcb_enter_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Client message are sent to the root window. The only interesting
|
/* 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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//DLOG("Unhandled event of type %d\n", type);
|
printf("Unhandled event of type %d\n", type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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); */
|
||||||
}
|
}
|
||||||
|
|
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"));
|
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);
|
||||||
|
|
Loading…
Reference in New Issue