2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: MenuButton.c /main/9 1998/04/09 17:51:40 mgreess $
25 * (c) Copyright 1996 Digital Equipment Corporation.
26 * (c) Copyright 1996 Hewlett-Packard Company.
27 * (c) Copyright 1996 International Business Machines Corp.
28 * (c) Copyright 1986, 1991, 1996 Sun Microsystems, Inc.
29 * (c) Copyright 1996 Novell, Inc.
30 * (c) Copyright 1996 FUJITSU LIMITED.
31 * (c) Copyright 1996 Hitachi.
35 * Copyright (C) 1986,1991 Sun Microsystems, Inc
36 * All rights reserved.
37 * Notice of copyright on this source code
38 * product does not indicate publication.
40 * RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by
41 * the U.S. Government is subject to restrictions as set forth
42 * in subparagraph (c)(1)(ii) of the Rights in Technical Data
43 * and Computer Software Clause at DFARS 252.227-7013 (Oct. 1988)
44 * and FAR 52.227-19 (c) (June 1987).
46 * Sun Microsystems, Inc., 2550 Garcia Avenue,
47 * Mountain View, California 94043.
51 * The DtMenuButton widget is rigged with the Motif widget binary compatibilit
52 * mechanism. All Motif-specific changes for this mechanism are preceded
53 * by a comment including the string "MotifBc".
55 * For a description of the Motif widget binary compatibility mechanism
56 * see the reference manual entry on XmResolveAllPartOffsets().
60 #include <Dt/DtMsgsP.h>
61 #include "MenuButtonP.h"
63 #include <Xm/LabelP.h>
64 #include <Xm/MenuUtilP.h>
67 #include <X11/keysymdef.h>
68 #include "DtWidgetI.h"
73 #define DtMenuButtonIndex (XmLabelIndex + 1)
74 static XmOffsetPtr ipot; /* Instance part offset table */
75 static XmOffsetPtr cpot; /* Constraint part offset table */
78 #define Max(x, y) (((x) > (y)) ? (x) : (y))
81 #define GLYPH_PIX_SPACE 4 /* pixels between label and bit map */
86 #define CascadingCallback(w) XmField(w,ipot,DtMenuButton,cascading_callback,XtCallbackList)
87 #define MenuRect(w) XmField(w,ipot,DtMenuButton,menu_rect,XRectangle)
88 #define LNormalGC(w) XmField(w,ipot,XmLabel,normal_GC,GC)
89 #define LAlignment(w) XmField(w,ipot,XmLabel,alignment,unsigned char)
90 #define LRecomputeSize(w) XmField(w,ipot,XmLabel,recompute_size,Boolean)
91 #define LLabelType(w) XmField(w,ipot,XmLabel,label_type,unsigned char)
93 /* Access macro definitions */
94 #define MB_PVT_SMENU(mb) XmField(mb,ipot,DtMenuButton,private_submenu,Boolean)
95 #define MB_LAST_TIMESTAMP(mb) XmField(mb,ipot,DtMenuButton,last_timestamp,Time)
96 #define MB_SMENU(mb) XmField(mb,ipot,DtMenuButton,submenu,Widget)
97 #define MB_PIXMAP(mb) XmField(mb,ipot,DtMenuButton,menu_pixmap,Pixmap)
98 #define MB_GLYPH_X(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).x
99 #define MB_GLYPH_Y(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).y
100 #define MB_GLYPH_WIDTH(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).width
101 #define MB_GLYPH_HEIGHT(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).height
102 #define MB_ARMED(mb) XmField(mb,ipot,DtMenuButton,armed,Boolean)
103 #define MB_POPPED_UP(mb) XmField(mb,ipot,DtMenuButton,popped_up,Boolean)
104 #define MB_GC(mb) XmField(mb,ipot,DtMenuButton,gc,GC)
107 /******** Static Function Declarations ********/
108 static void ClassInitialize (void);
110 static void AdjustMenuButtonSize(
111 DtMenuButtonWidget menubtn,
113 Boolean adjustHeight) ;
115 DtMenuButtonWidget mb) ;
116 static void ArmAndActivate(
120 Cardinal *num_params) ;
122 static void CalculateMenuGlyphSize(
123 DtMenuButtonWidget menubtn) ;
124 static void CallCascadingCallbacks(
131 DtMenuButtonWidget mb,
133 static void DrawArrow(
135 static void Draw3DShadows(
136 DtMenuButtonWidget mb) ;
137 static void DrawMenuGlyph(
138 DtMenuButtonWidget mb) ;
141 DtMenuButtonWidget mb);
143 static void Initialize(
147 Cardinal *num_args) ;
149 static void LocateMenuGlyph(
150 DtMenuButtonWidget menubtn) ;
152 static void MenuButtonHandler(
156 Boolean *cont_to_dispatch) ;
159 DtMenuButtonWidget mb,
161 Boolean call_cbacks );
163 static void Redisplay(
174 Cardinal *num_param) ;
175 static Boolean SetValues(
180 Cardinal *num_args) ;
181 static void GetTopManager(
183 Widget *topManager) ;
186 /******** End Static Function Declarations ********/
190 * event translation tables for menubutton.
193 static char menuButton_translations[] = "\
194 <Key>space:Select()\n\
195 <Key>osfSelect:Select()";
197 static XtActionsRec menuButton_actions [] = {
202 #define DtOffset(field) XmPartOffset(DtMenuButton,field)
203 #define XmPrimOffset(field) XmPartOffset(XmPrimitive,field)
204 #define XmLabelOffset(field) XmPartOffset(XmLabel,field)
205 static XmPartResource resources[] = {
207 DtNcascadingCallback,
210 sizeof (XtCallbackList),
211 DtOffset(cascading_callback),
217 DtCMenuWidget, /* submenu */
227 XmRPrimForegroundPixmap,
229 DtOffset(menu_pixmap),
231 (XtPointer) XmUNSPECIFIED_PIXMAP
236 XmRHorizontalDimension,
238 XmPrimOffset(shadow_thickness),
247 XmPrimOffset(traversal_on),
252 XmNhighlightThickness,
253 XmCHighlightThickness,
254 XmRHorizontalDimension,
256 XmPrimOffset(highlight_thickness),
263 XmRHorizontalDimension,
265 XmLabelOffset(margin_width),
271 externaldef(xmmenubuttonclassrec)
272 DtMenuButtonClassRec dtMenuButtonClassRec = {
273 { /* core class record */
274 (WidgetClass) &xmLabelClassRec, /* superclass ptr */
275 "DtMenuButton", /* class_name */
276 sizeof(DtMenuButtonPart), /* size of Pulldown widget */
277 (XtProc)ClassInitialize, /* class init proc */
278 NULL, /* chained class init */
279 FALSE, /* class is not init'ed */
280 Initialize, /* widget init proc */
281 NULL, /* init_hook proc */
282 XtInheritRealize, /* widget realize proc */
283 menuButton_actions, /* class action table */
284 XtNumber (menuButton_actions), /* num of actions */
285 (XtResourceList)resources, /* this class's resource list*/
286 XtNumber (resources), /* resource_count */
287 NULLQUARK, /* xrm_class */
288 TRUE, /* compress motion */
289 XtExposeCompressMaximal, /* compress exposure */
290 TRUE, /* compress enter-leave */
291 FALSE, /* no VisibilityNotify */
292 Destroy, /* class destroy proc */
293 Resize, /* class resize proc */
294 Redisplay, /* expose proc */
295 SetValues, /* set_value proc */
296 NULL, /* set_value_hook proc */
297 XtInheritSetValuesAlmost, /* set_value_almost proc */
298 NULL, /* get_values_hook */
299 NULL, /* class accept focus proc */
300 XtVersionDontCheck, /* current version */
301 NULL, /* callback offset list */
302 menuButton_translations, /* default translation table */
303 XtInheritQueryGeometry, /* query geo proc */
304 NULL, /* display accelerator*/
305 (XtPointer)NULL, /* extension */
308 /* Primitive Class record */
309 XmInheritWidgetProc, /* border_highlight */
310 XmInheritWidgetProc, /* border_uhighlight */
311 XtInheritTranslations, /* translations */
312 ArmAndActivate, /* arm & activate */
313 NULL, /* get resources */
314 0, /* num get_resources */
315 (XtPointer)NULL, /* extension */
317 { /* Label Class record */
318 XmInheritWidgetProc, /* set override callback */
319 XmInheritMenuProc, /* menu procedures */
320 XtInheritTranslations, /* menu traversal xlation */
321 NULL, /* extension */
323 { /* menu_button class record */
324 NULL, /* extension */
330 * Now make a public symbol that points to this class record.
333 externaldef(dtmenubuttonwidgetclass)
334 WidgetClass dtMenuButtonWidgetClass =
335 (WidgetClass) &dtMenuButtonClassRec;
338 * MotifBc, to calculate offset var. ipot
341 ClassInitialize(void)
343 XmResolveAllPartOffsets(dtMenuButtonWidgetClass, &ipot, &cpot);
348 DtMenuButtonWidget mb )
350 if (XtIsRealized((Widget)mb))
351 XmeDrawShadows (XtDisplay (mb), XtWindow (mb),
352 mb->primitive.top_shadow_GC,
353 mb->primitive.bottom_shadow_GC,
354 mb->primitive.highlight_thickness,
355 mb->primitive.highlight_thickness,
357 mb->primitive.highlight_thickness,
358 mb->core.height - 2 *
359 mb->primitive.highlight_thickness,
360 mb->primitive.shadow_thickness,
361 (MB_ARMED(mb) == TRUE) ? XmSHADOW_IN: XmSHADOW_OUT);
367 DtMenuButtonWidget mb )
369 if ((MB_GLYPH_WIDTH(mb) != 0))
370 if(MB_PIXMAP(mb) != XmUNSPECIFIED_PIXMAP)
371 XCopyArea (XtDisplay(mb),
375 MB_GLYPH_WIDTH(mb), MB_GLYPH_HEIGHT(mb),
376 MB_GLYPH_X(mb), MB_GLYPH_Y(mb));
378 DrawArrow((Widget)mb);
382 * Redisplay the widget.
390 if (XtIsRealized (mb)) {
391 /* Label expose method does the initial work */
394 expose = xmLabelClassRec.core_class.expose;
396 (* expose)(mb, event, region) ;
398 DrawMenuGlyph((DtMenuButtonWidget) mb);
399 Draw3DShadows ((DtMenuButtonWidget) mb);
405 DtMenuButtonWidget mb )
407 XmProcessTraversal( (Widget) mb, XmTRAVERSE_CURRENT);
408 if (MB_ARMED(mb) == FALSE) {
420 Cardinal *num_params )
422 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
424 if(MB_SMENU(mb) == (Widget)NULL ||
425 event == (XEvent*) NULL)
428 if (!_XmIsEventUnique(event))
431 Popup(mb, event, TRUE);
432 _XmSetInDragMode((Widget)mb,FALSE);
433 if (!XmProcessTraversal(MB_SMENU(mb), XmTRAVERSE_CURRENT))
434 XtSetKeyboardFocus(XtParent(MB_SMENU(mb)), MB_SMENU(mb));
436 _XmRecordEvent(event);
442 DtMenuButtonWidget mb,
445 if (MB_ARMED(mb) == TRUE) {
446 MB_ARMED(mb) = FALSE;
448 if (pop_down == TRUE &&
449 MB_SMENU(mb) != (Widget)NULL)
450 XtUnmanageChild(MB_SMENU(mb));
463 Cardinal *num_param )
465 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
466 XtActionProc arm_and_activate;
468 if(MB_POPPED_UP(mb) == TRUE) {
474 arm_and_activate = ((DtMenuButtonClassRec *)(mb->core.widget_class))->
475 primitive_class.arm_and_activate;
477 (* arm_and_activate) ((Widget) mb, event, NULL, NULL);
481 PreMenuButtonHandler(
485 Boolean *cont_to_dispatch)
487 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
489 if(MB_SMENU(mb) == (Widget)NULL ||
490 event->xany.type != ButtonPress ||
491 event->xbutton.time <= MB_LAST_TIMESTAMP(mb))
494 if(event->xbutton.button==Button1||event->xbutton.button==Button3)
497 XtVaGetValues(MB_SMENU(mb), XmNmenuPost, &btnstr, NULL);
498 if (btnstr==NULL || !strcmp(btnstr,"") ||
499 !strcmp(btnstr, "<Btn3Down>"))
500 event->xbutton.button=Button3;
501 else if (!strcmp(btnstr, "<Btn1Down>"))
502 event->xbutton.button=Button1;
513 Boolean *cont_to_dispatch)
515 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
518 if(MB_SMENU(mb) == (Widget)NULL ||
519 event->xany.type != ButtonPress ||
520 event->xbutton.time <= MB_LAST_TIMESTAMP(mb))
523 MB_LAST_TIMESTAMP(mb) = event->xbutton.time;
525 Popup (mb, event, TRUE);
531 CallCascadingCallbacks(
535 DtMenuButtonWidget mb = (DtMenuButtonWidget)w;
536 XmAnyCallbackStruct cback;
538 if(MB_POPPED_UP(mb) == TRUE)
541 cback.reason = DtCR_CASCADING;
544 XtCallCallbackList ((Widget) mb,
545 CascadingCallback(mb), &cback);
549 PopdownCallback(Widget w, XtPointer client_data, XtPointer call_data)
551 DtMenuButtonWidget mb = (DtMenuButtonWidget)client_data;
554 MB_POPPED_UP(mb) = FALSE;
555 MB_LAST_TIMESTAMP(mb) = XtLastTimestampProcessed(XtDisplay(mb));
559 PopupCallback(Widget w, XtPointer client_data, XtPointer call_data)
561 DtMenuButtonWidget mb = (DtMenuButtonWidget)client_data;
564 MB_POPPED_UP(mb) = TRUE;
568 * Call the cascading callbacks and popup any submenu.
573 DtMenuButtonWidget mb,
575 Boolean call_cbacks )
578 Position root_x=0, root_y=0;
579 Position save_x = 0, save_y = 0;
580 Dimension sw=0, sh=0;
584 if((MB_SMENU(mb) == (Widget)NULL) ||
585 (MB_POPPED_UP(mb) == TRUE))
589 CallCascadingCallbacks((Widget)mb, event);
591 x = (Position)((int)XtWidth((Widget)mb) - (int)XtWidth(MB_SMENU(mb)))/2;
592 y = XtHeight((Widget)mb) - mb->primitive.highlight_thickness + 1;
593 XtTranslateCoords((Widget)mb, x,y, &root_x, &root_y);
595 /* Check if not completely on the screen */
596 screen = XtScreen(mb);
597 sw = WidthOfScreen(screen);
598 sh = HeightOfScreen(screen);
600 if((dx = root_x - sw + XtWidth(MB_SMENU(mb))) > 0)
602 if((dy = root_y - sh + XtHeight(MB_SMENU(mb))) > 0) {
603 root_y -= (2 - (mb->primitive.highlight_thickness<<1));
604 root_y -= (XtHeight(mb) + XtHeight(MB_SMENU(mb)));
607 save_x = event->xbutton.x_root;
608 save_y = event->xbutton.y_root;
610 event->xbutton.x_root = root_x;
611 event->xbutton.y_root = root_y;
613 /* Position the menu */
614 XmMenuPosition(MB_SMENU(mb),(XButtonPressedEvent*)event);
616 event->xbutton.x_root = save_x;
617 event->xbutton.y_root = save_y;
619 XtManageChild(MB_SMENU(mb));
623 * Get the menu glyph size set up.
626 CalculateMenuGlyphSize(
627 DtMenuButtonWidget menubtn )
630 int x,y; /* must be int */
631 unsigned int width, height, border, depth; /* must be int */
633 if (MB_PIXMAP(menubtn) != XmUNSPECIFIED_PIXMAP) {
634 XGetGeometry(XtDisplay(menubtn), MB_PIXMAP(menubtn),
635 &rootwin, &x, &y, &width, &height,
638 MB_GLYPH_WIDTH(menubtn) = (Dimension) width;
639 MB_GLYPH_HEIGHT(menubtn) = (Dimension) height;
643 unsigned int text_height;
645 ht = menubtn->primitive.highlight_thickness;
646 st = menubtn->primitive.shadow_thickness;
647 text_height = Lab_TextRect_height(menubtn);
649 side = Max( (text_height * 2 / 3) + 2 * (ht + st),
650 (2*(ht + (st-1) +1)) +1 );
651 MB_GLYPH_WIDTH(menubtn) =
652 MB_GLYPH_HEIGHT(menubtn) = side;
657 * Set up the menu glyph location.
661 DtMenuButtonWidget menubtn )
665 MB_GLYPH_X(menubtn) =
667 menubtn->primitive.highlight_thickness -
668 menubtn->primitive.shadow_thickness -
669 Lab_MarginWidth(menubtn) -
670 MB_GLYPH_WIDTH(menubtn);
672 buffer = menubtn->primitive.highlight_thickness +
673 menubtn->primitive.shadow_thickness +
674 Lab_MarginHeight(menubtn);
676 MB_GLYPH_Y(menubtn) = (Position)((int)buffer +
677 (((int)XtHeight(menubtn) - 2*(int)buffer) -
678 (int)MB_GLYPH_HEIGHT(menubtn)) / 2);
682 * Make room for menu glyph in menu button.
685 AdjustMenuButtonSize(
686 DtMenuButtonWidget menubtn,
688 Boolean adjustHeight )
693 * Modify the size of the menubutton to acommadate the menu.
694 * The menu should fit inside MarginRight.
696 if ((int)(MB_GLYPH_WIDTH(menubtn) + GLYPH_PIX_SPACE) >
697 (int)Lab_MarginRight(menubtn)) {
698 delta = MB_GLYPH_WIDTH(menubtn) + GLYPH_PIX_SPACE -
699 Lab_MarginRight(menubtn);
700 Lab_MarginRight(menubtn) += delta;
703 XtWidth(menubtn) += delta;
705 if (LAlignment(menubtn) == XmALIGNMENT_END)
706 Lab_TextRect_x(menubtn) -= delta;
708 if (LAlignment(menubtn) == XmALIGNMENT_CENTER)
709 Lab_TextRect_x(menubtn) -= delta/2;
714 * the menu height should fit inside of
715 * TextRect + marginTop + marginBottom
717 delta = MB_GLYPH_HEIGHT(menubtn) +
718 2 * (Lab_MarginHeight(menubtn) +
719 menubtn->primitive.shadow_thickness +
720 menubtn->primitive.highlight_thickness);
722 if (delta > XtHeight(menubtn)) {
723 delta -= XtHeight(menubtn);
724 Lab_MarginTop(menubtn) += delta/2;
725 Lab_TextRect_y(menubtn) += delta/2;
726 Lab_MarginBottom(menubtn) += delta - (delta/2);
729 XtHeight(menubtn) += delta;
732 LocateMenuGlyph(menubtn);
742 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
743 XmRowColumnWidget submenu = (XmRowColumnWidget) MB_SMENU(mb);
745 Display *dpy = XtDisplay(wid);
747 XtRemoveAllCallbacks ((Widget) mb, DtNcascadingCallback);
749 if(submenu != (XmRowColumnWidget)NULL) {
750 shell = XtParent((Widget)submenu);
751 XtRemoveCallback(shell, XtNpopupCallback,PopupCallback, (XtPointer)mb);
752 XtRemoveCallback(shell, XtNpopdownCallback, PopdownCallback,(XtPointer)mb);
755 if(MB_PVT_SMENU(mb) == TRUE) {
756 XtDestroyWidget((Widget)submenu);
758 MB_PVT_SMENU(mb) = FALSE;
769 if (mb != (Widget)NULL) {
770 /* Label resize method lays out the label string */
773 resize = xmLabelClassRec.core_class.resize;
777 LocateMenuGlyph ((DtMenuButtonWidget) mb);
792 DtMenuButtonWidget old = (DtMenuButtonWidget) cw ;
793 DtMenuButtonWidget requested = (DtMenuButtonWidget) rw ;
794 DtMenuButtonWidget new_w = (DtMenuButtonWidget) nw ;
795 Boolean flag = FALSE;
796 Boolean adjustWidth = FALSE;
797 Boolean adjustHeight = FALSE;
798 unsigned char rowcol_type = NULL;
799 Display *dpy = XtDisplay(nw);
800 Boolean menu_glyph_changed = FALSE;
802 if (MB_SMENU(new_w) != (Widget)NULL) {
803 XtVaGetValues(MB_SMENU(new_w), XmNrowColumnType,
805 if(rowcol_type != XmMENU_POPUP) {
806 MB_SMENU(new_w) = NULL;
811 /* Never let traversal become FALSE */
812 new_w->primitive.traversal_on = TRUE;
814 if ((LRecomputeSize(new_w)) ||
815 (requested->core.width <= 0))
818 if ((LRecomputeSize(new_w)) ||
819 (requested->core.height <= 0))
822 /* get new pixmap size */
823 if ((MB_PIXMAP(old) != MB_PIXMAP (new_w)) ||
824 (Lab_TextRect_height(old) != Lab_TextRect_height(new_w))) {
825 CalculateMenuGlyphSize (new_w);
826 menu_glyph_changed = TRUE;
829 if ((old->primitive.foreground !=
830 new_w->primitive.foreground) ||
831 (old->core.background_pixel !=
832 new_w->core.background_pixel)) {
833 menu_glyph_changed = TRUE;
838 * Resize widget if submenu appeared or disappeared, or if the
839 * menu glyph changed.
842 if ( menu_glyph_changed == TRUE ||
843 (LLabelType(old) != LLabelType(new_w)) ||
844 (MB_SMENU(old) != MB_SMENU(new_w))) {
846 AdjustMenuButtonSize (new_w, adjustWidth, adjustHeight);
850 if ((MB_SMENU(old) != MB_SMENU(new_w))) {
852 if(MB_SMENU(new_w)) {
853 XtRemoveEventHandler((Widget)new_w,
854 ButtonPressMask, False,
855 PreMenuButtonHandler, MB_SMENU(old));
856 XtInsertEventHandler((Widget)new_w,
857 ButtonPressMask, False,
858 PreMenuButtonHandler, MB_SMENU(new_w),
860 XtAddCallback(XtParent(
863 PopdownCallback, (XtPointer)new_w);
864 XtAddCallback(XtParent(
867 PopupCallback, (XtPointer)new_w);
870 if(MB_PVT_SMENU(old) == TRUE) {
871 XtDestroyWidget(MB_SMENU(old));
872 MB_PVT_SMENU(new_w) = FALSE;
877 } else if ((new_w->primitive.highlight_thickness !=
878 old->primitive.highlight_thickness) ||
879 (new_w->primitive.shadow_thickness !=
880 old->primitive.shadow_thickness) ||
881 (Lab_MarginRight (new_w) != Lab_MarginRight (old)) ||
882 (Lab_MarginHeight (new_w) != Lab_MarginHeight (old)) ||
883 (Lab_MarginTop (new_w) != Lab_MarginTop (old)) ||
884 (Lab_MarginBottom (new_w) != Lab_MarginBottom (old))) {
885 CalculateMenuGlyphSize (new_w);
886 AdjustMenuButtonSize (new_w,adjustWidth, adjustHeight);
888 } else if ((Lab_MarginWidth(new_w) != Lab_MarginWidth(old)) ||
889 (new_w->core.width != old->core.width) ||
890 (new_w->core.height != old->core.height)) {
891 LocateMenuGlyph (new_w);
908 DtMenuButtonWidget req = (DtMenuButtonWidget) w_req ;
909 DtMenuButtonWidget new_w = (DtMenuButtonWidget) w_new ;
911 Boolean adjustWidth = FALSE;
912 Boolean adjustHeight = FALSE;
913 Widget parent = XtParent(new_w);
914 unsigned char rowcol_type = NULL;
917 if ((XmIsRowColumn (parent))) {
918 XtVaGetValues(parent, XmNrowColumnType,
920 if(rowcol_type != XmWORK_AREA)
924 name = XtMalloc(10 + strlen(new_w->core.name));
925 sprintf(name,"submenu_%s",new_w->core.name);
927 GetTopManager(w_new,&topManager);
928 MB_SMENU(new_w) = XmCreatePopupMenu(topManager, name, NULL, 0);
929 /* Remove our passive grab */
930 XtUngrabButton(topManager, RC_PostButton(MB_SMENU(new_w)), AnyModifier);
932 MB_PVT_SMENU(new_w) = TRUE;
934 MB_ARMED(new_w) = FALSE;
935 MB_POPPED_UP(new_w) = FALSE;
936 MB_LAST_TIMESTAMP(new_w) = 0;
937 MB_GC(new_w) = (GC)NULL;
939 if (req->core.width <= 0)
942 if (req->core.height <= 0)
945 CalculateMenuGlyphSize (new_w);
946 AdjustMenuButtonSize (new_w, adjustWidth, adjustHeight);
949 new_w->primitive.traversal_on = TRUE;
951 if(MB_SMENU(new_w) != (Widget)NULL) {
952 XtInsertEventHandler((Widget)new_w, ButtonPressMask,
953 False, PreMenuButtonHandler, MB_SMENU(new_w), XtListHead);
954 XtAddEventHandler((Widget)new_w, ButtonPressMask,
955 FALSE, MenuButtonHandler, MB_SMENU(new_w));
956 XtAddCallback(XtParent(MB_SMENU(new_w)), XtNpopdownCallback,
957 PopdownCallback, (XtPointer)new_w);
958 XtAddCallback(XtParent(MB_SMENU(new_w)), XtNpopupCallback,
959 PopupCallback, (XtPointer)new_w);
962 if (name) XtFree(name);
973 unsigned int text_height;
975 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
976 Window win = XtWindow(wid);
977 Display *dpy = XtDisplay(wid);
979 ht = mb->primitive.highlight_thickness;
980 st = mb->primitive.shadow_thickness;
981 text_height = Lab_TextRect_height(mb);
983 tsc = mb->primitive.top_shadow_color;
984 bsc = mb->primitive.bottom_shadow_color;
986 tsGC = mb->primitive.top_shadow_GC;
987 bsGC = mb->primitive.bottom_shadow_GC;
991 if(MB_ARMED(mb) == TRUE) {
992 XFillRectangle(dpy, win, gc,
993 MB_GLYPH_X(mb), MB_GLYPH_Y(mb),
994 MB_GLYPH_WIDTH(mb), MB_GLYPH_HEIGHT(mb));
995 XmeDrawArrow(dpy, win,
997 MB_GLYPH_X(mb) + ht + st - 1,
998 MB_GLYPH_Y(mb) + ht + st - 1,
999 MB_GLYPH_WIDTH(mb) - 2*(ht + st - 1),
1000 MB_GLYPH_HEIGHT(mb) - 2*(ht + st - 1),
1003 /* standard (unarmed) arrow */
1005 XFillRectangle(dpy, win, gc,
1006 MB_GLYPH_X(mb), MB_GLYPH_Y(mb),
1007 MB_GLYPH_WIDTH(mb), MB_GLYPH_HEIGHT(mb));
1008 XmeDrawArrow(dpy, win,
1010 MB_GLYPH_X(mb) + ht + st - 1,
1011 MB_GLYPH_Y(mb) + ht + st - 1,
1012 MB_GLYPH_WIDTH(mb) - 2*(ht + st - 1),
1013 MB_GLYPH_HEIGHT(mb) - 2*(ht + st - 1),
1021 DtMenuButtonWidget mb)
1026 if(MB_GC(mb) != (GC)NULL) {
1027 XtReleaseGC((Widget)mb, MB_GC(mb));
1028 MB_GC(mb) = (GC)NULL;
1031 bg = mb->core.background_pixel;
1032 values.foreground = values.background = bg;
1033 values.graphics_exposures = FALSE;
1034 MB_GC(mb) = XtGetGC ((Widget) mb,
1035 GCForeground | GCBackground | GCGraphicsExposures, &values);
1039 *************************************************************************
1043 *************************************************************************
1053 return XtCreateWidget(name,dtMenuButtonWidgetClass,parent, al, ac);
1059 Widget *topManager )
1061 while (XmIsManager(XtParent(w)))