summaryrefslogtreecommitdiff
path: root/uisimulator/x11/screenhack.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2002-04-27 23:48:49 +0000
committerDaniel Stenberg <daniel@haxx.se>2002-04-27 23:48:49 +0000
commit3caa3c08717ad745b49da01bf70a4c0da195ac14 (patch)
tree486f9d59673e537cd100957c8748b351e0a64ce4 /uisimulator/x11/screenhack.c
parentc1543511b342162b2b537485c6646186037d8845 (diff)
downloadrockbox-3caa3c08717ad745b49da01bf70a4c0da195ac14.tar.gz
rockbox-3caa3c08717ad745b49da01bf70a4c0da195ac14.zip
moved X11-specific files into a separate subdir to keep root clean for
target files git-svn-id: svn://svn.rockbox.org/rockbox/trunk@282 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'uisimulator/x11/screenhack.c')
-rw-r--r--uisimulator/x11/screenhack.c576
1 files changed, 576 insertions, 0 deletions
diff --git a/uisimulator/x11/screenhack.c b/uisimulator/x11/screenhack.c
new file mode 100644
index 0000000000..f4f5aaa348
--- /dev/null
+++ b/uisimulator/x11/screenhack.c
@@ -0,0 +1,576 @@
1/* xscreensaver, Copyright (c) 1992, 1995, 1997, 1998
2 * Jamie Zawinski <jwz@jwz.org>
3 *
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
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
10 * implied warranty.
11 *
12 * And remember: X Windows is to graphics hacking as roman numerals are to
13 * the square root of pi.
14 */
15
16/* This file contains simple code to open a window or draw on the root.
17 The idea being that, when writing a graphics hack, you can just link
18 with this .o to get all of the uninteresting junk out of the way.
19
20 - create a procedure `screenhack(dpy, window)'
21
22 - create a variable `char *progclass' which names this program's
23 resource class.
24
25 - create a variable `char defaults []' for the default resources, and
26 null-terminate it.
27
28 - create a variable `XrmOptionDescRec options[]' for the command-line,
29 and null-terminate it.
30
31 And that's it...
32 */
33
34#include <stdio.h>
35#include <X11/Intrinsic.h>
36#include <X11/IntrinsicP.h>
37#include <X11/CoreP.h>
38#include <X11/Shell.h>
39#include <X11/StringDefs.h>
40#include <X11/Xutil.h>
41#include <X11/keysym.h>
42
43#ifdef __sgi
44# include <X11/SGIScheme.h> /* for SgiUseSchemes() */
45#endif /* __sgi */
46
47#ifdef HAVE_XMU
48# ifndef VMS
49# include <X11/Xmu/Error.h>
50# else /* VMS */
51# include <Xmu/Error.h>
52# endif
53#else
54# include "xmu.h"
55#endif
56#include "screenhack.h"
57#include "version.h"
58#include "vroot.h"
59
60#ifndef isupper
61# define isupper(c) ((c) >= 'A' && (c) <= 'Z')
62#endif
63#ifndef _tolower
64# define _tolower(c) ((c) - 'A' + 'a')
65#endif
66
67
68char *progname;
69XrmDatabase db;
70XtAppContext app;
71Bool mono_p;
72
73static XrmOptionDescRec default_options [] = {
74 { "-root", ".root", XrmoptionNoArg, "True" },
75 { "-window", ".root", XrmoptionNoArg, "False" },
76 { "-mono", ".mono", XrmoptionNoArg, "True" },
77 { "-install", ".installColormap", XrmoptionNoArg, "True" },
78 { "-noinstall",".installColormap", XrmoptionNoArg, "False" },
79 { "-visual", ".visualID", XrmoptionSepArg, 0 },
80 { "-window-id", ".windowID", XrmoptionSepArg, 0 },
81 { 0, 0, 0, 0 }
82};
83
84static char *default_defaults[] = {
85 ".root: false",
86 "*geometry: 200x100", /* this should be .geometry, but nooooo... */
87 "*mono: false",
88 "*installColormap: false",
89 "*visualID: default",
90 "*windowID: ",
91 0
92};
93
94extern Display* dpy;
95
96static XrmOptionDescRec *merged_options;
97static int merged_options_size;
98static char **merged_defaults;
99
100static void
101merge_options (void)
102{
103 int def_opts_size, opts_size;
104 int def_defaults_size, defaults_size;
105
106 for (def_opts_size = 0; default_options[def_opts_size].option;
107 def_opts_size++)
108 ;
109 for (opts_size = 0; options[opts_size].option; opts_size++)
110 ;
111
112 merged_options_size = def_opts_size + opts_size;
113 merged_options = (XrmOptionDescRec *)
114 malloc ((merged_options_size + 1) * sizeof(*default_options));
115 memcpy (merged_options, default_options,
116 (def_opts_size * sizeof(*default_options)));
117 memcpy (merged_options + def_opts_size, options,
118 ((opts_size + 1) * sizeof(*default_options)));
119
120 for (def_defaults_size = 0; default_defaults[def_defaults_size];
121 def_defaults_size++)
122 ;
123 for (defaults_size = 0; defaults[defaults_size]; defaults_size++)
124 ;
125 merged_defaults = (char **)
126 malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));;
127 memcpy (merged_defaults, default_defaults,
128 def_defaults_size * sizeof(*defaults));
129 memcpy (merged_defaults + def_defaults_size, defaults,
130 (defaults_size + 1) * sizeof(*defaults));
131
132 /* This totally sucks. Xt should behave like this by default.
133 If the string in `defaults' looks like ".foo", change that
134 to "Progclass.foo".
135 */
136 {
137 char **s;
138 for (s = merged_defaults; *s; s++)
139 if (**s == '.')
140 {
141 const char *oldr = *s;
142 char *newr = (char *) malloc(strlen(oldr) + strlen(progclass) + 3);
143 strcpy (newr, progclass);
144 strcat (newr, oldr);
145 *s = newr;
146 }
147 }
148}
149
150
151/* Make the X errors print out the name of this program, so we have some
152 clue which one has a bug when they die under the screensaver.
153 */
154
155static int
156screenhack_ehandler (Display *dpy, XErrorEvent *error)
157{
158 fprintf (stderr, "\nX error in %s:\n", progname);
159 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
160 exit (-1);
161 else
162 fprintf (stderr, " (nonfatal.)\n");
163 return 0;
164}
165
166static Bool
167MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
168{
169 return (event->xany.type == MapNotify &&
170 event->xvisibility.window == (Window) window);
171}
172
173
174#ifdef XLOCKMORE
175extern void pre_merge_options (void);
176#endif
177
178
179static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW;
180
181/* Dead-trivial event handling: exits if "q" or "ESC" are typed.
182 Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
183 */
184int
185screenhack_handle_event (Display *dpy, XEvent *event)
186{
187 int key=0;
188 switch (event->xany.type)
189 {
190 case KeyPress:
191 {
192 KeySym keysym;
193 unsigned char c = 0;
194 XLookupString (&event->xkey, &c, 1, &keysym, 0);
195 if (! (keysym >= XK_Shift_L && keysym <= XK_Hyper_R))
196 XBell (dpy, 0); /* beep for non-chord keys */
197 key = keysym;
198 fprintf(stderr, "KEY PRESSED: %c (%02x)\n", c, c);
199 }
200 break;
201 case ResizeRequest:
202 screen_resized(event->xresizerequest.width, event->xresizerequest.height);
203 screen_redraw();
204 fprintf(stderr, "WINDOW RESIZED to width %d height %d\n",
205 event->xresizerequest.width, event->xresizerequest.height);
206 break;
207 default:
208 fprintf(stderr, "EVENT: %d (see /usr/include/X11/X.h)\n",
209 event->xany.type);
210 break;
211 case Expose:
212 screen_redraw();
213 fprintf(stderr, "EXPOSE: x: %d y: %d width: %d height: %d\n",
214 event->xexpose.x, event->xexpose.y,
215 event->xexpose.width, event->xexpose.height);
216 break;
217 case ButtonPress:
218 fprintf(stderr, "BUTTON PRESSED\n");
219 break;
220 case ClientMessage:
221 {
222 if (event->xclient.message_type != XA_WM_PROTOCOLS)
223 {
224 char *s = XGetAtomName(dpy, event->xclient.message_type);
225 if (!s) s = "(null)";
226 fprintf (stderr, "%s: unknown ClientMessage %s received!\n",
227 progname, s);
228 }
229 else if (event->xclient.data.l[0] != XA_WM_DELETE_WINDOW)
230 {
231 char *s1 = XGetAtomName(dpy, event->xclient.message_type);
232 char *s2 = XGetAtomName(dpy, event->xclient.data.l[0]);
233 if (!s1) s1 = "(null)";
234 if (!s2) s2 = "(null)";
235 fprintf (stderr, "%s: unknown ClientMessage %s[%s] received!\n",
236 progname, s1, s2);
237 }
238 else
239 {
240 exit (0);
241 }
242 }
243 break;
244 }
245 return key;
246}
247
248
249int
250screenhack_handle_events (void)
251{
252 int key=0;
253 while (XPending (dpy))
254 {
255 XEvent event;
256 XNextEvent (dpy, &event);
257 key=screenhack_handle_event (dpy, &event);
258 }
259 return key;
260}
261
262
263static Visual *
264pick_visual (Screen *screen)
265{
266#ifdef USE_GL
267 /* If we're linking against GL (that is, this is the version of screenhack.o
268 that the GL hacks will use, which is different from the one that the
269 non-GL hacks will use) then try to pick the "best" visual by interrogating
270 the GL library instead of by asking Xlib. GL knows better.
271 */
272 Visual *v = 0;
273 char *string = get_string_resource ("visualID", "VisualID");
274 char *s;
275
276 if (string)
277 for (s = string; *s; s++)
278 if (isupper (*s)) *s = _tolower (*s);
279
280 if (!string || !*string ||
281 !strcmp (string, "gl") ||
282 !strcmp (string, "best") ||
283 !strcmp (string, "color") ||
284 !strcmp (string, "default"))
285 v = get_gl_visual (screen); /* from ../utils/visual-gl.c */
286
287 if (string)
288 free (string);
289 if (v)
290 return v;
291#endif /* USE_GL */
292
293 return get_visual_resource (screen, "visualID", "VisualID", False);
294}
295
296
297/* Notice when the user has requested a different visual or colormap
298 on a pre-existing window (e.g., "-root -visual truecolor" or
299 "-window-id 0x2c00001 -install") and complain, since when drawing
300 on an existing window, we have no choice about these things.
301 */
302static void
303visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
304 Bool window_p)
305{
306 char *visual_string = get_string_resource ("visualID", "VisualID");
307 Visual *desired_visual = pick_visual (screen);
308 char win[100];
309 char why[100];
310
311 if (window == RootWindowOfScreen (screen))
312 strcpy (win, "root window");
313 else
314 sprintf (win, "window 0x%x", (unsigned long) window);
315
316 if (window_p)
317 sprintf (why, "-window-id 0x%x", (unsigned long) window);
318 else
319 strcpy (why, "-root");
320
321 if (visual_string && *visual_string)
322 {
323 char *s;
324 for (s = visual_string; *s; s++)
325 if (isupper (*s)) *s = _tolower (*s);
326
327 if (!strcmp (visual_string, "default") ||
328 !strcmp (visual_string, "default") ||
329 !strcmp (visual_string, "best"))
330 /* don't warn about these, just silently DWIM. */
331 ;
332 else if (visual != desired_visual)
333 {
334 fprintf (stderr, "%s: ignoring `-visual %s' because of `%s'.\n",
335 progname, visual_string, why);
336 fprintf (stderr, "%s: using %s's visual 0x%x.\n",
337 progname, win, XVisualIDFromVisual (visual));
338 }
339 free (visual_string);
340 }
341
342 if (visual == DefaultVisualOfScreen (screen) &&
343 has_writable_cells (screen, visual) &&
344 get_boolean_resource ("installColormap", "InstallColormap"))
345 {
346 fprintf (stderr, "%s: ignoring `-install' because of `%s'.\n",
347 progname, why);
348 fprintf (stderr, "%s: using %s's colormap 0x%x.\n",
349 progname, win, (unsigned long) cmap);
350 }
351}
352
353
354int
355main (int argc, char **argv)
356{
357 Widget toplevel;
358 Display *dpy;
359 Window window;
360 Screen *screen;
361 Visual *visual;
362 Colormap cmap;
363 Bool root_p;
364 Window on_window = 0;
365 XEvent event;
366 Boolean dont_clear /*, dont_map */;
367 char version[255];
368
369#ifdef XLOCKMORE
370 pre_merge_options ();
371#endif
372 merge_options ();
373
374#ifdef __sgi
375 /* We have to do this on SGI to prevent the background color from being
376 overridden by the current desktop color scheme (we'd like our backgrounds
377 to be black, thanks.) This should be the same as setting the
378 "*useSchemes: none" resource, but it's not -- if that resource is
379 present in the `default_defaults' above, it doesn't work, though it
380 does work when passed as an -xrm arg on the command line. So screw it,
381 turn them off from C instead.
382 */
383 SgiUseSchemes ("none");
384#endif /* __sgi */
385
386 toplevel = XtAppInitialize (&app, progclass, merged_options,
387 merged_options_size, &argc, argv,
388 merged_defaults, 0, 0);
389 dpy = XtDisplay (toplevel);
390 screen = XtScreen (toplevel);
391 db = XtDatabase (dpy);
392
393 XtGetApplicationNameAndClass (dpy, &progname, &progclass);
394
395 /* half-assed way of avoiding buffer-overrun attacks. */
396 if (strlen (progname) >= 100) progname[100] = 0;
397
398 XSetErrorHandler (screenhack_ehandler);
399
400 XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
401 XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
402
403
404 if (argc > 1)
405 {
406 const char *s;
407 int i;
408 int x = 18;
409 int end = 78;
410 Bool help_p = !strcmp(argv[1], "-help");
411 fprintf (stderr, "%s\n", version);
412 for (s = progclass; *s; s++) fprintf(stderr, " ");
413 fprintf (stderr, " eXcellent GUI\n\n");
414
415 if (!help_p)
416 fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
417 fprintf (stderr, "Options include: ");
418 for (i = 0; i < merged_options_size; i++)
419 {
420 char *sw = merged_options [i].option;
421 Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
422 int size = strlen (sw) + (argp ? 6 : 0) + 2;
423 if (x + size >= end)
424 {
425 fprintf (stderr, "\n\t\t ");
426 x = 18;
427 }
428 x += size;
429 fprintf (stderr, "%s", sw);
430 if (argp) fprintf (stderr, " <arg>");
431 if (i != merged_options_size - 1) fprintf (stderr, ", ");
432 }
433 fprintf (stderr, ".\n");
434 exit (help_p ? 0 : 1);
435 }
436
437 dont_clear = get_boolean_resource ("dontClearRoot", "Boolean");
438/*dont_map = get_boolean_resource ("dontMapWindow", "Boolean"); */
439 mono_p = get_boolean_resource ("mono", "Boolean");
440 if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
441 mono_p = True;
442
443 root_p = get_boolean_resource ("root", "Boolean");
444
445 {
446 char *s = get_string_resource ("windowID", "WindowID");
447 if (s && *s)
448 on_window = get_integer_resource ("windowID", "WindowID");
449 if (s) free (s);
450 }
451
452 if (on_window)
453 {
454 XWindowAttributes xgwa;
455 window = (Window) on_window;
456 XtDestroyWidget (toplevel);
457 XGetWindowAttributes (dpy, window, &xgwa);
458 cmap = xgwa.colormap;
459 visual = xgwa.visual;
460 visual_warning (screen, window, visual, cmap, True);
461 }
462 else if (root_p)
463 {
464 XWindowAttributes xgwa;
465 window = RootWindowOfScreen (XtScreen (toplevel));
466 XtDestroyWidget (toplevel);
467 XGetWindowAttributes (dpy, window, &xgwa);
468 cmap = xgwa.colormap;
469 visual = xgwa.visual;
470 visual_warning (screen, window, visual, cmap, False);
471 }
472 else
473 {
474 Boolean def_visual_p;
475 visual = pick_visual (screen);
476
477 if (toplevel->core.width <= 0)
478 toplevel->core.width = 600;
479 if (toplevel->core.height <= 0)
480 toplevel->core.height = 480;
481
482 def_visual_p = (visual == DefaultVisualOfScreen (screen));
483
484 if (!def_visual_p)
485 {
486 unsigned int bg, bd;
487 Widget new;
488
489 cmap = XCreateColormap (dpy, RootWindowOfScreen(screen),
490 visual, AllocNone);
491 bg = get_pixel_resource ("background", "Background", dpy, cmap);
492 bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
493
494 new = XtVaAppCreateShell (progname, progclass,
495 topLevelShellWidgetClass, dpy,
496 XtNmappedWhenManaged, False,
497 XtNvisual, visual,
498 XtNdepth, visual_depth (screen, visual),
499 XtNwidth, toplevel->core.width,
500 XtNheight, toplevel->core.height,
501 XtNcolormap, cmap,
502 XtNbackground, (Pixel) bg,
503 XtNborderColor, (Pixel) bd,
504 XtNinput, True, /* for WM_HINTS */
505 0);
506 XtDestroyWidget (toplevel);
507 toplevel = new;
508 XtRealizeWidget (toplevel);
509 window = XtWindow (toplevel);
510 }
511 else
512 {
513 XtVaSetValues (toplevel,
514 XtNmappedWhenManaged, False,
515 XtNinput, True, /* for WM_HINTS */
516 0);
517 XtRealizeWidget (toplevel);
518 window = XtWindow (toplevel);
519
520 if (get_boolean_resource ("installColormap", "InstallColormap"))
521 {
522 cmap = XCreateColormap (dpy, window,
523 DefaultVisualOfScreen (XtScreen (toplevel)),
524 AllocNone);
525 XSetWindowColormap (dpy, window, cmap);
526 }
527 else
528 {
529 cmap = DefaultColormap (dpy, DefaultScreen (dpy));
530 }
531 }
532
533/*
534 if (dont_map)
535 {
536 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
537 XtRealizeWidget (toplevel);
538 }
539 else
540*/
541 {
542 XtPopup (toplevel, XtGrabNone);
543 }
544
545 XtVaSetValues(toplevel, XtNtitle, version, 0);
546
547 /* For screenhack_handle_events(): select KeyPress, and
548 announce that we accept WM_DELETE_WINDOW. */
549 {
550 XWindowAttributes xgwa;
551 XGetWindowAttributes (dpy, window, &xgwa);
552 XSelectInput (dpy, window,
553 xgwa.your_event_mask | KeyPressMask | ButtonPressMask | ResizeRedirectMask | ExposureMask);
554 XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
555 PropModeReplace,
556 (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
557 }
558 }
559
560 if (!dont_clear)
561 {
562 XSetWindowBackground (dpy, window,
563 get_pixel_resource ("background", "Background",
564 dpy, cmap));
565 XClearWindow (dpy, window);
566 }
567
568 if (!root_p && !on_window)
569 /* wait for it to be mapped */
570 XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
571
572 XSync (dpy, False);
573
574 screenhack (dpy, window); /* doesn't return */
575 return 0;
576}