diff options
| author | Eli Zaretskii | 2013-10-05 18:42:17 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2013-10-05 18:42:17 +0300 |
| commit | 63dfbda7df0df5b054f8f95b79673672c267de54 (patch) | |
| tree | 47440f83d3d0d60714a5987cd30f715718e36a78 /src | |
| parent | 6270e29ea3692882ce1ceee9be222b59b993c0e6 (diff) | |
| download | emacs-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.c | 92 | ||||
| -rw-r--r-- | src/menu.c | 54 |
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. */ | ||
| 5413 | static bool | ||
| 5414 | toolkit_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 | ||
| 1038 | DEFUN ("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. | ||
| 1041 | X and Y are frame-relative pixel coordinates, assumed to define | ||
| 1042 | a location within the menu bar. | ||
| 1043 | If FRAME is nil or omitted, it defaults to the selected frame. | ||
| 1044 | |||
| 1045 | Value is the symbol of the menu at X/Y, or nil if the specified | ||
| 1046 | coordinates are not within the FRAME's menu bar. The symbol can | ||
| 1047 | be used to look up the menu like this: | ||
| 1048 | |||
| 1049 | (lookup-key global-map [menu-bar SYMBOL]) | ||
| 1050 | |||
| 1051 | This function can return non-nil only on a text-terminal frame | ||
| 1052 | or on an X frame that doesn't use any GUI toolkit. Otherwise, | ||
| 1053 | Emacs does not manage the menu bar and cannot convert coordinates | ||
| 1054 | into 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 | |||
| 1038 | DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0, | 1091 | DEFUN ("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. |
| 1040 | POSITION is a position specification. This is either a mouse button event | 1093 | POSITION 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 | } |