diff options
author | Robert Ancell <robert.ancell@canonical.com> | 2014-05-29 17:58:58 +0200 |
---|---|---|
committer | Robert Ancell <robert.ancell@canonical.com> | 2014-05-29 17:58:58 +0200 |
commit | d46a4d980d2ce773426987dc5ccb90f87247cce8 (patch) | |
tree | 07b02a93c3e4152601952daf7105a2270d224f71 | |
parent | 3d73ecb6d9f63947bf277cb1fd0474ac2827092b (diff) | |
download | gtk+-d46a4d980d2ce773426987dc5ccb90f87247cce8.tar.gz |
Draw transient windows onto their parents
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | gdk/mir/gdkmir-private.h | 7 | ||||
-rw-r--r-- | gdk/mir/gdkmir.h | 4 | ||||
-rw-r--r-- | gdk/mir/gdkmirdisplay.c | 5 | ||||
-rw-r--r-- | gdk/mir/gdkmirwindowimpl.c | 142 | ||||
-rw-r--r-- | gtk/gtktooltip.c | 16 |
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, ®ion); - - // 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, ®ion); + + // 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)); |