xdg_toplevel_v6: Implement remaining part of xdg_toplevel_v6 08/295108/1
authorSeunghun Lee <shiin.lee@samsung.com>
Mon, 15 May 2023 06:57:00 +0000 (15:57 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Mon, 3 Jul 2023 03:14:35 +0000 (12:14 +0900)
This makes xdg_shell_v6 work properly.

Change-Id: I33ff81c5870aaf101471a7d68666e61d11d708be

include/libds/xdg_shell_v6.h
src/xdg_shell_v6/xdg_shell_v6.h
src/xdg_shell_v6/xdg_surface_v6.c
src/xdg_shell_v6/xdg_toplevel_v6.c

index 35a2d42..34916f6 100644 (file)
@@ -16,6 +16,19 @@ struct ds_xdg_surface_v6;
 
 struct ds_xdg_toplevel_v6;
 
+struct ds_xdg_toplevel_v6_event_request_move {
+    struct ds_xdg_toplevel_v6 *toplevel;
+    struct wl_resource *seat_resource;
+    uint32_t serial;
+};
+
+struct ds_xdg_toplevel_v6_event_request_resize {
+    struct ds_xdg_toplevel_v6 *toplevel;
+    struct wl_resource *seat_resource;
+    uint32_t serial;
+    uint32_t edges;
+};
+
 struct ds_xdg_shell_v6 *
 ds_xdg_shell_v6_create(struct wl_display *display);
 
@@ -45,6 +58,30 @@ ds_xdg_surface_v6_ping(struct ds_xdg_surface_v6 *surface);
 struct ds_surface *
 ds_xdg_surface_v6_get_surface(struct ds_xdg_surface_v6 *surface);
 
+void 
+ds_xdg_toplevel_v6_add_set_parent_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener);
+
+void
+ds_xdg_toplevel_v6_add_request_move_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener);
+
+void
+ds_xdg_toplevel_v6_add_request_resize_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener);
+
+void
+ds_xdg_toplevel_v6_add_request_maximize_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener);
+
+void
+ds_xdg_toplevel_v6_add_request_fullscreen_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener);
+
+void
+ds_xdg_toplevel_v6_add_request_minimize_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener);
+
 uint32_t ds_xdg_toplevel_v6_set_size(struct ds_xdg_toplevel_v6 *toplevel,
         int32_t width, int32_t height);
 
index 5bd7615..0e2ff52 100644 (file)
@@ -5,6 +5,7 @@
 #include <xdg-shell-unstable-v6-server-protocol.h>
 
 #include "libds/output.h"
+#include "libds/xdg_shell_v6.h"
 
 #include "surface.h"
 
@@ -71,9 +72,8 @@ struct ds_xdg_toplevel_v6
 {
     struct wl_resource *resource;
     struct ds_xdg_surface_v6 *base;
-    bool added;
 
-    struct ds_xdg_surface_v6 *parent;
+    struct ds_xdg_toplevel_v6 *parent;
     struct wl_listener parent_unmap;
 
     struct ds_xdg_toplevel_v6_state current, pending;
@@ -94,6 +94,8 @@ struct ds_xdg_toplevel_v6
         struct wl_signal set_title;
         struct wl_signal set_app_id;
     } events;
+
+    bool sent_initial_configure;
 };
 
 struct ds_xdg_popup
@@ -174,14 +176,20 @@ reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface);
 void
 create_xdg_toplevel_v6(struct ds_xdg_surface_v6 *surface, uint32_t id);
 
+void destroy_xdg_surface_v6_role(struct ds_xdg_surface_v6 *surface);
+
 void
 handle_xdg_surface_v6_commit(struct ds_surface *ds_surface);
 
 void
-handle_xdg_surface_v6_toplevel_committed(struct ds_xdg_surface_v6 *surface);
+handle_xdg_toplevel_v6_committed(struct ds_xdg_toplevel_v6 *toplevel);
 
 void
 send_xdg_toplevel_v6_configure(struct ds_xdg_surface_v6 *surface,
         struct ds_xdg_surface_v6_configure *configure);
 
+void reset_xdg_toplevel_v6(struct ds_xdg_toplevel_v6 *toplevel);
+
+void destroy_xdg_toplevel_v6(struct ds_xdg_toplevel_v6 *toplevel);
+
 #endif
