1 /*
2 * misc useful X11 functions for UI. Athena Widgets.
3 *
4 * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
5 *
6 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <pthread.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14
15 #include <X11/Intrinsic.h>
16 #include <X11/StringDefs.h>
17 #include <X11/Shell.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xaw/XawInit.h>
20 #include <X11/Xaw/MenuButton.h>
21 #include <X11/Xaw/SimpleMenu.h>
22 #include <X11/Xaw/SmeBSB.h>
23 #include <X11/Xaw/SmeLine.h>
24 #include <X11/Xaw/Dialog.h>
25 #include <X11/Xaw/Scrollbar.h>
26 #include <X11/Xaw/Viewport.h>
27
28 #include "config.h"
29 #include "grab-ng.h"
30 #include "toolbox.h"
31 #include "wmhooks.h"
32
33 extern Display *dpy;
34 extern XVisualInfo vinfo;
35 extern Colormap colormap;
36 extern int stay_on_top;
37
38 extern Cursor menu_ptr;
39 extern Cursor left_ptr;
40
41 /* ---------------------------------------------------------------------- */
42 /* simple and handy error rotine */
43
44 void
45 oops(char *msg)
46 {
47 fprintf(stderr,"Oops: %s\n",msg);
48 exit(1);
49 }
50
51 /* ---------------------------------------------------------------------- */
52 /* some menu stuff */
53
54 Widget
55 add_pulldown_menu(Widget menubar,
56 char *name)
57 {
58 Widget menu,button;
59
60 button = XtVaCreateManagedWidget(name,menuButtonWidgetClass,menubar,NULL);
61 menu = XtVaCreatePopupShell("menu",simpleMenuWidgetClass,button,
62 XtNvisual,vinfo.visual,
63 XtNcolormap,colormap,
64 XtNdepth, vinfo.depth,
65 NULL);
66 return menu;
67 }
68
69 Widget
70 add_menu_entry(Widget menu, const char *name,
71 XtCallbackProc callback, XtPointer data)
72 {
73 Widget entry;
74
75 entry = XtVaCreateManagedWidget(name,smeBSBObjectClass,menu,NULL);
76 if (callback)
77 XtAddCallback(entry,XtNcallback,callback,data);
78 return entry;
79 }
80
81 Widget
82 add_menu_sep(Widget menu,char *name)
83 {
84 Widget entry;
85
86 entry = XtVaCreateManagedWidget(name,smeLineObjectClass,menu,NULL);
87 return entry;
88 }
89
90 /* ---------------------------------------------------------------------- */
91 /* right-mouse popupmenu */
92
93 static long sel=-1;
94
95 static void
96 popdown_menu_CB(Widget widget, XtPointer client_data, XtPointer calldata)
97 {
98 if (-1 == sel)
99 sel = -2;
100 XUngrabPointer(dpy,CurrentTime);
101 XtDestroyWidget(widget);
102 }
103
104 static void
105 select_menu_CB(Widget widget, XtPointer client_data, XtPointer calldata)
106 {
107 sel = (long)client_data;
108 }
109
110 int
111 popup_menu(Widget parent, const char *title, struct STRTAB *entries)
112 {
113 Widget menu,line;
114 int x,y,rx,ry,mask;
115 Window root,child;
116 XtAppContext context;
117 long i;
118
119 sel = -1;
120 if (!title)
121 menu = XtVaCreatePopupShell("menu",simpleMenuWidgetClass,parent,
122 XtNvisual,vinfo.visual,
123 XtNcolormap,colormap,
124 XtNdepth, vinfo.depth,
125 NULL);
126 else {
127 menu = XtVaCreatePopupShell("menu",simpleMenuWidgetClass,parent,
128 XtNvisual,vinfo.visual,
129 XtNcolormap,colormap,
130 XtNdepth, vinfo.depth,
131 XtNlabel,title,
132 NULL);
133 add_menu_sep(menu,"sep");
134 }
135
136 for (i = 0; entries[i].str != NULL; i++) {
137 if (strlen(entries[i].str) == 0) {
138 add_menu_sep(menu,"sep");
139 } else {
140 line = add_menu_entry(menu, entries[i].str,
141 select_menu_CB,
142 (XtPointer)i/*(entries[i].nr)*/);
143 if (entries[i].nr == -1)
144 XtVaSetValues(line,XtNsensitive,False,NULL);
145 }
146 }
147
148 XQueryPointer(dpy,
149 RootWindowOfScreen(XtScreen(menu)),
150 &root, &child,
151 &rx, &ry, &x, &y, &mask);
152 XtVaSetValues(menu,
153 XtNx,x-10,
154 XtNy,y-10,
155 NULL);
156
157 XtAddCallback(menu,XtNpopdownCallback,
158 (XtCallbackProc)popdown_menu_CB,(XtPointer)NULL);
159 XtPopupSpringLoaded(menu);
160 XGrabPointer(dpy, XtWindow(menu), False,
161 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
162 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
163
164 #if 0
165 XtVaGetValues(menu,XtNheight,&height,NULL);
166 if (y > XtScreen(menu)->height - height) {
167 y = XtScreen(menu)->height - height;
168 XtVaSetValues(menu,XtNy,y,NULL);
169 }
170 #endif
171
172 XDefineCursor(dpy,XtWindow(menu),menu_ptr);
173
174 context = XtWidgetToApplicationContext (menu);
175 while (sel == -1 || XtAppPending(context)) {
176 XtAppProcessEvent (context, XtIMAll);
177 }
178 if (sel == -2)
179 sel = -1;
180 return sel;
181 }
182
183 void
184 offscreen_scroll_AC(Widget widget, XEvent *event,
185 String *params, Cardinal *num_params)
186 {
187 #define AUTOJUMP 25
188 int x,y,rx,ry,sy,wy,wh,mask;
189 Dimension dwy,dwh;
190 Window root,child;
191
192
193 XQueryPointer(dpy,RootWindowOfScreen(XtScreen(widget)),
194 &root, &child, &rx, &ry, &x, &y, &mask);
195 sy = XtScreen(widget)->height;
196 XtVaGetValues(widget,
197 XtNy, &dwy,
198 XtNheight, &dwh,
199 NULL);
200 wy = (signed short)dwy;
201 wh = (signed short)dwh;
202 if (ry + AUTOJUMP < sy && ry > AUTOJUMP)
203 return;
204 if (ry <= wy)
205 return;
206 if (ry >= wy+wh)
207 return;
208
209 if (ry + AUTOJUMP >= sy)
210 ry -= AUTOJUMP, wy -= AUTOJUMP;
211 if (ry <= AUTOJUMP)
212 ry += AUTOJUMP, wy += AUTOJUMP;
213 XtVaSetValues(widget,
214 XtNy,wy,
215 NULL);
216 XWarpPointer(dpy, None, RootWindowOfScreen(XtScreen(widget)),
217 0, 0, 0, 0, rx, ry);
218 }
219
220 /* ---------------------------------------------------------------------- */
221 /* resource handling */
222
223 char*
224 get_string_resource(Widget widget, char *name)
225 {
226 struct RESDATA { char *str; } resdata = { NULL };
227 XtResource res_desc[] = {{
228 NULL, /* name goes here */
229 XtCString,
230 XtRString,
231 sizeof(char*),
232 XtOffset(struct RESDATA*,str),
233 XtRString,
234 ""
235 }};
236
237 res_desc[0].resource_name = name;
238 XtGetApplicationResources(widget,&resdata,
239 res_desc,XtNumber(res_desc),
240 NULL,0);
241 return resdata.str;
242 }
243
244 /* ---------------------------------------------------------------------- */
245 /* some stuff for doing keyboard scroll with the viewport widget */
246
247 void
248 kbd_scroll_viewport_AC(Widget widget, XEvent *event,
249 String *params, Cardinal *num_params)
250 {
251 XtOrientation ori;
252 long dir, percent;
253 Dimension length = 0;
254
255 if (2 != *num_params) {
256 fprintf(stderr,"KbdScroll: wrong number of arguments\n");
257 return;
258 }
259
260 if (XtClass(widget) != scrollbarWidgetClass) {
261 fprintf(stderr,"KbdScroll: not a scrollbar\n");
262 return;
263 }
264
265 XtVaGetValues(widget,XtNorientation,&ori,NULL);
266 XtVaGetValues(widget,(ori == XtorientVertical) ? XtNheight : XtNwidth,
267 &length,NULL);
268
269
270 if (0 == strcasecmp(params[0],"left") ||
271 0 == strcasecmp(params[0],"up")) {
272 dir = -1;
273 } else if (0 == strcasecmp(params[0],"right") ||
274 0 == strcasecmp(params[0],"down")) {
275 dir = 1;
276 } else {
277 fprintf(stderr,"KbdScroll: what is %s?\n",params[0]);
278 return;
279 }
280
281 /* secound arg */
282 percent = atoi(params[1]);
283 if (percent <= 0 || percent > 100) {
284 fprintf(stderr,"KbdScroll: invalid value: %s\n",params[1]);
285 return;
286 }
287 #if 0
288 fprintf(stderr,"KbdScroll: %d %d %d => %d\n",
289 percent,length,dir,(dir*percent*length/100));
290 #endif
291 XtCallCallbacks(widget, XtNscrollProc,
292 (XtPointer)(dir*percent*length/100));
293 }
294
295 void
296 report_viewport_CB(Widget widget, XtPointer client_data, XtPointer calldata)
297 {
298 Widget w,s;
299
300 w = (Widget)client_data;
301 s = w;
302 while (s && !XtIsShell(s))
303 s = XtParent(s);
304 if (s)
305 XtInstallAllAccelerators(w,s);
306 }
307
308 /* ---------------------------------------------------------------------- */
309 /* ask/tell user */
310
311 void
312 popdown_CB(Widget widget, XtPointer client_data, XtPointer calldata)
313 {
314 Widget cancel;
315
316 cancel = (Widget)client_data;
317 XtPopdown(cancel);
318 }
319
320 void
321 destroy_CB(Widget widget, XtPointer client_data, XtPointer calldata)
322 {
323 Widget cancel;
324
325 cancel = (Widget)client_data;
326 XtDestroyWidget(cancel);
327 }
328
329 void
330 center_under_mouse(Widget shell, int w, int h)
331 {
332 int x,y,rx,ry,mask,width=0,height=0,nx,ny;
333 Window root,child;
334
335 if (!XtIsShell(shell))
336 oops("move_under_mouse: not a shell");
337
338 XQueryPointer(dpy,
339 RootWindowOfScreen(XtScreen(shell)),
340 &root, &child,
341 &rx, &ry, &x, &y, &mask);
342 XtVaGetValues(shell,
343 XtNwidth, &width,
344 XtNheight,&height,
345 NULL);
346 if (width==0) width=w;
347 if (height==0) height=h;
348 nx = rx-(width/2);
349 ny = ry-(height/2);
350 if (nx < 0) nx = 0;
351 if (ny < 0) ny = 0;
352 /* TODO: test right & bottom border too */
353 XtVaSetValues(shell,
354 XtNx,nx,
355 XtNy,ny,
356 NULL);
357 }
358
359 void
360 get_user_string(Widget parent, char *title, char *label, char *value,
361 XtCallbackProc ok, XtPointer data)
362 {
363 Widget shell,ask;
364 char *t,*l;
365
366 t = get_string_resource(parent,title);
367 l = get_string_resource(parent,label);
368 if (strlen(t) == 0) t = title;
369 if (strlen(l) == 0) l = label;
370
371 shell = XtVaCreatePopupShell("popup_ask",transientShellWidgetClass,parent,
372 XtNtitle,t,
373 XtNvisual,vinfo.visual,
374 XtNcolormap,colormap,
375 XtNdepth, vinfo.depth,
376 NULL);
377 ask = XtVaCreateManagedWidget("ask",dialogWidgetClass,shell,
378 XtNlabel,l,
379 XtNvalue,value ? value : "",
380 NULL);
381 XawDialogAddButton(ask,"ok",ok,data);
382 XawDialogAddButton(ask,"cancel",
383 (XtCallbackProc)destroy_CB,(XtPointer)shell);
384 XtInstallAllAccelerators
385 (XtNameToWidget(ask,"value"),shell);
386
387 center_under_mouse(XtParent(ask),200,80);
388 XtPopup(XtParent(ask),XtGrabNonexclusive);
389 XDefineCursor(dpy,XtWindow(shell),left_ptr);
390 }
391
392 void
393 tell_user(Widget parent, char *title, char *label)
394 {
395 Widget shell,tell;
396 char *t,*l;
397
398 t = get_string_resource(parent,title);
399 l = get_string_resource(parent,label);
400 if (strlen(t) == 0) t = title;
401 if (strlen(l) == 0) l = label;
402
403 shell = XtVaCreatePopupShell("popup_tell",transientShellWidgetClass,parent,
404 XtNtitle,t,
405 XtNvisual,vinfo.visual,
406 XtNcolormap,colormap,
407 XtNdepth, vinfo.depth,
408 NULL);
409 tell = XtVaCreateManagedWidget("tell",dialogWidgetClass,shell,
410 XtNlabel,l,
411 NULL);
412 XawDialogAddButton(tell,"ok",(XtCallbackProc)destroy_CB,
413 (XtPointer)shell);
414 XtInstallAllAccelerators(tell,shell);
415
416 center_under_mouse(XtParent(tell),200,80);
417 XtPopup(XtParent(tell),XtGrabNonexclusive);
418 XDefineCursor(dpy,XtWindow(shell),left_ptr);
419 }
420
421 void
422 xperror(Widget parent, char *msg)
423 {
424 char text[512];
425
426 sprintf(text,"%s: %s",msg,strerror(errno));
427 tell_user(parent,"str_perror_title",text);
428 }
429
430 /* ---------------------------------------------------------------------- */
431 /* cool 3D-Buttons :-) */
432
433 void
434 set_shadowWidth_AC(Widget widget, XEvent *event,
435 String *params, Cardinal *num_params)
436 {
437 int depth;
438
439 if (1 != *num_params) {
440 fprintf(stderr,"SetShadowWidth: wrong number of arguments\n");
441 return;
442 }
443 depth = atoi(params[0]);
444 XtVaSetValues(widget,"shadowWidth" /* XtNshadowWidth */, depth,NULL);
445 }
446
447
448 /* ---------------------------------------------------------------------- */
449 /* some stuff for help */
450
451 void
452 help_AC(Widget widget, XEvent *event,
453 String *params, Cardinal *num_params)
454 {
455 Widget shell,help;
456 char *l;
457
458 shell =
459 XtVaCreatePopupShell("popup_help",transientShellWidgetClass,widget,
460 XtNvisual,vinfo.visual,
461 XtNcolormap,colormap,
462 XtNdepth, vinfo.depth,
463 NULL);
464 help = XtVaCreateManagedWidget("help",dialogWidgetClass,shell,
465 NULL);
466 XawDialogAddButton(help,"ok",(XtCallbackProc)destroy_CB,
467 (XtPointer)shell);
468 XtInstallAllAccelerators(help,shell);
469
470 l = get_string_resource(widget,"help");
471 if (strlen(l) == 0)
472 l = "Sorry, no help text available.";
473
474 center_under_mouse(shell,200,100);
475
476 XtVaSetValues(help,XtNlabel,l,NULL);
477 XtPopup(shell,XtGrabNonexclusive);
478 if (wm_stay_on_top && stay_on_top > 0)
479 wm_stay_on_top(dpy,XtWindow(shell),1);
480
481 XDefineCursor(dpy,XtWindow(shell),left_ptr);
482 }
483
|
This page was automatically generated by the
LXR engine.
|