client-side-windows vs metacity



I'm running a full gnome session with the client-side-windows branch
here. There are a few minor issues I'm working on, but overall it just
works(tm). I'll send a new status report soon.

However, there is a specific issue with metacity that I'd like some
feedback on. Metacity uses gdk to handle the frame window for managed
children. This window will get the clients window reparented into it,
however metacity never accesses that window as a gdk window (i.e. it
doesn't call gdk_window_foreign_new on the xid) , so gdk doesn't know
about it.

This means that as gdk knows there are no children of the frame, and
thus the event emulation code won't send a leave for inferior event to
the frame when the mouse moves from the frame to the client window. This
means metacity won't reset the cursor on the frame, thus affecting the
default cursor in the client window. (In X the default cursor is
inherited from the parent.)

Now, how do we solve this? There are two possibilities. Either we add
special code to metacity so that it creates the child window as a gdk
object and keeps it updated as to the size when the frame is resized.

Or, we add some hacks to gdk to track this case and make it work. One
way is to detect native Inferior Leave events on windows with no
children and use XQueryTree to find the windows. Resizes can be tracked
with ConfigureEvents. I'm attaching a patch that implements this.

Solution 1 requires code to be added to metacity, that could would work
(but be useless) on older gtk+ versions, but older metacity versions
would be incompatible with a csw gtk+.

Solution 2 doesn't require any metacity changes, but is kinda ugly and
may cause other problems. Or, possibly it could solve other similar
problems if they happen in other apps.

What approach do people think is best here?
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index bd73aed..44dee5e 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -959,6 +959,47 @@ gdk_event_translate (GdkDisplay *display,
     
   if (window != NULL)
     {
+      if (xevent->type == LeaveNotify &&
+	  xevent->xcrossing.detail == NotifyInferior &&
+	  window_private->children == NULL &&
+	  GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+	{
+	  GdkWindowImplX11 *child_impl;
+	  GdkWindow *child;
+	  Window ret_parent, ret_root, *ret_children;
+	  guint ret_nchildren;
+	  int i;
+	  
+	  /* We got a leave-notify for an inferiour window, but
+	   * we don't know of any such windows, so look for one.
+	   * We also set track_configure to make sure we later
+	   * update the size of the window if it changes.
+	   *
+	   * This is a workaround for metacity to find the client
+	   * window in the frame.
+	   */
+	  gdk_error_trap_push ();
+	  if (XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
+			  &ret_root, &ret_parent,
+			  &ret_children, &ret_nchildren))
+	    {
+	      for (i = 0; i < ret_nchildren; i++)
+		{
+		  child = gdk_window_foreign_new_for_display (display,
+							      ret_children[i]);
+		  if (child)
+		    {
+		      child_impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (child)->impl);
+		      child_impl->track_configure = TRUE;
+		    }
+		}
+	      
+	      if (ret_children)
+		XFree (ret_children);
+	    }
+	  gdk_error_trap_pop ();
+	}
+
       /* Apply keyboard grabs to non-native windows */
       if (/* Is key event */
 	  (xevent->type == KeyPress || xevent->type == KeyRelease) &&
@@ -1876,6 +1917,21 @@ gdk_event_translate (GdkDisplay *display,
 	}
 #endif
 
+      if (window && window_impl->track_configure &&
+	  xevent->xconfigure.event != xevent->xconfigure.window)
+	{
+	  /* We're getting a configure event for the child which we
+	     normally won't send to the app. However, as a part of
+	     the metacity workaround above we want to update the
+	     size of the window as gdk knows */
+	  window_private->x = xevent->xconfigure.x;
+	  window_private->y = xevent->xconfigure.y;
+	  window_private->width = xevent->xconfigure.width;
+	  window_private->height = xevent->xconfigure.height;
+	  _gdk_window_update_size (window);
+	  _gdk_x11_drawable_update_size (window_private->impl);
+	}
+
       if (!window ||
 	  xevent->xconfigure.event != xevent->xconfigure.window ||
           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h
index 9a7f2ae..b77a50c 100644
--- a/gdk/x11/gdkwindow-x11.h
+++ b/gdk/x11/gdkwindow-x11.h
@@ -65,6 +65,9 @@ struct _GdkWindowImplX11
 				 * unset during resizing and scaling */
   guint override_redirect : 1;
   guint use_synchronized_configure : 1;
+  guint track_configure : 1;    /* This is a workaround to track unknown
+				   foreign children, mainly to make metacity
+				   work */
 
 #if defined (HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
   Damage damage;


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