]> git.mdlowis.com Git - proto/labwc.git/commitdiff
view: refactor view_next()
authorJohan Malm <jgm323@gmail.com>
Mon, 7 Sep 2020 18:47:11 +0000 (19:47 +0100)
committerJohan Malm <jgm323@gmail.com>
Mon, 7 Sep 2020 18:47:11 +0000 (19:47 +0100)
include/labwc.h
src/action.c
src/dbg.c
src/keyboard.c
src/view.c
src/xdg.c
src/xwayland.c

index 0ace4d233d6655772ccd62980edaffd03ee53fa6..fbffc8464546b78040e02d3340abc79274f44f9c 100644 (file)
@@ -128,6 +128,7 @@ struct view {
 
        bool mapped;
        bool been_mapped;
+       bool minimized;
        int x, y, w, h;
        bool show_server_side_deco;
 
@@ -178,8 +179,7 @@ struct wlr_box view_get_surface_geometry(struct view *view);
 struct wlr_box view_geometry(struct view *view);
 void view_resize(struct view *view, struct wlr_box geo);
 void view_focus(struct view *view);
-struct view *view_front_toplevel(struct server *server);
-struct view *next_toplevel(struct view *current);
+struct view *view_next(struct view *current);
 bool view_hasfocus(struct view *view);
 struct view *view_at(struct server *server, double lx, double ly,
                     struct wlr_surface **surface, double *sx, double *sy,
index ab4a91c96a977b4aa93b1539f417b5fc291d0855..9787cb451b3d2efd1fcb9724ae5cf0a3f8a5e6ca 100644 (file)
@@ -11,7 +11,7 @@ void action(struct server *server, struct keybind *keybind)
        if (!strcasecmp(keybind->action, "Exit")) {
                wl_display_terminate(server->wl_display);
        } else if (!strcasecmp(keybind->action, "NextWindow")) {
-               server->cycle_view = next_toplevel(view_front_toplevel(server));
+               server->cycle_view = view_next(server->cycle_view);
        } else if (!strcasecmp(keybind->action, "Execute")) {
                spawn_async_no_shell(keybind->command);
        } else if (!strcasecmp(keybind->action, "debug-views")) {
index 9e26e6020eb8051667bf38f74a63edfb976b4d69..ff845fae5299803ede5dd488d6809bc6914c03e5 100644 (file)
--- a/src/dbg.c
+++ b/src/dbg.c
@@ -71,6 +71,10 @@ static void show_one_xwl_view(struct view *view)
 
 void dbg_show_one_view(struct view *view)
 {
+       if (!view->surface)
+               return;
+       if (!view->mapped && !view->minimized)
+               return;
        if (view->type == LAB_XDG_SHELL_VIEW)
                show_one_xdg_view(view);
        else if (view->type == LAB_XWAYLAND_VIEW)
index 2ca9009e7ccbda8aaf3e2ee9740f6ed521746805..02a2e8214217e84ae55b3434dac3e316ad0e093f 100644 (file)
@@ -65,7 +65,7 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data)
                        server->cycle_view = NULL;
                } else if (event->state == WLR_KEY_PRESSED) {
                        /* cycle to next */
-                       server->cycle_view = next_toplevel(server->cycle_view);
+                       server->cycle_view = view_next(server->cycle_view);
                        return;
                }
        }
index d4034f47b872f6cb87532689c1dd80e3c8f0508c..74e26d28439fe4c56d24ef9ab00b4f0662332968 100644 (file)
@@ -1,19 +1,6 @@
 #include "labwc.h"
 #include "common/bug-on.h"
 
-static bool is_toplevel(struct view *view)
-{
-       if (!view)
-               return false;
-       switch (view->type) {
-       case LAB_XDG_SHELL_VIEW:
-               return view->xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL;
-       case LAB_XWAYLAND_VIEW:
-               return view->xwayland_surface->parent == NULL;
-       }
-       return false;
-}
-
 void view_init_position(struct view *view)
 {
        /* If surface already has a 'desired' position, don't touch it */
@@ -112,39 +99,6 @@ bool view_hasfocus(struct view *view)
        return (view->surface == seat->keyboard_state.focused_surface);
 }
 
-static struct wlr_xwayland_surface *top_parent(struct view *view)
-{
-       struct wlr_xwayland_surface *s = view->xwayland_surface;
-       while (s->parent)
-               s = s->parent;
-       return s;
-}
-
-static void move_xwayland_decendants_to_front(struct view *parent)
-{
-       if (!parent || parent->type != LAB_XWAYLAND_VIEW)
-               return;
-       struct view *view, *next;
-       wl_list_for_each_reverse_safe(view, next, &parent->server->views, link)
-       {
-               /* need to stop here, otherwise loops keeps going forever */
-               if (view == parent)
-                       break;
-               if (view->type != LAB_XWAYLAND_VIEW)
-                       continue;
-               if (!view->mapped)
-                       continue;
-               if (top_parent(view) != parent->xwayland_surface)
-                       continue;
-               move_to_front(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.
- */
 void view_focus(struct view *view)
 {
        /* Note: this function only deals with keyboard focus. */
@@ -183,27 +137,56 @@ void view_focus(struct view *view)
                                       keyboard->num_keycodes,
                                       &keyboard->modifiers);
 
-       move_xwayland_decendants_to_front(view);
+       /* TODO: move xwayland decendants to front */
 }
 
-struct view *view_front_toplevel(struct server *server)
+static struct view *first_view(void)
 {
        struct view *view;
-       wl_list_for_each (view, &server->views, link) {
-               if (is_toplevel(view))
-                       return view;
+       view = wl_container_of(server.views.next, view, link);
+       return view;
+}
+
+/*
+ * Some xwayland apps produce unmapped surfaces on startup and also leave
+ * some unmapped surfaces kicking around on 'close' (for example * leafpad's
+ * "about" dialogue). Whilst this is not normally a problem, we have to be
+ * careful when cycling between views. The only view's we should focus are
+ * those that are already mapped and those that have been minimized.
+ */
+static bool isfocusable(struct view *view)
+{
+       /* filter out those xwayland surfaces that have never been mapped */
+       if (!view->surface)
+               return false;
+       return (view->mapped || view->minimized);
+}
+
+static int has_focusable_view(struct wl_list *wl_list)
+{
+       struct view *view;
+       wl_list_for_each (view, wl_list, link) {
+               if (isfocusable(view))
+                       return true;
        }
-       return NULL;
+       return false;
 }
 
-struct view *next_toplevel(struct view *current)
+/*
+ * Return next view. If NULL provided, return second view from front.
+ */
+/* TODO: rename function */
+struct view *view_next(struct view *current)
 {
-       if (!current)
+       if (!has_focusable_view(&server.views))
                return NULL;
-       struct view *view = current;
+
+       struct view *view = current ? current : first_view();
+
+       /* Replacement for wl_list_for_each_from() */
        do {
                view = wl_container_of(view->link.next, view, link);
-       } while (!is_toplevel(view));
+       } while (&view->link == &server.views || !isfocusable(view));
        return view;
 }
 
index 2dd88809851966599aeacff5fa17a2abc938ab27..63d8186280c533c69a528311136d7267933a809d 100644 (file)
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -148,7 +148,7 @@ static void xdg_toplevel_view_unmap(struct view *view)
 {
        view->mapped = false;
        wl_list_remove(&view->commit.link);
-       view_focus(next_toplevel(view));
+       view_focus(view_next(view));
 }
 
 static const struct view_impl xdg_toplevel_view_impl = {
index 2498ef1ccbfa5426f4c7571977934a4ad0c1e058..8400d573627d1b567a05fd71ce7072d9abcfae7c 100644 (file)
@@ -57,8 +57,6 @@ static void _close(struct view *view)
 
 static bool want_ssd(struct view *view)
 {
-       if (view->xwayland_surface->override_redirect)
-               return false;
        if (view->xwayland_surface->decorations !=
            WLR_XWAYLAND_SURFACE_DECORATIONS_ALL)
                return false;
@@ -89,7 +87,7 @@ static void unmap(struct view *view)
 {
        view->mapped = false;
        wl_list_remove(&view->commit.link);
-       view_focus(next_toplevel(view));
+       view_focus(view_next(view));
 }
 
 static const struct view_impl xwl_view_impl = {