]> git.mdlowis.com Git - proto/labwc.git/commitdiff
action: allow client-menu to open at mouse cursor
authorAndrew J. Hesford <ajh@sideband.org>
Sun, 10 Mar 2024 18:28:41 +0000 (14:28 -0400)
committerAndrew J. Hesford <ajh@sideband.org>
Wed, 13 Mar 2024 14:51:50 +0000 (10:51 -0400)
docs/labwc-actions.5.scd
include/config/default-bindings.h [new file with mode: 0644]
src/action.c
src/config/rcxml.c

index 9236567e96a56a92ff1ee541c98195f85c9936b4..86186e7f07ce4cd7639c62067f4850c23369af62 100644 (file)
@@ -105,8 +105,17 @@ Actions are used in menus and keyboard/mouse bindings.
 *<action name="Reconfigure" />*
        Re-load configuration and theme files.
 
-*<action name="ShowMenu" menu="value" />*
-       Show menu. Valid menu names are "root-menu" and "client-menu".
+*<action name="ShowMenu" menu="value" atCursor="yes" />*
+       Show a menu.
+
+       *menu* The name of the menu to show. The menus "root-menu" and
+       "client-menu" are guaranteed to exist, but others may be defined
+       explicitly. See labwc-menu(5) for more information.
+
+       *atCursor* [yes|no] When opening a menu, open the menu at the location
+       of the mouse cursor. When set to no, the menu will appear at the
+       upper-left corner of the window associated with the action. Default is
+       yes.
 
 *<action name="ToggleDecorations" />*
        Toggle decorations of focused window.
