[gtk+/wip/attach-params: 4/20] gdkwindow-mir: implement move_using_params ()



commit 2ab290d00956f84f8d888b05fa711b657d574a19
Author: William Hua <william hua canonical com>
Date:   Wed Jan 20 02:20:20 2016 -0600

    gdkwindow-mir: implement move_using_params ()
    
    https://bugzilla.gnome.org/show_bug.cgi?id=756579

 gdk/mir/gdkmirwindowimpl.c |  210 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 201 insertions(+), 9 deletions(-)
---
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
index 8455f36..9f8175a 100644
--- a/gdk/mir/gdkmirwindowimpl.c
+++ b/gdk/mir/gdkmirwindowimpl.c
@@ -28,6 +28,7 @@
 #include "gdkintl.h"
 #include "gdkdisplayprivate.h"
 #include "gdkdeviceprivate.h"
+#include "gdkattachparamsprivate.h"
 
 #define GDK_MIR_WINDOW_IMPL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_MIR, 
GdkMirWindowImplClass))
 #define GDK_IS_WINDOW_IMPL_MIR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_MIR))
@@ -50,6 +51,11 @@ struct _GdkMirWindowImpl
   GdkWindowTypeHint type_hint;
   MirSurfaceState surface_state;
 
+  /* Attachment rectangle */
+  gboolean has_attach_rect;
+  GdkRectangle attach_rect;
+  MirEdgeAttachment attach_edge;
+
   /* Pattern for background */
   cairo_pattern_t *background;
 
@@ -170,6 +176,8 @@ create_mir_surface (GdkDisplay *display,
                     gint y,
                     gint width,
                     gint height,
+                    const GdkRectangle *attach_rect,
+                    MirEdgeAttachment attach_edge,
                     GdkWindowTypeHint type,
                     MirBufferUsage buffer_usage)
 {
@@ -216,17 +224,28 @@ 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;
+        if (attach_rect)
+          {
+            rect.left = attach_rect->x;
+            rect.top = attach_rect->y;
+            rect.width = attach_rect->width;
+            rect.height = attach_rect->height;
+          }
+        else
+          {
+            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);
+                                                    attach_edge);
         break;
       case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
       case GDK_WINDOW_TYPE_HINT_UTILITY:
@@ -239,10 +258,21 @@ 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;
+        if (attach_rect)
+          {
+            rect.left = attach_rect->x;
+            rect.top = attach_rect->y;
+            rect.width = attach_rect->width;
+            rect.height = attach_rect->height;
+          }
+        else
+          {
+            rect.left = x;
+            rect.top = y;
+            rect.width = 1;
+            rect.height = 1;
+          }
+
         spec = mir_connection_create_spec_for_tooltip (connection,
                                                        width,
                                                        height,
@@ -323,6 +353,8 @@ ensure_surface_full (GdkWindow *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->has_attach_rect ? &impl->attach_rect : NULL,
+                                      impl->attach_edge,
                                       impl->type_hint,
                                       buffer_usage);
 
@@ -1496,6 +1528,165 @@ gdk_mir_window_get_mir_surface (GdkWindow *window)
   return impl->surface;
 }
 
+static gint
+get_edge_x (GdkWindowEdge edge)
+{
+  switch (edge)
+    {
+    case GDK_WINDOW_EDGE_NORTH_WEST:
+    case GDK_WINDOW_EDGE_WEST:
+    case GDK_WINDOW_EDGE_SOUTH_WEST:
+      return -1;
+
+    case GDK_WINDOW_EDGE_NORTH:
+    case GDK_WINDOW_EDGE_CENTER:
+    case GDK_WINDOW_EDGE_SOUTH:
+      return 0;
+
+    case GDK_WINDOW_EDGE_NORTH_EAST:
+    case GDK_WINDOW_EDGE_EAST:
+    case GDK_WINDOW_EDGE_SOUTH_EAST:
+      return 1;
+    }
+
+  g_return_val_if_reached (0);
+}
+
+static gint
+get_edge_y (GdkWindowEdge edge)
+{
+  switch (edge)
+    {
+    case GDK_WINDOW_EDGE_NORTH_WEST:
+    case GDK_WINDOW_EDGE_NORTH:
+    case GDK_WINDOW_EDGE_NORTH_EAST:
+      return -1;
+
+    case GDK_WINDOW_EDGE_WEST:
+    case GDK_WINDOW_EDGE_CENTER:
+    case GDK_WINDOW_EDGE_EAST:
+      return 0;
+
+    case GDK_WINDOW_EDGE_SOUTH_WEST:
+    case GDK_WINDOW_EDGE_SOUTH:
+    case GDK_WINDOW_EDGE_SOUTH_EAST:
+      return 1;
+    }
+
+  g_return_val_if_reached (0);
+}
+
+static MirEdgeAttachment
+get_attach_edge (const GdkAttachParams *params)
+{
+  gint overlap_x;
+  gint overlap_y;
+  gint x0;
+  gint y0;
+  gint x1;
+  gint y1;
+
+  if (params->flip_x)
+    {
+      if (!params->flip_y)
+        return mir_edge_attachment_vertical;
+    }
+  else
+    {
+      if (params->flip_y)
+        return mir_edge_attachment_horizontal;
+    }
+
+  x0 = get_edge_x (params->attach_anchor);
+  y0 = get_edge_y (params->attach_anchor);
+  x1 = get_edge_x (params->window_anchor);
+  y1 = get_edge_y (params->window_anchor);
+
+  overlap_x = 2 - ABS (x1 - x0);
+  overlap_y = 2 - ABS (y1 - y0);
+
+  if (overlap_x < overlap_y)
+    return mir_edge_attachment_vertical;
+  else if (overlap_x > overlap_y)
+    return mir_edge_attachment_horizontal;
+  else
+    return mir_edge_attachment_any;
+}
+
+static GdkRectangle
+get_attach_rect (const GdkAttachParams *params,
+                 MirEdgeAttachment      edge)
+{
+  GdkRectangle rectangle = params->attach_rect;
+  gint origin_x;
+  gint origin_y;
+
+  if (params->attach_parent)
+    {
+      gdk_window_get_origin (params->attach_parent, &origin_x, &origin_y);
+      rectangle.x += origin_x;
+      rectangle.y += origin_y;
+    }
+
+  switch (edge)
+    {
+    case mir_edge_attachment_vertical:
+      rectangle.x += params->window_padding.right;
+      rectangle.y -= params->window_padding.top;
+      rectangle.width -= params->window_padding.left + params->window_padding.right;
+      rectangle.height += params->window_padding.top + params->window_padding.bottom;
+      break;
+
+    case mir_edge_attachment_horizontal:
+      rectangle.x -= params->window_padding.left;
+      rectangle.y += params->window_padding.bottom;
+      rectangle.width += params->window_padding.left + params->window_padding.right;
+      rectangle.height -= params->window_padding.top + params->window_padding.bottom;
+      break;
+
+    case mir_edge_attachment_any:
+      break;
+    }
+
+  return rectangle;
+}
+
+static void
+gdk_mir_window_impl_move_using_params (GdkWindow             *window,
+                                       const GdkAttachParams *params)
+{
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  MirEdgeAttachment edge;
+  GdkRectangle rectangle;
+
+  if (!params || !params->has_attach_rect)
+    {
+      if (impl->has_attach_rect)
+        {
+          impl->has_attach_rect = FALSE;
+          ensure_no_surface (window);
+        }
+
+      return;
+    }
+
+  edge = get_attach_edge (params);
+  rectangle = get_attach_rect (params, edge);
+
+  if (impl->has_attach_rect &&
+      rectangle.x == impl->attach_rect.x &&
+      rectangle.y == impl->attach_rect.y &&
+      rectangle.width == impl->attach_rect.width &&
+      rectangle.height == impl->attach_rect.height &&
+      edge == impl->attach_edge)
+    return;
+
+  impl->has_attach_rect = TRUE;
+  impl->attach_rect = rectangle;
+  impl->attach_edge = edge;
+  ensure_no_surface (window);
+}
+
 static void
 gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
 {
@@ -1586,4 +1777,5 @@ gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
   impl_class->set_shadow_width = gdk_mir_window_impl_set_shadow_width;
   impl_class->create_gl_context = gdk_mir_window_impl_create_gl_context;
   impl_class->invalidate_for_new_frame = gdk_mir_window_impl_invalidate_for_new_frame;
+  impl_class->move_using_params = gdk_mir_window_impl_move_using_params;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]