Bug 1026803 part 8 - Add ability for CurrentX11TimeGetter to perform an asynchronous request of the current time; r=karlt
authorBrian Birtles <birtles@gmail.com>
Wed, 12 Aug 2015 10:35:38 +0900
changeset 258999 3e9a0b5dad97dedfb8f60a635c2d79916942071d
parent 258998 f11af0ae18111d530cc620d3bb3f95f57a8b4f68
child 259000 e4be1361d6ca82367c0b03dd289c4b74070ebafd
push id29268
push userryanvm@gmail.com
push dateTue, 25 Aug 2015 00:37:23 +0000
treeherdermozilla-central@08015770c9d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1026803
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1026803 part 8 - Add ability for CurrentX11TimeGetter to perform an asynchronous request of the current time; r=karlt
widget/gtk/mozgtk/mozgtk.c
widget/gtk/nsWindow.cpp
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -119,16 +119,17 @@ STUB(gdk_window_show)
 STUB(gdk_window_show_unraised)
 STUB(gdk_x11_atom_to_xatom)
 STUB(gdk_x11_display_get_user_time)
 STUB(gdk_x11_display_get_xdisplay)
 STUB(gdk_x11_get_default_root_xwindow)
 STUB(gdk_x11_get_default_xdisplay)
 STUB(gdk_x11_get_server_time)
 STUB(gdk_x11_get_xatom_by_name)
+STUB(gdk_x11_get_xatom_by_name_for_display)
 STUB(gdk_x11_lookup_xdisplay)
 STUB(gdk_x11_screen_get_xscreen)
 STUB(gdk_x11_visual_get_xvisual)
 STUB(gdk_x11_window_foreign_new_for_display)
 STUB(gdk_x11_window_lookup_for_display)
 STUB(gdk_x11_window_set_user_time)
 STUB(gdk_x11_xatom_to_atom)
 STUB(gtk_accel_label_new)
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -141,17 +141,18 @@ using mozilla::gl::GLContext;
 const gint kEvents = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
                      GDK_VISIBILITY_NOTIFY_MASK |
                      GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
                      GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
 #if GTK_CHECK_VERSION(3,4,0)
                      GDK_SMOOTH_SCROLL_MASK |
 #endif
                      GDK_SCROLL_MASK |
-                     GDK_POINTER_MOTION_MASK;
+                     GDK_POINTER_MOTION_MASK |
+                     GDK_PROPERTY_CHANGE_MASK;
 
 /* utility functions */
 static bool       is_mouse_in_window(GdkWindow* aWindow,
                                      gdouble aMouseX, gdouble aMouseY);
 static nsWindow  *get_window_for_gtk_widget(GtkWidget *widget);
 static nsWindow  *get_window_for_gdk_window(GdkWindow *window);
 static GtkWidget *get_gtk_widget_for_gdk_window(GdkWindow *window);
 static GdkCursor *get_gtk_cursor(nsCursor aCursor);
@@ -195,16 +196,18 @@ static gboolean button_release_event_cb 
 static gboolean focus_in_event_cb         (GtkWidget *widget,
                                            GdkEventFocus *event);
 static gboolean focus_out_event_cb        (GtkWidget *widget,
                                            GdkEventFocus *event);
 static gboolean key_press_event_cb        (GtkWidget *widget,
                                            GdkEventKey *event);
 static gboolean key_release_event_cb      (GtkWidget *widget,
                                            GdkEventKey *event);
+static gboolean property_notify_event_cb  (GtkWidget *widget,
+                                           GdkEventProperty *event);
 static gboolean scroll_event_cb           (GtkWidget *widget,
                                            GdkEventScroll *event);
 static gboolean visibility_notify_event_cb(GtkWidget *widget,
                                            GdkEventVisibility *event);
 static void     hierarchy_changed_cb      (GtkWidget *widget,
                                            GtkWidget *previous_toplevel);
 static gboolean window_state_event_cb     (GtkWidget *widget,
                                            GdkEventWindowState *event);
@@ -268,32 +271,70 @@ TimeConverter() {
     return sTimeConverterSingleton;
 }
 
 namespace mozilla {
 
 class CurrentX11TimeGetter
 {
 public:
-    CurrentX11TimeGetter(GdkWindow* aWindow) : mWindow(aWindow) { }
+    CurrentX11TimeGetter(GdkWindow* aWindow)
+        : mWindow(aWindow)
+        , mAsyncUpdateStart()
+    {
+    }
 
     guint32 GetCurrentTime() const
     {
         return gdk_x11_get_server_time(mWindow);
     }
 
     void GetTimeAsyncForPossibleBackwardsSkew(const TimeStamp& aNow)
     {
-        // FIXME: Get time async
+        // Check for in-flight request
+        if (!mAsyncUpdateStart.IsNull()) {
+            return;
+        }
+        mAsyncUpdateStart = aNow;
+
+        Display* xDisplay = GDK_WINDOW_XDISPLAY(mWindow);
+        Window xWindow = GDK_WINDOW_XID(mWindow);
+        unsigned char c = 'a';
+        Atom timeStampPropAtom = TimeStampPropAtom();
+        XChangeProperty(xDisplay, xWindow, timeStampPropAtom,
+                        timeStampPropAtom, 8, PropModeReplace, &c, 1);
+        XFlush(xDisplay);
+    }
+
+    gboolean PropertyNotifyHandler(GtkWidget* aWidget,
+                                   GdkEventProperty* aEvent)
+    {
+        if (aEvent->atom !=
+            gdk_x11_xatom_to_atom(TimeStampPropAtom())) {
+            return FALSE;
+        }
+
+        guint32 eventTime = aEvent->time;
+        TimeStamp lowerBound = mAsyncUpdateStart;
+
+        TimeConverter().CompensateForBackwardsSkew(eventTime, lowerBound);
+        mAsyncUpdateStart = TimeStamp();
+        return TRUE;
     }
 
 private:
+    static Atom TimeStampPropAtom() {
+        return gdk_x11_get_xatom_by_name_for_display(
+            gdk_display_get_default(), "GDK_TIMESTAMP_PROP");
+    }
+
     // This is safe because this class is stored as a member of mWindow and
     // won't outlive it.
     GdkWindow* mWindow;
+    TimeStamp  mAsyncUpdateStart;
 };
 
 } // namespace mozilla
 
 static NS_DEFINE_IID(kCDragServiceCID,  NS_DRAGSERVICE_CID);
 
 // The window from which the focus manager asks us to dispatch key events.
 static nsWindow         *gFocusWindow          = nullptr;
@@ -3761,16 +3802,18 @@ nsWindow::Create(nsIWidget        *aPare
         g_signal_connect(eventWidget, "leave-notify-event",
                          G_CALLBACK(leave_notify_event_cb), nullptr);
         g_signal_connect(eventWidget, "motion-notify-event",
                          G_CALLBACK(motion_notify_event_cb), nullptr);
         g_signal_connect(eventWidget, "button-press-event",
                          G_CALLBACK(button_press_event_cb), nullptr);
         g_signal_connect(eventWidget, "button-release-event",
                          G_CALLBACK(button_release_event_cb), nullptr);
+        g_signal_connect(eventWidget, "property-notify-event",
+                         G_CALLBACK(property_notify_event_cb), nullptr);
         g_signal_connect(eventWidget, "scroll-event",
                          G_CALLBACK(scroll_event_cb), nullptr);
     }
 
     LOG(("nsWindow [%p]\n", (void *)this));
     if (mShell) {
         LOG(("\tmShell %p mContainer %p mGdkWindow %p 0x%lx\n",
              mShell, mContainer, mGdkWindow,
@@ -5685,16 +5728,27 @@ key_release_event_cb(GtkWidget *widget, 
         return FALSE;
 
     nsRefPtr<nsWindow> focusWindow = gFocusWindow ? gFocusWindow : window;
 
     return focusWindow->OnKeyReleaseEvent(event);
 }
 
 static gboolean
+property_notify_event_cb(GtkWidget* aWidget, GdkEventProperty* aEvent)
+{
+    nsRefPtr<nsWindow> window = get_window_for_gdk_window(aEvent->window);
+    if (!window)
+        return FALSE;
+
+    CurrentX11TimeGetter* currentTimeGetter = window->GetCurrentTimeGetter();
+    return currentTimeGetter->PropertyNotifyHandler(aWidget, aEvent);
+}
+
+static gboolean
 scroll_event_cb(GtkWidget *widget, GdkEventScroll *event)
 {
     nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
     if (!window)
         return FALSE;
 
     window->OnScrollEvent(event);