From dc83dc6725c7af7dc7345b6085ac8f281602946a Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Tue, 5 Mar 2024 10:24:45 -0700 Subject: Added some escape-hatch keybindings for Wetterhorn. Specifically a way to reload the plugin and switch vterms. This is important in case the plugin is borked and stops accepting keyboard, the user can switch to a vterm, fix the plugin and reload it to get things working again without running into data loss. --- Setup.hs | 2 +- harness/include/wl.h | 4 +++- harness/src/wl.c | 48 ++++++++++++++++++++++++++++++++++++++---------- src/Wetterhorn/Core/W.hs | 1 + 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Setup.hs b/Setup.hs index 50385ed..f3a2180 100644 --- a/Setup.hs +++ b/Setup.hs @@ -19,7 +19,7 @@ main = do let buildPath = fromJust (flagToMaybe $ configDistPref conf) callCommand $ - printf "cd wlroots && meson setup %s -Dexamples=false --reconfigure" (wlrootsDir buildPath) + printf "cd wlroots && meson setup %s -Dexamples=false -Dbackends=x11,drm,libinput --reconfigure" (wlrootsDir buildPath) callCommand $ printf "cmake -B %s -S harness" (harnessDir buildPath) diff --git a/harness/include/wl.h b/harness/include/wl.h index b8d4e14..903ba10 100644 --- a/harness/include/wl.h +++ b/harness/include/wl.h @@ -6,10 +6,11 @@ #include #include #include +#include #include #include -#include #include +#include #include #include #include @@ -68,6 +69,7 @@ struct tinywl_server { struct wl_list outputs; struct wl_listener new_output; + struct wlr_session *session; plugin_t plugin; }; diff --git a/harness/src/wl.c b/harness/src/wl.c index 0bd0410..f083a5e 100644 --- a/harness/src/wl.c +++ b/harness/src/wl.c @@ -105,15 +105,43 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data) int handled = false; uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->wlr_keyboard); uint32_t codepoint; - /* Pass the information along to the plugin for the plugin to handle. The - * plugin will return via 'handled' whether or not the key event was handled - * or not. */ - if (nsyms > 0) { - codepoint = - xkb_state_key_get_utf32(keyboard->wlr_keyboard->xkb_state, keycode); - plugin_call_update_state(server->plugin, plugin_handle_keybinding, - keyboard->wlr_keyboard, event, modifiers, syms[0], - codepoint, &handled); + int ec; + + if (nsyms > 0 && syms[0] >= XKB_KEY_XF86Switch_VT_1 && + syms[0] <= XKB_KEY_XF86Switch_VT_12) { + /* Escape-hatch to change sessions. These should always be available key + * bindings regardless of what the plugin dictates. This allows an escape + * hatch to edit the plugin in a different vterm and then use the escape + * hatch below to hot-restart the plugin if things get borked. */ + if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + wlr_session_change_vt(server->session, + syms[0] - XKB_KEY_XF86Switch_VT_1 + 1); + } + } + else if (modifiers == + (WLR_MODIFIER_SHIFT | WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT) && + nsyms > 0 && syms[0] == XKB_KEY_Escape) { + /* Escape-hatch to hot-reload the plugin in case the plugin got borked and + * stops accepting keybindings. Ctrl+Shift+Alt+Escape will always reload the + * plugin.*/ + if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + if ((ec = plugin_hot_reload_same_state(&server->plugin)) != 0) { + fprintf(stderr, "Failed to hot reload plugin"); + exit(1); + } + } + } + else { + /* Pass the information along to the plugin for the plugin to handle. The + * plugin will return via 'handled' whether or not the key event was handled + * or not. */ + if (nsyms > 0) { + codepoint = + xkb_state_key_get_utf32(keyboard->wlr_keyboard->xkb_state, keycode); + plugin_call_update_state(server->plugin, plugin_handle_keybinding, + keyboard->wlr_keyboard, event, modifiers, + syms[0], codepoint, &handled); + } } } @@ -806,7 +834,7 @@ int main(int argc, char *argv[]) * output hardware. The autocreate option will choose the most suitable * backend based on the current environment, such as opening an X11 window * if an X11 server is running. */ - server.backend = wlr_backend_autocreate(server.wl_display, NULL); + server.backend = wlr_backend_autocreate(server.wl_display, &server.session); if (server.backend == NULL) { wlr_log(WLR_ERROR, "failed to create wlr_backend"); return 1; diff --git a/src/Wetterhorn/Core/W.hs b/src/Wetterhorn/Core/W.hs index b809545..b2c6b51 100644 --- a/src/Wetterhorn/Core/W.hs +++ b/src/Wetterhorn/Core/W.hs @@ -224,6 +224,7 @@ shellExec = wio . ForeignInterface.doShellExec wio :: IO a -> W a wio = liftIO +-- | Type class to lift an arbitrary 'W' computation into another monad. class Wlike m where liftW :: W a -> m a -- cgit