2 Copyright 1989, 1994, 1998 The Open Group
4 Permission to use, copy, modify, distribute, and sell this software and its
5 documentation for any purpose is hereby granted without fee, provided that
6 the above copyright notice appear in all copies and that both that
7 copyright notice and this permission notice appear in supporting
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 Except as contained in this notice, the name of The Open Group shall not be
21 used in advertising or otherwise to promote the sale, use or other dealings
22 in this Software without prior written authorization from The Open Group.
27 * MenuButton.c - Source code for MenuButton widget.
29 * This is the source code for the Athena MenuButton widget.
30 * It is intended to provide an easy method of activating pulldown menus.
34 * By: Chris D. Peterson
36 * kit@expo.lcs.mit.edu
43 #include <X11/IntrinsicP.h>
44 #include <X11/StringDefs.h>
45 #include <X11/Xmu/SysUtil.h>
46 #include <X11/Xaw/MenuButtoP.h>
47 #include <X11/Xaw/XawInit.h>
53 static void XawMenuButtonClassInitialize(void);
54 static void XawMenuButtonInitialize(Widget, Widget, ArgList, Cardinal*);
55 static void XawMenuButtonDestroy(Widget);
56 static Boolean XawMenuButtonSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
61 static void PopupMenu(Widget, XEvent*, String*, Cardinal*);
66 #define superclass ((CommandWidgetClass)&commandClassRec)
68 static char defaultTranslations[] =
69 "<Enter>:" "highlight()\n"
70 "<Leave>:" "reset()\n"
71 "Any<BtnDown>:" "reset() PopupMenu()\n";
73 static char default_menu_name[] = "menu";
75 #define offset(field) XtOffsetOf(MenuButtonRec, field)
76 static XtResource resources[] = {
82 offset(menu_button.menu_name),
84 (XtPointer)default_menu_name
89 static XtActionsRec actionsList[] =
91 {"PopupMenu", PopupMenu},
94 MenuButtonClassRec menuButtonClassRec = {
97 (WidgetClass)superclass, /* superclass */
98 "MenuButton", /* class_name */
99 sizeof(MenuButtonRec), /* size */
100 XawMenuButtonClassInitialize, /* class_initialize */
101 NULL, /* class_part_initialize */
102 False, /* class_inited */
103 XawMenuButtonInitialize, /* initialize */
104 NULL, /* initialize_hook */
105 XtInheritRealize, /* realize */
106 actionsList, /* actions */
107 XtNumber(actionsList), /* num_actions */
108 resources, /* resources */
109 XtNumber(resources), /* num_resources */
110 NULLQUARK, /* xrm_class */
111 False, /* compress_motion */
112 True, /* compress_exposure */
113 True, /* compress_enterleave */
114 False, /* visible_interest */
115 XawMenuButtonDestroy, /* destroy */
116 XtInheritResize, /* resize */
117 XtInheritExpose, /* expose */
118 XawMenuButtonSetValues, /* set_values */
119 NULL, /* set_values_hook */
120 XtInheritSetValuesAlmost, /* set_values_almost */
121 NULL, /* get_values_hook */
122 NULL, /* accept_focus */
123 XtVersion, /* version */
124 NULL, /* callback_private */
125 defaultTranslations, /* tm_table */
126 XtInheritQueryGeometry, /* query_geometry */
127 XtInheritDisplayAccelerator, /* display_accelerator */
128 NULL, /* extension */
132 XtInheritChangeSensitive /* change_sensitive */
136 NULL, /* extension */
140 NULL, /* extension */
144 NULL, /* extension */
148 WidgetClass menuButtonWidgetClass = (WidgetClass)&menuButtonClassRec;
154 XawMenuButtonClassInitialize(void)
156 XawInitializeWidgetSet();
157 XtRegisterGrabAction(PopupMenu, True,
158 ButtonPressMask | ButtonReleaseMask,
159 GrabModeAsync, GrabModeAsync);
164 XawMenuButtonInitialize(Widget request, Widget cnew,
165 ArgList args, Cardinal *num_args)
167 MenuButtonWidget mbw = (MenuButtonWidget)cnew;
169 if (mbw->menu_button.menu_name != default_menu_name)
170 mbw->menu_button.menu_name = XtNewString(mbw->menu_button.menu_name);
174 XawMenuButtonDestroy(Widget w)
176 MenuButtonWidget mbw = (MenuButtonWidget)w;
178 if (mbw->menu_button.menu_name != default_menu_name)
179 XtFree(mbw->menu_button.menu_name);
184 XawMenuButtonSetValues(Widget current, Widget request, Widget cnew,
185 ArgList args, Cardinal *num_args)
187 MenuButtonWidget mbw_old = (MenuButtonWidget)current;
188 MenuButtonWidget mbw_new = (MenuButtonWidget)cnew;
190 if (mbw_old->menu_button.menu_name != mbw_new->menu_button.menu_name) {
191 if (mbw_old->menu_button.menu_name != default_menu_name)
192 XtFree(mbw_old->menu_button.menu_name);
193 if (mbw_new->menu_button.menu_name != default_menu_name)
194 mbw_new->menu_button.menu_name =
195 XtNewString(mbw_new->menu_button.menu_name);
203 PopupMenu(Widget w, XEvent *event, String *params, Cardinal *num_params)
205 MenuButtonWidget mbw = (MenuButtonWidget)w;
206 Widget menu = NULL, temp;
209 int menu_x, menu_y, menu_width, menu_height, button_height;
210 Position button_x, button_y;
213 while(temp != NULL) {
214 menu = XtNameToWidget(temp, mbw->menu_button.menu_name);
216 temp = XtParent(temp);
222 char error_buf[BUFSIZ];
224 (void)XmuSnprintf(error_buf, sizeof(error_buf),
225 "MenuButton: Could not find menu widget named %s.",
226 mbw->menu_button.menu_name);
227 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
231 if (!XtIsRealized(menu))
232 XtRealizeWidget(menu);
234 menu_width = XtWidth(menu) + (XtBorderWidth(menu) << 1);
235 button_height = XtHeight(w) + (XtBorderWidth(w) << 1);
236 menu_height = XtHeight(menu) + (XtBorderWidth(menu) << 1);
238 XtTranslateCoords(w, 0, 0, &button_x, &button_y);
240 menu_y = button_y + button_height;
243 int scr_height = HeightOfScreen(XtScreen(menu));
245 if (menu_y + menu_height > scr_height)
246 menu_y = button_y - menu_height;
248 menu_y = scr_height - menu_height;
249 menu_x = button_x + XtWidth(w) + (XtBorderWidth(w) << 1);
250 if (menu_x + menu_width > WidthOfScreen(XtScreen(menu)))
251 menu_x = button_x - menu_width;
258 int scr_width = WidthOfScreen(XtScreen(menu));
260 if (menu_x + menu_width > scr_width)
261 menu_x = scr_width - menu_width;
267 XtSetArg(arglist[num_args], XtNx, menu_x); num_args++;
268 XtSetArg(arglist[num_args], XtNy, menu_y); num_args++;
269 XtSetValues(menu, arglist, num_args);
271 XtPopupSpringLoaded(menu);