return wdialog;
}
-
-\f
-/***********************************************************************
- File dialog functions
- ***********************************************************************/
-/* Return non-zero if the old file selection dialog is being used.
- Return zero if not. */
-
-int
-xg_uses_old_file_dialog ()
+struct xg_dialog_data
{
-#ifdef HAVE_GTK_FILE_BOTH
- extern int x_gtk_use_old_file_dialog;
- return x_gtk_use_old_file_dialog;
-#else /* ! HAVE_GTK_FILE_BOTH */
-
-#ifdef HAVE_GTK_FILE_SELECTION_NEW
- return 1;
-#else
- return 0;
-#endif
-
-#endif /* ! HAVE_GTK_FILE_BOTH */
-}
-
+ GMainLoop *loop;
+ int response;
+ GtkWidget *w;
+ guint timerid;
+};
/* Function that is called when the file or font dialogs pop down.
W is the dialog widget, RESPONSE is the response code.
- USER_DATA is what we passed in to g_signal_connect (pointer to int). */
+ USER_DATA is what we passed in to g_signal_connect. */
static void
xg_dialog_response_cb (w,
- response,
- user_data)
+ response,
+ user_data)
GtkDialog *w;
gint response;
gpointer user_data;
{
- int *ptr = (int *) user_data;
- *ptr = response;
+ struct xg_dialog_data *dd = (struct xg_dialog_data *)user_data;
+ dd->response = response;
+ g_main_loop_quit (dd->loop);
}
Lisp_Object arg;
{
struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
+ struct xg_dialog_data *dd = (struct xg_dialog_data *) p->pointer;
+
BLOCK_INPUT;
- gtk_widget_destroy (GTK_WIDGET (p->pointer));
+ if (dd->w) gtk_widget_destroy (dd->w);
+ if (dd->timerid != 0) g_source_remove (dd->timerid);
+
+ g_main_loop_quit (dd->loop);
+ g_main_loop_unref (dd->loop);
+
UNBLOCK_INPUT;
+
return Qnil;
}
+/* If there are any emacs timers pending, add a timeout to main loop in DATA.
+ We pass in DATA as gpointer* so we can use this as a callback. */
+
+static gboolean
+xg_maybe_add_timer (data)
+ gpointer data;
+{
+ struct xg_dialog_data *dd = (struct xg_dialog_data *) data;
+ EMACS_TIME next_time = timer_check (1);
+ long secs = EMACS_SECS (next_time);
+ long usecs = EMACS_USECS (next_time);
+
+ dd->timerid = 0;
+
+ if (secs >= 0 && usecs >= 0 && secs < ((guint)-1)/1000)
+ {
+ dd->timerid = g_timeout_add (secs * 1000 + usecs/1000,
+ xg_maybe_add_timer,
+ dd);
+ }
+ return FALSE;
+}
+
+
+/* Pops up a modal dialog W and waits for response.
+ We don't use gtk_dialog_run because we want to process emacs timers.
+ The dialog W is not destroyed when this function returns. */
+
+static int
+xg_dialog_run (f, w)
+ FRAME_PTR f;
+ GtkWidget *w;
+
+{
+ int count = SPECPDL_INDEX ();
+ struct xg_dialog_data dd;
+
+ xg_set_screen (w, f);
+ gtk_window_set_transient_for (GTK_WINDOW (w),
+ GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE);
+ gtk_window_set_modal (GTK_WINDOW (w), TRUE);
+
+ dd.loop = g_main_loop_new (NULL, FALSE);
+ dd.response = GTK_RESPONSE_CANCEL;
+ dd.w = w;
+ dd.timerid = 0;
+
+ g_signal_connect (G_OBJECT (w),
+ "response",
+ G_CALLBACK (xg_dialog_response_cb),
+ &dd);
+ /* Don't destroy the widget if closed by the window manager close button. */
+ g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL);
+ gtk_widget_show (w);
+
+ record_unwind_protect (pop_down_dialog, make_save_value (&dd, 0));
+
+ (void) xg_maybe_add_timer (&dd);
+ g_main_loop_run (dd.loop);
+
+ dd.w = 0;
+ unbind_to (count, Qnil);
+
+ return dd.response;
+}
+
+\f
+/***********************************************************************
+ File dialog functions
+ ***********************************************************************/
+/* Return non-zero if the old file selection dialog is being used.
+ Return zero if not. */
+
+int
+xg_uses_old_file_dialog ()
+{
+#ifdef HAVE_GTK_FILE_BOTH
+ extern int x_gtk_use_old_file_dialog;
+ return x_gtk_use_old_file_dialog;
+#else /* ! HAVE_GTK_FILE_BOTH */
+
+#ifdef HAVE_GTK_FILE_SELECTION_NEW
+ return 1;
+#else
+ return 0;
+#endif
+
+#endif /* ! HAVE_GTK_FILE_BOTH */
+}
+
+
typedef char * (*xg_get_file_func) P_ ((GtkWidget *));
#ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW
int mustmatch_p, only_dir_p;
{
GtkWidget *w = 0;
- int count = SPECPDL_INDEX ();
char *fn = 0;
int filesel_done = 0;
xg_get_file_func func;
#endif /* HAVE_GTK_FILE_BOTH */
- xg_set_screen (w, f);
gtk_widget_set_name (w, "emacs-filedialog");
- gtk_window_set_transient_for (GTK_WINDOW (w),
- GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
- gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE);
- gtk_window_set_modal (GTK_WINDOW (w), TRUE);
-
- g_signal_connect (G_OBJECT (w),
- "response",
- G_CALLBACK (xg_dialog_response_cb),
- &filesel_done);
-
- /* Don't destroy the widget if closed by the window manager close button. */
- g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL);
- gtk_widget_show (w);
-
- record_unwind_protect (pop_down_dialog, make_save_value (w, 0));
- while (! filesel_done)
- {
- x_menu_wait_for_event (0);
- gtk_main_iteration ();
- }
+ filesel_done = xg_dialog_run (f, w);
#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
sigunblock (sigmask (__SIGRTMIN));
if (filesel_done == GTK_RESPONSE_OK)
fn = (*func) (w);
- unbind_to (count, Qnil);
-
+ gtk_widget_destroy (w);
return fn;
}
FRAME_PTR f;
char *default_name;
{
- GtkWidget *w = 0;
- int count = SPECPDL_INDEX ();
+ GtkWidget *w;
char *fontname = NULL;
int done = 0;
gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (w),
default_name);
- xg_set_screen (w, f);
gtk_widget_set_name (w, "emacs-fontdialog");
- gtk_window_set_transient_for (GTK_WINDOW (w),
- GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
- gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE);
- gtk_window_set_modal (GTK_WINDOW (w), TRUE);
-
- g_signal_connect (G_OBJECT (w), "response",
- G_CALLBACK (xg_dialog_response_cb), &done);
-
- /* Don't destroy the widget if closed by the window manager close button. */
- g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL);
-
- gtk_widget_show (w);
- record_unwind_protect (pop_down_dialog, make_save_value (w, 0));
- while (!done)
- {
- x_menu_wait_for_event (0);
- gtk_main_iteration ();
- }
+ done = xg_dialog_run (f, w);
#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
sigunblock (sigmask (__SIGRTMIN));
if (done == GTK_RESPONSE_OK)
fontname = gtk_font_selection_dialog_get_font_name
- ((GtkFontSelectionDialog *) w);
-
- unbind_to (count, Qnil);
+ (GTK_FONT_SELECTION_DIALOG (w));
+ gtk_widget_destroy (w);
return fontname;
}
#endif /* HAVE_FREETYPE */
disregard elements that are not proper timers. Do not make a circular
timer list for the time being.
- Returns the number of seconds to wait until the next timer fires. If a
- timer is triggering now, return zero seconds.
- If no timer is active, return -1 seconds.
+ Returns the time to wait until the next timer fires. If a
+ timer is triggering now, return zero.
+ If no timer is active, return -1.
If a timer is ripe, we run it, with quitting turned off.
+ In that case we return 0 to indicate that a new timer_check_2 call
+ should be done. */
- DO_IT_NOW is now ignored. It used to mean that we should
- run the timer directly instead of queueing a timer-event.
- Now we always run timers directly. */
-
-EMACS_TIME
-timer_check (do_it_now)
- int do_it_now;
+static EMACS_TIME
+timer_check_2 ()
{
EMACS_TIME nexttime;
EMACS_TIME now, idleness_now;
/* Since we have handled the event,
we don't need to tell the caller to wake up and do it. */
+ /* But the caller must still wait for the next timer, so
+ return 0 to indicate that. */
}
+
+ EMACS_SET_SECS (nexttime, 0);
+ EMACS_SET_USECS (nexttime, 0);
}
else
/* When we encounter a timer that is still waiting,
return nexttime;
}
+
+/* Check whether a timer has fired. To prevent larger problems we simply
+ disregard elements that are not proper timers. Do not make a circular
+ timer list for the time being.
+
+ Returns the time to wait until the next timer fires.
+ If no timer is active, return -1.
+
+ As long as any timer is ripe, we run it.
+
+ DO_IT_NOW is now ignored. It used to mean that we should
+ run the timer directly instead of queueing a timer-event.
+ Now we always run timers directly. */
+
+EMACS_TIME
+timer_check (do_it_now)
+ int do_it_now;
+{
+ EMACS_TIME nexttime;
+
+ do
+ {
+ nexttime = timer_check_2 ();
+ }
+ while (EMACS_SECS (nexttime) == 0 && EMACS_USECS (nexttime) == 0);
+
+ return nexttime;
+}
+
DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
doc: /* Return the current length of Emacs idleness, or nil.
The value when Emacs is idle is a list of three integers. The first has