diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 65fcec2..96d221b 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -42,6 +42,8 @@ struct _MetaCompositor
 
   gboolean frame_has_updated_xsurfaces;
   gboolean have_x11_sync_object;
+
+  gint64 last_presentation_time;
 };
 
 /* Wait 2ms after vblank before starting to draw next frame */
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 30504ac..06904dd 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -414,8 +414,15 @@ after_stage_paint (ClutterStage *stage,
     meta_window_actor_post_paint (l->data);
 
 #ifdef HAVE_WAYLAND
+  /* Our presentation time is in milliseconds to match Weston.
+   * gdk-wayland, for example, expects such and tries to handle
+   * the loss of precision in the presentation_time needing to
+   * be in 32-bit milliseconds.
+   */
   if (meta_is_wayland_compositor ())
-    meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
+    if (compositor->last_presentation_time)
+      meta_wayland_compositor_notify_frame_callbacks (meta_wayland_compositor_get_default (),
+                                                      compositor->last_presentation_time / 1000);
 #endif
 }
 
@@ -1033,6 +1040,8 @@ frame_callback (CoglOnscreen  *onscreen,
           presentation_time = 0;
         }
 
+      compositor->last_presentation_time = presentation_time;
+
       for (l = compositor->windows; l; l = l->next)
         meta_window_actor_frame_complete (l->data, frame_info, presentation_time);
     }
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 3199c99..2a88eb5 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -171,14 +171,15 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
 }
 
 void
-meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor)
+meta_wayland_compositor_notify_frame_callbacks (MetaWaylandCompositor *compositor,
+                                                guint32                presentation_time)
 {
   while (!wl_list_empty (&compositor->frame_callbacks))
     {
       MetaWaylandFrameCallback *callback =
         wl_container_of (compositor->frame_callbacks.next, callback, link);
 
-      wl_callback_send_done (callback->resource, g_get_monotonic_time () / 1000);
+      wl_callback_send_done (callback->resource, presentation_time);
       wl_resource_destroy (callback->resource);
     }
 }
diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h
index 7db5ca1..81e6c76 100644
--- a/src/wayland/meta-wayland.h
+++ b/src/wayland/meta-wayland.h
@@ -48,7 +48,8 @@ void                    meta_wayland_compositor_repick          (MetaWaylandComp
 void                    meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
                                                                  MetaWindow            *window);
 
-void                    meta_wayland_compositor_paint_finished  (MetaWaylandCompositor *compositor);
+void                    meta_wayland_compositor_notify_frame_callbacks  (MetaWaylandCompositor *compositor,
+                                                                         guint32                presentation_time);
 
 void                    meta_wayland_compositor_destroy_frame_callbacks (MetaWaylandCompositor *compositor,
                                                                          MetaWaylandSurface    *surface);
