mir: implement gdk_window_move_to_rect ()

https://bugzilla.gnome.org/show_bug.cgi?id=756579
This commit is contained in:
William Hua 2016-07-04 15:31:16 -04:00
parent 8701e34f74
commit 748ebd3d72

View File

@ -46,6 +46,11 @@ struct _GdkMirWindowImpl
gint transient_x;
gint transient_y;
/* Anchor rectangle */
gboolean has_rect;
MirRectangle rect;
MirEdgeAttachment edge;
/* Desired surface attributes */
GdkWindowTypeHint type_hint;
MirSurfaceState surface_state;
@ -171,6 +176,8 @@ create_mir_surface (GdkDisplay *display,
gint width,
gint height,
GdkWindowTypeHint type,
const MirRectangle *rect,
MirEdgeAttachment edge,
MirBufferUsage buffer_usage)
{
MirSurface *parent_surface = NULL;
@ -178,7 +185,7 @@ create_mir_surface (GdkDisplay *display,
MirConnection *connection;
MirPixelFormat format;
MirSurface *surface;
MirRectangle rect;
MirRectangle real_rect;
connection = gdk_mir_display_get_mir_connection (display);
format = _gdk_mir_display_get_pixel_format (display, buffer_usage);
@ -202,6 +209,25 @@ create_mir_surface (GdkDisplay *display,
}
}
if (rect)
{
real_rect = *rect;
while (parent && !gdk_window_has_native (parent) && gdk_window_get_effective_parent (parent))
{
real_rect.left += parent->x;
real_rect.top += parent->y;
parent = gdk_window_get_effective_parent (parent);
}
}
else
{
real_rect.left = x;
real_rect.top = y;
real_rect.width = 1;
real_rect.height = 1;
}
switch (type)
{
case GDK_WINDOW_TYPE_HINT_DIALOG:
@ -216,17 +242,13 @@ create_mir_surface (GdkDisplay *display,
case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
case GDK_WINDOW_TYPE_HINT_TOOLBAR:
case GDK_WINDOW_TYPE_HINT_COMBO:
rect.left = x;
rect.top = y;
rect.width = 1;
rect.height = 1;
spec = mir_connection_create_spec_for_menu (connection,
width,
height,
format,
parent_surface,
&rect,
mir_edge_attachment_any);
&real_rect,
edge);
break;
case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
case GDK_WINDOW_TYPE_HINT_UTILITY:
@ -239,16 +261,12 @@ create_mir_surface (GdkDisplay *display,
case GDK_WINDOW_TYPE_HINT_DND:
case GDK_WINDOW_TYPE_HINT_TOOLTIP:
case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
rect.left = x;
rect.top = y;
rect.width = 1;
rect.height = 1;
spec = mir_connection_create_spec_for_tooltip (connection,
width,
height,
format,
parent_surface,
&rect);
&real_rect);
break;
case GDK_WINDOW_TYPE_HINT_NORMAL:
case GDK_WINDOW_TYPE_HINT_DESKTOP:
@ -328,10 +346,15 @@ ensure_surface_full (GdkWindow *window,
*/
window_ref = _gdk_mir_event_source_get_window_reference (window);
impl->surface = create_mir_surface (gdk_window_get_display (window), impl->transient_for,
impl->transient_x, impl->transient_y,
window->width, window->height,
impl->surface = create_mir_surface (gdk_window_get_display (window),
impl->transient_for,
impl->transient_x,
impl->transient_y,
window->width,
window->height,
impl->type_hint,
impl->has_rect ? &impl->rect : NULL,
impl->has_rect ? impl->edge : mir_edge_attachment_any,
buffer_usage);
/* FIXME: can't make an initial resize event */
@ -615,8 +638,9 @@ gdk_mir_window_impl_move_resize (GdkWindow *window,
/* Transient windows can move wherever they want */
if (with_move)
{
if (x != impl->transient_x || y != impl->transient_y)
if (impl->has_rect || x != impl->transient_x || y != impl->transient_y)
{
impl->has_rect = FALSE;
impl->transient_x = x;
impl->transient_y = y;
recreate_surface = TRUE;
@ -639,6 +663,79 @@ gdk_mir_window_impl_move_resize (GdkWindow *window,
}
}
static MirEdgeAttachment
get_edge_for_anchors (GdkGravity rect_anchor,
GdkGravity window_anchor,
GdkAnchorHints anchor_hints)
{
MirEdgeAttachment edge = 0;
if (anchor_hints & GDK_ANCHOR_FLIP_X)
edge |= mir_edge_attachment_vertical;
if (anchor_hints & GDK_ANCHOR_FLIP_Y)
edge |= mir_edge_attachment_horizontal;
return edge;
}
static void
get_rect_for_edge (MirRectangle *out_rect,
const GdkRectangle *in_rect,
MirEdgeAttachment edge,
GdkWindow *window)
{
out_rect->left = in_rect->x;
out_rect->top = in_rect->y;
out_rect->width = in_rect->width;
out_rect->height = in_rect->height;
switch (edge)
{
case mir_edge_attachment_vertical:
out_rect->left += window->shadow_right;
out_rect->top -= window->shadow_top;
out_rect->width -= window->shadow_left + window->shadow_right;
out_rect->height += window->shadow_top + window->shadow_bottom;
break;
case mir_edge_attachment_horizontal:
out_rect->left -= window->shadow_left;
out_rect->top += window->shadow_bottom;
out_rect->width += window->shadow_left + window->shadow_right;
out_rect->height -= window->shadow_top + window->shadow_bottom;
break;
default:
break;
}
}
static void
gdk_mir_window_impl_move_to_rect (GdkWindow *window,
const GdkRectangle *rect,
GdkGravity rect_anchor,
GdkGravity window_anchor,
GdkAnchorHints anchor_hints,
gint rect_anchor_dx,
gint rect_anchor_dy)
{
GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
impl->edge = get_edge_for_anchors (rect_anchor, window_anchor, anchor_hints);
get_rect_for_edge (&impl->rect, rect, impl->edge, window);
impl->has_rect = TRUE;
ensure_no_surface (window);
g_signal_emit_by_name (window,
"moved-to-rect",
NULL,
NULL,
FALSE,
FALSE);
}
static void
gdk_mir_window_impl_set_background (GdkWindow *window,
cairo_pattern_t *pattern)
@ -1524,6 +1621,7 @@ gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
impl_class->restack_under = gdk_mir_window_impl_restack_under;
impl_class->restack_toplevel = gdk_mir_window_impl_restack_toplevel;
impl_class->move_resize = gdk_mir_window_impl_move_resize;
impl_class->move_to_rect = gdk_mir_window_impl_move_to_rect;
impl_class->set_background = gdk_mir_window_impl_set_background;
impl_class->get_events = gdk_mir_window_impl_get_events;
impl_class->set_events = gdk_mir_window_impl_set_events;