]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkdisplay-x11.c
GdkFrameTimings: strip down to a minimal public API
[~andy/gtk] / gdk / x11 / gdkdisplay-x11.c
index 5af36d278feaf7f37a7db5645c21bfb94f97250b..90a2eca921569ba7305c8d6879a8b2f552c15d6e 100644 (file)
@@ -26,6 +26,7 @@
 #include "gdkdisplay.h"
 #include "gdkeventsource.h"
 #include "gdkeventtranslator.h"
+#include "gdkframeclockprivate.h"
 #include "gdkinternals.h"
 #include "gdkscreen.h"
 #include "gdkinternals.h"
@@ -681,6 +682,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
                                              GDK_WINDOW_STATE_ICONIFIED);
             }
 
+          if (window_impl->toplevel &&
+              window_impl->toplevel->frame_pending)
+            {
+              window_impl->toplevel->frame_pending = FALSE;
+              gdk_frame_clock_thaw (gdk_window_get_frame_clock (event->any.window));
+            }
+
+         if (toplevel)
+            gdk_window_freeze_toplevel_updates_libgtk_only (window);
+
           _gdk_x11_window_grab_check_unmap (window, xevent->xany.serial);
         }
 
@@ -701,6 +712,9 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
            gdk_synthesize_window_state (window,
                                         GDK_WINDOW_STATE_ICONIFIED,
                                         0);
+
+         if (toplevel)
+           gdk_window_thaw_toplevel_updates_libgtk_only (window);
        }
 
       break;
@@ -750,6 +764,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
       if (!is_substructure && toplevel && display_x11->use_sync && toplevel->pending_counter_value != 0)
        {
          toplevel->configure_counter_value = toplevel->pending_counter_value;
+         toplevel->configure_counter_value_is_extended = toplevel->pending_counter_value_is_extended;
          toplevel->pending_counter_value = 0;
        }
 #endif
@@ -1043,6 +1058,25 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
   return return_val;
 }
 
+static GdkFrameTimings *
+find_frame_timings (GdkFrameClock *clock,
+                    guint64        serial)
+{
+  gint64 start_frame, end_frame, i;
+
+  start_frame = gdk_frame_clock_get_start (clock);
+  end_frame = gdk_frame_clock_get_frame_counter (clock);
+  for (i = end_frame; i >= start_frame; i--)
+    {
+      GdkFrameTimings *timings = gdk_frame_clock_get_timings (clock, i);
+
+      if (timings->cookie == serial)
+        return timings;
+    }
+
+  return NULL;
+}
+
 GdkFilterReturn
 _gdk_wm_protocols_filter (GdkXEvent *xev,
                          GdkEvent  *event,
@@ -1061,6 +1095,82 @@ _gdk_wm_protocols_filter (GdkXEvent *xev,
 
   display = GDK_WINDOW_DISPLAY (win);
 
+  /* This isn't actually WM_PROTOCOLS because that wouldn't leave enough space
+   * in the message for everything that gets stuffed in */
+  if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_DRAWN"))
+    {
+      GdkWindowImplX11 *window_impl;
+      window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl);
+      if (window_impl->toplevel)
+        {
+          guint32 d0 = xevent->xclient.data.l[0];
+          guint32 d1 = xevent->xclient.data.l[1];
+          guint32 d2 = xevent->xclient.data.l[2];
+          guint32 d3 = xevent->xclient.data.l[3];
+
+          guint64 serial = ((guint64)d1 << 32) | d0;
+          gint64 frame_drawn_time = ((guint64)d3 << 32) | d2;
+          gint64 refresh_interval, presentation_time;
+
+          GdkFrameClock *clock = gdk_window_get_frame_clock (event->any.window);
+          GdkFrameTimings *timings = find_frame_timings (clock, serial);
+
+          if (timings)
+            timings->drawn_time = frame_drawn_time;
+
+          if (window_impl->toplevel->frame_pending)
+            {
+              window_impl->toplevel->frame_pending = FALSE;
+              gdk_frame_clock_thaw (clock);
+            }
+
+          gdk_frame_clock_get_refresh_info (clock,
+                                            frame_drawn_time,
+                                            &refresh_interval,
+                                            &presentation_time);
+          if (presentation_time != 0)
+            window_impl->toplevel->throttled_presentation_time = presentation_time + refresh_interval;
+        }
+
+      return GDK_FILTER_REMOVE;
+    }
+
+  if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_TIMINGS"))
+    {
+      GdkWindowImplX11 *window_impl;
+      window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl);
+      if (window_impl->toplevel)
+        {
+          guint32 d0 = xevent->xclient.data.l[0];
+          guint32 d1 = xevent->xclient.data.l[1];
+          guint32 d2 = xevent->xclient.data.l[2];
+          guint32 d3 = xevent->xclient.data.l[3];
+
+          guint64 serial = ((guint64)d1 << 32) | d0;
+
+          GdkFrameClock *clock = gdk_window_get_frame_clock (event->any.window);
+          GdkFrameTimings *timings = find_frame_timings (clock, serial);
+
+          if (timings)
+            {
+              gint32 presentation_time_offset = (gint32)d2;
+              gint32 refresh_interval = d3;
+
+              if (timings->drawn_time && presentation_time_offset)
+                timings->presentation_time = timings->drawn_time + presentation_time_offset;
+
+              if (refresh_interval)
+                timings->refresh_interval = refresh_interval;
+
+              timings->complete = TRUE;
+#ifdef G_ENABLE_DEBUG
+              if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
+                _gdk_frame_clock_debug_print_timings (clock, timings);
+#endif /* G_ENABLE_DEBUG */
+            }
+        }
+    }
+
   if (xevent->xclient.message_type != gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS"))
     return GDK_FILTER_CONTINUE;
 
@@ -1127,6 +1237,7 @@ _gdk_wm_protocols_filter (GdkXEvent *xev,
        {
 #ifdef HAVE_XSYNC
          toplevel->pending_counter_value = xevent->xclient.data.l[2] + ((gint64)xevent->xclient.data.l[3] << 32);
+         toplevel->pending_counter_value_is_extended = xevent->xclient.data.l[4] != 0;
 #endif
        }
       return GDK_FILTER_REMOVE;