agl-shell-desktop: Add the ability to hide client windows 01/24401/3
authorMarius Vlad <marius.vlad@collabora.com>
Mon, 6 Apr 2020 19:30:55 +0000 (22:30 +0300)
committerMarius Vlad <marius.vlad@collabora.com>
Tue, 12 May 2020 18:56:35 +0000 (21:56 +0300)
This would be particularly useful to pop-up kind of window(s).

It implements the 'deactivate_app' request. For the pop-up role we
just remove the view from the layer while for the desktop we store
the previous surface and re-use it if that's set. Otherwise we just
display the background surface.

As we now allow to hide client windows, we need to able to activate/show
them back so this also adds a slight modification to take care to handle
the pop-up role separately when calling the 'activate_app' request.

Bug-AGL: SPEC-3269

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: Iec5ccbe2815f4b0e32086fd49856f5f338147f79

protocol/agl-shell-desktop.xml
src/ivi-compositor.h
src/layout.c
src/shell.c

index 28b2756..6d53f92 100644 (file)
       <arg name="y" type="int"/>
       <arg name="output" type="object" interface="wl_output"/>
     </request>
+
+    <request name="deactivate_app">
+      <description summary="de-activate/hide window identified by app_id">
+        Ask the compositor to hide the toplevel window for window
+        management purposes. Depending on the window role, this request
+        will either display the previously active window (or the background
+        in case there's no previously activate surface) or temporarly (or
+        until a 'activate_app' is called upon) hide the surface. All
+        the surfaces are identifiable by using the app_id, and no actions are
+        taken in case the app_id is not/was not present.
+
+        See xdg_toplevel.set_app_id from the xdg-shell protocol for a
+        description of app_id.
+      </description>
+      <arg name="app_id" type="string"/>
+    </request>
   </interface>
 </protocol>
index bdd91ff..b76da85 100644 (file)
@@ -130,6 +130,7 @@ struct ivi_output {
        struct weston_geometry area;
 
        struct ivi_surface *active;
+       struct ivi_surface *previous_active;
 
        /* Temporary: only used during configuration */
        size_t add_len;
@@ -290,4 +291,7 @@ ivi_layout_panel_committed(struct ivi_surface *surface);
 void
 ivi_layout_popup_committed(struct ivi_surface *surface);
 
+void
+ivi_layout_deactivate(struct ivi_compositor *ivi, const char *app_id);
+
 #endif
index 55509e4..0e7aaaf 100644 (file)
@@ -206,6 +206,7 @@ ivi_layout_activate_complete(struct ivi_output *output,
 
                weston_layer_entry_remove(&output->active->view->layer_link);
        }
+       output->previous_active = output->active;
        output->active = surf;
 
        weston_layer_entry_insert(&ivi->normal.view_list, &view->layer_link);
@@ -313,12 +314,33 @@ ivi_layout_popup_committed(struct ivi_surface *surface)
        weston_layer_entry_insert(&ivi->popup.view_list, &view->layer_link);
 
        weston_view_update_transform(view);
-       weston_view_schedule_repaint(view);
+       weston_view_damage_below(view);
 
        wsurface->is_mapped = true;
        surface->view->is_mapped = true;
 }
 
+static void
+ivi_layout_popup_re_add(struct ivi_surface *surface)
+{
+       assert(surface->role == IVI_SURFACE_ROLE_POPUP);
+       struct weston_view *view = surface->view;
+       struct ivi_compositor *ivi = surface->ivi;
+
+       if (weston_view_is_mapped(view)) {
+               struct weston_desktop_surface *dsurface = surface->dsurface;
+               struct weston_surface *wsurface =
+                       weston_desktop_surface_get_surface(dsurface);
+
+               weston_layer_entry_remove(&view->layer_link);
+
+               wsurface->is_mapped = false;
+               view->is_mapped = false;
+       }
+
+       ivi_layout_popup_committed(surface);
+}
+
 void
 ivi_layout_panel_committed(struct ivi_surface *surface)
 {
@@ -408,6 +430,12 @@ ivi_layout_activate(struct ivi_output *output, const char *app_id)
 #ifdef AGL_COMP_DEBUG
        weston_log("Found app_id %s\n", app_id);
 #endif
+
+       if (surf->role == IVI_SURFACE_ROLE_POPUP) {
+               ivi_layout_popup_re_add(surf);
+               return;
+       }
+
        if (surf == output->active)
                return;
 
@@ -444,3 +472,75 @@ ivi_layout_activate(struct ivi_output *output, const char *app_id)
        }
 
 }