index 37e7015..51742ed 100644 (file)
@@ -108,51 +108,60 @@ create_xdg_surface_v6(struct ds_xdg_client_v6 *client, struct ds_surface *ds_sur
 void
 unmap_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
 {
-    struct ds_xdg_surface_v6_configure *configure, *tmp;
+    surface->mapped = false;
+
+    wl_signal_emit_mutable(&surface->events.unmap, surface);
+}
 
-    // TODO handle popup
+void
+reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
+{
+    struct ds_xdg_surface_v6_configure *configure, *tmp;
 
-    if (surface->mapped)
-        wl_signal_emit_mutable(&surface->events.unmap, surface);
+    surface->configured = false;
 
     switch (surface->role) {
         case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL:
-            if (surface->toplevel->parent) {
-                wl_list_remove(&surface->toplevel->parent_unmap.link);
-                surface->toplevel->parent = NULL;
-            }
-            free(surface->toplevel->title);
-            surface->toplevel->title = NULL;
-            free(surface->toplevel->app_id);
-            surface->toplevel->app_id = NULL;
+            reset_xdg_toplevel_v6(surface->toplevel);
             break;
         case DS_XDG_SURFACE_V6_ROLE_POPUP:
             // TODO
             break;
         case DS_XDG_SURFACE_V6_ROLE_NONE:
-            DS_ASSERT_NOT_REACHED();
+            break;
     }
 
-    wl_list_for_each_safe(configure, tmp, &surface->configure_list, link)
+    wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
         xdg_surface_v6_configure_destroy(configure);
+    }
 
     if (surface->configure_idle) {
         wl_event_source_remove(surface->configure_idle);
         surface->configure_idle = NULL;
     }
-
-    surface->configured = false;
-    surface->mapped = false;
 }
 
 void
-reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
+destroy_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
 {
-    struct ds_xdg_toplevel_v6_requested *req;
+    destroy_xdg_surface_v6_role(surface);
+
+    wl_list_remove(&surface->link);
+    wl_list_remove(&surface->listener.surface_destroy.link);
+    wl_list_remove(&surface->listener.surface_commit.link);
+
+    wl_resource_set_user_data(surface->resource, NULL);
+    free(surface);
+}
 
