Standardizing _METACITY_UPDATE_COUNTER



Okay, here are metacity, gtk+ and wm-spec patches. The differences to
what we discussed earlier are

        - the initial value of the sync counter is undefined

        - the window manager is allowed to change the sync counter
          at any time

This is necessry, because if you change window manager the counter
would have an unpredictable value. So I made it the responsibility of
the window manager to set the initial value of the counter. It can do
this when it first sees the window, or it can do what the metacity
patch does: reset the counter every time it starts a resizing
sequence.

Søren


? sync-request-spec.patch
? syncrequest.patch
Index: wm-spec.xml
===================================================================
RCS file: /cvs/icccm-extensions/wm-spec/wm-spec.xml,v
retrieving revision 1.9
diff -u -r1.9 wm-spec.xml
--- wm-spec.xml	29 Jan 2004 13:19:58 -0000	1.9
+++ wm-spec.xml	26 Apr 2004 13:38:36 -0000
@@ -1438,6 +1438,57 @@
 		<para>
 See also the implementation notes on <link linkend="KILLINGWINDOWS">killing hung processes</link>.
 		</para>
+		<title>_NET_WM_SYNC_REQUEST</title>
+		<para>
+This protocol uses the XSync extension (see <ulink
+url="http://www.xfree86.org/current/sync.pdf";>the
+specification</ulink> and <ulink
+url="http://www.xfree86.org/current/synclib.pdf";>the library
+documentation</ulink>) to let client and window manager to synchronize
+the repaint of the window manager frame and the client window. A
+client indicates that it is willing to participate in the protocol by
+listing _NET_WM_SYNC_REQUEST in the WM_PROTOCOLS property of the
+client window and storing the XID of an XSync counter in the property
+_NET_WM_SYNC_REQUEST_COUNTER. The initial value of this counter is not
+defined by this specification.
+		</para>
+		<para>
+A window manager uses this protocol by preceding a ConfigureNotify
+event sent to a client by a client message as follows:
+		<para>
+		<programlisting><![[CDATA[
+type = ClientMessage
+window = the respective client window
+message_type = WM_PROTOCOLS
+format = 32
+data.l[0] = _NET_WM_SYNC_REQUEST
+data.l[1] = timestamp
+data.l[2] = low 32 bits of the update request number
+data.l[3] = high 32 bits of the update request number
+other data.l[] elements = 0
+]]></programlisting>
+		</para>
+		<para>
+After receiving one or more such message/ConfigureNotify pairs, and
+having handled all repainting associated with the ConfigureNotify
+events, the client MUST set the _NET_WM_SYNC_REQUEST_COUNTER to the 64
+bit number indicated by the data.l[2] and data.l[3] fields of the last
+client message received.
+		</para>
+		<para>
+By using either the Alarm or the Await mechanisms of the XSync
+extension, the window manager can know when the client has finished
+handling the ConfigureNotify events. The window manager SHOULD not
+resize the window faster than the client can keep up.
+		</para>
+		<para>
+The update request number in the client message is determined by the
+window manager, but is generally intended to be incremented by one for
+each message sent. Since the initial value of the XSync counter is not
+defined by this specification, the window manager MAY set the value of
+the XSync counter at any time, and MUST do so when it first manages a
+new window.
+		</para>
 	</sect2>
 </sect1>
 <sect1>
? 120479.patch
? Xcursor.patch
? adjustment-smooth.diff
? asdf
? bidi-2.patch
? birnan
? blap
? cachepatch
? childspace.patch
? commit
? config.guess
? config.sub
? constpatch
? counter-bidi-sync.patch
? counter-final-beta1.patch
? counter-retro.patch
? counter.patch
? depcomp
? deselect.patch
? destroy-fix.patch
? drawfix.patch
? frugt
? gcfix
? gtk-doc.make
? gtk-update-counter-2.patch
? gtk-update-counter.patch
? gtkd
? headdiff
? hmm
? huh
? ipadding.patch
? keymap.patch
? ltmain.sh
? menu.before-caching.patch
? menu.deadend.patch
? menu.with-caching.nw.patch
? menu.with-caching.patch
? menufix
? menufix-2.patch
? no-flicker-2.patch
? no-flicker-3.patch
? no-flicker.patch
? oldcounter+toolbar.patch
? owen-119722.patch
? radiomenuitem.patch
? rayiner-gtk-sync.diff
? showattachment.cgi
? socketpatch
? update-counter-ssp.patch
? usertime.patch
? usertime2.patch
? wheelfix-2.patch
? wheelfix-3.patch
? wheelfix.patch
? xft-instant-apply.patch
? demos/gtk-demo/core.31767
? demos/gtk-demo/core.31787
? gdk/119722.patch
? gdk/134230.patch
? gdk/antiexpose.patch
? gdk/blahblah.patch
? gdk/core.20280
? gdk/destroy-fix.patch
? gdk/emfle.patch
? gdk/gccache.patch
? gdk/gcfix
? gdk/huh
? gdk/newgccache.patch
? gdk/owen-134230-2.patch
? gdk/owen-134230.patch
? gdk/showattachment.cgi
? gdk/x11/antiexpose.patch
? gdk/x11/bitmap.patch
? gdk/x11/gdkdrawable-x11.ac
? gdk/x11/huh
? gdk/x11/xsettings.patch
? gtk/136446.patch
? gtk/57100.patch
? gtk/accels
? gtk/asdf.c
? gtk/birnan
? gtk/core.11586
? gtk/core.14263
? gtk/core.15648
? gtk/core.21013
? gtk/cursors.patch
? gtk/emfle.patch
? gtk/group.patch
? gtk/groupproperty.patch
? gtk/gtktoolbar.bad-approach.c
? gtk/mb-childspace-2.patch
? gtk/menu.start.patch
? gtk/showattachment.cgi
? gtk/sizer.patch
? gtk/window-group.patch
? tests/accels
? tests/action.patch
? tests/core.10834
? tests/core.11612
? tests/core.15556
? tests/core.19977
? tests/core.21230
? tests/core.21653
? tests/core.21684
? tests/core.22096
? tests/core.22114
? tests/core.22546
? tests/core.22970
? tests/core.24449
? tests/core.24946
? tests/menu-performance
? tests/menu-performance.c
Index: acconfig.h
===================================================================
RCS file: /cvs/gnome/gtk+/acconfig.h,v
retrieving revision 1.29
diff -u -p -u -r1.29 acconfig.h
--- acconfig.h	25 Jan 2004 22:19:39 -0000	1.29
+++ acconfig.h	26 Apr 2004 00:03:29 -0000
@@ -47,6 +47,9 @@
 #undef USE_GMODULE
 #undef USE_MMX
 
+/* Define to use Sync extension */
+#undef HAVE_XSYNC
+
 /* Define to use XKB extension */
 #undef HAVE_XKB
 
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gtk+/configure.in,v
retrieving revision 1.381
diff -u -p -u -r1.381 configure.in
--- configure.in	18 Apr 2004 15:04:17 -0000	1.381
+++ configure.in	26 Apr 2004 00:03:31 -0000
@@ -183,6 +183,10 @@ AC_ARG_ENABLE(ansi,
               [AC_HELP_STRING([--enable-ansi],
                               [turn on strict ansi [default=no]])],,
               [enable_ansi=no])
+AC_ARG_ENABLE(xsync,
+              [AC_HELP_STRING([--enable-xsync],
+                              [support X synchronization extension if available [default=yes]])],,
+              [enable_xsync="yes"])
 AC_ARG_ENABLE(xkb,
               [AC_HELP_STRING([--enable-xkb],
                               [support XKB [default=maybe]])],,
@@ -1207,7 +1211,17 @@ if test "x$gdktarget" = "xx11"; then
     GDK_EXTRA_CFLAGS="`$PKG_CONFIG --cflags xcursor` $GDK_EXTRA_CFLAGS"
     GDK_EXTRA_LIBS="`$PKG_CONFIG --libs xcursor` $GDK_EXTRA_LIBS"
   fi
-    
+
+  # X SYNC check
+
+  if test "x$enable_xsync" = "xyes"; then
+    AC_CHECK_LIB(Xext, XSyncQueryExtension,
+      [GTK_ADD_LIB(x_extra_libs,Xext)
+       AC_DEFINE([HAVE_XSYNC], [], [Have SYNC extension])],
+       ,
+       $x_libs_for_checks)
+  fi
+
   # Xshm checks
 
   if test "x$enable_shm" = "xyes"; then
Index: gdk/gdkinternals.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkinternals.h,v
retrieving revision 1.30
diff -u -p -u -r1.30 gdkinternals.h
--- gdk/gdkinternals.h	13 Mar 2004 18:27:55 -0000	1.30
+++ gdk/gdkinternals.h	26 Apr 2004 00:03:35 -0000
@@ -222,6 +222,8 @@ void       _gdk_window_destroy          
 					  gboolean     foreign_destroy);
 void       _gdk_window_clear_update_area (GdkWindow   *window);
 
+void       _gdk_window_queue_update_notify (void);
+
 void       _gdk_screen_close             (GdkScreen   *screen);
 
 const char *_gdk_get_sm_client_id (void);
@@ -242,6 +244,8 @@ extern GdkArgDesc _gdk_windowing_args[];
 void     _gdk_windowing_init                    (gint       *argc,
                                                  gchar    ***argv);
 void     _gdk_windowing_set_default_display     (GdkDisplay *display);
+
+void     _gdk_windowing_notify_updated          (void);
 
 gchar *_gdk_windowing_substitute_screen_number (const gchar *display_name,
 					        gint         screen_number);
Index: gdk/gdkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.c,v
retrieving revision 1.159
diff -u -p -u -r1.159 gdkwindow.c
--- gdk/gdkwindow.c	13 Mar 2004 18:27:55 -0000	1.159
+++ gdk/gdkwindow.c	26 Apr 2004 00:03:39 -0000
@@ -1986,11 +1986,33 @@ gdk_window_copy_to_image (GdkDrawable   
 
 /* Code for dirty-region queueing
  */
-
 static GSList *update_windows = NULL;
 static guint update_idle = 0;
 static gboolean debug_updates = FALSE;
 
+static gboolean
+gdk_window_update_idle (gpointer data)
+{
+  GDK_THREADS_ENTER ();
+  gdk_window_process_all_updates ();
+  GDK_THREADS_LEAVE ();
+  
+  return FALSE;
+}
+
+static void
+gdk_window_schedule_update (GdkWindow *window)
+{
+  if (window && GDK_WINDOW_OBJECT (window)->update_freeze_count)
+    return;
+
+  if (!update_idle)
+    {
+      update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
+				     gdk_window_update_idle, NULL, NULL);
+    }
+}
+
 static void
 gdk_window_process_updates_internal (GdkWindow *window)
 {
@@ -2096,24 +2118,35 @@ gdk_window_process_all_updates (void)
   
   while (tmp_list)
     {
-      gdk_window_process_updates_internal (tmp_list->data);
+      GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
+      
+      if (private->update_freeze_count)
+	update_windows = g_slist_prepend (update_windows, private);
+      else
+	gdk_window_process_updates_internal (tmp_list->data);
+      
       g_object_unref (tmp_list->data);
       tmp_list = tmp_list->next;
     }
 
   g_slist_free (old_update_windows);
 
+  _gdk_windowing_notify_updated ();
+
   flush_all_displays ();
 }
 
-static gboolean
-gdk_window_update_idle (gpointer data)
+/**
+ * _gdk_window_queue_update_notify
+ *
+ * Internal function that schedules a call of the function
+ * _gdk_windowing_notify_updated() after all windows have
+ * been updated.
+ */
+void
+_gdk_window_queue_update_notify (void)
 {
-  GDK_THREADS_ENTER ();
-  gdk_window_process_all_updates ();
-  GDK_THREADS_LEAVE ();
-  
-  return FALSE;
+  gdk_window_schedule_update (NULL);
 }
 
 /**
@@ -2285,9 +2318,7 @@ gdk_window_invalidate_maybe_recurse (Gdk
 	  update_windows = g_slist_prepend (update_windows, window);
 	  private->update_area = gdk_region_copy (visible_region);
 	  
-	  if (!private->update_freeze_count && !update_idle)
-	    update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
-					   gdk_window_update_idle, NULL, NULL);
+	  gdk_window_schedule_update (window);
 	}
       
       if (child_func)
@@ -2460,9 +2491,7 @@ gdk_window_thaw_updates (GdkWindow *wind
   g_return_if_fail (private->update_freeze_count > 0);
 
   private->update_freeze_count--;
-  if (!private->update_freeze_count && private->update_area && !update_idle)
-    update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
-				   gdk_window_update_idle, NULL, NULL);
+  gdk_window_schedule_update (window);
 }
 
 /**
Index: gdk/linux-fb/gdkevents-fb.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/linux-fb/gdkevents-fb.c,v
retrieving revision 1.14
diff -u -p -u -r1.14 gdkevents-fb.c
--- gdk/linux-fb/gdkevents-fb.c	6 Mar 2004 03:37:04 -0000	1.14
+++ gdk/linux-fb/gdkevents-fb.c	26 Apr 2004 00:03:40 -0000
@@ -231,3 +231,8 @@ void
 gdk_display_flush (GdkDisplay * display)
 {
 }
+
+void
+_gdk_windowing_notify_updated (void)
+{
+}
Index: gdk/win32/gdkevents-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkevents-win32.c,v
retrieving revision 1.131
diff -u -p -u -r1.131 gdkevents-win32.c
--- gdk/win32/gdkevents-win32.c	20 Mar 2004 23:45:31 -0000	1.131
+++ gdk/win32/gdkevents-win32.c	26 Apr 2004 00:03:50 -0000
@@ -3472,3 +3472,8 @@ gdk_net_wm_supports (GdkAtom property)
 {
   return FALSE;
 }
+
+void
+_gdk_windowing_notify_updated (void)
+{
+}
Index: gdk/x11/gdkdisplay-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.c,v
retrieving revision 1.41
diff -u -p -u -r1.41 gdkdisplay-x11.c
--- gdk/x11/gdkdisplay-x11.c	18 Apr 2004 14:33:07 -0000	1.41
+++ gdk/x11/gdkdisplay-x11.c	26 Apr 2004 00:03:51 -0000
@@ -79,6 +79,8 @@ static const char *const precache_atoms[
   "_NET_WM_STATE_MAXIMIZED_VERT",
   "_NET_WM_STATE_MAXIMIZED_HORZ",
   "_NET_WM_STATE_FULLSCREEN",
+  "_NET_WM_SYNC_REQUEST",
+  "_NET_WM_SYNC_REQUEST_COUNTER",
   "_NET_WM_WINDOW_TYPE",
   "_NET_WM_WINDOW_TYPE_NORMAL",
   "_NET_WM_USER_TIME",
@@ -258,6 +260,20 @@ gdk_display_open (const gchar *display_n
   }
 #endif
 
+  display_x11->use_sync = FALSE;
+#ifdef HAVE_XSYNC
+  {
+    int major, minor;
+    int error_base, event_base;
+    
+    if (XSyncQueryExtension (display_x11->xdisplay,
+			     &event_base, &error_base) &&
+        XSyncInitialize (display_x11->xdisplay,
+                         &major, &minor))
+      display_x11->use_sync = TRUE;
+  }
+#endif
+  
   _gdk_windowing_image_init (display);
   _gdk_events_init (display);
   _gdk_input_init (display);
Index: gdk/x11/gdkdisplay-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.h,v
retrieving revision 1.16
diff -u -p -u -r1.16 gdkdisplay-x11.h
--- gdk/x11/gdkdisplay-x11.h	18 Apr 2004 14:33:07 -0000	1.16
+++ gdk/x11/gdkdisplay-x11.h	26 Apr 2004 00:03:51 -0000
@@ -145,6 +145,7 @@ struct _GdkDisplayX11
   guint base_dnd_atoms_precached : 1;
   guint xdnd_atoms_precached : 1;
   guint motif_atoms_precached : 1;
+  guint use_sync : 1;
 };
 
 struct _GdkDisplayX11Class
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.130
diff -u -p -u -r1.130 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c	23 Apr 2004 13:03:56 -0000	1.130
+++ gdk/x11/gdkevents-x11.c	26 Apr 2004 00:03:53 -0000
@@ -46,6 +46,10 @@
 #include <X11/XKBlib.h>
 #endif
 
+#ifdef HAVE_XSYNC
+#include <X11/extensions/sync.h>
+#endif
+
 #include <X11/Xatom.h>
 
 typedef struct _GdkIOClosure GdkIOClosure;
@@ -113,6 +117,9 @@ static void gdk_xsettings_notify_cb (con
  */
 
 static GList *display_sources;
+#ifdef HAVE_XSYNC
+static GSList *update_toplevels;
+#endif
 
 static GSourceFuncs event_funcs = {
   gdk_event_prepare,
@@ -211,11 +218,10 @@ _gdk_events_init (GdkDisplay *display)
 
   display_sources = g_list_prepend (display_sources,display_source);
 
-  gdk_display_add_client_message_filter (
-	display,
-	gdk_atom_intern ("WM_PROTOCOLS", FALSE), 
-	gdk_wm_protocols_filter,   
-	NULL);
+  gdk_display_add_client_message_filter (display,
+					 gdk_atom_intern ("WM_PROTOCOLS", FALSE), 
+					 gdk_wm_protocols_filter,   
+					 NULL);
 }
 
 
@@ -1720,6 +1726,25 @@ gdk_event_translate (GdkDisplay *display
 	  (window_private->extension_events != 0))
 	_gdk_input_configure_event (&xevent->xconfigure, window);
 
+#ifdef HAVE_XSYNC
+      if (toplevel && display_x11->use_sync)
+	{
+	  if (!XSyncValueIsZero (toplevel->last_counter_value))
+	    {
+	      toplevel->next_counter_value = toplevel->last_counter_value;
+	      XSyncIntToValue (&toplevel->last_counter_value, 0);
+
+	      _gdk_window_queue_update_notify ();
+
+	      if (!g_slist_find (update_toplevels, window))
+		{
+		  update_toplevels =
+		    g_slist_prepend (update_toplevels, g_object_ref (window));
+		}
+	    }
+	}
+#endif
+      
       if (!window ||
 	  xevent->xconfigure.event != xevent->xconfigure.window ||
           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
@@ -2000,8 +2025,9 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
   XEvent *xevent = (XEvent *)xev;
   GdkWindow *win = event->any.window;
   GdkDisplay *display = GDK_WINDOW_DISPLAY (win);
+  Atom atom = (Atom)xevent->xclient.data.l[0];
 
-  if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
+  if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
     {
   /* The delete window request specifies a window
    *  to delete. We don't actually destroy the
@@ -2019,7 +2045,7 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
 
       return GDK_FILTER_TRANSLATE;
     }
-  else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
+  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
     {
       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
       GdkWindowObject *private = (GdkWindowObject *)win;
@@ -2034,7 +2060,7 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
 
       return GDK_FILTER_REMOVE;
     }
-  else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
+  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
 	   !_gdk_x11_display_is_root_window (display,
 					     xevent->xclient.window))
     {
@@ -2048,10 +2074,56 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
 
       return GDK_FILTER_REMOVE;
     }
-
+  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST") &&
+	   GDK_DISPLAY_X11 (display)->use_sync)
+    {
+      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
+      if (toplevel)
+	{
+#ifdef HAVE_XSYNC
+	  XSyncIntsToValue (&toplevel->last_counter_value, 
+			    xevent->xclient.data.l[2], 
+			    xevent->xclient.data.l[3]);
+#endif
+	}
+      return GDK_FILTER_REMOVE;
+    }
+  
   return GDK_FILTER_CONTINUE;
 }
 
+void
+_gdk_windowing_notify_updated (void)
+{
+#ifdef HAVE_XSYNC
+  GSList *slist;
+  
+  for (slist = update_toplevels; slist != NULL; slist = slist->next)
+    {
+      GdkWindow *window = slist->data;
+
+      if (!GDK_WINDOW_DESTROYED (window))
+	{
+	  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+	  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+	  
+	  if (toplevel && GDK_DISPLAY_X11 (display)->use_sync)
+	    {
+	      XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
+			       toplevel->update_counter,
+			       toplevel->next_counter_value);
+	      
+	      XSyncIntToValue (&toplevel->next_counter_value, 0);
+	    }
+	}
+      g_object_unref (window);
+    }
+
+  g_slist_free (update_toplevels);
+  update_toplevels = NULL;
+#endif
+}
+  
 void
 _gdk_events_queue (GdkDisplay *display)
 {
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.205
diff -u -p -u -r1.205 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c	18 Apr 2004 14:33:07 -0000	1.205
+++ gdk/x11/gdkwindow-x11.c	26 Apr 2004 00:04:02 -0000
@@ -349,14 +349,16 @@ _gdk_windowing_window_init (GdkScreen * 
 static void
 set_wm_protocols (GdkWindow *window)
 {
+#define N_PROTOCOLS 4
   GdkDisplay *display = gdk_drawable_get_display (window);
-  Atom protocols[3];
+  Atom protocols[N_PROTOCOLS];
   
   protocols[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
   protocols[1] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
   protocols[2] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
+  protocols[3] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
 
-  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, 3);
+  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, N_PROTOCOLS);
 }
 
 static const gchar *
@@ -405,7 +407,35 @@ create_focus_window (Display *xdisplay,
 }
 
 static void
-setup_toplevel_window (GdkWindow *window, GdkWindow *parent)
+create_sync_request_counter (GdkDisplay       *display,
+			     XID               xid,
+			     GdkToplevelX11   *toplevel)
+{
+#ifdef HAVE_XSYNC
+  XSyncValue value;
+  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  Atom atom;
+
+  XSyncIntToValue (&value, 0);
+  
+  toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
+
+  atom = gdk_x11_get_xatom_by_name_for_display (display,
+						"_NET_WM_SYNC_REQUEST_COUNTER");
+
+  XChangeProperty (xdisplay, xid,
+		   atom, XA_CARDINAL,
+		   32, PropModeReplace,
+		   (guchar *)&toplevel->update_counter, 1);
+  
+  XSyncIntToValue (&toplevel->last_counter_value, 0);
+  XSyncIntToValue (&toplevel->next_counter_value, 0);
+#endif /* HAVE_XSYNC */
+}
+
+static void
+setup_toplevel_window (GdkWindow *window, 
+		       GdkWindow *parent)
 {
   GdkWindowObject *obj = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
@@ -458,6 +488,9 @@ setup_toplevel_window (GdkWindow *window
 		   XA_WINDOW, 32, PropModeReplace,
 		   (guchar *) &GDK_DISPLAY_X11 (screen_x11->display)->leader_window, 1);
 
+  if (GDK_DISPLAY_X11 (screen_x11->display)->use_sync)
+    create_sync_request_counter (screen_x11->display, xid, toplevel);
+
   if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
     _gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
 }
@@ -893,7 +926,8 @@ gdk_window_lookup (GdkNativeWindow anid)
 }
 
 static void
-gdk_toplevel_x11_free_contents (GdkToplevelX11 *toplevel)
+gdk_toplevel_x11_free_contents (GdkDisplay *display,
+				GdkToplevelX11 *toplevel)
 {
   if (toplevel->icon_window)
     {
@@ -915,6 +949,17 @@ gdk_toplevel_x11_free_contents (GdkTople
       g_object_unref (toplevel->group_leader);
       toplevel->group_leader = NULL;
     }
+  if (toplevel->update_counter != None)
+    {
+#ifdef HAVE_XSYNC
+      XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
+			   toplevel->update_counter);
+      toplevel->update_counter = None;
+
+      XSyncIntToValue (&toplevel->last_counter_value, 0);
+      XSyncIntToValue (&toplevel->next_counter_value, 0);
+#endif
+    }
 }
 
 void
@@ -935,7 +980,7 @@ _gdk_windowing_window_destroy (GdkWindow
 
   toplevel = _gdk_x11_window_get_toplevel (window);
   if (toplevel)
-    gdk_toplevel_x11_free_contents (toplevel);
+    gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
 
   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
     
@@ -1574,7 +1619,8 @@ gdk_window_reparent (GdkWindow *window,
 		  _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
 		}
 		
-	      gdk_toplevel_x11_free_contents (impl->toplevel);
+	      gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
+					      impl->toplevel);
 	      g_free (impl->toplevel);
 	      impl->toplevel = NULL;
 	    }
