[mutter/wip/wayland-work: 13/13] wip window resizing for wayland clients
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland-work: 13/13] wip window resizing for wayland clients
- Date: Tue, 3 Sep 2013 15:03:00 +0000 (UTC)
commit 45a5cc8200517e9707f53f09c98c37e5a3a61077
Author: Giovanni Campagna <gcampagn redhat com>
Date: Tue Sep 3 15:43:22 2013 +0200
wip window resizing for wayland clients
src/core/constraints.h | 3 +-
src/core/window-private.h | 11 +
src/core/window.c | 640 +++++++++++++++++++++--------------
src/wayland/meta-wayland-keyboard.c | 2 +-
src/wayland/meta-wayland-surface.c | 182 ++++++-----
src/wayland/meta-wayland-surface.h | 39 ++-
src/wayland/meta-wayland.c | 4 +-
src/wayland/meta-xwayland.c | 4 -
8 files changed, 527 insertions(+), 358 deletions(-)
---
diff --git a/src/core/constraints.h b/src/core/constraints.h
index 5fa1e4e..0bea43d 100644
--- a/src/core/constraints.h
+++ b/src/core/constraints.h
@@ -35,7 +35,8 @@ typedef enum
META_DO_GRAVITY_ADJUST = 1 << 1,
META_IS_USER_ACTION = 1 << 2,
META_IS_MOVE_ACTION = 1 << 3,
- META_IS_RESIZE_ACTION = 1 << 4
+ META_IS_RESIZE_ACTION = 1 << 4,
+ META_IS_WAYLAND_RESIZE = 1 << 5
} MetaMoveResizeFlags;
void meta_window_constrain (MetaWindow *window,
diff --git a/src/core/window-private.h b/src/core/window-private.h
index b0cec17..9504bca 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -404,6 +404,12 @@ struct _MetaWindow
*/
MetaRectangle rect;
+ /* The size we want the window to be (i.e. what we last asked
+ * the client to configure).
+ * This is only used for wayland clients.
+ */
+ MetaRectangle expected_rect;
+
gboolean has_custom_frame_extents;
GtkBorder custom_frame_extents;
@@ -601,6 +607,11 @@ void meta_window_move_resize_request(MetaWindow *window,
int y,
int width,
int height);
+void meta_window_move_resize_wayland (MetaWindow *window,
+ int width,
+ int height,
+ int dx,
+ int dy);
gboolean meta_window_configure_request (MetaWindow *window,
XEvent *event);
gboolean meta_window_property_notify (MetaWindow *window,
diff --git a/src/core/window.c b/src/core/window.c
index 2f5fa2d..8d010ba 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4994,6 +4994,7 @@ meta_window_move_resize_internal (MetaWindow *window,
* 2 | A not-resize-only ConfigureRequest/net_moveresize_window request
* 3 | meta_window_move
* 3 | meta_window_move_resize
+ * 4 | meta_window_move_resize_wayland
*
* For each of the cases, root_x_nw and root_y_nw must be treated as follows:
*
@@ -5004,8 +5005,12 @@ meta_window_move_resize_internal (MetaWindow *window,
* coordinates are relative to some corner or side of the outer
* window (except for the case of StaticGravity) and we want to
* know the location of the upper left corner of the inner window.
- * (3) These values are already the desired positon of the NW corner
+ * (3) These values are already the desired position of the NW corner
* of the inner window
+ * (4) These values are already the desired position of the NW corner
+ * of the inner window (which is also the outer window, because
+ * we don't decorate wayland clients), and the client has acknowledged
+ * the window size change.
*/
XWindowChanges values;
unsigned int mask;
@@ -5021,6 +5026,7 @@ meta_window_move_resize_internal (MetaWindow *window,
gboolean is_configure_request;
gboolean do_gravity_adjust;
gboolean is_user_action;
+ gboolean is_wayland_resize;
gboolean did_placement;
gboolean configure_frame_first;
gboolean use_static_gravity;
@@ -5037,9 +5043,12 @@ meta_window_move_resize_internal (MetaWindow *window,
is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0;
do_gravity_adjust = (flags & META_DO_GRAVITY_ADJUST) != 0;
is_user_action = (flags & META_IS_USER_ACTION) != 0;
+ is_wayland_resize = (flags & META_IS_WAYLAND_RESIZE) != 0;
- /* The action has to be a move or a resize or both... */
- g_assert (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION));
+ /* The action has to be a move, a resize or the wayland client
+ * acking our choice of size.
+ */
+ g_assert (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION | META_IS_WAYLAND_RESIZE));
/* We don't need it in the idle queue anymore. */
meta_window_unqueue (window, META_QUEUE_MOVE_RESIZE);
@@ -5097,309 +5106,404 @@ meta_window_move_resize_internal (MetaWindow *window,
did_placement = !window->placed && window->calc_placement;
- meta_window_constrain (window,
- window->frame ? &borders : NULL,
- flags,
- gravity,
- &old_rect,
- &new_rect);
+ if (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION))
+ {
+ meta_window_constrain (window,
+ window->frame ? &borders : NULL,
+ flags,
+ gravity,
+ &old_rect,
+ &new_rect);
+ }
- w = new_rect.width;
- h = new_rect.height;
- root_x_nw = new_rect.x;
- root_y_nw = new_rect.y;
+ if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
+ {
+ g_assert (window->frame == NULL);
- if (w != window->rect.width ||
- h != window->rect.height)
- need_resize_client = TRUE;
+ /* For wayland clients, the size is completely determined by the client,
+ * and while this allows to avoid some trickery with frames and the resulting
+ * lagging, we also need to insist a bit when the constraints would apply
+ * a different size than the client decides.
+ *
+ * Note that this is not generally a problem for normal toplevel windows (the
+ * constraints don't see the size hints, or just change the position), but
+ * it can be for maximized or fullscreen.
+ *
+ */
+ root_x_nw = new_rect.x;
+ root_y_nw = new_rect.y;
- window->rect.width = w;
- window->rect.height = h;
+ /* First, save where we would like the client to be. This is used by the next
+ * attach to determine if the client is really moving/resizing or not.
+ */
+ window->expected_rect = new_rect;
- if (window->frame)
- {
- int frame_size_dx, frame_size_dy;
- int new_w, new_h;
+ if (is_wayland_resize)
+ {
+ /* This is a call to wl_surface_commit(), ignore the new_rect and
+ * update the real client size to match the buffer size.
+ */
- new_w = window->rect.width + borders.total.left + borders.total.right;
+ window->rect.width = w;
+ window->rect.height = h;
+ }
- if (window->shaded)
- new_h = borders.total.top;
+ if (new_rect.width != window->rect.width ||
+ new_rect.height != window->rect.height)
+ {
+ /* We need to resize the client. Resizing is in two parts:
+ * some of the movement happens immediately, and some happens as part
+ * of the resizing (through dx/dy in wl_surface_attach).
+ *
+ * To do so, we need to compute the resize from the point of the view
+ * of the client, and then adjust the immediate resize to match.
+ *
+ * dx/dy are the values we expect from the new attach(), while deltax/
+ * deltay reflect the overall movement.
+ */
+ MetaRectangle client_rect;
+ int dx, dy;
+ int deltax, deltay;
+
+ meta_rectangle_resize_with_gravity (&old_rect,
+ &client_rect,
+ gravity,
+ new_rect.width,
+ new_rect.height);
+
+ deltax = new_rect.x - old_rect.x;
+ deltay = new_rect.y - old_rect.y;
+ dx = client_rect.x - old_rect.x;
+ dy = client_rect.y - old_rect.y;
+
+ if ((deltax - dx) != 0 ||
+ (deltay - dy) != 0)
+ need_move_client = TRUE;
+
+ window->rect.x += (deltax - dx);
+ window->rect.y += (deltay - dy);
+
+ need_resize_client = TRUE;
+ meta_wayland_surface_configure_notify (window->surface,
+ new_rect.width,
+ new_rect.height,
+ (dx != 0 ? WL_SHELL_SURFACE_RESIZE_LEFT : 0) |
+ (dy != 0 ? WL_SHELL_SURFACE_RESIZE_TOP : 0));
+ }
else
- new_h = window->rect.height + borders.total.top + borders.total.bottom;
+ {
+ /* No resize happening, we can just move the window and live with it. */
+ if (window->rect.x != new_rect.x ||
+ window->rect.y != new_rect.y)
+ need_move_client = TRUE;
- frame_size_dx = new_w - window->frame->rect.width;
- frame_size_dy = new_h - window->frame->rect.height;
+ window->rect.x = new_rect.x;
+ window->rect.y = new_rect.y;
+ }
+ }
+ else
+ {
+ /* Everything else is the old X11 code, including weird gravities,
+ * the interaction with frames and the synthetic configure notifies.
+ */
- need_resize_frame = (frame_size_dx != 0 || frame_size_dy != 0);
+ root_x_nw = new_rect.x;
+ root_y_nw = new_rect.y;
+ w = new_rect.width;
+ h = new_rect.height;
- window->frame->rect.width = new_w;
- window->frame->rect.height = new_h;
+ if (w != window->rect.width ||
+ h != window->rect.height)
+ need_resize_client = TRUE;
- meta_topic (META_DEBUG_GEOMETRY,
- "Calculated frame size %dx%d\n",
- window->frame->rect.width,
- window->frame->rect.height);
- }
+ window->rect.width = w;
+ window->rect.height = h;
- /* For nice effect, when growing the window we want to move/resize
- * the frame first, when shrinking the window we want to move/resize
- * the client first. If we grow one way and shrink the other,
- * see which way we're moving "more"
- *
- * Mail from Owen subject "Suggestion: Gravity and resizing from the left"
- * http://mail.gnome.org/archives/wm-spec-list/1999-November/msg00088.html
- *
- * An annoying fact you need to know in this code is that StaticGravity
- * does nothing if you _only_ resize or _only_ move the frame;
- * it must move _and_ resize, otherwise you get NorthWestGravity
- * behavior. The move and resize must actually occur, it is not
- * enough to set CWX | CWWidth but pass in the current size/pos.
- */
+ if (window->frame)
+ {
+ int frame_size_dx, frame_size_dy;
+ int new_w, new_h;
- if (window->frame)
- {
- int new_x, new_y;
- int frame_pos_dx, frame_pos_dy;
+ new_w = window->rect.width + borders.total.left + borders.total.right;
- /* Compute new frame coords */
- new_x = root_x_nw - borders.total.left;
- new_y = root_y_nw - borders.total.top;
+ if (window->shaded)
+ new_h = borders.total.top;
+ else
+ new_h = window->rect.height + borders.total.top + borders.total.bottom;
- frame_pos_dx = new_x - window->frame->rect.x;
- frame_pos_dy = new_y - window->frame->rect.y;
+ frame_size_dx = new_w - window->frame->rect.width;
+ frame_size_dy = new_h - window->frame->rect.height;
- need_move_frame = (frame_pos_dx != 0 || frame_pos_dy != 0);
+ need_resize_frame = (frame_size_dx != 0 || frame_size_dy != 0);
- window->frame->rect.x = new_x;
- window->frame->rect.y = new_y;
+ window->frame->rect.width = new_w;
+ window->frame->rect.height = new_h;
- /* If frame will both move and resize, then StaticGravity
- * on the child window will kick in and implicitly move
- * the child with respect to the frame. The implicit
- * move will keep the child in the same place with
- * respect to the root window. If frame only moves
- * or only resizes, then the child will just move along
- * with the frame.
- */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Calculated frame size %dx%d\n",
+ window->frame->rect.width,
+ window->frame->rect.height);
+ }
- /* window->rect.x, window->rect.y are relative to frame,
- * remember they are the server coords
+ /* For nice effect, when growing the window we want to move/resize
+ * the frame first, when shrinking the window we want to move/resize
+ * the client first. If we grow one way and shrink the other,
+ * see which way we're moving "more"
+ *
+ * Mail from Owen subject "Suggestion: Gravity and resizing from the left"
+ * http://mail.gnome.org/archives/wm-spec-list/1999-November/msg00088.html
+ *
+ * An annoying fact you need to know in this code is that StaticGravity
+ * does nothing if you _only_ resize or _only_ move the frame;
+ * it must move _and_ resize, otherwise you get NorthWestGravity
+ * behavior. The move and resize must actually occur, it is not
+ * enough to set CWX | CWWidth but pass in the current size/pos.
*/
- new_x = borders.total.left;
- new_y = borders.total.top;
-
- if (need_resize_frame && need_move_frame &&
- static_gravity_works (window->display))
+ if (window->frame)
{
- /* static gravity kicks in because frame
- * is both moved and resized
+ int new_x, new_y;
+ int frame_pos_dx, frame_pos_dy;
+
+ /* Compute new frame coords */
+ new_x = root_x_nw - borders.total.left;
+ new_y = root_y_nw - borders.total.top;
+
+ frame_pos_dx = new_x - window->frame->rect.x;
+ frame_pos_dy = new_y - window->frame->rect.y;
+
+ need_move_frame = (frame_pos_dx != 0 || frame_pos_dy != 0);
+
+ window->frame->rect.x = new_x;
+ window->frame->rect.y = new_y;
+
+ /* If frame will both move and resize, then StaticGravity
+ * on the child window will kick in and implicitly move
+ * the child with respect to the frame. The implicit
+ * move will keep the child in the same place with
+ * respect to the root window. If frame only moves
+ * or only resizes, then the child will just move along
+ * with the frame.
*/
- /* when we move the frame by frame_pos_dx, frame_pos_dy the
- * client will implicitly move relative to frame by the
- * inverse delta.
- *
- * When moving client then frame, we move the client by the
- * frame delta, to be canceled out by the implicit move by
- * the inverse frame delta, resulting in a client at new_x,
- * new_y.
- *
- * When moving frame then client, we move the client
- * by the same delta as the frame, because the client
- * was "left behind" by the frame - resulting in a client
- * at new_x, new_y.
- *
- * In both cases we need to move the client window
- * in all cases where we had to move the frame window.
+
+ /* window->rect.x, window->rect.y are relative to frame,
+ * remember they are the server coords
*/
- client_move_x = new_x + frame_pos_dx;
- client_move_y = new_y + frame_pos_dy;
+ new_x = borders.total.left;
+ new_y = borders.total.top;
- if (need_move_frame)
- need_move_client = TRUE;
+ if (need_resize_frame && need_move_frame &&
+ static_gravity_works (window->display))
+ {
+ /* static gravity kicks in because frame
+ * is both moved and resized
+ */
+ /* when we move the frame by frame_pos_dx, frame_pos_dy the
+ * client will implicitly move relative to frame by the
+ * inverse delta.
+ *
+ * When moving client then frame, we move the client by the
+ * frame delta, to be canceled out by the implicit move by
+ * the inverse frame delta, resulting in a client at new_x,
+ * new_y.
+ *
+ * When moving frame then client, we move the client
+ * by the same delta as the frame, because the client
+ * was "left behind" by the frame - resulting in a client
+ * at new_x, new_y.
+ *
+ * In both cases we need to move the client window
+ * in all cases where we had to move the frame window.
+ */
+
+ client_move_x = new_x + frame_pos_dx;
+ client_move_y = new_y + frame_pos_dy;
+
+ if (need_move_frame)
+ need_move_client = TRUE;
+
+ use_static_gravity = TRUE;
+ }
+ else
+ {
+ client_move_x = new_x;
+ client_move_y = new_y;
+
+ if (client_move_x != window->rect.x ||
+ client_move_y != window->rect.y)
+ need_move_client = TRUE;
+
+ use_static_gravity = FALSE;
+ }
- use_static_gravity = TRUE;
+ /* This is the final target position, but not necessarily what
+ * we pass to XConfigureWindow, due to StaticGravity implicit
+ * movement.
+ */
+ window->rect.x = new_x;
+ window->rect.y = new_y;
}
else
{
- client_move_x = new_x;
- client_move_y = new_y;
-
- if (client_move_x != window->rect.x ||
- client_move_y != window->rect.y)
+ if (root_x_nw != window->rect.x ||
+ root_y_nw != window->rect.y)
need_move_client = TRUE;
- use_static_gravity = FALSE;
- }
-
- /* This is the final target position, but not necessarily what
- * we pass to XConfigureWindow, due to StaticGravity implicit
- * movement.
- */
- window->rect.x = new_x;
- window->rect.y = new_y;
- }
- else
- {
- if (root_x_nw != window->rect.x ||
- root_y_nw != window->rect.y)
- need_move_client = TRUE;
-
- window->rect.x = root_x_nw;
- window->rect.y = root_y_nw;
+ window->rect.x = root_x_nw;
+ window->rect.y = root_y_nw;
- client_move_x = window->rect.x;
- client_move_y = window->rect.y;
+ client_move_x = window->rect.x;
+ client_move_y = window->rect.y;
- use_static_gravity = FALSE;
- }
+ use_static_gravity = FALSE;
+ }
- /* If frame extents have changed, fill in other frame fields and
- change frame's extents property. */
- if (window->frame &&
- (window->frame->child_x != borders.total.left ||
- window->frame->child_y != borders.total.top ||
- window->frame->right_width != borders.total.right ||
- window->frame->bottom_height != borders.total.bottom))
- {
- window->frame->child_x = borders.total.left;
- window->frame->child_y = borders.total.top;
- window->frame->right_width = borders.total.right;
- window->frame->bottom_height = borders.total.bottom;
+ /* If frame extents have changed, fill in other frame fields and
+ change frame's extents property. */
+ if (window->frame &&
+ (window->frame->child_x != borders.total.left ||
+ window->frame->child_y != borders.total.top ||
+ window->frame->right_width != borders.total.right ||
+ window->frame->bottom_height != borders.total.bottom))
+ {
+ window->frame->child_x = borders.total.left;
+ window->frame->child_y = borders.total.top;
+ window->frame->right_width = borders.total.right;
+ window->frame->bottom_height = borders.total.bottom;
- update_net_frame_extents (window);
- }
+ update_net_frame_extents (window);
+ }
- /* See ICCCM 4.1.5 for when to send ConfigureNotify */
+ /* See ICCCM 4.1.5 for when to send ConfigureNotify */
- need_configure_notify = FALSE;
+ need_configure_notify = FALSE;
- /* If this is a configure request and we change nothing, then we
- * must send configure notify.
- */
- if (is_configure_request &&
- !(need_move_client || need_move_frame ||
- need_resize_client || need_resize_frame ||
- window->border_width != 0))
- need_configure_notify = TRUE;
-
- /* We must send configure notify if we move but don't resize, since
- * the client window may not get a real event
- */
- if ((need_move_client || need_move_frame) &&
- !(need_resize_client || need_resize_frame))
- need_configure_notify = TRUE;
-
- /* MapRequest events with a PPosition or UPosition hint with a frame
- * are moved by mutter without resizing; send a configure notify
- * in such cases. See #322840. (Note that window->constructing is
- * only true iff this call is due to a MapRequest, and when
- * PPosition/UPosition hints aren't set, mutter seems to send a
- * ConfigureNotify anyway due to the above code.)
- */
- if (window->constructing && window->frame &&
- ((window->size_hints.flags & PPosition) ||
- (window->size_hints.flags & USPosition)))
- need_configure_notify = TRUE;
+ /* If this is a configure request and we change nothing, then we
+ * must send configure notify.
+ */
+ if (is_configure_request &&
+ !(need_move_client || need_move_frame ||
+ need_resize_client || need_resize_frame ||
+ window->border_width != 0))
+ need_configure_notify = TRUE;
+
+ /* We must send configure notify if we move but don't resize, since
+ * the client window may not get a real event
+ */
+ if ((need_move_client || need_move_frame) &&
+ !(need_resize_client || need_resize_frame))
+ need_configure_notify = TRUE;
+
+ /* MapRequest events with a PPosition or UPosition hint with a frame
+ * are moved by mutter without resizing; send a configure notify
+ * in such cases. See #322840. (Note that window->constructing is
+ * only true iff this call is due to a MapRequest, and when
+ * PPosition/UPosition hints aren't set, mutter seems to send a
+ * ConfigureNotify anyway due to the above code.)
+ */
+ if (window->constructing && window->frame &&
+ ((window->size_hints.flags & PPosition) ||
+ (window->size_hints.flags & USPosition)))
+ need_configure_notify = TRUE;
- /* The rest of this function syncs our new size/pos with X as
- * efficiently as possible
- */
+ /* The rest of this function syncs our new size/pos with X as
+ * efficiently as possible
+ */
- /* Normally, we configure the frame first depending on whether
- * we grow the frame more than we shrink. The idea is to avoid
- * messing up the window contents by having a temporary situation
- * where the frame is smaller than the window. However, if we're
- * cooperating with the client to create an atomic frame upate,
- * and the window is redirected, then we should always update
- * the frame first, since updating the frame will force a new
- * backing pixmap to be allocated, and the old backing pixmap
- * will be left undisturbed for us to paint to the screen until
- * the client finishes redrawing.
- */
- if (window->extended_sync_request_counter)
- {
- configure_frame_first = TRUE;
- }
- else
- {
- size_dx = w - window->rect.width;
- size_dy = h - window->rect.height;
+ /* Normally, we configure the frame first depending on whether
+ * we grow the frame more than we shrink. The idea is to avoid
+ * messing up the window contents by having a temporary situation
+ * where the frame is smaller than the window. However, if we're
+ * cooperating with the client to create an atomic frame upate,
+ * and the window is redirected, then we should always update
+ * the frame first, since updating the frame will force a new
+ * backing pixmap to be allocated, and the old backing pixmap
+ * will be left undisturbed for us to paint to the screen until
+ * the client finishes redrawing.
+ */
+ if (window->extended_sync_request_counter)
+ {
+ configure_frame_first = TRUE;
+ }
+ else
+ {
+ size_dx = w - window->rect.width;
+ size_dy = h - window->rect.height;
- configure_frame_first = size_dx + size_dy >= 0;
- }
+ configure_frame_first = size_dx + size_dy >= 0;
+ }
- if (use_static_gravity)
- meta_window_set_gravity (window, StaticGravity);
+ if (use_static_gravity)
+ meta_window_set_gravity (window, StaticGravity);
- if (configure_frame_first && window->frame)
- frame_shape_changed = meta_frame_sync_to_window (window->frame,
- gravity,
- need_move_frame, need_resize_frame);
+ if (configure_frame_first && window->frame)
+ frame_shape_changed = meta_frame_sync_to_window (window->frame,
+ gravity,
+ need_move_frame, need_resize_frame);
- values.border_width = 0;
- values.x = client_move_x;
- values.y = client_move_y;
- values.width = window->rect.width;
- values.height = window->rect.height;
+ values.border_width = 0;
+ values.x = client_move_x;
+ values.y = client_move_y;
+ values.width = window->rect.width;
+ values.height = window->rect.height;
- mask = 0;
- if (is_configure_request && window->border_width != 0)
- mask |= CWBorderWidth; /* must force to 0 */
- if (need_move_client)
- mask |= (CWX | CWY);
- if (need_resize_client)
- mask |= (CWWidth | CWHeight);
+ mask = 0;
+ if (is_configure_request && window->border_width != 0)
+ mask |= CWBorderWidth; /* must force to 0 */
+ if (need_move_client)
+ mask |= (CWX | CWY);
+ if (need_resize_client)
+ mask |= (CWWidth | CWHeight);
- if (mask != 0)
- {
- {
- int newx, newy;
- meta_window_get_position (window, &newx, &newy);
- meta_topic (META_DEBUG_GEOMETRY,
- "Syncing new client geometry %d,%d %dx%d, border: %s pos: %s size: %s\n",
- newx, newy,
- window->rect.width, window->rect.height,
- mask & CWBorderWidth ? "true" : "false",
- need_move_client ? "true" : "false",
- need_resize_client ? "true" : "false");
- }
+ if (mask != 0)
+ {
+ {
+ int newx, newy;
+ meta_window_get_position (window, &newx, &newy);
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Syncing new client geometry %d,%d %dx%d, border: %s pos: %s size: %s\n",
+ newx, newy,
+ window->rect.width, window->rect.height,
+ mask & CWBorderWidth ? "true" : "false",
+ need_move_client ? "true" : "false",
+ need_resize_client ? "true" : "false");
+ }
- meta_error_trap_push (window->display);
+ meta_error_trap_push (window->display);
#ifdef HAVE_XSYNC
- if (window == window->display->grab_window &&
- meta_grab_op_is_resizing (window->display->grab_op) &&
- !window->disable_sync &&
- window->sync_request_counter != None &&
- window->sync_request_alarm != None &&
- window->sync_request_timeout_id == 0)
- {
- send_sync_request (window);
- }
+ if (window == window->display->grab_window &&
+ meta_grab_op_is_resizing (window->display->grab_op) &&
+ !window->disable_sync &&
+ window->sync_request_counter != None &&
+ window->sync_request_alarm != None &&
+ window->sync_request_timeout_id == 0)
+ {
+ send_sync_request (window);
+ }
#endif
- XConfigureWindow (window->display->xdisplay,
- window->xwindow,
- mask,
- &values);
+ XConfigureWindow (window->display->xdisplay,
+ window->xwindow,
+ mask,
+ &values);
- meta_error_trap_pop (window->display);
- }
+ meta_error_trap_pop (window->display);
+ }
- if (!configure_frame_first && window->frame)
- frame_shape_changed = meta_frame_sync_to_window (window->frame,
- gravity,
- need_move_frame, need_resize_frame);
+ if (!configure_frame_first && window->frame)
+ frame_shape_changed = meta_frame_sync_to_window (window->frame,
+ gravity,
+ need_move_frame, need_resize_frame);
- /* Put gravity back to be nice to lesser window managers */
- if (use_static_gravity)
- meta_window_set_gravity (window, NorthWestGravity);
+ /* Put gravity back to be nice to lesser window managers */
+ if (use_static_gravity)
+ meta_window_set_gravity (window, NorthWestGravity);
- if (need_configure_notify)
- send_configure_notify (window);
+ if (need_configure_notify)
+ send_configure_notify (window);
+ }
if (!window->placed && window->force_save_user_rect && !window->fullscreen)
force_save_user_window_placement (window);
@@ -5408,7 +5512,7 @@ meta_window_move_resize_internal (MetaWindow *window,
if (need_move_frame || need_resize_frame ||
need_move_client || need_resize_client ||
- did_placement)
+ did_placement || is_wayland_resize)
{
int newx, newy;
meta_window_get_position (window, &newx, &newy);
@@ -5478,6 +5582,34 @@ meta_window_resize (MetaWindow *window,
x, y, w, h);
}
+/*
+ * meta_window_move_resize_wayland:
+ *
+ * Complete a resize operation from a wayland client.
+ *
+ */
+void
+meta_window_move_resize_wayland (MetaWindow *window,
+ int width,
+ int height,
+ int dx,
+ int dy)
+{
+ int x, y;
+ MetaMoveResizeFlags flags;
+
+ flags = META_IS_RESIZE_ACTION | META_IS_WAYLAND_RESIZE;
+
+ meta_window_get_position (window, &x, &y);
+ x += dx; y += dy;
+
+ if (x != window->expected_rect.x || y != window->expected_rect.y)
+ flags |= META_IS_MOVE_ACTION;
+
+ meta_window_move_resize_internal (window, flags, NorthWestGravity,
+ x, y, width, height);
+}
+
/**
* meta_window_move:
* @window: a #MetaWindow
diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
index f0c6edc..90182ed 100644
--- a/src/wayland/meta-wayland-keyboard.c
+++ b/src/wayland/meta-wayland-keyboard.c
@@ -486,7 +486,7 @@ process_keybinding (MetaWaylandKeyboard *keyboard,
surface = keyboard->focus;
if (surface)
- device_event.event = surface->xid;
+ device_event.event = surface->window ? surface->window->xwindow : device_event.root;
else
device_event.event = device_event.root;
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 4da6cb8..2c90eed 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -64,8 +64,9 @@ static void
surface_process_damage (MetaWaylandSurface *surface,
cairo_region_t *region)
{
- if (surface->window &&
- surface->buffer_ref.buffer)
+ g_assert (surface->window);
+
+ if (surface->buffer_ref.buffer)
{
MetaWindowActor *window_actor =
META_WINDOW_ACTOR (meta_window_get_compositor_private (surface->window));
@@ -111,7 +112,7 @@ 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)
+ gint32 dx, gint32 dy)
{
MetaWaylandSurface *surface =
wl_resource_get_user_data (wayland_surface_resource);
@@ -130,8 +131,8 @@ meta_wayland_surface_attach (struct wl_client *wayland_client,
if (surface->pending.buffer)
wl_list_remove (&surface->pending.buffer_destroy_listener.link);
- surface->pending.sx = sx;
- surface->pending.sy = sy;
+ surface->pending.dx = dx;
+ surface->pending.dy = dy;
surface->pending.buffer = buffer;
surface->pending.newly_attached = TRUE;
@@ -252,31 +253,49 @@ meta_wayland_surface_commit (struct wl_client *client,
* surface. */
meta_wayland_buffer_reference (&surface->buffer_ref,
surface->pending.buffer);
+ }
- if (surface->pending.buffer)
- {
- MetaWaylandBuffer *buffer = surface->pending.buffer;
+ if (surface->initial)
+ {
+ MetaDisplay *display = meta_get_display ();
- if (surface->window)
- {
- MetaWindow *window = surface->window;
- MetaWindowActor *window_actor =
- META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
- MetaRectangle rect;
+ /* This will free and clear initial */
+ surface->window = meta_window_new_for_wayland (display, width, height, surface);
+ }
+
+ if (surface == compositor->seat->sprite)
+ meta_wayland_seat_update_sprite (compositor->seat);
+ else if (surface->window)
+ {
+ MetaWindow *window = surface->window;
- meta_window_get_input_rect (surface->window, &rect);
+ if (surface->pending.buffer)
+ {
+ MetaWaylandBuffer *buffer = surface->pending.buffer;
+ MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
- if (window_actor)
- meta_window_actor_attach_wayland_buffer (window_actor, buffer);
+ 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);
- }
+ /* We resize X based surfaces according to X events */
+ if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
+ {
+ int new_width;
+ int new_height;
+
+ new_width = surface->buffer_ref.buffer->width;
+ new_height = surface->buffer_ref.buffer->height;
+ if (new_width != window->rect.width ||
+ new_height != window->rect.height ||
+ surface->pending.dx != 0 ||
+ surface->pending.dy != 0)
+ meta_window_move_resize_wayland (surface->window, new_width, new_height,
+ surface->pending.dx, surface->pending.dy);
+ }
+
+ meta_window_set_opaque_region (surface->window, surface->pending.opaque_region);
+ meta_window_set_input_region (surface->window, surface->pending.input_region);
+ surface_process_damage (surface, surface->pending.damage);
}
if (surface->pending.buffer)
@@ -284,20 +303,11 @@ meta_wayland_surface_commit (struct wl_client *client,
wl_list_remove (&surface->pending.buffer_destroy_listener.link);
surface->pending.buffer = NULL;
}
- surface->pending.sx = 0;
- surface->pending.sy = 0;
+ surface->pending.dx = 0;
+ surface->pending.dy = 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);
+ g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
+ g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
empty_region (surface->pending.damage);
/* wl_surface.frame */
@@ -632,32 +642,6 @@ shell_surface_resize (struct wl_client *client,
g_warning ("TODO: support shell_surface_resize request");
}
-static gboolean
-ensure_surface_window (MetaWaylandSurface *surface)
-{
- MetaDisplay *display = meta_get_display ();
- int width, height;
-
- if (surface->window)
- return FALSE;
-
- 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);
-
- return TRUE;
-}
-
static void
shell_surface_set_toplevel (struct wl_client *client,
struct wl_resource *resource)
@@ -670,8 +654,19 @@ shell_surface_set_toplevel (struct wl_client *client,
if (client == compositor->xwayland_client)
return;
- if (!ensure_surface_window (surface))
- meta_window_unmake_fullscreen (surface->window);
+ if (surface->window)
+ {
+ if (surface->window->fullscreen)
+ meta_window_unmake_fullscreen (surface->window);
+ if (meta_window_get_maximized (surface->window) != 0)
+ meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
+ }
+ else
+ {
+ ensure_initial_state (surface);
+
+ surface->initial_type = META_WAYLAND_SURFACE_TOPLEVEL;
+ }
}
static void
@@ -691,8 +686,15 @@ shell_surface_set_transient (struct wl_client *client,
if (client == compositor->xwayland_client)
return;
- ensure_surface_window (surface);
- meta_window_set_transient_for (surface->window, parent_surface->window);
+ if (surface->window)
+ meta_window_set_transient_for (surface->window, parent_surface->window);
+ else
+ {
+ ensure_initial_state (surface);
+
+ surface->initial_type = META_WAYLAND_SURFACE_TOPLEVEL;
+ surface->transient_for = parent;
+ }
}
static void
@@ -710,9 +712,14 @@ shell_surface_set_fullscreen (struct wl_client *client,
if (client == compositor->xwayland_client)
return;
- ensure_surface_window (surface);
+ if (surface->window)
+ meta_window_make_fullscreen (surface->window);
+ else
+ {
+ ensure_initial_state (surface);
- meta_window_make_fullscreen (surface->window);
+ surface->initial_type = META_WAYLAND_SURFACE_FULLSCREEN;
+ }
}
static void
@@ -741,7 +748,7 @@ shell_surface_set_maximized (struct wl_client *client,
return;
ensure_surface_window (surface);
- meta_window_maximize (surface->window);
+ meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
}
static void
@@ -821,7 +828,7 @@ destroy_surface_extension (struct wl_resource *resource)
g_free (extension);
}
-static void
+static MetaWaylandSurfaceExtension *
create_surface_extension (struct wl_client *client,
struct wl_resource *master_resource,
guint32 id,
@@ -842,6 +849,8 @@ create_surface_extension (struct wl_client *client,
extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
wl_resource_add_destroy_listener (surface->resource,
&extension->surface_destroy_listener);
+
+ return extension;
}
static void
@@ -852,7 +861,7 @@ get_shell_surface (struct wl_client *client,
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
- if (surface->has_shell_surface)
+ if (surface->shell_surface)
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -860,10 +869,9 @@ get_shell_surface (struct wl_client *client,
return;
}
- create_surface_extension (client, resource, id, surface,
- &wl_shell_surface_interface,
- &meta_wayland_shell_surface_interface);
- surface->has_shell_surface = TRUE;
+ surface->shell_surface = create_surface_extension (client, resource, id, surface,
+ &wl_shell_surface_interface,
+ &meta_wayland_shell_surface_interface);
}
static const struct wl_shell_interface meta_wayland_shell_interface =
@@ -954,7 +962,7 @@ get_gtk_surface (struct wl_client *client,
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
- if (surface->has_gtk_surface)
+ if (surface->gtk_surface)
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -962,10 +970,9 @@ get_gtk_surface (struct wl_client *client,
return;
}
- create_surface_extension (client, resource, id, surface,
- >k_surface_interface,
- &meta_wayland_gtk_surface_interface);
- surface->has_gtk_surface = TRUE;
+ surface->gtk_surface = create_surface_extension (client, resource, id, surface,
+ >k_surface_interface,
+ &meta_wayland_gtk_surface_interface);
}
static const struct gtk_shell_interface meta_wayland_gtk_shell_interface =
@@ -1053,3 +1060,14 @@ free_initial_state (MetaWaylandSurfaceInitialState *initial)
g_slice_free (MetaWaylandSurfaceInitialState, initial);
}
+
+void
+meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
+ int new_width,
+ int new_height,
+ int edges)
+{
+ if (surface->shell_surface)
+ wl_shell_surface_send_configure (surface->shell_surface->resource,
+ edges, new_width, new_height);
+}
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 5957bce..3e5ee0e 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -52,8 +52,8 @@ typedef struct
gboolean newly_attached;
MetaWaylandBuffer *buffer;
struct wl_listener buffer_destroy_listener;
- int32_t sx;
- int32_t sy;
+ int32_t dx;
+ int32_t dy;
/* wl_surface.damage */
cairo_region_t *damage;
@@ -65,8 +65,17 @@ typedef struct
struct wl_list frame_callback_list;
} MetaWaylandDoubleBufferedState;
+typedef enum {
+ META_WAYLAND_SURFACE_TOPLEVEL,
+ META_WAYLAND_SURFACE_MAXIMIZED,
+ META_WAYLAND_SURFACE_TRANSIENT
+};
+
typedef struct
{
+ int initial_type;
+ struct wl_resource *transient_for;
+
char *title;
char *wm_class;
@@ -78,17 +87,21 @@ typedef struct
char *gtk_window_object_path;
} MetaWaylandSurfaceInitialState;
+typedef struct
+{
+ MetaWaylandSurface *surface;
+ struct wl_resource *resource;
+ struct wl_listener surface_destroy_listener;
+} MetaWaylandSurfaceExtension;
+
struct _MetaWaylandSurface
{
struct wl_resource *resource;
MetaWaylandCompositor *compositor;
- guint32 xid;
- int x;
- int y;
MetaWaylandBufferReference buffer_ref;
MetaWindow *window;
- gboolean has_shell_surface;
- gboolean has_gtk_surface;
+ MetaWaylandSurfaceExtension *shell_surface;
+ MetaWaylandSurfaceExtension *gtk_surface;
/* All the pending state, that wl_surface.commit will apply. */
MetaWaylandDoubleBufferedState pending;
@@ -98,13 +111,6 @@ struct _MetaWaylandSurface
MetaWaylandSurfaceInitialState *initial_state;
};
-typedef struct
-{
- MetaWaylandSurface *surface;
- struct wl_resource *resource;
- struct wl_listener surface_destroy_listener;
-} MetaWaylandSurfaceExtension;
-
void meta_wayland_init_shell (MetaWaylandCompositor *compositor);
MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *compositor,
@@ -116,4 +122,9 @@ void meta_wayland_surface_free (MetaWaylandSurface *surface)
void meta_wayland_surface_set_initial_state (MetaWaylandSurface *surface,
MetaWindow *window);
+void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
+ int width,
+ int height,
+ int edges);
+
#endif
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 51e064a..d2e99b5 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -609,8 +609,8 @@ synthesize_motion_event (MetaWaylandCompositor *compositor,
device_event.event_y = wl_fixed_to_double (pointer->y);
}
- if (surface && surface->xid != None)
- device_event.event = surface->xid;
+ if (surface && surface->window != NULL)
+ device_event.event = surface->window->xwindow;
else
device_event.event = device_event.root;
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index 49cc51d..0e67c6d 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -45,10 +45,6 @@ xserver_set_window_id (struct wl_client *client,
MetaDisplay *display = meta_get_display ();
MetaWindow *window;
- g_return_if_fail (surface->xid == None);
-
- surface->xid = xid;
-
window = meta_display_lookup_x_window (display, xid);
if (window)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]