--- ui/gcr-prompt-dialog.c.orig	2016-10-11 12:22:53.000000000 -0400
+++ ui/gcr-prompt-dialog.c	2016-10-16 09:22:23.000000000 -0400
@@ -27,7 +27,9 @@
 #include "gcr-secure-entry-buffer.h"
 
 #include <gtk/gtk.h>
-#include <gdk/gdkx.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
 #include <glib/gi18n.h>
 
 /**
@@ -107,7 +109,7 @@
 	GtkEntryBuffer *password_buffer;
 	GtkEntryBuffer *confirm_buffer;
 	PromptMode mode;
-	GdkDevice *grabbed_device;
+	GdkSeat *grabbed_seat;
 	gulong grab_broken_id;
 	gboolean grab_disabled;
 	gboolean was_closed;
@@ -141,21 +143,33 @@
 	if (window == NULL)
 		return;
 
-	handle = g_ascii_strtoll (self->pv->caller_window, &end, 10);
-	if (!end || *end != '\0') {
+	display = gtk_widget_get_display (GTK_WIDGET (self));
+	transient_for = NULL;
+	handle = 0;
+	end = NULL;
+#ifdef GDK_WINDOWING_X11
+	if (GDK_IS_X11_DISPLAY (display)) {
+	        handle = g_ascii_strtoll (self->pv->caller_window, &end, 10);
+	        if (end && *end == '\0') {
+	                transient_for = gdk_x11_window_foreign_new_for_display (display, (Window)handle);
+			if (transient_for == NULL) {
+			        g_warning ("caller-window property doesn't represent a window on current display: %s",
+					   self->pv->caller_window);
+			}
+		}
+	}
+#endif
+	if (transient_for == NULL) {
+	        transient_for = gcr_prompt_util_window_of_mock_id (self->pv->caller_window);
+		if (transient_for) { g_object_ref(transient_for); }
+	}
+	if (transient_for == NULL) {
 		g_warning ("couldn't parse caller-window property: %s", self->pv->caller_window);
 		return;
 	}
 
-	display = gtk_widget_get_display (GTK_WIDGET (self));
-	transient_for = gdk_x11_window_foreign_new_for_display (display, (Window)handle);
-	if (transient_for == NULL) {
-		g_warning ("caller-window property doesn't represent a window on current display: %s",
-		           self->pv->caller_window);
-	} else {
-		gdk_window_set_transient_for (window, transient_for);
-		g_object_unref (transient_for);
-	}
+	gdk_window_set_transient_for (window, transient_for);
+	g_object_unref (transient_for);
 
 	gtk_window_set_modal (GTK_WINDOW (self), TRUE);
 }
@@ -401,39 +415,28 @@
 {
 	GcrPromptDialog *self = GCR_PROMPT_DIALOG (user_data);
 	GdkGrabStatus status;
-	guint32 at;
-	GdkDevice *device = NULL;
-	GdkDeviceManager *manager;
+	GdkSeat *seat;
 	GdkDisplay *display;
-	GList *devices, *l;
 
-	if (self->pv->grabbed_device || !GRAB_KEYBOARD)
+	if (self->pv->grabbed_seat || !GRAB_KEYBOARD)
 		return FALSE;
 
 	display = gtk_widget_get_display (widget);
-	manager = gdk_display_get_device_manager (display);
-	devices = gdk_device_manager_list_devices (manager, GDK_DEVICE_TYPE_MASTER);
-	for (l = devices; l; l = g_list_next (l)) {
-		device = l->data;
-		if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
-			break;
-	}
-	g_list_free (devices);
+	seat = gdk_display_get_default_seat (display);
 
-	if (!device) {
-		g_message ("couldn't find device to grab");
+	if (!seat) {
+		g_message ("couldn't find seat to grab");
 		return FALSE;
 	}
 
-	at = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
-	status = gdk_device_grab (device, gtk_widget_get_window (widget),
-	                          GDK_OWNERSHIP_APPLICATION, TRUE,
-	                          GDK_KEY_PRESS | GDK_KEY_RELEASE, NULL, at);
+	status = gdk_seat_grab (seat, gtk_widget_get_window (widget),
+				GDK_SEAT_CAPABILITY_KEYBOARD, TRUE,
+				NULL, event, NULL, NULL);
 	if (status == GDK_GRAB_SUCCESS) {
 		self->pv->grab_broken_id = g_signal_connect (widget, "grab-broken-event",
 		                                             G_CALLBACK (on_grab_broken), self);
-		gtk_device_grab_add (widget, device, TRUE);
-		self->pv->grabbed_device = device;
+		gtk_device_grab_add (widget, gdk_seat_get_keyboard (seat), TRUE);
+		self->pv->grabbed_seat = seat;
 	} else {
 		g_message ("could not grab keyboard: %s", grab_status_message (status));
 	}
@@ -447,14 +450,14 @@
                  GdkEvent *event,
                  gpointer user_data)
 {
-	guint32 at = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
 	GcrPromptDialog *self = GCR_PROMPT_DIALOG (user_data);
 
-	if (self->pv->grabbed_device) {
+	if (self->pv->grabbed_seat) {
 		g_signal_handler_disconnect (widget, self->pv->grab_broken_id);
-		gdk_device_ungrab (self->pv->grabbed_device, at);
-		gtk_device_grab_remove (widget, self->pv->grabbed_device);
-		self->pv->grabbed_device = NULL;
+		gdk_seat_ungrab (self->pv->grabbed_seat);
+		gtk_device_grab_remove (widget,
+					gdk_seat_get_keyboard (self->pv->grabbed_seat));
+		self->pv->grabbed_seat = NULL;
 		self->pv->grab_broken_id = 0;
 	}
 
@@ -725,7 +728,7 @@
 	gcr_prompt_close (GCR_PROMPT (self));
 
 	ungrab_keyboard (GTK_WIDGET (self), NULL, self);
-	g_assert (self->pv->grabbed_device == NULL);
+	g_assert (self->pv->grabbed_seat == NULL);
 
 	G_OBJECT_CLASS (gcr_prompt_dialog_parent_class)->dispose (obj);
 }
@@ -962,3 +965,101 @@
 	iface->prompt_confirm_finish = gcr_prompt_dialog_confirm_finish;
 	iface->prompt_close = gcr_prompt_dialog_close;
 }
+
+#define MOCK_HANDLE_LENGTH 24
+typedef struct {
+        GdkWindow *win;
+        gchar      han[MOCK_HANDLE_LENGTH];
+} MockHandleEntry;
+  
+static GArray *
+mock_handle_table() {
+        static GArray *the_table = NULL;
+        if (the_table == NULL) {
+	        the_table = g_array_new (FALSE, FALSE, sizeof(MockHandleEntry));
+	}
+	return the_table;
+}
+
+static const gchar *
+mock_handle_header() {
+        static gchar the_header[16];
+        static gboolean inited = FALSE;
+        if (!inited) {
+	        g_snprintf (the_header, sizeof (the_header), "mh%ul", g_random_int());
+		inited = TRUE;
+	}
+	return the_header;
+}
+
+/**
+ * gcr_prompt_util_mock_id_of_window:
+ * @window: the GdkWindow
+ *
+ * Return a pointer to memory maintained internally by gcr_prompt which gives
+ * a mock string id for the given window, such that later passing a matching string to
+ * gcr_prompt_util_window_of_mock_id will give back the same GdkWindow, as long as bpth
+ * functions are called within the same process.
+ * 
+ * Useful as an argument to gcr_prompt_set_caller_window for handling caller windows within
+ * the same process if no backend handles that allow windows to be identified across
+ * processes are available.
+ */
+const gchar *
+gcr_prompt_util_mock_id_of_window (GdkWindow *window)
+{
+        GArray *table = mock_handle_table();
+	guint i;
+	guint cursize = table->len;
+	gsize h;
+	MockHandleEntry maybeNewEntry;
+	
+	/* linear search: not expecting many prompts in a given process */
+	for (i = 0; i < cursize; ++i) {
+	        if (g_array_index (table, MockHandleEntry,i).win == window) {
+		        return g_array_index (table, MockHandleEntry,i).han;
+		}
+	}
+	/* haven't seen this window yet, make a new entry */
+	maybeNewEntry.win = window;
+	h = g_strlcpy(maybeNewEntry.han, mock_handle_header(), MOCK_HANDLE_LENGTH);
+	g_snprintf(maybeNewEntry.han + h, MOCK_HANDLE_LENGTH - h, "%ul", cursize);
+	g_array_append_val (table, maybeNewEntry);
+	return g_array_index (table, MockHandleEntry, cursize).han;
+}
+
+/**
+ * gcr_prompt_util_window_of_mock_id:
+ * @try_handle: string to attempt to interpret as a mock handle
+ * 
+ * If gcr_prompt_util_mock_id_of_window earlier in the same process returned a string
+ * matching the argument to this function, return the GdkWindow* that 
+ * gcr_prompt_util_mock_id_of_window was called with, otherwise NULL.
+ * 
+ * The pair of functions gcr_prompt_util_mock_id_of_window and 
+ * gcr_prompt_util_window_of_mock_id attempt to ensure that a mock handle issued by another
+ * process will not be misconstrued as a mock handle for the current process.
+ */
+GdkWindow *
+gcr_prompt_util_window_of_mock_id (const gchar *try_handle)
+{
+        static guint h = 0;
+	GArray *table;
+	guint64 scanned;
+	
+	if (h == 0) {
+	        h = strlen (mock_handle_header());
+	}
+        if (!g_str_has_prefix (try_handle, mock_handle_header())) {
+	        return NULL;
+	}
+	if (!g_ascii_isdigit (try_handle[h])) {
+	        return NULL;
+	}
+	scanned = g_ascii_strtoull (try_handle + h, NULL, 10);
+	table = mock_handle_table();
+	if (scanned >= table->len) {
+	        return NULL;
+	}
+	return g_array_index (table, MockHandleEntry, scanned).win;
+}