Index: gdk/x11/gdkwindow-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.h,v
retrieving revision 1.11
diff -u -p -u -r1.11 gdkwindow-x11.h
--- gdk/x11/gdkwindow-x11.h	18 Apr 2004 14:33:07 -0000	1.11
+++ gdk/x11/gdkwindow-x11.h	26 Apr 2004 00:04:03 -0000
@@ -29,6 +29,10 @@
 
 #include <gdk/x11/gdkdrawable-x11.h>
 
+#ifdef HAVE_XSYNC
+#include <X11/extensions/sync.h>
+#endif
+
 G_BEGIN_DECLS
 
 typedef struct _GdkToplevelX11 GdkToplevelX11;
@@ -119,13 +123,22 @@ struct _GdkToplevelX11
    * that might not even be part of this app
    */
   Window focus_window;
+
+#ifdef HAVE_XSYNC
+  XID update_counter;
+  XSyncValue last_counter_value;  /* latest _NET_WM_SYNC_REQUEST value received */
+  XSyncValue next_counter_value;  /* latest _NET_WM_SYNC_REQUEST value for which we have
+				   * received the corresponding ConfigureNotify
+				   */
+#endif
 };
 
 GType gdk_window_impl_x11_get_type (void);
 
-GdkToplevelX11 *_gdk_x11_window_get_toplevel  (GdkWindow *window);
-void            _gdk_x11_window_set_user_time (GdkWindow *window,
-                                               guint32    timestamp);
+GdkToplevelX11 *_gdk_x11_window_get_toplevel   (GdkWindow *window);
+void            _gdk_x11_window_set_user_time  (GdkWindow *window,
+                                                guint32    timestamp);
+void            _gdk_x11_window_notify_updated (GdkWindow *window);
 
 G_END_DECLS
 
