[mutter/wip/frame-synchronization: 60/69] Add support for an extended style of _NET_WM_SYNC_REQUEST_COUNTER



commit 41fa3bfe917be0db195649f369a02d30106e1b6f
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Wed Jun 8 13:58:54 2011 -0400

    Add support for an extended style of _NET_WM_SYNC_REQUEST_COUNTER
    
    If an application provides two values in _NET_WM_SYNC_REQUEST_COUNTER,
    use that as a signal that the applications wants an extended behavior
    where it can update the counter as well as the window manager. If the
    application updates the counter to an odd value, updates of the
    window are frozen until the counter is updated again to an even value.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=685463

 src/core/display-private.h |    4 ++
 src/core/display.c         |   23 ++++++-------
 src/core/window-private.h  |    8 ++++-
 src/core/window-props.c    |   28 +++++++++++++---
 src/core/window.c          |   77 ++++++++++++++++++++++++++++++++++---------
 5 files changed, 106 insertions(+), 34 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 797cb95..2f6e236 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -221,6 +221,9 @@ struct _MetaDisplay
   int         xkb_base_event_type;
   guint32     last_bell_time;
 #endif
+#ifdef HAVE_XSYNC
+  gint64      grab_sync_counter_wait_serial;
+#endif
   int	      grab_resize_timeout_id;
 
   /* Keybindings stuff */
@@ -435,6 +438,7 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
 
 gboolean meta_grab_op_is_moving   (MetaGrabOp op);
 gboolean meta_grab_op_is_resizing (MetaGrabOp op);
+gboolean meta_grab_op_is_mouse    (MetaGrabOp op);
 
 void meta_display_devirtualize_modifiers (MetaDisplay        *display,
                                           MetaVirtualModifier modifiers,
diff --git a/src/core/display.c b/src/core/display.c
index 0747049..bb61d72 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1272,8 +1272,8 @@ grab_op_is_mouse_only (MetaGrabOp op)
     }
 }
 
