+}
+
+void notify_remote_exit(void *frontend)
+{
+ struct gui_data *inst = (struct gui_data *)frontend;
+
+ queue_toplevel_callback(exit_callback, inst);
+}
+
+static void notify_toplevel_callback(void *frontend);
+
+static gint quit_toplevel_callback_func(gpointer data)
+{
+ struct gui_data *inst = (struct gui_data *)data;
+
+ notify_toplevel_callback(inst);
+
+ inst->quit_fn_scheduled = FALSE;
+
+ return 0;
+}
+
+static gint idle_toplevel_callback_func(gpointer data)
+{
+ struct gui_data *inst = (struct gui_data *)data;
+
+ if (gtk_main_level() > 1) {
+ /*
+ * We don't run the callbacks if we're in the middle of a
+ * subsidiary gtk_main. Instead, ask for a callback when we
+ * get back out of the subsidiary main loop (if we haven't
+ * already arranged one), so we can reschedule ourself then.
+ */
+ if (!inst->quit_fn_scheduled) {
+ gtk_quit_add(2, quit_toplevel_callback_func, inst);
+ inst->quit_fn_scheduled = TRUE;
+ }
+ /*
+ * And unschedule this idle function, since we've now done
+ * everything we can until the innermost gtk_main has quit and
+ * can reschedule us with a chance of actually taking action.
+ */
+ if (inst->idle_fn_scheduled) { /* double-check, just in case */
+ gtk_idle_remove(inst->toplevel_callback_idle_id);
+ inst->idle_fn_scheduled = FALSE;
+ }
+ } else {
+ run_toplevel_callbacks();
+ }
+
+ /*
+ * If we've emptied our toplevel callback queue, unschedule
+ * ourself. Otherwise, leave ourselves pending so we'll be called
+ * again to deal with more callbacks after another round of the
+ * event loop.
+ */
+ if (!toplevel_callback_pending() && inst->idle_fn_scheduled) {
+ gtk_idle_remove(inst->toplevel_callback_idle_id);
+ inst->idle_fn_scheduled = FALSE;
+ }