]> git.mdlowis.com Git - proto/labwc.git/commitdiff
action: support SendToDesktop 'follow' option
authorJohan Malm <jgm323@gmail.com>
Sun, 26 Mar 2023 09:57:53 +0000 (10:57 +0100)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Sun, 26 Mar 2023 17:52:50 +0000 (19:52 +0200)
Make follow 'true' by default as per Openbox 3.6 specification.
Note: this is an interface change.

Fixes: issue #841
docs/labwc-actions.5.scd
docs/menu.xml
include/action.h
src/action.c
src/config/rcxml.c
src/menu/menu.c

index b5e7d2bc3e9e4137c69229f51a829cfd8ff4c07a..164f1540a9220bf2141123e3c638f5257b37e61f 100644 (file)
@@ -86,13 +86,19 @@ Actions are used in menus and keyboard/mouse bindings.
        any windows, the cursor is centered on the given output.
 
 *<action name="GoToDesktop" to="value" />*
-       Switch to workspace. Supported values are "last", "left", "right" or the
-       full name of a workspace or its index (starting at 1) as configured in
-       rc.xml.
+       Switch to workspace.
 
-*<action name="SendToDesktop" to="value" />*
+       *to* The workspace to switch to. Supported values are "last", "left",
+       "right" or the full name of a workspace or its index (starting at 1)
+       as configured in rc.xml.
+
+*<action name="SendToDesktop" to="value" follow="yes" />*
        Send active window to workspace.
-       Supported values are the same as for GoToDesktop.
+
+       *to* The workspace to send the window to. Supported values are the same
+       as for GoToDesktop.
+
+       *follow* [yes|no] Also switch to the specified workspace. Default yes.
 
 *<action name="None">*
        If used as the only action for a binding: clear an earlier defined binding.
index 87f4ed8256c00e0d6bd605fedb7c2283506bac98..01b960375fafbc6f3f084749533cd9093ec25f6a 100644 (file)
   <menu id="workspaces" label="Workspace">
     <item label="Move left">
       <action name="SendToDesktop" to="left" />
-      <action name="GoToDesktop" to="left" />
     </item>
     <item label="Move right">
       <action name="SendToDesktop" to="right" />
-      <action name="GoToDesktop" to="right" />
     </item>
   </menu>
   <item label="Close">
index 96697597a4d7975ad7b45aa626e67691f235b0be..c26f15a8697575f85f7f8d759c219a276d89c537 100644 (file)
@@ -19,7 +19,10 @@ struct action {
 };
 
 struct action *action_create(const char *action_name);
+
 void action_arg_add_str(struct action *action, char *key, const char *value);
+void action_arg_add_bool(struct action *action, char *key, bool value);
+
 void action_arg_from_xml_node(struct action *action, char *nodename, char *content);
 
 bool actions_contain_toggle_keybinds(struct wl_list *action_list);
index bea2d8965d6cb6a5701f80e8db22d87cc3607fd5..c8b92b6a92dcbae441333469139fa26425cea831 100644 (file)
@@ -7,6 +7,7 @@
 #include <unistd.h>
 #include <wlr/util/log.h>
 #include "action.h"
+#include "common/get-bool.h"
 #include "common/list.h"
 #include "common/mem.h"
 #include "common/spawn.h"
