[mutter/wayland] wayland: Add back wl_shell support



commit 86c1c3024526e479c2e65dee896757549d346c1e
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Feb 28 00:18:42 2014 -0500

    wayland: Add back wl_shell support

 src/wayland/meta-wayland-pointer.c  |   15 +--
 src/wayland/meta-wayland-surface.c  |  307 ++++++++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-surface.h  |    4 +
 src/wayland/meta-wayland-versions.h |    4 +-
 4 files changed, 310 insertions(+), 20 deletions(-)
---
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 21e41bb..e0c9ad2 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -49,7 +49,6 @@
 
 #include "meta-wayland-pointer.h"
 #include "meta-wayland-private.h"
-#include "xdg-shell-server-protocol.h"
 
 #include <string.h>
 
@@ -530,14 +529,7 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
 
   wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link)
     {
-      MetaWaylandSurfaceExtension *xdg_popup = &popup->surface->xdg_popup;
-      struct wl_client *client = wl_resource_get_client (xdg_popup->resource);
-      struct wl_display *display = wl_client_get_display (client);
-      uint32_t serial;
-
-      serial = wl_display_next_serial (display);
-
-      xdg_popup_send_popup_done (xdg_popup->resource, serial);
+      meta_wayland_surface_popup_done (popup->surface);
       wl_list_remove (&popup->surface_destroy_listener.link);
       wl_list_remove (&popup->link);
       g_slice_free (MetaWaylandPopup, popup);
@@ -597,7 +589,10 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
   popup->grab = grab;
   popup->surface = surface;
   popup->surface_destroy_listener.notify = on_popup_surface_destroy;
-  wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
+  if (surface->xdg_popup.resource)
+    wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
+  else if (surface->wl_shell_surface.resource)
+    wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
 
   wl_list_insert (&grab->all_popups, &popup->link);
       
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 0c5c711..0c67104 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -825,7 +825,7 @@ xdg_surface_move (struct wl_client *client,
 }
 
 static MetaGrabOp
-grab_op_for_edge (int edge)
+grab_op_for_xdg_surface_resize_edge (int edge)
 {
   switch (edge)
     {
@@ -867,7 +867,7 @@ xdg_surface_resize (struct wl_client *client,
       seat->pointer.focus_surface != surface)
     return;
 
-  begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));
+  begin_grab_op_on_surface (surface, seat, grab_op_for_xdg_surface_resize_edge (edges));
 }
 
 static void
@@ -1100,6 +1100,267 @@ bind_xdg_shell (struct wl_client *client,
 }
 
 static void
