diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd
index fe468cd1..33be0c26 100644
--- a/docs/labwc-actions.5.scd
+++ b/docs/labwc-actions.5.scd
@@ -125,8 +125,8 @@ Actions are used in menus and keyboard/mouse bindings.
Resize and move the active window back to its untiled or unmaximized
position if it had been maximized or tiled to a direction or region.
-**++
-**
+**++
+**
Cycle focus to next/previous window, respectively.
Default keybinds for NextWindow and PreviousWindow are Alt-Tab and
@@ -145,6 +145,10 @@ Actions are used in menus and keyboard/mouse bindings.
This determines whether to cycle through all windows or only windows of the
same application as the currently focused window. Default is "all".
+ *window* [root|all]
+ This determines whether to cycle through only topmost (root) windows or
+ all windows including child windows such as dialogs. Default is "root".
+
**
Re-load configuration and theme files.
diff --git a/include/config/types.h b/include/config/types.h
index fc293cd8..23e32a4f 100644
--- a/include/config/types.h
+++ b/include/config/types.h
@@ -133,4 +133,9 @@ enum cycle_app_id_filter {
CYCLE_APP_ID_CURRENT,
};
+enum cycle_window_filter {
+ CYCLE_WINDOW_ROOT,
+ CYCLE_WINDOW_ALL,
+};
+
#endif /* LABWC_CONFIG_TYPES_H */
diff --git a/include/cycle.h b/include/cycle.h
index c6e42810..5c2adf10 100644
--- a/include/cycle.h
+++ b/include/cycle.h
@@ -49,6 +49,7 @@ struct cycle_filter {
enum cycle_workspace_filter workspace;
enum cycle_output_filter output;
enum cycle_app_id_filter app_id;
+ enum cycle_window_filter window;
};
struct cycle_state {
diff --git a/src/action.c b/src/action.c
index 7f974917..b86fb1a1 100644
--- a/src/action.c
+++ b/src/action.c
@@ -403,6 +403,17 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
}
goto cleanup;
}
+ if (!strcasecmp(argument, "window")) {
+ if (!strcasecmp(content, "root")) {
+ action_arg_add_int(action, argument, CYCLE_WINDOW_ROOT);
+ } else if (!strcasecmp(content, "all")) {
+ action_arg_add_int(action, argument, CYCLE_WINDOW_ALL);
+ } else {
+ wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s' (%s)",
+ action_names[action->type], argument, content);
+ }
+ goto cleanup;
+ }
break;
case ACTION_TYPE_SHOW_MENU:
if (!strcmp(argument, "menu")) {
@@ -1174,6 +1185,8 @@ run_action(struct view *view, struct server *server, struct action *action,
CYCLE_OUTPUT_ALL),
.app_id = action_get_int(action, "identifier",
CYCLE_APP_ID_ALL),
+ .window = action_get_int(action, "window",
+ CYCLE_WINDOW_ROOT),
};
if (server->input_mode == LAB_INPUT_STATE_CYCLE) {
cycle_step(server, dir);
diff --git a/src/cycle/cycle.c b/src/cycle/cycle.c
index 32a7438f..7bbf7d55 100644
--- a/src/cycle/cycle.c
+++ b/src/cycle/cycle.c
@@ -331,8 +331,10 @@ static bool
init_cycle(struct server *server, struct cycle_filter filter)
{
enum lab_view_criteria criteria =
- LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER
- | LAB_VIEW_CRITERIA_ROOT_TOPLEVEL;
+ LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER;
+ if (filter.window == CYCLE_WINDOW_ROOT) {
+ criteria |= LAB_VIEW_CRITERIA_ROOT_TOPLEVEL;
+ }
if (filter.workspace == CYCLE_WORKSPACE_CURRENT) {
criteria |= LAB_VIEW_CRITERIA_CURRENT_WORKSPACE;
}