@@ -20,6 +21,7 @@
 
 enum action_arg_type {
        LAB_ACTION_ARG_STR = 0,
+       LAB_ACTION_ARG_BOOL,
 };
 
 struct action_arg {
@@ -34,6 +36,11 @@ struct action_arg_str {
        char *value;
 };
 
+struct action_arg_bool {
+       struct action_arg base;
+       bool value;
+};
+
 enum action_type {
        ACTION_TYPE_INVALID = 0,
        ACTION_TYPE_NONE,
@@ -117,7 +124,10 @@ action_arg_from_xml_node(struct action *action, char *nodename, char *content)
                action_arg_add_str(action, NULL, content);
        } else if (!strcmp(nodename, "to.action")) {
                /* GoToDesktop, SendToDesktop */
-               action_arg_add_str(action, NULL, content);
+               action_arg_add_str(action, "to", content);
+       } else if (!strcmp(nodename, "follow.action")) {
+               /* SendToDesktop */
+               action_arg_add_bool(action, "follow", get_bool(content));
        } else if (!strcmp(nodename, "region.action")) {
                /* SnapToRegion */
                action_arg_add_str(action, NULL, content);
@@ -134,6 +144,13 @@ action_str_from_arg(struct action_arg *arg)
        return ((struct action_arg_str *)arg)->value;
 }
 
+static bool
+action_bool_from_arg(struct action_arg *arg)
+{
+       assert(arg->type == LAB_ACTION_ARG_BOOL);
+       return ((struct action_arg_bool *)arg)->value;
+}
+
 static struct action_arg *
 action_get_first_arg(struct action *action)
 {
@@ -442,16 +459,25 @@ actions_run(struct view *activator, struct server *server,
                        }
                        break;
                case ACTION_TYPE_SEND_TO_DESKTOP:
-                       if (!arg) {
-                               wlr_log(WLR_ERROR, "Missing argument for SendToDesktop");
-                               break;
-                       }
                        if (view) {
+                               struct action_arg *arg;
+                               char *target_name = NULL;
                                struct workspace *target;
-                               char *target_name = action_str_from_arg(arg);
+                               bool follow = true;
+
+                               wl_list_for_each(arg, &action->args, link) {
+                                       if (!strcmp("to", arg->key)) {
+                                               target_name = action_str_from_arg(arg);
+                                       } else if (!strcmp("follow", arg->key)) {
+                                               follow = action_bool_from_arg(arg);
+                                       }
+                               }
                                target = workspaces_find(view->workspace, target_name);
                                if (target) {
                                        view_move_to_workspace(view, target);
+                                       if (follow) {
+                                               workspaces_switch_to(target);
+                                       }
                                }
                        }
                        break;
@@ -517,3 +543,15 @@ action_arg_add_str(struct action *action, char *key, const char *value)
        arg->value = xstrdup(value);
        wl_list_append(&action->args, &arg->base.link);
 }
+
+void
+action_arg_add_bool(struct action *action, char *key, bool value)
+{
+       struct action_arg_bool *arg = znew(*arg);
+       arg->base.type = LAB_ACTION_ARG_BOOL;
+       if (key) {
+               arg->base.key = xstrdup(key);
+       }
+       arg->value = value;
+       wl_list_append(&action->args, &arg->base.link);
+}
index d0321d3d366265eb282e07a14e460c5e5bc74308..78515e6928ac91194e543969fef7cf62be56052d 100644 (file)
@@ -120,6 +120,11 @@ fill_keybind(char *nodename, char *content)
                wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
                        "nodename: '%s' content: '%s'", nodename, content);
        } else {
+               /*
+                * Here we deal with action sub-elements such as <to>, <output>,
+                * <region>, <direction> and so on. This is common to key- and
+                * mousebinds.
+                */
                action_arg_from_xml_node(current_keybind_action, nodename, content);
        }
 }
index 3bc74a626b7770324d0df351956719a79fd835e5..9ad4a153551a5b0e76f10b39613ed07630085cfb 100644 (file)
@@ -664,15 +664,15 @@ init_windowmenu(struct server *server)
                /* Workspace sub-menu */
                struct menu *workspace_menu = menu_create(server, "workspaces", "");
                current_item = item_create(workspace_menu, _("Move left"), false);
+               /*
+                * <action name="SendToDesktop"><follow> is true by default so
+                * GoToDesktop will be called as part of the action.
+                */
                fill_item("name.action", "SendToDesktop");
                fill_item("to.action", "left");
-               fill_item("name.action", "GoToDesktop");
-               fill_item("to.action", "left");
                current_item = item_create(workspace_menu, _("Move right"), false);
                fill_item("name.action", "SendToDesktop");
                fill_item("to.action", "right");
-               fill_item("name.action", "GoToDesktop");
-               fill_item("to.action", "right");
                current_item = item_create(menu, _("Workspace"), true);
                current_item->submenu = workspace_menu;