shell: Add the ability to dynamically move application window 24/28724/3
authorMarius Vlad <marius.vlad@collabora.com>
Wed, 26 Apr 2023 06:48:40 +0000 (09:48 +0300)
committerMarius Vlad <marius.vlad@collabora.com>
Wed, 3 May 2023 15:46:19 +0000 (18:46 +0300)
So far, we could start an application on a different output, but
moving them back-and-worth wasn't really supported. This handles
a few use-cases like:

- move an application's window from one output to another
- install black curtain in case we no longer have any other surfaces
  on that output;
- deactivate and switch to the previous active window in case there's
  one available
- the activation is handled by the shell client, while deactivation
  is done implicitly by the compositor to simplify the shell client

This does a bit of rewording of a function that returns true whenever
we have only a single application window on a particular output.

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

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

index a8e6171..340f14f 100644 (file)
@@ -243,8 +243,9 @@ desktop_surface_added(struct weston_desktop_surface *dsurface, void *userdata)
 
 }
 
-static bool
-desktop_surface_check_last_surfaces(struct ivi_output *ivi_output, enum ivi_surface_role role)
+bool
+ivi_surface_count_one(struct ivi_output *ivi_output,
+                     enum ivi_surface_role role)
 {
        int count = 0;
        struct ivi_surface *surf;
@@ -331,8 +332,8 @@ desktop_surface_removed(struct weston_desktop_surface *dsurface, void *userdata)
        /* check if there's a last 'remote' surface and insert a black
         * surface view if there's no background set for that output
         */
-       if (desktop_surface_check_last_surfaces(output, IVI_SURFACE_ROLE_REMOTE) ||
-           desktop_surface_check_last_surfaces(output, IVI_SURFACE_ROLE_DESKTOP))
+       if (ivi_surface_count_one(output, IVI_SURFACE_ROLE_REMOTE) ||
+           ivi_surface_count_one(output, IVI_SURFACE_ROLE_DESKTOP))
                if (!output->background)
                        insert_black_curtain(output);
 
index fb5a0fa..857b816 100644 (file)
@@ -518,5 +518,8 @@ get_focused_output(struct weston_compositor *compositor);
 void
 shell_send_app_on_output(struct ivi_compositor *ivi, const char *app_id,
                         const char *output_name);
+bool
+ivi_surface_count_one(struct ivi_output *ivi_output,
+                     enum ivi_surface_role role);
 
 #endif
index b7ef788..ea293ca 100644 (file)
@@ -1116,7 +1116,8 @@ ivi_layout_deactivate(struct ivi_compositor *ivi, const char *app_id)
        weston_log("Deactiving %s, role %s\n", app_id,
                        ivi_layout_get_surface_role_name(surf));
 
-       if (surf->role == IVI_SURFACE_ROLE_DESKTOP) {
+       if (surf->role == IVI_SURFACE_ROLE_DESKTOP ||
+           surf->role == IVI_SURFACE_ROLE_REMOTE) {
                struct ivi_surface *previous_active;
 
                previous_active = ivi_output->previous_active;
index ac20b4f..07a7e98 100644 (file)
@@ -1711,15 +1711,46 @@ shell_set_app_output(struct wl_client *client, struct wl_resource *res,
        struct weston_output *woutput = weston_head_get_output(head);
        struct ivi_output *ioutput = to_ivi_output(woutput);
        struct ivi_surface *surf = ivi_find_app(ivi, app_id);
+       struct ivi_output *desktop_last_output = surf->desktop.last_output;
+       struct ivi_output *current_completed_output =
+               surf->current_completed_output;
 
        if (!app_id || !ioutput)
                return;
 
-       if (!surf || (surf && surf->role != IVI_SURFACE_ROLE_REMOTE)) {
+       /* handle the case we're not mapped at all */
+       if (!surf) {
                ivi_set_pending_desktop_surface_remote(ioutput, app_id);
                shell_send_app_on_output(ivi, app_id, woutput->name);
                return;
        }
+
+       if (surf->remote.output)
+               surf->hidden_layer_output = surf->remote.output;
+       else
+               surf->hidden_layer_output = desktop_last_output;
+       assert(surf->hidden_layer_output);
+
+       if (ivi_surface_count_one(current_completed_output, IVI_SURFACE_ROLE_REMOTE) ||
+           ivi_surface_count_one(current_completed_output, IVI_SURFACE_ROLE_DESKTOP)) {
+               if (!current_completed_output->background)
+                       insert_black_curtain(current_completed_output);
+       } else {
+               ivi_layout_deactivate(ivi, app_id);
+       }
+
+       /* update the remote output */
+       surf->remote.output = ioutput;
+
+       if (surf->role != IVI_SURFACE_ROLE_REMOTE) {
+               wl_list_remove(&surf->link);
+               wl_list_init(&surf->link);
+
+               surf->role = IVI_SURFACE_ROLE_NONE;
+               ivi_set_desktop_surface_remote(surf);
+       }
+
+       shell_send_app_on_output(ivi, app_id, woutput->name);
 }
 
 static void