-static gboolean
-grab_op_is_mouse (MetaGrabOp op)
+gboolean
+meta_grab_op_is_mouse (MetaGrabOp op)
 {
   switch (op)
     {
@@ -1878,12 +1878,11 @@ event_callback (XEvent   *event,
 
       if (alarm_window != NULL)
         {
-          filter_out_event = TRUE; /* our own alarm, GTK doesn't want to see this */
+          XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value;
 
-          if (display->grab_op != META_GRAB_OP_NONE &&
-              display->grab_window == alarm_window &&
-              grab_op_is_mouse (display->grab_op))
-            meta_window_handle_mouse_grab_op_event (display->grab_window, event);
+          filter_out_event = TRUE; /* our own alarm, GTK doesn't want to see this */
+          meta_window_update_sync_request_counter (alarm_window,
+                                                   XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32));
         }
     }
 #endif /* HAVE_XSYNC */
@@ -1983,7 +1982,7 @@ event_callback (XEvent   *event,
         break;
 
       if ((window &&
-           grab_op_is_mouse (display->grab_op) &&
+           meta_grab_op_is_mouse (display->grab_op) &&
            display->grab_button != (int) event->xbutton.button &&
            display->grab_window == window) ||
           grab_op_is_keyboard (display->grab_op))
@@ -2178,7 +2177,7 @@ event_callback (XEvent   *event,
       display->overlay_key_only_pressed = FALSE;
 
       if (display->grab_window == window &&
-          grab_op_is_mouse (display->grab_op))
+          meta_grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (window, event);
       break;
     case MotionNotify:
@@ -2186,7 +2185,7 @@ event_callback (XEvent   *event,
         break;
 
       if (display->grab_window == window &&
-          grab_op_is_mouse (display->grab_op))
+          meta_grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (window, event);
       break;
     case EnterNotify:
@@ -2194,7 +2193,7 @@ event_callback (XEvent   *event,
         break;
 
       if (display->grab_window == window &&
-          grab_op_is_mouse (display->grab_op))
+          meta_grab_op_is_mouse (display->grab_op))
         {
           meta_window_handle_mouse_grab_op_event (window, event);
           break;
@@ -2263,7 +2262,7 @@ event_callback (XEvent   *event,
         break;
 
       if (display->grab_window == window &&
-          grab_op_is_mouse (display->grab_op))
+          meta_grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (window, event);
       else if (window != NULL)
         {
diff --git a/src/core/window-private.h b/src/core/window-private.h
index fc4c986..e1648fc 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -339,13 +339,17 @@ struct _MetaWindow
   /* if TRUE, we are freezing updates during a resize */
   guint updates_frozen_for_resize : 1;
 
+  /* if TRUE, the we have the new form of sync request counter which
+   * also handles application frames */
+  guint extended_sync_request_counter : 1;
+
   /* Note: can be NULL */
   GSList *struts;
 
 #ifdef HAVE_XSYNC
   /* XSync update counter */
   XSyncCounter sync_request_counter;
-  guint sync_request_serial;
+  guint64 sync_request_serial;
   GTimeVal sync_request_time;
   /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
   XSyncAlarm sync_request_alarm;
@@ -623,6 +627,8 @@ void meta_window_free_delete_dialog (MetaWindow *window);
 
 void meta_window_create_sync_request_alarm  (MetaWindow *window);
 void meta_window_destroy_sync_request_alarm (MetaWindow *window);
+void meta_window_update_sync_request_counter (MetaWindow *window,
+                                              gint64      new_counter_value);
 
 void meta_window_update_keyboard_resize (MetaWindow *window,
                                          gboolean    update_cursor);
diff --git a/src/core/window-props.c b/src/core/window-props.c
index e3473e8..eab2d6f 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -883,13 +883,31 @@ reload_update_counter (MetaWindow    *window,
   if (value->type != META_PROP_VALUE_INVALID)
     {
       meta_window_destroy_sync_request_alarm (window);
+      window->sync_request_counter = None;
 
 #ifdef HAVE_XSYNC
-      XSyncCounter counter = value->v.xcounter;
+      if (value->v.xcounter_list.n_counters == 0)
+        {
+          meta_warning ("_NET_WM_SYNC_REQUEST_COUNTER is empty\n");
+          return;
+        }
+
+      if (value->v.xcounter_list.n_counters == 1)
+        {
+          window->sync_request_counter = value->v.xcounter_list.counters[0];
+          window->extended_sync_request_counter = FALSE;
+        }
+      else
+        {
+          window->sync_request_counter = value->v.xcounter_list.counters[1];
+          window->extended_sync_request_counter = TRUE;
+        }
+      meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx (extended=%s)\n",
+                    window->sync_request_counter,
+                    window->extended_sync_request_counter ? "true" : "false");
 
-      window->sync_request_counter = counter;
-      meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx\n",
-                    window->sync_request_counter);
+      if (window->extended_sync_request_counter)
+        meta_window_create_sync_request_alarm (window);
 #endif
     }
 }
@@ -1658,7 +1676,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
     { XA_WM_ICON_NAME,                 META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name, TRUE,  FALSE },
     { display->atom__NET_WM_DESKTOP,   META_PROP_VALUE_CARDINAL, reload_net_wm_desktop,    TRUE,  FALSE },
     { display->atom__NET_STARTUP_ID,   META_PROP_VALUE_UTF8,     reload_net_startup_id,    TRUE,  FALSE },
-    { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER, reload_update_counter, TRUE, FALSE },
+    { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER_LIST, reload_update_counter, TRUE, TRUE },
     { XA_WM_NORMAL_HINTS,              META_PROP_VALUE_SIZE_HINTS, reload_normal_hints,    TRUE,  FALSE },
     { display->atom_WM_PROTOCOLS,      META_PROP_VALUE_ATOM_LIST, reload_wm_protocols,     TRUE,  FALSE },
     { XA_WM_HINTS,                     META_PROP_VALUE_WM_HINTS,  reload_wm_hints,         TRUE,  FALSE },
diff --git a/src/core/window.c b/src/core/window.c
index a0a09c4..a131d9f 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4405,17 +4405,38 @@ meta_window_create_sync_request_alarm (MetaWindow *window)
 
   meta_error_trap_push_with_return (window->display);
 
-  /* Set the counter to 0, so we know that the application's
-   * responses to the client messages will always trigger
-   * a PositiveTransition
+  /* In the old style, we're responsible for setting the initial
+   * value of the counter. In the new (extended style), the counter
+   * value is initialized by the client before mapping the window
    */
-  XSyncIntToValue (&init, 0);
-  XSyncSetCounter (window->display->xdisplay,
-                   window->sync_request_counter, init);
-  window->sync_request_serial = 0;
+  if (window->extended_sync_request_counter)
+    {
+      if (!XSyncQueryCounter(window->display->xdisplay,
+                             window->sync_request_counter,
+                             &init))
+        {
+          meta_error_trap_pop_with_return (window->display);
+          window->sync_request_counter = None;
+          return;
+        }
+
+      window->sync_request_serial =
+        XSyncValueLow32 (init) + ((gint64)XSyncValueHigh32 (init) << 32);
+
+      /* if the value is odd, the window starts off with updates frozen */
+      meta_compositor_set_updates_frozen (window->display->compositor, window,
+                                          meta_window_updates_are_frozen (window));
+    }
+  else
+    {
+      XSyncIntToValue (&init, 0);
+      XSyncSetCounter (window->display->xdisplay,
+                       window->sync_request_counter, init);
+      window->sync_request_serial = 0;
+    }
 
   values.trigger.counter = window->sync_request_counter;
-  values.trigger.test_type = XSyncPositiveTransition;
+  values.trigger.test_type = XSyncPositiveComparison;
 
   /* Initialize to one greater than the current value */
   values.trigger.value_type = XSyncRelative;
@@ -4466,12 +4487,19 @@ meta_window_destroy_sync_request_alarm (MetaWindow *window)
 static void
 send_sync_request (MetaWindow *window)
 {
-  XSyncValue value;
   XClientMessageEvent ev;
+  gint64 wait_serial;
 
-  window->sync_request_serial++;
+  /* For the old style of _NET_WM_SYNC_REQUEST_COUNTER, we just have to
+   * increase the value, but for the new "extended" style we need to
+   * pick an even (unfrozen) value sufficiently ahead of the last serial
+   * that we received from the client; the same code still works
+   * for the old style */
+  wait_serial = window->sync_request_serial + 100;
+  if (wait_serial % 2 == 1)
+    wait_serial++;
 
-  XSyncIntToValue (&value, window->sync_request_serial);
+  window->display->grab_sync_counter_wait_serial = wait_serial;
 
   ev.type = ClientMessage;
   ev.window = window->xwindow;
@@ -4484,8 +4512,8 @@ send_sync_request (MetaWindow *window)
    * want to use _roundtrip, though?
    */
   ev.data.l[1] = meta_display_get_current_time (window->display);
-  ev.data.l[2] = XSyncValueLow32 (value);
-  ev.data.l[3] = XSyncValueHigh32 (value);
+  ev.data.l[2] = wait_serial & G_GUINT64_CONSTANT(0xffffffff);
+  ev.data.l[3] = wait_serial >> 32;
 
   /* We don't need to trap errors here as we are already
    * inside an error_trap_push()/pop() pair.
@@ -4512,6 +4540,11 @@ send_sync_request (MetaWindow *window)
 gboolean
 meta_window_updates_are_frozen (MetaWindow *window)
 {
+#ifdef HAVE_XSYNC
+  if (window->sync_request_serial % 2 == 1)
+    return TRUE;
+#endif
+
   return window->updates_frozen_for_resize;
 }
 
@@ -9329,11 +9362,18 @@ update_tile_mode (MetaWindow *window)
 }
 
 void
-meta_window_handle_mouse_grab_op_event (MetaWindow *window,
-                                        XEvent     *event)
+meta_window_update_sync_request_counter (MetaWindow *window,
+                                         gint64      new_counter_value)
 {
 #ifdef HAVE_XSYNC
-  if (event->type == (window->display->xsync_event_base + XSyncAlarmNotify))
+  window->sync_request_serial = new_counter_value;
+  meta_compositor_set_updates_frozen (window->display->compositor, window,
+                                      meta_window_updates_are_frozen (window));
+
+  if (window->display->grab_op != META_GRAB_OP_NONE &&
+      window == window->display->grab_window &&
+      meta_grab_op_is_mouse (window->display->grab_op) &&
+      new_counter_value >= window->display->grab_sync_counter_wait_serial)
     {
       meta_topic (META_DEBUG_RESIZING,
                   "Alarm event received last motion x = %d y = %d\n",
@@ -9380,7 +9420,12 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
         }
     }
 #endif /* HAVE_XSYNC */
+}
 
+void
+meta_window_handle_mouse_grab_op_event (MetaWindow *window,
+                                        XEvent     *event)
+{
   switch (event->type)
     {
     case ButtonRelease:



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