wayland: Add back wl_shell support

This commit is contained in:
Jasper St. Pierre 2014-02-28 00:18:42 -05:00
parent 283546b379
commit 86c1c30245
4 changed files with 311 additions and 21 deletions

View File

@ -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);

View File

@ -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
@ -1099,6 +1099,267 @@ bind_xdg_shell (struct wl_client *client,
wl_client_add_destroy_listener (client, &xdg_shell->client_destroy_listener);
}
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)
{
@ -1486,6 +1747,11 @@ meta_wayland_init_shell (MetaWaylandCompositor *compositor)
compositor, bind_xdg_shell) == NULL)
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,
@ -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 (xdg_shell == NULL)
if (surface->xdg_surface.resource)
{
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
return;
}
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
xdg_shell_send_ping (xdg_shell, serial);
if (xdg_shell == NULL)
{
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
return;
}
xdg_shell_send_ping (xdg_shell, serial);
}
else if (surface->wl_shell_surface.resource)
{
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, 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);
}

View File

@ -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

View File

@ -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 */