diff --git a/lib/wp/core.c b/lib/wp/core.c
index 9fc7e01d6eeedf0b52d901d048edcca0bf88c4f7..a892afcbb3104bfdc7b532be9adf15fc116c973b 100644
--- a/lib/wp/core.c
+++ b/lib/wp/core.c
@@ -495,6 +495,34 @@ wp_core_idle_add (WpCore * self, GSource **source, GSourceFunc function,
     *source = g_source_ref (s);
 }
 
+/**
+ * wp_core_idle_add_closure: (rename-to wp_core_idle_add)
+ * @self: the core
+ * @source: (out) (optional): the source
+ * @closure: the closure to invoke
+ *
+ * Adds an idle callback to be called in the same #GMainContext as the
+ * one used by this core.
+ *
+ * This is the same as wp_core_idle_add(), but it allows you to specify
+ * a #GClosure instead of a C callback.
+ */
+void
+wp_core_idle_add_closure (WpCore * self, GSource **source, GClosure * closure)
+{
+  g_autoptr (GSource) s = NULL;
+
+  g_return_if_fail (WP_IS_CORE (self));
+  g_return_if_fail (closure != NULL);
+
+  s = g_idle_source_new ();
+  g_source_set_closure (s, closure);
+  g_source_attach (s, self->context);
+
+  if (source)
+    *source = g_source_ref (s);
+}
+
 /**
  * wp_core_timeout_add:
  * @self: the core
@@ -513,7 +541,7 @@ wp_core_idle_add (WpCore * self, GSource **source, GSourceFunc function,
  * used by this core instead of the default context.
  */
 void
-wp_core_timeout_add (WpCore * self, GSource **source, guint64 timeout_ms,
+wp_core_timeout_add (WpCore * self, GSource **source, guint timeout_ms,
     GSourceFunc function, gpointer data, GDestroyNotify destroy)
 {
   g_autoptr (GSource) s = NULL;
@@ -528,6 +556,36 @@ wp_core_timeout_add (WpCore * self, GSource **source, guint64 timeout_ms,
     *source = g_source_ref (s);
 }
 
+/**
+ * wp_core_timeout_add_closure: (rename-to wp_core_timeout_add)
+ * @self: the core
+ * @source: (out) (optional): the source
+ * @timeout_ms: the timeout in milliseconds
+ * @closure: the closure to invoke
+ *
+ * Adds a timeout callback to be called at regular intervals in the same
+ * #GMainContext as the one used by this core.
+ *
+ * This is the same as wp_core_timeout_add(), but it allows you to specify
+ * a #GClosure instead of a C callback.
+ */
+void
+wp_core_timeout_add_closure (WpCore * self, GSource **source, guint timeout_ms,
+    GClosure * closure)
+{
+  g_autoptr (GSource) s = NULL;
+
+  g_return_if_fail (WP_IS_CORE (self));
+  g_return_if_fail (closure != NULL);
+
+  s = g_timeout_source_new (timeout_ms);
+  g_source_set_closure (s, closure);
+  g_source_attach (s, self->context);
+
+  if (source)
+    *source = g_source_ref (s);
+}
+
 /**
  * wp_core_sync:
  * @self: the core
diff --git a/lib/wp/core.h b/lib/wp/core.h
index 5128db4a9fd26f76f7707c6e8f24a8cbda96b059..9bafbc372eb64937911b0a6b9fb15fd6dd624b0c 100644
--- a/lib/wp/core.h
+++ b/lib/wp/core.h
@@ -54,9 +54,17 @@ void wp_core_idle_add (WpCore * self, GSource **source, GSourceFunc function,
     gpointer data, GDestroyNotify destroy);
 
 WP_API
-void wp_core_timeout_add (WpCore * self, GSource **source, guint64 timeout_ms,
+void wp_core_idle_add_closure (WpCore * self, GSource **source,
+    GClosure * closure);
+
+WP_API
+void wp_core_timeout_add (WpCore * self, GSource **source, guint timeout_ms,
     GSourceFunc function, gpointer data, GDestroyNotify destroy);
 
+WP_API
+void wp_core_timeout_add_closure (WpCore * self, GSource **source,
+    guint timeout_ms, GClosure * closure);
+
 WP_API
 gboolean wp_core_sync (WpCore * self, GCancellable * cancellable,
     GAsyncReadyCallback callback, gpointer user_data);