aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Reilly1994-09-17 12:53:30 +0000
committerPaul Reilly1994-09-17 12:53:30 +0000
commitd398028fdd7c383685cd02780f7295d08eb2a764 (patch)
tree872373bc3f12f3573cde5b6145f1249a7682c3a9
parent1a63b3de3637d53dbbacf83569c2c137971b4c45 (diff)
downloademacs-d398028fdd7c383685cd02780f7295d08eb2a764.tar.gz
emacs-d398028fdd7c383685cd02780f7295d08eb2a764.zip
*** empty log message ***
-rw-r--r--lwlib/xlwmenu.c308
1 files changed, 249 insertions, 59 deletions
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
index f317fc43338..c47412848da 100644
--- a/lwlib/xlwmenu.c
+++ b/lwlib/xlwmenu.c
@@ -19,9 +19,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19 19
20/* Created by devin@lucid.com */ 20/* Created by devin@lucid.com */
21 21
22#include <stdlib.h>
23#include <unistd.h>
24#include <string.h>
25#include <stdio.h> 22#include <stdio.h>
26 23
27#include <sys/types.h> 24#include <sys/types.h>
@@ -31,12 +28,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
31#include <X11/cursorfont.h> 28#include <X11/cursorfont.h>
32#include <X11/bitmaps/gray> 29#include <X11/bitmaps/gray>
33#include "xlwmenuP.h" 30#include "xlwmenuP.h"
34#include <string.h> 31
32static int pointer_grabbed;
33static XEvent menu_post_event;
35 34
36static char 35static char
37xlwMenuTranslations [] = 36xlwMenuTranslations [] =
38"<BtnDown>: start()\n\ 37"<BtnDown>: start()\n\
39<BtnMotion>: drag()\n\ 38<Motion>: drag()\n\
40<BtnUp>: select()\n\ 39<BtnUp>: select()\n\
41"; 40";
42 41
@@ -59,7 +58,7 @@ xlwMenuResources[] =
59 {XtNarrowSpacing, XtCMargin, XtRDimension, sizeof(Dimension), 58 {XtNarrowSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
60 offset(menu.arrow_spacing), XtRImmediate, (XtPointer)10}, 59 offset(menu.arrow_spacing), XtRImmediate, (XtPointer)10},
61 60
62 {XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, 61 {XmNshadowThickness, XmCShadowThickness, XtRDimension,
63 sizeof (Dimension), offset (menu.shadow_thickness), 62 sizeof (Dimension), offset (menu.shadow_thickness),
64 XtRImmediate, (XtPointer) 2}, 63 XtRImmediate, (XtPointer) 2},
65 {XmNtopShadowColor, XmCTopShadowColor, XtRPixel, sizeof (Pixel), 64 {XmNtopShadowColor, XmCTopShadowColor, XtRPixel, sizeof (Pixel),
@@ -149,9 +148,15 @@ XlwMenuClassRec xlwMenuClassRec =
149 148
150WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec; 149WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec;
151 150
151int submenu_destroyed;
152
153static int next_release_must_exit;
154
152 /* Utilities */ 155 /* Utilities */
153static void 156static void
154push_new_stack (XlwMenuWidget mw, widget_value* val) 157push_new_stack (mw, val)
158 XlwMenuWidget mw;
159 widget_value* val;
155{ 160{
156 if (!mw->menu.new_stack) 161 if (!mw->menu.new_stack)
157 { 162 {
@@ -171,7 +176,8 @@ push_new_stack (XlwMenuWidget mw, widget_value* val)
171} 176}
172 177
173static void 178static void
174pop_new_stack_if_no_contents (XlwMenuWidget mw) 179pop_new_stack_if_no_contents (mw)
180 XlwMenuWidget mw;
175{ 181{
176 if (mw->menu.new_depth) 182 if (mw->menu.new_depth)
177 { 183 {
@@ -181,7 +187,9 @@ pop_new_stack_if_no_contents (XlwMenuWidget mw)
181} 187}
182 188
183static void 189static void
184make_old_stack_space (XlwMenuWidget mw, int n) 190make_old_stack_space (mw, n)
191 XlwMenuWidget mw;
192 int n;
185{ 193{
186 if (!mw->menu.old_stack) 194 if (!mw->menu.old_stack)
187 { 195 {
@@ -201,15 +209,18 @@ make_old_stack_space (XlwMenuWidget mw, int n)
201 209
202 /* Size code */ 210 /* Size code */
203static Boolean 211static Boolean
204all_dashes_p (char* s) 212all_dashes_p (s)
213 char *s;
205{ 214{
206 char* p; 215 char* p;
207 for (p = s; *p == '-'; p++); 216 for (p = s; *p == '-'; p++);
208 return !*p; 217 return !*p;
209} 218}
210 219
211static int 220int
212string_width (XlwMenuWidget mw, char* s) 221string_width (mw, s)
222 XlwMenuWidget mw;
223 char *s;
213{ 224{
214 XCharStruct xcs; 225 XCharStruct xcs;
215 int drop; 226 int drop;
@@ -219,7 +230,8 @@ string_width (XlwMenuWidget mw, char* s)
219} 230}
220 231
221static int 232static int
222arrow_width (XlwMenuWidget mw) 233arrow_width (mw)
234 XlwMenuWidget mw;
223{ 235{
224 return mw->menu.font->ascent / 2 | 1; 236 return mw->menu.font->ascent / 2 | 1;
225} 237}
@@ -232,7 +244,9 @@ nameResource[] =
232}; 244};
233 245
234static char* 246static char*
235resource_widget_value (XlwMenuWidget mw, widget_value* val) 247resource_widget_value (mw, val)
248 XlwMenuWidget mw;
249 widget_value *val;
236{ 250{
237 if (!val->toolkit_data) 251 if (!val->toolkit_data)
238 { 252 {
@@ -268,8 +282,13 @@ resource_widget_value (XlwMenuWidget mw, widget_value* val)
268 282
269/* Returns the sizes of an item */ 283/* Returns the sizes of an item */
270static void 284static void
271size_menu_item (XlwMenuWidget mw, widget_value* val, int horizontal_p, 285size_menu_item (mw, val, horizontal_p, label_width, rest_width, height)
272 int* label_width, int* rest_width, int* height) 286 XlwMenuWidget mw;
287 widget_value* val;
288 int horizontal_p;
289 int* label_width;
290 int* rest_width;
291 int* height;
273{ 292{
274 if (all_dashes_p (val->name)) 293 if (all_dashes_p (val->name))
275 { 294 {
@@ -300,7 +319,9 @@ size_menu_item (XlwMenuWidget mw, widget_value* val, int horizontal_p,
300} 319}
301 320
302static void 321static void
303size_menu (XlwMenuWidget mw, int level) 322size_menu (mw, level)
323 XlwMenuWidget mw;
324 int level;
304{ 325{
305 int label_width = 0; 326 int label_width = 0;
306 int rest_width = 0; 327 int rest_width = 0;
@@ -350,7 +371,13 @@ size_menu (XlwMenuWidget mw, int level)
350 371
351 /* Display code */ 372 /* Display code */
352static void 373static void
353draw_arrow (XlwMenuWidget mw, Window window, GC gc, int x, int y, int width) 374draw_arrow (mw, window, gc, x, y, width)
375 XlwMenuWidget mw;
376 Window window;
377 GC gc;
378 int x;
379 int y;
380 int width;
354{ 381{
355 XPoint points [3]; 382 XPoint points [3];
356 points [0].x = x; 383 points [0].x = x;
@@ -365,8 +392,14 @@ draw_arrow (XlwMenuWidget mw, Window window, GC gc, int x, int y, int width)
365} 392}
366 393
367static void 394static void
368draw_shadow_rectangle (XlwMenuWidget mw, Window window, 395draw_shadow_rectangle (mw, window, x, y, width, height, erase_p)
369 int x, int y, int width, int height, int erase_p) 396 XlwMenuWidget mw;
397 Window window;
398 int x;
399 int y;
400 int width;
401 int height;
402 int erase_p;
370{ 403{
371 Display *dpy = XtDisplay (mw); 404 Display *dpy = XtDisplay (mw);
372 GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc; 405 GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc;
@@ -416,9 +449,14 @@ draw_shadow_rectangle (XlwMenuWidget mw, Window window,
416** the menu item was. 449** the menu item was.
417*/ 450*/
418static void 451static void
419display_menu_item (XlwMenuWidget mw, widget_value* val, window_state* ws, 452display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute_p)
420 XPoint* where, Boolean highlighted_p, Boolean horizontal_p, 453 XlwMenuWidget mw;
421 Boolean just_compute_p) 454 widget_value* val;
455 window_state* ws;
456 XPoint* where;
457 Boolean highlighted_p;
458 Boolean horizontal_p;
459 Boolean just_compute_p;
422{ 460{
423 GC deco_gc; 461 GC deco_gc;
424 GC text_gc; 462 GC text_gc;
@@ -490,7 +528,9 @@ display_menu_item (XlwMenuWidget mw, widget_value* val, window_state* ws,
490 { 528 {
491 int a_w = arrow_width (mw); 529 int a_w = arrow_width (mw);
492 draw_arrow (mw, ws->window, deco_gc, 530 draw_arrow (mw, ws->window, deco_gc,
493 x + label_width + mw->menu.arrow_spacing, 531 x + width - arrow_width (mw)
532 - mw->menu.horizontal_spacing
533 - mw->menu.shadow_thickness,
494 y + v_spacing + shadow, a_w); 534 y + v_spacing + shadow, a_w);
495 } 535 }
496 else if (val->key) 536 else if (val->key)
@@ -509,10 +549,22 @@ display_menu_item (XlwMenuWidget mw, widget_value* val, window_state* ws,
509 x + shadow, y + shadow, 549 x + shadow, y + shadow,
510 label_width + h_spacing - 1, 550 label_width + h_spacing - 1,
511 font_ascent + font_descent + 2 * v_spacing - 1); 551 font_ascent + font_descent + 2 * v_spacing - 1);
552 draw_shadow_rectangle (mw, ws->window, x, y, width, height,
553 False);
512#else 554#else
513 highlighted_p = True; 555 highlighted_p = True;
514#endif 556#endif
515 } 557 }
558 else
559 {
560 XDrawRectangle (XtDisplay (mw), ws->window,
561 mw->menu.background_gc,
562 x + shadow, y + shadow,
563 label_width + h_spacing - 1,
564 font_ascent + font_descent + 2 * v_spacing - 1);
565 draw_shadow_rectangle (mw, ws->window, x, y, width, height,
566 True);
567 }
516 568
517 if (highlighted_p) 569 if (highlighted_p)
518 draw_shadow_rectangle (mw, ws->window, x, y, width, height, False); 570 draw_shadow_rectangle (mw, ws->window, x, y, width, height, False);
@@ -524,9 +576,16 @@ display_menu_item (XlwMenuWidget mw, widget_value* val, window_state* ws,
524} 576}
525 577
526static void 578static void
527display_menu (XlwMenuWidget mw, int level, Boolean just_compute_p, 579display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
528 XPoint* highlighted_pos, XPoint* hit, widget_value** hit_return, 580 this, that)
529 widget_value* this, widget_value* that) 581 XlwMenuWidget mw;
582 int level;
583 Boolean just_compute_p;
584 XPoint* highlighted_pos;
585 XPoint* hit;
586 widget_value** hit_return;
587 widget_value* this;
588 widget_value* that;
530{ 589{
531 widget_value* val; 590 widget_value* val;
532 widget_value* following_item; 591 widget_value* following_item;
@@ -594,7 +653,10 @@ display_menu (XlwMenuWidget mw, int level, Boolean just_compute_p,
594 653
595 /* Motion code */ 654 /* Motion code */
596static void 655static void
597set_new_state (XlwMenuWidget mw, widget_value* val, int level) 656set_new_state (mw, val, level)
657 XlwMenuWidget mw;
658 widget_value* val;
659 int level;
598{ 660{
599 int i; 661 int i;
600 662
@@ -605,7 +667,9 @@ set_new_state (XlwMenuWidget mw, widget_value* val, int level)
605} 667}
606 668
607static void 669static void
608make_windows_if_needed (XlwMenuWidget mw, int n) 670make_windows_if_needed (mw, n)
671 XlwMenuWidget mw;
672 int n;
609{ 673{
610 int i; 674 int i;
611 int start_at; 675 int start_at;
@@ -622,7 +686,7 @@ make_windows_if_needed (XlwMenuWidget mw, int n)
622 xswa.background_pixel = mw->core.background_pixel; 686 xswa.background_pixel = mw->core.background_pixel;
623 xswa.border_pixel = mw->core.border_pixel; 687 xswa.border_pixel = mw->core.border_pixel;
624 xswa.event_mask = 688 xswa.event_mask =
625 ExposureMask | ButtonMotionMask | PointerMotionHintMask 689 ExposureMask | PointerMotionMask | PointerMotionHintMask
626 | ButtonReleaseMask | ButtonPressMask; 690 | ButtonReleaseMask | ButtonPressMask;
627 xswa.cursor = mw->menu.cursor_shape; 691 xswa.cursor = mw->menu.cursor_shape;
628 mask = CWSaveUnder | CWOverrideRedirect | CWBackPixel | CWBorderPixel 692 mask = CWSaveUnder | CWOverrideRedirect | CWBackPixel | CWBorderPixel
@@ -659,8 +723,11 @@ make_windows_if_needed (XlwMenuWidget mw, int n)
659 723
660/* Make the window fit in the screen */ 724/* Make the window fit in the screen */
661static void 725static void
662fit_to_screen (XlwMenuWidget mw, window_state* ws, window_state* previous_ws, 726fit_to_screen (mw, ws, previous_ws, horizontal_p)
663 Boolean horizontal_p) 727 XlwMenuWidget mw;
728 window_state* ws;
729 window_state* previous_ws;
730 Boolean horizontal_p;
664{ 731{
665 int screen_width = WidthOfScreen (XtScreen (mw)); 732 int screen_width = WidthOfScreen (XtScreen (mw));
666 int screen_height = HeightOfScreen (XtScreen (mw)); 733 int screen_height = HeightOfScreen (XtScreen (mw));
@@ -687,7 +754,8 @@ fit_to_screen (XlwMenuWidget mw, window_state* ws, window_state* previous_ws,
687 754
688/* Updates old_stack from new_stack and redisplays. */ 755/* Updates old_stack from new_stack and redisplays. */
689static void 756static void
690remap_menubar (XlwMenuWidget mw) 757remap_menubar (mw)
758 XlwMenuWidget mw;
691{ 759{
692 int i; 760 int i;
693 int last_same; 761 int last_same;
@@ -764,8 +832,11 @@ remap_menubar (XlwMenuWidget mw)
764} 832}
765 833
766static Boolean 834static Boolean
767motion_event_is_in_menu (XlwMenuWidget mw, XMotionEvent* ev, int level, 835motion_event_is_in_menu (mw, ev, level, relative_pos)
768 XPoint* relative_pos) 836 XlwMenuWidget mw;
837 XMotionEvent* ev;
838 int level;
839 XPoint* relative_pos;
769{ 840{
770 window_state* ws = &mw->menu.windows [level]; 841 window_state* ws = &mw->menu.windows [level];
771 int x = level == 0 ? ws->x : ws->x + mw->menu.shadow_thickness; 842 int x = level == 0 ? ws->x : ws->x + mw->menu.shadow_thickness;
@@ -777,8 +848,11 @@ motion_event_is_in_menu (XlwMenuWidget mw, XMotionEvent* ev, int level,
777} 848}
778 849
779static Boolean 850static Boolean
780map_event_to_widget_value (XlwMenuWidget mw, XMotionEvent* ev, 851map_event_to_widget_value (mw, ev, val, level)
781 widget_value** val, int* level) 852 XlwMenuWidget mw;
853 XMotionEvent* ev;
854 widget_value** val;
855 int* level;
782{ 856{
783 int i; 857 int i;
784 XPoint relative_pos; 858 XPoint relative_pos;
@@ -806,7 +880,8 @@ map_event_to_widget_value (XlwMenuWidget mw, XMotionEvent* ev,
806 880
807 /* Procedures */ 881 /* Procedures */
808static void 882static void
809make_drawing_gcs (XlwMenuWidget mw) 883make_drawing_gcs (mw)
884 XlwMenuWidget mw;
810{ 885{
811 XGCValues xgcv; 886 XGCValues xgcv;
812 887
@@ -851,7 +926,8 @@ make_drawing_gcs (XlwMenuWidget mw)
851} 926}
852 927
853static void 928static void
854release_drawing_gcs (XlwMenuWidget mw) 929release_drawing_gcs (mw)
930 XlwMenuWidget mw;
855{ 931{
856 XtReleaseGC ((Widget) mw, mw->menu.foreground_gc); 932 XtReleaseGC ((Widget) mw, mw->menu.foreground_gc);
857 XtReleaseGC ((Widget) mw, mw->menu.button_gc); 933 XtReleaseGC ((Widget) mw, mw->menu.button_gc);
@@ -870,7 +946,8 @@ release_drawing_gcs (XlwMenuWidget mw)
870 ? ((unsigned long) (x)) : ((unsigned long) (y))) 946 ? ((unsigned long) (x)) : ((unsigned long) (y)))
871 947
872static void 948static void
873make_shadow_gcs (XlwMenuWidget mw) 949make_shadow_gcs (mw)
950 XlwMenuWidget mw;
874{ 951{
875 XGCValues xgcv; 952 XGCValues xgcv;
876 unsigned long pm = 0; 953 unsigned long pm = 0;
@@ -960,15 +1037,19 @@ make_shadow_gcs (XlwMenuWidget mw)
960 1037
961 1038
962static void 1039static void
963release_shadow_gcs (XlwMenuWidget mw) 1040release_shadow_gcs (mw)
1041 XlwMenuWidget mw;
964{ 1042{
965 XtReleaseGC ((Widget) mw, mw->menu.shadow_top_gc); 1043 XtReleaseGC ((Widget) mw, mw->menu.shadow_top_gc);
966 XtReleaseGC ((Widget) mw, mw->menu.shadow_bottom_gc); 1044 XtReleaseGC ((Widget) mw, mw->menu.shadow_bottom_gc);
967} 1045}
968 1046
969static void 1047static void
970XlwMenuInitialize (Widget request, Widget new, ArgList args, 1048XlwMenuInitialize (request, new, args, num_args)
971 Cardinal *num_args) 1049 Widget request;
1050 Widget new;
1051 ArgList args;
1052 Cardinal *num_args;
972{ 1053{
973 /* Get the GCs and the widget size */ 1054 /* Get the GCs and the widget size */
974 XlwMenuWidget mw = (XlwMenuWidget)new; 1055 XlwMenuWidget mw = (XlwMenuWidget)new;
@@ -979,6 +1060,15 @@ XlwMenuInitialize (Widget request, Widget new, ArgList args,
979 Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw))); 1060 Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
980 Display* display = XtDisplay (mw); 1061 Display* display = XtDisplay (mw);
981 1062
1063#if 0
1064 widget_value *tem = (widget_value *) XtMalloc (sizeof (widget_value));
1065
1066 /* _XtCreate is freeing the object that was passed to us,
1067 so make a copy that we will actually keep. */
1068 lwlib_bcopy (mw->menu.contents, tem, sizeof (widget_value));
1069 mw->menu.contents = tem;
1070#endif
1071
982/* mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */ 1072/* mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */
983 mw->menu.cursor = mw->menu.cursor_shape; 1073 mw->menu.cursor = mw->menu.cursor_shape;
984 1074
@@ -1023,7 +1113,10 @@ XlwMenuClassInitialize ()
1023} 1113}
1024 1114
1025static void 1115static void
1026XlwMenuRealize (Widget w, Mask *valueMask, XSetWindowAttributes *attributes) 1116XlwMenuRealize (w, valueMask, attributes)
1117 Widget w;
1118 Mask *valueMask;
1119 XSetWindowAttributes *attributes;
1027{ 1120{
1028 XlwMenuWidget mw = (XlwMenuWidget)w; 1121 XlwMenuWidget mw = (XlwMenuWidget)w;
1029 XSetWindowAttributes xswa; 1122 XSetWindowAttributes xswa;
@@ -1048,21 +1141,39 @@ XlwMenuRealize (Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
1048 receives expose events through Xt. So we repaint all the other panes 1141 receives expose events through Xt. So we repaint all the other panes
1049 when receiving an Expose event. */ 1142 when receiving an Expose event. */
1050static void 1143static void
1051XlwMenuRedisplay (Widget w, XEvent* ev, Region region) 1144XlwMenuRedisplay (w, ev, region)
1145 Widget w;
1146 XEvent* ev;
1147 Region region;
1052{ 1148{
1053 XlwMenuWidget mw = (XlwMenuWidget)w; 1149 XlwMenuWidget mw = (XlwMenuWidget)w;
1054 int i; 1150 int i;
1055 1151
1152 /* If we have a depth beyond 1, it's because a submenu was displayed.
1153 If the submenu has been destroyed, set the depth back to 1. */
1154 if (submenu_destroyed)
1155 {
1156 mw->menu.old_depth = 1;
1157 submenu_destroyed = 0;
1158 }
1159
1056 for (i = 0; i < mw->menu.old_depth; i++) 1160 for (i = 0; i < mw->menu.old_depth; i++)
1057 display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL); 1161 display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL);
1058} 1162}
1059 1163
1060static void 1164static void
1061XlwMenuDestroy (Widget w) 1165XlwMenuDestroy (w)
1166 Widget w;
1062{ 1167{
1063 int i; 1168 int i;
1064 XlwMenuWidget mw = (XlwMenuWidget) w; 1169 XlwMenuWidget mw = (XlwMenuWidget) w;
1065 1170
1171 if (pointer_grabbed)
1172 XtUngrabPointer ((Widget)w, CurrentTime);
1173 pointer_grabbed = 0;
1174
1175 submenu_destroyed = 1;
1176
1066 release_drawing_gcs (mw); 1177 release_drawing_gcs (mw);
1067 release_shadow_gcs (mw); 1178 release_shadow_gcs (mw);
1068 1179
@@ -1071,6 +1182,12 @@ XlwMenuDestroy (Widget w)
1071 XFreePixmap (XtDisplay (mw), mw->menu.gray_pixmap); 1182 XFreePixmap (XtDisplay (mw), mw->menu.gray_pixmap);
1072 mw->menu.gray_pixmap = (Pixmap) -1; 1183 mw->menu.gray_pixmap = (Pixmap) -1;
1073 1184
1185#if 0
1186 /* Do free mw->menu.contents because nowadays we copy it
1187 during initialization. */
1188 XtFree (mw->menu.contents);
1189#endif
1190
1074 /* Don't free mw->menu.contents because that comes from our creator. 1191 /* Don't free mw->menu.contents because that comes from our creator.
1075 The `*_stack' elements are just pointers into `contents' so leave 1192 The `*_stack' elements are just pointers into `contents' so leave
1076 that alone too. But free the stacks themselves. */ 1193 that alone too. But free the stacks themselves. */
@@ -1096,7 +1213,10 @@ XlwMenuDestroy (Widget w)
1096} 1213}
1097 1214
1098static Boolean 1215static Boolean
1099XlwMenuSetValues (Widget current, Widget request, Widget new) 1216XlwMenuSetValues (current, request, new)
1217 Widget current;
1218 Widget request;
1219 Widget new;
1100{ 1220{
1101 XlwMenuWidget oldmw = (XlwMenuWidget)current; 1221 XlwMenuWidget oldmw = (XlwMenuWidget)current;
1102 XlwMenuWidget newmw = (XlwMenuWidget)new; 1222 XlwMenuWidget newmw = (XlwMenuWidget)new;
@@ -1109,7 +1229,8 @@ XlwMenuSetValues (Widget current, Widget request, Widget new)
1109 redisplay = True; 1229 redisplay = True;
1110 1230
1111 if (newmw->core.background_pixel != oldmw->core.background_pixel 1231 if (newmw->core.background_pixel != oldmw->core.background_pixel
1112 || newmw->menu.foreground != oldmw->menu.foreground) 1232 || newmw->menu.foreground != oldmw->menu.foreground
1233 || newmw->menu.font != oldmw->menu.font)
1113 { 1234 {
1114 release_drawing_gcs (newmw); 1235 release_drawing_gcs (newmw);
1115 make_drawing_gcs (newmw); 1236 make_drawing_gcs (newmw);
@@ -1130,17 +1251,31 @@ XlwMenuSetValues (Widget current, Widget request, Widget new)
1130} 1251}
1131 1252
1132static void 1253static void
1133XlwMenuResize (Widget w) 1254XlwMenuResize (w)
1255 Widget w;
1134{ 1256{
1135 XlwMenuWidget mw = (XlwMenuWidget)w; 1257 XlwMenuWidget mw = (XlwMenuWidget)w;
1136 1258
1137 mw->menu.windows [0].width = mw->core.width; 1259 if (mw->menu.popped_up)
1138 mw->menu.windows [0].height = mw->core.height; 1260 {
1261 /* Don't allow the popup menu to resize itself. */
1262 mw->core.width = mw->menu.windows [0].width;
1263 mw->core.height = mw->menu.windows [0].height;
1264 mw->core.parent->core.width = mw->core.width ;
1265 mw->core.parent->core.height = mw->core.height ;
1266 }
1267 else
1268 {
1269 mw->menu.windows [0].width = mw->core.width;
1270 mw->menu.windows [0].height = mw->core.height;
1271 }
1139} 1272}
1140 1273
1141 /* Action procedures */ 1274 /* Action procedures */
1142static void 1275static void
1143handle_single_motion_event (XlwMenuWidget mw, XMotionEvent* ev) 1276handle_single_motion_event (mw, ev)
1277 XlwMenuWidget mw;
1278 XMotionEvent* ev;
1144{ 1279{
1145 widget_value* val; 1280 widget_value* val;
1146 int level; 1281 int level;
@@ -1151,12 +1286,16 @@ handle_single_motion_event (XlwMenuWidget mw, XMotionEvent* ev)
1151 set_new_state (mw, val, level); 1286 set_new_state (mw, val, level);
1152 remap_menubar (mw); 1287 remap_menubar (mw);
1153 1288
1289#if 0
1154 /* Sync with the display. Makes it feel better on X terms. */ 1290 /* Sync with the display. Makes it feel better on X terms. */
1155 XSync (XtDisplay (mw), False); 1291 XSync (XtDisplay (mw), False);
1292#endif
1156} 1293}
1157 1294
1158static void 1295static void
1159handle_motion_event (XlwMenuWidget mw, XMotionEvent* ev) 1296handle_motion_event (mw, ev)
1297 XlwMenuWidget mw;
1298 XMotionEvent* ev;
1160{ 1299{
1161 int x = ev->x_root; 1300 int x = ev->x_root;
1162 int y = ev->y_root; 1301 int y = ev->y_root;
@@ -1177,10 +1316,25 @@ handle_motion_event (XlwMenuWidget mw, XMotionEvent* ev)
1177} 1316}
1178 1317
1179static void 1318static void
1180Start (Widget w, XEvent *ev, String *params, Cardinal *num_params) 1319Start (w, ev, params, num_params)
1320 Widget w;
1321 XEvent *ev;
1322 String *params;
1323 Cardinal *num_params;
1181{ 1324{
1182 XlwMenuWidget mw = (XlwMenuWidget)w; 1325 XlwMenuWidget mw = (XlwMenuWidget)w;
1183 1326
1327 if (!mw->menu.popped_up)
1328 {
1329 menu_post_event = *ev;
1330 pop_up_menu (mw, ev);
1331 }
1332 else
1333 /* If we push a button while the menu is posted semipermanently,
1334 releasing the button should always pop the menu down. */
1335 next_release_must_exit = 1;
1336
1337#if 0
1184 XtCallCallbackList ((Widget)mw, mw->menu.open, NULL); 1338 XtCallCallbackList ((Widget)mw, mw->menu.open, NULL);
1185 1339
1186 /* notes the absolute position of the menubar window */ 1340 /* notes the absolute position of the menubar window */
@@ -1189,22 +1343,42 @@ Start (Widget w, XEvent *ev, String *params, Cardinal *num_params)
1189 1343
1190 /* handles the down like a move, slots are compatible */ 1344 /* handles the down like a move, slots are compatible */
1191 handle_motion_event (mw, &ev->xmotion); 1345 handle_motion_event (mw, &ev->xmotion);
1346#endif
1347
1192} 1348}
1193 1349
1194static void 1350static void
1195Drag (Widget w, XEvent *ev, String *params, Cardinal *num_params) 1351Drag (w, ev, params, num_params)
1352 Widget w;
1353 XEvent *ev;
1354 String *params;
1355 Cardinal *num_params;
1196{ 1356{
1197 XlwMenuWidget mw = (XlwMenuWidget)w; 1357 XlwMenuWidget mw = (XlwMenuWidget)w;
1198 handle_motion_event (mw, &ev->xmotion); 1358 handle_motion_event (mw, &ev->xmotion);
1199} 1359}
1200 1360
1201static void 1361static void
1202Select (Widget w, XEvent *ev, String *params, Cardinal *num_params) 1362Select (w, ev, params, num_params)
1363 Widget w;
1364 XEvent *ev;
1365 String *params;
1366 Cardinal *num_params;
1203{ 1367{
1204 XlwMenuWidget mw = (XlwMenuWidget)w; 1368 XlwMenuWidget mw = (XlwMenuWidget)w;
1205 widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; 1369 widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1];
1206 1370
1207 /* pop down everything */ 1371 /* If user releases the button quickly, without selecting anything,
1372 after the initial down-click that brought the menu up,
1373 do nothing. */
1374 if ((selected_item == 0
1375 || ((widget_value *) selected_item)->call_data == 0)
1376 && !next_release_must_exit
1377 && (ev->xbutton.time - menu_post_event.xbutton.time
1378 < XtGetMultiClickTime (XtDisplay (w))))
1379 return;
1380
1381 /* pop down everything. */
1208 mw->menu.new_depth = 1; 1382 mw->menu.new_depth = 1;
1209 remap_menubar (mw); 1383 remap_menubar (mw);
1210 1384
@@ -1223,7 +1397,9 @@ Select (Widget w, XEvent *ev, String *params, Cardinal *num_params)
1223 1397
1224 /* Special code to pop-up a menu */ 1398 /* Special code to pop-up a menu */
1225void 1399void
1226pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent* event) 1400pop_up_menu (mw, event)
1401 XlwMenuWidget mw;
1402 XButtonPressedEvent* event;
1227{ 1403{
1228 int x = event->x_root; 1404 int x = event->x_root;
1229 int y = event->y_root; 1405 int y = event->y_root;
@@ -1232,6 +1408,8 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent* event)
1232 int borderwidth = mw->menu.shadow_thickness; 1408 int borderwidth = mw->menu.shadow_thickness;
1233 Screen* screen = XtScreen (mw); 1409 Screen* screen = XtScreen (mw);
1234 1410
1411 next_release_must_exit = 0;
1412
1235 XtCallCallbackList ((Widget)mw, mw->menu.open, NULL); 1413 XtCallCallbackList ((Widget)mw, mw->menu.open, NULL);
1236 1414
1237 size_menu (mw, 0); 1415 size_menu (mw, 0);
@@ -1255,11 +1433,23 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent* event)
1255 XtParent (mw)->core.border_width); 1433 XtParent (mw)->core.border_width);
1256 XtPopup (XtParent (mw), XtGrabExclusive); 1434 XtPopup (XtParent (mw), XtGrabExclusive);
1257 display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL); 1435 display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
1436#ifdef emacs
1437 x_catch_errors ();
1438#endif
1258 XtGrabPointer ((Widget)mw, False, 1439 XtGrabPointer ((Widget)mw, False,
1259 (ButtonMotionMask | PointerMotionHintMask | ButtonReleaseMask 1440 (PointerMotionMask | PointerMotionHintMask | ButtonReleaseMask
1260 | ButtonPressMask), 1441 | ButtonPressMask),
1261 GrabModeAsync, GrabModeAsync, None, mw->menu.cursor_shape, 1442 GrabModeAsync, GrabModeAsync, None, mw->menu.cursor_shape,
1262 event->time); 1443 event->time);
1444 pointer_grabbed = 1;
1445#ifdef emacs
1446 if (x_had_errors_p ())
1447 {
1448 pointer_grabbed = 0;
1449 XtUngrabPointer ((Widget)mw, event->time);
1450 }
1451 x_uncatch_errors ();
1452#endif
1263 1453
1264 mw->menu.windows [0].x = x + borderwidth; 1454 mw->menu.windows [0].x = x + borderwidth;
1265 mw->menu.windows [0].y = y + borderwidth; 1455 mw->menu.windows [0].y = y + borderwidth;