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