mirror of
https://github.com/wizbright/waybox.git
synced 2025-10-29 05:40:20 -04:00
Allow multiple actions per keybinding
This commit is contained in:
parent
8403f759c4
commit
e9bf441ed0
3 changed files with 117 additions and 141 deletions
|
|
@ -21,6 +21,48 @@ static char *parse_xpath_expr(char *expr, xmlXPathContextPtr ctxt) {
|
|||
return (char *) ret;
|
||||
}
|
||||
|
||||
static void get_action(xmlNode *new_node, struct wb_key_binding *key_bind) {
|
||||
xmlAttr *attr;
|
||||
xmlNode *cur_node;
|
||||
for (cur_node = new_node; cur_node; cur_node = cur_node->next) {
|
||||
if (strcmp((char *) cur_node->name, "action") == 0) {
|
||||
attr = cur_node->properties;
|
||||
if (!attr) continue;
|
||||
while (strcmp((char *) attr->name, "name") != 0) {
|
||||
attr = attr->next;
|
||||
}
|
||||
char *action = (char *) attr->children->content;
|
||||
if (strcmp(action, "Execute") == 0)
|
||||
key_bind->action |= ACTION_EXECUTE;
|
||||
else if (strcmp(action, "NextWindow") == 0)
|
||||
key_bind->action |= ACTION_NEXT_WINDOW;
|
||||
else if (strcmp(action, "PreviousWindow") == 0)
|
||||
key_bind->action |= ACTION_PREVIOUS_WINDOW;
|
||||
else if (strcmp(action, "Close") == 0)
|
||||
key_bind->action |= ACTION_CLOSE;
|
||||
else if (strcmp(action, "ToggleMaximize") == 0)
|
||||
key_bind->action |= ACTION_TOGGLE_MAXIMIZE;
|
||||
else if (strcmp(action, "Iconify") == 0)
|
||||
key_bind->action |= ACTION_ICONIFY;
|
||||
else if (strcmp(action, "Shade") == 0)
|
||||
key_bind->action |= ACTION_SHADE;
|
||||
else if (strcmp(action, "Unshade") == 0)
|
||||
key_bind->action |= ACTION_UNSHADE;
|
||||
else if (strcmp(action, "Exit") == 0)
|
||||
key_bind->action |= ACTION_EXIT;
|
||||
else if (strcmp(action, "Reconfigure") == 0)
|
||||
key_bind->action |= ACTION_RECONFIGURE;
|
||||
}
|
||||
if (cur_node && cur_node->children)
|
||||
get_action(cur_node->children, key_bind);
|
||||
|
||||
if (strcmp((char *) cur_node->name, "execute") == 0) {
|
||||
key_bind->cmd = (char *) xmlStrdup(cur_node->children->content);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool parse_key_bindings(struct wb_config *config, xmlXPathContextPtr ctxt) {
|
||||
/* Get the key bindings */
|
||||
wl_list_init(&config->key_bindings);
|
||||
|
|
@ -42,9 +84,7 @@ static bool parse_key_bindings(struct wb_config *config, xmlXPathContextPtr ctxt
|
|||
/* First get the key combinations */
|
||||
xmlAttr *keycomb = object->nodesetval->nodeTab[i]->properties;
|
||||
while (strcmp((char *) keycomb->name, "key") != 0)
|
||||
{
|
||||
keycomb = keycomb->next;
|
||||
}
|
||||
|
||||
char *sym;
|
||||
uint32_t modifiers = 0;
|
||||
|
|
@ -54,8 +94,7 @@ static bool parse_key_bindings(struct wb_config *config, xmlXPathContextPtr ctxt
|
|||
struct wb_key_binding *key_bind = calloc(1, sizeof(struct wb_key_binding));
|
||||
key_bind->sym = 0;
|
||||
key_bind->modifiers = 0;
|
||||
while ((s = strtok(sym, "-")) != NULL)
|
||||
{
|
||||
while ((s = strtok(sym, "-")) != NULL) {
|
||||
if (strcmp(s, "A") == 0 || strcmp(s, "Alt") == 0)
|
||||
modifiers |= WLR_MODIFIER_ALT;
|
||||
else if (strcmp(s, "Caps") == 0)
|
||||
|
|
@ -78,50 +117,8 @@ static bool parse_key_bindings(struct wb_config *config, xmlXPathContextPtr ctxt
|
|||
}
|
||||
|
||||
/* Now get the actions */
|
||||
xmlNode *cur_node;
|
||||
xmlNode *new_node = object->nodesetval->nodeTab[i]->children;
|
||||
xmlAttr *attr;
|
||||
for (cur_node = new_node; cur_node; cur_node = cur_node->next)
|
||||
{
|
||||
if (strcmp((char *) cur_node->name, "action") == 0)
|
||||
{
|
||||
attr = cur_node->properties;
|
||||
while (strcmp((char *) attr->name, "name") != 0)
|
||||
{
|
||||
attr = attr->next;
|
||||
}
|
||||
char *action = (char *) attr->children->content;
|
||||
if (strcmp(action, "Execute") == 0)
|
||||
key_bind->action = ACTION_EXECUTE;
|
||||
else if (strcmp(action, "NextWindow") == 0)
|
||||
key_bind->action = ACTION_NEXT_WINDOW;
|
||||
else if (strcmp(action, "PreviousWindow") == 0)
|
||||
key_bind->action = ACTION_PREVIOUS_WINDOW;
|
||||
else if (strcmp(action, "Close") == 0)
|
||||
key_bind->action = ACTION_CLOSE;
|
||||
else if (strcmp(action, "ToggleMaximize") == 0)
|
||||
key_bind->action = ACTION_TOGGLE_MAXIMIZE;
|
||||
else if (strcmp(action, "Iconify") == 0)
|
||||
key_bind->action = ACTION_ICONIFY;
|
||||
else if (strcmp(action, "Shade") == 0)
|
||||
key_bind->action = ACTION_SHADE;
|
||||
else if (strcmp(action, "Unshade") == 0)
|
||||
key_bind->action = ACTION_UNSHADE;
|
||||
else if (strcmp(action, "Exit") == 0)
|
||||
key_bind->action = ACTION_EXIT;
|
||||
else if (strcmp(action, "Reconfigure") == 0)
|
||||
key_bind->action = ACTION_RECONFIGURE;
|
||||
if (key_bind->action != ACTION_EXECUTE)
|
||||
break;
|
||||
cur_node = cur_node->children;
|
||||
}
|
||||
if (strcmp((char *) cur_node->name, "execute") == 0)
|
||||
{
|
||||
key_bind->cmd = (char *) xmlStrdup(cur_node->children->content);
|
||||
if (key_bind->action)
|
||||
break;
|
||||
}
|
||||
}
|
||||
get_action(new_node, key_bind);
|
||||
|
||||
wl_list_insert(&config->key_bindings, &key_bind->link);
|
||||
}
|
||||
|
|
@ -168,8 +165,7 @@ bool init_config(struct wb_server *server) {
|
|||
struct wb_config *config = calloc(1, sizeof(struct wb_config));
|
||||
config->keyboard_layout.use_config = parse_xpath_expr("//ob:keyboard//ob:keyboardLayout", ctxt) != NULL;
|
||||
|
||||
if (config->keyboard_layout.use_config)
|
||||
{
|
||||
if (config->keyboard_layout.use_config) {
|
||||
config->keyboard_layout.layout = parse_xpath_expr("//ob:keyboard//ob:keyboardLayout//ob:layout", ctxt);
|
||||
config->keyboard_layout.model = parse_xpath_expr("//ob:keyboard//ob:keyboardLayout//ob:model", ctxt);
|
||||
config->keyboard_layout.options = parse_xpath_expr("//ob:keyboard//ob:keyboardLayout//ob:options", ctxt);
|
||||
|
|
|
|||
|
|
@ -4,17 +4,16 @@
|
|||
#include "waybox/server.h"
|
||||
|
||||
enum action_type {
|
||||
ACTION_FIRST,
|
||||
ACTION_CLOSE,
|
||||
ACTION_EXECUTE,
|
||||
ACTION_EXIT,
|
||||
ACTION_ICONIFY,
|
||||
ACTION_NEXT_WINDOW,
|
||||
ACTION_PREVIOUS_WINDOW,
|
||||
ACTION_RECONFIGURE,
|
||||
ACTION_SHADE,
|
||||
ACTION_TOGGLE_MAXIMIZE,
|
||||
ACTION_UNSHADE,
|
||||
ACTION_CLOSE = 1,
|
||||
ACTION_EXECUTE = 2,
|
||||
ACTION_EXIT = 4,
|
||||
ACTION_ICONIFY = 8,
|
||||
ACTION_NEXT_WINDOW = 16,
|
||||
ACTION_PREVIOUS_WINDOW = 32,
|
||||
ACTION_RECONFIGURE = 64,
|
||||
ACTION_SHADE = 128,
|
||||
ACTION_TOGGLE_MAXIMIZE = 256,
|
||||
ACTION_UNSHADE = 512,
|
||||
};
|
||||
|
||||
struct wb_config {
|
||||
|
|
|
|||
143
waybox/seat.c
143
waybox/seat.c
|
|
@ -51,8 +51,7 @@ static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32
|
|||
* client.
|
||||
*/
|
||||
|
||||
if (!server->config)
|
||||
{
|
||||
if (!server->config) {
|
||||
/* Some default key bindings, when the rc.xml file can't be
|
||||
* parsed. */
|
||||
if (modifiers & WLR_MODIFIER_ALT && sym == XKB_KEY_Tab)
|
||||
|
|
@ -69,88 +68,71 @@ static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32
|
|||
|
||||
struct wb_key_binding *key_binding;
|
||||
wl_list_for_each(key_binding, &server->config->key_bindings, link) {
|
||||
if (sym == key_binding->sym && modifiers == key_binding->modifiers)
|
||||
{
|
||||
switch (key_binding->action)
|
||||
{
|
||||
case ACTION_NEXT_WINDOW:
|
||||
cycle_views(server);
|
||||
break;
|
||||
case ACTION_PREVIOUS_WINDOW:
|
||||
cycle_views_reverse(server);
|
||||
break;
|
||||
case ACTION_CLOSE:
|
||||
{
|
||||
struct wb_view *current_view = wl_container_of(
|
||||
server->views.next, current_view, link);
|
||||
if (wlr_surface_is_xdg_surface(current_view->xdg_toplevel->base->surface))
|
||||
if (sym == key_binding->sym && modifiers == key_binding->modifiers) {
|
||||
if (key_binding->action & ACTION_NEXT_WINDOW)
|
||||
cycle_views(server);
|
||||
if (key_binding->action & ACTION_PREVIOUS_WINDOW)
|
||||
cycle_views_reverse(server);
|
||||
if (key_binding->action & ACTION_CLOSE) {
|
||||
struct wb_view *current_view = wl_container_of(
|
||||
server->views.next, current_view, link);
|
||||
if (wlr_surface_is_xdg_surface(current_view->xdg_toplevel->base->surface))
|
||||
#if WLR_CHECK_VERSION(0, 16, 0)
|
||||
wlr_xdg_toplevel_send_close(current_view->xdg_toplevel);
|
||||
wlr_xdg_toplevel_send_close(current_view->xdg_toplevel);
|
||||
#else
|
||||
wlr_xdg_toplevel_send_close(current_view->xdg_surface);
|
||||
wlr_xdg_toplevel_send_close(current_view->xdg_surface);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ACTION_EXECUTE:
|
||||
if (fork() == 0) {
|
||||
execl("/bin/sh", "/bin/sh", "-c", key_binding->cmd, (char *) NULL);
|
||||
}
|
||||
break;
|
||||
case ACTION_TOGGLE_MAXIMIZE:
|
||||
{
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface))
|
||||
wl_signal_emit(&view->xdg_toplevel->events.request_maximize, view->xdg_toplevel->base);
|
||||
break;
|
||||
}
|
||||
if (key_binding->action & ACTION_EXECUTE) {
|
||||
if (fork() == 0) {
|
||||
execl("/bin/sh", "/bin/sh", "-c", key_binding->cmd, (char *) NULL);
|
||||
}
|
||||
case ACTION_ICONIFY:
|
||||
{
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface))
|
||||
{
|
||||
view->xdg_toplevel->requested.minimized = true;
|
||||
wl_signal_emit(&view->xdg_toplevel->events.request_minimize, view->xdg_toplevel->base);
|
||||
struct wb_view *previous_view = wl_container_of(server->views.prev, previous_view, link);
|
||||
focus_view(previous_view, previous_view->xdg_toplevel->base->surface);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_SHADE:
|
||||
{
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface))
|
||||
{
|
||||
view->previous_position = view->current_position;
|
||||
wlr_xdg_toplevel_set_size(view->xdg_toplevel->base,
|
||||
view->current_position.width, view->decoration_height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_UNSHADE:
|
||||
{
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface))
|
||||
{
|
||||
#if WLR_CHECK_VERSION(0, 16, 0)
|
||||
wlr_xdg_toplevel_set_size(view->xdg_toplevel,
|
||||
view->previous_position.width, view->previous_position.height);
|
||||
#else
|
||||
wlr_xdg_toplevel_set_size(view->xdg_surface,
|
||||
view->previous_position.width, view->previous_position.height);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_RECONFIGURE:
|
||||
deinit_config(server->config);
|
||||
init_config(server);
|
||||
break;
|
||||
case ACTION_EXIT:
|
||||
wl_display_terminate(server->wl_display);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (key_binding->action & ACTION_TOGGLE_MAXIMIZE) {
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface))
|
||||
wl_signal_emit(&view->xdg_toplevel->events.request_maximize, view->xdg_toplevel->base);
|
||||
}
|
||||
if (key_binding->action & ACTION_ICONIFY) {
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface)) {
|
||||
view->xdg_toplevel->requested.minimized = true;
|
||||
wl_signal_emit(&view->xdg_toplevel->events.request_minimize, view->xdg_toplevel->base);
|
||||
struct wb_view *previous_view = wl_container_of(server->views.prev, previous_view, link);
|
||||
focus_view(previous_view, previous_view->xdg_toplevel->base->surface);
|
||||
}
|
||||
}
|
||||
if (key_binding->action & ACTION_SHADE) {
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface)) {
|
||||
view->previous_position = view->current_position;
|
||||
#if WLR_CHECK_VERSION(0, 16, 0)
|
||||
wlr_xdg_toplevel_set_size(view->xdg_toplevel,
|
||||
view->current_position.width, view->decoration_height);
|
||||
#else
|
||||
wlr_xdg_toplevel_set_size(view->xdg_surface,
|
||||
view->current_position.width, view->decoration_height);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (key_binding->action & ACTION_UNSHADE) {
|
||||
struct wb_view *view = wl_container_of(server->views.next, view, link);
|
||||
if (wlr_surface_is_xdg_surface(view->xdg_toplevel->base->surface)) {
|
||||
#if WLR_CHECK_VERSION(0, 16, 0)
|
||||
wlr_xdg_toplevel_set_size(view->xdg_toplevel,
|
||||
view->previous_position.width, view->previous_position.height);
|
||||
#else
|
||||
wlr_xdg_toplevel_set_size(view->xdg_surface,
|
||||
view->previous_position.width, view->previous_position.height);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (key_binding->action & ACTION_RECONFIGURE) {
|
||||
deinit_config(server->config);
|
||||
init_config(server);
|
||||
}
|
||||
if (key_binding->action & ACTION_EXIT)
|
||||
wl_display_terminate(server->wl_display);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -216,8 +198,7 @@ static void handle_new_keyboard(struct wb_server *server,
|
|||
|
||||
/* We need to prepare an XKB keymap and assign it to the keyboard. */
|
||||
struct xkb_rule_names *rules = malloc(sizeof(struct xkb_rule_names));
|
||||
if (server->config && server->config->keyboard_layout.use_config)
|
||||
{
|
||||
if (server->config && server->config->keyboard_layout.use_config) {
|
||||
if (server->config->keyboard_layout.layout)
|
||||
rules->layout = server->config->keyboard_layout.layout;
|
||||
if (server->config->keyboard_layout.model)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue