]> code.delx.au - gnu-emacs/blob - lwlib/lwlib-Xlw.c
Merge from emacs-24; up to 2012-05-04T19:17:01Z!monnier@iro.umontreal.ca
[gnu-emacs] / lwlib / lwlib-Xlw.c
1 /* The lwlib interface to "xlwmenu" menus.
2
3 Copyright (C) 1992 Lucid, Inc.
4 Copyright (C) 1994, 2000-2012 Free Software Foundation, Inc.
5
6 This file is part of the Lucid Widget Library.
7
8 The Lucid Widget Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
11 any later version.
12
13 The Lucid Widget Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23 #include <config.h>
24
25 #include <setjmp.h>
26 #include <lisp.h>
27
28 #include "lwlib-Xlw.h"
29 #include <X11/StringDefs.h>
30 #include <X11/IntrinsicP.h>
31 #include <X11/ObjectP.h>
32 #include <X11/CompositeP.h>
33 #include <X11/Shell.h>
34 #include "xlwmenu.h"
35
36 #if 0
37
38 #include <stdio.h>
39
40 /* Print the complete X resource name of widget WIDGET to stderr.
41 This is sometimes handy to have available. */
42
43 void
44 x_print_complete_resource_name (Widget widget)
45 {
46 int i;
47 String names[100];
48
49 for (i = 0; i < 100 && widget != NULL; ++i)
50 {
51 names[i] = XtName (widget);
52 widget = XtParent (widget);
53 }
54
55 for (--i; i >= 1; --i)
56 fprintf (stderr, "%s.", names[i]);
57 fprintf (stderr, "%s\n", names[0]);
58 }
59
60 #endif /* 0 */
61
62
63 \f/* Menu callbacks */
64
65 /* Callback XtNhighlightCallback for Lucid menus. W is the menu
66 widget, CLIENT_DATA contains a pointer to the widget_instance
67 for the menu, CALL_DATA contains a pointer to the widget_value
68 structure for the highlighted menu item. The latter may be null
69 if there isn't any highlighted menu item. */
70
71 static void
72 highlight_hook (Widget w, XtPointer client_data, XtPointer call_data)
73 {
74 widget_instance *instance = (widget_instance *) client_data;
75
76 if (instance->info->highlight_cb
77 && !w->core.being_destroyed)
78 instance->info->highlight_cb (w, instance->info->id, call_data);
79 }
80
81 static void
82 enter_hook (Widget w, XtPointer client_data, XtPointer call_data)
83 {
84 highlight_hook (w, client_data, call_data);
85 }
86
87 static void
88 leave_hook (Widget w, XtPointer client_data, XtPointer call_data)
89 {
90 highlight_hook (w, client_data, NULL);
91 }
92
93
94 static void
95 pre_hook (Widget w, XtPointer client_data, XtPointer call_data)
96 {
97 widget_instance* instance = (widget_instance*)client_data;
98 widget_value* val;
99
100 if (w->core.being_destroyed)
101 return;
102
103 val = lw_get_widget_value_for_widget (instance, w);
104 if (instance->info->pre_activate_cb)
105 instance->info->pre_activate_cb (w, instance->info->id,
106 val ? val->call_data : NULL);
107 }
108
109 static void
110 pick_hook (Widget w, XtPointer client_data, XtPointer call_data)
111 {
112 widget_instance* instance = (widget_instance*)client_data;
113 widget_value* contents_val = (widget_value*)call_data;
114 widget_value* widget_val;
115 XtPointer widget_arg;
116
117 if (w->core.being_destroyed)
118 return;
119
120 if (instance->info->selection_cb && contents_val && contents_val->enabled
121 && !contents_val->contents)
122 instance->info->selection_cb (w, instance->info->id,
123 contents_val->call_data);
124
125 widget_val = lw_get_widget_value_for_widget (instance, w);
126 widget_arg = widget_val ? widget_val->call_data : NULL;
127 if (instance->info->post_activate_cb)
128 instance->info->post_activate_cb (w, instance->info->id, widget_arg);
129
130 }
131
132 \f/* creation functions */
133
134 static Widget
135 xlw_create_menubar (widget_instance *instance)
136 {
137 Widget widget;
138 Arg al[5];
139 int ac = 0;
140
141 XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
142 #ifdef emacs
143 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
144 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
145 XtSetArg (al[ac], XtNallowResize, 1); ac++;
146 #endif
147
148 /* This used to use XtVaCreateWidget, but an old Xt version
149 has a bug in XtVaCreateWidget that frees instance->info->name. */
150 widget
151 = XtCreateWidget (instance->info->name, xlwMenuWidgetClass,
152 instance->parent, al, ac);
153
154 XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
155 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
156 XtAddCallback (widget, XtNleaveCallback, leave_hook, (XtPointer)instance);
157 XtAddCallback (widget, XtNenterCallback, enter_hook, (XtPointer)instance);
158 return widget;
159 }
160
161 static Widget
162 xlw_create_popup_menu (widget_instance *instance)
163 {
164 Widget popup_shell
165 = XtCreatePopupShell (instance->info->name, overrideShellWidgetClass,
166 instance->parent, NULL, 0);
167
168 Widget widget;
169 Arg al[2];
170 int ac = 0;
171
172 XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
173 XtSetArg (al[ac], XtNhorizontal, False); ac++;
174
175 /* This used to use XtVaManagedCreateWidget, but an old Xt version
176 has a bug in XtVaManagedCreateWidget that frees instance->info->name. */
177 widget
178 = XtCreateManagedWidget ("popup", xlwMenuWidgetClass,
179 popup_shell, al, ac);
180
181 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
182 XtAddCallback (widget, XtNleaveCallback, leave_hook, (XtPointer)instance);
183 XtAddCallback (widget, XtNenterCallback, enter_hook, (XtPointer)instance);
184
185 return popup_shell;
186 }
187
188 widget_creation_entry
189 xlw_creation_table [] =
190 {
191 {"menubar", xlw_create_menubar},
192 {"popup", xlw_create_popup_menu},
193 {NULL, NULL}
194 };
195
196 Boolean
197 lw_lucid_widget_p (Widget widget)
198 {
199 WidgetClass the_class = XtClass (widget);
200
201 if (the_class == xlwMenuWidgetClass)
202 return True;
203 if (the_class == overrideShellWidgetClass)
204 return (XtClass (((CompositeWidget)widget)->composite.children [0])
205 == xlwMenuWidgetClass);
206 return False;
207 }
208
209 void
210 xlw_update_one_widget (widget_instance* instance, Widget widget,
211 widget_value* val, Boolean deep_p)
212 {
213 Arg al[1];
214
215 /* This used to use XtVaSetValues, but some old Xt versions
216 that have a bug in XtVaCreateWidget might have it here too. */
217 XtSetArg (al[0], XtNmenu, instance->info->val);
218
219 XtSetValues (widget, al, 1);
220 }
221
222 void
223 xlw_update_one_value (widget_instance *instance,
224 Widget widget,
225 widget_value *val)
226 {
227 return;
228 }
229
230 void
231 xlw_pop_instance (widget_instance* instance, Boolean up)
232 {
233 }
234
235 void
236 xlw_popup_menu (Widget widget, XEvent *event)
237 {
238 XlwMenuWidget mw;
239
240 if (!XtIsShell (widget))
241 return;
242
243 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
244
245 if (event)
246 XtCallActionProc ((Widget) mw, "start", event, NULL, 0);
247 else
248 {
249 XEvent dummy;
250 XButtonPressedEvent *bd = &dummy.xbutton;
251
252 bd->type = ButtonPress;
253 bd->serial = 0;
254 bd->send_event = 0;
255 bd->display = XtDisplay (widget);
256 bd->window = XtWindow (XtParent (widget));
257 bd->time = CurrentTime;
258 bd->button = 0;
259 XQueryPointer (bd->display, bd->window, &bd->root,
260 &bd->subwindow, &bd->x_root, &bd->y_root,
261 &bd->x, &bd->y, &bd->state);
262
263 XtCallActionProc ((Widget) mw, "start", &dummy, NULL, 0);
264 }
265 }
266
267 \f/* Destruction of instances */
268 void
269 xlw_destroy_instance (widget_instance *instance)
270 {
271 if (instance->widget)
272 XtDestroyWidget (instance->widget);
273 }