[gtk+] Add support for enabling only native windows



commit a79f929dd6c89fceeaf0d9039e5a10cad9d87d2f
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Aug 24 15:18:10 2009 +0200

    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.

 gdk/gdk.c          |    3 +
 gdk/gdkdisplay.c   |    4 ++
 gdk/gdkglobals.c   |    1 +
 gdk/gdkinternals.h |    1 +
 gdk/gdkwindow.c    |  123 +++++++++++++++++++++++++++++++++++++++++++---------
 5 files changed, 111 insertions(+), 21 deletions(-)
---
diff --git a/gdk/gdk.c b/gdk/gdk.c
index da5d633..6b81cc7 100644
--- a/gdk/gdk.c
+++ b/gdk/gdk.c
@@ -206,6 +206,9 @@ gdk_pre_parse_libgtk_only (void)
   }
 #endif	/* G_ENABLE_DEBUG */
 
+  if (getenv("GDK_NATIVE_WINDOWS"))
+    _gdk_native_windows = TRUE;
+
   g_type_init ();
 
   /* Do any setup particular to the windowing system
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index ff11f08..10a0b90 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -836,6 +836,10 @@ synthesize_crossing_events (GdkDisplay *display,
   GdkWindow *src_toplevel, *dest_toplevel;
   GdkModifierType state;
   int x, y;
+
+  /* We use the native crossing events if all native */
+  if (_gdk_native_windows)
+    return;
   
   if (src_window)
     src_toplevel = gdk_window_get_toplevel (src_window);
diff --git a/gdk/gdkglobals.c b/gdk/gdkglobals.c
index 35e9908..4c3ad80 100644
--- a/gdk/gdkglobals.c
+++ b/gdk/gdkglobals.c
@@ -39,6 +39,7 @@ GList              *_gdk_default_filters = NULL;
 gchar              *_gdk_display_name = NULL;
 gint                _gdk_screen_number = -1;
 gchar              *_gdk_display_arg_name = NULL;
+gboolean            _gdk_native_windows = FALSE;
 
 GSList             *_gdk_displays = NULL;
 
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index a668e68..4cc45f9 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -107,6 +107,7 @@ extern gint		 _gdk_error_code;
 extern gint		 _gdk_error_warnings;
 
 extern guint _gdk_debug_flags;
+extern gboolean _gdk_native_windows;
 
 #ifdef G_ENABLE_DEBUG
 
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index c03104d..977861e 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -866,8 +866,14 @@ recompute_visible_regions_internal (GdkWindowObject *private,
 	    {
 	      gdk_region_intersect (new_clip, private->parent->clip_region);
 
-	      /* Remove all overlapping children from parent */
-	      remove_child_area (private->parent, private, FALSE, new_clip);
+	      /* Remove all overlapping children from parent.
+	       * 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 */
@@ -1093,8 +1099,11 @@ find_native_sibling_above (GdkWindowObject *parent,
 static GdkEventMask
 get_native_event_mask (GdkWindowObject *private)
 {
-  if (private->window_type != GDK_WINDOW_ROOT &&
-      private->window_type != GDK_WINDOW_FOREIGN)
+  if (_gdk_native_windows ||
+      private->window_type == GDK_WINDOW_ROOT ||
+      private->window_type == GDK_WINDOW_FOREIGN)
+    return private->event_mask;
+  else
     {
       return
 	/* 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_BUTTON3_MOTION_MASK));
     }
-  else
-    return private->event_mask;
 }
 
 /* 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.
-   This is useful if some operation changed the stacking order. */
+ * in the hierarchy, given the position it has in the client side data.
+ * 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
 sync_native_window_stack_position (GdkWindow *window)
 {
@@ -1187,6 +1196,13 @@ gdk_window_new (GdkWindow     *parent,
   if (GDK_WINDOW_DESTROYED (parent))
     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);
   private = (GdkWindowObject *) window;
 
@@ -1288,7 +1304,7 @@ gdk_window_new (GdkWindow     *parent,
   if (private->parent)
     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)
     native = TRUE; /* Always use native windows for toplevels */
   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
        * 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
     {
@@ -1432,7 +1449,7 @@ gdk_window_reparent (GdkWindow *window,
   GdkWindowObject *new_parent_private;
   GdkWindowObject *old_parent;
   GdkScreen *screen;
-  gboolean show, was_toplevel, was_mapped;
+  gboolean show, was_mapped;
   gboolean do_reparent_to_impl;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -1476,7 +1493,6 @@ gdk_window_reparent (GdkWindow *window,
       private->redirect = NULL;
     }
 
-  was_toplevel = private->parent == NULL;
   was_mapped = GDK_WINDOW_IS_MAPPED (window);
   show = FALSE;
 
@@ -1576,7 +1592,8 @@ gdk_window_reparent (GdkWindow *window,
       /* 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,
        * so restack */
-      sync_native_window_stack_position (window);
+      if (!gdk_window_has_impl (new_parent_private))
+	sync_native_window_stack_position (window);
     }
 
   if (show)
@@ -1645,8 +1662,9 @@ gdk_window_ensure_native (GdkWindow *window)
   change_impl (private, private, new_impl);
 
   /* Native window creation 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 */
+   * native parent, which may be wrong wrt the position of the previous
+   * non-native window wrt to the other non-native children, so correct this.
+   */
   above = find_native_sibling_above (private->parent, private);
   if (above)
     {
@@ -2361,6 +2379,9 @@ gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
 
   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))
     return FALSE; /* Implementation does double buffering */
 
@@ -3263,8 +3284,8 @@ start_draw_helper (GdkDrawable *drawable,
 	 guarantee ordering. */
       gdk_window_flush ((GdkWindow *)drawable);
 
-      /* Don't clip when drawing to root */
-      if (private->window_type != GDK_WINDOW_ROOT)
+      /* Don't clip when drawing to root or all native */
+      if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
 	{
 	  if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
 	    clip = private->clip_region_with_children;
@@ -5928,7 +5949,13 @@ gdk_window_raise_internal (GdkWindow *window)
 
   /* Just do native raise for toplevels */
   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);
     }
@@ -6203,7 +6230,13 @@ gdk_window_lower_internal (GdkWindow *window)
 
   /* Just do native lower for toplevels */
   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);
     }
@@ -7244,7 +7277,8 @@ gdk_window_set_cursor (GdkWindow *window,
       if (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)
         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))
@@ -9005,6 +9039,11 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
 {
   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;
 
   if (display->pointer_info.window_under_pointer)
@@ -9073,7 +9112,10 @@ gdk_pointer_grab (GdkWindow *	  window,
       !gdk_window_is_viewable (window))
     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))
     {
       native = gdk_offscreen_window_get_embedder (native);
@@ -9178,6 +9220,9 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
   GdkWindow *toplevel;
   GdkWindowObject *toplevel_priv;
 
+  if (_gdk_native_windows)
+    return; /* We use the native crossing events if all native */
+
   display = gdk_drawable_get_display (changed_window);
 
   toplevel = get_event_toplevel (changed_window);
@@ -9650,6 +9695,42 @@ _gdk_windowing_got_event (GdkDisplay *display,
   if (!event_window)
     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);
 
 #ifdef DEBUG_WINDOW_PRINTING



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]