From c3438661cbfac6a4622ea16c25c237a4ecd43009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dj=C3=A4rv?= Date: Fri, 12 Nov 2004 08:33:51 +0000 Subject: * xmenu.c (x_menu_wait_for_event): New function. (popup_get_selection, popup_widget_loop): Call x_menu_wait_for_event to handle timers. (xmenu_show): Call XMenuActivateSetWaitFunction so that x_menu_wait_for_event is called by XMenuActivate. --- src/xmenu.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 10 deletions(-) (limited to 'src/xmenu.c') diff --git a/src/xmenu.c b/src/xmenu.c index 9868902f3f3..9b9de8aa16d 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. @@ -1115,6 +1114,60 @@ 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) @@ -1140,17 +1193,16 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress) 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, @@ -1196,13 +1248,15 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress) /* Loop util popup_activated_flag is set to zero in a callback. Used for popup menus and dialogs. */ static void -popup_widget_loop () +popup_widget_loop (do_timers) + int do_timers; { ++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 (); } } @@ -2402,7 +2456,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 (0); gtk_widget_destroy (menu); @@ -2811,7 +2865,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); gtk_widget_destroy (menu); } @@ -3323,6 +3377,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; -- cgit v1.2.1 From df00f4364c61cb4d813a158d6f7d4f31e1ea4adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dj=C3=A4rv?= Date: Fri, 12 Nov 2004 09:36:55 +0000 Subject: (popup_widget_loop): Add argument do_timers. (create_and_show_popup_menu, create_and_show_dialog): Pass 1 for do_timers to popup_widget_loop. (create_and_show_popup_menu): Pass 1 for do_timers to popup_get_selection. --- src/xmenu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/xmenu.c') diff --git a/src/xmenu.c b/src/xmenu.c index 9b9de8aa16d..d8ab2eb58aa 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -2456,7 +2456,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 (0); + popup_widget_loop (1); gtk_widget_destroy (menu); @@ -2544,7 +2544,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. -- cgit v1.2.1 From f1d1cd24db8ab975bbe9bf0c4260bd8025e8bd75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dj=C3=A4rv?= Date: Fri, 12 Nov 2004 10:34:36 +0000 Subject: (pop_down_menu): New function. (popup_get_selection, popup_widget_loop): Unwind protect to pop_down_menu. (popup_widget_loop): Add argument widget. (create_and_show_popup_menu, create_and_show_dialog): Pass new argument widget to popup_widget_loop. --- src/xmenu.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'src/xmenu.c') diff --git a/src/xmenu.c b/src/xmenu.c index d8ab2eb58aa..d7551cd7e45 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1132,7 +1132,7 @@ x_menu_wait_for_event (void *data) while ( #ifdef USE_X_TOOLKIT - XtAppPending (Xt_app_con) + ! XtAppPending (Xt_app_con) #elif defined USE_GTK ! gtk_events_pending () #else @@ -1171,6 +1171,15 @@ x_menu_wait_for_event (void *data) #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; +} + /* 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. @@ -1180,7 +1189,6 @@ x_menu_wait_for_event (void *data) 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; @@ -1191,6 +1199,9 @@ 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 (initial_event) @@ -1240,6 +1251,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 */ @@ -1247,10 +1260,29 @@ 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; + } +} + static void -popup_widget_loop (do_timers) +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. */ @@ -1259,6 +1291,8 @@ popup_widget_loop (do_timers) if (do_timers) x_menu_wait_for_event (0); gtk_main_iteration (); } + + unbind_to (specpdl_count, Qnil); } #endif @@ -2456,7 +2490,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 (1); + popup_widget_loop (1, 0); gtk_widget_destroy (menu); @@ -2865,7 +2899,7 @@ create_and_show_dialog (f, first_wv) gtk_widget_show_all (menu); /* Process events that apply to the menu. */ - popup_widget_loop (1); + popup_widget_loop (1, menu); gtk_widget_destroy (menu); } -- cgit v1.2.1 From b9de078aa68bc403b9da6c801cdbd37eb77af44a Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Fri, 12 Nov 2004 13:47:13 +0000 Subject: (pop_down_menu): Return nil. --- src/xmenu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/xmenu.c') diff --git a/src/xmenu.c b/src/xmenu.c index d7551cd7e45..3b813927281 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -524,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 @@ -1098,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. */ @@ -1178,6 +1178,7 @@ pop_down_menu (dummy) int dummy; { popup_activated_flag = 0; + return Qnil; } /* Loop in Xt until the menu pulldown or dialog popup has been @@ -1272,6 +1273,7 @@ pop_down_menu (dummy) current_menu = 0; popup_activated_flag = 0; } + return Qnil; } static void @@ -2417,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; -- cgit v1.2.1