summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2014-05-29 17:58:58 +0200
committerRobert Ancell <robert.ancell@canonical.com>2014-05-29 17:58:58 +0200
commitd46a4d980d2ce773426987dc5ccb90f87247cce8 (patch)
tree07b02a93c3e4152601952daf7105a2270d224f71
parent3d73ecb6d9f63947bf277cb1fd0474ac2827092b (diff)
downloadgtk+-d46a4d980d2ce773426987dc5ccb90f87247cce8.tar.gz
Draw transient windows onto their parents
-rw-r--r--configure.ac2
-rw-r--r--gdk/mir/gdkmir-private.h7
-rw-r--r--gdk/mir/gdkmir.h4
-rw-r--r--gdk/mir/gdkmirdisplay.c5
-rw-r--r--gdk/mir/gdkmirwindowimpl.c142
-rw-r--r--gtk/gtktooltip.c16
6 files changed, 145 insertions, 31 deletions
diff --git a/configure.ac b/configure.ac
index bea2b167c5..e241d0c4e1 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 8309edfe2a..d81f62f724 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 8ce99b7378..1ab0a2867a 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 67af65da77..e7052399b7 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 ab0bcc7d9c..a3d94256b0 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 60fb11ec14..c3d8e1deff 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));