aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-10-05 18:42:17 +0300
committerEli Zaretskii2013-10-05 18:42:17 +0300
commit63dfbda7df0df5b054f8f95b79673672c267de54 (patch)
tree47440f83d3d0d60714a5987cd30f715718e36a78 /src
parent6270e29ea3692882ce1ceee9be222b59b993c0e6 (diff)
downloademacs-63dfbda7df0df5b054f8f95b79673672c267de54.tar.gz
emacs-63dfbda7df0df5b054f8f95b79673672c267de54.zip
Fix menu drop by mouse click; new primitive menu-bar-menu-at-x-y.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c92
-rw-r--r--src/menu.c54
2 files changed, 107 insertions, 39 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index a595742ace8..6fd1e9b9c67 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5406,6 +5406,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
5406 extra_info)))); 5406 extra_info))));
5407} 5407}
5408 5408
5409/* Return non-zero if F is a GUI frame that uses some toolkit-managed
5410 menu bar. This really means that Emacs draws and manages the menu
5411 bar as part of its normal display, and therefore can compute its
5412 geometry. */
5413static bool
5414toolkit_menubar_in_use (struct frame *f)
5415{
5416#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
5417 return !(!FRAME_WINDOW_P (f));
5418#else
5419 return false;
5420#endif
5421}
5422
5409/* Given a struct input_event, build the lisp event which represents 5423/* Given a struct input_event, build the lisp event which represents
5410 it. If EVENT is 0, build a mouse movement event from the mouse 5424 it. If EVENT is 0, build a mouse movement event from the mouse
5411 movement buffer, which should have a movement event in it. 5425 movement buffer, which should have a movement event in it.
@@ -5557,64 +5571,64 @@ make_lispy_event (struct input_event *event)
5557 if (event->kind == MOUSE_CLICK_EVENT) 5571 if (event->kind == MOUSE_CLICK_EVENT)
5558 { 5572 {
5559 struct frame *f = XFRAME (event->frame_or_window); 5573 struct frame *f = XFRAME (event->frame_or_window);
5560#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5561 int row, column; 5574 int row, column;
5562#endif
5563 5575
5564 /* Ignore mouse events that were made on frame that 5576 /* Ignore mouse events that were made on frame that
5565 have been deleted. */ 5577 have been deleted. */
5566 if (! FRAME_LIVE_P (f)) 5578 if (! FRAME_LIVE_P (f))
5567 return Qnil; 5579 return Qnil;
5568 5580
5569#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5570 /* EVENT->x and EVENT->y are frame-relative pixel 5581 /* EVENT->x and EVENT->y are frame-relative pixel
5571 coordinates at this place. Under old redisplay, COLUMN 5582 coordinates at this place. Under old redisplay, COLUMN
5572 and ROW are set to frame relative glyph coordinates 5583 and ROW are set to frame relative glyph coordinates
5573 which are then used to determine whether this click is 5584 which are then used to determine whether this click is
5574 in a menu (non-toolkit version). */ 5585 in a menu (non-toolkit version). */
5575 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), 5586 if (!toolkit_menubar_in_use (f))
5576 &column, &row, NULL, 1);
5577
5578 /* In the non-toolkit version, clicks on the menu bar
5579 are ordinary button events in the event buffer.
5580 Distinguish them, and invoke the menu.
5581
5582 (In the toolkit version, the toolkit handles the menu bar
5583 and Emacs doesn't know about it until after the user
5584 makes a selection.) */
5585 if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
5586 && (event->modifiers & down_modifier))
5587 { 5587 {
5588 Lisp_Object items, item; 5588 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
5589 5589 &column, &row, NULL, 1);
5590 /* Find the menu bar item under `column'. */ 5590
5591 item = Qnil; 5591 /* In the non-toolkit version, clicks on the menu bar
5592 items = FRAME_MENU_BAR_ITEMS (f); 5592 are ordinary button events in the event buffer.
5593 for (i = 0; i < ASIZE (items); i += 4) 5593 Distinguish them, and invoke the menu.
5594
5595 (In the toolkit version, the toolkit handles the
5596 menu bar and Emacs doesn't know about it until
5597 after the user makes a selection.) */
5598 if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
5599 && (event->modifiers & down_modifier))
5594 { 5600 {
5595 Lisp_Object pos, string; 5601 Lisp_Object items, item;
5596 string = AREF (items, i + 1); 5602
5597 pos = AREF (items, i + 3); 5603 /* Find the menu bar item under `column'. */
5598 if (NILP (string)) 5604 item = Qnil;
5599 break; 5605 items = FRAME_MENU_BAR_ITEMS (f);
5600 if (column >= XINT (pos) 5606 for (i = 0; i < ASIZE (items); i += 4)
5601 && column < XINT (pos) + SCHARS (string))
5602 { 5607 {
5603 item = AREF (items, i); 5608 Lisp_Object pos, string;
5604 break; 5609 string = AREF (items, i + 1);
5610 pos = AREF (items, i + 3);
5611 if (NILP (string))
5612 break;
5613 if (column >= XINT (pos)
5614 && column < XINT (pos) + SCHARS (string))
5615 {
5616 item = AREF (items, i);
5617 break;
5618 }
5605 } 5619 }
5606 }
5607 5620
5608 /* ELisp manual 2.4b says (x y) are window relative but 5621 /* ELisp manual 2.4b says (x y) are window
5609 code says they are frame-relative. */ 5622 relative but code says they are
5610 position = list4 (event->frame_or_window, 5623 frame-relative. */
5611 Qmenu_bar, 5624 position = list4 (event->frame_or_window,
5612 Fcons (event->x, event->y), 5625 Qmenu_bar,
5613 make_number (event->timestamp)); 5626 Fcons (event->x, event->y),
5627 make_number (event->timestamp));
5614 5628
5615 return list2 (item, position); 5629 return list2 (item, position);
5630 }
5616 } 5631 }
5617#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
5618 5632
5619 position = make_lispy_position (f, event->x, event->y, 5633 position = make_lispy_position (f, event->x, event->y,
5620 event->timestamp); 5634 event->timestamp);
diff --git a/src/menu.c b/src/menu.c
index 3f7aa0c33c3..690955ca0ad 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1035,6 +1035,59 @@ find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data
1035} 1035}
1036#endif /* HAVE_NS */ 1036#endif /* HAVE_NS */
1037 1037
1038DEFUN ("menu-bar-menu-at-x-y", Fmenu_bar_menu_at_x_y, Smenu_bar_menu_at_x_y,
1039 2, 3, 0,
1040 doc: /* Return the menu-bar menu on FRAME at pixel coordinates X, Y.
1041X and Y are frame-relative pixel coordinates, assumed to define
1042a location within the menu bar.
1043If FRAME is nil or omitted, it defaults to the selected frame.
1044
1045Value is the symbol of the menu at X/Y, or nil if the specified
1046coordinates are not within the FRAME's menu bar. The symbol can
1047be used to look up the menu like this:
1048
1049 (lookup-key global-map [menu-bar SYMBOL])
1050
1051This function can return non-nil only on a text-terminal frame
1052or on an X frame that doesn't use any GUI toolkit. Otherwise,
1053Emacs does not manage the menu bar and cannot convert coordinates
1054into menu items. */)
1055 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1056{
1057 int row, col;
1058 struct frame *f = decode_any_frame (frame);
1059
1060 if (!FRAME_LIVE_P (f))
1061 return Qnil;
1062
1063 pixel_to_glyph_coords (f, XINT (x), XINT (y), &col, &row, NULL, 1);
1064 if (0 <= row && row < FRAME_MENU_BAR_LINES (f))
1065 {
1066 Lisp_Object items, item;
1067 int i;
1068
1069 /* Find the menu bar item under `col'. */
1070 item = Qnil;
1071 items = FRAME_MENU_BAR_ITEMS (f);
1072 for (i = 0; i < ASIZE (items); i += 4)
1073 {
1074 Lisp_Object pos, str;
1075
1076 str = AREF (items, i + 1);
1077 pos = AREF (items, i + 3);
1078 if (NILP (str))
1079 return item;
1080 if (XINT (pos) <= col && col < XINT (pos) + SCHARS (str))
1081 {
1082 item = AREF (items, i);
1083 return item;
1084 }
1085 }
1086 }
1087 return Qnil;
1088}
1089
1090
1038DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0, 1091DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
1039 doc: /* Pop up a deck-of-cards menu and return user's selection. 1092 doc: /* Pop up a deck-of-cards menu and return user's selection.
1040POSITION is a position specification. This is either a mouse button event 1093POSITION is a position specification. This is either a mouse button event
@@ -1527,4 +1580,5 @@ syms_of_menu (void)
1527#ifdef HAVE_MENUS 1580#ifdef HAVE_MENUS
1528 defsubr (&Sx_popup_dialog); 1581 defsubr (&Sx_popup_dialog);
1529#endif 1582#endif
1583 defsubr (&Smenu_bar_menu_at_x_y);
1530} 1584}