window: Move move_resize_internal logic to protocol-specific directories
This commit is contained in:
parent
a377a1a110
commit
a53e094fcd
5 changed files with 610 additions and 555 deletions
|
@ -27,16 +27,6 @@
|
|||
#include "window-private.h"
|
||||
#include "frame.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_IS_CONFIGURE_REQUEST = 1 << 0,
|
||||
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_WAYLAND_RESIZE = 1 << 5
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
void meta_window_constrain (MetaWindow *window,
|
||||
MetaMoveResizeFlags flags,
|
||||
int resize_gravity,
|
||||
|
|
|
@ -65,13 +65,28 @@ typedef enum {
|
|||
|
||||
#define NUMBER_OF_QUEUES 3
|
||||
|
||||
|
||||
typedef enum {
|
||||
_NET_WM_BYPASS_COMPOSITOR_HINT_AUTO = 0,
|
||||
_NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1,
|
||||
_NET_WM_BYPASS_COMPOSITOR_HINT_OFF = 2,
|
||||
} MetaBypassCompositorHintValue;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_IS_CONFIGURE_REQUEST = 1 << 0,
|
||||
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_WAYLAND_RESIZE = 1 << 5
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_MOVE_RESIZE_RESULT_MOVED = 1 << 0,
|
||||
META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1,
|
||||
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
|
||||
} MetaMoveResizeResultFlags;
|
||||
|
||||
struct _MetaWindow
|
||||
{
|
||||
|
@ -456,6 +471,12 @@ struct _MetaWindowClass
|
|||
|
||||
void (*manage) (MetaWindow *window);
|
||||
void (*unmanage) (MetaWindow *window);
|
||||
void (*move_resize_internal) (MetaWindow *window,
|
||||
int gravity,
|
||||
MetaRectangle requested_rect,
|
||||
MetaRectangle constrained_rect,
|
||||
MetaMoveResizeFlags flags,
|
||||
MetaMoveResizeResultFlags *result);
|
||||
void (*get_default_skip_hints) (MetaWindow *window,
|
||||
gboolean *skip_taskbar_out,
|
||||
gboolean *skip_pager_out);
|
||||
|
@ -732,4 +753,9 @@ void meta_window_update_monitor (MetaWindow *window);
|
|||
void meta_window_set_urgent (MetaWindow *window,
|
||||
gboolean urgent);
|
||||
|
||||
void meta_window_update_resize (MetaWindow *window,
|
||||
gboolean snap,
|
||||
int x, int y,
|
||||
gboolean force);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,15 +73,12 @@
|
|||
static int destroying_windows_disallowed = 0;
|
||||
|
||||
|
||||
static void update_net_frame_extents (MetaWindow *window);
|
||||
static void invalidate_work_areas (MetaWindow *window);
|
||||
static void set_wm_state (MetaWindow *window);
|
||||
static void set_net_wm_state (MetaWindow *window);
|
||||
static void meta_window_set_above (MetaWindow *window,
|
||||
gboolean new_value);
|
||||
|
||||
static void send_configure_notify (MetaWindow *window);
|
||||
|
||||
static void meta_window_force_placement (MetaWindow *window);
|
||||
|
||||
static void meta_window_show (MetaWindow *window);
|
||||
|
@ -1578,12 +1575,6 @@ meta_window_unmanage (MetaWindow *window,
|
|||
if (window->maximized_horizontally || window->maximized_vertically)
|
||||
unmaximize_window_before_freeing (window);
|
||||
|
||||
/* The XReparentWindow call in meta_window_destroy_frame() moves the
|
||||
* window so we need to send a configure notify; see bug 399552. (We
|
||||
* also do this just in case a window got unmaximized.)
|
||||
*/
|
||||
send_configure_notify (window);
|
||||
|
||||
meta_window_unqueue (window, META_QUEUE_CALC_SHOWING |
|
||||
META_QUEUE_MOVE_RESIZE |
|
||||
META_QUEUE_UPDATE_ICON);
|
||||
|
@ -1619,9 +1610,6 @@ meta_window_unmanage (MetaWindow *window,
|
|||
|
||||
meta_window_destroy_sync_request_alarm (window);
|
||||
|
||||
if (window->frame)
|
||||
meta_window_destroy_frame (window);
|
||||
|
||||
/* If an undecorated window is being withdrawn, that will change the
|
||||
* stack as presented to the compositing manager, without actually
|
||||
* changing the stacking order of X windows.
|
||||
|
@ -1636,6 +1624,9 @@ meta_window_unmanage (MetaWindow *window,
|
|||
|
||||
META_WINDOW_GET_CLASS (window)->unmanage (window);
|
||||
|
||||
if (window->frame)
|
||||
meta_window_destroy_frame (window);
|
||||
|
||||
meta_prefs_remove_listener (prefs_changed_callback, window);
|
||||
meta_screen_queue_check_fullscreen (window->screen);
|
||||
|
||||
|
@ -4034,90 +4025,6 @@ meta_window_destroy_sync_request_alarm (MetaWindow *window)
|
|||
#endif /* HAVE_XSYNC */
|
||||
}
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
static gboolean
|
||||
sync_request_timeout (gpointer data)
|
||||
{
|
||||
MetaWindow *window = data;
|
||||
|
||||
window->sync_request_timeout_id = 0;
|
||||
|
||||
/* We have now waited for more than a second for the
|
||||
* application to respond to the sync request
|
||||
*/
|
||||
window->disable_sync = TRUE;
|
||||
|
||||
/* Reset the wait serial, so we don't continue freezing
|
||||
* window updates
|
||||
*/
|
||||
window->sync_request_wait_serial = 0;
|
||||
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
||||
meta_window_updates_are_frozen (window));
|
||||
|
||||
if (window == window->display->grab_window &&
|
||||
meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
update_resize (window,
|
||||
window->display->grab_last_user_action_was_snap,
|
||||
window->display->grab_latest_motion_x,
|
||||
window->display->grab_latest_motion_y,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
send_sync_request (MetaWindow *window)
|
||||
{
|
||||
XClientMessageEvent ev;
|
||||
gint64 wait_serial;
|
||||
|
||||
/* For the old style of _NET_WM_SYNC_REQUEST_COUNTER, we just have to
|
||||
* increase the value, but for the new "extended" style we need to
|
||||
* pick an even (unfrozen) value sufficiently ahead of the last serial
|
||||
* that we received from the client; the same code still works
|
||||
* for the old style. The increment of 240 is specified by the EWMH
|
||||
* and is (1 second) * (60fps) * (an increment of 4 per frame).
|
||||
*/
|
||||
wait_serial = window->sync_request_serial + 240;
|
||||
|
||||
window->sync_request_wait_serial = wait_serial;
|
||||
|
||||
ev.type = ClientMessage;
|
||||
ev.window = window->xwindow;
|
||||
ev.message_type = window->display->atom_WM_PROTOCOLS;
|
||||
ev.format = 32;
|
||||
ev.data.l[0] = window->display->atom__NET_WM_SYNC_REQUEST;
|
||||
/* FIXME: meta_display_get_current_time() is bad, but since calls
|
||||
* come from meta_window_move_resize_internal (which in turn come
|
||||
* from all over), I'm not sure what we can do to fix it. Do we
|
||||
* want to use _roundtrip, though?
|
||||
*/
|
||||
ev.data.l[1] = meta_display_get_current_time (window->display);
|
||||
ev.data.l[2] = wait_serial & G_GUINT64_CONSTANT(0xffffffff);
|
||||
ev.data.l[3] = wait_serial >> 32;
|
||||
ev.data.l[4] = window->extended_sync_request_counter ? 1 : 0;
|
||||
|
||||
/* We don't need to trap errors here as we are already
|
||||
* inside an error_trap_push()/pop() pair.
|
||||
*/
|
||||
XSendEvent (window->display->xdisplay,
|
||||
window->xwindow, False, 0, (XEvent*) &ev);
|
||||
|
||||
/* We give the window 1 sec to respond to _NET_WM_SYNC_REQUEST;
|
||||
* if this time expires, we consider the window unresponsive
|
||||
* and resize it unsynchonized.
|
||||
*/
|
||||
window->sync_request_timeout_id = g_timeout_add (1000,
|
||||
sync_request_timeout,
|
||||
window);
|
||||
|
||||
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
||||
meta_window_updates_are_frozen (window));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* meta_window_updates_are_frozen:
|
||||
* @window: a #MetaWindow
|
||||
|
@ -4307,30 +4214,21 @@ meta_window_move_resize_internal (MetaWindow *window,
|
|||
* we don't decorate wayland clients), and the client has acknowledged
|
||||
* the window size change.
|
||||
*/
|
||||
XWindowChanges values;
|
||||
unsigned int mask;
|
||||
gboolean need_configure_notify;
|
||||
MetaFrameBorders borders;
|
||||
gboolean need_move_client = FALSE;
|
||||
gboolean need_move_frame = FALSE;
|
||||
gboolean need_resize_client = FALSE;
|
||||
gboolean need_resize_frame = FALSE;
|
||||
int size_dx;
|
||||
int size_dy;
|
||||
gboolean frame_shape_changed = FALSE;
|
||||
|
||||
gboolean is_configure_request;
|
||||
gboolean do_gravity_adjust;
|
||||
gboolean is_user_action;
|
||||
gboolean is_wayland_resize;
|
||||
gboolean did_placement;
|
||||
gboolean configure_frame_first;
|
||||
/* used for the configure request, but may not be final
|
||||
* destination due to StaticGravity etc.
|
||||
*/
|
||||
int client_move_x;
|
||||
int client_move_y;
|
||||
MetaRectangle new_rect;
|
||||
MetaRectangle old_rect;
|
||||
MetaRectangle requested_rect;
|
||||
MetaMoveResizeResultFlags result;
|
||||
MetaFrameBorders borders;
|
||||
|
||||
g_return_if_fail (!window->override_redirect);
|
||||
|
||||
|
@ -4356,13 +4254,14 @@ meta_window_move_resize_internal (MetaWindow *window,
|
|||
is_user_action ? " (user move/resize)" : "",
|
||||
old_rect.x, old_rect.y, old_rect.width, old_rect.height);
|
||||
|
||||
meta_frame_calc_borders (window->frame,
|
||||
&borders);
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
new_rect.x = root_x_nw;
|
||||
new_rect.y = root_y_nw;
|
||||
new_rect.width = w;
|
||||
new_rect.height = h;
|
||||
requested_rect.x = root_x_nw;
|
||||
requested_rect.y = root_y_nw;
|
||||
requested_rect.width = w;
|
||||
requested_rect.height = h;
|
||||
|
||||
new_rect = requested_rect;
|
||||
|
||||
/* If this is a resize only, the position should be ignored and
|
||||
* instead obtained by resizing the old rectangle according to the
|
||||
|
@ -4409,363 +4308,21 @@ meta_window_move_resize_internal (MetaWindow *window,
|
|||
&new_rect);
|
||||
}
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
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.
|
||||
*
|
||||
*/
|
||||
root_x_nw = new_rect.x;
|
||||
root_y_nw = new_rect.y;
|
||||
|
||||
/* 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 (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.
|
||||
*/
|
||||
|
||||
window->rect.width = w;
|
||||
window->rect.height = h;
|
||||
}
|
||||
|
||||
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 || deltay != dy)
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* meta_window_constrain() might have maximized the window after placement,
|
||||
* changing the borders.
|
||||
*/
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
root_x_nw = new_rect.x;
|
||||
root_y_nw = new_rect.y;
|
||||
w = new_rect.width;
|
||||
h = new_rect.height;
|
||||
|
||||
if (w != window->rect.width ||
|
||||
h != window->rect.height)
|
||||
need_resize_client = TRUE;
|
||||
|
||||
window->rect.width = w;
|
||||
window->rect.height = h;
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
int frame_size_dx, frame_size_dy;
|
||||
int new_w, new_h;
|
||||
|
||||
new_w = window->rect.width + borders.total.left + borders.total.right;
|
||||
|
||||
if (window->shaded)
|
||||
new_h = borders.total.top;
|
||||
else
|
||||
new_h = window->rect.height + borders.total.top + borders.total.bottom;
|
||||
|
||||
frame_size_dx = new_w - window->frame->rect.width;
|
||||
frame_size_dy = new_h - window->frame->rect.height;
|
||||
|
||||
need_resize_frame = (frame_size_dx != 0 || frame_size_dy != 0);
|
||||
|
||||
window->frame->rect.width = new_w;
|
||||
window->frame->rect.height = new_h;
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Calculated frame size %dx%d\n",
|
||||
window->frame->rect.width,
|
||||
window->frame->rect.height);
|
||||
}
|
||||
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
/* window->rect.x, window->rect.y are relative to frame,
|
||||
* remember they are the server coords
|
||||
*/
|
||||
|
||||
new_x = borders.total.left;
|
||||
new_y = borders.total.top;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
client_move_x = window->rect.x;
|
||||
client_move_y = window->rect.y;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* See ICCCM 4.1.5 for when to send ConfigureNotify */
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
configure_frame_first = size_dx + size_dy >= 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
XConfigureWindow (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
mask,
|
||||
&values);
|
||||
|
||||
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 (need_configure_notify)
|
||||
send_configure_notify (window);
|
||||
}
|
||||
/* Do the protocol-specific move/resize logic */
|
||||
META_WINDOW_GET_CLASS (window)->move_resize_internal (window, gravity, requested_rect, new_rect, flags, &result);
|
||||
|
||||
if (!window->placed && window->force_save_user_rect && !window->fullscreen)
|
||||
force_save_user_window_placement (window);
|
||||
else if (is_user_action)
|
||||
save_user_window_placement (window);
|
||||
|
||||
if (need_move_client || need_move_frame)
|
||||
if (result & META_MOVE_RESIZE_RESULT_MOVED)
|
||||
g_signal_emit (window, window_signals[POSITION_CHANGED], 0);
|
||||
|
||||
if (need_resize_client || need_resize_frame)
|
||||
if (result & META_MOVE_RESIZE_RESULT_RESIZED)
|
||||
g_signal_emit (window, window_signals[SIZE_CHANGED], 0);
|
||||
|
||||
if (need_move_frame || need_resize_frame ||
|
||||
need_move_client || need_resize_client ||
|
||||
if ((result & (META_MOVE_RESIZE_RESULT_MOVED | META_MOVE_RESIZE_RESULT_RESIZED)) != 0 ||
|
||||
did_placement || is_wayland_resize)
|
||||
{
|
||||
int newx, newy;
|
||||
|
@ -5751,35 +5308,6 @@ meta_window_get_net_wm_desktop (MetaWindow *window)
|
|||
return meta_workspace_index (window->workspace);
|
||||
}
|
||||
|
||||
static void
|
||||
update_net_frame_extents (MetaWindow *window)
|
||||
{
|
||||
unsigned long data[4];
|
||||
MetaFrameBorders borders;
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
/* Left */
|
||||
data[0] = borders.visible.left;
|
||||
/* Right */
|
||||
data[1] = borders.visible.right;
|
||||
/* Top */
|
||||
data[2] = borders.visible.top;
|
||||
/* Bottom */
|
||||
data[3] = borders.visible.bottom;
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Setting _NET_FRAME_EXTENTS on managed window 0x%lx "
|
||||
"to left = %lu, right = %lu, top = %lu, bottom = %lu\n",
|
||||
window->xwindow, data[0], data[1], data[2], data[3]);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XChangeProperty (window->display->xdisplay, window->xwindow,
|
||||
window->display->atom__NET_FRAME_EXTENTS,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) data, 4);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_current_workspace_hint (MetaWindow *window)
|
||||
{
|
||||
|
@ -6304,59 +5832,6 @@ meta_window_set_focused_internal (MetaWindow *window,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
send_configure_notify (MetaWindow *window)
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
/* from twm */
|
||||
|
||||
event.type = ConfigureNotify;
|
||||
event.xconfigure.display = window->display->xdisplay;
|
||||
event.xconfigure.event = window->xwindow;
|
||||
event.xconfigure.window = window->xwindow;
|
||||
event.xconfigure.x = window->rect.x - window->border_width;
|
||||
event.xconfigure.y = window->rect.y - window->border_width;
|
||||
if (window->frame)
|
||||
{
|
||||
if (window->withdrawn)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
/* We reparent the client window and put it to the position
|
||||
* where the visible top-left of the frame window currently is.
|
||||
*/
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
event.xconfigure.x = window->frame->rect.x + borders.invisible.left;
|
||||
event.xconfigure.y = window->frame->rect.y + borders.invisible.top;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to be in root window coordinates */
|
||||
event.xconfigure.x += window->frame->rect.x;
|
||||
event.xconfigure.y += window->frame->rect.y;
|
||||
}
|
||||
}
|
||||
event.xconfigure.width = window->rect.width;
|
||||
event.xconfigure.height = window->rect.height;
|
||||
event.xconfigure.border_width = window->border_width; /* requested not actual */
|
||||
event.xconfigure.above = None; /* FIXME */
|
||||
event.xconfigure.override_redirect = False;
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Sending synthetic configure notify to %s with x: %d y: %d w: %d h: %d\n",
|
||||
window->desc,
|
||||
event.xconfigure.x, event.xconfigure.y,
|
||||
event.xconfigure.width, event.xconfigure.height);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XSendEvent (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
False, StructureNotifyMask, &event);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_icon_geometry:
|
||||
* @window: a #MetaWindow
|
||||
|
@ -8083,6 +7558,15 @@ update_tile_mode (MetaWindow *window)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_update_resize (MetaWindow *window,
|
||||
gboolean snap,
|
||||
int x, int y,
|
||||
gboolean force)
|
||||
{
|
||||
update_resize (window, snap, x, y, force);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
void
|
||||
meta_window_update_sync_request_counter (MetaWindow *window,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "window-wayland.h"
|
||||
|
||||
#include "window-private.h"
|
||||
#include "boxes-private.h"
|
||||
#include "stack-tracker.h"
|
||||
#include "meta-wayland-surface.h"
|
||||
|
||||
|
@ -74,6 +75,95 @@ meta_window_wayland_unmanage (MetaWindow *window)
|
|||
meta_display_unregister_wayland_window (window->display, window);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_move_resize_internal (MetaWindow *window,
|
||||
int gravity,
|
||||
MetaRectangle requested_rect,
|
||||
MetaRectangle constrained_rect,
|
||||
MetaMoveResizeFlags flags,
|
||||
MetaMoveResizeResultFlags *result)
|
||||
{
|
||||
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.
|
||||
*/
|
||||
|
||||
/* 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 = constrained_rect;
|
||||
|
||||
if (flags & META_IS_WAYLAND_RESIZE)
|
||||
{
|
||||
/* This is a call to wl_surface_commit(), ignore the constrained_rect and
|
||||
* update the real client size to match the buffer size.
|
||||
*/
|
||||
|
||||
window->rect.width = requested_rect.width;
|
||||
window->rect.height = requested_rect.height;
|
||||
}
|
||||
|
||||
if (constrained_rect.width != window->rect.width ||
|
||||
constrained_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 old_rect;
|
||||
MetaRectangle client_rect;
|
||||
int dx, dy;
|
||||
int deltax, deltay;
|
||||
|
||||
meta_window_get_client_root_coords (window, &old_rect);
|
||||
|
||||
meta_rectangle_resize_with_gravity (&old_rect,
|
||||
&client_rect,
|
||||
gravity,
|
||||
constrained_rect.width,
|
||||
constrained_rect.height);
|
||||
|
||||
deltax = constrained_rect.x - old_rect.x;
|
||||
deltay = constrained_rect.y - old_rect.y;
|
||||
dx = client_rect.x - constrained_rect.x;
|
||||
dy = client_rect.y - constrained_rect.y;
|
||||
|
||||
if (deltax != dx || deltay != dy)
|
||||
*result |= META_MOVE_RESIZE_RESULT_MOVED;
|
||||
|
||||
window->rect.x += (deltax - dx);
|
||||
window->rect.y += (deltay - dy);
|
||||
|
||||
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
|
||||
meta_wayland_surface_configure_notify (window->surface,
|
||||
constrained_rect.width,
|
||||
constrained_rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No resize happening, we can just move the window and live with it. */
|
||||
if (window->rect.x != constrained_rect.x ||
|
||||
window->rect.y != constrained_rect.y)
|
||||
*result |= META_MOVE_RESIZE_RESULT_MOVED;
|
||||
|
||||
window->rect.x = constrained_rect.x;
|
||||
window->rect.y = constrained_rect.y;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_init (MetaWindowWayland *window_wayland)
|
||||
{
|
||||
|
@ -86,4 +176,5 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
|
|||
|
||||
window_class->manage = meta_window_wayland_manage;
|
||||
window_class->unmanage = meta_window_wayland_unmanage;
|
||||
window_class->move_resize_internal = meta_window_wayland_move_resize_internal;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <meta/prefs.h>
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "window-private.h"
|
||||
#include "window-props.h"
|
||||
#include "xprops.h"
|
||||
|
@ -158,6 +159,59 @@ update_sm_hints (MetaWindow *window)
|
|||
window->sm_client_id ? window->sm_client_id : "none");
|
||||
}
|
||||
|
||||
static void
|
||||
send_configure_notify (MetaWindow *window)
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
/* from twm */
|
||||
|
||||
event.type = ConfigureNotify;
|
||||
event.xconfigure.display = window->display->xdisplay;
|
||||
event.xconfigure.event = window->xwindow;
|
||||
event.xconfigure.window = window->xwindow;
|
||||
event.xconfigure.x = window->rect.x - window->border_width;
|
||||
event.xconfigure.y = window->rect.y - window->border_width;
|
||||
if (window->frame)
|
||||
{
|
||||
if (window->withdrawn)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
/* We reparent the client window and put it to the position
|
||||
* where the visible top-left of the frame window currently is.
|
||||
*/
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
event.xconfigure.x = window->frame->rect.x + borders.invisible.left;
|
||||
event.xconfigure.y = window->frame->rect.y + borders.invisible.top;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to be in root window coordinates */
|
||||
event.xconfigure.x += window->frame->rect.x;
|
||||
event.xconfigure.y += window->frame->rect.y;
|
||||
}
|
||||
}
|
||||
event.xconfigure.width = window->rect.width;
|
||||
event.xconfigure.height = window->rect.height;
|
||||
event.xconfigure.border_width = window->border_width; /* requested not actual */
|
||||
event.xconfigure.above = None; /* FIXME */
|
||||
event.xconfigure.override_redirect = False;
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Sending synthetic configure notify to %s with x: %d y: %d w: %d h: %d\n",
|
||||
window->desc,
|
||||
event.xconfigure.x, event.xconfigure.y,
|
||||
event.xconfigure.width, event.xconfigure.height);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XSendEvent (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
False, StructureNotifyMask, &event);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_manage (MetaWindow *window)
|
||||
{
|
||||
|
@ -259,9 +313,418 @@ meta_window_x11_unmanage (MetaWindow *window)
|
|||
XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask);
|
||||
#endif
|
||||
|
||||
/* The XReparentWindow call in meta_window_destroy_frame() moves the
|
||||
* window so we need to send a configure notify; see bug 399552. (We
|
||||
* also do this just in case a window got unmaximized.)
|
||||
*/
|
||||
send_configure_notify (window);
|
||||
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
static void
|
||||
update_net_frame_extents (MetaWindow *window)
|
||||
{
|
||||
unsigned long data[4];
|
||||
MetaFrameBorders borders;
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
/* Left */
|
||||
data[0] = borders.visible.left;
|
||||
/* Right */
|
||||
data[1] = borders.visible.right;
|
||||
/* Top */
|
||||
data[2] = borders.visible.top;
|
||||
/* Bottom */
|
||||
data[3] = borders.visible.bottom;
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Setting _NET_FRAME_EXTENTS on managed window 0x%lx "
|
||||
"to left = %lu, right = %lu, top = %lu, bottom = %lu\n",
|
||||
window->xwindow, data[0], data[1], data[2], data[3]);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XChangeProperty (window->display->xdisplay, window->xwindow,
|
||||
window->display->atom__NET_FRAME_EXTENTS,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) data, 4);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
static gboolean
|
||||
sync_request_timeout (gpointer data)
|
||||
{
|
||||
MetaWindow *window = data;
|
||||
|
||||
window->sync_request_timeout_id = 0;
|
||||
|
||||
/* We have now waited for more than a second for the
|
||||
* application to respond to the sync request
|
||||
*/
|
||||
window->disable_sync = TRUE;
|
||||
|
||||
/* Reset the wait serial, so we don't continue freezing
|
||||
* window updates
|
||||
*/
|
||||
window->sync_request_wait_serial = 0;
|
||||
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
||||
meta_window_updates_are_frozen (window));
|
||||
|
||||
if (window == window->display->grab_window &&
|
||||
meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
meta_window_update_resize (window,
|
||||
window->display->grab_last_user_action_was_snap,
|
||||
window->display->grab_latest_motion_x,
|
||||
window->display->grab_latest_motion_y,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
send_sync_request (MetaWindow *window)
|
||||
{
|
||||
XClientMessageEvent ev;
|
||||
gint64 wait_serial;
|
||||
|
||||
/* For the old style of _NET_WM_SYNC_REQUEST_COUNTER, we just have to
|
||||
* increase the value, but for the new "extended" style we need to
|
||||
* pick an even (unfrozen) value sufficiently ahead of the last serial
|
||||
* that we received from the client; the same code still works
|
||||
* for the old style. The increment of 240 is specified by the EWMH
|
||||
* and is (1 second) * (60fps) * (an increment of 4 per frame).
|
||||
*/
|
||||
wait_serial = window->sync_request_serial + 240;
|
||||
|
||||
window->sync_request_wait_serial = wait_serial;
|
||||
|
||||
ev.type = ClientMessage;
|
||||
ev.window = window->xwindow;
|
||||
ev.message_type = window->display->atom_WM_PROTOCOLS;
|
||||
ev.format = 32;
|
||||
ev.data.l[0] = window->display->atom__NET_WM_SYNC_REQUEST;
|
||||
/* FIXME: meta_display_get_current_time() is bad, but since calls
|
||||
* come from meta_window_move_resize_internal (which in turn come
|
||||
* from all over), I'm not sure what we can do to fix it. Do we
|
||||
* want to use _roundtrip, though?
|
||||
*/
|
||||
ev.data.l[1] = meta_display_get_current_time (window->display);
|
||||
ev.data.l[2] = wait_serial & G_GUINT64_CONSTANT(0xffffffff);
|
||||
ev.data.l[3] = wait_serial >> 32;
|
||||
ev.data.l[4] = window->extended_sync_request_counter ? 1 : 0;
|
||||
|
||||
/* We don't need to trap errors here as we are already
|
||||
* inside an error_trap_push()/pop() pair.
|
||||
*/
|
||||
XSendEvent (window->display->xdisplay,
|
||||
window->xwindow, False, 0, (XEvent*) &ev);
|
||||
|
||||
/* We give the window 1 sec to respond to _NET_WM_SYNC_REQUEST;
|
||||
* if this time expires, we consider the window unresponsive
|
||||
* and resize it unsynchonized.
|
||||
*/
|
||||
window->sync_request_timeout_id = g_timeout_add (1000,
|
||||
sync_request_timeout,
|
||||
window);
|
||||
|
||||
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
||||
meta_window_updates_are_frozen (window));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
meta_window_x11_move_resize_internal (MetaWindow *window,
|
||||
int gravity,
|
||||
MetaRectangle requested_rect,
|
||||
MetaRectangle constrained_rect,
|
||||
MetaMoveResizeFlags flags,
|
||||
MetaMoveResizeResultFlags *result)
|
||||
{
|
||||
int root_x_nw, root_y_nw;
|
||||
int w, h;
|
||||
int client_move_x, client_move_y;
|
||||
int size_dx, size_dy;
|
||||
XWindowChanges values;
|
||||
unsigned int mask;
|
||||
gboolean need_configure_notify;
|
||||
MetaFrameBorders borders;
|
||||
gboolean need_move_client = FALSE;
|
||||
gboolean need_move_frame = FALSE;
|
||||
gboolean need_resize_client = FALSE;
|
||||
gboolean need_resize_frame = FALSE;
|
||||
gboolean frame_shape_changed = FALSE;
|
||||
gboolean configure_frame_first;
|
||||
|
||||
gboolean is_configure_request;
|
||||
|
||||
is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0;
|
||||
|
||||
/* meta_window_constrain() might have maximized the window after placement,
|
||||
* changing the borders.
|
||||
*/
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
root_x_nw = constrained_rect.x;
|
||||
root_y_nw = constrained_rect.y;
|
||||
w = constrained_rect.width;
|
||||
h = constrained_rect.height;
|
||||
|
||||
if (w != window->rect.width ||
|
||||
h != window->rect.height)
|
||||
need_resize_client = TRUE;
|
||||
|
||||
window->rect.width = w;
|
||||
window->rect.height = h;
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
int frame_size_dx, frame_size_dy;
|
||||
int new_w, new_h;
|
||||
|
||||
new_w = window->rect.width + borders.total.left + borders.total.right;
|
||||
|
||||
if (window->shaded)
|
||||
new_h = borders.total.top;
|
||||
else
|
||||
new_h = window->rect.height + borders.total.top + borders.total.bottom;
|
||||
|
||||
frame_size_dx = new_w - window->frame->rect.width;
|
||||
frame_size_dy = new_h - window->frame->rect.height;
|
||||
|
||||
need_resize_frame = (frame_size_dx != 0 || frame_size_dy != 0);
|
||||
|
||||
window->frame->rect.width = new_w;
|
||||
window->frame->rect.height = new_h;
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Calculated frame size %dx%d\n",
|
||||
window->frame->rect.width,
|
||||
window->frame->rect.height);
|
||||
}
|
||||
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
/* window->rect.x, window->rect.y are relative to frame,
|
||||
* remember they are the server coords
|
||||
*/
|
||||
|
||||
new_x = borders.total.left;
|
||||
new_y = borders.total.top;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
client_move_x = window->rect.x;
|
||||
client_move_y = window->rect.y;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* See ICCCM 4.1.5 for when to send ConfigureNotify */
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
configure_frame_first = size_dx + size_dy >= 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
XConfigureWindow (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
mask,
|
||||
&values);
|
||||
|
||||
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 (need_configure_notify)
|
||||
send_configure_notify (window);
|
||||
|
||||
if (frame_shape_changed)
|
||||
*result |= META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED;
|
||||
if (need_move_client || need_move_frame)
|
||||
*result |= META_MOVE_RESIZE_RESULT_MOVED;
|
||||
if (need_resize_client || need_resize_frame)
|
||||
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_get_default_skip_hints (MetaWindow *window,
|
||||
gboolean *skip_taskbar_out,
|
||||
|
@ -281,6 +744,7 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
|
|||
|
||||
window_class->manage = meta_window_x11_manage;
|
||||
window_class->unmanage = meta_window_x11_unmanage;
|
||||
window_class->move_resize_internal = meta_window_x11_move_resize_internal;
|
||||
window_class->get_default_skip_hints = meta_window_x11_get_default_skip_hints;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue