[gtk+/wip/mir] Draw transient windows onto their parents



commit d46a4d980d2ce773426987dc5ccb90f87247cce8
Author: Robert Ancell <robert ancell canonical com>
Date:   Thu May 29 17:58:58 2014 +0200

    Draw transient windows onto their parents

 configure.ac               |    2 +-
 gdk/mir/gdkmir-private.h   |    7 ++
 gdk/mir/gdkmir.h           |    4 +-
 gdk/mir/gdkmirdisplay.c    |    5 +-
 gdk/mir/gdkmirwindowimpl.c |  142 +++++++++++++++++++++++++++++++++++---------
 gtk/gtktooltip.c           |   16 +++++
 6 files changed, 145 insertions(+), 31 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index bea2b16..e241d0c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1366,7 +1366,7 @@ fi
 PKG_CHECK_MODULES(ATK, $ATK_PACKAGES)
 
 GTK_PACKAGES="atk cairo cairo-gobject gdk-pixbuf-2.0 gio-2.0"
-GTK_PRIVATE_PACKAGES="$ATK_PACKAGES"
+GTK_PRIVATE_PACKAGES="$ATK_PACKAGES $WAYLAND_PACKAGES $MIR_PACKAGES"
 if test "x$enable_x11_backend" = xyes; then
   GTK_PRIVATE_PACKAGES="$GTK_PRIVATE_PACKAGES pangoft2"
 fi
diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
index 8309edf..d81f62f 100644
--- a/gdk/mir/gdkmir-private.h
+++ b/gdk/mir/gdkmir-private.h
@@ -55,6 +55,13 @@ struct _GdkMirWindowImpl
 {
   GdkWindowImpl parent_instance;
 
+  /* Window we are temporary for */
+  GdkWindow *transient_for;
+  GdkRectangle transient_size;
+
+  /* Child windows (e.g. tooltips) */
+  GList *transient_children;
+
   /* Desired surface attributes */
   MirSurfaceType surface_type; // FIXME
   MirSurfaceState surface_state;
diff --git a/gdk/mir/gdkmir.h b/gdk/mir/gdkmir.h
index 8ce99b7..1ab0a28 100644
--- a/gdk/mir/gdkmir.h
+++ b/gdk/mir/gdkmir.h
@@ -27,11 +27,13 @@
 #define GDK_TYPE_MIR_WINDOW              (gdk_mir_window_get_type ())
 #define GDK_IS_WINDOW_MIR(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_MIR))
 
+GDK_AVAILABLE_IN_3_10
 GType gdk_mir_display_get_type (void);
 
-GDK_AVAILABLE_IN_ALL
+GDK_AVAILABLE_IN_3_10
 struct MirConnection *gdk_mir_display_get_mir_connection (GdkDisplay *display);
 
+GDK_AVAILABLE_IN_3_10
 GType gdk_mir_window_get_type (void);
 
 #endif /* __GDK_MIR_H__ */
diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
index 67af65d..e705239 100644
--- a/gdk/mir/gdkmirdisplay.c
+++ b/gdk/mir/gdkmirdisplay.c
@@ -405,7 +405,10 @@ gdk_mir_display_create_window_impl (GdkDisplay    *display,
                                     GdkWindowAttr *attributes,
                                     gint           attributes_mask)
 {
-  g_printerr ("gdk_mir_display_create_window_impl (%d, %d, %d, %d), events=0x%X\n", window->x, window->y, 
window->width, window->height, event_mask);
+  g_printerr ("gdk_mir_display_create_window_impl");
+  g_printerr (" location=(%d, %d)", window->x, window->y);
+  g_printerr (" size=(%d, %d)", window->width, window->height);
+  g_printerr ("\n");
   window->impl = _gdk_mir_window_impl_new ();
 }
 
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
index ab0bcc7..a3d9425 100644
--- a/gdk/mir/gdkmirwindowimpl.c
+++ b/gdk/mir/gdkmirwindowimpl.c
@@ -41,6 +41,8 @@ struct _GdkMirWindowImplClass
 
 G_DEFINE_TYPE (GdkMirWindowImpl, gdk_mir_window_impl, GDK_TYPE_WINDOW_IMPL)
 
+static cairo_surface_t *gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window);
+
 GdkWindowImpl *
 _gdk_mir_window_impl_new (void)
 {
@@ -153,6 +155,41 @@ send_buffer (GdkWindow *window)
 {
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
+  /* Transient windows draw onto parent instead */
+  if (impl->transient_for)
+    {
+      gdk_window_invalidate_rect (impl->transient_for, &impl->transient_size, FALSE);
+      return;
+    }
+
+  /* Composite transient windows over this one */
+  if (impl->transient_children)
+    {
+      cairo_surface_t *surface;
+      cairo_t *c;
+      GList *link;
+
+      surface = gdk_mir_window_impl_ref_cairo_surface (window);
+      c = cairo_create (surface);
+
+      for (link = impl->transient_children; link; link = link->next)
+        {
+          GdkWindow *child_window = link->data;
+          GdkMirWindowImpl *child_impl = GDK_MIR_WINDOW_IMPL (child_window->impl);
+
+          /* Skip children not yet drawn to */
+          if (!child_impl->cairo_surface)
+            continue;
+
+          cairo_set_source_surface (c, child_impl->cairo_surface, child_impl->transient_size.x, 
child_impl->transient_size.y);
+          cairo_rectangle (c, child_impl->transient_size.x, child_impl->transient_size.y, 
child_impl->transient_size.width, child_impl->transient_size.height);
+          cairo_fill (c);
+        }
+
+      cairo_destroy (c);
+      cairo_surface_destroy (surface);
+    }
+
   /* Send the completed buffer to Mir */
   mir_surface_swap_buffers_sync (impl->surface);
 
@@ -180,31 +217,40 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
       return impl->cairo_surface;
     }
 
-  ensure_surface (window);
-
-  mir_surface_get_graphics_region (impl->surface, &region);
-
-  // FIXME: Should calculate this once
-  switch (region.pixel_format)
+  /* Transient windows get rendered into a buffer and copied onto their parent */
+  if (impl->transient_for)
     {
-    case mir_pixel_format_argb_8888:
-      pixel_format = CAIRO_FORMAT_ARGB32;
-      break;
-    default:
-    case mir_pixel_format_abgr_8888:
-    case mir_pixel_format_xbgr_8888:
-    case mir_pixel_format_xrgb_8888:
-    case mir_pixel_format_bgr_888:
-        // uh-oh...
-        g_printerr ("Unsupported pixel format %d\n", region.pixel_format);
-        break;
+      cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, impl->transient_size.width, 
impl->transient_size.height);
+    }
+  else
+    {
+      ensure_surface (window);
+
+      mir_surface_get_graphics_region (impl->surface, &region);
+
+      // FIXME: Should calculate this once
+      switch (region.pixel_format)
+        {
+        case mir_pixel_format_argb_8888:
+          pixel_format = CAIRO_FORMAT_ARGB32;
+          break;
+        default:
+        case mir_pixel_format_abgr_8888:
+        case mir_pixel_format_xbgr_8888:
+        case mir_pixel_format_xrgb_8888:
+        case mir_pixel_format_bgr_888:
+          // uh-oh...
+          g_printerr ("Unsupported pixel format %d\n", region.pixel_format);
+          break;
+        }
+
+      cairo_surface = cairo_image_surface_create_for_data ((unsigned char *) region.vaddr,
+                                                           pixel_format,
+                                                           region.width,
+                                                           region.height,
+                                                           region.stride);
     }
 
-  cairo_surface = cairo_image_surface_create_for_data ((unsigned char *) region.vaddr,
-                                                       pixel_format,
-                                                       region.width,
-                                                       region.height,
-                                                       region.stride);
   impl->cairo_surface = cairo_surface_reference (cairo_surface);
 
   /* Draw background */
@@ -233,6 +279,13 @@ static void
 gdk_mir_window_impl_finalize (GObject *object)
 {
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (object);
+  GList *link;
+
+  for (link = impl->transient_children; link; link = link->next)
+    {
+      GdkWindow *window = link->data;
+      gdk_window_destroy (window);
+    }
 
   if (impl->background)
     cairo_pattern_destroy (impl->background);
@@ -240,6 +293,7 @@ gdk_mir_window_impl_finalize (GObject *object)
     mir_surface_release_sync (impl->surface);
   if (impl->cairo_surface)
     cairo_surface_destroy (impl->cairo_surface);
+  g_list_free (impl->transient_children);
 
   G_OBJECT_CLASS (gdk_mir_window_impl_parent_class)->finalize (object);
 }
@@ -324,16 +378,25 @@ gdk_mir_window_impl_move_resize (GdkWindow *window,
                                  gint       height)
 {
   g_printerr ("gdk_mir_window_impl_move_resize (%d, %d, %d, %d)\n", x, y, width, height);
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
-  if (with_move)
+  /* Transient windows are always the requested size */
+  if (impl->transient_for)
     {
-      window->x = x;
-      window->y = y;
+      if (with_move)
+        {
+          impl->transient_size.x = x;
+          impl->transient_size.y = y;
+        }
+      if (width >= 0)
+        impl->transient_size.width = width;
+      if (height >= 0)
+        impl->transient_size.height = height;
     }
 
   /* If resize requested then destroy surface */
   if (width >= 0)
-      ensure_no_surface (window);
+    ensure_no_surface (window);
 }
 
 static void
@@ -511,6 +574,13 @@ gdk_mir_window_impl_destroy (GdkWindow *window,
 
   impl->visible = FALSE;
   ensure_no_surface (window);
+
+  /* Remove from transient list */
+  if (impl->transient_for)
+    {
+      GdkMirWindowImpl *parent_impl = GDK_MIR_WINDOW_IMPL (impl->transient_for->impl);
+      parent_impl->transient_children = g_list_remove (parent_impl->transient_children, window);
+    }
 }
 
 static void
@@ -614,8 +684,24 @@ static void
 gdk_mir_window_impl_set_transient_for (GdkWindow *window,
                                        GdkWindow *parent)
 {
-  //g_printerr ("gdk_mir_window_impl_set_transient_for\n");
-  //FIXME
+  g_printerr ("gdk_mir_window_impl_set_transient_for\n");
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+
+  if (impl->transient_for == parent)
+    return;
+
+  g_return_if_fail (impl->transient_for == NULL);
+
+  /* Link this window to the parent */
+  impl->transient_for = parent;
+  if (parent)
+    {
+      GdkMirWindowImpl *parent_impl = GDK_MIR_WINDOW_IMPL (parent->impl);
+      parent_impl->transient_children = g_list_append (parent_impl->transient_children, window);
+    }
+
+  /* Remove surface if we had made one before this was set */
+  ensure_no_surface (window);
 }
 
 static void
diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c
index 60fb11e..c3d8e1d 100644
--- a/gtk/gtktooltip.c
+++ b/gtk/gtktooltip.c
@@ -39,6 +39,9 @@
 #ifdef GDK_WINDOWING_WAYLAND
 #include "wayland/gdkwayland.h"
 #endif
+#ifdef GDK_WINDOWING_MIR
+#include "mir/gdkmir.h"
+#endif
 
 
 /**
@@ -1262,6 +1265,19 @@ found:
                                           GTK_WINDOW (toplevel));
         }
 #endif
+#ifdef GDK_WINDOWING_MIR
+      /* Set the transient parent on the tooltip when running with the Mir
+       * backend to allow correct positioning of the tooltip windows */
+      if (GDK_IS_MIR_DISPLAY (display))
+        {
+          GtkWidget *toplevel;
+
+          toplevel = gtk_widget_get_toplevel (tooltip->tooltip_widget);
+          if (GTK_IS_WINDOW (toplevel))
+            gtk_window_set_transient_for (GTK_WINDOW (tooltip->current_window),
+                                          GTK_WINDOW (toplevel));
+        }
+#endif
 
       gtk_window_move (GTK_WINDOW (tooltip->current_window), x, y);
       gtk_widget_show (GTK_WIDGET (tooltip->current_window));


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