+wl_shell_surface_destructor (struct wl_resource *resource)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  destroy_surface_extension (wl_shell_surface);
+}
+
+static void
+wl_shell_surface_pong (struct wl_client *client,
+                       struct wl_resource *resource,
+                       uint32_t serial)
+{
+  MetaDisplay *display = meta_get_display ();
+
+  meta_display_pong_for_serial (display, serial);
+}
+
+static void
+wl_shell_surface_move (struct wl_client *client,
+                       struct wl_resource *resource,
+                       struct wl_resource *seat_resource,
+                       uint32_t serial)
+{
+  MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  if (seat->pointer.button_count == 0 ||
+      seat->pointer.grab_serial != serial ||
+      seat->pointer.focus_surface != surface)
+    return;
+
+  begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING);
+}
+
+static MetaGrabOp
+grab_op_for_wl_shell_surface_resize_edge (int edge)
+{
+  switch (edge)
+    {
+    case WL_SHELL_SURFACE_RESIZE_TOP_LEFT:
+      return META_GRAB_OP_RESIZING_NW;
+    case WL_SHELL_SURFACE_RESIZE_TOP:
+      return META_GRAB_OP_RESIZING_N;
+    case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
+      return META_GRAB_OP_RESIZING_NE;
+    case WL_SHELL_SURFACE_RESIZE_RIGHT:
+      return META_GRAB_OP_RESIZING_E;
+    case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
+      return META_GRAB_OP_RESIZING_SE;
+    case WL_SHELL_SURFACE_RESIZE_BOTTOM:
+      return META_GRAB_OP_RESIZING_S;
+    case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
+      return META_GRAB_OP_RESIZING_SW;
+    case WL_SHELL_SURFACE_RESIZE_LEFT:
+      return META_GRAB_OP_RESIZING_W;
+    default:
+      g_warning ("invalid edge: %d", edge);
+      return META_GRAB_OP_NONE;
+    }
+}
+
+static void
+wl_shell_surface_resize (struct wl_client *client,
+                         struct wl_resource *resource,
+                         struct wl_resource *seat_resource,
+                         uint32_t serial,
+                         uint32_t edges)
+{
+  MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  if (seat->pointer.button_count == 0 ||
+      seat->pointer.grab_serial != serial ||
+      seat->pointer.focus_surface != surface)
+    return;
+
+  begin_grab_op_on_surface (surface, seat, grab_op_for_wl_shell_surface_resize_edge (edges));
+}
+
+typedef enum {
+  SURFACE_STATE_TOPLEVEL,
+  SURFACE_STATE_FULLSCREEN,
+  SURFACE_STATE_MAXIMIZED,
+} SurfaceState;
+
+static void
+wl_shell_surface_set_state (MetaWaylandSurface *surface,
+                            SurfaceState        state)
+{
+  if (state == SURFACE_STATE_FULLSCREEN)
+    meta_window_make_fullscreen (surface->window);
+  else
+    meta_window_unmake_fullscreen (surface->window);
+
+  if (state == SURFACE_STATE_MAXIMIZED)
+    meta_window_maximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
+  else
+    meta_window_unmaximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
+}
+
+static void
+wl_shell_surface_set_toplevel (struct wl_client *client,
+                               struct wl_resource *resource)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
+}
+
+static void
+wl_shell_surface_set_transient (struct wl_client *client,
+                                struct wl_resource *resource,
+                                struct wl_resource *parent_resource,
+                                int32_t x,
+                                int32_t y,
+                                uint32_t flags)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+  MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
+
+  wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
+
+  meta_window_set_transient_for (surface->window, parent_surf->window);
+  meta_window_move (surface->window, FALSE,
+                    parent_surf->window->rect.x + x,
+                    parent_surf->window->rect.y + y);
+  surface->window->placed = TRUE;
+}
+
+static void
+wl_shell_surface_set_fullscreen (struct wl_client *client,
+                                 struct wl_resource *resource,
+                                 uint32_t method,
+                                 uint32_t framerate,
+                                 struct wl_resource *output)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  wl_shell_surface_set_state (surface, SURFACE_STATE_FULLSCREEN);
+}
+
+static void
+wl_shell_surface_set_popup (struct wl_client *client,
+                            struct wl_resource *resource,
+                            struct wl_resource *seat_resource,
+                            uint32_t serial,
+                            struct wl_resource *parent_resource,
+                            int32_t x,
+                            int32_t y,
+                            uint32_t flags)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+  MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
+  MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
+
+  wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
+
+  meta_window_set_transient_for (surface->window, parent_surf->window);
+  meta_window_move (surface->window, FALSE,
+                    parent_surf->window->rect.x + x,
+                    parent_surf->window->rect.y + y);
+  surface->window->placed = TRUE;
+
+  meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
+}
+
+static void
+wl_shell_surface_set_maximized (struct wl_client *client,
+                                struct wl_resource *resource,
+                                struct wl_resource *output)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  wl_shell_surface_set_state (surface, SURFACE_STATE_MAXIMIZED);
+}
+
+static void
+wl_shell_surface_set_title (struct wl_client *client,
+                            struct wl_resource *resource,
+                            const char *title)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  meta_window_set_title (surface->window, title);
+}
+
+static void
+wl_shell_surface_set_class (struct wl_client *client,
+                            struct wl_resource *resource,
+                            const char *class_)
+{
+  MetaWaylandSurfaceExtension *wl_shell_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (wl_shell_surface, surface, wl_shell_surface);
+
+  meta_window_set_wm_class (surface->window, class_, class_);
+}
+
+static const struct wl_shell_surface_interface meta_wayland_wl_shell_surface_interface = {
+  wl_shell_surface_pong,
+  wl_shell_surface_move,
+  wl_shell_surface_resize,
+  wl_shell_surface_set_toplevel,
+  wl_shell_surface_set_transient,
+  wl_shell_surface_set_fullscreen,
+  wl_shell_surface_set_popup,
+  wl_shell_surface_set_maximized,
+  wl_shell_surface_set_title,
+  wl_shell_surface_set_class,
+};
+
+static void
+wl_shell_get_shell_surface (struct wl_client *client,
+                            struct wl_resource *resource,
+                            uint32_t id,
+                            struct wl_resource *surface_resource)
+{
+  MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+
+  if (!create_surface_extension (&surface->wl_shell_surface, client, surface_resource, resource, id,
+                                 META_WL_SHELL_SURFACE_VERSION,
+                                 &wl_shell_surface_interface,
+                                 &meta_wayland_wl_shell_surface_interface,
+                                 wl_shell_surface_destructor))
+    {
+      wl_resource_post_error (surface_resource,
+                              WL_DISPLAY_ERROR_INVALID_OBJECT,
+                              "wl_shell::get_shell_surface already requested");
+      return;
+    }
+
+  meta_wayland_surface_make_toplevel (surface);
+  surface->window = meta_window_wayland_new (meta_get_display (), surface);
+}
+
+static const struct wl_shell_interface meta_wayland_wl_shell_interface = {
+  wl_shell_get_shell_surface,
+};
+
+static void
+bind_wl_shell (struct wl_client *client,
+               void             *data,
+               uint32_t          version,
+               uint32_t          id)
+{
+  struct wl_resource *resource;
+
+  resource = wl_resource_create (client, &wl_shell_interface,
+                                 MIN (META_WL_SHELL_VERSION, version), id);
+  wl_resource_set_implementation (resource, &meta_wayland_wl_shell_interface, data, NULL);
+}
+
+static void
 gtk_surface_destructor (struct wl_resource *resource)
 {
   MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
@@ -1487,6 +1748,11 @@ meta_wayland_init_shell (MetaWaylandCompositor *compositor)
     g_error ("Failed to register a global xdg-shell object");
 
   if (wl_global_create (compositor->wayland_display,
+                       &wl_shell_interface, 1,
+                       compositor, bind_wl_shell) == NULL)
+    g_error ("Failed to register a global wl-shell object");
+
+  if (wl_global_create (compositor->wayland_display,
                        &gtk_shell_interface,
                        META_GTK_SHELL_VERSION,
                        compositor, bind_gtk_shell) == NULL)
@@ -1507,6 +1773,9 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
   if (surface->xdg_surface.resource)
     xdg_surface_send_configure (surface->xdg_surface.resource,
                                 new_width, new_height);
+  else if (surface->wl_shell_surface.resource)
+    wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
+                                     0, new_width, new_height);
 }
 
 void
