aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Djärv2003-01-08 20:06:05 +0000
committerJan Djärv2003-01-08 20:06:05 +0000
commit8b806a8574f8e3a292a36e73dd144b46fb4d07d2 (patch)
tree7a2aa5a4bca5130f66e32f52aff1ee7af4b2a754 /src
parent00e3ab56664fbf759daa5a98e31976e90a8fca8e (diff)
downloademacs-8b806a8574f8e3a292a36e73dd144b46fb4d07d2.tar.gz
emacs-8b806a8574f8e3a292a36e73dd144b46fb4d07d2.zip
(Fx_popup_menu): If popping up at mouse position,
call XQueryPointer to get coordinates. (popup_get_selection): Do not set popup_activated_flag to zero, let popup_deactivate_callback do that. Needed for Motif. Call x_dispatch_event instead of XtDispatchEvent. (xmenu_show): Calculate root coordinate from frame top/left position.
Diffstat (limited to 'src')
-rw-r--r--src/xmenu.c240
1 files changed, 88 insertions, 152 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index 4724b2e7ff4..d4c09edfa5d 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -108,7 +108,6 @@ extern Lisp_Object Qmenu_bar_update_hook;
108 108
109#ifdef USE_X_TOOLKIT 109#ifdef USE_X_TOOLKIT
110extern void set_frame_menubar (); 110extern void set_frame_menubar ();
111extern void process_expose_from_menu ();
112extern XtAppContext Xt_app_con; 111extern XtAppContext Xt_app_con;
113 112
114static Lisp_Object xdialog_show (); 113static Lisp_Object xdialog_show ();
@@ -731,21 +730,44 @@ cached information about equivalent key sequences. */)
731 { 730 {
732 /* Use the mouse's current position. */ 731 /* Use the mouse's current position. */
733 FRAME_PTR new_f = SELECTED_FRAME (); 732 FRAME_PTR new_f = SELECTED_FRAME ();
734 Lisp_Object bar_window; 733 Window root, dummy_window;
735 enum scroll_bar_part part; 734 int cur_x, cur_y, dummy;
736 unsigned long time; 735
737 736 BLOCK_INPUT;
738 if (mouse_position_hook) 737
739 (*mouse_position_hook) (&new_f, 1, &bar_window, 738 XQueryPointer (FRAME_X_DISPLAY (new_f),
740 &part, &x, &y, &time); 739 DefaultRootWindow (FRAME_X_DISPLAY (new_f)),
741 if (new_f != 0) 740
742 XSETFRAME (window, new_f); 741 /* The root window which contains the pointer. */
743 else 742 &root,
744 { 743
745 window = selected_window; 744 /* Window pointer is on, not used */
746 XSETFASTINT (x, 0); 745 &dummy_window,
747 XSETFASTINT (y, 0); 746
748 } 747 /* The position on that root window. */
748 &cur_x, &cur_y,
749
750 /* x/y in dummy_window coordinates, not used. */
751 &dummy, &dummy,
752
753 /* Modifier keys and pointer buttons, about which
754 we don't care. */
755 (unsigned int *) &dummy);
756
757 UNBLOCK_INPUT;
758
759 /* xmenu_show expects window coordinates, not root window
760 coordinates. Translate. */
761 cur_x -= new_f->output_data.x->left_pos
762 + FRAME_OUTER_TO_INNER_DIFF_X (new_f);
763 cur_y -= new_f->output_data.x->top_pos
764 + FRAME_OUTER_TO_INNER_DIFF_Y (new_f);
765
766 /* cur_x/y may be negative, so use make_number. */
767 x = make_number (cur_x);
768 y = make_number (cur_y);
769
770 XSETFRAME (window, new_f);
749 } 771 }
750 else 772 else
751 { 773 {
@@ -1017,21 +1039,6 @@ on the left of the dialog box and all following items on the right.
1017 1039
1018#ifdef USE_X_TOOLKIT 1040#ifdef USE_X_TOOLKIT
1019 1041
1020/* Define a queue to save up for later unreading
1021 all X events that don't pertain to the menu. */
1022struct event_queue
1023 {
1024 XEvent event;
1025 struct event_queue *next;
1026 };
1027
1028/* It is ok that this queue is a static variable,
1029 because init_menu_items won't allow the menu mechanism
1030 to be entered recursively. */
1031static struct event_queue *popup_get_selection_queue;
1032
1033static Lisp_Object popup_get_selection_unwind ();
1034
1035/* Loop in Xt until the menu pulldown or dialog popup has been 1042/* Loop in Xt until the menu pulldown or dialog popup has been
1036 popped down (deactivated). This is used for x-popup-menu 1043 popped down (deactivated). This is used for x-popup-menu
1037 and x-popup-dialog; it is not used for the menu bar. 1044 and x-popup-dialog; it is not used for the menu bar.
@@ -1049,107 +1056,51 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers)
1049 int do_timers; 1056 int do_timers;
1050{ 1057{
1051 XEvent event; 1058 XEvent event;
1052 struct event_queue *queue_tmp;
1053 int count = SPECPDL_INDEX ();
1054
1055 popup_get_selection_queue = NULL;
1056 1059
1057 record_unwind_protect (popup_get_selection_unwind, Qnil); 1060 while (popup_activated_flag)
1061 {
1062 /* If we have no events to run, consider timers. */
1063 if (do_timers && !XtAppPending (Xt_app_con))
1064 timer_check (1);
1058 1065
1059 if (initial_event) 1066 if (initial_event)
1060 event = *initial_event; 1067 {
1061 else 1068 event = *initial_event;
1062 XtAppNextEvent (Xt_app_con, &event); 1069 initial_event = 0;
1070 }
1071 else
1072 XtAppNextEvent (Xt_app_con, &event);
1063 1073
1064 while (1)
1065 {
1066 /* Handle expose events for editor frames right away. */
1067 if (event.type == Expose)
1068 process_expose_from_menu (event);
1069 /* Make sure we don't consider buttons grabbed after menu goes. 1074 /* Make sure we don't consider buttons grabbed after menu goes.
1070 And make sure to deactivate for any ButtonRelease, 1075 And make sure to deactivate for any ButtonRelease,
1071 even if XtDispatchEvent doesn't do that. */ 1076 even if XtDispatchEvent doesn't do that. */
1072 else if (event.type == ButtonRelease 1077 if (event.type == ButtonRelease
1073 && dpyinfo->display == event.xbutton.display) 1078 && dpyinfo->display == event.xbutton.display)
1074 { 1079 {
1075 dpyinfo->grabbed &= ~(1 << event.xbutton.button); 1080 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
1076 popup_activated_flag = 0;
1077#ifdef USE_MOTIF /* Pretending that the event came from a 1081#ifdef USE_MOTIF /* Pretending that the event came from a
1078 Btn1Down seems the only way to convince Motif to 1082 Btn1Down seems the only way to convince Motif to
1079 activate its callbacks; setting the XmNmenuPost 1083 activate its callbacks; setting the XmNmenuPost
1080 isn't working. --marcus@sysc.pdx.edu. */ 1084 isn't working. --marcus@sysc.pdx.edu. */
1081 event.xbutton.button = 1; 1085 event.xbutton.button = 1;
1086 /* Motif only pops down menus when no Ctrl, Alt or Mod
1087 key is pressed and the button is released. So reset key state
1088 so Motif thinks this is the case. */
1089 event.xbutton.state = 0;
1082#endif 1090#endif
1083 } 1091 }
1084 /* If the user presses a key, deactivate the menu. 1092 /* If the user presses a key, deactivate the menu.
1085 The user is likely to do that if we get wedged. */ 1093 The user is likely to do that if we get wedged.
1094 This is mostly for Lucid, Motif pops down the menu on ESC. */
1086 else if (event.type == KeyPress 1095 else if (event.type == KeyPress
1087 && dpyinfo->display == event.xbutton.display)
1088 {
1089 KeySym keysym = XLookupKeysym (&event.xkey, 0);
1090 if (!IsModifierKey (keysym))
1091 {
1092 popup_activated_flag = 0;
1093 break;
1094 }
1095 }
1096 /* Button presses outside the menu also pop it down. */
1097 else if (event.type == ButtonPress
1098 && event.xany.display == dpyinfo->display
1099 && x_any_window_to_frame (dpyinfo, event.xany.window))
1100 {
1101 popup_activated_flag = 0;
1102 break;
1103 }
1104
1105 /* Queue all events not for this popup,
1106 except for Expose, which we've already handled, and ButtonRelease.
1107 Note that the X window is associated with the frame if this
1108 is a menu bar popup, but not if it's a dialog box. So we use
1109 x_non_menubar_window_to_frame, not x_any_window_to_frame. */
1110 if (event.type != Expose
1111 && !(event.type == ButtonRelease
1112 && dpyinfo->display == event.xbutton.display) 1096 && dpyinfo->display == event.xbutton.display)
1113 && (event.xany.display != dpyinfo->display 1097 {
1114 || x_non_menubar_window_to_frame (dpyinfo, event.xany.window))) 1098 KeySym keysym = XLookupKeysym (&event.xkey, 0);
1115 { 1099 if (!IsModifierKey (keysym))
1116 queue_tmp = (struct event_queue *) xmalloc (sizeof *queue_tmp); 1100 popup_activated_flag = 0;
1117 queue_tmp->event = event; 1101 }
1118 queue_tmp->next = popup_get_selection_queue; 1102
1119 popup_get_selection_queue = queue_tmp; 1103 x_dispatch_event (&event, event.xany.display);
1120 }
1121 else
1122 XtDispatchEvent (&event);
1123
1124 /* If the event deactivated the menu, we are finished. */
1125 if (!popup_activated_flag)
1126 break;
1127
1128 /* If we have no events to run, consider timers. */
1129 if (do_timers && !XtAppPending (Xt_app_con))
1130 timer_check (1);
1131
1132 XtAppNextEvent (Xt_app_con, &event);
1133 }
1134
1135 unbind_to (count, Qnil);
1136}
1137
1138/* Unread any events that popup_get_selection read but did not handle. */
1139
1140static Lisp_Object
1141popup_get_selection_unwind (ignore)
1142 Lisp_Object ignore;
1143{
1144 while (popup_get_selection_queue != NULL)
1145 {
1146 struct event_queue *queue_tmp;
1147 queue_tmp = popup_get_selection_queue;
1148 XPutBackEvent (queue_tmp->event.xany.display, &queue_tmp->event);
1149 popup_get_selection_queue = queue_tmp->next;
1150 xfree ((char *)queue_tmp);
1151 /* Cause these events to get read as soon as we UNBLOCK_INPUT. */
1152 interrupt_input_pending = 1;
1153 } 1104 }
1154} 1105}
1155 1106
@@ -1630,7 +1581,7 @@ update_frame_menubar (f)
1630{ 1581{
1631 struct x_output *x = f->output_data.x; 1582 struct x_output *x = f->output_data.x;
1632 int columns, rows; 1583 int columns, rows;
1633 1584
1634 if (!x->menubar_widget || XtIsManaged (x->menubar_widget)) 1585 if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
1635 return 0; 1586 return 0;
1636 1587
@@ -2278,38 +2229,18 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
2278 popup_selection_callback, 2229 popup_selection_callback,
2279 popup_deactivate_callback, 2230 popup_deactivate_callback,
2280 menu_highlight_callback); 2231 menu_highlight_callback);
2281 2232
2282 /* Adjust coordinates to relative to the outer (window manager) window. */ 2233 /* See if whe positions are up to date. Temporary code to be removed
2234 when we are sure positions are always up to date. */
2283 { 2235 {
2284 Window child; 2236 int real_x, real_y;
2285 int win_x = 0, win_y = 0; 2237 x_real_positions (f, &real_x, &real_y);
2286 2238
2287 /* Find the position of the outside upper-left corner of 2239 if (real_x != f->output_data.x->left_pos ||
2288 the inner window, with respect to the outer window. */ 2240 real_y != f->output_data.x->top_pos)
2289 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window) 2241 abort ();
2290 {
2291 BLOCK_INPUT;
2292 XTranslateCoordinates (FRAME_X_DISPLAY (f),
2293
2294 /* From-window, to-window. */
2295 f->output_data.x->window_desc,
2296 f->output_data.x->parent_desc,
2297
2298 /* From-position, to-position. */
2299 0, 0, &win_x, &win_y,
2300
2301 /* Child of window. */
2302 &child);
2303 UNBLOCK_INPUT;
2304 x += win_x;
2305 y += win_y;
2306 }
2307 } 2242 }
2308 2243
2309 /* Adjust coordinates to be root-window-relative. */
2310 x += f->output_data.x->left_pos;
2311 y += f->output_data.x->top_pos;
2312
2313 dummy.type = ButtonPress; 2244 dummy.type = ButtonPress;
2314 dummy.serial = 0; 2245 dummy.serial = 0;
2315 dummy.send_event = 0; 2246 dummy.send_event = 0;
@@ -2318,11 +2249,16 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
2318 dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window; 2249 dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
2319 dummy.window = dummy.root; 2250 dummy.window = dummy.root;
2320 dummy.subwindow = dummy.root; 2251 dummy.subwindow = dummy.root;
2321 dummy.x_root = x;
2322 dummy.y_root = y;
2323 dummy.x = x; 2252 dummy.x = x;
2324 dummy.y = y; 2253 dummy.y = y;
2325 dummy.state = (FRAME_X_DISPLAY_INFO (f)->grabbed >> 1) * Button1Mask; 2254
2255 /* Adjust coordinates to be root-window-relative. */
2256 x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2257 y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2258
2259 dummy.x_root = x;
2260 dummy.y_root = y;
2261 dummy.state = 0;
2326 dummy.button = 0; 2262 dummy.button = 0;
2327 for (i = 0; i < 5; i++) 2263 for (i = 0; i < 5; i++)
2328 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i)) 2264 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))