x11: Make popups move with their parent

This is another step towards implementing
popup semantics for X11.

We do a sort-of ok job on stacking order
here - whenever the parent window gets a
ConfigureNotify, we just restack all popups
directly on top of their parent. This is good
enough to keep popups on top of their parent
while we drag it around, and it gets the popup
to disappear when raising another window on
top of the parent.
This commit is contained in:
Matthias Clasen
2019-04-22 16:35:23 +00:00
parent efff718d4e
commit f7bedacecb
4 changed files with 77 additions and 15 deletions

View File

@@ -985,8 +985,12 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
}
if (!is_substructure)
{
surface->x = event->configure.x;
surface->y = event->configure.y;
if (surface->x != event->configure.x ||
surface->y != event->configure.y)
{
surface->x = event->configure.x;
surface->y = event->configure.y;
}
if (surface_impl->unscaled_width != xevent->xconfigure.width ||
surface_impl->unscaled_height != xevent->xconfigure.height)
@@ -1007,6 +1011,8 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
if (surface->resize_count == 0)
_gdk_x11_moveresize_configure_done (display, surface);
}
gdk_x11_surface_update_popups (surface);
}
}
break;

View File

@@ -227,6 +227,8 @@ void _gdk_x11_cursor_display_finalize (GdkDisplay *display);
void _gdk_x11_surface_register_dnd (GdkSurface *window);
void gdk_x11_surface_update_popups (GdkSurface *surface);
GdkDrag * _gdk_x11_surface_drag_begin (GdkSurface *window,
GdkDevice *device,
GdkContentProvider *content,

View File

@@ -425,12 +425,20 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
static void
gdk_x11_surface_finalize (GObject *object)
{
GdkSurface *surface;
GdkX11Surface *impl;
g_return_if_fail (GDK_IS_X11_SURFACE (object));
surface = GDK_SURFACE (object);
impl = GDK_X11_SURFACE (object);
if (surface->parent)
{
GdkX11Surface *parent_impl = GDK_X11_SURFACE (surface->parent);
parent_impl->popups = g_list_remove (parent_impl->popups, surface);
}
if (impl->toplevel->in_frame)
unhook_surface_changed (GDK_SURFACE (impl));
@@ -900,6 +908,12 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
gdk_surface_freeze_toplevel_updates (surface);
if (parent)
{
GdkX11Surface *parent_impl = GDK_X11_SURFACE (parent);
parent_impl->popups = g_list_prepend (parent_impl->popups, surface);
}
return surface;
}
@@ -1232,8 +1246,8 @@ gdk_x11_surface_hide (GdkSurface *surface)
static inline void
x11_surface_move (GdkSurface *surface,
gint x,
gint y)
gint x,
gint y)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
@@ -1245,6 +1259,12 @@ x11_surface_move (GdkSurface *surface,
{
surface->x = x;
surface->y = y;
if (surface->parent)
{
impl->offset_x = surface->x - surface->parent->x;
impl->offset_y = surface->y - surface->parent->y;
}
}
}
@@ -1284,10 +1304,10 @@ x11_surface_resize (GdkSurface *surface,
static inline void
x11_surface_move_resize (GdkSurface *surface,
gint x,
gint y,
gint width,
gint height)
gint x,
gint y,
gint width,
gint height)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
@@ -1315,6 +1335,12 @@ x11_surface_move_resize (GdkSurface *surface,
surface->height = height;
_gdk_x11_surface_update_size (GDK_X11_SURFACE (surface));
if (surface->parent)
{
impl->offset_x = surface->x - surface->parent->x;
impl->offset_y = surface->y - surface->parent->y;
}
}
else
{
@@ -1325,11 +1351,11 @@ x11_surface_move_resize (GdkSurface *surface,
static void
gdk_x11_surface_move_resize (GdkSurface *surface,
gboolean with_move,
gint x,
gint y,
gint width,
gint height)
gboolean with_move,
gint x,
gint y,
gint width,
gint height)
{
if (with_move && (width < 0 && height < 0))
x11_surface_move (surface, x, y);
@@ -1342,6 +1368,29 @@ gdk_x11_surface_move_resize (GdkSurface *surface,
}
}
static void gdk_x11_surface_restack_toplevel (GdkSurface *surface,
GdkSurface *sibling,
gboolean above);
void
gdk_x11_surface_update_popups (GdkSurface *parent)
{
GdkX11Surface *impl = GDK_X11_SURFACE (parent);
GList *l;
for (l = impl->popups; l; l = l->next)
{
GdkX11Surface *popup_impl = l->data;
GdkSurface *popup = GDK_SURFACE (popup_impl);
int new_x = parent->x + popup_impl->offset_x;
int new_y = parent->y + popup_impl->offset_y;
if (new_x != popup->x || new_y != popup->y)
x11_surface_move (popup, new_x, new_y);
gdk_x11_surface_restack_toplevel (popup, parent, TRUE);
}
}
void
_gdk_x11_surface_set_surface_scale (GdkSurface *surface,
int scale)
@@ -1391,8 +1440,8 @@ gdk_x11_surface_raise (GdkSurface *surface)
static void
gdk_x11_surface_restack_toplevel (GdkSurface *surface,
GdkSurface *sibling,
gboolean above)
GdkSurface *sibling,
gboolean above)
{
XWindowChanges changes;

View File

@@ -75,6 +75,11 @@ struct _GdkX11Surface
#if defined (HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
Damage damage;
#endif
int offset_x;
int offset_y;
GList *popups;
};
struct _GdkX11SurfaceClass