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>
68 #include <Xm/XmPrivate.h> /* _XmRecordEvent, _XmSetInDragMode, ... */
70 #include <X11/keysymdef.h>
71 #include "DtWidgetI.h"
76 #define DtMenuButtonIndex (XmLabelIndex + 1)
77 static XmOffsetPtr ipot; /* Instance part offset table */
78 static XmOffsetPtr cpot; /* Constraint part offset table */
81 #define Max(x, y) (((x) > (y)) ? (x) : (y))
84 #define GLYPH_PIX_SPACE 4 /* pixels between label and bit map */
89 #define CascadingCallback(w) XmField(w,ipot,DtMenuButton,cascading_callback,XtCallbackList)
90 #define MenuRect(w) XmField(w,ipot,DtMenuButton,menu_rect,XRectangle)
91 #define LNormalGC(w) XmField(w,ipot,XmLabel,normal_GC,GC)
92 #define LAlignment(w) XmField(w,ipot,XmLabel,alignment,unsigned char)
93 #define LRecomputeSize(w) XmField(w,ipot,XmLabel,recompute_size,Boolean)
94 #define LLabelType(w) XmField(w,ipot,XmLabel,label_type,unsigned char)
96 /* Access macro definitions */
97 #define MB_PVT_SMENU(mb) XmField(mb,ipot,DtMenuButton,private_submenu,Boolean)
98 #define MB_LAST_TIMESTAMP(mb) XmField(mb,ipot,DtMenuButton,last_timestamp,Time)
99 #define MB_SMENU(mb) XmField(mb,ipot,DtMenuButton,submenu,Widget)
100 #define MB_PIXMAP(mb) XmField(mb,ipot,DtMenuButton,menu_pixmap,Pixmap)
101 #define MB_GLYPH_X(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).x
102 #define MB_GLYPH_Y(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).y
103 #define MB_GLYPH_WIDTH(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).width
104 #define MB_GLYPH_HEIGHT(mb) (XmField(mb,ipot,DtMenuButton,menu_rect,XRectangle)).height
105 #define MB_ARMED(mb) XmField(mb,ipot,DtMenuButton,armed,Boolean)
106 #define MB_POPPED_UP(mb) XmField(mb,ipot,DtMenuButton,popped_up,Boolean)
107 #define MB_GC(mb) XmField(mb,ipot,DtMenuButton,gc,GC)
110 /******** Static Function Declarations ********/
111 static void ClassInitialize (void);
113 static void AdjustMenuButtonSize(
114 DtMenuButtonWidget menubtn,
116 Boolean adjustHeight) ;
118 DtMenuButtonWidget mb) ;
119 static void ArmAndActivate(
123 Cardinal *num_params) ;
125 static void CalculateMenuGlyphSize(
126 DtMenuButtonWidget menubtn) ;
127 static void CallCascadingCallbacks(
134 DtMenuButtonWidget mb,
136 static void DrawArrow(
138 static void Draw3DShadows(
139 DtMenuButtonWidget mb) ;
140 static void DrawMenuGlyph(
141 DtMenuButtonWidget mb) ;
144 DtMenuButtonWidget mb);
146 static void Initialize(
150 Cardinal *num_args) ;
152 static void LocateMenuGlyph(
153 DtMenuButtonWidget menubtn) ;
155 static void MenuButtonHandler(
159 Boolean *cont_to_dispatch) ;
162 DtMenuButtonWidget mb,
164 Boolean call_cbacks );
166 static void Redisplay(
177 Cardinal *num_param) ;
178 static Boolean SetValues(
183 Cardinal *num_args) ;
184 static void GetTopManager(
186 Widget *topManager) ;
189 /******** End Static Function Declarations ********/
193 * event translation tables for menubutton.
196 static char menuButton_translations[] = "\
197 <Key>space:Select()\n\
198 <Key>osfSelect:Select()";
200 static XtActionsRec menuButton_actions [] = {
205 #define DtOffset(field) XmPartOffset(DtMenuButton,field)
206 #define XmPrimOffset(field) XmPartOffset(XmPrimitive,field)
207 #define XmLabelOffset(field) XmPartOffset(XmLabel,field)
208 static XmPartResource resources[] = {
210 DtNcascadingCallback,
213 sizeof (XtCallbackList),
214 DtOffset(cascading_callback),
220 DtCMenuWidget, /* submenu */
230 XmRPrimForegroundPixmap,
232 DtOffset(menu_pixmap),
234 (XtPointer) XmUNSPECIFIED_PIXMAP
239 XmRHorizontalDimension,
241 XmPrimOffset(shadow_thickness),
250 XmPrimOffset(traversal_on),
255 XmNhighlightThickness,
256 XmCHighlightThickness,
257 XmRHorizontalDimension,
259 XmPrimOffset(highlight_thickness),
266 XmRHorizontalDimension,
268 XmLabelOffset(margin_width),
274 externaldef(xmmenubuttonclassrec)
275 DtMenuButtonClassRec dtMenuButtonClassRec = {
276 { /* core class record */
277 (WidgetClass) &xmLabelClassRec, /* superclass ptr */
278 "DtMenuButton", /* class_name */
279 sizeof(DtMenuButtonPart), /* size of Pulldown widget */
280 (XtProc)ClassInitialize, /* class init proc */
281 NULL, /* chained class init */
282 FALSE, /* class is not init'ed */
283 Initialize, /* widget init proc */
284 NULL, /* init_hook proc */
285 XtInheritRealize, /* widget realize proc */
286 menuButton_actions, /* class action table */
287 XtNumber (menuButton_actions), /* num of actions */
288 (XtResourceList)resources, /* this class's resource list*/
289 XtNumber (resources), /* resource_count */
290 NULLQUARK, /* xrm_class */
291 TRUE, /* compress motion */
292 XtExposeCompressMaximal, /* compress exposure */
293 TRUE, /* compress enter-leave */
294 FALSE, /* no VisibilityNotify */
295 Destroy, /* class destroy proc */
296 Resize, /* class resize proc */
297 Redisplay, /* expose proc */
298 SetValues, /* set_value proc */
299 NULL, /* set_value_hook proc */
300 XtInheritSetValuesAlmost, /* set_value_almost proc */
301 NULL, /* get_values_hook */
302 NULL, /* class accept focus proc */
303 XtVersionDontCheck, /* current version */
304 NULL, /* callback offset list */
305 menuButton_translations, /* default translation table */
306 XtInheritQueryGeometry, /* query geo proc */
307 NULL, /* display accelerator*/
308 (XtPointer)NULL, /* extension */
311 /* Primitive Class record */
312 XmInheritWidgetProc, /* border_highlight */
313 XmInheritWidgetProc, /* border_uhighlight */
314 XtInheritTranslations, /* translations */
315 ArmAndActivate, /* arm & activate */
316 NULL, /* get resources */
317 0, /* num get_resources */
318 (XtPointer)NULL, /* extension */
320 { /* Label Class record */
321 XmInheritWidgetProc, /* set override callback */
322 XmInheritMenuProc, /* menu procedures */
323 XtInheritTranslations, /* menu traversal xlation */
324 NULL, /* extension */
326 { /* menu_button class record */
327 NULL, /* extension */
333 * Now make a public symbol that points to this class record.
336 externaldef(dtmenubuttonwidgetclass)
337 WidgetClass dtMenuButtonWidgetClass =
338 (WidgetClass) &dtMenuButtonClassRec;
341 * MotifBc, to calculate offset var. ipot
344 ClassInitialize(void)
346 XmResolveAllPartOffsets(dtMenuButtonWidgetClass, &ipot, &cpot);
351 DtMenuButtonWidget mb )
353 if (XtIsRealized((Widget)mb))
354 XmeDrawShadows (XtDisplay (mb), XtWindow (mb),
355 mb->primitive.top_shadow_GC,
356 mb->primitive.bottom_shadow_GC,
357 mb->primitive.highlight_thickness,
358 mb->primitive.highlight_thickness,
360 mb->primitive.highlight_thickness,
361 mb->core.height - 2 *
362 mb->primitive.highlight_thickness,
363 mb->primitive.shadow_thickness,
364 (MB_ARMED(mb) == TRUE) ? XmSHADOW_IN: XmSHADOW_OUT);
370 DtMenuButtonWidget mb )
372 if ((MB_GLYPH_WIDTH(mb) != 0)){
373 if(MB_PIXMAP(mb) != XmUNSPECIFIED_PIXMAP)
374 XCopyArea (XtDisplay(mb),
378 MB_GLYPH_WIDTH(mb), MB_GLYPH_HEIGHT(mb),
379 MB_GLYPH_X(mb), MB_GLYPH_Y(mb));
381 DrawArrow((Widget)mb);
386 * Redisplay the widget.
394 if (XtIsRealized (mb)) {
395 /* Label expose method does the initial work */
398 expose = xmLabelClassRec.core_class.expose;
400 (* expose)(mb, event, region) ;
402 DrawMenuGlyph((DtMenuButtonWidget) mb);
403 Draw3DShadows ((DtMenuButtonWidget) mb);
409 DtMenuButtonWidget mb )
411 XmProcessTraversal( (Widget) mb, XmTRAVERSE_CURRENT);
412 if (MB_ARMED(mb) == FALSE) {
424 Cardinal *num_params )
426 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
428 if(MB_SMENU(mb) == (Widget)NULL ||
429 event == (XEvent*) NULL)
432 if (!_XmIsEventUnique(event))
435 Popup(mb, event, TRUE);
436 _XmSetInDragMode((Widget)mb,FALSE);
437 if (!XmProcessTraversal(MB_SMENU(mb), XmTRAVERSE_CURRENT))
438 XtSetKeyboardFocus(XtParent(MB_SMENU(mb)), MB_SMENU(mb));
440 _XmRecordEvent(event);
446 DtMenuButtonWidget mb,
449 if (MB_ARMED(mb) == TRUE) {
450 MB_ARMED(mb) = FALSE;
452 if (pop_down == TRUE &&
453 MB_SMENU(mb) != (Widget)NULL)
454 XtUnmanageChild(MB_SMENU(mb));
467 Cardinal *num_param )
469 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
470 XtActionProc arm_and_activate;
472 if(MB_POPPED_UP(mb) == TRUE) {
478 arm_and_activate = ((DtMenuButtonClassRec *)(mb->core.widget_class))->
479 primitive_class.arm_and_activate;
481 (* arm_and_activate) ((Widget) mb, event, NULL, NULL);
485 PreMenuButtonHandler(
489 Boolean *cont_to_dispatch)
491 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
493 if(MB_SMENU(mb) == (Widget)NULL ||
494 event->xany.type != ButtonPress ||
495 event->xbutton.time <= MB_LAST_TIMESTAMP(mb))
498 if(event->xbutton.button==Button1||event->xbutton.button==Button3)
501 XtVaGetValues(MB_SMENU(mb), XmNmenuPost, &btnstr, NULL);
502 if (btnstr==NULL || !strcmp(btnstr,"") ||
503 !strcmp(btnstr, "<Btn3Down>"))
504 event->xbutton.button=Button3;
505 else if (!strcmp(btnstr, "<Btn1Down>"))
506 event->xbutton.button=Button1;
517 Boolean *cont_to_dispatch)
519 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
522 if(MB_SMENU(mb) == (Widget)NULL ||
523 event->xany.type != ButtonPress ||
524 event->xbutton.time <= MB_LAST_TIMESTAMP(mb))
527 MB_LAST_TIMESTAMP(mb) = event->xbutton.time;
529 Popup (mb, event, TRUE);
535 CallCascadingCallbacks(
539 DtMenuButtonWidget mb = (DtMenuButtonWidget)w;
540 XmAnyCallbackStruct cback;
542 if(MB_POPPED_UP(mb) == TRUE)
545 cback.reason = DtCR_CASCADING;
548 XtCallCallbackList ((Widget) mb,
549 CascadingCallback(mb), &cback);
553 PopdownCallback(Widget w, XtPointer client_data, XtPointer call_data)
555 DtMenuButtonWidget mb = (DtMenuButtonWidget)client_data;
558 MB_POPPED_UP(mb) = FALSE;
559 MB_LAST_TIMESTAMP(mb) = XtLastTimestampProcessed(XtDisplay(mb));
563 PopupCallback(Widget w, XtPointer client_data, XtPointer call_data)
565 DtMenuButtonWidget mb = (DtMenuButtonWidget)client_data;
568 MB_POPPED_UP(mb) = TRUE;
572 * Call the cascading callbacks and popup any submenu.
577 DtMenuButtonWidget mb,
579 Boolean call_cbacks )
582 Position root_x=0, root_y=0;
583 Position save_x = 0, save_y = 0;
584 Dimension sw=0, sh=0;
588 if((MB_SMENU(mb) == (Widget)NULL) ||
589 (MB_POPPED_UP(mb) == TRUE))
593 CallCascadingCallbacks((Widget)mb, event);
595 x = (Position)((int)XtWidth((Widget)mb) - (int)XtWidth(MB_SMENU(mb)))/2;
596 y = XtHeight((Widget)mb) - mb->primitive.highlight_thickness + 1;
597 XtTranslateCoords((Widget)mb, x,y, &root_x, &root_y);
599 /* Check if not completely on the screen */
600 screen = XtScreen(mb);
601 sw = WidthOfScreen(screen);
602 sh = HeightOfScreen(screen);
604 if((dx = root_x - sw + XtWidth(MB_SMENU(mb))) > 0)
606 if((dy = root_y - sh + XtHeight(MB_SMENU(mb))) > 0) {
607 root_y -= (2 - (mb->primitive.highlight_thickness<<1));
608 root_y -= (XtHeight(mb) + XtHeight(MB_SMENU(mb)));
611 save_x = event->xbutton.x_root;
612 save_y = event->xbutton.y_root;
614 event->xbutton.x_root = root_x;
615 event->xbutton.y_root = root_y;
617 /* Position the menu */
618 XmMenuPosition(MB_SMENU(mb),(XButtonPressedEvent*)event);
620 event->xbutton.x_root = save_x;
621 event->xbutton.y_root = save_y;
623 XtManageChild(MB_SMENU(mb));
627 * Get the menu glyph size set up.
630 CalculateMenuGlyphSize(
631 DtMenuButtonWidget menubtn )
634 int x,y; /* must be int */
635 unsigned int width, height, border, depth; /* must be int */
637 if (MB_PIXMAP(menubtn) != XmUNSPECIFIED_PIXMAP) {
638 XGetGeometry(XtDisplay(menubtn), MB_PIXMAP(menubtn),
639 &rootwin, &x, &y, &width, &height,
642 MB_GLYPH_WIDTH(menubtn) = (Dimension) width;
643 MB_GLYPH_HEIGHT(menubtn) = (Dimension) height;
647 unsigned int text_height;
649 ht = menubtn->primitive.highlight_thickness;
650 st = menubtn->primitive.shadow_thickness;
651 text_height = Lab_TextRect_height(menubtn);
653 side = Max( (text_height * 2 / 3) + 2 * (ht + st),
654 (2*(ht + (st-1) +1)) +1 );
655 MB_GLYPH_WIDTH(menubtn) =
656 MB_GLYPH_HEIGHT(menubtn) = side;
661 * Set up the menu glyph location.
665 DtMenuButtonWidget menubtn )
669 MB_GLYPH_X(menubtn) =
671 menubtn->primitive.highlight_thickness -
672 menubtn->primitive.shadow_thickness -
673 Lab_MarginWidth(menubtn) -
674 MB_GLYPH_WIDTH(menubtn);
676 buffer = menubtn->primitive.highlight_thickness +
677 menubtn->primitive.shadow_thickness +
678 Lab_MarginHeight(menubtn);
680 MB_GLYPH_Y(menubtn) = (Position)((int)buffer +
681 (((int)XtHeight(menubtn) - 2*(int)buffer) -
682 (int)MB_GLYPH_HEIGHT(menubtn)) / 2);
686 * Make room for menu glyph in menu button.
689 AdjustMenuButtonSize(
690 DtMenuButtonWidget menubtn,
692 Boolean adjustHeight )
697 * Modify the size of the menubutton to acommadate the menu.
698 * The menu should fit inside MarginRight.
700 if ((int)(MB_GLYPH_WIDTH(menubtn) + GLYPH_PIX_SPACE) >
701 (int)Lab_MarginRight(menubtn)) {
702 delta = MB_GLYPH_WIDTH(menubtn) + GLYPH_PIX_SPACE -
703 Lab_MarginRight(menubtn);
704 Lab_MarginRight(menubtn) += delta;
707 XtWidth(menubtn) += delta;
709 if (LAlignment(menubtn) == XmALIGNMENT_END)
710 Lab_TextRect_x(menubtn) -= delta;
712 if (LAlignment(menubtn) == XmALIGNMENT_CENTER)
713 Lab_TextRect_x(menubtn) -= delta/2;
718 * the menu height should fit inside of
719 * TextRect + marginTop + marginBottom
721 delta = MB_GLYPH_HEIGHT(menubtn) +
722 2 * (Lab_MarginHeight(menubtn) +
723 menubtn->primitive.shadow_thickness +
724 menubtn->primitive.highlight_thickness);
726 if (delta > XtHeight(menubtn)) {
727 delta -= XtHeight(menubtn);
728 Lab_MarginTop(menubtn) += delta/2;
729 Lab_TextRect_y(menubtn) += delta/2;
730 Lab_MarginBottom(menubtn) += delta - (delta/2);
733 XtHeight(menubtn) += delta;
736 LocateMenuGlyph(menubtn);
746 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
747 XmRowColumnWidget submenu = (XmRowColumnWidget) MB_SMENU(mb);
750 XtRemoveAllCallbacks ((Widget) mb, DtNcascadingCallback);
752 if(submenu != (XmRowColumnWidget)NULL) {
753 shell = XtParent((Widget)submenu);
754 XtRemoveCallback(shell, XtNpopupCallback,PopupCallback, (XtPointer)mb);
755 XtRemoveCallback(shell, XtNpopdownCallback, PopdownCallback,(XtPointer)mb);
758 if(MB_PVT_SMENU(mb) == TRUE) {
759 XtDestroyWidget((Widget)submenu);
761 MB_PVT_SMENU(mb) = FALSE;
772 if (mb != (Widget)NULL) {
773 /* Label resize method lays out the label string */
776 resize = xmLabelClassRec.core_class.resize;
780 LocateMenuGlyph ((DtMenuButtonWidget) mb);
795 DtMenuButtonWidget old = (DtMenuButtonWidget) cw ;
796 DtMenuButtonWidget requested = (DtMenuButtonWidget) rw ;
797 DtMenuButtonWidget new_w = (DtMenuButtonWidget) nw ;
798 Boolean flag = FALSE;
799 Boolean adjustWidth = FALSE;
800 Boolean adjustHeight = FALSE;
801 unsigned char rowcol_type = 0;
802 Boolean menu_glyph_changed = FALSE;
804 if (MB_SMENU(new_w) != (Widget)NULL) {
805 XtVaGetValues(MB_SMENU(new_w), XmNrowColumnType,
807 if(rowcol_type != XmMENU_POPUP) {
808 MB_SMENU(new_w) = NULL;
813 /* Never let traversal become FALSE */
814 new_w->primitive.traversal_on = TRUE;
816 if ((LRecomputeSize(new_w)) ||
817 (requested->core.width <= 0))
820 if ((LRecomputeSize(new_w)) ||
821 (requested->core.height <= 0))
824 /* get new pixmap size */
825 if ((MB_PIXMAP(old) != MB_PIXMAP (new_w)) ||
826 (Lab_TextRect_height(old) != Lab_TextRect_height(new_w))) {
827 CalculateMenuGlyphSize (new_w);
828 menu_glyph_changed = TRUE;
831 if ((old->primitive.foreground !=
832 new_w->primitive.foreground) ||
833 (old->core.background_pixel !=
834 new_w->core.background_pixel)) {
835 menu_glyph_changed = TRUE;
840 * Resize widget if submenu appeared or disappeared, or if the
841 * menu glyph changed.
844 if ( menu_glyph_changed == TRUE ||
845 (LLabelType(old) != LLabelType(new_w)) ||
846 (MB_SMENU(old) != MB_SMENU(new_w))) {
848 AdjustMenuButtonSize (new_w, adjustWidth, adjustHeight);
852 if ((MB_SMENU(old) != MB_SMENU(new_w))) {
854 if(MB_SMENU(new_w)) {
855 XtRemoveEventHandler((Widget)new_w,
856 ButtonPressMask, False,
857 PreMenuButtonHandler, MB_SMENU(old));
858 XtInsertEventHandler((Widget)new_w,
859 ButtonPressMask, False,
860 PreMenuButtonHandler, MB_SMENU(new_w),
862 XtAddCallback(XtParent(
865 PopdownCallback, (XtPointer)new_w);
866 XtAddCallback(XtParent(
869 PopupCallback, (XtPointer)new_w);
872 if(MB_PVT_SMENU(old) == TRUE) {
873 XtDestroyWidget(MB_SMENU(old));
874 MB_PVT_SMENU(new_w) = FALSE;
879 } else if ((new_w->primitive.highlight_thickness !=
880 old->primitive.highlight_thickness) ||
881 (new_w->primitive.shadow_thickness !=
882 old->primitive.shadow_thickness) ||
883 (Lab_MarginRight (new_w) != Lab_MarginRight (old)) ||
884 (Lab_MarginHeight (new_w) != Lab_MarginHeight (old)) ||
885 (Lab_MarginTop (new_w) != Lab_MarginTop (old)) ||
886 (Lab_MarginBottom (new_w) != Lab_MarginBottom (old))) {
887 CalculateMenuGlyphSize (new_w);
888 AdjustMenuButtonSize (new_w,adjustWidth, adjustHeight);
890 } else if ((Lab_MarginWidth(new_w) != Lab_MarginWidth(old)) ||
891 (new_w->core.width != old->core.width) ||
892 (new_w->core.height != old->core.height)) {
893 LocateMenuGlyph (new_w);
910 DtMenuButtonWidget req = (DtMenuButtonWidget) w_req ;
911 DtMenuButtonWidget new_w = (DtMenuButtonWidget) w_new ;
913 Boolean adjustWidth = FALSE;
914 Boolean adjustHeight = FALSE;
915 Widget parent = XtParent(new_w);
916 unsigned char rowcol_type = 0;
919 if ((XmIsRowColumn (parent))) {
920 XtVaGetValues(parent, XmNrowColumnType,
922 if(rowcol_type != XmWORK_AREA)
926 name = XtMalloc(10 + strlen(new_w->core.name));
927 sprintf(name,"submenu_%s",new_w->core.name);
929 GetTopManager(w_new,&topManager);
930 MB_SMENU(new_w) = XmCreatePopupMenu(topManager, name, NULL, 0);
931 /* Remove our passive grab */
932 XtUngrabButton(topManager, RC_PostButton(MB_SMENU(new_w)), AnyModifier);
934 MB_PVT_SMENU(new_w) = TRUE;
936 MB_ARMED(new_w) = FALSE;
937 MB_POPPED_UP(new_w) = FALSE;
938 MB_LAST_TIMESTAMP(new_w) = 0;
939 MB_GC(new_w) = (GC)NULL;
941 if (req->core.width <= 0)
944 if (req->core.height <= 0)
947 CalculateMenuGlyphSize (new_w);
948 AdjustMenuButtonSize (new_w, adjustWidth, adjustHeight);
951 new_w->primitive.traversal_on = TRUE;
953 if(MB_SMENU(new_w) != (Widget)NULL) {
954 XtInsertEventHandler((Widget)new_w, ButtonPressMask,
955 False, PreMenuButtonHandler, MB_SMENU(new_w), XtListHead);
956 XtAddEventHandler((Widget)new_w, ButtonPressMask,
957 FALSE, MenuButtonHandler, MB_SMENU(new_w));
958 XtAddCallback(XtParent(MB_SMENU(new_w)), XtNpopdownCallback,
959 PopdownCallback, (XtPointer)new_w);
960 XtAddCallback(XtParent(MB_SMENU(new_w)), XtNpopupCallback,
961 PopupCallback, (XtPointer)new_w);
964 if (name) XtFree(name);
975 unsigned int text_height;
977 DtMenuButtonWidget mb = (DtMenuButtonWidget) wid ;
978 Window win = XtWindow(wid);
979 Display *dpy = XtDisplay(wid);
981 ht = mb->primitive.highlight_thickness;
982 st = mb->primitive.shadow_thickness;
983 text_height = Lab_TextRect_height(mb);
985 tsc = mb->primitive.top_shadow_color;
986 bsc = mb->primitive.bottom_shadow_color;
988 tsGC = mb->primitive.top_shadow_GC;
989 bsGC = mb->primitive.bottom_shadow_GC;
993 if(MB_ARMED(mb) == TRUE) {
994 XFillRectangle(dpy, win, gc,
995 MB_GLYPH_X(mb), MB_GLYPH_Y(mb),
996 MB_GLYPH_WIDTH(mb), MB_GLYPH_HEIGHT(mb));
997 XmeDrawArrow(dpy, win,
999 MB_GLYPH_X(mb) + ht + st - 1,
1000 MB_GLYPH_Y(mb) + ht + st - 1,
1001 MB_GLYPH_WIDTH(mb) - 2*(ht + st - 1),
1002 MB_GLYPH_HEIGHT(mb) - 2*(ht + st - 1),
1005 /* standard (unarmed) arrow */
1007 XFillRectangle(dpy, win, gc,
1008 MB_GLYPH_X(mb), MB_GLYPH_Y(mb),
1009 MB_GLYPH_WIDTH(mb), MB_GLYPH_HEIGHT(mb));
1010 XmeDrawArrow(dpy, win,
1012 MB_GLYPH_X(mb) + ht + st - 1,
1013 MB_GLYPH_Y(mb) + ht + st - 1,
1014 MB_GLYPH_WIDTH(mb) - 2*(ht + st - 1),
1015 MB_GLYPH_HEIGHT(mb) - 2*(ht + st - 1),
1023 DtMenuButtonWidget mb)
1028 if(MB_GC(mb) != (GC)NULL) {
1029 XtReleaseGC((Widget)mb, MB_GC(mb));
1030 MB_GC(mb) = (GC)NULL;
1033 bg = mb->core.background_pixel;
1034 values.foreground = values.background = bg;
1035 values.graphics_exposures = FALSE;
1036 MB_GC(mb) = XtGetGC ((Widget) mb,
1037 GCForeground | GCBackground | GCGraphicsExposures, &values);
1041 *************************************************************************
1045 *************************************************************************
1055 return XtCreateWidget(name,dtMenuButtonWidgetClass,parent, al, ac);
1061 Widget *topManager )
1063 while (XmIsManager(XtParent(w)))