diff --git a/include/config/default-bindings.h b/include/config/default-bindings.h
new file mode 100644 (file)
index 0000000..553fb32
--- /dev/null
@@ -0,0 +1,447 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LABWC_DEFAULT_BINDINGS_H
+#define LABWC_DEFAULT_BINDINGS_H
+
+static struct key_combos {
+       const char *binding, *action;
+       struct {
+               const char *name, *value;
+       } attributes[2];
+} key_combos[] = { {
+               .binding = "A-Tab",
+               .action = "NextWindow",
+       }, {
+               .binding = "W-Return",
+               .action = "Execute",
+               .attributes[0] = {
+                       .name = "command",
+                       .value = "alacritty",
+               },
+       }, {
+               .binding = "A-F3",
+               .action = "Execute",
+               .attributes[0] = {
+                       .name = "command",
+                       .value = "bemenu-run",
+               },
+       }, {
+               .binding = "A-F4",
+               .action = "Close",
+       }, {
+               .binding = "W-a",
+               .action = "ToggleMaximize",
+       }, {
+               .binding = "A-Left",
+               .action = "MoveToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "left",
+               },
+       }, {
+               .binding = "A-Right",
+               .action = "MoveToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "right",
+               },
+       }, {
+               .binding = "A-Up",
+               .action = "MoveToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "up",
+               },
+       }, {
+               .binding = "A-Down",
+               .action = "MoveToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "down",
+               },
+       }, {
+               .binding = "W-Left",
+               .action = "SnapToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "left",
+               },
+       }, {
+               .binding = "W-Right",
+               .action = "SnapToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "right",
+               },
+       }, {
+               .binding = "W-Up",
+               .action = "SnapToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "up",
+               },
+       }, {
+               .binding = "W-Down",
+               .action = "SnapToEdge",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "down",
+               },
+       }, {
+               .binding = "A-Space",
+               .action = "ShowMenu",
+               .attributes[0] = {
+                       .name = "menu",
+                       .value = "client-menu"
+               },
+               .attributes[1] = {
+                       .name = "atCursor",
+                       .value = "no",
+               },
+       }, {
+               .binding = "XF86_AudioLowerVolume",
+               .action = "Execute",
+               .attributes[0] = {
+                       .name = "command",
+                       .value = "amixer sset Master 5%-",
+               },
+       }, {
+               .binding = "XF86_AudioRaiseVolume",
+               .action = "Execute",
+               .attributes[0] = {
+                       .name = "command",
+                       .value = "amixer sset Master 5%+",
+               },
+       }, {
+               .binding = "XF86_AudioMute",
+               .action = "Execute",
+               .attributes[0] = {
+                       .name = "command",
+                       .value = "amixer sset Master toggle",
+               },
+       }, {
+               .binding = "XF86_MonBrightnessUp",
+               .action = "Execute",
+               .attributes[0] = {
+                       .name = "command",
+                       .value = "brightnessctl set +10%",
+               },
+       }, {
+               .binding = "XF86_MonBrightnessDown",
+               .action = "Execute",
+               .attributes[0] = {
+                       .name = "command",
+                       .value = "brightnessctl set 10%-",
+               },
+       }, {
+               .binding = NULL,
+       },
+};
+
+/*
+ * `struct mouse_combo` variable description and examples:
+ *
+ * | Variable   | Description                | Examples
+ * |------------|----------------------------|----------------------------
+ * | context    | context name               | Maximize, Root
+ * | button     | mousebind button/direction | Left, Up
+ * | event      | mousebind action           | Click, Scroll
+ * | action     | action name                | ToggleMaximize, GoToDesktop
+ * |============|============================|============================
+ * | Attributes |                            |
+ * |------------|----------------------------|----------------------------
+ * | name       | action attribute name      | to
+ * | value      | action attribute value     | left
+ *
+ * <mouse>
+ *   <context name="Maximize">
+ *     <mousebind button="Left" action="Click">
+ *       <action name="Focus"/>
+ *       <action name="Raise"/>
+ *       <action name="ToggleMaximize"/>
+ *     </mousebind>
+ *   </context>
+ *   <context name="Root">
+ *     <mousebind direction="Up" action="Scroll">
+ *       <action name="GoToDesktop" to="left" wrap="yes"/>
+ *     </mousebind>
+ *   </context>
+ * </mouse>
+ */
+static struct mouse_combos {
+       const char *context, *button, *event, *action;
+       struct {
+               const char *name, *value;
+       } attributes[2];
+} mouse_combos[] = { {
+               .context = "Left",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "Top",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "Bottom",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "Right",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "TLCorner",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "TRCorner",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "BRCorner",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "BLCorner",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "Frame",
+               .button = "A-Left",
+               .event = "Press",
+               .action = "Focus",
+       }, {
+               .context = "Frame",
+               .button = "A-Left",
+               .event = "Press",
+               .action = "Raise",
+       }, {
+               .context = "Frame",
+               .button = "A-Left",
+               .event = "Drag",
+               .action = "Move",
+       }, {
+               .context = "Frame",
+               .button = "A-Right",
+               .event = "Press",
+               .action = "Focus",
+       }, {
+               .context = "Frame",
+               .button = "A-Right",
+               .event = "Press",
+               .action = "Raise",
+       }, {
+               .context = "Frame",
+               .button = "A-Right",
+               .event = "Drag",
+               .action = "Resize",
+       }, {
+               .context = "Titlebar",
+               .button = "Left",
+               .event = "Press",
+               .action = "Focus",
+       }, {
+               .context = "Titlebar",
+               .button = "Left",
+               .event = "Press",
+               .action = "Raise",
+       }, {
+               .context = "Titlebar",
+               .button = "Up",
+               .event = "Scroll",
+               .action = "Unfocus",
+       }, {
+               .context = "Titlebar",
+               .button = "Up",
+               .event = "Scroll",
+               .action = "Shade",
+       }, {
+               .context = "Titlebar",
+               .button = "Down",
+               .event = "Scroll",
+               .action = "Unshade",
+       }, {
+               .context = "Titlebar",
+               .button = "Down",
+               .event = "Scroll",
+               .action = "Focus",
+       }, {
+               .context = "Title",
+               .button = "Left",
+               .event = "Drag",
+               .action = "Move",
+       }, {
+               .context = "Title",
+               .button = "Left",
+               .event = "DoubleClick",
+               .action = "ToggleMaximize",
+       }, {
+               .context = "TitleBar",
+               .button = "Right",
+               .event = "Click",
+               .action = "Focus",
+       }, {
+               .context = "TitleBar",
+               .button = "Right",
+               .event = "Click",
+               .action = "Raise",
+       }, {
+               .context = "Title",
+               .button = "Right",
+               .event = "Click",
+               .action = "ShowMenu",
+               .attributes[0] = {
+                       .name = "menu",
+                       .value = "client-menu",
+               },
+               .attributes[1] = {
+                       .name = "atCursor",
+                       .value = "yes",
+               },
+       }, {
+               .context = "Close",
+               .button = "Left",
+               .event = "Click",
+               .action = "Close",
+       }, {
+               .context = "Iconify",
+               .button = "Left",
+               .event = "Click",
+               .action = "Iconify",
+       }, {
+               .context = "Maximize",
+               .button = "Left",
+               .event = "Click",
+               .action = "ToggleMaximize",
+       }, {
+               .context = "Maximize",
+               .button = "Right",
+               .event = "Click",
+               .action = "ToggleMaximize",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "horizontal",
+               },
+       }, {
+               .context = "Maximize",
+               .button = "Middle",
+               .event = "Click",
+               .action = "ToggleMaximize",
+               .attributes[0] = {
+                       .name = "direction",
+                       .value = "vertical",
+               },
+       }, {
+               .context = "WindowMenu",
+               .button = "Left",
+               .event = "Click",
+               .action = "ShowMenu",
+               .attributes[0] = {
+                       .name = "menu",
+                       .value = "client-menu",
+               },
+               .attributes[1] = {
+                       .name = "atCursor",
+                       .value = "no",
+               },
+       }, {
+               .context = "WindowMenu",
+               .button = "Right",
+               .event = "Click",
+               .action = "ShowMenu",
+               .attributes[0] = {
+                       .name = "menu",
+                       .value = "client-menu",
+               },
+               .attributes[1] = {
+                       .name = "atCursor",
+                       .value = "no",
+               },
+       }, {
+               .context = "Root",
+               .button = "Left",
+               .event = "Press",
+               .action = "ShowMenu",
+               .attributes[0] = {
+                       .name = "menu",
+                       .value = "root-menu",
+               },
+       }, {
+               .context = "Root",
+               .button = "Right",
+               .event = "Press",
+               .action = "ShowMenu",
+               .attributes[0] = {
+                       .name = "menu",
+                       .value = "root-menu",
+               },
+       }, {
+               .context = "Root",
+               .button = "Middle",
+               .event = "Press",
+               .action = "ShowMenu",
+               .attributes[0] = {
+                       .name = "menu",
+                       .value = "root-menu",
+               },
+       }, {
+               .context = "Root",
+               .button = "Up",
+               .event = "Scroll",
+               .action = "GoToDesktop",
+               .attributes[0] = {
+                       .name = "to",
+                       .value = "left",
+               },
+       }, {
+               .context = "Root",
+               .button = "Down",
+               .event = "Scroll",
+               .action = "GoToDesktop",
+               .attributes[0] = {
+                       .name = "to",
+                       .value = "right",
+               },
+       }, {
+               .context = "Client",
+               .button = "Left",
+               .event = "Press",
+               .action = "Focus",
+       }, {
+               .context = "Client",
+               .button = "Left",
+               .event = "Press",
+               .action = "Raise",
+       }, {
+               .context = "Client",
+               .button = "Right",
+               .event = "Press",
+               .action = "Focus",
+       }, {
+               .context = "Client",
+               .button = "Right",
+               .event = "Press",
+               .action = "Raise",
+       }, {
+               .context = "Client",
+               .button = "Middle",
+               .event = "Press",
+               .action = "Focus",
+       }, {
+               .context = "Client",
+               .button = "Middle",
+               .event = "Press",
+               .action = "Raise",
+       }, {
+               .context = NULL,
+       },
+};
+
+#endif /* LABWC_DEFAULT_BINDINGS_H */
index 6c0267335438cf2aff4b22bc382669a64a45df1a..3723e42b72a28d48e4458cd0b7ceaeed786983c8 100644 (file)
@@ -321,6 +321,10 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
                        action_arg_add_str(action, argument, content);
                        goto cleanup;
                }
