summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-01-28 23:30:29 +0100
committerMatthias Clasen <mclasen@redhat.com>2018-01-28 23:30:29 +0100
commitb54e24ea292a3c8385474126015b8129eb763195 (patch)
tree7009a176e21087a695d546d234069d4bfb1a7ec0
parent794d9d266e35b1eee87221b6687a39aa490c50db (diff)
downloadgtk+-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.c68
-rw-r--r--gdk/gdkwindow.h4
-rw-r--r--gdk/x11/gdkdisplay-x11.c10
-rw-r--r--gdk/x11/gdkwindow-x11.c75
-rw-r--r--gdk/x11/gdkwindow-x11.h10
-rw-r--r--gtk/gtkmain.c1
-rw-r--r--gtk/gtkpopover.c32
-rw-r--r--gtk/gtkwidget.c7
-rw-r--r--gtk/gtkwindow.c8
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);
}