[mutter/wip/wayland-work: 13/13] wip window resizing for wayland clients



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,
-                           &gtk_surface_interface,
-                           &meta_wayland_gtk_surface_interface);
-  surface->has_gtk_surface = TRUE;
+  surface->gtk_surface = create_surface_extension (client, resource, id, surface,
+                                                  &gtk_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]