diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 7788d551..56c840a6 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -125,13 +125,17 @@ 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 keybind for NextWindow is Alt-Tab. + Default keybinds for NextWindow and PreviousWindow are Alt-Tab and + Shift-Alt-Tab. While cycling through windows, the arrow keys move the + selected window forwards/backwards and the escape key halts the cycling. - The arrow keys are used to move forwards/backwards while cycling. + *workspace* [all|current] + This determines whether to cycle through windows on all workspaces or the + current workspace. Default is "current". ** Re-load configuration and theme files. diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 85363354..a1cedb20 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -339,7 +339,7 @@ this is for compatibility with Openbox. ## WINDOW SWITCHER ``` - + @@ -349,17 +349,13 @@ this is for compatibility with Openbox. ``` -** +** *preview* [yes|no] Preview the contents of the selected window when switching between windows. Default is yes. *outlines* [yes|no] Draw an outline around the selected window when switching between windows. Default is yes. - *allWorkspaces* [yes|no] Show windows regardless of what workspace - they are on. Default no (that is only windows on the current workspace - are shown). - *unshade* [yes|no] Temporarily unshade windows when switching between them and permanently unshade on the final selection. Default is yes. diff --git a/docs/rc.xml.all b/docs/rc.xml.all index a99aa997..dd348300 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -77,7 +77,7 @@ - + @@ -119,7 +119,7 @@ then workspace name, then identifier/app-id, then the window title. It uses 100% of OSD window width. - + diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 8fd11aa0..6036be9c 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -182,7 +182,7 @@ struct rcxml { bool outlines; bool unshade; enum window_switcher_order order; - enum lab_view_criteria criteria; + enum cycle_workspace_filter workspace_filter; /* deprecated */ struct { bool show; enum cycle_osd_style style; diff --git a/include/config/types.h b/include/config/types.h index 540f609f..81d8fd36 100644 --- a/include/config/types.h +++ b/include/config/types.h @@ -117,6 +117,11 @@ enum cycle_osd_style { CYCLE_OSD_STYLE_THUMBNAIL, }; +enum cycle_workspace_filter { + CYCLE_WORKSPACE_ALL, + CYCLE_WORKSPACE_CURRENT, +}; + enum cycle_output_filter { CYCLE_OUTPUT_ALL, CYCLE_OUTPUT_CURSOR, diff --git a/include/cycle.h b/include/cycle.h index ba58b88d..2f2c5a2a 100644 --- a/include/cycle.h +++ b/include/cycle.h @@ -4,6 +4,7 @@ #include #include +#include "config/types.h" struct output; @@ -42,13 +43,18 @@ struct cycle_osd_field { struct wl_list link; /* struct rcxml.window_switcher.osd.fields */ }; +struct cycle_filter { + enum cycle_workspace_filter workspace; +}; + struct buf; struct view; struct server; struct wlr_scene_node; /* Begin window switcher */ -void cycle_begin(struct server *server, enum lab_cycle_dir direction); +void cycle_begin(struct server *server, enum lab_cycle_dir direction, + struct cycle_filter filter); /* Cycle the selected view in the window switcher */ void cycle_step(struct server *server, enum lab_cycle_dir direction); diff --git a/include/labwc.h b/include/labwc.h index 3d3ca2a3..ee10af12 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -5,6 +5,7 @@ #include #include #include "common/set.h" +#include "cycle.h" #include "input/cursor.h" #include "overlay.h" @@ -310,6 +311,7 @@ struct server { struct wlr_scene_node *preview_node; struct wlr_scene_node *preview_dummy; struct lab_scene_rect *preview_outline; + struct cycle_filter filter; } cycle; struct theme *theme; diff --git a/src/action.c b/src/action.c index 7ddba0be..9fb7ca22 100644 --- a/src/action.c +++ b/src/action.c @@ -366,6 +366,20 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char goto cleanup; } break; + case ACTION_TYPE_NEXT_WINDOW: + case ACTION_TYPE_PREVIOUS_WINDOW: + if (!strcasecmp(argument, "workspace")) { + if (!strcasecmp(content, "all")) { + action_arg_add_int(action, argument, CYCLE_WORKSPACE_ALL); + } else if (!strcasecmp(content, "current")) { + action_arg_add_int(action, argument, CYCLE_WORKSPACE_CURRENT); + } 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")) { action_arg_add_str(action, argument, content); @@ -1126,19 +1140,20 @@ run_action(struct view *view, struct server *server, struct action *action, } break; case ACTION_TYPE_NEXT_WINDOW: + case ACTION_TYPE_PREVIOUS_WINDOW: { + enum lab_cycle_dir dir = (action->type == ACTION_TYPE_NEXT_WINDOW) ? + LAB_CYCLE_DIR_FORWARD : LAB_CYCLE_DIR_BACKWARD; + struct cycle_filter filter = { + .workspace = action_get_int(action, "workspace", + rc.window_switcher.workspace_filter), + }; if (server->input_mode == LAB_INPUT_STATE_CYCLE) { - cycle_step(server, LAB_CYCLE_DIR_FORWARD); + cycle_step(server, dir); } else { - cycle_begin(server, LAB_CYCLE_DIR_FORWARD); - } - break; - case ACTION_TYPE_PREVIOUS_WINDOW: - if (server->input_mode == LAB_INPUT_STATE_CYCLE) { - cycle_step(server, LAB_CYCLE_DIR_BACKWARD); - } else { - cycle_begin(server, LAB_CYCLE_DIR_BACKWARD); + cycle_begin(server, dir, filter); } break; + } case ACTION_TYPE_RECONFIGURE: kill(getpid(), SIGHUP); break; diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 60e709f2..00217596 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1269,10 +1269,16 @@ entry(xmlNode *node, char *nodename, char *content) } else if (!strcasecmp(nodename, "outlines.windowSwitcher")) { set_bool(content, &rc.window_switcher.outlines); } else if (!strcasecmp(nodename, "allWorkspaces.windowSwitcher")) { - if (parse_bool(content, -1) == true) { - rc.window_switcher.criteria &= - ~LAB_VIEW_CRITERIA_CURRENT_WORKSPACE; + int ret = parse_bool(content, -1); + if (ret < 0) { + wlr_log(WLR_ERROR, "Invalid value for : '%s'", content); + } else { + rc.window_switcher.workspace_filter = ret ? + CYCLE_WORKSPACE_ALL : CYCLE_WORKSPACE_CURRENT; } + wlr_log(WLR_ERROR, " is deprecated." + " Use instead."); } else if (!strcasecmp(nodename, "unshade.windowSwitcher")) { set_bool(content, &rc.window_switcher.unshade); @@ -1493,9 +1499,7 @@ rcxml_init(void) rc.window_switcher.preview = true; rc.window_switcher.outlines = true; rc.window_switcher.unshade = true; - rc.window_switcher.criteria = LAB_VIEW_CRITERIA_CURRENT_WORKSPACE - | LAB_VIEW_CRITERIA_ROOT_TOPLEVEL - | LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER; + rc.window_switcher.workspace_filter = CYCLE_WORKSPACE_CURRENT; rc.window_switcher.order = WINDOW_SWITCHER_ORDER_FOCUS; rc.resize_indicator = LAB_RESIZE_INDICATOR_NEVER; diff --git a/src/cycle/cycle.c b/src/cycle/cycle.c index 067c9929..9ae5b9b0 100644 --- a/src/cycle/cycle.c +++ b/src/cycle/cycle.c @@ -17,7 +17,7 @@ #include "theme.h" #include "view.h" -static bool init_cycle(struct server *server); +static bool init_cycle(struct server *server, struct cycle_filter filter); static void update_cycle(struct server *server); static void destroy_cycle(struct server *server); @@ -93,9 +93,10 @@ cycle_reinitialize(struct server *server) struct view *selected_view = cycle->selected_view; struct view *selected_view_prev = get_next_selected_view(server, LAB_CYCLE_DIR_BACKWARD); + struct cycle_filter filter = cycle->filter; destroy_cycle(server); - if (init_cycle(server)) { + if (init_cycle(server, filter)) { /* * Preserve the selected view (or its previous view) if it's * still in the cycle list @@ -152,13 +153,14 @@ restore_preview_node(struct server *server) } void -cycle_begin(struct server *server, enum lab_cycle_dir direction) +cycle_begin(struct server *server, enum lab_cycle_dir direction, + struct cycle_filter filter) { if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) { return; } - if (!init_cycle(server)) { + if (!init_cycle(server, filter)) { return; } @@ -314,10 +316,17 @@ insert_view_ordered_by_age(struct wl_list *views, struct view *new_view) /* Return false on failure */ static bool -init_cycle(struct server *server) +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; + if (filter.workspace == CYCLE_WORKSPACE_CURRENT) { + criteria |= LAB_VIEW_CRITERIA_CURRENT_WORKSPACE; + } + struct view *view; - for_each_view(view, &server->views, rc.window_switcher.criteria) { + for_each_view(view, &server->views, criteria) { if (rc.window_switcher.order == WINDOW_SWITCHER_ORDER_AGE) { insert_view_ordered_by_age(&server->cycle.views, view); } else { @@ -328,6 +337,7 @@ init_cycle(struct server *server) wlr_log(WLR_DEBUG, "no views to switch between"); return false; } + server->cycle.filter = filter; if (rc.window_switcher.osd.show) { /* Create OSD */ @@ -406,4 +416,5 @@ destroy_cycle(struct server *server) } server->cycle.selected_view = NULL; + server->cycle.filter = (struct cycle_filter){0}; }