Add support for enabling only native windows

Some applications make weird assumtions on Gtk+ that do not work anymore
with the new client-side windows support. For instance SWT/Eclipse reorders
the stacking order of the X windows directly without telling gdk this,
which breaks gdk drawing as gdk now relies on knowing the stacking order
for window clipping.

This introduces a GDK_NATIVE_WINDOWS environment variable, which if set
causes Gtk+ to always use native windows. Its more compatible with
pre-csw Gtk+ behaviour if you do weird X-specific hacks, although it does
limit the size of GdkWindows to 65535x65535.
This commit is contained in:
Alexander Larsson 2009-08-24 15:18:10 +02:00
parent deda8b97f6
commit a79f929dd6
5 changed files with 111 additions and 21 deletions

View File

@ -206,6 +206,9 @@ gdk_pre_parse_libgtk_only (void)
} }
#endif /* G_ENABLE_DEBUG */ #endif /* G_ENABLE_DEBUG */
if (getenv("GDK_NATIVE_WINDOWS"))
_gdk_native_windows = TRUE;
g_type_init (); g_type_init ();
/* Do any setup particular to the windowing system /* Do any setup particular to the windowing system

View File

@ -836,6 +836,10 @@ synthesize_crossing_events (GdkDisplay *display,
GdkWindow *src_toplevel, *dest_toplevel; GdkWindow *src_toplevel, *dest_toplevel;
GdkModifierType state; GdkModifierType state;
int x, y; int x, y;
/* We use the native crossing events if all native */
if (_gdk_native_windows)
return;
if (src_window) if (src_window)
src_toplevel = gdk_window_get_toplevel (src_window); src_toplevel = gdk_window_get_toplevel (src_window);

View File

@ -39,6 +39,7 @@ GList *_gdk_default_filters = NULL;
gchar *_gdk_display_name = NULL; gchar *_gdk_display_name = NULL;
gint _gdk_screen_number = -1; gint _gdk_screen_number = -1;
gchar *_gdk_display_arg_name = NULL; gchar *_gdk_display_arg_name = NULL;
gboolean _gdk_native_windows = FALSE;
GSList *_gdk_displays = NULL; GSList *_gdk_displays = NULL;

View File

@ -107,6 +107,7 @@ extern gint _gdk_error_code;
extern gint _gdk_error_warnings; extern gint _gdk_error_warnings;
extern guint _gdk_debug_flags; extern guint _gdk_debug_flags;
extern gboolean _gdk_native_windows;
#ifdef G_ENABLE_DEBUG #ifdef G_ENABLE_DEBUG

View File

