summaryrefslogtreecommitdiff
path: root/src/xmenu.c
diff options
context:
space:
mode:
authorKaroly Lorentey <lorentey@elte.hu>2004-11-13 18:34:40 +0000
committerKaroly Lorentey <lorentey@elte.hu>2004-11-13 18:34:40 +0000
commite417405015c93c81641f5c4a33ec898b5c353772 (patch)
tree017a980c35c8a71c372304418d151e3826f88636 /src/xmenu.c
parentf590a2a442d19f3a74d7bbd02bbcb4e3239f2327 (diff)
parent68d1b30d251b4771f739d20f507cd9523ae3919b (diff)
downloademacs-e417405015c93c81641f5c4a33ec898b5c353772.tar.gz
Merged in changes from CVS trunk.
Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-673 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-674 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-675 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-676 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-677 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-678 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-679 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-680 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-681 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-682 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-683 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-684 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-685 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-686 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-687 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-688 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-689 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-690 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-691 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-692 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-693 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-69 Merge from emacs--cvs-trunk--0 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-70 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-71 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-267
Diffstat (limited to 'src/xmenu.c')
-rw-r--r--src/xmenu.c124
1 files changed, 109 insertions, 15 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index a08f4610101..0a83266a482 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA. */
#include "buffer.h"
#include "charset.h"
#include "coding.h"
+#include "sysselect.h"
#ifdef MSDOS
#include "msdos.h"
@@ -157,8 +158,6 @@ static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
static void list_of_panes P_ ((Lisp_Object));
static void list_of_items P_ ((Lisp_Object));
-extern EMACS_TIME timer_check P_ ((int));
-
/* This holds a Lisp vector that holds the results of decoding
the keymaps or alist-of-alists that specify a menu.
@@ -525,7 +524,7 @@ single_menu_item (key, item, dummy, skp_v)
return; /* Not a menu item. */
map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
-
+
if (skp->notreal)
{
/* We don't want to make a menu, just traverse the keymaps to
@@ -1099,7 +1098,7 @@ on the left of the dialog box and all following items on the right.
the dialog. Also, the lesstif/motif version crashes if there are
no buttons. */
contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
-
+
list_of_panes (Fcons (contents, Qnil));
/* Display them in a dialog box. */
@@ -1115,9 +1114,73 @@ on the left of the dialog box and all following items on the right.
}
#endif
}
+
+
+#ifndef MSDOS
+
+/* Wait for an X event to arrive or for a timer to expire. */
+
+static void
+x_menu_wait_for_event (void *data)
+{
+ extern EMACS_TIME timer_check P_ ((int));
+
+ /* Another way to do this is to register a timer callback, that can be
+ done in GTK and Xt. But we have to do it like this when using only X
+ anyway, and with callbacks we would have three variants for timer handling
+ instead of the small ifdefs below. */
+
+ while (
+#ifdef USE_X_TOOLKIT
+ ! XtAppPending (Xt_app_con)
+#elif defined USE_GTK
+ ! gtk_events_pending ()
+#else
+ ! XPending ((Display*) data)
+#endif
+ )
+ {
+ EMACS_TIME next_time = timer_check (1);
+ long secs = EMACS_SECS (next_time);
+ long usecs = EMACS_USECS (next_time);
+ SELECT_TYPE read_fds;
+ struct x_display_info *dpyinfo;
+ int n = 0;
+
+ FD_ZERO (&read_fds);
+ for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+ {
+ int fd = ConnectionNumber (dpyinfo->display);
+ FD_SET (fd, &read_fds);
+ if (fd > n) n = fd;
+ }
+
+ if (secs < 0 || (secs == 0 && usecs == 0))
+ {
+ /* Sometimes timer_check returns -1 (no timers) even if there are
+ timers. So do a timeout anyway. */
+ EMACS_SET_SECS (next_time, 1);
+ EMACS_SET_USECS (next_time, 0);
+ }
+
+ select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, &next_time);
+ }
+}
+#endif /* ! MSDOS */
+
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+#ifdef USE_X_TOOLKIT
+
+static Lisp_Object
+pop_down_menu (dummy)
+ int dummy;
+{
+ popup_activated_flag = 0;
+ return Qnil;
+}
+
/* Loop in Xt until the menu pulldown or dialog popup has been
popped down (deactivated). This is used for x-popup-menu
and x-popup-dialog; it is not used for the menu bar.
@@ -1127,7 +1190,6 @@ on the left of the dialog box and all following items on the right.
NOTE: All calls to popup_get_selection should be protected
with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
-#ifdef USE_X_TOOLKIT
static void
popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)
XEvent *initial_event;
@@ -1138,19 +1200,21 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)
{
XEvent event;
+ int specpdl_count = SPECPDL_INDEX ();
+ record_unwind_protect (pop_down_menu, Qnil);
+
while (popup_activated_flag)
{
- /* If we have no events to run, consider timers. */
- if (do_timers && !XtAppPending (Xt_app_con))
- timer_check (1);
-
if (initial_event)
{
event = *initial_event;
initial_event = 0;
}
else
- XtAppNextEvent (Xt_app_con, &event);
+ {
+ if (do_timers) x_menu_wait_for_event (0);
+ XtAppNextEvent (Xt_app_con, &event);
+ }
/* Make sure we don't consider buttons grabbed after menu goes.
And make sure to deactivate for any ButtonRelease,
@@ -1188,6 +1252,8 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)
x_dispatch_event (&event, event.xany.display);
}
+
+ unbind_to (specpdl_count, Qnil);
}
#endif /* USE_X_TOOLKIT */
@@ -1195,16 +1261,40 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)
#ifdef USE_GTK
/* Loop util popup_activated_flag is set to zero in a callback.
Used for popup menus and dialogs. */
+static GtkWidget *current_menu;
+
+static Lisp_Object
+pop_down_menu (dummy)
+ int dummy;
+{
+ if (current_menu)
+ {
+ gtk_widget_unmap (current_menu);
+ current_menu = 0;
+ popup_activated_flag = 0;
+ }
+ return Qnil;
+}
+
static void
-popup_widget_loop ()
+popup_widget_loop (do_timers, widget)
+ int do_timers;
+ GtkWidget *widget;
{
+ int specpdl_count = SPECPDL_INDEX ();
+ current_menu = widget;
+ record_unwind_protect (pop_down_menu, Qnil);
+
++popup_activated_flag;
/* Process events in the Gtk event loop until done. */
while (popup_activated_flag)
{
+ if (do_timers) x_menu_wait_for_event (0);
gtk_main_iteration ();
}
+
+ unbind_to (specpdl_count, Qnil);
}
#endif
@@ -2329,7 +2419,7 @@ menu_position_func (menu, x, y, push_in, user_data)
GtkRequisition req;
int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width;
int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height;
-
+
*x = data->x;
*y = data->y;
@@ -2402,7 +2492,7 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
two. show_help_echo uses this to detect popup menus. */
popup_activated_flag = 1;
/* Process events that apply to the menu. */
- popup_widget_loop ();
+ popup_widget_loop (1, 0);
gtk_widget_destroy (menu);
@@ -2490,7 +2580,7 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
popup_activated_flag = 1;
/* Process events that apply to the menu. */
- popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0, 0);
+ popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1, 0);
/* fp turned off the following statement and wrote a comment
that it is unnecessary--that the menu has already disappeared.
@@ -2811,7 +2901,7 @@ create_and_show_dialog (f, first_wv)
gtk_widget_show_all (menu);
/* Process events that apply to the menu. */
- popup_widget_loop ();
+ popup_widget_loop (1, menu);
gtk_widget_destroy (menu);
}
@@ -3323,6 +3413,10 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
XMenuSetFreeze (menu, TRUE);
pane = selidx = 0;
+#ifndef MSDOS
+ XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
+#endif
+
/* Help display under X won't work because XMenuActivate contains
a loop that doesn't give Emacs a chance to process it. */
menu_help_frame = f;