[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] Changes to emacs/src/xmenu.c [lexbind]
From: |
Miles Bader |
Subject: |
[Emacs-diffs] Changes to emacs/src/xmenu.c [lexbind] |
Date: |
Wed, 08 Dec 2004 19:38:25 -0500 |
Index: emacs/src/xmenu.c
diff -c emacs/src/xmenu.c:1.230.4.9 emacs/src/xmenu.c:1.230.4.10
*** emacs/src/xmenu.c:1.230.4.9 Fri Nov 12 04:21:15 2004
--- emacs/src/xmenu.c Wed Dec 8 23:31:37 2004
***************
*** 48,53 ****
--- 48,54 ----
#include "buffer.h"
#include "charset.h"
#include "coding.h"
+ #include "sysselect.h"
#ifdef MSDOS
#include "msdos.h"
***************
*** 157,164 ****
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.
--- 158,163 ----
***************
*** 289,295 ****
static Lisp_Object
unuse_menu_items (dummy)
! int dummy;
{
return menu_items_inuse = Qnil;
}
--- 288,294 ----
static Lisp_Object
unuse_menu_items (dummy)
! Lisp_Object dummy;
{
return menu_items_inuse = Qnil;
}
***************
*** 525,531 ****
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
--- 524,530 ----
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,1105 ****
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. */
--- 1098,1104 ----
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,1123 ****
--- 1114,1188 ----
}
#endif
}
+
+
+ #ifndef MSDOS
+
+ /* Set menu_items_inuse so no other popup menu or dialog is created. */
+
+ void
+ x_menu_set_in_use (in_use)
+ int in_use;
+ {
+ menu_items_inuse = in_use ? Qt : Qnil;
+ popup_activated_flag = in_use;
+ }
+
+ /* Wait for an X event to arrive or for a timer to expire. */
+
+ 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
+
/* 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,1133 ****
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;
--- 1192,1197 ----
***************
*** 1140,1156 ****
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);
/* Make sure we don't consider buttons grabbed after menu goes.
And make sure to deactivate for any ButtonRelease,
--- 1204,1219 ----
while (popup_activated_flag)
{
if (initial_event)
{
event = *initial_event;
initial_event = 0;
}
else
! {
! 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,
***************
*** 1195,1208 ****
#ifdef USE_GTK
/* Loop util popup_activated_flag is set to zero in a callback.
Used for popup menus and dialogs. */
static void
! popup_widget_loop ()
{
++popup_activated_flag;
/* Process events in the Gtk event loop until done. */
while (popup_activated_flag)
{
gtk_main_iteration ();
}
}
--- 1258,1275 ----
#ifdef USE_GTK
/* Loop util popup_activated_flag is set to zero in a callback.
Used for popup menus and dialogs. */
+
static void
! popup_widget_loop (do_timers, widget)
! int do_timers;
! GtkWidget *widget;
{
++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 ();
}
}
***************
*** 2329,2335 ****
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;
--- 2396,2402 ----
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;
***************
*** 2353,2358 ****
--- 2420,2438 ----
if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
}
+ static Lisp_Object
+ pop_down_menu (arg)
+ Lisp_Object arg;
+ {
+ struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
+
+ popup_activated_flag = 0;
+ BLOCK_INPUT;
+ gtk_widget_destroy (GTK_WIDGET (p->pointer));
+ UNBLOCK_INPUT;
+ return Qnil;
+ }
+
/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
menu pops down.
menu_item_selection will be set to the selection. */
***************
*** 2368,2373 ****
--- 2448,2454 ----
GtkWidget *menu;
GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
struct next_popup_x_y popup_x_y;
+ int specpdl_count = SPECPDL_INDEX ();
xg_crazy_callback_abort = 1;
menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
***************
*** 2398,2410 ****
gtk_widget_show_all (menu);
gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
/* Set this to one. popup_widget_loop increases it by one, so it becomes
two. show_help_echo uses this to detect popup menus. */
popup_activated_flag = 1;
/* Process events that apply to the menu. */
! popup_widget_loop ();
! gtk_widget_destroy (menu);
/* Must reset this manually because the button release event is not passed
to Emacs event loop. */
--- 2479,2493 ----
gtk_widget_show_all (menu);
gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
+ record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
+
/* Set this to one. popup_widget_loop increases it by one, so it becomes
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, menu);
! unbind_to (specpdl_count, Qnil);
/* Must reset this manually because the button release event is not passed
to Emacs event loop. */
***************
*** 2432,2437 ****
--- 2515,2538 ----
menu_item_selection = (Lisp_Object *) client_data;
}
+ /* ARG is the LWLIB ID of the dialog box, represented
+ as a Lisp object as (HIGHPART . LOWPART). */
+
+ static Lisp_Object
+ pop_down_menu (arg)
+ Lisp_Object arg;
+ {
+ LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
+ | XINT (XCDR (arg)));
+
+ BLOCK_INPUT;
+ lw_destroy_all_widgets (id);
+ UNBLOCK_INPUT;
+ popup_activated_flag = 0;
+
+ return Qnil;
+ }
+
/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
menu pops down.
menu_item_selection will be set to the selection. */
***************
*** 2488,2502 ****
/* Display the menu. */
lw_popup_menu (menu, (XEvent *) &dummy);
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);
! /* fp turned off the following statement and wrote a comment
! that it is unnecessary--that the menu has already disappeared.
! Nowadays the menu disappears ok, all right, but
! we need to delete the widgets or multiple ones will pile up. */
! lw_destroy_all_widgets (menu_id);
}
#endif /* not USE_GTK */
--- 2589,2607 ----
/* Display the menu. */
lw_popup_menu (menu, (XEvent *) &dummy);
popup_activated_flag = 1;
+
+ {
+ int fact = 4 * sizeof (LWLIB_ID);
+ int specpdl_count = SPECPDL_INDEX ();
+ record_unwind_protect (pop_down_menu,
+ Fcons (make_number (menu_id >> (fact)),
+ make_number (menu_id & ~(-1 << (fact)))));
! /* Process events that apply to the menu. */
! popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1,
0);
! unbind_to (specpdl_count, Qnil);
! }
}
#endif /* not USE_GTK */
***************
*** 2807,2819 ****
if (menu)
{
/* Display the menu. */
gtk_widget_show_all (menu);
/* Process events that apply to the menu. */
! popup_widget_loop ();
! gtk_widget_destroy (menu);
}
}
--- 2912,2927 ----
if (menu)
{
+ int specpdl_count = SPECPDL_INDEX ();
+ record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
+
/* Display the menu. */
gtk_widget_show_all (menu);
/* Process events that apply to the menu. */
! popup_widget_loop (1, menu);
! unbind_to (specpdl_count, Qnil);
}
}
***************
*** 2836,2858 ****
}
- /* ARG is the LWLIB ID of the dialog box, represented
- as a Lisp object as (HIGHPART . LOWPART). */
-
- Lisp_Object
- xdialog_show_unwind (arg)
- Lisp_Object arg;
- {
- LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
- | XINT (XCDR (arg)));
- BLOCK_INPUT;
- lw_destroy_all_widgets (id);
- UNBLOCK_INPUT;
- popup_activated_flag = 0;
- return Qnil;
- }
-
-
/* Pop up the dialog for frame F defined by FIRST_WV and loop until the
dialog pops down.
menu_item_selection will be set to the selection. */
--- 2944,2949 ----
***************
*** 2880,2886 ****
int fact = 4 * sizeof (LWLIB_ID);
/* xdialog_show_unwind is responsible for popping the dialog box down. */
! record_unwind_protect (xdialog_show_unwind,
Fcons (make_number (dialog_id >> (fact)),
make_number (dialog_id & ~(-1 << (fact)))));
--- 2971,2977 ----
int fact = 4 * sizeof (LWLIB_ID);
/* xdialog_show_unwind is responsible for popping the dialog box down. */
! record_unwind_protect (pop_down_menu,
Fcons (make_number (dialog_id >> (fact)),
make_number (dialog_id & ~(-1 << (fact)))));
***************
*** 3113,3118 ****
--- 3204,3244 ----
Qnil, menu_object, make_number (item), 1);
}
+ static Lisp_Object
+ pop_down_menu (arg)
+ Lisp_Object arg;
+ {
+ struct Lisp_Save_Value *p1 = XSAVE_VALUE (Fcar (arg));
+ struct Lisp_Save_Value *p2 = XSAVE_VALUE (Fcdr (arg));
+
+ FRAME_PTR f = p1->pointer;
+ XMenu *menu = p2->pointer;
+
+ BLOCK_INPUT;
+ #ifndef MSDOS
+ XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
+ XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
+ #endif
+ XMenuDestroy (FRAME_X_DISPLAY (f), menu);
+
+ #ifdef HAVE_X_WINDOWS
+ /* Assume the mouse has moved out of the X window.
+ If it has actually moved in, we will get an EnterNotify. */
+ x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
+
+ /* State that no mouse buttons are now held.
+ (The oldXMenu code doesn't track this info for us.)
+ That is not necessarily true, but the fiction leads to reasonable
+ results, and it is a pain to ask which are actually held now. */
+ FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+
+ #endif /* HAVE_X_WINDOWS */
+
+ UNBLOCK_INPUT;
+
+ return Qnil;
+ }
+
static Lisp_Object
xmenu_show (f, x, y, for_click, keymaps, title, error)
***************
*** 3134,3139 ****
--- 3260,3266 ----
int maxwidth;
int dummy_int;
unsigned int dummy_uint;
+ int specpdl_count = SPECPDL_INDEX ();
*error = 0;
if (menu_items_n_panes == 0)
***************
*** 3323,3341 ****
XMenuSetFreeze (menu, TRUE);
pane = selidx = 0;
/* 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;
status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
! x, y, ButtonReleaseMask, &datap,
! menu_help_callback);
!
!
! #ifdef HAVE_X_WINDOWS
! /* Assume the mouse has moved out of the X window.
! If it has actually moved in, we will get an EnterNotify. */
! x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
! #endif
switch (status)
{
--- 3450,3469 ----
XMenuSetFreeze (menu, TRUE);
pane = selidx = 0;
+ #ifndef MSDOS
+ XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
+ #endif
+
+ record_unwind_protect (pop_down_menu,
+ Fcons (make_save_value (f, 0),
+ make_save_value (menu, 0)));
+
/* 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;
status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
! x, y, ButtonReleaseMask, &datap,
! menu_help_callback);
switch (status)
{
***************
*** 3386,3400 ****
entry = Qnil;
break;
}
- XMenuDestroy (FRAME_X_DISPLAY (f), menu);
! #ifdef HAVE_X_WINDOWS
! /* State that no mouse buttons are now held.
! (The oldXMenu code doesn't track this info for us.)
! That is not necessarily true, but the fiction leads to reasonable
! results, and it is a pain to ask which are actually held now. */
! FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
! #endif
return entry;
}
--- 3514,3521 ----
entry = Qnil;
break;
}
! unbind_to (specpdl_count, Qnil);
return entry;
}