/* X Communication module for terminals which understand the X protocol.
Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#endif
#include <stdio.h>
+#include <setjmp.h>
#include "lisp.h"
#include "keyboard.h"
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#ifdef USE_LUCID
+#include "xsettings.h"
+#include "../lwlib/xlwmenu.h"
#ifdef HAVE_XAW3D
#include <X11/Xaw3d/Paned.h>
#else /* !HAVE_XAW3D */
#include <X11/Xaw/Paned.h>
#endif /* HAVE_XAW3D */
#endif /* USE_LUCID */
+#ifdef USE_MOTIF
#include "../lwlib/lwlib.h"
+#endif
#else /* not USE_X_TOOLKIT */
#ifndef USE_GTK
#include "../oldXMenu/XMenu.h"
Lisp_Object Qdebug_on_next_call;
-extern Lisp_Object Vmenu_updating_frame;
-
-extern Lisp_Object Qmenu_bar;
-
-extern Lisp_Object QCtoggle, QCradio;
-
-extern Lisp_Object Voverriding_local_map;
-extern Lisp_Object Voverriding_local_map_menu_flag;
-
-extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-
-extern Lisp_Object Qmenu_bar_update_hook;
-
-#ifdef USE_X_TOOLKIT
-extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
-extern XtAppContext Xt_app_con;
-
-static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
- char **));
-static void popup_get_selection P_ ((XEvent *, struct x_display_info *,
- LWLIB_ID, int));
-#endif /* USE_X_TOOLKIT */
-
-#ifdef USE_GTK
-extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
-static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
- char **));
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+static Lisp_Object xdialog_show (FRAME_PTR, int, Lisp_Object, Lisp_Object,
+ const char **);
#endif
-static int update_frame_menubar P_ ((struct frame *));
-static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int,
- Lisp_Object, char **));
+static int update_frame_menubar (struct frame *);
\f
/* Flag which when set indicates a dialog or menu has been posted by
Xt on behalf of one of the widget sets. */
static int next_menubar_widget_id;
-/* For NS and NTGUI, these prototypes are defined in keyboard.h. */
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-extern widget_value *xmalloc_widget_value P_ ((void));
-extern widget_value *digest_single_submenu P_ ((int, int, int));
-#endif
-
-/* This is set nonzero after the user activates the menu bar, and set
- to zero again after the menu bars are redisplayed by prepare_menu_bar.
- While it is nonzero, all calls to set_frame_menubar go deep.
-
- I don't understand why this is needed, but it does seem to be
- needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
-
-int pending_menu_activation;
\f
#ifdef USE_X_TOOLKIT
/* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
static struct frame *
-menubar_id_to_frame (id)
- LWLIB_ID id;
+menubar_id_to_frame (LWLIB_ID id)
{
Lisp_Object tail, frame;
FRAME_PTR f;
for the window where the mouse is in. This could be the menu bar,
the scroll bar or the edit window. Fx_popup_menu needs to be
sure it is the edit window. */
-static void
-mouse_position_for_popup (f, x, y)
- FRAME_PTR f;
- int *x;
- int *y;
+void
+mouse_position_for_popup (FRAME_PTR f, int *x, int *y)
{
Window root, dummy_window;
int dummy;
#endif /* HAVE_X_WINDOWS */
-DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
- doc: /* Pop up a deck-of-cards menu and return user's selection.
-POSITION is a position specification. This is either a mouse button event
-or a list ((XOFFSET YOFFSET) WINDOW)
-where XOFFSET and YOFFSET are positions in pixels from the top left
-corner of WINDOW. (WINDOW may be a window or a frame object.)
-This controls the position of the top left of the menu as a whole.
-If POSITION is t, it means to use the current mouse position.
-
-MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
-The menu items come from key bindings that have a menu string as well as
-a definition; actually, the "definition" in such a key binding looks like
-\(STRING . REAL-DEFINITION). To give the menu a title, put a string into
-the keymap as a top-level element.
-
-If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
-Otherwise, REAL-DEFINITION should be a valid key binding definition.
-
-You can also use a list of keymaps as MENU.
- Then each keymap makes a separate pane.
-
-When MENU is a keymap or a list of keymaps, the return value is the
-list of events corresponding to the user's choice. Note that
-`x-popup-menu' does not actually execute the command bound to that
-sequence of events.
-
-Alternatively, you can specify a menu of multiple panes
- with a list of the form (TITLE PANE1 PANE2...),
-where each pane is a list of form (TITLE ITEM1 ITEM2...).
-Each ITEM is normally a cons cell (STRING . VALUE);
-but a string can appear as an item--that makes a nonselectable line
-in the menu.
-With this form of menu, the return value is VALUE from the chosen item.
-
-If POSITION is nil, don't display the menu at all, just precalculate the
-cached information about equivalent key sequences.
-
-If the user gets rid of the menu without making a valid choice, for
-instance by clicking the mouse away from a valid choice or by typing
-keyboard input, then this normally results in a quit and
-`x-popup-menu' does not return. But if POSITION is a mouse button
-event (indicating that the user invoked the menu with the mouse) then
-no quit occurs and `x-popup-menu' returns nil. */)
- (position, menu)
- Lisp_Object position, menu;
-{
- Lisp_Object keymap, tem;
- int xpos = 0, ypos = 0;
- Lisp_Object title;
- char *error_name = NULL;
- Lisp_Object selection = Qnil;
- FRAME_PTR f = NULL;
- Lisp_Object x, y, window;
- int keymaps = 0;
- int for_click = 0;
- int specpdl_count = SPECPDL_INDEX ();
- struct gcpro gcpro1;
-
-#ifdef HAVE_MENUS
- if (! NILP (position))
- {
- int get_current_pos_p = 0;
- check_x ();
-
- /* Decode the first argument: find the window and the coordinates. */
- if (EQ (position, Qt)
- || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
- || EQ (XCAR (position), Qtool_bar))))
- {
- get_current_pos_p = 1;
- }
- else
- {
- tem = Fcar (position);
- if (CONSP (tem))
- {
- window = Fcar (Fcdr (position));
- x = XCAR (tem);
- y = Fcar (XCDR (tem));
- }
- else
- {
- for_click = 1;
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
- x = Fcar (tem);
- y = Fcdr (tem);
- }
-
- /* If a click happens in an external tool bar or a detached
- tool bar, x and y is NIL. In that case, use the current
- mouse position. This happens for the help button in the
- tool bar. Ideally popup-menu should pass NIL to
- this function, but it doesn't. */
- if (NILP (x) && NILP (y))
- get_current_pos_p = 1;
- }
-
- if (get_current_pos_p)
- {
- /* Use the mouse's current position. */
- FRAME_PTR new_f = SELECTED_FRAME ();
-#ifdef HAVE_X_WINDOWS
- /* Can't use mouse_position_hook for X since it returns
- coordinates relative to the window the mouse is in,
- we need coordinates relative to the edit widget always. */
- if (new_f != 0)
- {
- int cur_x, cur_y;
-
- mouse_position_for_popup (new_f, &cur_x, &cur_y);
- /* cur_x/y may be negative, so use make_number. */
- x = make_number (cur_x);
- y = make_number (cur_y);
- }
-
-#else /* not HAVE_X_WINDOWS */
- Lisp_Object bar_window;
- enum scroll_bar_part part;
- unsigned long time;
- void (*mouse_position_hook) P_ ((struct frame **, int,
- Lisp_Object *,
- enum scroll_bar_part *,
- Lisp_Object *,
- Lisp_Object *,
- unsigned long *)) =
- new_f->terminal->mouse_position_hook;
-
- if (mouse_position_hook)
- (*mouse_position_hook) (&new_f, 1, &bar_window,
- &part, &x, &y, &time);
-#endif /* not HAVE_X_WINDOWS */
-
- if (new_f != 0)
- XSETFRAME (window, new_f);
- else
- {
- window = selected_window;
- XSETFASTINT (x, 0);
- XSETFASTINT (y, 0);
- }
- }
-
- CHECK_NUMBER (x);
- CHECK_NUMBER (y);
-
- /* Decode where to put the menu. */
-
- if (FRAMEP (window))
- {
- f = XFRAME (window);
- xpos = 0;
- ypos = 0;
- }
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-
- xpos = WINDOW_LEFT_EDGE_X (XWINDOW (window));
- ypos = WINDOW_TOP_EDGE_Y (XWINDOW (window));
- }
- else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window);
-
- xpos += XINT (x);
- ypos += XINT (y);
-
- if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
- error ("Can not put X menu on this terminal");
-
- XSETFRAME (Vmenu_updating_frame, f);
- }
- else
- Vmenu_updating_frame = Qnil;
-#endif /* HAVE_MENUS */
-
- record_unwind_protect (unuse_menu_items, Qnil);
- title = Qnil;
- GCPRO1 (title);
-
- /* Decode the menu items from what was specified. */
-
- keymap = get_keymap (menu, 0, 0);
- if (CONSP (keymap))
- {
- /* We were given a keymap. Extract menu info from the keymap. */
- Lisp_Object prompt;
-
- /* Extract the detailed info to make one pane. */
- keymap_panes (&menu, 1, NILP (position));
-
- /* Search for a string appearing directly as an element of the keymap.
- That string is the title of the menu. */
- prompt = Fkeymap_prompt (keymap);
- if (NILP (title) && !NILP (prompt))
- title = prompt;
-
- /* Make that be the pane title of the first pane. */
- if (!NILP (prompt) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
-
- keymaps = 1;
- }
- else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
- {
- /* We were given a list of keymaps. */
- int nmaps = XFASTINT (Flength (menu));
- Lisp_Object *maps
- = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
- int i;
-
- title = Qnil;
-
- /* The first keymap that has a prompt string
- supplies the menu title. */
- for (tem = menu, i = 0; CONSP (tem); tem = XCDR (tem))
- {
- Lisp_Object prompt;
-
- maps[i++] = keymap = get_keymap (XCAR (tem), 1, 0);
-
- prompt = Fkeymap_prompt (keymap);
- if (NILP (title) && !NILP (prompt))
- title = prompt;
- }
-
- /* Extract the detailed info to make one pane. */
- keymap_panes (maps, nmaps, NILP (position));
-
- /* Make the title be the pane title of the first pane. */
- if (!NILP (title) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
-
- keymaps = 1;
- }
- else
- {
- /* We were given an old-fashioned menu. */
- title = Fcar (menu);
- CHECK_STRING (title);
-
- list_of_panes (Fcdr (menu));
-
- keymaps = 0;
- }
-
- unbind_to (specpdl_count, Qnil);
-
- if (NILP (position))
- {
- discard_menu_items ();
- UNGCPRO;
- return Qnil;
- }
-
-#ifdef HAVE_MENUS
- /* Display them in a menu. */
- BLOCK_INPUT;
-
- selection = xmenu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name);
- UNBLOCK_INPUT;
-
- discard_menu_items ();
-
- UNGCPRO;
-#endif /* HAVE_MENUS */
-
- if (error_name) error (error_name);
- return selection;
-}
-
#ifdef HAVE_MENUS
DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
If the user gets rid of the dialog box without making a valid choice,
for instance using the window manager, then this produces a quit and
`x-popup-dialog' does not return. */)
- (position, contents, header)
- Lisp_Object position, contents, header;
+ (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
{
FRAME_PTR f = NULL;
Lisp_Object window;
if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
error ("Can not put X dialog on this terminal");
+ /* Force a redisplay before showing the dialog. If a frame is created
+ just before showing the dialog, its contents may not have been fully
+ drawn, as this depends on timing of events from the X server. Redisplay
+ is not done when a dialog is shown. If redisplay could be done in the
+ X event loop (i.e. the X event loop does not run in a signal handler)
+ this would not be needed.
+
+ Do this before creating the widget value that points to Lisp
+ string contents, because Fredisplay may GC and relocate them. */
+ Fredisplay (Qt);
+
#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
/* Display a menu with these alternatives
in the middle of frame F. */
#else
{
Lisp_Object title;
- char *error_name;
+ const char *error_name;
Lisp_Object selection;
int specpdl_count = SPECPDL_INDEX ();
/* Set menu_items_inuse so no other popup menu or dialog is created. */
void
-x_menu_set_in_use (in_use)
- int in_use;
+x_menu_set_in_use (int in_use)
{
menu_items_inuse = in_use ? Qt : Qnil;
popup_activated_flag = in_use;
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
#endif
)
{
- EMACS_TIME next_time = timer_check (1);
+ EMACS_TIME next_time = timer_check (1), *ntp;
long secs = EMACS_SECS (next_time);
long usecs = EMACS_USECS (next_time);
SELECT_TYPE read_fds;
int fd = ConnectionNumber (dpyinfo->display);
FD_SET (fd, &read_fds);
if (fd > n) n = fd;
+ XFlush (dpyinfo->display);
}
- 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);
- }
+ if (secs < 0 && usecs < 0)
+ ntp = 0;
+ else
+ ntp = &next_time;
- select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, &next_time);
+ select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
}
}
#endif /* ! MSDOS */
with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
static void
-popup_get_selection (initial_event, dpyinfo, id, do_timers)
- XEvent *initial_event;
- struct x_display_info *dpyinfo;
- LWLIB_ID id;
- int do_timers;
+popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, LWLIB_ID id, int do_timers)
{
XEvent event;
escape key. If FRAME has no menu bar this function does nothing.
If FRAME is nil or not given, use the selected frame. */)
- (frame)
- Lisp_Object frame;
+ (Lisp_Object frame)
{
XEvent ev;
FRAME_PTR f = check_x_frame (frame);
escape key. If FRAME has no menu bar this function does nothing.
If FRAME is nil or not given, use the selected frame. */)
- (frame)
- Lisp_Object frame;
+ (Lisp_Object frame)
{
GtkWidget *menubar;
FRAME_PTR f;
Used for popup menus and dialogs. */
static void
-popup_widget_loop (do_timers, widget)
- int do_timers;
- GtkWidget *widget;
+popup_widget_loop (int do_timers, GtkWidget *widget)
{
++popup_activated_flag;
execute Lisp code. */
void
-x_activate_menubar (f)
- FRAME_PTR f;
+x_activate_menubar (FRAME_PTR f)
{
if (! FRAME_X_P (f))
abort ();
set_frame_menubar (f, 0, 1);
BLOCK_INPUT;
+ popup_activated_flag = 1;
#ifdef USE_GTK
XPutBackEvent (f->output_data.x->display_info->display,
f->output_data.x->saved_menu_event);
- popup_activated_flag = 1;
#else
XtDispatchEvent (f->output_data.x->saved_menu_event);
#endif
UNBLOCK_INPUT;
-#ifdef USE_MOTIF
- if (f->output_data.x->saved_menu_event->type == ButtonRelease)
- pending_menu_activation = 1;
-#endif
/* Ignore this if we get it a second time. */
f->output_data.x->saved_menu_event->type = 0;
#ifndef USE_GTK
static void
-popup_activate_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
+popup_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
{
popup_activated_flag = 1;
#ifdef USE_X_TOOLKIT
#ifdef USE_GTK
static void
-popup_deactivate_callback (widget, client_data)
- GtkWidget *widget;
- gpointer client_data;
+popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
{
popup_activated_flag = 0;
}
#else
static void
-popup_deactivate_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
+popup_deactivate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
{
popup_activated_flag = 0;
}
for that widget.
F is the frame if known, or NULL if not known. */
static void
-show_help_event (f, widget, help)
- FRAME_PTR f;
- xt_or_gtk_widget widget;
- Lisp_Object help;
+show_help_event (FRAME_PTR f, xt_or_gtk_widget widget, Lisp_Object help)
{
Lisp_Object frame;
#ifdef USE_GTK
void
-menu_highlight_callback (widget, call_data)
- GtkWidget *widget;
- gpointer call_data;
+menu_highlight_callback (GtkWidget *widget, gpointer call_data)
{
xg_menu_item_cb_data *cb_data;
Lisp_Object help;
}
#else
void
-menu_highlight_callback (widget, id, call_data)
- Widget widget;
- LWLIB_ID id;
- void *call_data;
+menu_highlight_callback (Widget widget, LWLIB_ID id, void *call_data)
{
struct frame *f;
Lisp_Object help;
Figure out what the user chose
and put the appropriate events into the keyboard buffer. */
static void
-menubar_selection_callback (widget, client_data)
- GtkWidget *widget;
- gpointer client_data;
+menubar_selection_callback (GtkWidget *widget, gpointer client_data)
{
xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
Figure out what the user chose
and put the appropriate events into the keyboard buffer. */
static void
-menubar_selection_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
+menubar_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
{
FRAME_PTR f;
changed. Value is non-zero if widgets were updated. */
static int
-update_frame_menubar (f)
- FRAME_PTR f;
+update_frame_menubar (FRAME_PTR f)
{
#ifdef USE_GTK
return xg_update_frame_menubar (f);
return 1;
}
+#ifdef USE_LUCID
+static void
+apply_systemfont_to_dialog (Widget w)
+{
+ const char *fn = xsettings_get_system_normal_font ();
+ if (fn)
+ {
+ XrmDatabase db = XtDatabase (XtDisplay (w));
+ if (db)
+ XrmPutStringResource (&db, "*dialog.faceName", fn);
+ }
+}
+
+static void
+apply_systemfont_to_menu (Widget w)
+{
+ const char *fn = xsettings_get_system_normal_font ();
+ int defflt;
+
+ if (!fn) return;
+
+ if (XtIsShell (w)) /* popup menu */
+ {
+ Widget *childs = NULL;
+
+ XtVaGetValues (w, XtNchildren, &childs, NULL);
+ if (*childs) w = *childs;
+ }
+
+ /* Only use system font if the default is used for the menu. */
+ XtVaGetValues (w, XtNdefaultFace, &defflt, NULL);
+ if (defflt)
+ XtVaSetValues (w, XtNfaceName, fn, NULL);
+}
+#endif
+
/* Set the contents of the menubar widgets of frame F.
The argument FIRST_TIME is currently ignored;
it is set the first time this is called, from initialize_frame_menubar. */
void
-set_frame_menubar (f, first_time, deep_p)
- FRAME_PTR f;
- int first_time;
- int deep_p;
+set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
{
xt_or_gtk_widget menubar_widget;
#ifdef USE_X_TOOLKIT
if (! menubar_widget)
deep_p = 1;
- else if (pending_menu_activation && !deep_p)
- deep_p = 1;
/* Make the first call for any given frame always go deep. */
else if (!f->output_data.x->saved_menu_event && !deep_p)
{
/* Save the frame's previous menu bar contents data. */
if (previous_menu_items_used)
- bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
- previous_menu_items_used * sizeof (Lisp_Object));
+ memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+ previous_menu_items_used * sizeof (Lisp_Object));
/* Fill in menu_items with the current menu bar contents.
This can evaluate Lisp code. */
string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
- wv->name = (char *) SDATA (string);
+ wv->name = SSDATA (string);
update_submenu_strings (wv->contents);
wv = wv->next;
}
break;
wv = xmalloc_widget_value ();
- wv->name = (char *) SDATA (string);
+ wv->name = SSDATA (string);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
/* Make menu pop down on C-g. */
XtOverrideTranslations (menubar_widget, override);
+#ifdef USE_LUCID
+ apply_systemfont_to_menu (menubar_widget);
+#endif
}
{
- int menubar_size
+ int menubar_size;
+ if (f->output_data.x->menubar_widget)
+ XtRealizeWidget (f->output_data.x->menubar_widget);
+
+ menubar_size
= (f->output_data.x->menubar_widget
? (f->output_data.x->menubar_widget->core.height
+ f->output_data.x->menubar_widget->core.border_width)
: 0);
-#if 0 /* Experimentally, we now get the right results
- for -geometry -0-0 without this. 24 Aug 96, rms. */
+#if 1 /* Experimentally, we now get the right results
+ for -geometry -0-0 without this. 24 Aug 96, rms.
+ Maybe so, but the menu bar size is missing the pixels so the
+ WM size hints are off by these pixels. Jan D, oct 2009. */
#ifdef USE_LUCID
if (FRAME_EXTERNAL_MENU_BAR (f))
{
menubar_size += ibw;
}
#endif /* USE_LUCID */
-#endif /* 0 */
+#endif /* 1 */
f->output_data.x->menubar_height = menubar_size;
}
is visible. */
void
-initialize_frame_menubar (f)
- FRAME_PTR f;
+initialize_frame_menubar (FRAME_PTR f)
{
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
#ifndef USE_GTK
void
-free_frame_menubar (f)
- FRAME_PTR f;
+free_frame_menubar (FRAME_PTR f)
{
Widget menubar_widget;
lw_destroy_all_widgets ((LWLIB_ID) f->output_data.x->id);
f->output_data.x->menubar_widget = NULL;
-#ifdef USE_MOTIF
if (f->output_data.x->widget)
{
+#ifdef USE_MOTIF
XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
if (x1 == 0 && y1 == 0)
XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
- }
#endif
-
+ x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+ }
UNBLOCK_INPUT;
}
}
Here only X and Y are used. */
static void
-menu_position_func (menu, x, y, push_in, user_data)
- GtkMenu *menu;
- gint *x;
- gint *y;
- gboolean *push_in;
- gpointer user_data;
+menu_position_func (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
{
struct next_popup_x_y* data = (struct next_popup_x_y*)user_data;
GtkRequisition req;
- int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width;
- int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height;
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (data->f);
+ int disp_width = x_display_pixel_width (dpyinfo);
+ int disp_height = x_display_pixel_height (dpyinfo);
*x = data->x;
*y = data->y;
}
static void
-popup_selection_callback (widget, client_data)
- GtkWidget *widget;
- gpointer client_data;
+popup_selection_callback (GtkWidget *widget, gpointer client_data)
{
xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
}
static Lisp_Object
-pop_down_menu (arg)
- Lisp_Object arg;
+pop_down_menu (Lisp_Object arg)
{
struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
menu pops down.
menu_item_selection will be set to the selection. */
static void
-create_and_show_popup_menu (f, first_wv, x, y, for_click)
- FRAME_PTR f;
- widget_value *first_wv;
- int x;
- int y;
- int for_click;
+create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y, int for_click, EMACS_UINT timestamp)
{
int i;
GtkWidget *menu;
/* Display the menu. */
gtk_widget_show_all (menu);
- gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
+
+ gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i,
+ timestamp > 0 ? timestamp : gtk_get_current_event_time());
record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
- if (GTK_WIDGET_MAPPED (menu))
+ if (gtk_widget_get_mapped (menu))
{
/* Set this to one. popup_widget_loop increases it by one, so it becomes
two. show_help_echo uses this to detect popup menus. */
LWLIB_ID widget_id_tick;
static void
-popup_selection_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
+popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
{
menu_item_selection = (Lisp_Object *) client_data;
}
as a Lisp object as (HIGHPART . LOWPART). */
static Lisp_Object
-pop_down_menu (arg)
- Lisp_Object arg;
+pop_down_menu (Lisp_Object arg)
{
LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
| XINT (XCDR (arg)));
menu pops down.
menu_item_selection will be set to the selection. */
static void
-create_and_show_popup_menu (f, first_wv, x, y, for_click)
- FRAME_PTR f;
- widget_value *first_wv;
- int x;
- int y;
- int for_click;
+create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
+ int x, int y, int for_click, EMACS_UINT timestamp)
{
int i;
Arg av[2];
popup_deactivate_callback,
menu_highlight_callback);
+#ifdef USE_LUCID
+ apply_systemfont_to_menu (menu);
+#endif
+
dummy.type = ButtonPress;
dummy.serial = 0;
dummy.send_event = 0;
#endif /* not USE_GTK */
-static Lisp_Object
-xmenu_show (f, x, y, for_click, keymaps, title, error)
- FRAME_PTR f;
- int x;
- int y;
- int for_click;
- int keymaps;
- Lisp_Object title;
- char **error;
+Lisp_Object
+xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
+ Lisp_Object title, const char **error, EMACS_UINT timestamp)
{
int i;
widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
- char *pane_string;
+ const char *pane_string;
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
}
#endif
pane_string = (NILP (pane_name)
- ? "" : (char *) SDATA (pane_name));
+ ? "" : SSDATA (pane_name));
/* If there is just one top-level pane, put all its items directly
under the top-level menu. */
if (menu_items_n_panes == 1)
prev_wv->next = wv;
else
save_wv->contents = wv;
- wv->name = (char *) SDATA (item_name);
+ wv->name = SSDATA (item_name);
if (!NILP (descrip))
- wv->key = (char *) SDATA (descrip);
+ wv->key = SSDATA (descrip);
wv->value = 0;
/* If this item has a null value,
make the call_data null so that it won't display a box
title = ENCODE_MENU_STRING (title);
#endif
- wv_title->name = (char *) SDATA (title);
+ wv_title->name = SSDATA (title);
wv_title->enabled = TRUE;
wv_title->button_type = BUTTON_TYPE_NONE;
wv_title->help = Qnil;
menu_item_selection = 0;
/* Actually create and show the menu until popped down. */
- create_and_show_popup_menu (f, first_wv, x, y, for_click);
+ 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);
\f
#ifdef USE_GTK
static void
-dialog_selection_callback (widget, client_data)
- GtkWidget *widget;
- gpointer client_data;
+dialog_selection_callback (GtkWidget *widget, gpointer client_data)
{
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
dialog pops down.
menu_item_selection will be set to the selection. */
static void
-create_and_show_dialog (f, first_wv)
- FRAME_PTR f;
- widget_value *first_wv;
+create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
{
GtkWidget *menu;
#else /* not USE_GTK */
static void
-dialog_selection_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
+dialog_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
{
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
dialog pops down.
menu_item_selection will be set to the selection. */
static void
-create_and_show_dialog (f, first_wv)
- FRAME_PTR f;
- widget_value *first_wv;
+create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
{
LWLIB_ID dialog_id;
abort();
dialog_id = widget_id_tick++;
+#ifdef USE_LUCID
+ apply_systemfont_to_dialog (f->output_data.x->widget);
+#endif
lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
f->output_data.x->widget, 1, 0,
dialog_selection_callback, 0, 0);
lw_modify_all_widgets (dialog_id, first_wv->contents, True);
-
/* Display the dialog box. */
lw_pop_up_all_widgets (dialog_id);
popup_activated_flag = 1;
#endif /* not USE_GTK */
-static char * button_names [] = {
+static const char * button_names [] = {
"button1", "button2", "button3", "button4", "button5",
"button6", "button7", "button8", "button9", "button10" };
static Lisp_Object
-xdialog_show (f, keymaps, title, header, error_name)
- FRAME_PTR f;
- int keymaps;
- Lisp_Object title, header;
- char **error_name;
+xdialog_show (FRAME_PTR f,
+ int keymaps,
+ Lisp_Object title,
+ Lisp_Object header,
+ const char **error_name)
{
int i, nb_buttons=0;
char dialog_name[6];
representing the text label and buttons. */
{
Lisp_Object pane_name, prefix;
- char *pane_string;
+ const char *pane_string;
pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
pane_string = (NILP (pane_name)
- ? "" : (char *) SDATA (pane_name));
+ ? "" : SSDATA (pane_name));
prev_wv = xmalloc_widget_value ();
prev_wv->value = pane_string;
if (keymaps && !NILP (prefix))
prev_wv->next = wv;
wv->name = (char *) button_names[nb_buttons];
if (!NILP (descrip))
- wv->key = (char *) SDATA (descrip);
- wv->value = (char *) SDATA (item_name);
+ wv->key = SSDATA (descrip);
+ wv->value = SSDATA (item_name);
wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
wv->enabled = !NILP (enable);
wv->help = Qnil;
/* No selection has been chosen yet. */
menu_item_selection = 0;
- /* Force a redisplay before showing the dialog. If a frame is created
- just before showing the dialog, its contents may not have been fully
- drawn, as this depends on timing of events from the X server. Redisplay
- is not done when a dialog is shown. If redisplay could be done in the
- X event loop (i.e. the X event loop does not run in a signal handler)
- this would not be needed. */
- Fredisplay (Qt);
-
/* Actually create and show the dialog. */
create_and_show_dialog (f, first_wv);
keyboard events. */
static void
-menu_help_callback (help_string, pane, item)
- char *help_string;
- int pane, item;
+menu_help_callback (char *help_string, int pane, int item)
{
- extern Lisp_Object Qmenu_item;
Lisp_Object *first_item;
Lisp_Object pane_name;
Lisp_Object menu_object;
}
static Lisp_Object
-pop_down_menu (arg)
- Lisp_Object arg;
+pop_down_menu (Lisp_Object arg)
{
struct Lisp_Save_Value *p1 = XSAVE_VALUE (Fcar (arg));
struct Lisp_Save_Value *p2 = XSAVE_VALUE (Fcdr (arg));
}
-static Lisp_Object
-xmenu_show (f, x, y, for_click, keymaps, title, error)
- FRAME_PTR f;
- int x, y;
- int for_click;
- int keymaps;
- Lisp_Object title;
- char **error;
+Lisp_Object
+xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
+ Lisp_Object title, const char **error, EMACS_UINT timestamp)
{
Window root;
XMenu *menu;
pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
pane_string = (NILP (pane_name)
- ? "" : (char *) SDATA (pane_name));
+ ? "" : SSDATA (pane_name));
if (keymaps && !NILP (prefix))
pane_string++;
item_data
= (unsigned char *) alloca (maxwidth
+ SBYTES (descrip) + 1);
- bcopy (SDATA (item_name), item_data,
- SBYTES (item_name));
+ memcpy (item_data, SDATA (item_name), SBYTES (item_name));
for (j = SCHARS (item_name); j < maxwidth; j++)
item_data[j] = ' ';
- bcopy (SDATA (descrip), item_data + j,
- SBYTES (descrip));
+ memcpy (item_data + j, SDATA (descrip), SBYTES (descrip));
item_data[j + SBYTES (descrip)] = 0;
}
else
y -= (uly + height) - dispheight;
uly = dispheight - height;
}
+#ifndef HAVE_X_WINDOWS
+ if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1)
+ {
+ /* Move the menu away of the echo area, to avoid overwriting the
+ menu with help echo messages or vice versa. */
+ if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
+ {
+ y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
+ uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
+ }
+ else
+ {
+ y--;
+ uly--;
+ }
+ }
+#endif
if (ulx < 0) x -= ulx;
if (uly < 0) y -= uly;
#endif /* HAVE_MENUS */
-/* Detect if a dialog or menu has been posted. */
+#ifndef MSDOS
+/* Detect if a dialog or menu has been posted. MSDOS has its own
+ implementation on msdos.c. */
int
-popup_activated ()
+popup_activated (void)
{
return popup_activated_flag;
}
+#endif /* not MSDOS */
/* The following is used by delayed window autoselection. */
DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
doc: /* Return t if a menu or popup dialog is active. */)
- ()
+ (void)
{
#ifdef HAVE_MENUS
return (popup_activated ()) ? Qt : Qnil;
}
\f
void
-syms_of_xmenu ()
+syms_of_xmenu (void)
{
- Qdebug_on_next_call = intern ("debug-on-next-call");
+ Qdebug_on_next_call = intern_c_string ("debug-on-next-call");
staticpro (&Qdebug_on_next_call);
#ifdef USE_X_TOOLKIT
next_menubar_widget_id = 1;
#endif
- defsubr (&Sx_popup_menu);
defsubr (&Smenu_or_popup_active_p);
#if defined (USE_GTK) || defined (USE_X_TOOLKIT)
defsubr (&Sx_menu_bar_open_internal);
- Ffset (intern ("accelerate-menu"),
- intern (Sx_menu_bar_open_internal.symbol_name));
+ Ffset (intern_c_string ("accelerate-menu"),
+ intern_c_string (Sx_menu_bar_open_internal.symbol_name));
#endif
#ifdef HAVE_MENUS
defsubr (&Sx_popup_dialog);
#endif
}
-
-/* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
- (do not change this comment) */