layout: Added sticky implementation for split windows 79/29679/2
authorMarius Vlad <marius.vlad@collabora.com>
Mon, 12 Feb 2024 12:13:05 +0000 (14:13 +0200)
committerMarius Vlad <marius.vlad@collabora.com>
Thu, 22 Feb 2024 13:51:33 +0000 (13:51 +0000)
This continues implementing the sticky window functionality to
be able to keep a window, set as sticky, always displayed while
having the ability to activate/switch to other windows.

This could be useful in a handful of sitauations like keeping the nav
application on, while activing other windows.

Bug-AGL: SPEC-4839
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: I94c835c0d8f9f7e334e4c75389d78bd267b71a87

src/ivi-compositor.h
src/layout.c
src/shell.c

index 90ec4d9..5250dba 100644 (file)
@@ -243,6 +243,7 @@ struct pending_app_tile {
        struct pending_app base;
        uint32_t orientation;
        uint32_t width;
+       int32_t sticky;
 };
 
 struct ivi_desktop_surface {
@@ -295,6 +296,7 @@ struct ivi_surface {
        struct wl_list link;
        int focus_count;
        uint32_t orientation;
+       int32_t sticky;
 
        struct {
                enum ivi_surface_flags flags;
@@ -544,6 +546,7 @@ ivi_layout_reset_split_surfaces(struct ivi_compositor *ivi);
 
 void
 _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *output,
-                            uint32_t orientation, uint32_t width, bool to_activate);
+                            uint32_t orientation, uint32_t width, int32_t sticky,
+                            bool to_activate);
 
 #endif
index 7a2c9ac..a2cf48c 100644 (file)
@@ -286,7 +286,8 @@ ivi_layout_activate_complete(struct ivi_output *output,
                                         woutput->y + output->area.y);
 
        /* reset any previous orientation */
-       if (surf->orientation != AGL_SHELL_TILE_ORIENTATION_NONE) {
+       if (surf->orientation != AGL_SHELL_TILE_ORIENTATION_NONE &&
+           !surf->sticky) {
                weston_log("%s() resetting itself to none orientation\n", __func__);
                surf->orientation = AGL_SHELL_TILE_ORIENTATION_NONE;
                weston_desktop_surface_set_orientation(surf->dsurface,
@@ -317,7 +318,9 @@ ivi_layout_activate_complete(struct ivi_output *output,
 
        if (output->active) {
                /* keep the background surface mapped at all times */
-               if (output->active->role != IVI_SURFACE_ROLE_BACKGROUND) {
+               if (output->active->role != IVI_SURFACE_ROLE_BACKGROUND &&
+                   !output->active->sticky) {
+
                        output->active->view->is_mapped = false;
                        output->active->view->surface->is_mapped = false;
 
@@ -1036,11 +1039,13 @@ void
 ivi_layout_reset_split_surfaces(struct ivi_compositor *ivi)
 {
        struct ivi_surface *ivisurf;
+       struct ivi_surface *found_ivi_surf = NULL;
        bool found_split_surface = false;
        struct ivi_output *output = NULL;
 
        wl_list_for_each(ivisurf, &ivi->surfaces, link) {
                if (ivisurf->orientation != AGL_SHELL_TILE_ORIENTATION_NONE) {
+                       found_ivi_surf = ivisurf;
                        found_split_surface = true;
                        break;
                }
@@ -1049,7 +1054,11 @@ ivi_layout_reset_split_surfaces(struct ivi_compositor *ivi)
        if (!found_split_surface)
                return;
 
-       output = ivisurf->current_completed_output;
+       output = found_ivi_surf->current_completed_output;
+
+       if (found_ivi_surf->sticky)
+               return;
+
        if (output->previous_active && output->background != output->previous_active) {
                struct weston_view *ev = output->previous_active->view;
                struct weston_output *woutput = output->output;
@@ -1068,7 +1077,7 @@ ivi_layout_reset_split_surfaces(struct ivi_compositor *ivi)
                weston_layer_entry_insert(&ivi->normal.view_list, &ev->layer_link);
 
                _ivi_set_shell_surface_split(output->previous_active, NULL, 0,
-                                            AGL_SHELL_TILE_ORIENTATION_NONE, false);
+                                            AGL_SHELL_TILE_ORIENTATION_NONE, false, false);
 
                if (output->active == ivisurf) {
                        output->active = output->previous_active;
@@ -1076,7 +1085,7 @@ ivi_layout_reset_split_surfaces(struct ivi_compositor *ivi)
        }
 
        _ivi_set_shell_surface_split(ivisurf, NULL, 0,
-                                    AGL_SHELL_TILE_ORIENTATION_NONE, false);
+                                    AGL_SHELL_TILE_ORIENTATION_NONE, false, false);
 }
 
 void
@@ -1128,6 +1137,12 @@ ivi_layout_activate_by_surf(struct ivi_output *output, struct ivi_surface *surf)
                return;
        }
 
+       if (surf->sticky && surf->role == IVI_SURFACE_ROLE_TILE) {
+               weston_log("Application %s is already active on output %s (split role)\n",
+                               app_id, output->output->name);
+               return;
+       }
+
        if (ivi_layout_surface_is_split_or_fullscreen(surf)) {
                weston_log("Application %s is fullscreen or split on output %s\n",
                                app_id, output->output->name);
index eb29316..2e27742 100644 (file)
@@ -52,6 +52,9 @@ create_black_curtain_view(struct ivi_output *output);
 static uint32_t
 reverse_orientation(uint32_t orientation);
 
+const char *
+split_orientation_to_string(uint32_t orientation);
+
 void
 agl_shell_desktop_advertise_application_id(struct ivi_compositor *ivi,
                                           struct ivi_surface *surface)
@@ -662,7 +665,7 @@ ivi_check_pending_desktop_surface(struct ivi_surface *surface)
                        }
                        _ivi_set_shell_surface_split(papp->ioutput->active, NULL,
                                        reverse_orientation(papp_tile->orientation),
-                                       width_prev_app, false);
+                                       width_prev_app, false, false);
                }
 
                surface->role = IVI_SURFACE_ROLE_TILE;
@@ -670,7 +673,8 @@ ivi_check_pending_desktop_surface(struct ivi_surface *surface)
                wl_list_insert(&surface->ivi->surfaces, &surface->link);
 
                _ivi_set_shell_surface_split(surface, papp->ioutput,
-                               papp_tile->orientation, papp_tile->width, true);
+                                            papp_tile->orientation, papp_tile->width,
+                                            papp_tile->sticky, true);
 
                /* remove it from pending */
                wl_list_remove(&papp->link);
@@ -1776,6 +1780,27 @@ _ivi_set_pending_desktop_surface_split(struct wl_resource *output,
 }
 
 
+const char *
+split_orientation_to_string(uint32_t orientation)
+{
+       switch (orientation) {
+       case AGL_SHELL_TILE_ORIENTATION_LEFT:
+               return "tile_left";
+       break;
+       case AGL_SHELL_TILE_ORIENTATION_RIGHT:
+               return "tile_right";
+       break;
+       case AGL_SHELL_TILE_ORIENTATION_TOP:
+               return "title_top";
+       break;
+       case AGL_SHELL_TILE_ORIENTATION_BOTTOM:
+               return "tile_bottom";
+       break;
+       default:
+               return "none";
+       }
+}
+
 static uint32_t
 reverse_orientation(uint32_t orientation)
 {
@@ -1800,7 +1825,8 @@ reverse_orientation(uint32_t orientation)
 
 void
 _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *ioutput,
-                            uint32_t orientation, uint32_t width, bool to_activate)
+                            uint32_t orientation, uint32_t width, int32_t sticky,
+                            bool to_activate)
 {
        struct ivi_compositor *ivi = surface->ivi;
        struct weston_geometry geom = {};
@@ -1839,8 +1865,27 @@ _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *iou
                }
        break;
        case AGL_SHELL_TILE_ORIENTATION_NONE:
-               new_width = output->area.width;
-               new_height = output->area.height;
+               /* use the current_completed_output because the sticky window
+                * might have changed the output area */
+               new_width = surface->current_completed_output->area_activation.width;
+               new_height = surface->current_completed_output->area_activation.height;
+
+               if (new_width != output->area.width)
+                       output->area.width = new_width;
+
+               if (new_height != output->area.height)
+                       output->area.height = new_height;
+
+               weston_log("Adjusting activation area "
+                          "to %dX%d\n", output->area.width, output->area.height);
+
+               if (surface->sticky) {
+                       surface->sticky = 0;
+                       weston_log("Resetting sticky window\n");
+               }
+
+               surface->role = IVI_SURFACE_ROLE_DESKTOP;
+               weston_log("Resetting tile role to desktop\n");
        break;
        default:
                /* nothing */
@@ -1891,12 +1936,35 @@ _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *iou
                        ivi_shell_activate_surface(surface, ivi_seat, WESTON_ACTIVATE_FLAG_NONE);
        }
 
+
        weston_view_set_position(surface->view, x, y);
        weston_desktop_surface_set_size(surface->dsurface, new_width, new_height);
        weston_desktop_surface_set_orientation(surface->dsurface, orientation);
        surface->orientation = orientation;
 
        weston_compositor_schedule_repaint(ivi->compositor);
+
+       if (sticky)
+               surface->sticky = sticky;
+
+       if (orientation != AGL_SHELL_TILE_ORIENTATION_NONE) {
+               surface->role = IVI_SURFACE_ROLE_TILE;
+               weston_log("Found split orientation different that none, "
+                          "setting surface role to orientation tile\n");
+       }
+
+       if (surface->sticky) {
+               if (orientation == AGL_SHELL_TILE_ORIENTATION_LEFT ||
+                   orientation == AGL_SHELL_TILE_ORIENTATION_RIGHT)
+                       output->area.width -= new_width;
+
+               if (orientation == AGL_SHELL_TILE_ORIENTATION_TOP ||
+                   orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM)
+                       output->area.height -= new_height;
+
+               weston_log("Found sticky window, adjusting activation area "
+                          "to %dX%d\n", output->area.width, output->area.height);
+       }
 }
 
 static int
@@ -1944,6 +2012,8 @@ void shell_set_app_split(struct wl_client *client, struct wl_resource *res,
        if (output->previous_active && output->background != output->previous_active) {
                struct weston_view *ev = output->previous_active->view;
                int width_prev_app = 0;
+               const char *prev_app_id = 
+                       weston_desktop_surface_get_app_id(output->previous_active->dsurface);
 
                if (!weston_view_is_mapped(ev))
                        weston_view_update_transform(ev);
@@ -1967,9 +2037,13 @@ void shell_set_app_split(struct wl_client *client, struct wl_resource *res,
                                width_prev_app = output->area.width - width;
                }
 
+               weston_log("Setting previous application '%s' to orientation '%s' width %d, not sticky\n",
+                          prev_app_id, split_orientation_to_string(reverse_orientation(orientation)),
+                          width_prev_app);
+
                _ivi_set_shell_surface_split(output->previous_active, NULL,
                                             reverse_orientation(orientation),
-                                            width_prev_app, false);
+                                            width_prev_app, false, false);
 
                if (orientation == AGL_SHELL_TILE_ORIENTATION_NONE &&
                    output->active == surf) {
@@ -1977,7 +2051,10 @@ void shell_set_app_split(struct wl_client *client, struct wl_resource *res,
                }
        }
 
-       _ivi_set_shell_surface_split(surf, NULL, orientation, width, false);
+       weston_log("Setting application '%s' to orientation '%s' width %d, %s\n",
+                  app_id, split_orientation_to_string(orientation),
+                  width, sticky == 1 ? "sticky" : "not sticky");
+       _ivi_set_shell_surface_split(surf, NULL, orientation, width, sticky, false);
 }
 
 static void