? bidi-2.patch
? blah
? emfle.patch
? hmm
? meta-theme.patch
? metacity-counter-bidi-sync.patch
? metacity-counter-final-beta1.patch
? metacity-counter.patch
? src/asdf
? src/compiled-theme.h
? src/exc-theme-parser.c
? src/gccheck
? src/hmm
? src/index.html
? src/new-new-theme-parser.c
? src/new-theme-parser.c
? src/new-theme-parser.h
? src/new_theme.h
? src/old-theme-parser.c
? src/results.aspx?View=msdn&st=a&qu=windows+forms&c=0&s=1
? src/spew
? src/theme-compiler.c
? src/theme-compiler.h
? src/theme-utils.h
Index: src/display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.215
diff -u -p -u -r1.215 display.c
--- src/display.c	16 Apr 2004 03:38:19 -0000	1.215
+++ src/display.c	26 Apr 2004 00:59:05 -0000
@@ -2,7 +2,7 @@
 
 /* 
  * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002, 2003 Red Hat, Inc.
+ * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
  * Copyright (C) 2003, 2004 Rob Adams
  * 
  * This program is free software; you can redistribute it and/or
@@ -270,8 +270,8 @@ meta_display_open (const char *name)
     "_NET_WM_STATE_BELOW",
     "_NET_STARTUP_ID",
     "_METACITY_TOGGLE_VERBOSE",
-    "_METACITY_UPDATE_COUNTER",
-    "SYNC_COUNTER",
+    "_NET_WM_SYNC_REQUEST",
+    "_NET_WM_SYNC_REQUEST_COUNTER",
     "_GNOME_PANEL_ACTION",
     "_GNOME_PANEL_ACTION_MAIN_MENU",
     "_GNOME_PANEL_ACTION_RUN_DIALOG",
@@ -323,7 +323,7 @@ meta_display_open (const char *name)
   display->expected_focus_window = NULL;
 
 #ifdef HAVE_XSYNC
-  display->grab_update_alarm = None;
+  display->grab_sync_request_alarm = None;
 #endif
   
   /* FIXME copy the checks from GDK probably */
