mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-05 16:20:10 +00:00
Show/Hide native window when updating viewable
This moves the native show/hide calls to the generic code for calculating viewable rather than in its own separate code called from gdk_window_show/hide. This simplifies the code a bit, but most significantly it means things are correctly shown when they become viewable for other reasons than a show/hide call. For instance, this fixes bug 590442 (gvim embedding) where the toplevel GtkPlug is mapped by the embedder and we didn't previously pick up that the native children became viewable and should be shown.
This commit is contained in:
parent
70efa73311
commit
f30cfd729a
@ -386,7 +386,7 @@ void _gdk_window_destroy (GdkWindow *window,
|
||||
gboolean foreign_destroy);
|
||||
void _gdk_window_clear_update_area (GdkWindow *window);
|
||||
void _gdk_window_update_size (GdkWindow *window);
|
||||
void _gdk_window_update_viewable (GdkWindow *window);
|
||||
gboolean _gdk_window_update_viewable (GdkWindow *window);
|
||||
|
||||
void _gdk_window_process_updates_recurse (GdkWindow *window,
|
||||
GdkRegion *expose_region);
|
||||
|
129
gdk/gdkwindow.c
129
gdk/gdkwindow.c
@ -5818,38 +5818,17 @@ gdk_window_raise_internal (GdkWindow *window)
|
||||
}
|
||||
}
|
||||
|
||||
/* Showing a non-native parent may cause children to become visible,
|
||||
we need to handle this by manually showing them then. To simplify
|
||||
things we hide them all when they are not visible. */
|
||||
static void
|
||||
show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
|
||||
{
|
||||
GdkWindowObject *child;
|
||||
GList *l;
|
||||
|
||||
for (l = private->children; l != NULL; l = l->next)
|
||||
{
|
||||
child = l->data;
|
||||
|
||||
/* For foreign windows, only show if if was
|
||||
explicitly hidden, otherwise we might cause
|
||||
suprising things to happen to the other client. */
|
||||
if (GDK_WINDOW_IS_MAPPED (child) &&
|
||||
child->window_type != GDK_WINDOW_FOREIGN)
|
||||
show_all_visible_impls (child, FALSE);
|
||||
}
|
||||
|
||||
if (gdk_window_has_impl (private))
|
||||
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
|
||||
}
|
||||
|
||||
static void
|
||||
/* Returns TRUE If the native window was mapped or unmapped */
|
||||
static gboolean
|
||||
set_viewable (GdkWindowObject *w,
|
||||
gboolean val)
|
||||
{
|
||||
GdkWindowObject *child;
|
||||
GList *l;
|
||||
|
||||
if (w->viewable == val)
|
||||
return FALSE;
|
||||
|
||||
w->viewable = val;
|
||||
|
||||
if (val)
|
||||
@ -5863,9 +5842,48 @@ set_viewable (GdkWindowObject *w,
|
||||
child->window_type != GDK_WINDOW_FOREIGN)
|
||||
set_viewable (child, val);
|
||||
}
|
||||
|
||||
if (gdk_window_has_impl (w) &&
|
||||
w->window_type != GDK_WINDOW_FOREIGN &&
|
||||
w->parent != NULL &&
|
||||
w->parent->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
/* For most native windows we show/hide them not when they are
|
||||
* mapped/unmapped, because that may not produce the correct results.
|
||||
* For instance, if a native window have a non-native parent which is
|
||||
* hidden, but its native parent is viewable then showing the window
|
||||
* would make it viewable to X but its not viewable wrt the non-native
|
||||
* hierarchy. In order to handle this we track the gdk side viewability
|
||||
* and only map really viewable windows.
|
||||
*
|
||||
* There are two exceptions though:
|
||||
*
|
||||
* For foreign windows we don't want ever change the mapped state
|
||||
* except when explicitly done via gdk_window_show/hide, as this may
|
||||
* cause problems for client owning the foreign window when its window
|
||||
* is suddenly mapped or unmapped.
|
||||
*
|
||||
* For toplevel windows embedded in a foreign window (e.g. a plug)
|
||||
* we sometimes synthesize a map of a window, but the native
|
||||
* window is really shown by the embedder, so we don't want to
|
||||
* do the show ourselves. We can't really tell this case from the normal
|
||||
* toplevel show as such toplevels are seen by gdk as parents of the
|
||||
* root window, so we make an exception for all toplevels.
|
||||
*/
|
||||
|
||||
if (val)
|
||||
GDK_WINDOW_IMPL_GET_IFACE (w->impl)->show ((GdkWindow *)w, FALSE);
|
||||
else
|
||||
GDK_WINDOW_IMPL_GET_IFACE (w->impl)->hide ((GdkWindow *)w);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
/* Returns TRUE If the native window was mapped or unmapped */
|
||||
gboolean
|
||||
_gdk_window_update_viewable (GdkWindow *window)
|
||||
{
|
||||
GdkWindowObject *priv = (GdkWindowObject *)window;
|
||||
@ -5881,15 +5899,15 @@ _gdk_window_update_viewable (GdkWindow *window)
|
||||
else
|
||||
viewable = FALSE;
|
||||
|
||||
if (priv->viewable != viewable)
|
||||
set_viewable (priv, viewable);
|
||||
return set_viewable (priv, viewable);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_window_show_internal (GdkWindow *window, gboolean raise)
|
||||
{
|
||||
GdkWindowObject *private;
|
||||
gboolean was_mapped;
|
||||
gboolean was_mapped, was_viewable;
|
||||
gboolean did_show;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
@ -5898,6 +5916,7 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise)
|
||||
return;
|
||||
|
||||
was_mapped = GDK_WINDOW_IS_MAPPED (window);
|
||||
was_viewable = private->viewable;
|
||||
|
||||
if (raise)
|
||||
/* Keep children in (reverse) stacking order */
|
||||
@ -5915,10 +5934,17 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise)
|
||||
private->state = 0;
|
||||
}
|
||||
|
||||
_gdk_window_update_viewable (window);
|
||||
did_show = _gdk_window_update_viewable (window);
|
||||
|
||||
if (gdk_window_is_viewable (window))
|
||||
show_all_visible_impls (private, was_mapped);
|
||||
/* If it was already viewable the backend show op won't be called, call it
|
||||
again to ensure things happen right if the mapped tracking was not right
|
||||
for e.g. a foreign window.
|
||||
Dunno if this is strictly needed but its what happened pre-csw.
|
||||
Also show if not done by gdk_window_update_viewable. */
|
||||
if (gdk_window_has_impl (private) && (was_viewable || !did_show))
|
||||
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private,
|
||||
!did_show ?
|
||||
was_mapped : TRUE);
|
||||
|
||||
if (!was_mapped && !gdk_window_has_impl (private))
|
||||
{
|
||||
@ -6146,33 +6172,6 @@ gdk_window_show (GdkWindow *window)
|
||||
gdk_window_show_internal (window, TRUE);
|
||||
}
|
||||
|
||||
/* Hiding a non-native parent may cause parents to become non-visible,
|
||||
even if their parent native window is visible. We need to handle this
|
||||
by manually hiding them then. To simplify things we hide them all
|
||||
when they are not visible. */
|
||||
static void
|
||||
hide_all_visible_impls (GdkWindowObject *private)
|
||||
{
|
||||
GdkWindowObject *child;
|
||||
GList *l;
|
||||
|
||||
for (l = private->children; l != NULL; l = l->next)
|
||||
{
|
||||
child = l->data;
|
||||
|
||||
/* For foreign windows, only hide if if was
|
||||
explicitly hidden, otherwise we might cause
|
||||
suprising things to happen to the other client. */
|
||||
if (GDK_WINDOW_IS_MAPPED (child) &&
|
||||
child->window_type != GDK_WINDOW_FOREIGN)
|
||||
hide_all_visible_impls (child);
|
||||
}
|
||||
|
||||
if (gdk_window_has_impl (private))
|
||||
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gdk_window_hide:
|
||||
* @window: a #GdkWindow
|
||||
@ -6186,7 +6185,7 @@ void
|
||||
gdk_window_hide (GdkWindow *window)
|
||||
{
|
||||
GdkWindowObject *private;
|
||||
gboolean was_mapped, was_viewable;
|
||||
gboolean was_mapped, did_hide;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
@ -6195,7 +6194,6 @@ gdk_window_hide (GdkWindow *window)
|
||||
return;
|
||||
|
||||
was_mapped = GDK_WINDOW_IS_MAPPED (private);
|
||||
was_viewable = gdk_window_is_viewable (window);
|
||||
|
||||
if (gdk_window_has_impl (private))
|
||||
{
|
||||
@ -6234,10 +6232,11 @@ gdk_window_hide (GdkWindow *window)
|
||||
private->state = GDK_WINDOW_STATE_WITHDRAWN;
|
||||
}
|
||||
|
||||
_gdk_window_update_viewable (window);
|
||||
did_hide = _gdk_window_update_viewable (window);
|
||||
|
||||
if (was_viewable)
|
||||
hide_all_visible_impls (private);
|
||||
/* Hide foreign window as those are not handled by update_viewable. */
|
||||
if (gdk_window_has_impl (private) && (!did_hide))
|
||||
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
|
||||
|
||||
recompute_visible_regions (private, TRUE, FALSE);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user