From: Johan Malm Date: Mon, 18 May 2020 19:54:25 +0000 (+0100) Subject: Support openbox style "cycle window" X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=a2c48c7aab662269fe080c5aade1368a491838fb;p=proto%2Flabwc.git Support openbox style "cycle window" We still use alt-F2, but it now feels like alt-tab does. --- diff --git a/labwc.h b/labwc.h index 871589f7..05d5755c 100644 --- a/labwc.h +++ b/labwc.h @@ -68,6 +68,8 @@ struct server { struct wl_listener request_cursor; struct wl_listener request_set_selection; struct wl_list keyboards; + + /* cursor interactive */ enum cursor_mode cursor_mode; struct view *grabbed_view; double grab_x, grab_y; @@ -139,19 +141,15 @@ void xwl_surface_configure(struct wl_listener *listener, void *data); void xwl_surface_new(struct wl_listener *listener, void *data); bool view_want_deco(struct view *view); -void view_focus_last_toplevel(struct server *server); void view_focus(struct view *view); -void view_focus_next_toplevel(struct view *current); void begin_interactive(struct view *view, enum cursor_mode mode, uint32_t edges); -bool is_toplevel(struct view *view); +struct view *view_front_toplevel(struct server *server); +struct view *next_toplevel(struct view *current); struct view *view_at(struct server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy, int *view_area); -/* TODO: try to refactor to remove from header file */ -struct view *first_toplevel(struct server *server); - void server_new_input(struct wl_listener *listener, void *data); void seat_request_cursor(struct wl_listener *listener, void *data); void seat_request_set_selection(struct wl_listener *listener, void *data); diff --git a/server.c b/server.c index 3ec0a831..c5eef472 100644 --- a/server.c +++ b/server.c @@ -1,5 +1,8 @@ #include "labwc.h" +static bool in_alt_tab_mode; +static struct view *alt_tab_view; + static void keyboard_handle_modifiers(struct wl_listener *listener, void *data) { /* This event is raised when a modifier key, such as shift or alt, is @@ -33,7 +36,9 @@ static bool handle_keybinding(struct server *server, xkb_keysym_t sym) break; case XKB_KEY_F1: case XKB_KEY_F2: - view_focus_last_toplevel(server); + in_alt_tab_mode = true; + alt_tab_view = next_toplevel(view_front_toplevel(server)); + fprintf(stderr, "alt_tab_view=%p\n", (void *)alt_tab_view); break; case XKB_KEY_F3: if (fork() == 0) { @@ -41,8 +46,8 @@ static bool handle_keybinding(struct server *server, xkb_keysym_t sym) } break; case XKB_KEY_F6: - begin_interactive(first_toplevel(server), TINYWL_CURSOR_MOVE, - 0); + begin_interactive(view_front_toplevel(server), + TINYWL_CURSOR_MOVE, 0); break; case XKB_KEY_F12: dbg_show_views(server); @@ -71,6 +76,23 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data) bool handled = false; uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); + + if (in_alt_tab_mode) { + if ((syms[0] == XKB_KEY_Alt_L) && + event->state == WLR_KEY_RELEASED) { + /* end cycle */ + in_alt_tab_mode = false; + view_focus(alt_tab_view); + } else if (event->state == WLR_KEY_PRESSED) { + /* cycle to next */ + alt_tab_view = next_toplevel(alt_tab_view); + fprintf(stderr, "alt_tab_view=%p\n", + (void *)alt_tab_view); + return; + } + } + + /* Handle compositor key bindings */ if ((modifiers & WLR_MODIFIER_ALT) && event->state == WLR_KEY_PRESSED) { /* If alt is held down and this button was _pressed_, we attempt * to process it as a compositor keybinding. */ @@ -78,7 +100,6 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data) handled = handle_keybinding(server, syms[i]); } } - if (!handled) { /* Otherwise, we pass it along to the client. */ wlr_seat_set_keyboard(seat, keyboard->device); diff --git a/view.c b/view.c index edddebca..966b8690 100644 --- a/view.c +++ b/view.c @@ -1,6 +1,6 @@ #include "labwc.h" -bool is_toplevel(struct view *view) +static bool is_toplevel(struct view *view) { switch (view->type) { case LAB_XDG_SHELL_VIEW: @@ -11,61 +11,18 @@ bool is_toplevel(struct view *view) return false; } -struct view *first_toplevel(struct server *server) -{ - struct view *view; - - wl_list_for_each (view, &server->views, link) { - if (!view->been_mapped) { - continue; - } - if (is_toplevel(view)) { - return view; - } - } - fprintf(stderr, "warn: found no toplevel view (%s)\n", __func__); - return NULL; -} - -static struct view *last_toplevel(struct server *server) -{ - struct view *view; - - wl_list_for_each_reverse (view, &server->views, link) { - if (!view->been_mapped) - continue; - if (is_toplevel(view)) - return view; - } - /* no top-level view */ - return NULL; -} - -void view_focus_last_toplevel(struct server *server) -{ - /* TODO: write view_nr_toplevel_views() */ - if (wl_list_length(&server->views) < 2) - return; - struct view *view = last_toplevel(server); - view_focus(view); -} - -static struct view *next_toplevel(struct view *current) -{ - struct view *tmp = current; - - do { - tmp = wl_container_of(tmp->link.next, tmp, link); - } while (!tmp->been_mapped || !is_toplevel(tmp)); - return tmp; -} - -/* Original function name - suggest we keep it */ -void view_focus_next_toplevel(struct view *current) +bool view_want_deco(struct view *view) { - struct view *view; - view = next_toplevel(current); - view_focus(view); + if (view->type != LAB_XWAYLAND_VIEW) + return false; + if (!is_toplevel(view)) + return false; + if (view->xwayland_surface->override_redirect) + return false; + if (view->xwayland_surface->decorations != + WLR_XWAYLAND_SURFACE_DECORATIONS_ALL) + return false; + return true; } static void move_to_front(struct view *view) @@ -128,20 +85,6 @@ void view_focus(struct view *view) &keyboard->modifiers); } -bool view_want_deco(struct view *view) -{ - if (view->type != LAB_XWAYLAND_VIEW) - return false; - if (!is_toplevel(view)) - return false; - if (view->xwayland_surface->override_redirect) - return false; - if (view->xwayland_surface->decorations != - WLR_XWAYLAND_SURFACE_DECORATIONS_ALL) - return false; - return true; -} - void begin_interactive(struct view *view, enum cursor_mode mode, uint32_t edges) { /* This function sets up an interactive move or resize operation, where @@ -184,6 +127,28 @@ void begin_interactive(struct view *view, enum cursor_mode mode, uint32_t edges) } } +struct view *view_front_toplevel(struct server *server) +{ + struct view *view; + wl_list_for_each (view, &server->views, link) { + if (!view->been_mapped) + continue; + if (is_toplevel(view)) + return view; + } + return NULL; +} + +struct view *next_toplevel(struct view *current) +{ + /* FIXME: write nr_toplevels() */ + struct view *view = current; + do { + view = wl_container_of(view->link.next, view, link); + } while (!view->been_mapped || !is_toplevel(view)); + return view; +} + static bool _view_at(struct view *view, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { diff --git a/xdg.c b/xdg.c index 8234eb90..39310d4f 100644 --- a/xdg.c +++ b/xdg.c @@ -61,7 +61,7 @@ void xdg_surface_unmap(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, unmap); view->mapped = false; - view_focus_next_toplevel(view); + view_focus(next_toplevel(view)); } void xdg_surface_destroy(struct wl_listener *listener, void *data) diff --git a/xwl.c b/xwl.c index 9294377d..c6e7806f 100644 --- a/xwl.c +++ b/xwl.c @@ -49,7 +49,12 @@ void xwl_surface_unmap(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, unmap); view->mapped = false; - view_focus_next_toplevel(view); + /* + * Note that if 'view' is not a toplevel view, the 'front' toplevel view + * will be focussed on; but if 'view' is a toplevel view, the 'next' + * will be focussed on. + */ + view_focus(next_toplevel(view)); } void xwl_surface_destroy(struct wl_listener *listener, void *data)