@@ -416,8 +416,8 @@ meta_display_open (const char *name)
   display->atom_net_wm_state_below = atoms[71];
   display->atom_net_startup_id = atoms[72];
   display->atom_metacity_toggle_verbose = atoms[73];
-  display->atom_metacity_update_counter = atoms[74];
-  display->atom_sync_counter = atoms[75];
+  display->atom_net_wm_sync_request = atoms[74];
+  display->atom_net_wm_sync_request_counter = atoms[75];
   display->atom_gnome_panel_action = atoms[76];
   display->atom_gnome_panel_action_main_menu = atoms[77];
   display->atom_gnome_panel_action_run_dialog = atoms[78];
@@ -1264,7 +1264,7 @@ event_callback (XEvent   *event,
 #ifdef HAVE_XSYNC
   if (META_DISPLAY_HAS_XSYNC (display) && 
       event->type == (display->xsync_event_base + XSyncAlarmNotify) &&
-      ((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_update_alarm)
+      ((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_sync_request_alarm)
     {
       filter_out_event = TRUE; /* GTK doesn't want to see this really */
       
@@ -1272,7 +1272,7 @@ event_callback (XEvent   *event,
           display->grab_window != NULL &&
           event->xany.serial >= display->grab_start_serial &&
           grab_op_is_mouse (display->grab_op))
-        meta_window_handle_mouse_grab_op_event (display->grab_window, event);
+	meta_window_handle_mouse_grab_op_event (display->grab_window, event);
     }
 #endif /* HAVE_XSYNC */
 
@@ -2969,10 +2969,16 @@ meta_display_begin_grab_op (MetaDisplay 
   display->grab_last_moveresize_time.tv_usec = 0;
   display->grab_motion_notify_time = 0;
 #ifdef HAVE_XSYNC
-  display->grab_update_alarm = None;
+  display->grab_sync_request_alarm = None;
 #endif
   display->grab_was_cancelled = FALSE;
   
+  if (display->grab_resize_timeout_id)
+    {
+      g_source_remove (display->grab_resize_timeout_id);
+      display->grab_resize_timeout_id = 0;
+    }
+	
   if (display->grab_window)
     {
       display->grab_initial_window_pos = display->grab_window->rect;
@@ -3007,28 +3013,41 @@ meta_display_begin_grab_op (MetaDisplay 
 #ifdef HAVE_XSYNC
       if (!display->grab_wireframe_active &&
           meta_grab_op_is_resizing (display->grab_op) &&
-          display->grab_window->update_counter != None)
+          display->grab_window->sync_request_counter != None)
         {
           XSyncAlarmAttributes values;
+	  XSyncValue init;
 
-          /* trigger when we make a positive transition to a value
-           * one higher than the current value.
-           */
-          values.trigger.counter = display->grab_window->update_counter;
-          values.trigger.value_type = XSyncRelative;
-          values.trigger.test_type = XSyncPositiveTransition;
-          XSyncIntToValue (&values.trigger.wait_value, 1);
+          meta_error_trap_push_with_return (display);
 
+	  /* Set the counter to 0, so we know that the application's
+	   * responses to the client messages will always trigger
+	   * a PositiveTransition
+	   */
+	  
+	  XSyncIntToValue (&init, 0);
+	  XSyncSetCounter (display->xdisplay,
+			   display->grab_window->sync_request_counter, init);
+	  
+	  display->grab_window->sync_request_serial = 0;
+	  display->grab_window->sync_request_time.tv_sec = 0;
+	  display->grab_window->sync_request_time.tv_usec = 0;
+	  
+          values.trigger.counter = display->grab_window->sync_request_counter;
+          values.trigger.value_type = XSyncAbsolute;
+          values.trigger.test_type = XSyncPositiveTransition;
+          XSyncIntToValue (&values.trigger.wait_value,
+			   display->grab_window->sync_request_serial + 1);
+	  
           /* After triggering, increment test_value by this.
            * (NOT wait_value above)
            */
           XSyncIntToValue (&values.delta, 1);
-
+	  
           /* we want events (on by default anyway) */
           values.events = True;
           
-          meta_error_trap_push_with_return (display);
-          display->grab_update_alarm = XSyncCreateAlarm (display->xdisplay,
+          display->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay,
                                                          XSyncCACounter |
                                                          XSyncCAValueType |
                                                          XSyncCAValue |
@@ -3036,12 +3055,13 @@ meta_display_begin_grab_op (MetaDisplay 
                                                          XSyncCADelta |
                                                          XSyncCAEvents,
                                                          &values);
+
           if (meta_error_trap_pop_with_return (display, FALSE) != Success)
-            display->grab_update_alarm = None;
+	    display->grab_sync_request_alarm = None;
 
           meta_topic (META_DEBUG_RESIZING,
                       "Created update alarm 0x%lx\n",
-                      display->grab_update_alarm);
+                      display->grab_sync_request_alarm);
         }
 #endif
     }
@@ -3138,10 +3158,11 @@ meta_display_end_grab_op (MetaDisplay *d
     }
 
 #ifdef HAVE_XSYNC
-  if (display->grab_update_alarm != None)
+  if (display->grab_sync_request_alarm != None)
     {
       XSyncDestroyAlarm (display->xdisplay,
-                         display->grab_update_alarm);
+                         display->grab_sync_request_alarm);
+      display->grab_sync_request_alarm = None;
     }
 #endif /* HAVE_XSYNC */
 
@@ -3176,6 +3197,12 @@ meta_display_end_grab_op (MetaDisplay *d
     {
       meta_ui_resize_popup_free (display->grab_resize_popup);
       display->grab_resize_popup = NULL;
+    }
+
+  if (display->grab_resize_timeout_id)
+    {
+      g_source_remove (display->grab_resize_timeout_id);
+      display->grab_resize_timeout_id = 0;
     }
 }
 
Index: src/display.h
===================================================================
RCS file: /cvs/gnome/metacity/src/display.h,v
retrieving revision 1.116
diff -u -p -u -r1.116 display.h
--- src/display.h	23 Feb 2004 01:48:29 -0000	1.116
+++ src/display.h	26 Apr 2004 00:59:05 -0000
@@ -166,8 +166,8 @@ struct _MetaDisplay
   Atom atom_net_wm_state_below;
   Atom atom_net_startup_id;
   Atom atom_metacity_toggle_verbose;
-  Atom atom_metacity_update_counter;
-  Atom atom_sync_counter;
+  Atom atom_net_wm_sync_request;
+  Atom atom_net_wm_sync_request_counter;
   Atom atom_gnome_panel_action;
   Atom atom_gnome_panel_action_main_menu;
   Atom atom_gnome_panel_action_run_dialog;
@@ -258,9 +258,10 @@ struct _MetaDisplay
   int         xkb_base_event_type;
 #endif
 #ifdef HAVE_XSYNC
-  /* alarm monitoring client's _METACITY_UPDATE_COUNTER */
-  XSyncAlarm  grab_update_alarm;
+  /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
+  XSyncAlarm  grab_sync_request_alarm;
 #endif
+  int	      grab_resize_timeout_id;
 
   /* Keybindings stuff */
   MetaKeyBinding *screen_bindings;
Index: src/window-props.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window-props.c,v
retrieving revision 1.15
diff -u -p -u -r1.15 window-props.c
--- src/window-props.c	13 Dec 2003 23:00:06 -0000	1.15
+++ src/window-props.c	26 Apr 2004 00:59:07 -0000
@@ -385,7 +385,7 @@ init_update_counter (MetaDisplay   *disp
                      MetaPropValue *value)
 {
   value->type = META_PROP_VALUE_SYNC_COUNTER;
-  value->atom = display->atom_metacity_update_counter;
+  value->atom = display->atom_net_wm_sync_request_counter;
 }
 
 static void
@@ -397,9 +397,9 @@ reload_update_counter (MetaWindow    *wi
 #ifdef HAVE_XSYNC
       XSyncCounter counter = value->v.xcounter;
 
-      window->update_counter = counter;
-      meta_verbose ("Window has _METACITY_UPDATE_COUNTER 0x%lx\n",
-                    window->update_counter);
+      window->sync_request_counter = counter;
+      meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx\n",
+                    window->sync_request_counter);
 #endif
     }
 }
@@ -924,7 +924,7 @@ meta_display_init_window_prop_hooks (Met
   hooks[i].reload_func = reload_net_startup_id;
   ++i;
 
-  hooks[i].property = display->atom_metacity_update_counter;
+  hooks[i].property = display->atom_net_wm_sync_request_counter;
   hooks[i].init_func = init_update_counter;
   hooks[i].reload_func = reload_update_counter;
   ++i;
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.325
diff -u -p -u -r1.325 window.c
--- src/window.c	28 Feb 2004 02:53:55 -0000	1.325
+++ src/window.c	26 Apr 2004 00:59:14 -0000
@@ -357,7 +357,10 @@ meta_window_new_with_attrs (MetaDisplay 
   window->workspaces = NULL;
 
 #ifdef HAVE_XSYNC
-  window->update_counter = None;
+  window->sync_request_counter = None;
+  window->sync_request_serial = 0;
+  window->sync_request_time.tv_sec = 0;
+  window->sync_request_time.tv_usec = 0;
 #endif
   
   window->screen = NULL;
@@ -446,6 +449,7 @@ meta_window_new_with_attrs (MetaDisplay 
   window->calc_placement = FALSE;
   window->shaken_loose = FALSE;
   window->have_focus_click_grab = FALSE;
+  window->disable_sync = FALSE;
   
   window->unmaps_pending = 0;
   
@@ -528,7 +532,7 @@ meta_window_new_with_attrs (MetaDisplay 
   initial_props[i++] = XA_WM_ICON_NAME;
   initial_props[i++] = display->atom_net_wm_desktop;
   initial_props[i++] = display->atom_net_startup_id;
-  initial_props[i++] = display->atom_metacity_update_counter;
+  initial_props[i++] = display->atom_net_wm_sync_request_counter;
   initial_props[i++] = XA_WM_NORMAL_HINTS;
   initial_props[i++] = display->atom_wm_protocols;
   initial_props[i++] = XA_WM_HINTS;
@@ -2297,6 +2301,36 @@ get_mouse_deltas_for_resize (MetaWindow 
     }
 }
 
+#ifdef HAVE_XSYNC
+static void
+send_sync_request (MetaWindow *window)
+{
+  XSyncValue value;
+  XClientMessageEvent ev;
+
+  window->sync_request_serial++;
+
+  XSyncIntToValue (&value, window->sync_request_serial);
+  
+  ev.type = ClientMessage;
+  ev.window = window->xwindow;
+  ev.message_type = window->display->atom_wm_protocols;
+  ev.format = 32;
+  ev.data.l[0] = window->display->atom_net_wm_sync_request;
+  ev.data.l[1] = meta_display_get_current_time (window->display);
+  ev.data.l[2] = XSyncValueLow32 (value);
+  ev.data.l[3] = XSyncValueHigh32 (value);
+
+  /* We don't need to trap errors here as we are already
+   * inside an error_trap_push()/pop() pair.
+   */
+  XSendEvent (window->display->xdisplay,
+	      window->xwindow, False, 0, (XEvent*) &ev);
+
+  g_get_current_time (&window->sync_request_time);
+}
+#endif
+
 static void
 meta_window_move_resize_internal (MetaWindow  *window,
                                   MetaMoveResizeFlags flags,
@@ -2627,10 +2661,20 @@ meta_window_move_resize_internal (MetaWi
       }
       
       meta_error_trap_push (window->display);
+
+      if (window->sync_request_counter != None &&
+	  window->display->grab_sync_request_alarm != None &&
+	  window->sync_request_time.tv_usec == 0 &&
+	  window->sync_request_time.tv_sec == 0)
+	{
+	  send_sync_request (window);
+	}
+
       XConfigureWindow (window->display->xdisplay,
                         window->xwindow,
                         mask,
                         &values);
+      
       meta_error_trap_pop (window->display, FALSE);
     }
 
@@ -4364,12 +4408,12 @@ process_property_notify (MetaWindow     
       meta_window_reload_property (window,
                                    window->display->atom_net_startup_id);
     }
-  else if (event->atom == window->display->atom_metacity_update_counter)
+  else if (event->atom == window->display->atom_net_wm_sync_request_counter)
     {
-      meta_verbose ("Property notify on %s for _METACITY_UPDATE_COUNTER\n", window->desc);
+      meta_verbose ("Property notify on %s for _NET_WM_SYNC_REQUEST_COUNTER\n", window->desc);
       
       meta_window_reload_property (window,
-                                   window->display->atom_metacity_update_counter);
+                                   window->display->atom_net_wm_sync_request_counter);
     }
 
   return TRUE;
@@ -5802,59 +5846,94 @@ meta_window_show_menu (MetaWindow *windo
   meta_ui_window_menu_popup (menu, root_x, root_y, button, timestamp);
 }
 
-static void
-clear_moveresize_time (MetaWindow *window)
+static double
+timeval_to_ms (const GTimeVal *timeval)
 {
-  /* Forces the next update to actually do something */
-  window->display->grab_last_moveresize_time.tv_sec = 0;
-  window->display->grab_last_moveresize_time.tv_usec = 0;
+  return (timeval->tv_sec * G_USEC_PER_SEC + timeval->tv_usec) / 1000.0;
+}
+
+static double
+time_diff (const GTimeVal *first,
+	   const GTimeVal *second)
+{
+  double first_ms = timeval_to_ms (first);
+  double second_ms = timeval_to_ms (second);
+
+  return first_ms - second_ms;
 }
 
 static gboolean
-check_moveresize_frequency (MetaWindow *window)
+check_moveresize_frequency (MetaWindow *window, 
+			    gdouble    *remaining)
 {
   GTimeVal current_time;
-  double elapsed;
-  double max_resizes_per_second;
   
   g_get_current_time (&current_time);
 
-  /* use milliseconds, 1000 milliseconds/second */
-  elapsed =
-    ((((double)current_time.tv_sec - window->display->grab_last_moveresize_time.tv_sec) * G_USEC_PER_SEC +
-      (current_time.tv_usec - window->display->grab_last_moveresize_time.tv_usec))) / 1000.0;
-
 #ifdef HAVE_XSYNC
-  if (window->display->grab_update_alarm != None)
-    max_resizes_per_second = 1.0;   /* this is max resizes without
-                                     * getting any alarms; we resize
-                                     * immediately if we get one.
-                                     * i.e. this is a timeout for the
-                                     * client getting stuck.
-                                     */
+  if (!window->disable_sync &&
+      window->display->grab_sync_request_alarm != None)
+    {
+      if (window->sync_request_time.tv_sec != 0 ||
+	  window->sync_request_time.tv_usec != 0)
+	{
+	  double elapsed =
+	    time_diff (&current_time, &window->sync_request_time);
+
+	  if (elapsed < 1000.0)
+	    {
+	      /* We want to be sure that the timeout happens at
+	       * a time where elapsed will definitely be
+	       * greater than 1000, so we can disable sync
+	       */
+	      if (remaining)
+		*remaining = 1000.0 - elapsed + 100;
+	      
+	      return FALSE;
+	    }
+	  else
+	    {
+	      /* We have now waited for more than a second for the
+	       * application to respond to the sync request
+	       */
+	      window->disable_sync = TRUE;
+	      return TRUE;
+	    }
+	}
+      else
+	{
+	  /* No outstanding sync requests. Go ahead and resize
+	   */
+	  return TRUE;
+	}
+    }
   else
 #endif /* HAVE_XSYNC */
-    max_resizes_per_second = 20.0;
-  
-#define EPSILON (1e-6)  
-  if (elapsed >= 0.0 && elapsed < (1000.0 / max_resizes_per_second))
     {
+      const double max_resizes_per_second = 25.0;
+      const double ms_between_resizes = 1000.0 / max_resizes_per_second;
+      double elapsed;
+
+      elapsed = time_diff (&current_time, &window->display->grab_last_moveresize_time);
+
+      if (elapsed >= 0.0 && elapsed < ms_between_resizes)
+	{
+	  meta_topic (META_DEBUG_RESIZING,
+		      "Delaying move/resize as only %g of %g ms elapsed\n",
+		      elapsed, ms_between_resizes);
+	  
+	  if (remaining)
+	    *remaining = (ms_between_resizes - elapsed);
+
+	  return FALSE;
+	}
+      
       meta_topic (META_DEBUG_RESIZING,
-                  "Delaying move/resize as only %g of %g seconds elapsed\n",
-                  elapsed / 1000.0, 1.0 / max_resizes_per_second);
-      return FALSE;
+		  " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)\n",
+		  elapsed / 1000.0, 1.0 / max_resizes_per_second);
+      
+      return TRUE;
     }
-  else if (elapsed < (0.0 - EPSILON)) /* handle clock getting set backward */
-    clear_moveresize_time (window);
-  
-  /* store latest time */
-  window->display->grab_last_moveresize_time = current_time;
-  
-  meta_topic (META_DEBUG_RESIZING,
-              " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)\n",
-              elapsed / 1000.0, 1.0 / max_resizes_per_second);
-  
-  return TRUE;
 }
 
 static void
@@ -6005,15 +6084,34 @@ update_move (MetaWindow  *window,
     }
 }
 
+static void update_resize (MetaWindow *window,
+			   int         x,
+			   int         y,
+			   gboolean    force);
+
+static gboolean
+update_resize_timeout (gpointer data)
+{
+  MetaWindow *window = data;
+
+  update_resize (window, 
+		 window->display->grab_latest_motion_x,
+		 window->display->grab_latest_motion_y,
+		 TRUE);
+  return FALSE;
+}
+
 static void
 update_resize (MetaWindow *window,
-               int x, int y)
+               int x, int y,
+	       gboolean force)
 {
   int dx, dy;
   int new_w, new_h;
   int gravity;
   MetaRectangle old;
   int new_x, new_y;
+  double remaining;
   
   window->display->grab_latest_motion_x = x;
   window->display->grab_latest_motion_y = y;
@@ -6077,8 +6175,28 @@ update_resize (MetaWindow *window,
       break;
     }
 
-  if (!check_moveresize_frequency (window))
-    return;
+  if (!check_moveresize_frequency (window, &remaining) && !force)
+    {
+      /* we are ignoring an event here, so we schedule a
+       * compensation event when we would otherwise not ignore
+       * an event. Otherwise we can become stuck if the user never
+       * generates another event.
+       */
+      if (!window->display->grab_resize_timeout_id)
+	{
+	  window->display->grab_resize_timeout_id = 
+	    g_timeout_add ((int)remaining, update_resize_timeout, window);
+	}
+
+      return;
+    }
+
+  /* Remove any scheduled compensation events */
+  if (window->display->grab_resize_timeout_id)
+    {
+      g_source_remove (window->display->grab_resize_timeout_id);
+      window->display->grab_resize_timeout_id = 0;
+    }
   
   old = window->rect;
 
@@ -6118,14 +6236,12 @@ update_resize (MetaWindow *window,
       meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity);
     }
 
-  /* If we don't actually resize the window, we clear the timestamp,
-   * so we'll quickly try again.  Otherwise you get "stuck" because
-   * the window doesn't increment its _METACITY_UPDATE_COUNTER when
-   * nothing happens.
-   */
-  if (window->rect.width == old.width &&
-      window->rect.height == old.height)
-    clear_moveresize_time (window);
+  /* Store the latest resize time, if we actually resized. */
+  if (window->rect.width != old.width &&
+      window->rect.height != old.height)
+    {
+      g_get_current_time (&window->display->grab_last_moveresize_time);
+    }
 }
 
 typedef struct