+
+static struct ivi_output *
+ivi_layout_get_output_from_surface(struct ivi_surface *surf)
+{
+       struct ivi_output *ivi_output = NULL;
+
+       switch (surf->role) {
+       case IVI_SURFACE_ROLE_DESKTOP:
+               if (surf->desktop.pending_output)
+                       ivi_output = surf->desktop.pending_output;
+               else
+                       ivi_output = surf->desktop.last_output;
+               break;
+       case IVI_SURFACE_ROLE_POPUP:
+               ivi_output = surf->popup.output;
+               break;
+       default:
+       case IVI_SURFACE_ROLE_BACKGROUND:
+       case IVI_SURFACE_ROLE_PANEL:
+       case IVI_SURFACE_ROLE_NONE:
+               break;
+       }
+
+       return ivi_output;
+}
+
+void
+ivi_layout_deactivate(struct ivi_compositor *ivi, const char *app_id)
+{
+       struct ivi_surface *surf;
+       struct ivi_output *ivi_output;
+
+       surf = ivi_find_app(ivi, app_id);
+       if (!surf)
+               return;
+
+       ivi_output = ivi_layout_get_output_from_surface(surf);
+       weston_log("deactiving %s\n", app_id);
+
+       if (surf->role == IVI_SURFACE_ROLE_DESKTOP) {
+               struct ivi_surface *previous_active;
+
+               previous_active = ivi_output->previous_active;
+               if (!previous_active) {
+                       /* we don't have a previous active it means we should
+                        * display the bg */
+                       if (ivi_output->active) {
+                               struct weston_view *view;
+
+                               view = ivi_output->active->view;
+                               view->is_mapped = false;
+                               view->surface->is_mapped = false;
+
+                               weston_layer_entry_remove(&view->layer_link);
+                               weston_output_damage(ivi_output->output);
+                       }
+               } else {
+                       struct weston_desktop_surface *dsurface;
+                       const char *previous_active_app_id;
+
+                       dsurface = previous_active->dsurface;
+                       previous_active_app_id =
+                               weston_desktop_surface_get_app_id(dsurface);
+                       ivi_layout_activate(ivi_output, previous_active_app_id);
+               }
+       } else if (surf->role == IVI_SURFACE_ROLE_POPUP) {
+               struct weston_view *view  = surf->view;
+
+               weston_layer_entry_remove(&view->layer_link);
+               weston_view_damage_below(view);
+       }
+}
index cf1214a..768b6d2 100644 (file)
@@ -522,6 +522,15 @@ shell_activate_app(struct wl_client *client,
        ivi_layout_activate(output, app_id);
 }
 
+static void
+shell_deactivate_app(struct wl_client *client,
+                  struct wl_resource *shell_res,
+                  const char *app_id)
+{
+       struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
+       ivi_layout_deactivate(dclient->ivi, app_id);
+}
+
 static const struct agl_shell_interface agl_shell_implementation = {
        .ready = shell_ready,
        .set_background = shell_set_background,
@@ -546,7 +555,8 @@ shell_desktop_set_app_property(struct wl_client *client,
 
 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
        .activate_app = shell_activate_app,
-       .set_app_property = shell_desktop_set_app_property
+       .set_app_property = shell_desktop_set_app_property,
+       .deactivate_app = shell_deactivate_app,
 };
 
 static void