diff --git a/include/labwc.h b/include/labwc.h index eb00fd02..cc04b6b7 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -386,12 +386,19 @@ void foreign_toplevel_handle_create(struct view *view); void desktop_raise_view(struct view *view); void desktop_focus_and_activate_view(struct seat *seat, struct view *view); +enum lab_cycle_dir +{ + LAB_CYCLE_DIR_NONE, + LAB_CYCLE_DIR_FORWARD, + LAB_CYCLE_DIR_BACKWARD, +}; + /** * desktop_cycle_view - return view to 'cycle' to * @current: reference point for finding next view to cycle to * Note: If !current, the server->views second focusable view is returned */ -struct view *desktop_cycle_view(struct server *server, struct view *current); +struct view *desktop_cycle_view(struct server *server, struct view *current, enum lab_cycle_dir dir); struct view *desktop_focused_view(struct server *server); void desktop_focus_topmost_mapped_view(struct server *server); bool isfocusable(struct view *view); diff --git a/src/action.c b/src/action.c index b6b679e2..4c0ff03e 100644 --- a/src/action.c +++ b/src/action.c @@ -46,7 +46,7 @@ action(struct server *server, const char *action, const char *command) view_snap_to_edge(desktop_focused_view(server), command); } else if (!strcasecmp(action, "NextWindow")) { server->cycle_view = - desktop_cycle_view(server, server->cycle_view); + desktop_cycle_view(server, server->cycle_view, LAB_CYCLE_DIR_NONE); osd_update(server); } else if (!strcasecmp(action, "Reconfigure")) { spawn_async_no_shell("killall -SIGHUP labwc"); diff --git a/src/desktop.c b/src/desktop.c index b616acf5..59999091 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -149,18 +149,23 @@ first_view(struct server *server) } struct view * -desktop_cycle_view(struct server *server, struct view *current) +desktop_cycle_view(struct server *server, struct view *current, enum lab_cycle_dir dir) { if (!has_focusable_view(&server->views)) { return NULL; } struct view *view = current ? current : first_view(server); - - /* Replacement for wl_list_for_each_from() */ - do { - view = wl_container_of(view->link.next, view, link); - } while (&view->link == &server->views || !isfocusable(view)); + if (dir == LAB_CYCLE_DIR_FORWARD) { + /* Replacement for wl_list_for_each_from() */ + do { + view = wl_container_of(view->link.next, view, link); + } while (&view->link == &server->views || !isfocusable(view)); + } else if (dir == LAB_CYCLE_DIR_BACKWARD) { + do { + view = wl_container_of(view->link.prev, view, link); + } while (&view->link == &server->views || !isfocusable(view)); + } damage_all_outputs(server); return view; } diff --git a/src/keyboard.c b/src/keyboard.c index 4f7fd253..dd1452ec 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -73,6 +73,18 @@ handle_keybinding(struct server *server, uint32_t modifiers, xkb_keysym_t sym) return false; } +static bool is_modifier_key(xkb_keysym_t sym) +{ + return sym == XKB_KEY_Shift_L || + sym == XKB_KEY_Shift_R || + sym == XKB_KEY_Alt_L || + sym == XKB_KEY_Alt_R || + sym == XKB_KEY_Control_L || + sym == XKB_KEY_Control_R || + sym == XKB_KEY_Super_L || + sym == XKB_KEY_Super_R; +} + static bool handle_compositor_keybindings(struct wl_listener *listener, struct wlr_event_keyboard_key *event) @@ -96,10 +108,20 @@ handle_compositor_keybindings(struct wl_listener *listener, damage_all_outputs(server); if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { /* cycle to next */ - server->cycle_view = - desktop_cycle_view(server, server->cycle_view); - osd_update(server); - damage_all_outputs(server); + bool backwards = modifiers & WLR_MODIFIER_SHIFT; + /* ignore if this is a modifier key being pressed */ + bool ignore = false; + for (int i = 0; i < nsyms; i++) { + ignore |= is_modifier_key(syms[i]); + } + + if (!ignore) { + server->cycle_view = + desktop_cycle_view(server, server->cycle_view, + backwards ? LAB_CYCLE_DIR_BACKWARD : LAB_CYCLE_DIR_FORWARD); + osd_update(server); + damage_all_outputs(server); + } } /* don't send any key events to clients when osd onscreen */ return true;