summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2014-02-28 00:18:42 -0500
committerJasper St. Pierre <jstpierre@mecheye.net>2014-02-28 08:32:14 -0500
commit86c1c3024526e479c2e65dee896757549d346c1e (patch)
tree6882f1433355ddb5fec0ca1fd82dd3e3627cde24
parent283546b3790669e7690a1a278c87627117f4b30c (diff)
downloadmutter-86c1c3024526e479c2e65dee896757549d346c1e.tar.gz
wayland: Add back wl_shell support
-rw-r--r--src/wayland/meta-wayland-pointer.c15
-rw-r--r--src/wayland/meta-wayland-surface.c307
-rw-r--r--src/wayland/meta-wayland-surface.h4
-rw-r--r--src/wayland/meta-wayland-versions.h4
4 files changed, 310 insertions, 20 deletions
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 21e41bb80..e0c9ad21a 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 0c5c7115f..0c671048f 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 9e12451d4..e0203f58c 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 e2d608c86..17d8895eb 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 */