+               if (!strcasecmp(argument, "atCursor")) {
+                       action_arg_add_bool(action, argument, parse_bool(content, true));
+                       goto cleanup;
+               }
                break;
        case ACTION_TYPE_TOGGLE_MAXIMIZE:
        case ACTION_TYPE_MAXIMIZE:
@@ -571,7 +575,8 @@ action_list_free(struct wl_list *action_list)
 }
 
 static void
-show_menu(struct server *server, struct view *view, const char *menu_name)
+show_menu(struct server *server, struct view *view,
+               const char *menu_name, bool at_cursor)
 {
        if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH
                        && server->input_mode != LAB_INPUT_STATE_MENU) {
@@ -579,34 +584,25 @@ show_menu(struct server *server, struct view *view, const char *menu_name)
                return;
        }
 
-       bool force_menu_top_left = false;
        struct menu *menu = menu_get_by_id(server, menu_name);
        if (!menu) {
                return;
        }
-       if (!strcasecmp(menu_name, "client-menu")) {
-               if (!view) {
-                       return;
-               }
-               enum ssd_part_type type = ssd_at(view->ssd, server->scene,
-                       server->seat.cursor->x, server->seat.cursor->y);
-               if (type == LAB_SSD_BUTTON_WINDOW_MENU) {
-                       force_menu_top_left = true;
-               } else if (ssd_part_contains(LAB_SSD_PART_TITLEBAR, type)) {
-                       force_menu_top_left = false;
-               } else {
-                       force_menu_top_left = true;
-               }
+
+       int x = server->seat.cursor->x;
+       int y = server->seat.cursor->y;
+
+       /* The client menu needs an active client */
+       if (!view && strcasecmp(menu_name, "client-menu") == 0) {
+               return;
        }
 
-       int x, y;
-       if (force_menu_top_left) {
+       /* Place menu in the view corner if desired (and menu is not root-menu) */
+       if (!at_cursor && view) {
                x = view->current.x;
                y = view->current.y;
-       } else {
-               x = server->seat.cursor->x;
-               y = server->seat.cursor->y;
        }
+
        /* Replaced by next show_menu() or cleaned on view_destroy() */
        menu->triggered_by_view = view;
        menu_open(menu, x, y);
@@ -764,7 +760,9 @@ actions_run(struct view *activator, struct server *server,
                        kill(getpid(), SIGHUP);
                        break;
                case ACTION_TYPE_SHOW_MENU:
-                       show_menu(server, view, action_get_str(action, "menu", NULL));
+                       show_menu(server, view,
+                               action_get_str(action, "menu", NULL),
+                               action_get_bool(action, "atCursor", true));
                        break;
                case ACTION_TYPE_TOGGLE_MAXIMIZE:
                        if (view) {
index e672aebd1a56162258856d6b677c39ed78c8ac45..fd5b41e8f717d23d71ab0c2e06e4b6615a8fae86 100644 (file)
@@ -21,6 +21,7 @@
 #include "common/nodename.h"
 #include "common/parse-bool.h"
 #include "common/string-helpers.h"
+#include "config/default-bindings.h"
 #include "config/keybind.h"
 #include "config/libinput.h"
 #include "config/mousebind.h"
@@ -1165,137 +1166,41 @@ rcxml_init(void)
        rc.workspace_config.min_nr_workspaces = 1;
 }
 
-static struct {
-       const char *binding, *action, *attribute, *value;
-} key_combos[] = {
-       { "A-Tab", "NextWindow", NULL, NULL },
-       { "W-Return", "Execute", "command", "alacritty" },
-       { "A-F3", "Execute", "command", "bemenu-run" },
-       { "A-F4", "Close", NULL, NULL },
-       { "W-a", "ToggleMaximize", NULL, NULL },
-       { "A-Left", "MoveToEdge", "direction", "left" },
-       { "A-Right", "MoveToEdge", "direction", "right" },
-       { "A-Up", "MoveToEdge", "direction", "up" },
-       { "A-Down", "MoveToEdge", "direction", "down" },
-       { "W-Left", "SnapToEdge", "direction", "left" },
-       { "W-Right", "SnapToEdge", "direction", "right" },
-       { "W-Up", "SnapToEdge", "direction", "up" },
-       { "W-Down", "SnapToEdge", "direction", "down" },
-       { "A-Space", "ShowMenu", "menu", "client-menu"},
-       { "XF86_AudioLowerVolume", "Execute", "command", "amixer sset Master 5%-" },
-       { "XF86_AudioRaiseVolume", "Execute", "command", "amixer sset Master 5%+" },
-       { "XF86_AudioMute", "Execute", "command", "amixer sset Master toggle" },
-       { "XF86_MonBrightnessUp", "Execute", "command", "brightnessctl set +10%" },
-       { "XF86_MonBrightnessDown", "Execute", "command", "brightnessctl set 10%-" },
-       { NULL, NULL, NULL, NULL },
-};
-
 static void
 load_default_key_bindings(void)
 {
        struct keybind *k;
        struct action *action;
        for (int i = 0; key_combos[i].binding; i++) {
-               k = keybind_create(key_combos[i].binding);
+               struct key_combos *current = &key_combos[i];
+               k = keybind_create(current->binding);
                if (!k) {
                        continue;
                }
 
-               action = action_create(key_combos[i].action);
+               action = action_create(current->action);
                wl_list_append(&k->actions, &action->link);
 
-               if (key_combos[i].attribute && key_combos[i].value) {
+               for (size_t j = 0; j < ARRAY_SIZE(current->attributes); j++) {
+                       if (!current->attributes[j].name
+                                       || !current->attributes[j].value) {
+                               break;
+                       }
                        action_arg_from_xml_node(action,
-                               key_combos[i].attribute, key_combos[i].value);
+                               current->attributes[j].name,
+                               current->attributes[j].value);
                }
        }
 }
 
-/*
- * `struct mouse_combo` variable description and examples:
- *
- * | Variable  | Description                | Examples
- * |-----------|----------------------------|---------------------
- * | context   | context name               | Maximize, Root
- * | button    | mousebind button/direction | Left, Up
- * | event     | mousebind action           | Click, Scroll
- * | action    | action name                | ToggleMaximize, GoToDesktop
- * | attribute | action attribute           | to
- * | value     | action attribute value     | left
- *
- * <mouse>
- *   <context name="Maximize">
- *     <mousebind button="Left" action="Click">
- *       <action name="Focus"/>
- *       <action name="Raise"/>
- *       <action name="ToggleMaximize"/>
- *     </mousebind>
- *   </context>
- *   <context name="Root">
- *     <mousebind direction="Up" action="Scroll">
- *       <action name="GoToDesktop" to="left" wrap="yes"/>
- *     </mousebind>
- *   </context>
- * </mouse>
- */
-static struct mouse_combos {
-       const char *context, *button, *event, *action, *attribute, *value;
-} mouse_combos[] = {
-       { "Left", "Left", "Drag", "Resize", NULL, NULL},
-       { "Top", "Left", "Drag", "Resize", NULL, NULL},
-       { "Bottom", "Left", "Drag", "Resize", NULL, NULL},
-       { "Right", "Left", "Drag", "Resize", NULL, NULL},
-       { "TLCorner", "Left", "Drag", "Resize", NULL, NULL},
-       { "TRCorner", "Left", "Drag", "Resize", NULL, NULL},
-       { "BRCorner", "Left", "Drag", "Resize", NULL, NULL},
-       { "BLCorner", "Left", "Drag", "Resize", NULL, NULL},
-       { "Frame", "A-Left", "Press", "Focus", NULL, NULL},
-       { "Frame", "A-Left", "Press", "Raise", NULL, NULL},
-       { "Frame", "A-Left", "Drag", "Move", NULL, NULL},
-       { "Frame", "A-Right", "Press", "Focus", NULL, NULL},
-       { "Frame", "A-Right", "Press", "Raise", NULL, NULL},
-       { "Frame", "A-Right", "Drag", "Resize", NULL, NULL},
-       { "Titlebar", "Left", "Press", "Focus", NULL, NULL},
-       { "Titlebar", "Left", "Press", "Raise", NULL, NULL},
-       { "Titlebar", "Up", "Scroll", "Unfocus", NULL, NULL},
-       { "Titlebar", "Up", "Scroll", "Shade", NULL, NULL},
-       { "Titlebar", "Down", "Scroll", "Unshade", NULL, NULL},
-       { "Titlebar", "Down", "Scroll", "Focus", NULL, NULL},
-       { "Title", "Left", "Drag", "Move", NULL, NULL },
-       { "Title", "Left", "DoubleClick", "ToggleMaximize", NULL, NULL },
-       { "TitleBar", "Right", "Click", "Focus", NULL, NULL},
-       { "TitleBar", "Right", "Click", "Raise", NULL, NULL},
-       { "Title", "Right", "Click", "ShowMenu", "menu", "client-menu"},
-       { "Close", "Left", "Click", "Close", NULL, NULL },
-       { "Iconify", "Left", "Click", "Iconify", NULL, NULL},
-       { "Maximize", "Left", "Click", "ToggleMaximize", NULL, NULL},
-       { "Maximize", "Right", "Click", "ToggleMaximize", "direction", "horizontal"},
-       { "Maximize", "Middle", "Click", "ToggleMaximize", "direction", "vertical"},
-       { "WindowMenu", "Left", "Click", "ShowMenu", "menu", "client-menu"},
-       { "WindowMenu", "Right", "Click", "ShowMenu", "menu", "client-menu"},
-       { "Root", "Left", "Press", "ShowMenu", "menu", "root-menu"},
-       { "Root", "Right", "Press", "ShowMenu", "menu", "root-menu"},
-       { "Root", "Middle", "Press", "ShowMenu", "menu", "root-menu"},
-       { "Root", "Up", "Scroll", "GoToDesktop", "to", "left"},
-       { "Root", "Down", "Scroll", "GoToDesktop", "to", "right"},
-       { "Client", "Left", "Press", "Focus", NULL, NULL},
-       { "Client", "Left", "Press", "Raise", NULL, NULL},
-       { "Client", "Right", "Press", "Focus", NULL, NULL},
-       { "Client", "Right", "Press", "Raise", NULL, NULL},
-       { "Client", "Middle", "Press", "Focus", NULL, NULL},
-       { "Client", "Middle", "Press", "Raise", NULL, NULL},
-       { NULL, NULL, NULL, NULL, NULL, NULL },
-};
-
 static void
 load_default_mouse_bindings(void)
 {
        uint32_t count = 0;
        struct mousebind *m;
        struct action *action;
-       struct mouse_combos *current;
        for (int i = 0; mouse_combos[i].context; i++) {
-               current = &mouse_combos[i];
+               struct mouse_combos *current = &mouse_combos[i];
                if (i == 0
                                || strcmp(current->context, mouse_combos[i - 1].context)
                                || strcmp(current->button, mouse_combos[i - 1].button)
@@ -1316,14 +1221,14 @@ load_default_mouse_bindings(void)
                action = action_create(current->action);
                wl_list_append(&m->actions, &action->link);
 
-               /*
-                * Only one attribute/value (of string type) is required for the
-                * built-in binds.  If more are required in the future, a
-                * slightly more sophisticated approach will be needed.
-                */
-               if (current->attribute && current->value) {
+               for (size_t j = 0; j < ARRAY_SIZE(current->attributes); j++) {
+                       if (!current->attributes[j].name
+                                       || !current->attributes[j].value) {
+                               break;
+                       }
                        action_arg_from_xml_node(action,
-                               current->attribute, current->value);
+                               current->attributes[j].name,
+                               current->attributes[j].value);
                }
        }
        wlr_log(WLR_DEBUG, "Loaded %u merged mousebinds", count);