/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2011
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef USE_GTK
#include "gtkutil.h"
+#ifdef HAVE_GTK3
+#include "xgselect.h"
+#endif
#endif
#include "menu.h"
Lisp_Object title;
const char *error_name;
Lisp_Object selection;
- int specpdl_count = SPECPDL_INDEX ();
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
/* Decode the dialog items from what was specified. */
title = Fcar (contents);
#ifndef MSDOS
+#if defined USE_GTK || defined USE_MOTIF
+
/* Set menu_items_inuse so no other popup menu or dialog is created. */
void
#endif
}
+#endif
+
/* Wait for an X event to arrive or for a timer to expire. */
#ifndef USE_MOTIF
else
ntp = &next_time;
+#ifdef HAVE_GTK3
+ /* Gtk3 have arrows on menus when they don't fit. When the pointer is
+ over an arrow, a timeout scrolls it a bit. Use xg_select so that
+ timeout gets triggered. */
+
+ xg_select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
+#else
select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
+#endif
}
}
#endif /* ! MSDOS */
help = call_data ? cb_data->help : Qnil;
/* If popup_activated_flag is greater than 1 we are in a popup menu.
- Don't show help for them, they won't appear before the
- popup is popped down. */
- if (popup_activated_flag <= 1)
- show_help_event (cb_data->cl_data->f, widget, help);
+ Don't pass the frame to show_help_event for those.
+ Passing frame creates an Emacs event. As we are looping in
+ popup_widget_loop, it won't be handled. Passing NULL shows the tip
+ directly without using an Emacs event. This is what the Lucid code
+ does below. */
+ show_help_event (popup_activated_flag <= 1 ? cb_data->cl_data->f : NULL,
+ widget, help);
}
#else
static void
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- int specpdl_count = SPECPDL_INDEX ();
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= (Lisp_Object *) alloca (previous_menu_items_used
#ifdef USE_MOTIF
/* Removing the menu bar magically changes the shell widget's x
and y position of (0, 0) which, when the menu bar is turned
- on again, leads to pull-down menuss appearing in strange
+ on again, leads to pull-down menus appearing in strange
positions near the upper-left corner of the display. This
happens only with some window managers like twm and ctwm,
but not with other like Motif's mwm or kwm, because the
GtkWidget *menu;
GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
struct next_popup_x_y popup_x_y;
- int specpdl_count = SPECPDL_INDEX ();
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ int use_pos_func = ! for_click;
+
+#ifdef HAVE_GTK3
+ /* Always use position function for Gtk3. Otherwise menus may become
+ too small to show anything. */
+ use_pos_func = 1;
+#endif
if (! FRAME_X_P (f))
abort ();
G_CALLBACK (menu_highlight_callback));
xg_crazy_callback_abort = 0;
- if (! for_click)
+ if (use_pos_func)
{
/* Not invoked by a click. pop up at x/y. */
pos_func = menu_position_func;
i = 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
}
- else
+
+ if (for_click)
{
for (i = 0; i < 5; i++)
if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
{
int fact = 4 * sizeof (LWLIB_ID);
- int specpdl_count = SPECPDL_INDEX ();
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
record_unwind_protect (pop_down_menu,
Fcons (make_number (menu_id >> (fact)),
make_number (menu_id & ~(-1 << (fact)))));
#endif /* not USE_GTK */
+static Lisp_Object
+cleanup_widget_value_tree (Lisp_Object arg)
+{
+ struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
+ widget_value *wv = p->pointer;
+
+ free_menubar_widget_value_tree (wv);
+
+ return Qnil;
+}
+
Lisp_Object
xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
Lisp_Object title, const char **error_name, Time timestamp)
int first_pane;
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+
if (! FRAME_X_P (f))
abort ();
/* No selection has been chosen yet. */
menu_item_selection = 0;
+ /* Make sure to free the widget_value objects we used to specify the
+ contents even with longjmp. */
+ record_unwind_protect (cleanup_widget_value_tree,
+ make_save_value (first_wv, 0));
+
/* Actually create and show the menu until popped down. */
create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp);
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
+ unbind_to (specpdl_count, Qnil);
/* Find the selected item, and its pane, to return
the proper value. */
if (menu)
{
- int specpdl_count = SPECPDL_INDEX ();
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
/* Display the menu. */
static void
dialog_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
{
- /* The EMACS_INT cast avoids a warning. There's no problem
+ /* Treat the pointer as an integer. There's no problem
as long as pointers have enough bits to hold small integers. */
- if ((int) (EMACS_INT) client_data != -1)
+ if ((intptr_t) client_data != -1)
menu_item_selection = (Lisp_Object *) client_data;
BLOCK_INPUT;
LWLIB_ID dialog_id;
if (!FRAME_X_P (f))
- abort();
+ abort ();
dialog_id = widget_id_tick++;
#ifdef USE_LUCID
/* Process events that apply to the dialog box.
Also handle timers. */
{
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
int fact = 4 * sizeof (LWLIB_ID);
/* xdialog_show_unwind is responsible for popping the dialog box down. */
/* 1 means we've seen the boundary between left-hand elts and right-hand. */
int boundary_seen = 0;
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+
if (! FRAME_X_P (f))
abort ();
/* Frame title: 'Q' = Question, 'I' = Information.
Can also have 'E' = Error if, one day, we want
a popup for errors. */
- if (NILP(header))
+ if (NILP (header))
dialog_name[0] = 'Q';
else
dialog_name[0] = 'I';
/* No selection has been chosen yet. */
menu_item_selection = 0;
+ /* Make sure to free the widget_value objects we used to specify the
+ contents even with longjmp. */
+ record_unwind_protect (cleanup_widget_value_tree,
+ make_save_value (first_wv, 0));
+
/* Actually create and show the dialog. */
create_and_show_dialog (f, first_wv);
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
+ unbind_to (specpdl_count, Qnil);
/* Find the selected item, and its pane, to return
the proper value. */
int maxwidth;
int dummy_int;
unsigned int dummy_uint;
- int specpdl_count = SPECPDL_INDEX ();
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
abort ();
void
syms_of_xmenu (void)
{
- Qdebug_on_next_call = intern_c_string ("debug-on-next-call");
- staticpro (&Qdebug_on_next_call);
+ DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
#ifdef USE_X_TOOLKIT
widget_id_tick = (1<<16);