diff options
| author | Paul Reilly | 1994-09-17 12:53:30 +0000 |
|---|---|---|
| committer | Paul Reilly | 1994-09-17 12:53:30 +0000 |
| commit | d398028fdd7c383685cd02780f7295d08eb2a764 (patch) | |
| tree | 872373bc3f12f3573cde5b6145f1249a7682c3a9 | |
| parent | 1a63b3de3637d53dbbacf83569c2c137971b4c45 (diff) | |
| download | emacs-d398028fdd7c383685cd02780f7295d08eb2a764.tar.gz emacs-d398028fdd7c383685cd02780f7295d08eb2a764.zip | |
*** empty log message ***
| -rw-r--r-- | lwlib/xlwmenu.c | 308 |
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 | |
| 32 | static int pointer_grabbed; | ||
| 33 | static XEvent menu_post_event; | ||
| 35 | 34 | ||
| 36 | static char | 35 | static char |
| 37 | xlwMenuTranslations [] = | 36 | xlwMenuTranslations [] = |
| 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 | ||
| 150 | WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec; | 149 | WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec; |
| 151 | 150 | ||
| 151 | int submenu_destroyed; | ||
| 152 | |||
| 153 | static int next_release_must_exit; | ||
| 154 | |||
| 152 | /* Utilities */ | 155 | /* Utilities */ |
| 153 | static void | 156 | static void |
| 154 | push_new_stack (XlwMenuWidget mw, widget_value* val) | 157 | push_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 | ||
| 173 | static void | 178 | static void |
| 174 | pop_new_stack_if_no_contents (XlwMenuWidget mw) | 179 | pop_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 | ||
| 183 | static void | 189 | static void |
| 184 | make_old_stack_space (XlwMenuWidget mw, int n) | 190 | make_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 */ |
| 203 | static Boolean | 211 | static Boolean |
| 204 | all_dashes_p (char* s) | 212 | all_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 | ||
| 211 | static int | 220 | int |
| 212 | string_width (XlwMenuWidget mw, char* s) | 221 | string_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 | ||
| 221 | static int | 232 | static int |
| 222 | arrow_width (XlwMenuWidget mw) | 233 | arrow_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 | ||
| 234 | static char* | 246 | static char* |
| 235 | resource_widget_value (XlwMenuWidget mw, widget_value* val) | 247 | resource_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 */ |
| 270 | static void | 284 | static void |
| 271 | size_menu_item (XlwMenuWidget mw, widget_value* val, int horizontal_p, | 285 | size_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 | ||
| 302 | static void | 321 | static void |
| 303 | size_menu (XlwMenuWidget mw, int level) | 322 | size_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 */ |
| 352 | static void | 373 | static void |
| 353 | draw_arrow (XlwMenuWidget mw, Window window, GC gc, int x, int y, int width) | 374 | draw_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 | ||
| 367 | static void | 394 | static void |
| 368 | draw_shadow_rectangle (XlwMenuWidget mw, Window window, | 395 | draw_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 | */ |
| 418 | static void | 451 | static void |
| 419 | display_menu_item (XlwMenuWidget mw, widget_value* val, window_state* ws, | 452 | display_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 | ||
| 526 | static void | 578 | static void |
| 527 | display_menu (XlwMenuWidget mw, int level, Boolean just_compute_p, | 579 | display_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 */ |
| 596 | static void | 655 | static void |
| 597 | set_new_state (XlwMenuWidget mw, widget_value* val, int level) | 656 | set_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 | ||
| 607 | static void | 669 | static void |
| 608 | make_windows_if_needed (XlwMenuWidget mw, int n) | 670 | make_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 */ |
| 661 | static void | 725 | static void |
| 662 | fit_to_screen (XlwMenuWidget mw, window_state* ws, window_state* previous_ws, | 726 | fit_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. */ |
| 689 | static void | 756 | static void |
| 690 | remap_menubar (XlwMenuWidget mw) | 757 | remap_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 | ||
| 766 | static Boolean | 834 | static Boolean |
| 767 | motion_event_is_in_menu (XlwMenuWidget mw, XMotionEvent* ev, int level, | 835 | motion_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 | ||
| 779 | static Boolean | 850 | static Boolean |
| 780 | map_event_to_widget_value (XlwMenuWidget mw, XMotionEvent* ev, | 851 | map_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 */ |
| 808 | static void | 882 | static void |
| 809 | make_drawing_gcs (XlwMenuWidget mw) | 883 | make_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 | ||
| 853 | static void | 928 | static void |
| 854 | release_drawing_gcs (XlwMenuWidget mw) | 929 | release_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 | ||
| 872 | static void | 948 | static void |
| 873 | make_shadow_gcs (XlwMenuWidget mw) | 949 | make_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 | ||
| 962 | static void | 1039 | static void |
| 963 | release_shadow_gcs (XlwMenuWidget mw) | 1040 | release_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 | ||
| 969 | static void | 1047 | static void |
| 970 | XlwMenuInitialize (Widget request, Widget new, ArgList args, | 1048 | XlwMenuInitialize (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 | ||
| 1025 | static void | 1115 | static void |
| 1026 | XlwMenuRealize (Widget w, Mask *valueMask, XSetWindowAttributes *attributes) | 1116 | XlwMenuRealize (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. */ |
| 1050 | static void | 1143 | static void |
| 1051 | XlwMenuRedisplay (Widget w, XEvent* ev, Region region) | 1144 | XlwMenuRedisplay (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 | ||
| 1060 | static void | 1164 | static void |
| 1061 | XlwMenuDestroy (Widget w) | 1165 | XlwMenuDestroy (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 | ||
| 1098 | static Boolean | 1215 | static Boolean |
| 1099 | XlwMenuSetValues (Widget current, Widget request, Widget new) | 1216 | XlwMenuSetValues (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 | ||
| 1132 | static void | 1253 | static void |
| 1133 | XlwMenuResize (Widget w) | 1254 | XlwMenuResize (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 */ |
| 1142 | static void | 1275 | static void |
| 1143 | handle_single_motion_event (XlwMenuWidget mw, XMotionEvent* ev) | 1276 | handle_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 | ||
| 1158 | static void | 1295 | static void |
| 1159 | handle_motion_event (XlwMenuWidget mw, XMotionEvent* ev) | 1296 | handle_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 | ||
| 1179 | static void | 1318 | static void |
| 1180 | Start (Widget w, XEvent *ev, String *params, Cardinal *num_params) | 1319 | Start (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 | ||
| 1194 | static void | 1350 | static void |
| 1195 | Drag (Widget w, XEvent *ev, String *params, Cardinal *num_params) | 1351 | Drag (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 | ||
| 1201 | static void | 1361 | static void |
| 1202 | Select (Widget w, XEvent *ev, String *params, Cardinal *num_params) | 1362 | Select (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 */ |
| 1225 | void | 1399 | void |
| 1226 | pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent* event) | 1400 | pop_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; |