diff options
| author | Paul Reilly | 1994-10-02 15:51:13 +0000 |
|---|---|---|
| committer | Paul Reilly | 1994-10-02 15:51:13 +0000 |
| commit | 4dedbfe0bf00decbc4c6f42970cde37af21198ff (patch) | |
| tree | f108eca4a025571ec0815fadfe63e1066338e5a2 /src | |
| parent | a263cd2dd908102c57283919ab6a22235e544b58 (diff) | |
| download | emacs-4dedbfe0bf00decbc4c6f42970cde37af21198ff.tar.gz emacs-4dedbfe0bf00decbc4c6f42970cde37af21198ff.zip | |
(widget_id_tick): Renamed from popup_id_tick.
(popup_get_selection, popup_activated, popup_activate_callback,
menubar_selection_callback, popup_deactivate_callback,
single_submenu): New or replaced functions.
(popup_activated_flag): New variable.
(dispatch_dummy_expose, event_is_in_menu_item, map_event_to_object):
Removed.
(update_frame_menubar): Use lw_refigure_widget to provide widget set
independence.
(set_frame_menubar): Use lw_allow_resizing to control unsightly Motif
menubar resizing in a widget set independent fashion.
(xmenu_show): Removed menubar handling code, since that is now done in
lwlib. Display a popup menu title centered and followed by two
separators. Use lw_popup_menu() to display the menu. Use
popup_get_selection() to deal with X11 event handling while the menu
is posted.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xmenu.c | 726 |
1 files changed, 380 insertions, 346 deletions
diff --git a/src/xmenu.c b/src/xmenu.c index c78f8f59aff..096ff34559c 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -66,9 +66,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 66 | #include <X11/CoreP.h> | 66 | #include <X11/CoreP.h> |
| 67 | #include <X11/StringDefs.h> | 67 | #include <X11/StringDefs.h> |
| 68 | #include <X11/Shell.h> | 68 | #include <X11/Shell.h> |
| 69 | #include <X11/Xaw/Paned.h> | ||
| 70 | #include "../lwlib/lwlib.h" | 69 | #include "../lwlib/lwlib.h" |
| 71 | #include "../lwlib/xlwmenuP.h" | ||
| 72 | #endif /* USE_X_TOOLKIT */ | 70 | #endif /* USE_X_TOOLKIT */ |
| 73 | 71 | ||
| 74 | #define min(x,y) (((x) < (y)) ? (x) : (y)) | 72 | #define min(x,y) (((x) < (y)) ? (x) : (y)) |
| @@ -85,8 +83,10 @@ extern Display *x_current_display; | |||
| 85 | #define ButtonReleaseMask ButtonReleased | 83 | #define ButtonReleaseMask ButtonReleased |
| 86 | #endif /* not HAVE_X11 */ | 84 | #endif /* not HAVE_X11 */ |
| 87 | 85 | ||
| 88 | /* We need a unique id for each popup menu and dialog box. */ | 86 | /* We need a unique id for each widget handled by the Lucid Widget |
| 89 | static unsigned int popup_id_tick; | 87 | library. This includes the frame main windows, popup menu and |
| 88 | dialog box. */ | ||
| 89 | LWLIB_ID widget_id_tick; | ||
| 90 | 90 | ||
| 91 | extern Lisp_Object Qmenu_enable; | 91 | extern Lisp_Object Qmenu_enable; |
| 92 | extern Lisp_Object Qmenu_bar; | 92 | extern Lisp_Object Qmenu_bar; |
| @@ -96,6 +96,7 @@ extern void process_expose_from_menu (); | |||
| 96 | extern XtAppContext Xt_app_con; | 96 | extern XtAppContext Xt_app_con; |
| 97 | 97 | ||
| 98 | static Lisp_Object xdialog_show (); | 98 | static Lisp_Object xdialog_show (); |
| 99 | void popup_get_selection (); | ||
| 99 | #endif | 100 | #endif |
| 100 | 101 | ||
| 101 | static Lisp_Object xmenu_show (); | 102 | static Lisp_Object xmenu_show (); |
| @@ -151,6 +152,11 @@ static int menu_items_n_panes; | |||
| 151 | /* Current depth within submenus. */ | 152 | /* Current depth within submenus. */ |
| 152 | static int menu_items_submenu_depth; | 153 | static int menu_items_submenu_depth; |
| 153 | 154 | ||
| 155 | /* Flag which when set indicates a dialog or menu has been posted by | ||
| 156 | Xt on behalf of one of the widget sets. */ | ||
| 157 | static int popup_activated_flag; | ||
| 158 | |||
| 159 | |||
| 154 | /* Initialize the menu_items structure if we haven't already done so. | 160 | /* Initialize the menu_items structure if we haven't already done so. |
| 155 | Also mark it as currently empty. */ | 161 | Also mark it as currently empty. */ |
| 156 | 162 | ||
| @@ -994,122 +1000,148 @@ on the left of the dialog box and all following items on the right.\n\ | |||
| 994 | 1000 | ||
| 995 | #ifdef USE_X_TOOLKIT | 1001 | #ifdef USE_X_TOOLKIT |
| 996 | 1002 | ||
| 997 | static void | 1003 | /* Loop in Xt until the menu pulldown or dialog popup has been |
| 998 | dispatch_dummy_expose (w, x, y) | 1004 | popped down (deactivated). */ |
| 999 | Widget w; | 1005 | void |
| 1000 | int x; | 1006 | popup_get_selection (initial_event) |
| 1001 | int y; | 1007 | XEvent *initial_event; |
| 1002 | { | ||
| 1003 | XExposeEvent dummy; | ||
| 1004 | |||
| 1005 | dummy.type = Expose; | ||
| 1006 | dummy.window = XtWindow (w); | ||
| 1007 | dummy.count = 0; | ||
| 1008 | dummy.serial = 0; | ||
| 1009 | dummy.send_event = 0; | ||
| 1010 | dummy.display = XtDisplay (w); | ||
| 1011 | dummy.x = x; | ||
| 1012 | dummy.y = y; | ||
| 1013 | |||
| 1014 | XtDispatchEvent ((XEvent *) &dummy); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | static int | ||
| 1018 | event_is_in_menu_item (mw, event, name, string_w) | ||
| 1019 | XlwMenuWidget mw; | ||
| 1020 | struct input_event *event; | ||
| 1021 | char *name; | ||
| 1022 | int *string_w; | ||
| 1023 | { | ||
| 1024 | *string_w += (string_width (mw, name) | ||
| 1025 | + 2 * (mw->menu.horizontal_spacing | ||
| 1026 | + mw->menu.shadow_thickness)); | ||
| 1027 | return XINT (event->x) < *string_w; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | |||
| 1031 | /* Return the menu bar key which corresponds to event EVENT in frame F. */ | ||
| 1032 | |||
| 1033 | Lisp_Object | ||
| 1034 | map_event_to_object (event, f) | ||
| 1035 | struct input_event *event; | ||
| 1036 | FRAME_PTR f; | ||
| 1037 | { | 1008 | { |
| 1038 | int i,j, string_w; | 1009 | XEvent event; |
| 1039 | window_state* ws; | ||
| 1040 | XlwMenuWidget mw = (XlwMenuWidget) f->display.x->menubar_widget; | ||
| 1041 | widget_value *val; | ||
| 1042 | 1010 | ||
| 1011 | if (initial_event) | ||
| 1012 | event = *initial_event; | ||
| 1013 | else | ||
| 1014 | XtAppNextEvent (Xt_app_con, &event); | ||
| 1043 | 1015 | ||
| 1044 | string_w = 0; | 1016 | while (1) |
| 1045 | /* Find the window */ | ||
| 1046 | for (val = mw->menu.old_stack [0]->contents; val; val = val->next) | ||
| 1047 | { | 1017 | { |
| 1048 | ws = &mw->menu.windows [0]; | 1018 | BLOCK_INPUT; |
| 1049 | if (ws && event_is_in_menu_item (mw, event, val->name, &string_w)) | 1019 | XtDispatchEvent (&event); |
| 1050 | { | 1020 | UNBLOCK_INPUT; |
| 1051 | Lisp_Object items; | 1021 | if (!popup_activated()) |
| 1052 | int i; | 1022 | break; |
| 1053 | 1023 | XtAppNextEvent (Xt_app_con, &event); | |
| 1054 | items = FRAME_MENU_BAR_ITEMS (f); | ||
| 1055 | |||
| 1056 | for (i = 0; i < XVECTOR (items)->size; i += 3) | ||
| 1057 | { | ||
| 1058 | Lisp_Object pos, string, item; | ||
| 1059 | item = XVECTOR (items)->contents[i]; | ||
| 1060 | string = XVECTOR (items)->contents[i + 1]; | ||
| 1061 | pos = XVECTOR (items)->contents[i + 2]; | ||
| 1062 | if (NILP (string)) | ||
| 1063 | break; | ||
| 1064 | |||
| 1065 | if (!strcmp (val->name, XSTRING (string)->data)) | ||
| 1066 | return item; | ||
| 1067 | } | ||
| 1068 | } | ||
| 1069 | } | 1024 | } |
| 1070 | return Qnil; | ||
| 1071 | } | 1025 | } |
| 1072 | 1026 | ||
| 1073 | #ifdef __STDC__ | 1027 | /* Detect if a dialog or menu has been posted. */ |
| 1074 | static Lisp_Object *volatile menu_item_selection; | 1028 | int |
| 1075 | #else | 1029 | popup_activated () |
| 1076 | static Lisp_Object *menu_item_selection; | 1030 | { |
| 1077 | #endif | 1031 | return popup_activated_flag; |
| 1032 | } | ||
| 1033 | |||
| 1034 | |||
| 1035 | /* This callback is invoked when the user selects a menubar cascade | ||
| 1036 | pushbutton, but before the pulldown menu is posted. */ | ||
| 1078 | 1037 | ||
| 1079 | static void | 1038 | static void |
| 1080 | popup_selection_callback (widget, id, client_data) | 1039 | popup_activate_callback (widget, id, client_data) |
| 1081 | Widget widget; | 1040 | Widget widget; |
| 1082 | LWLIB_ID id; | 1041 | LWLIB_ID id; |
| 1083 | XtPointer client_data; | 1042 | XtPointer client_data; |
| 1084 | { | 1043 | { |
| 1085 | menu_item_selection = (Lisp_Object *) client_data; | 1044 | popup_activated_flag = 1; |
| 1086 | } | 1045 | } |
| 1087 | 1046 | ||
| 1047 | /* This callback is called from the menu bar pulldown menu | ||
| 1048 | when the user makes a selection. | ||
| 1049 | Figure out what the user chose | ||
| 1050 | and put the appropriate events into the keyboard buffer. */ | ||
| 1051 | |||
| 1088 | static void | 1052 | static void |
| 1089 | popup_down_callback (widget, id, client_data) | 1053 | menubar_selection_callback (widget, id, client_data) |
| 1090 | Widget widget; | 1054 | Widget widget; |
| 1091 | LWLIB_ID id; | 1055 | LWLIB_ID id; |
| 1092 | XtPointer client_data; | 1056 | XtPointer client_data; |
| 1093 | { | 1057 | { |
| 1094 | BLOCK_INPUT; | 1058 | Lisp_Object prefix; |
| 1095 | lw_destroy_all_widgets (id); | 1059 | FRAME_PTR f = (FRAME_PTR) id; |
| 1096 | UNBLOCK_INPUT; | 1060 | Lisp_Object vector; |
| 1061 | Lisp_Object *subprefix_stack; | ||
| 1062 | int submenu_depth = 0; | ||
| 1063 | int i; | ||
| 1064 | |||
| 1065 | if (!f) | ||
| 1066 | return; | ||
| 1067 | subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object)); | ||
| 1068 | vector = f->menu_bar_vector; | ||
| 1069 | prefix = Qnil; | ||
| 1070 | i = 0; | ||
| 1071 | while (i < f->menu_bar_items_used) | ||
| 1072 | { | ||
| 1073 | Lisp_Object entry; | ||
| 1074 | |||
| 1075 | if (EQ (XVECTOR (vector)->contents[i], Qnil)) | ||
| 1076 | { | ||
| 1077 | subprefix_stack[submenu_depth++] = prefix; | ||
| 1078 | prefix = entry; | ||
| 1079 | i++; | ||
| 1080 | } | ||
| 1081 | else if (EQ (XVECTOR (vector)->contents[i], Qlambda)) | ||
| 1082 | { | ||
| 1083 | prefix = subprefix_stack[--submenu_depth]; | ||
| 1084 | i++; | ||
| 1085 | } | ||
| 1086 | else if (EQ (XVECTOR (vector)->contents[i], Qt)) | ||
| 1087 | { | ||
| 1088 | prefix | ||
| 1089 | = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX]; | ||
| 1090 | i += MENU_ITEMS_PANE_LENGTH; | ||
| 1091 | } | ||
| 1092 | else | ||
| 1093 | { | ||
| 1094 | entry | ||
| 1095 | = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE]; | ||
| 1096 | if ((int) client_data == i) | ||
| 1097 | { | ||
| 1098 | int j; | ||
| 1099 | struct input_event buf; | ||
| 1100 | |||
| 1101 | buf.kind = menu_bar_event; | ||
| 1102 | buf.frame_or_window = Qmenu_bar; | ||
| 1103 | kbd_buffer_store_event (&buf); | ||
| 1104 | |||
| 1105 | for (j = 0; j < submenu_depth; j++) | ||
| 1106 | if (!NILP (subprefix_stack[j])) | ||
| 1107 | { | ||
| 1108 | buf.kind = menu_bar_event; | ||
| 1109 | buf.frame_or_window = subprefix_stack[j]; | ||
| 1110 | kbd_buffer_store_event (&buf); | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | if (!NILP (prefix)) | ||
| 1114 | { | ||
| 1115 | buf.kind = menu_bar_event; | ||
| 1116 | buf.frame_or_window = prefix; | ||
| 1117 | kbd_buffer_store_event (&buf); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | buf.kind = menu_bar_event; | ||
| 1121 | buf.frame_or_window = entry; | ||
| 1122 | kbd_buffer_store_event (&buf); | ||
| 1123 | |||
| 1124 | return; | ||
| 1125 | } | ||
| 1126 | i += MENU_ITEMS_ITEM_LENGTH; | ||
| 1127 | } | ||
| 1128 | } | ||
| 1097 | } | 1129 | } |
| 1098 | 1130 | ||
| 1131 | /* This callback is invoked when a dialog or menu is finished being | ||
| 1132 | used and has been unposted. */ | ||
| 1133 | |||
| 1099 | static void | 1134 | static void |
| 1100 | dialog_selection_callback (widget, id, client_data) | 1135 | popup_deactivate_callback (widget, id, client_data) |
| 1101 | Widget widget; | 1136 | Widget widget; |
| 1102 | LWLIB_ID id; | 1137 | LWLIB_ID id; |
| 1103 | XtPointer client_data; | 1138 | XtPointer client_data; |
| 1104 | { | 1139 | { |
| 1105 | if ((int)client_data != -1) | 1140 | popup_activated_flag = 0; |
| 1106 | menu_item_selection = (Lisp_Object *) client_data; | ||
| 1107 | BLOCK_INPUT; | ||
| 1108 | lw_destroy_all_widgets (id); | ||
| 1109 | UNBLOCK_INPUT; | ||
| 1110 | } | 1141 | } |
| 1111 | 1142 | ||
| 1112 | /* This recursively calls free_widget_value() on the tree of widgets. | 1143 | |
| 1144 | /* This recursively calls free_widget_value on the tree of widgets. | ||
| 1113 | It must free all data that was malloc'ed for these widget_values. | 1145 | It must free all data that was malloc'ed for these widget_values. |
| 1114 | In Emacs, many slots are pointers into the data of Lisp_Strings, and | 1146 | In Emacs, many slots are pointers into the data of Lisp_Strings, and |
| 1115 | must be left alone. */ | 1147 | must be left alone. */ |
| @@ -1136,9 +1168,149 @@ free_menubar_widget_value_tree (wv) | |||
| 1136 | free_widget_value (wv); | 1168 | free_widget_value (wv); |
| 1137 | UNBLOCK_INPUT; | 1169 | UNBLOCK_INPUT; |
| 1138 | } | 1170 | } |
| 1171 | |||
| 1172 | /* Return a tree of widget_value structures for a menu bar item | ||
| 1173 | whose event type is ITEM_KEY (with string ITEM_NAME) | ||
| 1174 | and whose contents come from the list of keymaps MAPS. */ | ||
| 1175 | |||
| 1176 | static widget_value * | ||
| 1177 | single_submenu (item_key, item_name, maps) | ||
| 1178 | Lisp_Object item_key, item_name, maps; | ||
| 1179 | { | ||
| 1180 | widget_value *wv, *prev_wv, *save_wv, *first_wv; | ||
| 1181 | int i; | ||
| 1182 | int submenu_depth = 0; | ||
| 1183 | Lisp_Object length; | ||
| 1184 | int len; | ||
| 1185 | Lisp_Object *mapvec; | ||
| 1186 | widget_value **submenu_stack; | ||
| 1187 | int mapno; | ||
| 1188 | int previous_items = menu_items_used; | ||
| 1189 | |||
| 1190 | length = Flength (maps); | ||
| 1191 | len = XINT (length); | ||
| 1192 | |||
| 1193 | /* Convert the list MAPS into a vector MAPVEC. */ | ||
| 1194 | mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | ||
| 1195 | for (i = 0; i < len; i++) | ||
| 1196 | { | ||
| 1197 | mapvec[i] = Fcar (maps); | ||
| 1198 | maps = Fcdr (maps); | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | menu_items_n_panes = 0; | ||
| 1202 | |||
| 1203 | /* Loop over the given keymaps, making a pane for each map. | ||
| 1204 | But don't make a pane that is empty--ignore that map instead. */ | ||
| 1205 | for (i = 0; i < len; i++) | ||
| 1206 | single_keymap_panes (mapvec[i], item_name, item_key, 0); | ||
| 1207 | |||
| 1208 | /* Create a tree of widget_value objects | ||
| 1209 | representing the panes and their items. */ | ||
| 1210 | |||
| 1211 | submenu_stack | ||
| 1212 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | ||
| 1213 | wv = malloc_widget_value (); | ||
| 1214 | wv->name = "menu"; | ||
| 1215 | wv->value = 0; | ||
| 1216 | wv->enabled = 1; | ||
| 1217 | first_wv = wv; | ||
| 1218 | save_wv = 0; | ||
| 1219 | |||
| 1220 | /* Loop over all panes and items made during this call | ||
| 1221 | and construct a tree of widget_value objects. | ||
| 1222 | Ignore the panes and items made by previous calls to | ||
| 1223 | single_submenu, even though those are also in menu_items. */ | ||
| 1224 | i = previous_items; | ||
| 1225 | while (i < menu_items_used) | ||
| 1226 | { | ||
| 1227 | if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) | ||
| 1228 | { | ||
| 1229 | submenu_stack[submenu_depth++] = save_wv; | ||
| 1230 | save_wv = prev_wv; | ||
| 1231 | prev_wv = 0; | ||
| 1232 | i++; | ||
| 1233 | } | ||
| 1234 | else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda)) | ||
| 1235 | { | ||
| 1236 | prev_wv = save_wv; | ||
| 1237 | save_wv = submenu_stack[--submenu_depth]; | ||
| 1238 | i++; | ||
| 1239 | } | ||
| 1240 | else if (EQ (XVECTOR (menu_items)->contents[i], Qt) | ||
| 1241 | && submenu_depth != 0) | ||
| 1242 | i += MENU_ITEMS_PANE_LENGTH; | ||
| 1243 | /* Ignore a nil in the item list. | ||
| 1244 | It's meaningful only for dialog boxes. */ | ||
| 1245 | else if (EQ (XVECTOR (menu_items)->contents[i], Qquote)) | ||
| 1246 | i += 1; | ||
| 1247 | else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) | ||
| 1248 | { | ||
| 1249 | /* Create a new pane. */ | ||
| 1250 | Lisp_Object pane_name, prefix; | ||
| 1251 | char *pane_string; | ||
| 1252 | pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; | ||
| 1253 | prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; | ||
| 1254 | pane_string = (NILP (pane_name) | ||
| 1255 | ? "" : (char *) XSTRING (pane_name)->data); | ||
| 1256 | /* If there is just one top-level pane, put all its items directly | ||
| 1257 | under the top-level menu. */ | ||
| 1258 | if (menu_items_n_panes == 1) | ||
| 1259 | pane_string = ""; | ||
| 1260 | |||
| 1261 | /* If the pane has a meaningful name, | ||
| 1262 | make the pane a top-level menu item | ||
| 1263 | with its items as a submenu beneath it. */ | ||
| 1264 | if (strcmp (pane_string, "")) | ||
| 1265 | { | ||
| 1266 | wv = malloc_widget_value (); | ||
| 1267 | if (save_wv) | ||
| 1268 | save_wv->next = wv; | ||
| 1269 | else | ||
| 1270 | first_wv->contents = wv; | ||
| 1271 | wv->name = pane_string; | ||
| 1272 | if (!NILP (prefix)) | ||
| 1273 | wv->name++; | ||
| 1274 | wv->value = 0; | ||
| 1275 | wv->enabled = 1; | ||
| 1276 | } | ||
| 1277 | save_wv = wv; | ||
| 1278 | prev_wv = 0; | ||
| 1279 | i += MENU_ITEMS_PANE_LENGTH; | ||
| 1280 | } | ||
| 1281 | else | ||
| 1282 | { | ||
| 1283 | /* Create a new item within current pane. */ | ||
| 1284 | Lisp_Object item_name, enable, descrip; | ||
| 1285 | item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME]; | ||
| 1286 | enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE]; | ||
| 1287 | descrip | ||
| 1288 | = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; | ||
| 1139 | 1289 | ||
| 1290 | wv = malloc_widget_value (); | ||
| 1291 | if (prev_wv) | ||
| 1292 | prev_wv->next = wv; | ||
| 1293 | else | ||
| 1294 | save_wv->contents = wv; | ||
| 1295 | wv->name = (char *) XSTRING (item_name)->data; | ||
| 1296 | if (!NILP (descrip)) | ||
| 1297 | wv->key = (char *) XSTRING (descrip)->data; | ||
| 1298 | wv->value = 0; | ||
| 1299 | wv->call_data = (void *) i; | ||
| 1300 | wv->enabled = !NILP (enable); | ||
| 1301 | prev_wv = wv; | ||
| 1302 | |||
| 1303 | i += MENU_ITEMS_ITEM_LENGTH; | ||
| 1304 | } | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | return first_wv; | ||
| 1308 | } | ||
| 1309 | |||
| 1140 | extern void EmacsFrameSetCharSize (); | 1310 | extern void EmacsFrameSetCharSize (); |
| 1141 | 1311 | ||
| 1312 | /* Recompute the menu bar of frame F. */ | ||
| 1313 | |||
| 1142 | static void | 1314 | static void |
| 1143 | update_frame_menubar (f) | 1315 | update_frame_menubar (f) |
| 1144 | FRAME_PTR f; | 1316 | FRAME_PTR f; |
| @@ -1147,6 +1319,12 @@ update_frame_menubar (f) | |||
| 1147 | int columns, rows; | 1319 | int columns, rows; |
| 1148 | int menubar_changed; | 1320 | int menubar_changed; |
| 1149 | 1321 | ||
| 1322 | Dimension shell_height; | ||
| 1323 | |||
| 1324 | /* We assume the menubar contents has changed if the global flag is set, | ||
| 1325 | or if the current buffer has changed, or if the menubar has never | ||
| 1326 | been updated before. | ||
| 1327 | */ | ||
| 1150 | menubar_changed = (x->menubar_widget | 1328 | menubar_changed = (x->menubar_widget |
| 1151 | && !XtIsManaged (x->menubar_widget)); | 1329 | && !XtIsManaged (x->menubar_widget)); |
| 1152 | 1330 | ||
| @@ -1159,9 +1337,10 @@ update_frame_menubar (f) | |||
| 1159 | columns = f->width; | 1337 | columns = f->width; |
| 1160 | rows = f->height; | 1338 | rows = f->height; |
| 1161 | 1339 | ||
| 1340 | /* Do the voodoo which means "I'm changing lots of things, don't try to | ||
| 1341 | refigure sizes until I'm done." */ | ||
| 1342 | lw_refigure_widget (x->column_widget, False); | ||
| 1162 | 1343 | ||
| 1163 | XawPanedSetRefigureMode (x->column_widget, 0); | ||
| 1164 | |||
| 1165 | /* the order in which children are managed is the top to | 1344 | /* the order in which children are managed is the top to |
| 1166 | bottom order in which they are displayed in the paned window. | 1345 | bottom order in which they are displayed in the paned window. |
| 1167 | First, remove the text-area widget. | 1346 | First, remove the text-area widget. |
| @@ -1178,12 +1357,9 @@ update_frame_menubar (f) | |||
| 1178 | XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, 0); | 1357 | XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, 0); |
| 1179 | } | 1358 | } |
| 1180 | 1359 | ||
| 1181 | 1360 | /* Re-manage the text-area widget, and then thrash the sizes. */ | |
| 1182 | /* Re-manage the text-area widget */ | ||
| 1183 | XtManageChild (x->edit_widget); | 1361 | XtManageChild (x->edit_widget); |
| 1184 | 1362 | lw_refigure_widget (x->column_widget, True); | |
| 1185 | /* and now thrash the sizes */ | ||
| 1186 | XawPanedSetRefigureMode (x->column_widget, 1); | ||
| 1187 | 1363 | ||
| 1188 | /* Force the pane widget to resize itself with the right values. */ | 1364 | /* Force the pane widget to resize itself with the right values. */ |
| 1189 | EmacsFrameSetCharSize (x->edit_widget, columns, rows); | 1365 | EmacsFrameSetCharSize (x->edit_widget, columns, rows); |
| @@ -1209,44 +1385,59 @@ set_frame_menubar (f, first_time) | |||
| 1209 | wv->value = 0; | 1385 | wv->value = 0; |
| 1210 | wv->enabled = 1; | 1386 | wv->enabled = 1; |
| 1211 | save_wv = first_wv = wv; | 1387 | save_wv = first_wv = wv; |
| 1212 | 1388 | items = FRAME_MENU_BAR_ITEMS (f); | |
| 1213 | if (NILP (items = FRAME_MENU_BAR_ITEMS (f))) | 1389 | menu_items = f->menu_bar_vector; |
| 1214 | items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); | 1390 | menu_items_allocated = XVECTOR (menu_items)->size; |
| 1391 | init_menu_items (); | ||
| 1215 | 1392 | ||
| 1216 | for (i = 0; i < XVECTOR (items)->size; i += 3) | 1393 | for (i = 0; i < XVECTOR (items)->size; i += 3) |
| 1217 | { | 1394 | { |
| 1218 | Lisp_Object string; | 1395 | Lisp_Object key, string, maps; |
| 1219 | 1396 | ||
| 1397 | key = XVECTOR (items)->contents[i]; | ||
| 1220 | string = XVECTOR (items)->contents[i + 1]; | 1398 | string = XVECTOR (items)->contents[i + 1]; |
| 1399 | maps = XVECTOR (items)->contents[i + 2]; | ||
| 1221 | if (NILP (string)) | 1400 | if (NILP (string)) |
| 1222 | break; | 1401 | break; |
| 1223 | 1402 | ||
| 1224 | wv = malloc_widget_value (); | 1403 | wv = single_submenu (key, string, maps); |
| 1225 | if (prev_wv) | 1404 | if (prev_wv) |
| 1226 | prev_wv->next = wv; | 1405 | prev_wv->next = wv; |
| 1227 | else | 1406 | else |
| 1228 | save_wv->contents = wv; | 1407 | save_wv->contents = wv; |
| 1229 | wv->name = (char *) XSTRING (string)->data; | 1408 | wv->name = (char *) XSTRING (string)->data; |
| 1230 | wv->value = 0; | ||
| 1231 | wv->enabled = 1; | 1409 | wv->enabled = 1; |
| 1232 | prev_wv = wv; | 1410 | prev_wv = wv; |
| 1233 | } | 1411 | } |
| 1234 | 1412 | ||
| 1413 | finish_menu_items (); | ||
| 1414 | |||
| 1415 | f->menu_bar_vector = menu_items; | ||
| 1416 | f->menu_bar_items_used = menu_items_used; | ||
| 1417 | menu_items = Qnil; | ||
| 1418 | |||
| 1235 | if (menubar_widget) | 1419 | if (menubar_widget) |
| 1236 | lw_modify_all_widgets (id, first_wv, False); | 1420 | { |
| 1421 | /* Disable resizing (done for Motif!) */ | ||
| 1422 | lw_allow_resizing (f->display.x->widget, False); | ||
| 1423 | |||
| 1424 | /* The third arg is DEEP_P, which says to consider the entire | ||
| 1425 | menu trees we supply, rather than just the menu bar item names. */ | ||
| 1426 | lw_modify_all_widgets (id, first_wv, 1); | ||
| 1427 | |||
| 1428 | /* Re-enable the edit widget to resize. */ | ||
| 1429 | lw_allow_resizing (f->display.x->widget, True); | ||
| 1430 | } | ||
| 1237 | else | 1431 | else |
| 1238 | { | 1432 | { |
| 1239 | menubar_widget = lw_create_widget ("menubar", "menubar", | 1433 | menubar_widget = lw_create_widget ("menubar", "menubar", |
| 1240 | id, first_wv, | 1434 | id, first_wv, |
| 1241 | f->display.x->column_widget, | 1435 | f->display.x->column_widget, |
| 1242 | 0, 0, | 1436 | 0, |
| 1243 | 0, 0); | 1437 | popup_activate_callback, |
| 1438 | menubar_selection_callback, | ||
| 1439 | popup_deactivate_callback); | ||
| 1244 | f->display.x->menubar_widget = menubar_widget; | 1440 | f->display.x->menubar_widget = menubar_widget; |
| 1245 | XtVaSetValues (menubar_widget, | ||
| 1246 | XtNshowGrip, 0, | ||
| 1247 | XtNresizeToPreferred, 1, | ||
| 1248 | XtNallowResize, 1, | ||
| 1249 | 0); | ||
| 1250 | } | 1441 | } |
| 1251 | 1442 | ||
| 1252 | free_menubar_widget_value_tree (first_wv); | 1443 | free_menubar_widget_value_tree (first_wv); |
| @@ -1258,6 +1449,24 @@ set_frame_menubar (f, first_time) | |||
| 1258 | UNBLOCK_INPUT; | 1449 | UNBLOCK_INPUT; |
| 1259 | } | 1450 | } |
| 1260 | 1451 | ||
| 1452 | /* Called from Fx_create_frame to create the inital menubar of a frame | ||
| 1453 | before it is mapped, so that the window is mapped with the menubar already | ||
| 1454 | there instead of us tacking it on later and thrashing the window after it | ||
| 1455 | is visible. */ | ||
| 1456 | |||
| 1457 | void | ||
| 1458 | initialize_frame_menubar (f) | ||
| 1459 | FRAME_PTR f; | ||
| 1460 | { | ||
| 1461 | /* This function is called before the first chance to redisplay | ||
| 1462 | the frame. It has to be, so the frame will have the right size. */ | ||
| 1463 | FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); | ||
| 1464 | set_frame_menubar (f, 1); | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | /* Get rid of the menu bar of frame F, and free its storage. | ||
| 1468 | This is used when deleting a frame, and when turning off the menu bar. */ | ||
| 1469 | |||
| 1261 | void | 1470 | void |
| 1262 | free_frame_menubar (f) | 1471 | free_frame_menubar (f) |
| 1263 | FRAME_PTR f; | 1472 | FRAME_PTR f; |
| @@ -1275,16 +1484,6 @@ free_frame_menubar (f) | |||
| 1275 | UNBLOCK_INPUT; | 1484 | UNBLOCK_INPUT; |
| 1276 | } | 1485 | } |
| 1277 | } | 1486 | } |
| 1278 | /* Called from Fx_create_frame to create the inital menubar of a frame | ||
| 1279 | before it is mapped, so that the window is mapped with the menubar already | ||
| 1280 | there instead of us tacking it on later and thrashing the window after it | ||
| 1281 | is visible. */ | ||
| 1282 | void | ||
| 1283 | initialize_frame_menubar (f) | ||
| 1284 | FRAME_PTR f; | ||
| 1285 | { | ||
| 1286 | set_frame_menubar (f, 1); | ||
| 1287 | } | ||
| 1288 | 1487 | ||
| 1289 | /* Horizontal bounds of the current menu bar item. */ | 1488 | /* Horizontal bounds of the current menu bar item. */ |
| 1290 | 1489 | ||
| @@ -1383,12 +1582,28 @@ extern Lisp_Object Vdouble_click_time; | |||
| 1383 | extern unsigned int x_mouse_grabbed; | 1582 | extern unsigned int x_mouse_grabbed; |
| 1384 | extern Lisp_Object Vmouse_depressed; | 1583 | extern Lisp_Object Vmouse_depressed; |
| 1385 | 1584 | ||
| 1585 | #ifdef __STDC__ | ||
| 1586 | static Lisp_Object *volatile menu_item_selection; | ||
| 1587 | #else | ||
| 1588 | static Lisp_Object *menu_item_selection; | ||
| 1589 | #endif | ||
| 1590 | |||
| 1591 | static void | ||
| 1592 | popup_selection_callback (widget, id, client_data) | ||
| 1593 | Widget widget; | ||
| 1594 | LWLIB_ID id; | ||
| 1595 | XtPointer client_data; | ||
| 1596 | { | ||
| 1597 | menu_item_selection = (Lisp_Object *) client_data; | ||
| 1598 | } | ||
| 1599 | |||
| 1386 | static Lisp_Object | 1600 | static Lisp_Object |
| 1387 | xmenu_show (f, x, y, menubarp, keymaps, title, error) | 1601 | xmenu_show (f, x, y, menubarp, keymaps, title, error) |
| 1388 | FRAME_PTR f; | 1602 | FRAME_PTR f; |
| 1389 | int x; | 1603 | int x; |
| 1390 | int y; | 1604 | int y; |
| 1391 | int menubarp; | 1605 | int menubarp; /* Dummy parameter for Xt version of |
| 1606 | xmenu_show() */ | ||
| 1392 | int keymaps; | 1607 | int keymaps; |
| 1393 | Lisp_Object title; | 1608 | Lisp_Object title; |
| 1394 | char **error; | 1609 | char **error; |
| @@ -1396,13 +1611,8 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1396 | int i; | 1611 | int i; |
| 1397 | int menu_id; | 1612 | int menu_id; |
| 1398 | Widget menu; | 1613 | Widget menu; |
| 1399 | XlwMenuWidget menubar = (XlwMenuWidget) f->display.x->menubar_widget; | ||
| 1400 | Arg av [2]; | 1614 | Arg av [2]; |
| 1401 | int ac = 0; | 1615 | int ac = 0; |
| 1402 | |||
| 1403 | /* This is the menu bar item (if any) that led to this menu. */ | ||
| 1404 | widget_value *menubar_item = 0; | ||
| 1405 | |||
| 1406 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; | 1616 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; |
| 1407 | widget_value **submenu_stack | 1617 | widget_value **submenu_stack |
| 1408 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | 1618 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); |
| @@ -1433,48 +1643,6 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1433 | *error = "Empty menu"; | 1643 | *error = "Empty menu"; |
| 1434 | return Qnil; | 1644 | return Qnil; |
| 1435 | } | 1645 | } |
| 1436 | this_menu_bar_item_beg = -1; | ||
| 1437 | this_menu_bar_item_end = -1; | ||
| 1438 | last_menu_bar_item_end = -1; | ||
| 1439 | |||
| 1440 | /* Figure out which menu bar item, if any, this menu is for. */ | ||
| 1441 | if (menubarp) | ||
| 1442 | { | ||
| 1443 | int xbeg; | ||
| 1444 | int xend = 0; | ||
| 1445 | widget_value *mb_item = 0; | ||
| 1446 | |||
| 1447 | for (mb_item = menubar->menu.old_stack[0]->contents; | ||
| 1448 | mb_item; | ||
| 1449 | mb_item = mb_item->next) | ||
| 1450 | { | ||
| 1451 | xbeg = xend; | ||
| 1452 | xend += (string_width (menubar, mb_item->name) | ||
| 1453 | + 2 * (menubar->menu.horizontal_spacing | ||
| 1454 | + menubar->menu.shadow_thickness)); | ||
| 1455 | if (x >= xbeg && x < xend) | ||
| 1456 | { | ||
| 1457 | x = xbeg + 4; | ||
| 1458 | y = 0; | ||
| 1459 | menubar_item = mb_item; | ||
| 1460 | /* Arrange to show a different menu if we move in the menu bar | ||
| 1461 | to a different item. */ | ||
| 1462 | this_menu_bar_item_beg = xbeg; | ||
| 1463 | this_menu_bar_item_end = xend; | ||
| 1464 | } | ||
| 1465 | } | ||
| 1466 | last_menu_bar_item_end = xend; | ||
| 1467 | } | ||
| 1468 | if (menubar_item == 0) | ||
| 1469 | menubarp = 0; | ||
| 1470 | |||
| 1471 | /* Offset the coordinates to root-relative. */ | ||
| 1472 | if (f->display.x->menubar_widget != 0) | ||
| 1473 | y += f->display.x->menubar_widget->core.height; | ||
| 1474 | XtTranslateCoords (f->display.x->widget, | ||
| 1475 | x, y, &root_x, &root_y); | ||
| 1476 | x = root_x; | ||
| 1477 | y = root_y; | ||
| 1478 | 1646 | ||
| 1479 | /* Create a tree of widget_value objects | 1647 | /* Create a tree of widget_value objects |
| 1480 | representing the panes and their items. */ | 1648 | representing the panes and their items. */ |
| @@ -1577,11 +1745,31 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1577 | } | 1745 | } |
| 1578 | } | 1746 | } |
| 1579 | 1747 | ||
| 1748 | /* Deal with the title, if it is non-nil. */ | ||
| 1749 | if (!NILP (title)) | ||
| 1750 | { | ||
| 1751 | widget_value *wv_title = malloc_widget_value (); | ||
| 1752 | widget_value *wv_sep1 = malloc_widget_value (); | ||
| 1753 | widget_value *wv_sep2 = malloc_widget_value (); | ||
| 1754 | |||
| 1755 | wv_sep2->name = "--"; | ||
| 1756 | wv_sep2->next = first_wv->contents; | ||
| 1757 | |||
| 1758 | wv_sep1->name = "--"; | ||
| 1759 | wv_sep1->next = wv_sep2; | ||
| 1760 | |||
| 1761 | wv_title->name = (char *) XSTRING (title)->data; | ||
| 1762 | wv_title->enabled = True; | ||
| 1763 | wv_title->next = wv_sep1; | ||
| 1764 | first_wv->contents = wv_title; | ||
| 1765 | } | ||
| 1766 | |||
| 1580 | /* Actually create the menu. */ | 1767 | /* Actually create the menu. */ |
| 1581 | menu_id = ++popup_id_tick; | 1768 | menu_id = ++widget_id_tick; |
| 1582 | menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv, | 1769 | menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv, |
| 1583 | f->display.x->widget, 1, 0, | 1770 | f->display.x->widget, 1, 0, |
| 1584 | popup_selection_callback, popup_down_callback); | 1771 | popup_selection_callback, |
| 1772 | popup_deactivate_callback); | ||
| 1585 | 1773 | ||
| 1586 | /* Don't allow any geometry request from the user. */ | 1774 | /* Don't allow any geometry request from the user. */ |
| 1587 | XtSetArg (av[ac], XtNgeometry, 0); ac++; | 1775 | XtSetArg (av[ac], XtNgeometry, 0); ac++; |
| @@ -1593,42 +1781,9 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1593 | /* No selection has been chosen yet. */ | 1781 | /* No selection has been chosen yet. */ |
| 1594 | menu_item_selection = 0; | 1782 | menu_item_selection = 0; |
| 1595 | 1783 | ||
| 1596 | /* If the mouse moves out of the menu before we show the menu, | ||
| 1597 | don't show it at all. */ | ||
| 1598 | if (check_mouse_other_menu_bar (f)) | ||
| 1599 | { | ||
| 1600 | lw_destroy_all_widgets (menu_id); | ||
| 1601 | return Qnil; | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | |||
| 1605 | /* Highlight the menu bar item (if any) that led to this menu. */ | ||
| 1606 | if (menubarp) | ||
| 1607 | { | ||
| 1608 | menubar_item->call_data = (XtPointer) 1; | ||
| 1609 | dispatch_dummy_expose (f->display.x->menubar_widget, x, y); | ||
| 1610 | } | ||
| 1611 | |||
| 1612 | /* Display the menu. */ | 1784 | /* Display the menu. */ |
| 1613 | { | 1785 | lw_popup_menu (menu); |
| 1614 | XButtonPressedEvent dummy; | 1786 | popup_activated_flag = 1; |
| 1615 | XlwMenuWidget mw; | ||
| 1616 | |||
| 1617 | mw = (XlwMenuWidget) ((CompositeWidget)menu)->composite.children[0]; | ||
| 1618 | |||
| 1619 | dummy.type = ButtonPress; | ||
| 1620 | dummy.serial = 0; | ||
| 1621 | dummy.send_event = 0; | ||
| 1622 | dummy.display = XtDisplay (menu); | ||
| 1623 | dummy.window = XtWindow (XtParent (menu)); | ||
| 1624 | dummy.time = CurrentTime; | ||
| 1625 | dummy.button = 0; | ||
| 1626 | dummy.x_root = x; | ||
| 1627 | dummy.y_root = y; | ||
| 1628 | |||
| 1629 | /* We activate directly the lucid implementation. */ | ||
| 1630 | pop_up_menu (mw, &dummy); | ||
| 1631 | } | ||
| 1632 | 1787 | ||
| 1633 | /* No need to check a second time since this is done in the XEvent loop. | 1788 | /* No need to check a second time since this is done in the XEvent loop. |
| 1634 | This slows done the execution. */ | 1789 | This slows done the execution. */ |
| @@ -1639,143 +1794,15 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1639 | /* The mouse moved into a different menu bar item. | 1794 | /* The mouse moved into a different menu bar item. |
| 1640 | We should bring up that item's menu instead. | 1795 | We should bring up that item's menu instead. |
| 1641 | First pop down this menu. */ | 1796 | First pop down this menu. */ |
| 1642 | #if 0 /* xlwmenu.c now does this. */ | ||
| 1643 | XtUngrabPointer ((Widget) | ||
| 1644 | ((XlwMenuWidget) | ||
| 1645 | ((CompositeWidget)menu)->composite.children[0]), | ||
| 1646 | CurrentTime); | ||
| 1647 | #endif | ||
| 1648 | lw_destroy_all_widgets (menu_id); | 1797 | lw_destroy_all_widgets (menu_id); |
| 1649 | goto pop_down; | 1798 | goto pop_down; |
| 1650 | } | 1799 | } |
| 1651 | #endif | 1800 | #endif |
| 1652 | 1801 | ||
| 1653 | /* Process events that apply to the menu. */ | 1802 | /* Process events that apply to the menu. */ |
| 1654 | while (1) | 1803 | popup_get_selection ((XEvent *) 0); |
| 1655 | { | ||
| 1656 | XEvent event; | ||
| 1657 | int queue_and_exit = 0; | ||
| 1658 | int in_this_menu = 0, in_menu_bar = 0; | ||
| 1659 | Widget widget; | ||
| 1660 | |||
| 1661 | XtAppNextEvent (Xt_app_con, &event); | ||
| 1662 | |||
| 1663 | /* Check whether the event happened in the menu | ||
| 1664 | or any child of it. */ | ||
| 1665 | widget = XtWindowToWidget (XDISPLAY event.xany.window); | ||
| 1666 | |||
| 1667 | while (widget) | ||
| 1668 | { | ||
| 1669 | if (widget == menu) | ||
| 1670 | { | ||
| 1671 | in_this_menu = 1; | ||
| 1672 | break; | ||
| 1673 | } | ||
| 1674 | if (widget == f->display.x->menubar_widget) | ||
| 1675 | { | ||
| 1676 | in_menu_bar = 1; | ||
| 1677 | break; | ||
| 1678 | } | ||
| 1679 | widget = XtParent (widget); | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | if (event.type == ButtonRelease) | ||
| 1683 | { | ||
| 1684 | /* Do the work of construct_mouse_click since it can't | ||
| 1685 | be called. Initially, the popup menu has been called | ||
| 1686 | from a ButtonPress in the edit_widget. Then the mouse | ||
| 1687 | has been set to grabbed. Reset it now. */ | ||
| 1688 | x_mouse_grabbed &= ~(1 << event.xbutton.button); | ||
| 1689 | if (!x_mouse_grabbed) | ||
| 1690 | Vmouse_depressed = Qnil; | ||
| 1691 | |||
| 1692 | /* If we release the button soon without selecting anything, | ||
| 1693 | stay in the loop--that is, leave the menu posted. | ||
| 1694 | Otherwise, exit this loop and thus pop down the menu. */ | ||
| 1695 | if (! in_this_menu | ||
| 1696 | && (next_release_must_exit | ||
| 1697 | || !(((XButtonEvent *) (&event))->time - last_event_timestamp | ||
| 1698 | < XINT (Vdouble_click_time)))) | ||
| 1699 | break; | ||
| 1700 | } | ||
| 1701 | /* A button press outside the menu => pop it down. */ | ||
| 1702 | else if (event.type == ButtonPress && !in_this_menu) | ||
| 1703 | break; | ||
| 1704 | else if (event.type == ButtonPress) | ||
| 1705 | next_release_must_exit = 1; | ||
| 1706 | else if (event.type == KeyPress) | ||
| 1707 | { | ||
| 1708 | /* Exit the loop, but first queue this event for reuse. */ | ||
| 1709 | queue_and_exit = 1; | ||
| 1710 | } | ||
| 1711 | else if (event.type == Expose) | ||
| 1712 | process_expose_from_menu (event); | ||
| 1713 | /* If the mouse moves to a different menu bar item, switch to | ||
| 1714 | that item's menu. But only if the button is still held down. */ | ||
| 1715 | else if (event.type == MotionNotify | ||
| 1716 | && x_mouse_grabbed) | ||
| 1717 | { | ||
| 1718 | int event_x = (event.xmotion.x_root | ||
| 1719 | - (f->display.x->widget->core.x | ||
| 1720 | + f->display.x->widget->core.border_width)); | ||
| 1721 | int event_y = (event.xmotion.y_root | ||
| 1722 | - (f->display.x->widget->core.y | ||
| 1723 | + f->display.x->widget->core.border_width)); | ||
| 1724 | |||
| 1725 | if (other_menu_bar_item_p (f, event_x, event_y)) | ||
| 1726 | { | ||
| 1727 | /* The mouse moved into a different menu bar item. | ||
| 1728 | We should bring up that item's menu instead. | ||
| 1729 | First pop down this menu. */ | ||
| 1730 | #if 0 /* xlwmenu.c now does this. */ | ||
| 1731 | XtUngrabPointer ((Widget) | ||
| 1732 | ((XlwMenuWidget) | ||
| 1733 | ((CompositeWidget)menu)->composite.children[0]), | ||
| 1734 | event.xbutton.time); | ||
| 1735 | #endif | ||
| 1736 | lw_destroy_all_widgets (menu_id); | ||
| 1737 | |||
| 1738 | /* Put back an event that will bring up the other item's menu. */ | ||
| 1739 | unread_menu_bar_button (f, event_x); | ||
| 1740 | /* Don't let us select anything in this case. */ | ||
| 1741 | menu_item_selection = 0; | ||
| 1742 | break; | ||
| 1743 | } | ||
| 1744 | } | ||
| 1745 | else if (event.type == UnmapNotify) | ||
| 1746 | { | ||
| 1747 | /* If the menu disappears, there is no need to stay in the | ||
| 1748 | loop. */ | ||
| 1749 | if (event.xunmap.window == menu->core.window) | ||
| 1750 | break; | ||
| 1751 | } | ||
| 1752 | |||
| 1753 | XtDispatchEvent (&event); | ||
| 1754 | |||
| 1755 | if (queue_and_exit || (!in_this_menu && !in_menu_bar)) | ||
| 1756 | { | ||
| 1757 | queue_tmp | ||
| 1758 | = (struct event_queue *) malloc (sizeof (struct event_queue)); | ||
| 1759 | |||
| 1760 | if (queue_tmp != NULL) | ||
| 1761 | { | ||
| 1762 | queue_tmp->event = event; | ||
| 1763 | queue_tmp->next = queue; | ||
| 1764 | queue = queue_tmp; | ||
| 1765 | } | ||
| 1766 | } | ||
| 1767 | if (queue_and_exit) | ||
| 1768 | break; | ||
| 1769 | } | ||
| 1770 | 1804 | ||
| 1771 | pop_down: | 1805 | pop_down: |
| 1772 | /* Unhighlight the menu bar item (if any) that led to this menu. */ | ||
| 1773 | if (menubarp) | ||
| 1774 | { | ||
| 1775 | menubar_item->call_data = (XtPointer) 0; | ||
| 1776 | dispatch_dummy_expose (f->display.x->menubar_widget, x, y); | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | /* fp turned off the following statement and wrote a comment | 1806 | /* fp turned off the following statement and wrote a comment |
| 1780 | that it is unnecessary--that the menu has already disappeared. | 1807 | that it is unnecessary--that the menu has already disappeared. |
| 1781 | I observer that is not so. -- rms. */ | 1808 | I observer that is not so. -- rms. */ |
| @@ -1848,6 +1875,19 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1848 | 1875 | ||
| 1849 | return Qnil; | 1876 | return Qnil; |
| 1850 | } | 1877 | } |
| 1878 | |||
| 1879 | static void | ||
| 1880 | dialog_selection_callback (widget, id, client_data) | ||
| 1881 | Widget widget; | ||
| 1882 | LWLIB_ID id; | ||
| 1883 | XtPointer client_data; | ||
| 1884 | { | ||
| 1885 | if ((int)client_data != -1) | ||
| 1886 | menu_item_selection = (Lisp_Object *) client_data; | ||
| 1887 | BLOCK_INPUT; | ||
| 1888 | lw_destroy_all_widgets (id); | ||
| 1889 | UNBLOCK_INPUT; | ||
| 1890 | } | ||
| 1851 | 1891 | ||
| 1852 | static char * button_names [] = { | 1892 | static char * button_names [] = { |
| 1853 | "button1", "button2", "button3", "button4", "button5", | 1893 | "button1", "button2", "button3", "button4", "button5", |
| @@ -1864,12 +1904,8 @@ xdialog_show (f, menubarp, keymaps, title, error) | |||
| 1864 | int i, nb_buttons=0; | 1904 | int i, nb_buttons=0; |
| 1865 | int dialog_id; | 1905 | int dialog_id; |
| 1866 | Widget menu; | 1906 | Widget menu; |
| 1867 | XlwMenuWidget menubar = (XlwMenuWidget) f->display.x->menubar_widget; | ||
| 1868 | char dialog_name[6]; | 1907 | char dialog_name[6]; |
| 1869 | 1908 | ||
| 1870 | /* This is the menu bar item (if any) that led to this menu. */ | ||
| 1871 | widget_value *menubar_item = 0; | ||
| 1872 | |||
| 1873 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; | 1909 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; |
| 1874 | 1910 | ||
| 1875 | /* Define a queue to save up for later unreading | 1911 | /* Define a queue to save up for later unreading |
| @@ -1987,13 +2023,10 @@ xdialog_show (f, menubarp, keymaps, title, error) | |||
| 1987 | } | 2023 | } |
| 1988 | 2024 | ||
| 1989 | /* Actually create the dialog. */ | 2025 | /* Actually create the dialog. */ |
| 1990 | dialog_id = ++popup_id_tick; | 2026 | dialog_id = ++widget_id_tick; |
| 1991 | menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv, | 2027 | menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv, |
| 1992 | f->display.x->widget, 1, 0, | 2028 | f->display.x->widget, 1, 0, |
| 1993 | dialog_selection_callback, 0); | 2029 | dialog_selection_callback, 0); |
| 1994 | #if 0 /* This causes crashes, and seems to be redundant -- rms. */ | ||
| 1995 | lw_modify_all_widgets (dialog_id, first_wv, True); | ||
| 1996 | #endif | ||
| 1997 | lw_modify_all_widgets (dialog_id, first_wv->contents, True); | 2030 | lw_modify_all_widgets (dialog_id, first_wv->contents, True); |
| 1998 | /* Free the widget_value objects we used to specify the contents. */ | 2031 | /* Free the widget_value objects we used to specify the contents. */ |
| 1999 | free_menubar_widget_value_tree (first_wv); | 2032 | free_menubar_widget_value_tree (first_wv); |
| @@ -2355,6 +2388,7 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 2355 | 2388 | ||
| 2356 | return entry; | 2389 | return entry; |
| 2357 | } | 2390 | } |
| 2391 | |||
| 2358 | #endif /* not USE_X_TOOLKIT */ | 2392 | #endif /* not USE_X_TOOLKIT */ |
| 2359 | 2393 | ||
| 2360 | syms_of_xmenu () | 2394 | syms_of_xmenu () |
| @@ -2362,7 +2396,7 @@ syms_of_xmenu () | |||
| 2362 | staticpro (&menu_items); | 2396 | staticpro (&menu_items); |
| 2363 | menu_items = Qnil; | 2397 | menu_items = Qnil; |
| 2364 | 2398 | ||
| 2365 | popup_id_tick = (1<<16); | 2399 | widget_id_tick = (1<<16); |
| 2366 | defsubr (&Sx_popup_menu); | 2400 | defsubr (&Sx_popup_menu); |
| 2367 | defsubr (&Sx_popup_dialog); | 2401 | defsubr (&Sx_popup_dialog); |
| 2368 | } | 2402 | } |