@@ -1527,16 +1796,23 @@ void
 meta_wayland_surface_ping (MetaWaylandSurface *surface,
                            guint32             serial)
 {
-  struct wl_client *client = wl_resource_get_client (surface->resource);
-  struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
+  if (surface->xdg_surface.resource)
+    {
+      struct wl_client *client = wl_resource_get_client (surface->resource);
+      struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
+
+      if (xdg_shell == NULL)
+        {
+          g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
+          return;
+        }
 
-  if (xdg_shell == NULL)
+      xdg_shell_send_ping (xdg_shell, serial);
+    }
+  else if (surface->wl_shell_surface.resource)
     {
-      g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
-      return;
+      wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
     }
-
-  xdg_shell_send_ping (xdg_shell, serial);
 }
 
 void
@@ -1545,3 +1821,16 @@ meta_wayland_surface_delete (MetaWaylandSurface *surface)
   if (surface->xdg_surface.resource)
     xdg_surface_send_delete (surface->xdg_surface.resource);
 }
+
+void
+meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
+{
+  struct wl_client *client = wl_resource_get_client (surface->resource);
+  struct wl_display *display = wl_client_get_display (client);
+  uint32_t serial = wl_display_next_serial (display);
+
+  if (surface->xdg_popup.resource)
+    xdg_popup_send_popup_done (surface->xdg_popup.resource, serial);
+  else if (surface->wl_shell_surface.resource)
+    wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource);
+}
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 9e12451..e0203f5 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -86,6 +86,7 @@ struct _MetaWaylandSurface
   MetaWindow *window;
   MetaWaylandSurfaceExtension xdg_surface;
   MetaWaylandSurfaceExtension xdg_popup;
+  MetaWaylandSurfaceExtension wl_shell_surface;
   MetaWaylandSurfaceExtension gtk_surface;
   MetaWaylandSurfaceExtension subsurface;
 
@@ -132,4 +133,7 @@ void                meta_wayland_surface_ping (MetaWaylandSurface *surface,
                                                guint32             serial);
 void                meta_wayland_surface_delete (MetaWaylandSurface *surface);
 
+void                meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
+
+
 #endif
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index e2d608c..17d8895 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -37,6 +37,7 @@
 /* Global/master objects (version exported by wl_registry and negotiated through bind) */
 #define META_WL_COMPOSITOR_VERSION          3
 #define META_WL_DATA_DEVICE_MANAGER_VERSION 1
+#define META_WL_SHELL_VERSION               1
 #define META_WL_SEAT_VERSION                2 /* 3 not implemented yet */
 #define META_WL_OUTPUT_VERSION              2
 #define META_XSERVER_VERSION                1
@@ -52,9 +53,10 @@
 #define META_WL_KEYBOARD_VERSION            2 /* from wl_seat; 3 not implemented yet */
 #define META_WL_TOUCH_VERSION               0 /* from wl_seat; wl_touch not supported */
 #define META_WL_REGION_VERSION              1 /* from wl_compositor */
-#define META_GTK_SURFACE_VERSION            1 /* from gtk_shell */
 #define META_XDG_SURFACE_VERSION            1 /* from xdg_shell */
 #define META_XDG_POPUP_VERSION              1 /* from xdg_shell */
+#define META_WL_SHELL_SURFACE_VERSION       1 /* from wl_shell */
+#define META_GTK_SURFACE_VERSION            1 /* from gtk_shell */
 #define META_WL_SUBSURFACE_VERSION          1 /* from wl_subcompositor */
 
 /* The first version to implement a specific event */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]