-    if (surface->role != DS_XDG_SURFACE_V6_ROLE_NONE)
+void
+destroy_xdg_surface_v6_role(struct ds_xdg_surface_v6 *surface)
+{
+    if (surface->configured && surface->mapped)
         unmap_xdg_surface_v6(surface);
 
+    reset_xdg_surface_v6(surface);
+
     if (surface->added) {
         wl_signal_emit_mutable(&surface->events.destroy, surface);
         surface->added = false;
@@ -160,19 +169,13 @@ reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
 
     switch (surface->role) {
         case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL:
-            wl_resource_set_user_data(surface->toplevel->resource, NULL);
-            surface->toplevel->resource = NULL;
-            req = &surface->toplevel->requested;
-            if (req->fullscreen_output)
-                wl_list_remove(&req->fullscreen_output_destroy.link);
-            free(surface->toplevel);
+            destroy_xdg_toplevel_v6(surface->toplevel);
             surface->toplevel = NULL;
             break;
         case DS_XDG_SURFACE_V6_ROLE_POPUP:
             // TODO
             break;
-        case DS_XDG_SURFACE_V6_ROLE_NONE:
-            // This space is intentionally left blank
+        default:
             break;
     }
 
@@ -180,22 +183,6 @@ reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
 }
 
 void
-destroy_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
-{
-    reset_xdg_surface_v6(surface);
-
-    wl_resource_set_user_data(surface->resource, NULL);
-
-    ds_surface_reset_role_data(surface->ds_surface);
-
-    wl_list_remove(&surface->link);
-    wl_list_remove(&surface->listener.surface_destroy.link);
-    wl_list_remove(&surface->listener.surface_commit.link);
-
-    free(surface);
-}
-
-void
 handle_xdg_surface_v6_commit(struct ds_surface *ds_surface)
 {
     struct ds_xdg_surface_v6 *surface;
@@ -208,8 +195,7 @@ handle_xdg_surface_v6_commit(struct ds_surface *ds_surface)
             // inert toplevel or popup
             break;
         case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL:
-            handle_xdg_surface_v6_toplevel_committed(surface);
-            // TODO
+            handle_xdg_toplevel_v6_committed(surface->toplevel);
             break;
         case DS_XDG_SURFACE_V6_ROLE_POPUP:
             // TODO
index 7e5426a..d15eee1 100644 (file)
@@ -13,6 +13,53 @@ static const struct ds_surface_role xdg_toplevel_v6_surface_role =
 static const struct zxdg_toplevel_v6_interface xdg_toplevel_v6_impl;
 
 static void xdg_toplevel_v6_handle_resource_destroy(struct wl_resource *resource);
+static void xdg_toplevel_v6_set_parent(struct ds_xdg_toplevel_v6 *toplevel,
+        struct ds_xdg_toplevel_v6 *parent);
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_set_parent_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&toplevel->events.set_parent, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_move_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&toplevel->events.request_move, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_resize_listener(struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&toplevel->events.request_resize, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_maximize_listener(
+        struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&toplevel->events.request_maximize, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_fullscreen_listener(
+        struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&toplevel->events.request_fullscreen, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_minimize_listener(
+        struct ds_xdg_toplevel_v6 *toplevel,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&toplevel->events.request_minimize, listener);
+}
 
 WL_EXPORT uint32_t
 ds_xdg_toplevel_v6_set_size(struct ds_xdg_toplevel_v6 *toplevel,
@@ -106,15 +153,14 @@ create_xdg_toplevel_v6(struct ds_xdg_surface_v6 *surface, uint32_t id)
 }
 
 void
-handle_xdg_surface_v6_toplevel_committed(struct ds_xdg_surface_v6 *surface)
+handle_xdg_toplevel_v6_committed(struct ds_xdg_toplevel_v6 *toplevel)
 {
-    if (!surface->toplevel->added) {
-        ds_xdg_surface_v6_schedule_configure(surface);
-        surface->toplevel->added = true;
-        return;
-    }
+    toplevel->current = toplevel->pending;
 
-    surface->toplevel->current = surface->toplevel->pending;
+    if (!toplevel->sent_initial_configure) {
+        ds_xdg_surface_v6_schedule_configure(toplevel->base);
+        toplevel->sent_initial_configure = true;
+    }
 }
 
 void
@@ -177,9 +223,36 @@ error_out:
 }
 
 void
-destroy_xdg_toplevel_v6(struct ds_xdg_surface_v6 *xdg_surface_v6)
+destroy_xdg_toplevel_v6(struct ds_xdg_toplevel_v6 *toplevel)
 {
-    reset_xdg_surface_v6(xdg_surface_v6);
+    wl_resource_set_user_data(toplevel->resource, NULL);
+    free(toplevel);
+}
+
+void
+reset_xdg_toplevel_v6(struct ds_xdg_toplevel_v6 *toplevel)
+{
+    if (toplevel->parent) {
+        wl_list_remove(&toplevel->parent_unmap.link);
+        toplevel->parent = NULL;
+    }
+
+    free(toplevel->title);
+    toplevel->title = NULL;
+
+    free(toplevel->app_id);
+    toplevel->app_id = NULL;
+
+    if (toplevel->requested.fullscreen_output) {
+        wl_list_remove(&toplevel->requested.fullscreen_output_destroy.link);
+        toplevel->requested.fullscreen_output = NULL;
+    }
+
+    toplevel->requested.fullscreen = false;
+    toplevel->requested.maximized = false;
+    toplevel->requested.minimized = false;
+
+    toplevel->sent_initial_configure = false;
 }
 
 static void
@@ -193,7 +266,16 @@ static void
 xdg_toplevel_v6_handle_set_parent(struct wl_client *client,
         struct wl_resource *resource, struct wl_resource *parent_resource)
 {
-    // TODO
+    struct ds_xdg_toplevel_v6 *toplevel, *parent = NULL;
+
+    toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
+    if (parent_resource)
+        parent = wl_resource_get_user_data(parent_resource);
+
+    xdg_toplevel_v6_set_parent(toplevel, parent);
 }
 
 static void
@@ -204,6 +286,9 @@ xdg_toplevel_v6_handle_set_title(struct wl_client *client,
     char *tmp;
 
     toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
     tmp = strdup(title);
     if (!tmp) {
         wl_resource_post_no_memory(resource);
@@ -225,6 +310,9 @@ xdg_toplevel_v6_handle_set_app_id(struct wl_client *client,
     char *tmp;
 
     toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
     tmp = strdup(app_id);
     if (!tmp) {
         wl_resource_post_no_memory(resource);
@@ -251,7 +339,25 @@ xdg_toplevel_v6_handle_move(struct wl_client *client,
         struct wl_resource *resource, struct wl_resource *seat_resource,
         uint32_t serial)
 {
-    // TODO
+    struct ds_xdg_toplevel_v6 *toplevel;
+
+    toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
+    if (!toplevel->base->configured) {
+        wl_resource_post_error(toplevel->base->resource,
+                ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+                "surface has not been configured yet");
+        return;
+    }
+
+    struct ds_xdg_toplevel_v6_event_request_move event = {
+        .toplevel = toplevel,
+        .seat_resource = seat_resource,
+        .serial = serial,
+    };
+    wl_signal_emit_mutable(&toplevel->events.request_move, &event);
 }
 
 static void
@@ -259,7 +365,26 @@ xdg_toplevel_v6_handle_resize(struct wl_client *client,
         struct wl_resource *resource, struct wl_resource *seat_resource,
         uint32_t serial, uint32_t edges)
 {
-    // TODO
+    struct ds_xdg_toplevel_v6 *toplevel;
+
+    toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
+    if (!toplevel->base->configured) {
+        wl_resource_post_error(toplevel->base->resource,
+                ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+                "surface has not been configured yet");
+        return;
+    }
+
+    struct ds_xdg_toplevel_v6_event_request_resize event = {
+        .toplevel = toplevel,
+        .seat_resource = seat_resource,
+        .serial = serial,
+        .edges = edges,
+    };
+    wl_signal_emit_mutable(&toplevel->events.request_resize, &event);
 }
 
 static void
@@ -269,6 +394,9 @@ xdg_toplevel_v6_handle_set_max_size(struct wl_client *client,
     struct ds_xdg_toplevel_v6 *toplevel;
 
     toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
     toplevel->pending.max_width = width;
     toplevel->pending.max_height = height;
 }
@@ -280,6 +408,9 @@ xdg_toplevel_v6_handle_set_min_size(struct wl_client *client,
     struct ds_xdg_toplevel_v6 *toplevel;
 
     toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
     toplevel->pending.min_width = width;
     toplevel->pending.min_height = height;
 }
@@ -291,9 +422,11 @@ xdg_toplevel_v6_handle_set_maximized(struct wl_client *client,
     struct ds_xdg_toplevel_v6 *toplevel;
 
     toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
     toplevel->requested.maximized = true;
     wl_signal_emit_mutable(&toplevel->events.request_maximize, toplevel);
-    ds_xdg_surface_v6_schedule_configure(toplevel->base);
 }
 
 static void
@@ -303,23 +436,41 @@ xdg_toplevel_v6_handle_unset_maximized(struct wl_client *client,
     struct ds_xdg_toplevel_v6 *toplevel;
 
     toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
     toplevel->requested.maximized = false;
     wl_signal_emit_mutable(&toplevel->events.request_maximize, toplevel);
-    ds_xdg_surface_v6_schedule_configure(toplevel->base);
 }
 
 static void
 xdg_toplevel_v6_handle_set_fullscreen(struct wl_client *client,
         struct wl_resource *resource, struct wl_resource  *output_resource)
 {
-    // TODO
+    struct ds_xdg_toplevel_v6 *toplevel;
+
+    toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
+    // TODO get a ds_output from an output_resource
+
+    toplevel->requested.fullscreen = true;
+    wl_signal_emit_mutable(&toplevel->events.request_fullscreen, toplevel);
 }
 
 static void
 xdg_toplevel_v6_handle_unset_fullscreen(struct wl_client *client,
         struct wl_resource *resource)
 {
-    // TODO
+    struct ds_xdg_toplevel_v6 *toplevel;
+
+    toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
+    toplevel->requested.fullscreen = false;
+    wl_signal_emit_mutable(&toplevel->events.request_fullscreen, toplevel);
 }
 
 static void
@@ -329,6 +480,9 @@ xdg_toplevel_v6_handle_set_minimized(struct wl_client *client,
     struct ds_xdg_toplevel_v6 *toplevel;
 
     toplevel = wl_resource_get_user_data(resource);
+    if (!toplevel)
+        return;
+
     toplevel->requested.minimized = true;
     wl_signal_emit_mutable(&toplevel->events.request_maximize, toplevel);
 }
@@ -360,5 +514,42 @@ xdg_toplevel_v6_handle_resource_destroy(struct wl_resource *resource)
     if (!toplevel)
         return;
 
-    destroy_xdg_toplevel_v6(toplevel->base);
+    destroy_xdg_surface_v6_role(toplevel->base);
+}
+
+static void
+xdg_toplevel_v6_handle_parent_unmap(struct wl_listener *listener, void *data)
+{
+    struct ds_xdg_toplevel_v6 *toplevel;
+
+    toplevel = wl_container_of(listener, toplevel, parent_unmap);
+    xdg_toplevel_v6_set_parent(toplevel, toplevel->parent->parent);
+}
+
+static void
+xdg_toplevel_v6_set_parent(struct ds_xdg_toplevel_v6 *toplevel,
+        struct ds_xdg_toplevel_v6 *parent)
+{
+    struct ds_xdg_toplevel_v6 *iter = parent;
+
+    while (iter) {
+        if (iter == toplevel)
+            return;
+        iter = iter->parent;
+    }
+
+    if (toplevel->parent)
+        wl_list_remove(&toplevel->parent_unmap.link);
+
+    if (parent && parent->base->mapped) {
+        toplevel->parent = parent;
+        toplevel->parent_unmap.notify = xdg_toplevel_v6_handle_parent_unmap;
+        wl_signal_add(&toplevel->parent->base->events.unmap,
+                &toplevel->parent_unmap);
+    }
+    else {
+        toplevel->parent = NULL;
+    }
+
+    wl_signal_emit_mutable(&toplevel->events.set_parent, NULL);
 }