diff options
author | Matthias Clasen <mclasen@redhat.com> | 2018-01-28 23:30:29 +0100 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2018-01-28 23:30:29 +0100 |
commit | b54e24ea292a3c8385474126015b8129eb763195 (patch) | |
tree | 7009a176e21087a695d546d234069d4bfb1a7ec0 | |
parent | 794d9d266e35b1eee87221b6687a39aa490c50db (diff) | |
download | gtk+-wip/matthiasc/subsurface.tar.gz |
wip: subsurface window typewip/matthiasc/subsurface
Make subsurfaces for X11 as follows:
- toplevel
- override-redirect
- moves with the parent
Attempt to use subsurfaces for popovers again
This does not quite work yet
-rw-r--r-- | gdk/gdkwindow.c | 68 | ||||
-rw-r--r-- | gdk/gdkwindow.h | 4 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.c | 10 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 75 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.h | 10 | ||||
-rw-r--r-- | gtk/gtkmain.c | 1 | ||||
-rw-r--r-- | gtk/gtkpopover.c | 32 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 7 | ||||
-rw-r--r-- | gtk/gtkwindow.c | 8 |
9 files changed, 151 insertions, 64 deletions
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 6641c122af..66ac01fc84 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -458,12 +458,6 @@ gdk_window_get_property (GObject *object, } } -static gboolean -gdk_window_is_subsurface (GdkWindow *window) -{ - return window->window_type == GDK_WINDOW_SUBSURFACE; -} - static GdkWindow * gdk_window_get_impl_window (GdkWindow *window) { @@ -700,10 +694,7 @@ recompute_visible_regions_internal (GdkWindow *private, old_abs_y = private->abs_y; /* Update absolute position */ - if ((gdk_window_has_impl (private) && - private->window_type != GDK_WINDOW_SUBSURFACE) || - (gdk_window_is_toplevel (private) && - private->window_type == GDK_WINDOW_SUBSURFACE)) + if (gdk_window_has_impl (private)) { /* Native windows and toplevel subsurfaces start here */ private->abs_x = 0; @@ -745,7 +736,7 @@ recompute_visible_regions_internal (GdkWindow *private, cairo_region_intersect (new_clip, private->shape); } else - new_clip = cairo_region_create (); + new_clip = cairo_region_create (); if (private->clip_region == NULL || !cairo_region_equal (private->clip_region, new_clip)) @@ -855,7 +846,7 @@ get_native_device_event_mask (GdkWindow *private, mask = private->event_mask; - /* We need thse for all native windows so we can + /* We need these for all native windows so we can emulate events on children: */ mask |= GDK_EXPOSURE_MASK | @@ -929,13 +920,6 @@ gdk_window_new (GdkDisplay *display, "a window of type GDK_WINDOW_ROOT"); break; case GDK_WINDOW_SUBSURFACE: -#ifdef GDK_WINDOWING_WAYLAND - if (!GDK_IS_WAYLAND_DISPLAY (display)) - { - g_warning (G_STRLOC "Subsurface windows can only be used on Wayland"); - return NULL; - } -#endif break; case GDK_WINDOW_CHILD: if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT || @@ -975,11 +959,6 @@ gdk_window_new (GdkDisplay *display, native = TRUE; /* Always use native windows for toplevels */ } -#ifdef GDK_WINDOWING_WAYLAND - if (window->window_type == GDK_WINDOW_SUBSURFACE) - native = TRUE; /* Always use native windows for subsurfaces as well */ -#endif - if (native) { event_mask = get_native_event_mask (window); @@ -1065,6 +1044,41 @@ gdk_window_new_popup (GdkDisplay *display, } /** + * gdk_window_new_subsurface: (constructor) + * @parent: the parent window + * @position: placement of the window relative to @parent + * + * Creates a new toplevel window that is attached to @parent. + * The window will bypass window management and move together + * with its parent. + * + * Returns: (transfer full): the new #GdkWindow + * + * Since: 3.94 + **/ +GdkWindow * +gdk_window_new_subsurface (GdkWindow *parent, + const GdkRectangle *position) +{ + GdkWindowAttr attr; + GdkWindow *window; + + g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL); + + attr.wclass = GDK_INPUT_OUTPUT; + attr.x = position->x; + attr.y = position->y; + attr.width = position->width; + attr.height = position->height; + attr.window_type = GDK_WINDOW_SUBSURFACE; + + window = gdk_window_new (gdk_window_get_display (parent), NULL, &attr); + gdk_window_set_transient_for (window, parent); + + return window; +} + +/** * gdk_window_new_temp: (constructor) * @display: the display to create the window on * @@ -1547,9 +1561,6 @@ gdk_window_get_parent (GdkWindow *window) { g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); - if (gdk_window_is_subsurface (window)) - return window->transient_for; - else return window->parent; } @@ -1570,8 +1581,7 @@ gdk_window_get_toplevel (GdkWindow *window) { g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); - while (window->window_type == GDK_WINDOW_CHILD || - window->window_type == GDK_WINDOW_SUBSURFACE) + while (window->window_type == GDK_WINDOW_CHILD) { if (gdk_window_is_toplevel (window)) break; diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index e33e70cbf0..4338239ce4 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -452,6 +452,10 @@ GdkWindow * gdk_window_new_toplevel (GdkDisplay *display, GDK_AVAILABLE_IN_3_90 GdkWindow * gdk_window_new_popup (GdkDisplay *display, const GdkRectangle *position); +GDK_AVAILABLE_IN_3_94 +GdkWindow * gdk_window_new_subsurface (GdkWindow *parent, + const GdkRectangle *position); + GDK_AVAILABLE_IN_3_90 GdkWindow * gdk_window_new_temp (GdkDisplay *display); GDK_AVAILABLE_IN_3_90 diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 67a7217b4f..172add046c 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -992,8 +992,14 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, } if (!is_substructure) { - window->x = event->configure.x; - window->y = event->configure.y; + if (window->x != event->configure.x || + window->y != event->configure.y) + { + window->x = event->configure.x; + window->y = event->configure.y; + + gdk_x11_window_update_position (window_impl); + } if (window_impl->unscaled_width != xevent->xconfigure.width || window_impl->unscaled_height != xevent->xconfigure.height) diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 83f8dea6f2..dcda6bb608 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -113,10 +113,12 @@ static void gdk_window_impl_x11_finalize (GObject *object); #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \ (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL || \ GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || \ + GDK_WINDOW_TYPE (window) == GDK_WINDOW_SUBSURFACE || \ GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN) #define WINDOW_IS_TOPLEVEL(window) \ (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL || \ + GDK_WINDOW_TYPE (window) == GDK_WINDOW_SUBSURFACE || \ GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP) /* Return whether time1 is considered later than time2 as far as xserver @@ -510,9 +512,16 @@ gdk_window_impl_x11_finalize (GObject *object) g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object)); impl = GDK_WINDOW_IMPL_X11 (object); - wrapper = impl->wrapper; + if (wrapper->transient_for) + { + GdkWindowImplX11 *x11_parent; + + x11_parent = GDK_WINDOW_IMPL_X11 (wrapper->transient_for->impl); + x11_parent->transients = g_list_remove (x11_parent->transients, wrapper); + } + if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame) unhook_surface_changed (wrapper); @@ -900,6 +909,7 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display, { case GDK_WINDOW_TOPLEVEL: case GDK_WINDOW_TEMP: + case GDK_WINDOW_SUBSURFACE: if (window->parent) { /* The common code warns for this case */ @@ -928,7 +938,8 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display, xattributes.colormap = gdk_x11_display_get_window_colormap (display_x11); xattributes_mask |= CWColormap; - if (window->window_type == GDK_WINDOW_TEMP) + if (window->window_type == GDK_WINDOW_TEMP || + window->window_type == GDK_WINDOW_SUBSURFACE) { xattributes.save_under = True; xattributes.override_redirect = True; @@ -944,7 +955,8 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display, { class = InputOnly; - if (window->window_type == GDK_WINDOW_TEMP) + if (window->window_type == GDK_WINDOW_TEMP || + window->window_type == GDK_WINDOW_SUBSURFACE) { xattributes.override_redirect = True; xattributes_mask |= CWOverrideRedirect; @@ -992,6 +1004,7 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display, switch (GDK_WINDOW_TYPE (window)) { + case GDK_WINDOW_SUBSURFACE: case GDK_WINDOW_TOPLEVEL: case GDK_WINDOW_TEMP: gdk_window_set_title (window, get_default_title ()); @@ -1450,6 +1463,7 @@ gdk_window_x11_hide (GdkWindow *window) { case GDK_WINDOW_TOPLEVEL: case GDK_WINDOW_TEMP: /* ? */ + case GDK_WINDOW_SUBSURFACE: gdk_window_withdraw (window); return; @@ -1583,6 +1597,17 @@ gdk_window_x11_move_resize (GdkWindow *window, gint width, gint height) { + if (gdk_window_get_window_type (window) == GDK_WINDOW_SUBSURFACE) + { + GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl); + + impl->offset_x = x; + impl->offset_y = y; + + x = window->transient_for->x + impl->offset_x; + y = window->transient_for->y + impl->offset_y; + } + if (with_move && (width < 0 && height < 0)) window_x11_move (window, x, y); else @@ -1595,6 +1620,23 @@ gdk_window_x11_move_resize (GdkWindow *window, } void +gdk_x11_window_update_position (GdkWindowImplX11 *impl) +{ + GList *l; + + for (l = impl->transients; l; l = l->next) + { + GdkWindow *window = l->data; + + if (gdk_window_get_window_type (window) == GDK_WINDOW_SUBSURFACE) + { + GdkWindowImplX11 *win_impl = GDK_WINDOW_IMPL_X11 (window->impl); + gdk_window_x11_move_resize (window, TRUE, win_impl->offset_x, win_impl->offset_y, window->width, window->height); + } + } +} + +void _gdk_x11_window_set_window_scale (GdkWindow *window, int scale) { @@ -2446,19 +2488,34 @@ static void gdk_x11_window_set_transient_for (GdkWindow *window, GdkWindow *parent) { + GdkWindowImplX11 *x11_parent; + if (GDK_WINDOW_DESTROYED (window) || !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window)) return; /* XSetTransientForHint() doesn't allow unsetting, so do it manually */ if (parent && !GDK_WINDOW_DESTROYED (parent)) - XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - GDK_WINDOW_XID (parent)); + { + XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + GDK_WINDOW_XID (parent)); + + x11_parent = GDK_WINDOW_IMPL_X11 (parent->impl); + x11_parent->transients = g_list_prepend (x11_parent->transients, window); + } else - XDeleteProperty (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), "WM_TRANSIENT_FOR")); + { + if (window->transient_for) + { + x11_parent = GDK_WINDOW_IMPL_X11 (window->transient_for->impl); + x11_parent->transients = g_list_remove (x11_parent->transients, window); + } + + XDeleteProperty (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), "WM_TRANSIENT_FOR")); + } } GdkCursor * diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index 2199692327..8e438b25fe 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -89,6 +89,14 @@ struct _GdkWindowImplX11 #if defined (HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES) Damage damage; #endif + + /* Subsurfaces are positioned relative to their transient parent. + * We keep the offset here. + */ + int offset_x; + int offset_y; + + GList *transients; }; struct _GdkWindowImplX11Class @@ -191,9 +199,11 @@ GdkToplevelX11 *_gdk_x11_window_get_toplevel (GdkWindow *window); GdkCursor *_gdk_x11_window_get_cursor (GdkWindow *window); void _gdk_x11_window_update_size (GdkWindowImplX11 *impl); +void gdk_x11_window_update_position (GdkWindowImplX11 *impl); void _gdk_x11_window_set_window_scale (GdkWindow *window, int scale); + G_END_DECLS #endif /* __GDK_WINDOW_X11_H__ */ diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index fcd1f363bc..b813fe24c5 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1546,6 +1546,7 @@ handle_pointing_event (GdkEvent *event) return widget; toplevel_widget = gtk_widget_get_toplevel (widget); +g_print ("pointing event on %s\n", G_OBJECT_TYPE_NAME (toplevel_widget)); if (!GTK_IS_WINDOW (toplevel_widget)) return widget; diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c index 58b89ec133..2fa8dabdbe 100644 --- a/gtk/gtkpopover.c +++ b/gtk/gtkpopover.c @@ -472,36 +472,21 @@ gtk_popover_realize (GtkWidget *widget) { GtkAllocation allocation; GdkWindow *window; + GtkWidget *toplevel; + GskRenderer *renderer; + toplevel = gtk_widget_get_toplevel (widget); gtk_widget_get_window_allocation (widget, &allocation); - /* We want to use subsurfaces for popovers, so they can extend outside - * the main window, but for that, we first need to have clean subsurface - * support that works with GSK. - */ -#if 0 - if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget))) - { - GtkWidget *toplevel = gtk_widget_get_toplevel (widget); - - g_assert (GTK_IS_WINDOW (toplevel)); - - window = gdk_wayland_window_new_subsurface (gtk_widget_get_display (toplevel), - &allocation); - - gdk_window_set_transient_for (window, - gtk_widget_get_window (toplevel)); - } - else -#endif - { - window = gdk_window_new_child (gtk_widget_get_parent_window (widget), - &allocation); - } + window = gdk_window_new_subsurface (gtk_widget_get_window (toplevel), + &allocation); gtk_widget_set_window (widget, window); gtk_widget_register_window (widget, window); gtk_widget_set_realized (widget, TRUE); + + renderer = gsk_renderer_new_for_window (window); + g_object_set_data_full (G_OBJECT (window), "renderer", renderer, g_object_unref); } static void @@ -1021,6 +1006,7 @@ gtk_popover_update_shape (GtkPopover *popover) GdkWindow *win; cairo_t *cr; + return; #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget))) return; diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index b1386298bf..93ca9d176d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5446,6 +5446,13 @@ static GskRenderer * gtk_widget_get_renderer (GtkWidget *widget) { GtkWidget *toplevel; + GdkWindow *window; + GskRenderer *renderer; + + window = gtk_widget_get_window (widget); + renderer = g_object_get_data (G_OBJECT (window), "renderer"); + if (renderer) + return renderer; toplevel = _gtk_widget_get_toplevel (widget); if (_gtk_widget_is_toplevel (toplevel)) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 147e505058..bf7aff9b2c 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -6953,7 +6953,11 @@ gtk_window_realize (GtkWidget *widget) gtk_widget_set_realized (widget, TRUE); if (priv->renderer == NULL) - priv->renderer = gsk_renderer_new_for_window (gdk_window); + { + priv->renderer = gsk_renderer_new_for_window (gdk_window); + g_object_set_data_full (G_OBJECT (gdk_window), "renderer", + g_object_ref (priv->renderer), g_object_unref); + } if (priv->transient_parent && _gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent))) @@ -9385,11 +9389,13 @@ gtk_window_snapshot (GtkWidget *widget, gtk_widget_snapshot_child (widget, child, snapshot); } +#if 0 for (l = priv->popovers.head; l; l = l->next) { GtkWindowPopover *data = l->data; gtk_widget_snapshot_child (widget, data->widget, snapshot); } +#endif gtk_debug_updates_snapshot (widget, snapshot); } |