@@ -6216,6 +6332,14 @@ meta_window_handle_mouse_grab_op_event (
                   "Alarm event received last motion x = %d y = %d\n",
                   window->display->grab_latest_motion_x,
                   window->display->grab_latest_motion_y);
+
+      /* If sync was previously disabled, turn it back on and hope
+       * the application has come to its senses (maybe it was just
+       * busy with a pagefault or a long computation).
+       */
+      window->disable_sync = FALSE;
+      window->sync_request_time.tv_sec = 0;
+      window->sync_request_time.tv_usec = 0;
       
       /* This means we are ready for another configure. */
       switch (window->display->grab_op)
@@ -6236,12 +6360,11 @@ meta_window_handle_mouse_grab_op_event (
         case META_GRAB_OP_KEYBOARD_RESIZING_NE:
         case META_GRAB_OP_KEYBOARD_RESIZING_SW:
         case META_GRAB_OP_KEYBOARD_RESIZING_NW:
-          clear_moveresize_time (window); /* force update to do something */
-
           /* no pointer round trip here, to keep in sync */
           update_resize (window,
                          window->display->grab_latest_motion_x,
-                         window->display->grab_latest_motion_y);
+                         window->display->grab_latest_motion_y,
+			 TRUE);
           break;
           
         default:
@@ -6255,16 +6378,17 @@ meta_window_handle_mouse_grab_op_event (
     case ButtonRelease:      
       if (meta_grab_op_is_moving (window->display->grab_op))
         {
-          clear_moveresize_time (window);
           if (event->xbutton.root == window->screen->xroot)
             update_move (window, event->xbutton.state,
                          event->xbutton.x_root, event->xbutton.y_root);
         }
       else if (meta_grab_op_is_resizing (window->display->grab_op))
         {
-          clear_moveresize_time (window);
           if (event->xbutton.root == window->screen->xroot)
-            update_resize (window, event->xbutton.x_root, event->xbutton.y_root);
+            update_resize (window,
+			   event->xbutton.x_root,
+			   event->xbutton.y_root,
+			   TRUE);
         }
 
       meta_display_end_grab_op (window->display, event->xbutton.time);
@@ -6291,7 +6415,8 @@ meta_window_handle_mouse_grab_op_event (
                                                 event))
                 update_resize (window,
                                event->xmotion.x_root,
-                               event->xmotion.y_root);
+                               event->xmotion.y_root,
+			       FALSE);
             }
         }
       break;