@ -866,8 +866,14 @@ recompute_visible_regions_internal (GdkWindowObject *private,
{ {
gdk_region_intersect (new_clip, private->parent->clip_region); gdk_region_intersect (new_clip, private->parent->clip_region);
/* Remove all overlapping children from parent */ /* Remove all overlapping children from parent.
remove_child_area (private->parent, private, FALSE, new_clip); * Unless we're all native, because then we don't need to take
* siblings into account since X does that clipping for us.
* This makes things like SWT that modify the raw X stacking
* order without GDKs knowledge work.
*/
if (!_gdk_native_windows)
remove_child_area (private->parent, private, FALSE, new_clip);
} }
/* Convert from parent coords to window coords */ /* Convert from parent coords to window coords */
@ -1093,8 +1099,11 @@ find_native_sibling_above (GdkWindowObject *parent,
static GdkEventMask static GdkEventMask
get_native_event_mask (GdkWindowObject *private) get_native_event_mask (GdkWindowObject *private)
{ {
if (private->window_type != GDK_WINDOW_ROOT && if (_gdk_native_windows ||
private->window_type != GDK_WINDOW_FOREIGN) private->window_type == GDK_WINDOW_ROOT ||
private->window_type == GDK_WINDOW_FOREIGN)
return private->event_mask;
else
{ {
return return
/* We need thse for all native window so we can emulate /* We need thse for all native window so we can emulate
@ -1116,13 +1125,13 @@ get_native_event_mask (GdkWindowObject *private)
GDK_BUTTON2_MOTION_MASK | GDK_BUTTON2_MOTION_MASK |
GDK_BUTTON3_MOTION_MASK)); GDK_BUTTON3_MOTION_MASK));
} }
else
return private->event_mask;
} }
/* Puts the native window in the right order wrt the other native windows /* Puts the native window in the right order wrt the other native windows
in the hierarchy, given the position it has in the client side data. * in the hierarchy, given the position it has in the client side data.
This is useful if some operation changed the stacking order. */ * This is useful if some operation changed the stacking order.
* This calls assumes the native window is now topmost in its native parent.
*/
static void static void
sync_native_window_stack_position (GdkWindow *window) sync_native_window_stack_position (GdkWindow *window)
{ {
@ -1187,6 +1196,13 @@ gdk_window_new (GdkWindow *parent,
if (GDK_WINDOW_DESTROYED (parent)) if (GDK_WINDOW_DESTROYED (parent))
return NULL; return NULL;
if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
_gdk_native_windows)
{
g_warning ("Offscreen windows not supported with native-windows gdk");
return NULL;
}
window = g_object_new (GDK_TYPE_WINDOW, NULL); window = g_object_new (GDK_TYPE_WINDOW, NULL);
private = (GdkWindowObject *) window; private = (GdkWindowObject *) window;
@ -1288,7 +1304,7 @@ gdk_window_new (GdkWindow *parent,
if (private->parent) if (private->parent)
private->parent->children = g_list_prepend (private->parent->children, window); private->parent->children = g_list_prepend (private->parent->children, window);
native = FALSE; /* Default */ native = _gdk_native_windows; /* Default */
if (private->parent->window_type == GDK_WINDOW_ROOT) if (private->parent->window_type == GDK_WINDOW_ROOT)
native = TRUE; /* Always use native windows for toplevels */ native = TRUE; /* Always use native windows for toplevels */
else if (!private->input_only && else if (!private->input_only &&
@ -1313,7 +1329,8 @@ gdk_window_new (GdkWindow *parent,
/* This will put the native window topmost in the native parent, which may /* This will put the native window topmost in the native parent, which may
* be wrong wrt other native windows in the non-native hierarchy, so restack */ * be wrong wrt other native windows in the non-native hierarchy, so restack */
sync_native_window_stack_position (window); if (!_gdk_window_has_impl (real_parent))
sync_native_window_stack_position (window);
} }
else else
{ {
@ -1432,7 +1449,7 @@ gdk_window_reparent (GdkWindow *window,
GdkWindowObject *new_parent_private; GdkWindowObject *new_parent_private;
GdkWindowObject *old_parent; GdkWindowObject *old_parent;
GdkScreen *screen; GdkScreen *screen;
gboolean show, was_toplevel, was_mapped; gboolean show, was_mapped;
gboolean do_reparent_to_impl; gboolean do_reparent_to_impl;
g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (GDK_IS_WINDOW (window));
@ -1476,7 +1493,6 @@ gdk_window_reparent (GdkWindow *window,
private->redirect = NULL; private->redirect = NULL;
} }
was_toplevel = private->parent == NULL;
was_mapped = GDK_WINDOW_IS_MAPPED (window); was_mapped = GDK_WINDOW_IS_MAPPED (window);
show = FALSE; show = FALSE;
@ -1576,7 +1592,8 @@ gdk_window_reparent (GdkWindow *window,
/* The reparent will have put the native window topmost in the native parent, /* The reparent will have put the native window topmost in the native parent,
* which may be wrong wrt other native windows in the non-native hierarchy, * which may be wrong wrt other native windows in the non-native hierarchy,
* so restack */ * so restack */
sync_native_window_stack_position (window); if (!gdk_window_has_impl (new_parent_private))
sync_native_window_stack_position (window);
} }
if (show) if (show)
@ -1645,8 +1662,9 @@ gdk_window_ensure_native (GdkWindow *window)
change_impl (private, private, new_impl); change_impl (private, private, new_impl);
/* Native window creation will put the native window topmost in the /* Native window creation will put the native window topmost in the
* native parent, which may be wrong wrt other native windows in the * native parent, which may be wrong wrt the position of the previous
* non-native hierarchy, so restack */ * non-native window wrt to the other non-native children, so correct this.
*/
above = find_native_sibling_above (private->parent, private); above = find_native_sibling_above (private->parent, private);
if (above) if (above)
{ {
@ -2361,6 +2379,9 @@ gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
g_assert (gdk_window_has_impl (private)); g_assert (gdk_window_has_impl (private));
if (_gdk_native_windows)
return FALSE; /* No need for implicit paints since we can't merge draws anyway */
if (GDK_IS_PAINTABLE (private->impl)) if (GDK_IS_PAINTABLE (private->impl))
return FALSE; /* Implementation does double buffering */ return FALSE; /* Implementation does double buffering */
@ -3263,8 +3284,8 @@ start_draw_helper (GdkDrawable *drawable,
guarantee ordering. */ guarantee ordering. */
gdk_window_flush ((GdkWindow *)drawable); gdk_window_flush ((GdkWindow *)drawable);
/* Don't clip when drawing to root */ /* Don't clip when drawing to root or all native */
if (private->window_type != GDK_WINDOW_ROOT) if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
{ {
if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN) if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
clip = private->clip_region_with_children; clip = private->clip_region_with_children;
@ -5928,7 +5949,13 @@ gdk_window_raise_internal (GdkWindow *window)
/* Just do native raise for toplevels */ /* Just do native raise for toplevels */
if (private->parent == NULL || if (private->parent == NULL ||
private->parent->window_type == GDK_WINDOW_ROOT) private->parent->window_type == GDK_WINDOW_ROOT ||
/* The restack_under codepath should work correctly even if the parent
is native, but it relies on the order of ->children to be correct,
and some apps like SWT reorder the x windows without gdks knowledge,
so we use raise directly in order to make these behave as before
when using native windows */
(gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
{ {
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window); GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
} }
@ -6203,7 +6230,13 @@ gdk_window_lower_internal (GdkWindow *window)
/* Just do native lower for toplevels */ /* Just do native lower for toplevels */
if (private->parent == NULL || if (private->parent == NULL ||
private->parent->window_type == GDK_WINDOW_ROOT) private->parent->window_type == GDK_WINDOW_ROOT ||
/* The restack_under codepath should work correctly even if the parent
is native, but it relies on the order of ->children to be correct,
and some apps like SWT reorder the x windows without gdks knowledge,
so we use lower directly in order to make these behave as before
when using native windows */
(gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
{ {
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window); GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
} }
@ -7244,7 +7277,8 @@ gdk_window_set_cursor (GdkWindow *window,
if (cursor) if (cursor)
private->cursor = gdk_cursor_ref (cursor); private->cursor = gdk_cursor_ref (cursor);
if (private->window_type == GDK_WINDOW_ROOT || if (_gdk_native_windows ||
private->window_type == GDK_WINDOW_ROOT ||
private->window_type == GDK_WINDOW_FOREIGN) private->window_type == GDK_WINDOW_FOREIGN)
GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor); GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer)) else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
@ -9005,6 +9039,11 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
{ {
GdkWindowObject *private; GdkWindowObject *private;
/* We don't track this if all native, and it can cause issues
with the update_cursor call below */
if (_gdk_native_windows)
return;
private = (GdkWindowObject *)window; private = (GdkWindowObject *)window;
if (display->pointer_info.window_under_pointer) if (display->pointer_info.window_under_pointer)
@ -9073,7 +9112,10 @@ gdk_pointer_grab (GdkWindow * window,
!gdk_window_is_viewable (window)) !gdk_window_is_viewable (window))
return GDK_GRAB_NOT_VIEWABLE; return GDK_GRAB_NOT_VIEWABLE;
native = gdk_window_get_toplevel (window); if (_gdk_native_windows)
native = window;
else
native = gdk_window_get_toplevel (window);
while (gdk_window_is_offscreen ((GdkWindowObject *)native)) while (gdk_window_is_offscreen ((GdkWindowObject *)native))
{ {
native = gdk_offscreen_window_get_embedder (native); native = gdk_offscreen_window_get_embedder (native);
@ -9178,6 +9220,9 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
GdkWindow *toplevel; GdkWindow *toplevel;
GdkWindowObject *toplevel_priv; GdkWindowObject *toplevel_priv;
if (_gdk_native_windows)
return; /* We use the native crossing events if all native */
display = gdk_drawable_get_display (changed_window); display = gdk_drawable_get_display (changed_window);
toplevel = get_event_toplevel (changed_window); toplevel = get_event_toplevel (changed_window);
@ -9650,6 +9695,42 @@ _gdk_windowing_got_event (GdkDisplay *display,
if (!event_window) if (!event_window)
return; return;
if (_gdk_native_windows)
{
if (event->type == GDK_BUTTON_PRESS &&
_gdk_display_has_pointer_grab (display, serial) == NULL)
{
_gdk_display_add_pointer_grab (display,
event_window,
event_window,
FALSE,
gdk_window_get_events (event_window),
serial,
gdk_event_get_time (event),
TRUE);
_gdk_display_pointer_grab_update (display,
serial);
}
if (event->type == GDK_BUTTON_RELEASE)
{
button_release_grab =
_gdk_display_has_pointer_grab (display, serial);
if (button_release_grab &&
button_release_grab->implicit &&
(event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
{
button_release_grab->serial_end = serial;
button_release_grab->implicit_ungrab = TRUE;
_gdk_display_pointer_grab_update (display, serial);
}
}
if (event->type == GDK_BUTTON_PRESS)
_gdk_event_button_generate (display, event);
return;
}
event_private = GDK_WINDOW_OBJECT (event_window); event_private = GDK_WINDOW_OBJECT (event_window);
#ifdef DEBUG_WINDOW_PRINTING #ifdef DEBUG_WINDOW_PRINTING