2014-03-19 09:26:17 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Red Hat
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* Written by:
|
|
|
|
* Jasper St. Pierre <jstpierre@mecheye.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2015-04-27 21:09:16 -04:00
|
|
|
#include "meta-window-wayland.h"
|
2014-03-19 09:26:17 -04:00
|
|
|
|
2014-05-20 09:08:11 -04:00
|
|
|
#include <meta/errors.h>
|
2014-03-19 09:26:17 -04:00
|
|
|
#include "window-private.h"
|
2014-03-19 10:30:12 -04:00
|
|
|
#include "boxes-private.h"
|
2014-03-19 09:36:15 -04:00
|
|
|
#include "stack-tracker.h"
|
|
|
|
#include "meta-wayland-surface.h"
|
2015-03-02 22:13:05 -05:00
|
|
|
#include "compositor/meta-surface-actor-wayland.h"
|
2014-03-19 09:26:17 -04:00
|
|
|
|
|
|
|
struct _MetaWindowWayland
|
|
|
|
{
|
|
|
|
MetaWindow parent;
|
2014-04-28 16:19:06 -04:00
|
|
|
|
wayland-surface: Don't do pending move/resizes on all commits
We assume in meta_window_wayland_move_resize that the next commit that
changes the geometry will always be for our next pending operation, so
if we have a move pending on a resize, the next commit will trigger the
move. This is, of course, fundamentally wrong.
We broke this assumption even more now that we don't fizzle out calls to
meta_window_move_resize_internal and now call it on every commit, which
means that a simple damage and then commit would complete a pending
move.
This was even broken by apps like weston-terminal, which, when clicking
on the maximize button, first redraws the terminal with the maximize
button state back on hover on press, and would only redraw when it got
the configure event with the coordinates.
To track the correct commit to apply the move for, we implement the
ack_configure request and ignore all move/resizes that happen before
that.
Right now, we actually fizzle out the entire move/resize if there's a
future pending configure we're waiting on.
2014-07-27 11:23:17 -04:00
|
|
|
MetaWaylandSerial pending_configure_serial;
|
2014-07-27 11:37:18 -04:00
|
|
|
gboolean has_pending_move;
|
|
|
|
int pending_move_x;
|
|
|
|
int pending_move_y;
|
2014-05-12 18:05:31 -04:00
|
|
|
|
|
|
|
int last_sent_width;
|
|
|
|
int last_sent_height;
|
2014-03-19 09:26:17 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _MetaWindowWaylandClass
|
|
|
|
{
|
|
|
|
MetaWindowClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaWindowWayland, meta_window_wayland, META_TYPE_WINDOW)
|
|
|
|
|
2014-03-19 09:36:15 -04:00
|
|
|
static void
|
|
|
|
meta_window_wayland_manage (MetaWindow *window)
|
|
|
|
{
|
|
|
|
MetaDisplay *display = window->display;
|
|
|
|
|
|
|
|
meta_display_register_wayland_window (display, window);
|
|
|
|
|
|
|
|
{
|
|
|
|
meta_stack_tracker_record_add (window->screen->stack_tracker,
|
2014-09-08 21:20:14 -04:00
|
|
|
window->stamp,
|
2014-03-19 09:36:15 -04:00
|
|
|
0);
|
|
|
|
}
|
2015-02-24 14:55:45 -05:00
|
|
|
|
|
|
|
if (window->surface->role == META_WAYLAND_SURFACE_ROLE_XDG_POPUP)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *parent = window->surface->popup.parent;
|
|
|
|
|
|
|
|
g_assert (parent);
|
|
|
|
|
|
|
|
meta_window_set_transient_for (window, parent->window);
|
|
|
|
meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU);
|
|
|
|
}
|
2014-03-19 09:36:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_window_wayland_unmanage (MetaWindow *window)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
meta_stack_tracker_record_remove (window->screen->stack_tracker,
|
2014-09-08 21:20:14 -04:00
|
|
|
window->stamp,
|
2014-03-19 09:36:15 -04:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_display_unregister_wayland_window (window->display, window);
|
|
|
|
}
|
|
|
|
|
2014-03-20 15:12:44 -04:00
|
|
|
static void
|
|
|
|
meta_window_wayland_ping (MetaWindow *window,
|
|
|
|
guint32 serial)
|
|
|
|
{
|
|
|
|
meta_wayland_surface_ping (window->surface, serial);
|
|
|
|
}
|
|
|
|
|
2014-03-20 15:07:44 -04:00
|
|
|
static void
|
|
|
|
meta_window_wayland_delete (MetaWindow *window,
|
|
|
|
guint32 timestamp)
|
|
|
|
{
|
|
|
|
meta_wayland_surface_delete (window->surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_window_wayland_kill (MetaWindow *window)
|
|
|
|
{
|
2014-03-25 12:05:21 -04:00
|
|
|
MetaWaylandSurface *surface = window->surface;
|
|
|
|
struct wl_resource *resource = surface->resource;
|
|
|
|
|
|
|
|
/* Send the client an unrecoverable error to kill the client. */
|
|
|
|
wl_resource_post_error (resource,
|
|
|
|
WL_DISPLAY_ERROR_NO_MEMORY,
|
|
|
|
"User requested that we kill you. Sorry. Don't take it too personally.");
|
2014-03-20 15:07:44 -04:00
|
|
|
}
|
|
|
|
|
2014-03-20 15:16:57 -04:00
|
|
|
static void
|
|
|
|
meta_window_wayland_focus (MetaWindow *window,
|
|
|
|
guint32 timestamp)
|
|
|
|
{
|
|
|
|
meta_display_set_input_focus_window (window->display,
|
|
|
|
window,
|
|
|
|
FALSE,
|
|
|
|
timestamp);
|
|
|
|
}
|
|
|
|
|
2014-05-20 15:54:39 -04:00
|
|
|
static void
|
|
|
|
surface_state_changed (MetaWindow *window)
|
|
|
|
{
|
|
|
|
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
|
|
|
|
|
|
|
|
meta_wayland_surface_configure_notify (window->surface,
|
|
|
|
wl_window->last_sent_width,
|
wayland-surface: Don't do pending move/resizes on all commits
We assume in meta_window_wayland_move_resize that the next commit that
changes the geometry will always be for our next pending operation, so
if we have a move pending on a resize, the next commit will trigger the
move. This is, of course, fundamentally wrong.
We broke this assumption even more now that we don't fizzle out calls to
meta_window_move_resize_internal and now call it on every commit, which
means that a simple damage and then commit would complete a pending
move.
This was even broken by apps like weston-terminal, which, when clicking
on the maximize button, first redraws the terminal with the maximize
button state back on hover on press, and would only redraw when it got
the configure event with the coordinates.
To track the correct commit to apply the move for, we implement the
ack_configure request and ignore all move/resizes that happen before
that.
Right now, we actually fizzle out the entire move/resize if there's a
future pending configure we're waiting on.
2014-07-27 11:23:17 -04:00
|
|
|
wl_window->last_sent_height,
|
|
|
|
&wl_window->pending_configure_serial);
|
2014-05-20 15:54:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_window_wayland_grab_op_began (MetaWindow *window,
|
|
|
|
MetaGrabOp op)
|
|
|
|
{
|
2014-07-17 15:53:38 -04:00
|
|
|
if (meta_grab_op_is_resizing (op))
|
|
|
|
surface_state_changed (window);
|
2014-05-20 15:54:39 -04:00
|
|
|
|
|
|
|
META_WINDOW_CLASS (meta_window_wayland_parent_class)->grab_op_began (window, op);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_window_wayland_grab_op_ended (MetaWindow *window,
|
|
|
|
MetaGrabOp op)
|
|
|
|
{
|
2014-07-17 15:53:38 -04:00
|
|
|
if (meta_grab_op_is_resizing (op))
|
|
|
|
surface_state_changed (window);
|
2014-05-20 15:54:39 -04:00
|
|
|
|
|
|
|
META_WINDOW_CLASS (meta_window_wayland_parent_class)->grab_op_ended (window, op);
|
|
|
|
}
|
|
|
|
|
2014-03-19 10:30:12 -04:00
|
|
|
static void
|
|
|
|
meta_window_wayland_move_resize_internal (MetaWindow *window,
|
|
|
|
int gravity,
|
2014-05-21 13:59:13 -04:00
|
|
|
MetaRectangle unconstrained_rect,
|
2014-03-19 10:30:12 -04:00
|
|
|
MetaRectangle constrained_rect,
|
|
|
|
MetaMoveResizeFlags flags,
|
|
|
|
MetaMoveResizeResultFlags *result)
|
|
|
|
{
|
2014-04-28 16:19:06 -04:00
|
|
|
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
|
2014-07-27 11:47:40 -04:00
|
|
|
gboolean can_move_now;
|
2014-04-16 16:28:43 -04:00
|
|
|
|
2014-03-19 10:30:12 -04:00
|
|
|
g_assert (window->frame == NULL);
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
2014-12-15 16:28:47 -05:00
|
|
|
if (flags & META_MOVE_RESIZE_WAYLAND_RESIZE)
|
2014-03-19 10:30:12 -04:00
|
|
|
{
|
|
|
|
/* This is a call to wl_surface_commit(), ignore the constrained_rect and
|
|
|
|
* update the real client size to match the buffer size.
|
|
|
|
*/
|
|
|
|
|
2014-07-17 17:26:22 -04:00
|
|
|
if (window->rect.width != unconstrained_rect.width ||
|
|
|
|
window->rect.height != unconstrained_rect.height)
|
|
|
|
{
|
|
|
|
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
|
|
|
|
window->rect.width = unconstrained_rect.width;
|
|
|
|
window->rect.height = unconstrained_rect.height;
|
|
|
|
}
|
|
|
|
|
2014-04-16 16:28:43 -04:00
|
|
|
/* This is a commit of an attach. We should move the window to match the
|
|
|
|
* new position the client wants. */
|
2014-07-27 11:47:40 -04:00
|
|
|
can_move_now = TRUE;
|
2014-03-19 10:30:12 -04:00
|
|
|
}
|
2014-07-27 12:30:33 -04:00
|
|
|
else
|
2014-03-19 10:30:12 -04:00
|
|
|
{
|
2014-12-15 16:44:22 -05:00
|
|
|
/* If the size changed, or the state changed, then we have to wait until
|
|
|
|
* the client acks our configure before moving the window. */
|
2014-07-27 12:30:33 -04:00
|
|
|
if (constrained_rect.width != window->rect.width ||
|
2014-12-15 16:44:22 -05:00
|
|
|
constrained_rect.height != window->rect.height ||
|
|
|
|
(flags & META_MOVE_RESIZE_STATE_CHANGED))
|
2014-07-27 12:30:33 -04:00
|
|
|
{
|
2015-03-16 21:39:57 -04:00
|
|
|
/* If the constrained size is 1x1 and the unconstrained size is 0x0
|
|
|
|
* it means that we are trying to resize a window where the client has
|
|
|
|
* not yet committed a buffer. The 1x1 constrained size is a result of
|
|
|
|
* how the constraints code works. Lets avoid trying to have the
|
|
|
|
* client configure itself to draw on a 1x1 surface.
|
|
|
|
*
|
|
|
|
* We cannot guard against only an empty unconstrained_rect here,
|
|
|
|
* because the client may have created a xdg surface without a buffer
|
|
|
|
* attached and asked it to be maximized. In such case we should let
|
|
|
|
* it know about the expected window geometry of a maximized window,
|
|
|
|
* even though there is currently no buffer attached. */
|
2014-09-17 11:36:31 -04:00
|
|
|
if (unconstrained_rect.width == 0 &&
|
2015-03-16 21:39:57 -04:00
|
|
|
unconstrained_rect.height == 0 &&
|
|
|
|
constrained_rect.width == 1 &&
|
|
|
|
constrained_rect.height == 1)
|
2014-09-17 11:36:31 -04:00
|
|
|
return;
|
|
|
|
|
2014-07-27 12:30:33 -04:00
|
|
|
meta_wayland_surface_configure_notify (window->surface,
|
|
|
|
constrained_rect.width,
|
|
|
|
constrained_rect.height,
|
|
|
|
&wl_window->pending_configure_serial);
|
2014-07-27 11:47:40 -04:00
|
|
|
|
2014-07-27 12:30:33 -04:00
|
|
|
/* We need to wait until the resize completes before we can move */
|
|
|
|
can_move_now = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We're just moving the window, so we don't need to wait for a configure
|
|
|
|
* and then ack to simply move the window. */
|
|
|
|
can_move_now = TRUE;
|
|
|
|
}
|
2014-04-16 16:28:43 -04:00
|
|
|
}
|
2014-03-19 10:30:12 -04:00
|
|
|
|
2014-09-16 21:16:19 -04:00
|
|
|
wl_window->last_sent_width = constrained_rect.width;
|
|
|
|
wl_window->last_sent_height = constrained_rect.height;
|
2014-09-16 21:11:56 -04:00
|
|
|
|
2014-07-27 11:47:40 -04:00
|
|
|
if (can_move_now)
|
2014-04-16 16:16:01 -04:00
|
|
|
{
|
2014-04-28 18:15:03 -04:00
|
|
|
int new_x = constrained_rect.x;
|
|
|
|
int new_y = constrained_rect.y;
|
2014-04-28 16:20:53 -04:00
|
|
|
|
2014-04-28 15:51:41 -04:00
|
|
|
if (new_x != window->rect.x || new_y != window->rect.y)
|
2014-04-28 15:50:40 -04:00
|
|
|
{
|
|
|
|
*result |= META_MOVE_RESIZE_RESULT_MOVED;
|
2014-06-26 11:02:57 -04:00
|
|
|
window->rect.x = new_x;
|
|
|
|
window->rect.y = new_y;
|
2014-07-07 13:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int new_buffer_x = new_x - window->custom_frame_extents.left;
|
|
|
|
int new_buffer_y = new_y - window->custom_frame_extents.top;
|
2014-06-26 11:02:57 -04:00
|
|
|
|
2014-07-07 13:06:47 -04:00
|
|
|
if (new_buffer_x != window->buffer_rect.x || new_buffer_y != window->buffer_rect.y)
|
|
|
|
{
|
|
|
|
*result |= META_MOVE_RESIZE_RESULT_MOVED;
|
2014-07-17 15:27:47 -04:00
|
|
|
window->buffer_rect.x = new_buffer_x;
|
|
|
|
window->buffer_rect.y = new_buffer_y;
|
2014-04-28 15:50:40 -04:00
|
|
|
}
|
2014-03-19 10:30:12 -04:00
|
|
|
}
|
2014-07-27 11:47:40 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int new_x = constrained_rect.x;
|
|
|
|
int new_y = constrained_rect.y;
|
|
|
|
|
|
|
|
if (new_x != window->rect.x || new_y != window->rect.y)
|
|
|
|
{
|
|
|
|
wl_window->has_pending_move = TRUE;
|
|
|
|
wl_window->pending_move_x = new_x;
|
|
|
|
wl_window->pending_move_y = new_y;
|
|
|
|
}
|
|
|
|
}
|
2014-03-19 10:30:12 -04:00
|
|
|
}
|
|
|
|
|
2015-03-02 22:13:05 -05:00
|
|
|
static void
|
|
|
|
meta_window_wayland_main_monitor_changed (MetaWindow *window,
|
|
|
|
const MetaMonitorInfo *old)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = window->surface;
|
|
|
|
|
|
|
|
if (surface)
|
|
|
|
{
|
|
|
|
MetaSurfaceActorWayland *actor =
|
|
|
|
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
|
|
|
|
|
|
|
|
meta_surface_actor_wayland_sync_state_recursive (actor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-19 09:26:17 -04:00
|
|
|
static void
|
2014-05-12 18:19:11 -04:00
|
|
|
appears_focused_changed (GObject *object,
|
|
|
|
GParamSpec *pspec,
|
|
|
|
gpointer user_data)
|
2014-03-19 09:26:17 -04:00
|
|
|
{
|
2014-05-12 18:19:11 -04:00
|
|
|
MetaWindow *window = META_WINDOW (object);
|
|
|
|
|
|
|
|
/* When we're unmanaging, we remove focus from the window,
|
|
|
|
* causing this to fire. Don't do anything in that case. */
|
|
|
|
if (window->unmanaging)
|
|
|
|
return;
|
|
|
|
|
2014-05-05 19:09:22 -04:00
|
|
|
surface_state_changed (window);
|
2014-05-12 18:19:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_window_wayland_init (MetaWindowWayland *wl_window)
|
|
|
|
{
|
|
|
|
MetaWindow *window = META_WINDOW (wl_window);
|
|
|
|
|
|
|
|
g_signal_connect (window, "notify::appears-focused",
|
|
|
|
G_CALLBACK (appears_focused_changed), NULL);
|
2014-03-19 09:26:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
|
|
|
|
{
|
2014-03-19 09:36:15 -04:00
|
|
|
MetaWindowClass *window_class = META_WINDOW_CLASS (klass);
|
|
|
|
|
|
|
|
window_class->manage = meta_window_wayland_manage;
|
|
|
|
window_class->unmanage = meta_window_wayland_unmanage;
|
2014-03-20 15:12:44 -04:00
|
|
|
window_class->ping = meta_window_wayland_ping;
|
2014-03-20 15:07:44 -04:00
|
|
|
window_class->delete = meta_window_wayland_delete;
|
|
|
|
window_class->kill = meta_window_wayland_kill;
|
2014-03-20 15:16:57 -04:00
|
|
|
window_class->focus = meta_window_wayland_focus;
|
2014-05-20 15:54:39 -04:00
|
|
|
window_class->grab_op_began = meta_window_wayland_grab_op_began;
|
|
|
|
window_class->grab_op_ended = meta_window_wayland_grab_op_ended;
|
2014-03-19 10:30:12 -04:00
|
|
|
window_class->move_resize_internal = meta_window_wayland_move_resize_internal;
|
2015-03-02 22:13:05 -05:00
|
|
|
window_class->main_monitor_changed = meta_window_wayland_main_monitor_changed;
|
2014-03-19 09:26:17 -04:00
|
|
|
}
|
2014-04-28 17:44:45 -04:00
|
|
|
|
2014-05-20 09:08:11 -04:00
|
|
|
MetaWindow *
|
|
|
|
meta_window_wayland_new (MetaDisplay *display,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
XWindowAttributes attrs;
|
|
|
|
MetaScreen *scr = display->screen;
|
|
|
|
MetaWindow *window;
|
|
|
|
|
|
|
|
attrs.x = 0;
|
|
|
|
attrs.y = 0;
|
2014-09-16 23:09:13 -04:00
|
|
|
attrs.width = 0;
|
|
|
|
attrs.height = 0;
|
2014-05-20 09:08:11 -04:00
|
|
|
attrs.border_width = 0;
|
|
|
|
attrs.depth = 24;
|
|
|
|
attrs.visual = NULL;
|
|
|
|
attrs.root = scr->xroot;
|
|
|
|
attrs.class = InputOutput;
|
|
|
|
attrs.bit_gravity = NorthWestGravity;
|
|
|
|
attrs.win_gravity = NorthWestGravity;
|
|
|
|
attrs.backing_store = 0;
|
|
|
|
attrs.backing_planes = ~0;
|
|
|
|
attrs.backing_pixel = 0;
|
|
|
|
attrs.save_under = 0;
|
|
|
|
attrs.colormap = 0;
|
|
|
|
attrs.map_installed = 1;
|
|
|
|
attrs.map_state = IsUnmapped;
|
|
|
|
attrs.all_event_masks = ~0;
|
|
|
|
attrs.your_event_mask = 0;
|
|
|
|
attrs.do_not_propagate_mask = 0;
|
|
|
|
attrs.override_redirect = 0;
|
|
|
|
attrs.screen = scr->xscreen;
|
|
|
|
|
|
|
|
/* XXX: Note: In the Wayland case we currently still trap X errors while
|
|
|
|
* creating a MetaWindow because we will still be making various redundant
|
|
|
|
* X requests (passing a window xid of None) until we thoroughly audit all
|
|
|
|
* the code to make sure it knows about non X based clients...
|
|
|
|
*/
|
|
|
|
meta_error_trap_push (display); /* Push a trap over all of window
|
|
|
|
* creation, to reduce XSync() calls
|
|
|
|
*/
|
|
|
|
|
|
|
|
window = _meta_window_shared_new (display,
|
|
|
|
scr,
|
|
|
|
META_WINDOW_CLIENT_TYPE_WAYLAND,
|
|
|
|
surface,
|
|
|
|
None,
|
|
|
|
WithdrawnState,
|
|
|
|
META_COMP_EFFECT_CREATE,
|
|
|
|
&attrs);
|
|
|
|
window->can_ping = TRUE;
|
|
|
|
|
|
|
|
meta_error_trap_pop (display); /* pop the XSync()-reducing trap */
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
2014-07-28 06:04:23 -04:00
|
|
|
static gboolean
|
|
|
|
should_do_pending_move (MetaWindowWayland *wl_window,
|
|
|
|
MetaWaylandSerial *acked_configure_serial)
|
|
|
|
{
|
|
|
|
if (!wl_window->has_pending_move)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (wl_window->pending_configure_serial.set)
|
|
|
|
{
|
|
|
|
/* If we're waiting for a configure and this isn't an ACK for
|
|
|
|
* any configure, then fizzle it out. */
|
|
|
|
if (!acked_configure_serial->set)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* If we're waiting for a configure and this isn't an ACK for
|
|
|
|
* the configure we're waiting for, then fizzle it out. */
|
|
|
|
if (acked_configure_serial->value != wl_window->pending_configure_serial.value)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2014-04-28 17:44:45 -04:00
|
|
|
/**
|
|
|
|
* meta_window_move_resize_wayland:
|
|
|
|
*
|
|
|
|
* Complete a resize operation from a wayland client.
|
|
|
|
*/
|
|
|
|
void
|
wayland-surface: Don't do pending move/resizes on all commits
We assume in meta_window_wayland_move_resize that the next commit that
changes the geometry will always be for our next pending operation, so
if we have a move pending on a resize, the next commit will trigger the
move. This is, of course, fundamentally wrong.
We broke this assumption even more now that we don't fizzle out calls to
meta_window_move_resize_internal and now call it on every commit, which
means that a simple damage and then commit would complete a pending
move.
This was even broken by apps like weston-terminal, which, when clicking
on the maximize button, first redraws the terminal with the maximize
button state back on hover on press, and would only redraw when it got
the configure event with the coordinates.
To track the correct commit to apply the move for, we implement the
ack_configure request and ignore all move/resizes that happen before
that.
Right now, we actually fizzle out the entire move/resize if there's a
future pending configure we're waiting on.
2014-07-27 11:23:17 -04:00
|
|
|
meta_window_wayland_move_resize (MetaWindow *window,
|
|
|
|
MetaWaylandSerial *acked_configure_serial,
|
|
|
|
MetaRectangle new_geom,
|
|
|
|
int dx,
|
|
|
|
int dy)
|
2014-04-28 17:44:45 -04:00
|
|
|
{
|
2014-04-28 18:15:03 -04:00
|
|
|
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
|
2014-05-01 19:09:13 -04:00
|
|
|
int gravity;
|
|
|
|
MetaRectangle rect;
|
2014-04-28 17:44:45 -04:00
|
|
|
MetaMoveResizeFlags flags;
|
|
|
|
|
2014-07-17 15:24:06 -04:00
|
|
|
/* XXX: Find a better place to store the window geometry offsets. */
|
2014-07-17 16:42:41 -04:00
|
|
|
window->custom_frame_extents.left = new_geom.x;
|
|
|
|
window->custom_frame_extents.top = new_geom.y;
|
2014-07-17 15:24:06 -04:00
|
|
|
|
2014-12-15 16:28:47 -05:00
|
|
|
flags = META_MOVE_RESIZE_WAYLAND_RESIZE;
|
2014-04-28 17:44:45 -04:00
|
|
|
|
2014-05-01 18:55:34 -04:00
|
|
|
/* x/y are ignored when we're doing interactive resizing */
|
2014-04-28 17:44:45 -04:00
|
|
|
if (!meta_grab_op_is_resizing (window->display->grab_op))
|
|
|
|
{
|
2014-07-28 06:04:23 -04:00
|
|
|
if (wl_window->has_pending_move && should_do_pending_move (wl_window, acked_configure_serial))
|
2014-05-01 18:55:34 -04:00
|
|
|
{
|
2014-07-27 11:37:18 -04:00
|
|
|
rect.x = wl_window->pending_move_x;
|
|
|
|
rect.y = wl_window->pending_move_y;
|
|
|
|
wl_window->has_pending_move = FALSE;
|
2014-12-15 16:28:47 -05:00
|
|
|
flags |= META_MOVE_RESIZE_MOVE_ACTION;
|
2014-05-01 18:55:34 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-07-14 16:45:48 -04:00
|
|
|
rect.x = window->rect.x;
|
|
|
|
rect.y = window->rect.y;
|
2014-05-01 18:55:34 -04:00
|
|
|
}
|
|
|
|
|
2014-04-28 17:44:45 -04:00
|
|
|
if (dx != 0 || dy != 0)
|
|
|
|
{
|
2014-05-01 19:09:13 -04:00
|
|
|
rect.x += dx;
|
|
|
|
rect.y += dy;
|
2014-12-15 16:28:47 -05:00
|
|
|
flags |= META_MOVE_RESIZE_MOVE_ACTION;
|
2014-04-28 17:44:45 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-28 06:04:23 -04:00
|
|
|
wl_window->pending_configure_serial.set = FALSE;
|
|
|
|
|
2014-07-17 15:24:06 -04:00
|
|
|
rect.width = new_geom.width;
|
|
|
|
rect.height = new_geom.height;
|
2014-05-01 19:09:13 -04:00
|
|
|
|
|
|
|
if (rect.width != window->rect.width || rect.height != window->rect.height)
|
2014-12-15 16:28:47 -05:00
|
|
|
flags |= META_MOVE_RESIZE_RESIZE_ACTION;
|
2014-04-28 17:44:45 -04:00
|
|
|
|
2014-05-01 19:09:13 -04:00
|
|
|
gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
|
|
|
|
meta_window_move_resize_internal (window, flags, gravity, rect);
|
2014-04-28 17:44:45 -04:00
|
|
|
}
|