[mutter/wayland] Move surface state tracking and surface interface to a separate file
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wayland] Move surface state tracking and surface interface to a separate file
- Date: Tue, 3 Sep 2013 14:58:39 +0000 (UTC)
commit cad9e14463ed2599a1d3034021c6417527e3ea65
Author: Giovanni Campagna <gcampagn redhat com>
Date: Fri Aug 30 18:26:18 2013 +0200
Move surface state tracking and surface interface to a separate file
Move everything surface related from meta-wayland.c to meta-wayland-surface.c
https://bugzilla.gnome.org/show_bug.cgi?id=707128
src/Makefile.am | 1 +
src/wayland/meta-wayland-private.h | 6 +-
src/wayland/meta-wayland-surface.c | 863 ++++++++++++++++++++++++++++++++++++
src/wayland/meta-wayland-surface.h | 8 +
src/wayland/meta-wayland.c | 798 +--------------------------------
5 files changed, 887 insertions(+), 789 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 0a7bc37..c07e443 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -196,6 +196,7 @@ libmutter_wayland_la_SOURCES += \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-stage.h \
wayland/meta-wayland-stage.c \
+ wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
wayland/meta-weston-launch.c \
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index ebc066b..79ff6fd 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -105,6 +105,10 @@ void meta_wayland_compositor_set_input_focus (MetaWaylandComp
MetaLauncher *meta_wayland_compositor_get_launcher (MetaWaylandCompositor *compositor);
-void meta_wayland_surface_free (MetaWaylandSurface *surface);
+MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
+
+void meta_wayland_buffer_reference (MetaWaylandBufferReference *ref,
+ MetaWaylandBuffer *buffer);
+
#endif /* META_WAYLAND_PRIVATE_H */
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
new file mode 100644
index 0000000..deccf34
--- /dev/null
+++ b/src/wayland/meta-wayland-surface.c
@@ -0,0 +1,863 @@
+/*
+ * Wayland Support
+ *
+ * Copyright (C) 2012,2013 Intel Corporation
+ * 2013 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <clutter/clutter.h>
+#include <clutter/wayland/clutter-wayland-compositor.h>
+#include <clutter/wayland/clutter-wayland-surface.h>
+
+#include <glib.h>
+#include <sys/time.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <wayland-server.h>
+
+#include "meta-wayland-private.h"
+#include "meta-xwayland-private.h"
+#include "meta-wayland-stage.h"
+#include "meta-window-actor-private.h"
+#include "meta-wayland-seat.h"
+#include "meta-wayland-keyboard.h"
+#include "meta-wayland-pointer.h"
+#include "meta-wayland-data-device.h"
+#include "meta-cursor-tracker-private.h"
+#include "display-private.h"
+#include "window-private.h"
+#include <meta/types.h>
+#include <meta/main.h>
+#include "frame.h"
+#include "meta-idle-monitor-private.h"
+#include "meta-weston-launch.h"
+#include "monitor-private.h"
+
+static void
+surface_process_damage (MetaWaylandSurface *surface,
+ cairo_region_t *region)
+{
+ if (surface->window &&
+ surface->buffer_ref.buffer)
+ {
+ MetaWindowActor *window_actor =
+ META_WINDOW_ACTOR (meta_window_get_compositor_private (surface->window));
+ MetaRectangle rect;
+ cairo_rectangle_int_t cairo_rect;
+
+ meta_window_get_input_rect (surface->window, &rect);
+ cairo_rect.x = 0;
+ cairo_rect.y = 0;
+ cairo_rect.width = rect.width;
+ cairo_rect.height = rect.height;
+
+ cairo_region_intersect_rectangle (region, &cairo_rect);
+
+ if (window_actor)
+ {
+ int i, n_rectangles = cairo_region_num_rectangles (region);
+
+ for (i = 0; i < n_rectangles; i++)
+ {
+ cairo_rectangle_int_t rectangle;
+
+ cairo_region_get_rectangle (region, i, &rectangle);
+
+ meta_window_actor_process_wayland_damage (window_actor,
+ rectangle.x,
+ rectangle.y,
+ rectangle.width,
+ rectangle.height);
+ }
+ }
+ }
+}
+
+static void
+meta_wayland_surface_destroy (struct wl_client *wayland_client,
+ struct wl_resource *wayland_resource)
+{
+ wl_resource_destroy (wayland_resource);
+}
+
+static void
+meta_wayland_surface_attach (struct wl_client *wayland_client,
+ struct wl_resource *wayland_surface_resource,
+ struct wl_resource *wayland_buffer_resource,
+ gint32 sx, gint32 sy)
+{
+ MetaWaylandSurface *surface =
+ wl_resource_get_user_data (wayland_surface_resource);
+ MetaWaylandBuffer *buffer;
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ if (wayland_buffer_resource)
+ buffer = meta_wayland_buffer_from_resource (wayland_buffer_resource);
+ else
+ buffer = NULL;
+
+ /* Attach without commit in between does not send wl_buffer.release */
+ if (surface->pending.buffer)
+ wl_list_remove (&surface->pending.buffer_destroy_listener.link);
+
+ surface->pending.sx = sx;
+ surface->pending.sy = sy;
+ surface->pending.buffer = buffer;
+ surface->pending.newly_attached = TRUE;
+
+ if (buffer)
+ wl_signal_add (&buffer->destroy_signal,
+ &surface->pending.buffer_destroy_listener);
+}
+
+static void
+meta_wayland_surface_damage (struct wl_client *client,
+ struct wl_resource *surface_resource,
+ gint32 x,
+ gint32 y,
+ gint32 width,
+ gint32 height)
+{
+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+ cairo_rectangle_int_t rectangle = { x, y, width, height };
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ cairo_region_union_rectangle (surface->pending.damage, &rectangle);
+}
+
+static void
+destroy_frame_callback (struct wl_resource *callback_resource)
+{
+ MetaWaylandFrameCallback *callback =
+ wl_resource_get_user_data (callback_resource);
+
+ wl_list_remove (&callback->link);
+ g_slice_free (MetaWaylandFrameCallback, callback);
+}
+
+static void
+meta_wayland_surface_frame (struct wl_client *client,
+ struct wl_resource *surface_resource,
+ guint32 callback_id)
+{
+ MetaWaylandFrameCallback *callback;
+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ callback = g_slice_new0 (MetaWaylandFrameCallback);
+ callback->compositor = surface->compositor;
+ callback->resource = wl_resource_create (client,
+ &wl_callback_interface, 1,
+ callback_id);
+ wl_resource_set_user_data (callback->resource, callback);
+ wl_resource_set_destructor (callback->resource, destroy_frame_callback);
+
+ wl_list_insert (surface->pending.frame_callback_list.prev, &callback->link);
+}
+
+static void
+meta_wayland_surface_set_opaque_region (struct wl_client *client,
+ struct wl_resource *surface_resource,
+ struct wl_resource *region_resource)
+{
+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+ MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
+ surface->pending.opaque_region = cairo_region_copy (region->region);
+}
+
+static void
+meta_wayland_surface_set_input_region (struct wl_client *client,
+ struct wl_resource *surface_resource,
+ struct wl_resource *region_resource)
+{
+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+ MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
+ surface->pending.input_region = cairo_region_copy (region->region);
+}
+
+static void
+empty_region (cairo_region_t *region)
+{
+ cairo_rectangle_int_t rectangle = { 0, 0, 0, 0 };
+ cairo_region_intersect_rectangle (region, &rectangle);
+}
+
+static void
+meta_wayland_surface_commit (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+ MetaWaylandCompositor *compositor;
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ compositor = surface->compositor;
+
+ /* wl_surface.attach */
+ if (surface->pending.newly_attached &&
+ surface->buffer_ref.buffer != surface->pending.buffer)
+ {
+ /* Note: we set this before informing any window-actor since the
+ * window actor will expect to find the new buffer within the
+ * surface. */
+ meta_wayland_buffer_reference (&surface->buffer_ref,
+ surface->pending.buffer);
+
+ if (surface->pending.buffer)
+ {
+ MetaWaylandBuffer *buffer = surface->pending.buffer;
+
+ if (surface->window)
+ {
+ MetaWindow *window = surface->window;
+ MetaWindowActor *window_actor =
+ META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
+ MetaRectangle rect;
+
+ meta_window_get_input_rect (surface->window, &rect);
+
+ if (window_actor)
+ meta_window_actor_attach_wayland_buffer (window_actor, buffer);
+
+ /* XXX: we resize X based surfaces according to X events */
+ if (surface->xid == 0 &&
+ (buffer->width != rect.width || buffer->height != rect.height))
+ meta_window_resize (surface->window, FALSE, buffer->width, buffer->height);
+ }
+ else if (surface == compositor->seat->sprite)
+ meta_wayland_seat_update_sprite (compositor->seat);
+ }
+ }
+
+ if (surface->pending.buffer)
+ {
+ wl_list_remove (&surface->pending.buffer_destroy_listener.link);
+ surface->pending.buffer = NULL;
+ }
+ surface->pending.sx = 0;
+ surface->pending.sy = 0;
+ surface->pending.newly_attached = FALSE;
+
+ if (surface->window)
+ {
+ meta_window_set_opaque_region (surface->window, surface->pending.opaque_region);
+ g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
+
+ meta_window_set_input_region (surface->window, surface->pending.input_region);
+ g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
+ }
+
+ surface_process_damage (surface, surface->pending.damage);
+ empty_region (surface->pending.damage);
+
+ /* wl_surface.frame */
+ wl_list_insert_list (&compositor->frame_callbacks,
+ &surface->pending.frame_callback_list);
+ wl_list_init (&surface->pending.frame_callback_list);
+}
+
+static void
+meta_wayland_surface_set_buffer_transform (struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t transform)
+{
+ g_warning ("TODO: support set_buffer_transform request");
+}
+
+static void
+meta_wayland_surface_set_buffer_scale (struct wl_client *client,
+ struct wl_resource *resource,
+ int scale)
+{
+ g_warning ("TODO: support set_buffer_scale request");
+}
+
+const struct wl_surface_interface meta_wayland_surface_interface = {
+ meta_wayland_surface_destroy,
+ meta_wayland_surface_attach,
+ meta_wayland_surface_damage,
+ meta_wayland_surface_frame,
+ meta_wayland_surface_set_opaque_region,
+ meta_wayland_surface_set_input_region,
+ meta_wayland_surface_commit,
+ meta_wayland_surface_set_buffer_transform,
+ meta_wayland_surface_set_buffer_scale
+};
+
+void
+meta_wayland_surface_free (MetaWaylandSurface *surface)
+{
+ MetaWaylandCompositor *compositor = surface->compositor;
+ MetaWaylandFrameCallback *cb, *next;
+
+ compositor->surfaces = g_list_remove (compositor->surfaces, surface);
+
+ meta_wayland_buffer_reference (&surface->buffer_ref, NULL);
+
+ if (surface->pending.buffer)
+ wl_list_remove (&surface->pending.buffer_destroy_listener.link);
+
+ cairo_region_destroy (surface->pending.damage);
+
+ wl_list_for_each_safe (cb, next,
+ &surface->pending.frame_callback_list, link)
+ wl_resource_destroy (cb->resource);
+
+ meta_wayland_compositor_repick (compositor);
+
+ g_assert (surface != compositor->seat->keyboard.focus);
+ if (surface == compositor->seat->pointer.focus)
+ {
+ meta_wayland_pointer_destroy_focus (&compositor->seat->pointer);
+
+ g_assert (surface != compositor->seat->pointer.focus);
+ g_assert (surface != compositor->seat->pointer.grab->focus);
+ }
+
+ if (compositor->implicit_grab_surface == surface)
+ compositor->implicit_grab_surface = compositor->seat->pointer.current;
+
+ if (surface->resource)
+ wl_resource_set_user_data (surface->resource, NULL);
+ g_slice_free (MetaWaylandSurface, surface);
+}
+
+static void
+meta_wayland_surface_resource_destroy_cb (struct wl_resource *resource)
+{
+ MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+
+ /* There are four cases here:
+ - An X11 unmanaged window -> surface is NULL, nothing to do
+ - An X11 unmanaged window, but we got the wayland event first ->
+ just clear the resource pointer
+ - A wayland surface without window (destroyed before set_toplevel) ->
+ need to free the surface itself
+ - A wayland window -> need to unmanage
+ */
+
+ if (surface)
+ {
+ surface->resource = NULL;
+
+ /* NB: If the surface corresponds to an X window then we will be
+ * sure to free the MetaWindow according to some X event. */
+ if (surface->window &&
+ surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
+ {
+ MetaDisplay *display = meta_get_display ();
+ guint32 timestamp = meta_display_get_current_time_roundtrip (display);
+
+ meta_window_unmanage (surface->window, timestamp);
+ }
+ else if (!surface->window)
+ meta_wayland_surface_free (surface);
+ }
+}
+
+static void
+surface_handle_pending_buffer_destroy (struct wl_listener *listener,
+ void *data)
+{
+ MetaWaylandSurface *surface =
+ wl_container_of (listener, surface, pending.buffer_destroy_listener);
+
+ surface->pending.buffer = NULL;
+}
+
+MetaWaylandSurface *
+meta_wayland_surface_create (MetaWaylandCompositor *compositor,
+ struct wl_client *wayland_client,
+ guint32 id,
+ guint32 version)
+{
+ MetaWaylandSurface *surface = g_slice_new0 (MetaWaylandSurface);
+
+ surface->compositor = compositor;
+
+ surface->resource = wl_resource_create (wayland_client,
+ &wl_surface_interface,
+ version, id);
+ wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface,
+ meta_wayland_surface_resource_destroy_cb);
+
+ surface->pending.damage = cairo_region_create ();
+
+ surface->pending.buffer_destroy_listener.notify =
+ surface_handle_pending_buffer_destroy;
+ wl_list_init (&surface->pending.frame_callback_list);
+
+ return surface;
+}
+
+static void
+shell_surface_pong (struct wl_client *client,
+ struct wl_resource *resource,
+ guint32 serial)
+{
+}
+
+typedef struct _MetaWaylandGrab
+{
+ MetaWaylandPointerGrab grab;
+ MetaWaylandSurfaceExtension *shell_surface;
+ struct wl_listener shell_surface_destroy_listener;
+ MetaWaylandPointer *pointer;
+} MetaWaylandGrab;
+
+typedef struct _MetaWaylandMoveGrab
+{
+ MetaWaylandGrab base;
+ wl_fixed_t dx, dy;
+} MetaWaylandMoveGrab;
+
+static void
+destroy_shell_surface_grab_listener (struct wl_listener *listener,
+ void *data)
+{
+ MetaWaylandGrab *grab = wl_container_of (listener, grab,
+ shell_surface_destroy_listener);
+ grab->shell_surface = NULL;
+
+ /* XXX: Could we perhaps just stop the grab here so we don't have
+ * to consider grab->shell_surface becoming NULL in grab interface
+ * callbacks? */
+}
+
+typedef enum _GrabCursor
+{
+ GRAB_CURSOR_MOVE,
+} GrabCursor;
+
+static void
+grab_pointer (MetaWaylandGrab *grab,
+ const MetaWaylandPointerGrabInterface *interface,
+ MetaWaylandSurfaceExtension *shell_surface,
+ MetaWaylandPointer *pointer,
+ GrabCursor cursor)
+{
+ /* TODO: popup_grab_end (pointer); */
+
+ grab->grab.interface = interface;
+ grab->shell_surface = shell_surface;
+ grab->shell_surface_destroy_listener.notify =
+ destroy_shell_surface_grab_listener;
+ wl_resource_add_destroy_listener (shell_surface->resource,
+ &grab->shell_surface_destroy_listener);
+
+ grab->pointer = pointer;
+ grab->grab.focus = shell_surface->surface;
+
+ meta_wayland_pointer_start_grab (pointer, &grab->grab);
+
+ /* TODO: send_grab_cursor (cursor); */
+
+ /* XXX: In Weston there is a desktop shell protocol which has
+ * a set_grab_surface request that's used to specify the surface
+ * that's focused here.
+ *
+ * TODO: understand why.
+ *
+ * XXX: For now we just focus the surface directly associated with
+ * the grab.
+ */
+ meta_wayland_pointer_set_focus (pointer,
+ grab->shell_surface->surface,
+ wl_fixed_from_int (0),
+ wl_fixed_from_int (0));
+}
+
+static void
+release_pointer (MetaWaylandGrab *grab)
+{
+ if (grab->shell_surface)
+ wl_list_remove (&grab->shell_surface_destroy_listener.link);
+
+ meta_wayland_pointer_end_grab (grab->pointer);
+}
+
+static void
+noop_grab_focus (MetaWaylandPointerGrab *grab,
+ MetaWaylandSurface *surface,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ grab->focus = NULL;
+}
+
+static void
+move_grab_motion (MetaWaylandPointerGrab *grab,
+ uint32_t time,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ MetaWaylandMoveGrab *move = (MetaWaylandMoveGrab *)grab;
+ MetaWaylandPointer *pointer = move->base.pointer;
+ MetaWaylandSurfaceExtension *shell_surface = move->base.shell_surface;
+
+ if (!shell_surface)
+ return;
+
+ meta_window_move (shell_surface->surface->window,
+ TRUE,
+ wl_fixed_to_int (pointer->x + move->dx),
+ wl_fixed_to_int (pointer->y + move->dy));
+}
+
+static void
+move_grab_button (MetaWaylandPointerGrab *pointer_grab,
+ uint32_t time,
+ uint32_t button,
+ uint32_t state_w)
+{
+ MetaWaylandGrab *grab =
+ wl_container_of (pointer_grab, grab, grab);
+ MetaWaylandMoveGrab *move = (MetaWaylandMoveGrab *)grab;
+ MetaWaylandPointer *pointer = grab->pointer;
+ enum wl_pointer_button_state state = state_w;
+
+ if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED)
+ {
+ release_pointer (grab);
+ g_slice_free (MetaWaylandMoveGrab, move);
+ }
+}
+
+static const MetaWaylandPointerGrabInterface move_grab_interface = {
+ noop_grab_focus,
+ move_grab_motion,
+ move_grab_button,
+};
+
+static void
+start_surface_move (MetaWaylandSurfaceExtension *shell_surface,
+ MetaWaylandSeat *seat)
+{
+ MetaWaylandMoveGrab *move;
+ MetaRectangle rect;
+
+ g_return_if_fail (shell_surface != NULL);
+
+ /* TODO: check if the surface is fullscreen when we support fullscreen */
+
+ move = g_slice_new (MetaWaylandMoveGrab);
+
+ meta_window_get_input_rect (shell_surface->surface->window,
+ &rect);
+
+ move->dx = wl_fixed_from_int (rect.x) - seat->pointer.grab_x;
+ move->dy = wl_fixed_from_int (rect.y) - seat->pointer.grab_y;
+
+ grab_pointer (&move->base, &move_grab_interface, shell_surface,
+ &seat->pointer, GRAB_CURSOR_MOVE);
+}
+
+static void
+shell_surface_move (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat_resource,
+ guint32 serial)
+{
+ MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
+ MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
+
+ if (seat->pointer.button_count == 0 ||
+ seat->pointer.grab_serial != serial ||
+ seat->pointer.focus != shell_surface->surface)
+ return;
+
+ start_surface_move (shell_surface, seat);
+}
+
+static void
+shell_surface_resize (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat,
+ guint32 serial,
+ guint32 edges)
+{
+ g_warning ("TODO: support shell_surface_resize request");
+}
+
+static void
+ensure_surface_window (MetaWaylandSurface *surface)
+{
+ MetaDisplay *display = meta_get_display ();
+
+ if (!surface->window)
+ {
+ int width, height;
+
+ if (surface->buffer_ref.buffer)
+ {
+ MetaWaylandBuffer *buffer = surface->buffer_ref.buffer;
+ width = buffer->width;
+ height = buffer->width;
+ }
+ else
+ {
+ width = 0;
+ height = 0;
+ }
+
+ surface->window =
+ meta_window_new_for_wayland (display, width, height, surface);
+
+ meta_window_calc_showing (surface->window);
+ }
+}
+
+static void
+shell_surface_set_toplevel (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
+ MetaWaylandSurface *surface = shell_surface->surface;
+ MetaWaylandCompositor *compositor = surface->compositor;
+
+ /* NB: Surfaces from xwayland become managed based on X events. */
+ if (client == compositor->xwayland_client)
+ return;
+
+ ensure_surface_window (surface);
+
+ meta_window_unmake_fullscreen (surface->window);
+}
+
+static void
+shell_surface_set_transient (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *parent,
+ int x,
+ int y,
+ guint32 flags)
+{
+ MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
+ MetaWaylandSurface *surface = shell_surface->surface;
+ MetaWaylandCompositor *compositor = surface->compositor;
+
+ /* NB: Surfaces from xwayland become managed based on X events. */
+ if (client == compositor->xwayland_client)
+ return;
+
+ ensure_surface_window (surface);
+}
+
+static void
+shell_surface_set_fullscreen (struct wl_client *client,
+ struct wl_resource *resource,
+ guint32 method,
+ guint32 framerate,
+ struct wl_resource *output)
+{
+ MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
+ MetaWaylandSurface *surface = shell_surface->surface;
+ MetaWaylandCompositor *compositor = surface->compositor;
+
+ /* NB: Surfaces from xwayland become managed based on X events. */
+ if (client == compositor->xwayland_client)
+ return;
+
+ ensure_surface_window (surface);
+
+ meta_window_make_fullscreen (surface->window);
+}
+
+static void
+shell_surface_set_popup (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat,
+ guint32 serial,
+ struct wl_resource *parent,
+ gint32 x,
+ gint32 y,
+ guint32 flags)
+{
+}
+
+static void
+shell_surface_set_maximized (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output)
+{
+ g_warning ("TODO: support shell_surface_set_maximized request");
+}
+
+static void
+shell_surface_set_title (struct wl_client *client,
+ struct wl_resource *resource,
+ const char *title)
+{
+ MetaWaylandSurfaceExtension *extension = wl_resource_get_user_data (resource);
+ MetaWaylandSurface *surface = extension->surface;
+
+ g_warning ("TODO: support shell_surface_set_title request");
+}
+
+static void
+shell_surface_set_class (struct wl_client *client,
+ struct wl_resource *resource,
+ const char *class_)
+{
+ MetaWaylandSurfaceExtension *extension = wl_resource_get_user_data (resource);
+ MetaWaylandSurface *surface = extension->surface;
+
+ g_warning ("TODO: support shell_surface_set_class request");
+}
+
+static const struct wl_shell_surface_interface meta_wayland_shell_surface_interface =
+{
+ shell_surface_pong,
+ shell_surface_move,
+ shell_surface_resize,
+ shell_surface_set_toplevel,
+ shell_surface_set_transient,
+ shell_surface_set_fullscreen,
+ shell_surface_set_popup,
+ shell_surface_set_maximized,
+ shell_surface_set_title,
+ shell_surface_set_class
+};
+
+static void
+extension_handle_surface_destroy (struct wl_listener *listener,
+ void *data)
+{
+ MetaWaylandSurfaceExtension *extension =
+ wl_container_of (listener, extension, surface_destroy_listener);
+
+ extension->surface = NULL;
+ wl_resource_destroy (extension->resource);
+}
+
+static void
+destroy_surface_extension (struct wl_resource *resource)
+{
+ MetaWaylandSurfaceExtension *extension = wl_resource_get_user_data (resource);
+
+ /* In case cleaning up a dead client destroys extension first */
+ if (extension->surface)
+ {
+ wl_list_remove (&extension->surface_destroy_listener.link);
+ }
+
+ g_free (extension);
+}
+
+static void
+create_surface_extension (struct wl_client *client,
+ struct wl_resource *master_resource,
+ guint32 id,
+ MetaWaylandSurface *surface,
+ const struct wl_interface *interface,
+ const void *implementation)
+{
+ MetaWaylandSurfaceExtension *extension;
+
+ extension = g_new0 (MetaWaylandSurfaceExtension, 1);
+
+ extension->resource = wl_resource_create (client, interface,
+ wl_resource_get_version (master_resource), id);
+ wl_resource_set_implementation (extension->resource, implementation,
+ extension, destroy_surface_extension);
+
+ extension->surface = surface;
+ extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
+ wl_resource_add_destroy_listener (surface->resource,
+ &extension->surface_destroy_listener);
+}
+
+static void
+get_shell_surface (struct wl_client *client,
+ struct wl_resource *resource,
+ guint32 id,
+ struct wl_resource *surface_resource)
+{
+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+
+ if (surface->has_shell_surface)
+ {
+ wl_resource_post_error (surface_resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "wl_shell::get_shell_surface already requested");
+ return;
+ }
+
+ create_surface_extension (client, resource, id, surface,
+ &wl_shell_surface_interface,
+ &meta_wayland_shell_surface_interface);
+ surface->has_shell_surface = TRUE;
+}
+
+static const struct wl_shell_interface meta_wayland_shell_interface =
+{
+ get_shell_surface
+};
+
+static void
+bind_shell (struct wl_client *client,
+ void *data,
+ guint32 version,
+ guint32 id)
+{
+ struct wl_resource *resource;
+
+ resource = wl_resource_create (client, &wl_shell_interface, version, id);
+ wl_resource_set_implementation (resource, &meta_wayland_shell_interface, data, NULL);
+}
+
+void
+meta_wayland_init_shell (MetaWaylandCompositor *compositor)
+{
+ if (wl_global_create (compositor->wayland_display,
+ &wl_shell_interface, 1,
+ compositor, bind_shell) == NULL)
+ g_error ("Failed to register a global shell object");
+}
+
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index ec6f849..3926091 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -87,4 +87,12 @@ typedef struct
struct wl_listener surface_destroy_listener;
} MetaWaylandSurfaceExtension;
+void meta_wayland_init_shell (MetaWaylandCompositor *compositor);
+
+MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *compositor,
+ struct wl_client *client,
+ guint32 id,
+ guint32 version);
+void meta_wayland_surface_free (MetaWaylandSurface *surface);
+
#endif
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 2398e04..43c7d95 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -136,7 +136,7 @@ meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
g_slice_free (MetaWaylandBuffer, buffer);
}
-static MetaWaylandBuffer *
+MetaWaylandBuffer *
meta_wayland_buffer_from_resource (struct wl_resource *resource)
{
MetaWaylandBuffer *buffer;
@@ -165,7 +165,7 @@ meta_wayland_buffer_from_resource (struct wl_resource *resource)
static void
meta_wayland_buffer_reference_handle_destroy (struct wl_listener *listener,
- void *data)
+ void *data)
{
MetaWaylandBufferReference *ref =
wl_container_of (listener, ref, destroy_listener);
@@ -175,7 +175,7 @@ meta_wayland_buffer_reference_handle_destroy (struct wl_listener *listener,
ref->buffer = NULL;
}
-static void
+void
meta_wayland_buffer_reference (MetaWaylandBufferReference *ref,
MetaWaylandBuffer *buffer)
{
@@ -202,280 +202,6 @@ meta_wayland_buffer_reference (MetaWaylandBufferReference *ref,
ref->destroy_listener.notify = meta_wayland_buffer_reference_handle_destroy;
}
-static void
-surface_process_damage (MetaWaylandSurface *surface,
- cairo_region_t *region)
-{
- if (surface->window &&
- surface->buffer_ref.buffer)
- {
- MetaWindowActor *window_actor =
- META_WINDOW_ACTOR (meta_window_get_compositor_private (surface->window));
- MetaRectangle rect;
- cairo_rectangle_int_t cairo_rect;
-
- meta_window_get_input_rect (surface->window, &rect);
- cairo_rect.x = 0;
- cairo_rect.y = 0;
- cairo_rect.width = rect.width;
- cairo_rect.height = rect.height;
-
- cairo_region_intersect_rectangle (region, &cairo_rect);
-
- if (window_actor)
- {
- int i, n_rectangles = cairo_region_num_rectangles (region);
-
- for (i = 0; i < n_rectangles; i++)
- {
- cairo_rectangle_int_t rectangle;
-
- cairo_region_get_rectangle (region, i, &rectangle);
-
- meta_window_actor_process_wayland_damage (window_actor,
- rectangle.x,
- rectangle.y,
- rectangle.width,
- rectangle.height);
- }
- }
- }
-}
-
-static void
-meta_wayland_surface_destroy (struct wl_client *wayland_client,
- struct wl_resource *wayland_resource)
-{
- wl_resource_destroy (wayland_resource);
-}
-
-static void
-meta_wayland_surface_attach (struct wl_client *wayland_client,
- struct wl_resource *wayland_surface_resource,
- struct wl_resource *wayland_buffer_resource,
- gint32 sx, gint32 sy)
-{
- MetaWaylandSurface *surface =
- wl_resource_get_user_data (wayland_surface_resource);
- MetaWaylandBuffer *buffer;
-
- /* X11 unmanaged window */
- if (!surface)
- return;
-
- if (wayland_buffer_resource)
- buffer = meta_wayland_buffer_from_resource (wayland_buffer_resource);
- else
- buffer = NULL;
-
- /* Attach without commit in between does not send wl_buffer.release */
- if (surface->pending.buffer)
- wl_list_remove (&surface->pending.buffer_destroy_listener.link);
-
- surface->pending.sx = sx;
- surface->pending.sy = sy;
- surface->pending.buffer = buffer;
- surface->pending.newly_attached = TRUE;
-
- if (buffer)
- wl_signal_add (&buffer->destroy_signal,
- &surface->pending.buffer_destroy_listener);
-}
-
-static void
-meta_wayland_surface_damage (struct wl_client *client,
- struct wl_resource *surface_resource,
- gint32 x,
- gint32 y,
- gint32 width,
- gint32 height)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
- cairo_rectangle_int_t rectangle = { x, y, width, height };
-
- /* X11 unmanaged window */
- if (!surface)
- return;
-
- cairo_region_union_rectangle (surface->pending.damage, &rectangle);
-}
-
-static void
-destroy_frame_callback (struct wl_resource *callback_resource)
-{
- MetaWaylandFrameCallback *callback =
- wl_resource_get_user_data (callback_resource);
-
- wl_list_remove (&callback->link);
- g_slice_free (MetaWaylandFrameCallback, callback);
-}
-
-static void
-meta_wayland_surface_frame (struct wl_client *client,
- struct wl_resource *surface_resource,
- guint32 callback_id)
-{
- MetaWaylandFrameCallback *callback;
- MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
-
- /* X11 unmanaged window */
- if (!surface)
- return;
-
- callback = g_slice_new0 (MetaWaylandFrameCallback);
- callback->compositor = surface->compositor;
- callback->resource = wl_resource_create (client,
- &wl_callback_interface, 1,
- callback_id);
- wl_resource_set_user_data (callback->resource, callback);
- wl_resource_set_destructor (callback->resource, destroy_frame_callback);
-
- wl_list_insert (surface->pending.frame_callback_list.prev, &callback->link);
-}
-
-static void
-meta_wayland_surface_set_opaque_region (struct wl_client *client,
- struct wl_resource *surface_resource,
- struct wl_resource *region_resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
- MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
-
- /* X11 unmanaged window */
- if (!surface)
- return;
-
- g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
- surface->pending.opaque_region = cairo_region_copy (region->region);
-}
-
-static void
-meta_wayland_surface_set_input_region (struct wl_client *client,
- struct wl_resource *surface_resource,
- struct wl_resource *region_resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
- MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
-
- /* X11 unmanaged window */
- if (!surface)
- return;
-
- g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
- surface->pending.input_region = cairo_region_copy (region->region);
-}
-
-static void
-empty_region (cairo_region_t *region)
-{
- cairo_rectangle_int_t rectangle = { 0, 0, 0, 0 };
- cairo_region_intersect_rectangle (region, &rectangle);
-}
-
-static void
-meta_wayland_surface_commit (struct wl_client *client,
- struct wl_resource *resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
- MetaWaylandCompositor *compositor;
-
- /* X11 unmanaged window */
- if (!surface)
- return;
-
- compositor = surface->compositor;
-
- /* wl_surface.attach */
- if (surface->pending.newly_attached &&
- surface->buffer_ref.buffer != surface->pending.buffer)
- {
- /* Note: we set this before informing any window-actor since the
- * window actor will expect to find the new buffer within the
- * surface. */
- meta_wayland_buffer_reference (&surface->buffer_ref,
- surface->pending.buffer);
-
- if (surface->pending.buffer)
- {
- MetaWaylandBuffer *buffer = surface->pending.buffer;
-
- if (surface->window)
- {
- MetaWindow *window = surface->window;
- MetaWindowActor *window_actor =
- META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
- MetaRectangle rect;
-
- meta_window_get_input_rect (surface->window, &rect);
-
- if (window_actor)
- meta_window_actor_attach_wayland_buffer (window_actor, buffer);
-
- /* XXX: we resize X based surfaces according to X events */
- if (surface->xid == 0 &&
- (buffer->width != rect.width || buffer->height != rect.height))
- meta_window_resize (surface->window, FALSE, buffer->width, buffer->height);
- }
- else if (surface == compositor->seat->sprite)
- meta_wayland_seat_update_sprite (compositor->seat);
- }
- }
-
- if (surface->pending.buffer)
- {
- wl_list_remove (&surface->pending.buffer_destroy_listener.link);
- surface->pending.buffer = NULL;
- }
- surface->pending.sx = 0;
- surface->pending.sy = 0;
- surface->pending.newly_attached = FALSE;
-
- if (surface->window)
- {
- meta_window_set_opaque_region (surface->window, surface->pending.opaque_region);
- g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
-
- meta_window_set_input_region (surface->window, surface->pending.input_region);
- g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
- }
-
- surface_process_damage (surface, surface->pending.damage);
- empty_region (surface->pending.damage);
-
- /* wl_surface.frame */
- wl_list_insert_list (&compositor->frame_callbacks,
- &surface->pending.frame_callback_list);
- wl_list_init (&surface->pending.frame_callback_list);
-}
-
-static void
-meta_wayland_surface_set_buffer_transform (struct wl_client *client,
- struct wl_resource *resource,
- int32_t transform)
-{
- g_warning ("TODO: support set_buffer_transform request");
-}
-
-static void
-meta_wayland_surface_set_buffer_scale (struct wl_client *client,
- struct wl_resource *resource,
- int scale)
-{
- g_warning ("TODO: support set_buffer_scale request");
-}
-
-const struct wl_surface_interface meta_wayland_surface_interface = {
- meta_wayland_surface_destroy,
- meta_wayland_surface_attach,
- meta_wayland_surface_damage,
- meta_wayland_surface_frame,
- meta_wayland_surface_set_opaque_region,
- meta_wayland_surface_set_input_region,
- meta_wayland_surface_commit,
- meta_wayland_surface_set_buffer_transform,
- meta_wayland_surface_set_buffer_scale
-};
-
void
meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
MetaWindow *window)
@@ -495,87 +221,6 @@ meta_wayland_compositor_repick (MetaWaylandCompositor *compositor)
NULL);
}
-void
-meta_wayland_surface_free (MetaWaylandSurface *surface)
-{
- MetaWaylandCompositor *compositor = surface->compositor;
- MetaWaylandFrameCallback *cb, *next;
-
- compositor->surfaces = g_list_remove (compositor->surfaces, surface);
-
- meta_wayland_buffer_reference (&surface->buffer_ref, NULL);
-
- if (surface->pending.buffer)
- wl_list_remove (&surface->pending.buffer_destroy_listener.link);
-
- cairo_region_destroy (surface->pending.damage);
-
- wl_list_for_each_safe (cb, next,
- &surface->pending.frame_callback_list, link)
- wl_resource_destroy (cb->resource);
-
- meta_wayland_compositor_repick (compositor);
-
- g_assert (surface != compositor->seat->keyboard.focus);
- if (surface == compositor->seat->pointer.focus)
- {
- meta_wayland_pointer_destroy_focus (&compositor->seat->pointer);
-
- g_assert (surface != compositor->seat->pointer.focus);
- g_assert (surface != compositor->seat->pointer.grab->focus);
- }
-
- if (compositor->implicit_grab_surface == surface)
- compositor->implicit_grab_surface = compositor->seat->pointer.current;
-
- if (surface->resource)
- wl_resource_set_user_data (surface->resource, NULL);
- g_slice_free (MetaWaylandSurface, surface);
-}
-
-static void
-meta_wayland_surface_resource_destroy_cb (struct wl_resource *resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
-
- /* There are four cases here:
- - An X11 unmanaged window -> surface is NULL, nothing to do
- - An X11 unmanaged window, but we got the wayland event first ->
- just clear the resource pointer
- - A wayland surface without window (destroyed before set_toplevel) ->
- need to free the surface itself
- - A wayland window -> need to unmanage
- */
-
- if (surface)
- {
- surface->resource = NULL;
-
- /* NB: If the surface corresponds to an X window then we will be
- * sure to free the MetaWindow according to some X event. */
- if (surface->window &&
- surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
- {
- MetaDisplay *display = meta_get_display ();
- guint32 timestamp = meta_display_get_current_time_roundtrip (display);
-
- meta_window_unmanage (surface->window, timestamp);
- }
- else if (!surface->window)
- meta_wayland_surface_free (surface);
- }
-}
-
-static void
-surface_handle_pending_buffer_destroy (struct wl_listener *listener,
- void *data)
-{
- MetaWaylandSurface *surface =
- wl_container_of (listener, surface, pending.buffer_destroy_listener);
-
- surface->pending.buffer = NULL;
-}
-
static void
meta_wayland_compositor_create_surface (struct wl_client *wayland_client,
struct wl_resource *wayland_compositor_resource,
@@ -583,24 +228,14 @@ meta_wayland_compositor_create_surface (struct wl_client *wayland_client,
{
MetaWaylandCompositor *compositor =
wl_resource_get_user_data (wayland_compositor_resource);
- MetaWaylandSurface *surface = g_slice_new0 (MetaWaylandSurface);
-
- surface->compositor = compositor;
+ MetaWaylandSurface *surface;
/* a surface inherits the version from the compositor */
- surface->resource = wl_resource_create (wayland_client,
- &wl_surface_interface,
- wl_resource_get_version (wayland_compositor_resource),
- id);
- wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface,
- meta_wayland_surface_resource_destroy_cb);
-
- surface->pending.damage = cairo_region_create ();
-
- surface->pending.buffer_destroy_listener.notify =
- surface_handle_pending_buffer_destroy;
- wl_list_init (&surface->pending.frame_callback_list);
-
+ surface = meta_wayland_surface_create (compositor,
+ wayland_client,
+ id,
+ wl_resource_get_version (wayland_compositor_resource));
+
compositor->surfaces = g_list_prepend (compositor->surfaces, surface);
}
@@ -888,416 +523,6 @@ compositor_bind (struct wl_client *client,
}
static void
-shell_surface_pong (struct wl_client *client,
- struct wl_resource *resource,
- guint32 serial)
-{
-}
-
-typedef struct _MetaWaylandGrab
-{
- MetaWaylandPointerGrab grab;
- MetaWaylandSurfaceExtension *shell_surface;
- struct wl_listener shell_surface_destroy_listener;
- MetaWaylandPointer *pointer;
-} MetaWaylandGrab;
-
-typedef struct _MetaWaylandMoveGrab
-{
- MetaWaylandGrab base;
- wl_fixed_t dx, dy;
-} MetaWaylandMoveGrab;
-
-static void
-destroy_shell_surface_grab_listener (struct wl_listener *listener,
- void *data)
-{
- MetaWaylandGrab *grab = wl_container_of (listener, grab,
- shell_surface_destroy_listener);
- grab->shell_surface = NULL;
-
- /* XXX: Could we perhaps just stop the grab here so we don't have
- * to consider grab->shell_surface becoming NULL in grab interface
- * callbacks? */
-}
-
-typedef enum _GrabCursor
-{
- GRAB_CURSOR_MOVE,
-} GrabCursor;
-
-static void
-grab_pointer (MetaWaylandGrab *grab,
- const MetaWaylandPointerGrabInterface *interface,
- MetaWaylandSurfaceExtension *shell_surface,
- MetaWaylandPointer *pointer,
- GrabCursor cursor)
-{
- /* TODO: popup_grab_end (pointer); */
-
- grab->grab.interface = interface;
- grab->shell_surface = shell_surface;
- grab->shell_surface_destroy_listener.notify =
- destroy_shell_surface_grab_listener;
- wl_resource_add_destroy_listener (shell_surface->resource,
- &grab->shell_surface_destroy_listener);
-
- grab->pointer = pointer;
- grab->grab.focus = shell_surface->surface;
-
- meta_wayland_pointer_start_grab (pointer, &grab->grab);
-
- /* TODO: send_grab_cursor (cursor); */
-
- /* XXX: In Weston there is a desktop shell protocol which has
- * a set_grab_surface request that's used to specify the surface
- * that's focused here.
- *
- * TODO: understand why.
- *
- * XXX: For now we just focus the surface directly associated with
- * the grab.
- */
- meta_wayland_pointer_set_focus (pointer,
- grab->shell_surface->surface,
- wl_fixed_from_int (0),
- wl_fixed_from_int (0));
-}
-
-static void
-release_pointer (MetaWaylandGrab *grab)
-{
- if (grab->shell_surface)
- wl_list_remove (&grab->shell_surface_destroy_listener.link);
-
- meta_wayland_pointer_end_grab (grab->pointer);
-}
-
-static void
-noop_grab_focus (MetaWaylandPointerGrab *grab,
- MetaWaylandSurface *surface,
- wl_fixed_t x,
- wl_fixed_t y)
-{
- grab->focus = NULL;
-}
-
-static void
-move_grab_motion (MetaWaylandPointerGrab *grab,
- uint32_t time,
- wl_fixed_t x,
- wl_fixed_t y)
-{
- MetaWaylandMoveGrab *move = (MetaWaylandMoveGrab *)grab;
- MetaWaylandPointer *pointer = move->base.pointer;
- MetaWaylandSurfaceExtension *shell_surface = move->base.shell_surface;
-
- if (!shell_surface)
- return;
-
- meta_window_move (shell_surface->surface->window,
- TRUE,
- wl_fixed_to_int (pointer->x + move->dx),
- wl_fixed_to_int (pointer->y + move->dy));
-}
-
-static void
-move_grab_button (MetaWaylandPointerGrab *pointer_grab,
- uint32_t time,
- uint32_t button,
- uint32_t state_w)
-{
- MetaWaylandGrab *grab =
- wl_container_of (pointer_grab, grab, grab);
- MetaWaylandMoveGrab *move = (MetaWaylandMoveGrab *)grab;
- MetaWaylandPointer *pointer = grab->pointer;
- enum wl_pointer_button_state state = state_w;
-
- if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED)
- {
- release_pointer (grab);
- g_slice_free (MetaWaylandMoveGrab, move);
- }
-}
-
-static const MetaWaylandPointerGrabInterface move_grab_interface = {
- noop_grab_focus,
- move_grab_motion,
- move_grab_button,
-};
-
-static void
-start_surface_move (MetaWaylandSurfaceExtension *shell_surface,
- MetaWaylandSeat *seat)
-{
- MetaWaylandMoveGrab *move;
- MetaRectangle rect;
-
- g_return_if_fail (shell_surface != NULL);
-
- /* TODO: check if the surface is fullscreen when we support fullscreen */
-
- move = g_slice_new (MetaWaylandMoveGrab);
-
- meta_window_get_input_rect (shell_surface->surface->window,
- &rect);
-
- move->dx = wl_fixed_from_int (rect.x) - seat->pointer.grab_x;
- move->dy = wl_fixed_from_int (rect.y) - seat->pointer.grab_y;
-
- grab_pointer (&move->base, &move_grab_interface, shell_surface,
- &seat->pointer, GRAB_CURSOR_MOVE);
-}
-
-static void
-shell_surface_move (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *seat_resource,
- guint32 serial)
-{
- MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
- MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
-
- if (seat->pointer.button_count == 0 ||
- seat->pointer.grab_serial != serial ||
- seat->pointer.focus != shell_surface->surface)
- return;
-
- start_surface_move (shell_surface, seat);
-}
-
-static void
-shell_surface_resize (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *seat,
- guint32 serial,
- guint32 edges)
-{
- g_warning ("TODO: support shell_surface_resize request");
-}
-
-static void
-ensure_surface_window (MetaWaylandSurface *surface)
-{
- MetaDisplay *display = meta_get_display ();
-
- if (!surface->window)
- {
- int width, height;
-
- if (surface->buffer_ref.buffer)
- {
- MetaWaylandBuffer *buffer = surface->buffer_ref.buffer;
- width = buffer->width;
- height = buffer->width;
- }
- else
- {
- width = 0;
- height = 0;
- }
-
- surface->window =
- meta_window_new_for_wayland (display, width, height, surface);
-
- meta_window_calc_showing (surface->window);
- }
-}
-
-static void
-shell_surface_set_toplevel (struct wl_client *client,
- struct wl_resource *resource)
-{
- MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
- MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
- MetaWaylandSurface *surface = shell_surface->surface;
-
- /* NB: Surfaces from xwayland become managed based on X events. */
- if (client == compositor->xwayland_client)
- return;
-
- ensure_surface_window (surface);
-
- meta_window_unmake_fullscreen (surface->window);
-}
-
-static void
-shell_surface_set_transient (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *parent,
- int x,
- int y,
- guint32 flags)
-{
- MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
- MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
- MetaWaylandSurface *surface = shell_surface->surface;
-
- /* NB: Surfaces from xwayland become managed based on X events. */
- if (client == compositor->xwayland_client)
- return;
-
- ensure_surface_window (surface);
-}
-
-static void
-shell_surface_set_fullscreen (struct wl_client *client,
- struct wl_resource *resource,
- guint32 method,
- guint32 framerate,
- struct wl_resource *output)
-{
- MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
- MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
- MetaWaylandSurface *surface = shell_surface->surface;
-
- /* NB: Surfaces from xwayland become managed based on X events. */
- if (client == compositor->xwayland_client)
- return;
-
- ensure_surface_window (surface);
-
- meta_window_make_fullscreen (surface->window);
-}
-
-static void
-shell_surface_set_popup (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *seat,
- guint32 serial,
- struct wl_resource *parent,
- gint32 x,
- gint32 y,
- guint32 flags)
-{
-}
-
-static void
-shell_surface_set_maximized (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *output)
-{
- g_warning ("TODO: support shell_surface_set_maximized request");
-}
-
-static void
-shell_surface_set_title (struct wl_client *client,
- struct wl_resource *resource,
- const char *title)
-{
- g_warning ("TODO: support shell_surface_set_title request");
-}
-
-static void
-shell_surface_set_class (struct wl_client *client,
- struct wl_resource *resource,
- const char *class_)
-{
- g_warning ("TODO: support shell_surface_set_class request");
-}
-
-static const struct wl_shell_surface_interface meta_wayland_shell_surface_interface =
-{
- shell_surface_pong,
- shell_surface_move,
- shell_surface_resize,
- shell_surface_set_toplevel,
- shell_surface_set_transient,
- shell_surface_set_fullscreen,
- shell_surface_set_popup,
- shell_surface_set_maximized,
- shell_surface_set_title,
- shell_surface_set_class
-};
-
-static void
-extension_handle_surface_destroy (struct wl_listener *listener,
- void *data)
-{
- MetaWaylandSurfaceExtension *extension =
- wl_container_of (listener, extension, surface_destroy_listener);
-
- extension->surface = NULL;
- wl_resource_destroy (extension->resource);
-}
-
-static void
-destroy_surface_extension (struct wl_resource *resource)
-{
- MetaWaylandSurfaceExtension *extension = wl_resource_get_user_data (resource);
-
- /* In case cleaning up a dead client destroys extension first */
- if (extension->surface)
- {
- wl_list_remove (&extension->surface_destroy_listener.link);
- }
-
- g_free (extension);
-}
-
-static void
-create_surface_extension (struct wl_client *client,
- struct wl_resource *master_resource,
- guint32 id,
- MetaWaylandSurface *surface,
- const struct wl_interface *interface,
- const void *implementation)
-{
- MetaWaylandSurfaceExtension *extension;
-
- extension = g_new0 (MetaWaylandSurfaceExtension, 1);
-
- extension->resource = wl_resource_create (client, interface,
- wl_resource_get_version (master_resource), id);
- wl_resource_set_implementation (extension->resource, implementation,
- extension, destroy_surface_extension);
-
- extension->surface = surface;
- extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
- wl_resource_add_destroy_listener (surface->resource,
- &extension->surface_destroy_listener);
-}
-
-static void
-get_shell_surface (struct wl_client *client,
- struct wl_resource *resource,
- guint32 id,
- struct wl_resource *surface_resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
-
- if (surface->has_shell_surface)
- {
- wl_resource_post_error (surface_resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "wl_shell::get_shell_surface already requested");
- return;
- }
-
- create_surface_extension (client, resource, id, surface,
- &wl_shell_surface_interface,
- &meta_wayland_shell_surface_interface);
- surface->has_shell_surface = TRUE;
-}
-
-static const struct wl_shell_interface meta_wayland_shell_interface =
-{
- get_shell_surface
-};
-
-static void
-bind_shell (struct wl_client *client,
- void *data,
- guint32 version,
- guint32 id)
-{
- struct wl_resource *resource;
-
- resource = wl_resource_create (client, &wl_shell_interface, version, id);
- wl_resource_set_implementation (resource, &meta_wayland_shell_interface, data, NULL);
-}
-
-static void
stage_destroy_cb (void)
{
meta_quit (META_EXIT_SUCCESS);
@@ -1681,10 +906,7 @@ meta_wayland_init (void)
compositor, /* hook_data */
NULL /* data_destroy */);
- if (wl_global_create (compositor->wayland_display,
- &wl_shell_interface, 1,
- compositor, bind_shell) == NULL)
- g_error ("Failed to register a global shell object");
+ meta_wayland_init_shell (compositor);
clutter_actor_show (compositor->stage);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]