@@ -6311,7 +6436,8 @@ meta_window_handle_mouse_grab_op_event (
           if (event->xcrossing.root == window->screen->xroot)
             update_resize (window,
                            event->xcrossing.x_root,
-                           event->xcrossing.y_root);
+                           event->xcrossing.y_root,
+			   FALSE);
         }
       break;
     default:
Index: src/window.h
===================================================================
RCS file: /cvs/gnome/metacity/src/window.h,v
retrieving revision 1.101
diff -u -p -u -r1.101 window.h
--- src/window.h	28 Feb 2004 23:58:40 -0000	1.101
+++ src/window.h	26 Apr 2004 00:59:14 -0000
@@ -243,10 +243,15 @@ struct _MetaWindow
 
   /* if TRUE we have a grab on the focus click buttons */
   guint have_focus_click_grab : 1;
-  
+
+  /* if TRUE, application is buggy and SYNC resizing is turned off */
+  guint disable_sync : 1;
+
 #ifdef HAVE_XSYNC
   /* XSync update counter */
-  XSyncCounter update_counter;
+  XSyncCounter sync_request_counter;
+  guint sync_request_serial;
+  GTimeVal sync_request_time;
 #endif
   
   /* Number of UnmapNotify that are caused by us, if
Index: src/xprops.c
===================================================================
RCS file: /cvs/gnome/metacity/src/xprops.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 xprops.c
--- src/xprops.c	29 Sep 2003 18:16:45 -0000	1.20
+++ src/xprops.c	26 Apr 2004 00:59:16 -0000
@@ -544,7 +544,7 @@ counter_from_results (GetPropertyResults
                       XSyncCounter       *counter_p)
 {
   if (!validate_or_free_results (results, 32,
-                                 results->display->atom_sync_counter,
+                                 XA_CARDINAL,
                                  TRUE))
     return FALSE;  
 
@@ -986,7 +986,7 @@ meta_prop_get_values (MetaDisplay   *dis
               values[i].required_type = XA_WM_SIZE_HINTS;
               break;
             case META_PROP_VALUE_SYNC_COUNTER:
-              values[i].required_type = display->atom_sync_counter;
+	      values[i].required_type = XA_CARDINAL;
               break;
             }
         }
Index: src/xprops.h
===================================================================
RCS file: /cvs/gnome/metacity/src/xprops.h,v
retrieving revision 1.9
diff -u -p -u -r1.9 xprops.h
--- src/xprops.h	16 Dec 2002 22:01:15 -0000	1.9
+++ src/xprops.h	26 Apr 2004 00:59:16 -0000
@@ -145,7 +145,7 @@ typedef enum
   META_PROP_VALUE_WM_HINTS,
   META_PROP_VALUE_CLASS_HINT,
   META_PROP_VALUE_SIZE_HINTS,
-  META_PROP_VALUE_SYNC_COUNTER
+  META_PROP_VALUE_SYNC_COUNTER /* comes back as CARDINAL */
 } MetaPropValueType;
 
 /* used to request/return/store property values */


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