The modifications are for all larger screens
[Rockbox.git] / uisimulator / x11 / screenhack.c
blob4b8713970a3b08860dc85d193dfaccdf4a20152f
1 /* xscreensaver, Copyright (c) 1992, 1995, 1997, 1998
2 * Jamie Zawinski <jwz@jwz.org>
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.
12 * And remember: X Windows is to graphics hacking as roman numerals are to
13 * the square root of pi.
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.
20 - create a procedure `screenhack(dpy, window)'
22 - create a variable `char *progclass' which names this program's
23 resource class.
25 - create a variable `char defaults []' for the default resources, and
26 null-terminate it.
28 - create a variable `XrmOptionDescRec options[]' for the command-line,
29 and null-terminate it.
31 And that's it...
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>
43 #ifdef __sgi
44 # include <X11/SGIScheme.h> /* for SgiUseSchemes() */
45 #endif /* __sgi */
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"
60 #include "debug.h"
61 #include "config.h"
63 #ifndef isupper
64 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
65 #endif
66 #ifndef _tolower
67 # define _tolower(c) ((c) - 'A' + 'a')
68 #endif
70 #define KEYBOARD_GENERIC \
71 "Keyboard Rockbox\n" \
72 "-------- ------------\n" \
73 "4, Left LEFT\n" \
74 "6, Right RIGHT\n"
76 #if CONFIG_KEYPAD == PLAYER_PAD
77 #define KEYBOARD_SPECIFIC \
78 "8, Up PLAY\n" \
79 "2, Down STOP\n" \
80 "+, Q ON\n" \
81 "., INS MENU\n"
83 #elif CONFIG_KEYPAD == RECORDER_PAD
84 #define KEYBOARD_SPECIFIC \
85 "8, Up UP\n" \
86 "2, Down DOWN\n" \
87 "5, Space PLAY\n" \
88 "+, Q ON\n" \
89 "Enter, A OFF\n" \
90 "/, (1) F1\n" \
91 "*, (2) F2\n" \
92 "-, (3) F3\n"
94 #elif CONFIG_KEYPAD == ONDIO_PAD
95 #define KEYBOARD_SPECIFIC \
96 "8, Up UP\n" \
97 "2, Down DOWN\n" \
98 "., INS MENU\n" \
99 "Enter, A OFF\n"
101 #elif CONFIG_KEYPAD == IRIVER_H100_PAD
102 #define KEYBOARD_SPECIFIC \
103 "8, Up UP\n" \
104 "2, Down DOWN\n" \
105 "5, Space SELECT\n" \
106 "+, Q ON\n" \
107 "Enter, A OFF\n" \
108 "., INS MODE\n" \
109 "/, (1) RECORD\n"
111 #elif CONFIG_KEYPAD == GMINI100_PAD
112 #define KEYBOARD_SPECIFIC \
113 "8, Up UP\n" \
114 "2, Down DOWN\n" \
115 "5, Space PLAY\n" \
116 "+, Q ON\n" \
117 "Enter, A OFF\n" \
118 "., INS MENU\n"
120 #endif
123 char having_new_lcd=True;
125 char *progname;
126 XrmDatabase db;
127 XtAppContext app;
128 Display* dpy;
129 Window window;
130 Bool mono_p;
132 static XrmOptionDescRec default_options [] = {
133 { "-root", ".root", XrmoptionNoArg, "True" },
134 { "-window", ".root", XrmoptionNoArg, "False" },
135 { "-mono", ".mono", XrmoptionNoArg, "True" },
136 { "-install", ".installColormap", XrmoptionNoArg, "True" },
137 { "-noinstall", ".installColormap", XrmoptionNoArg, "False" },
138 { "-visual", ".visualID", XrmoptionSepArg, 0 },
139 { "-window-id", ".windowID", XrmoptionSepArg, 0 },
140 { 0, 0, 0, 0 }
143 static char *default_defaults[] = {
144 ".root: false",
145 #define GEOMETRY_POSITION 1
146 "*geometry: "
147 #ifdef HAVE_LCD_BITMAP
148 "120x68"
149 #else
150 "280x132" /* A bit larger that necessary */
151 #endif
152 , /* this should be .geometry, but nooooo... */
153 "*mono: false",
154 "*installColormap: false",
155 "*visualID: default",
156 "*windowID: ",
160 extern int display_zoom;
161 extern long current_tick;
163 static XrmOptionDescRec *merged_options;
164 static int merged_options_size;
165 static char **merged_defaults;
167 static void merge_options (void)
169 int def_opts_size, opts_size;
170 int def_defaults_size, defaults_size;
172 for (def_opts_size = 0; default_options[def_opts_size].option;
173 def_opts_size++)
175 for (opts_size = 0; options[opts_size].option; opts_size++)
178 merged_options_size = def_opts_size + opts_size;
179 merged_options = (XrmOptionDescRec *)
180 malloc ((merged_options_size + 1) * sizeof(*default_options));
181 memcpy (merged_options, default_options,
182 (def_opts_size * sizeof(*default_options)));
183 memcpy (merged_options + def_opts_size, options,
184 ((opts_size + 1) * sizeof(*default_options)));
186 for (def_defaults_size = 0; default_defaults[def_defaults_size];
187 def_defaults_size++)
189 for (defaults_size = 0; defaults[defaults_size]; defaults_size++)
192 merged_defaults = (char **)
193 malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));
195 memcpy (merged_defaults, default_defaults,
196 def_defaults_size * sizeof(*defaults));
197 memcpy (merged_defaults + def_defaults_size, defaults,
198 (defaults_size + 1) * sizeof(*defaults));
200 /* This totally sucks. Xt should behave like this by default.
201 If the string in `defaults' looks like ".foo", change that
202 to "Progclass.foo".
205 char **s;
206 for (s = merged_defaults; *s; s++)
207 if (**s == '.')
209 const char *oldr = *s;
210 char *newr = (char *) malloc(strlen(oldr)
211 + strlen(progclass) + 3);
212 strcpy (newr, progclass);
213 strcat (newr, oldr);
214 *s = newr;
220 /* Make the X errors print out the name of this program, so we have some
221 clue which one has a bug when they die under the screensaver.
224 static int screenhack_ehandler (Display *dpy, XErrorEvent *error)
226 fprintf (stderr, "\nX error in %s:\n", progname);
227 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
228 exit (-1);
229 else
230 fprintf (stderr, " (nonfatal.)\n");
231 return 0;
234 static Bool MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
236 (void)dpy;
237 return (event->xany.type == MapNotify &&
238 event->xvisibility.window == (Window) window);
241 static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW;
244 static void kb_disable_auto_repeat(bool on)
246 XKeyboardControl kb;
248 kb.auto_repeat_mode = on ? AutoRepeatModeOff : AutoRepeatModeDefault;
249 XChangeKeyboardControl(dpy, KBAutoRepeatMode, &kb);
252 static void kb_restore_auto_repeat(void) /* registered as an exit handler */
254 kb_disable_auto_repeat(false);
255 XSync(dpy, false); /* force the X server to process that */
258 /* Dead-trivial event handling.
259 Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
261 int screenhack_handle_event(XEvent *event, bool *release)
263 int key=0;
265 *release = FALSE;
267 switch (event->xany.type) {
268 case KeyPress:
270 KeySym keysym;
271 unsigned char c = 0;
272 XLookupString (&event->xkey, &c, 1, &keysym, 0);
273 key = keysym;
274 #if 0
275 DEBUGF("Got keypress: %c (%02x) %x, tick %ld\n", c, c,
276 event->xkey.keycode, current_tick);
277 #endif
279 break;
280 case KeyRelease:
282 KeySym keysym;
283 unsigned char c = 0;
284 XLookupString (&event->xkey, &c, 1, &keysym, 0);
285 key = keysym;
286 #if 0
287 DEBUGF("Got keyrelease: %c (%02x) %x, tick %ld\n", c, c,
288 event->xkey.keycode, current_tick);
289 #endif
290 *release = TRUE;
292 break;
293 case Expose:
294 screen_redraw();
295 break;
296 case FocusIn:
297 kb_disable_auto_repeat(true);
298 break;
299 case FocusOut:
300 kb_disable_auto_repeat(false);
301 break;
302 case ClientMessage:
303 if (event->xclient.message_type != XA_WM_PROTOCOLS) {
304 char *s = XGetAtomName(dpy, event->xclient.message_type);
305 if (!s)
306 s = "(null)";
307 fprintf (stderr, "%s: unknown ClientMessage %s received!\n",
308 progname, s);
310 else if (event->xclient.data.l[0] != (int)XA_WM_DELETE_WINDOW) {
311 char *s1 = XGetAtomName(dpy, event->xclient.message_type);
312 char *s2 = XGetAtomName(dpy, event->xclient.data.l[0]);
313 if (!s1)
314 s1 = "(null)";
315 if (!s2)
316 s2 = "(null)";
317 fprintf (stderr, "%s: unknown ClientMessage %s[%s] received!\n",
318 progname, s1, s2);
320 else {
321 exit (0);
323 break;
324 default:
325 break;
327 return key;
331 int screenhack_handle_events(bool *release)
333 int key=0;
334 XtAppLock(app);
335 if(XPending(dpy))
337 XEvent event;
338 XNextEvent(dpy, &event);
339 key=screenhack_handle_event(&event, release);
341 XtAppUnlock(app);
342 return key;
346 static Visual *pick_visual (Screen *screen)
348 #ifdef USE_GL
349 /* If we're linking against GL (that is, this is the version of
350 screenhack.o that the GL hacks will use, which is different from the
351 one that the non-GL hacks will use) then try to pick the "best" visual
352 by interrogating the GL library instead of by asking Xlib. GL knows
353 better.
355 Visual *v = 0;
356 char *string = get_string_resource ("visualID", "VisualID");
357 char *s;
359 if (string)
360 for (s = string; *s; s++)
361 if (isupper (*s)) *s = _tolower (*s);
363 if (!string || !*string ||
364 !strcmp (string, "gl") ||
365 !strcmp (string, "best") ||
366 !strcmp (string, "color") ||
367 !strcmp (string, "default"))
368 v = get_gl_visual (screen); /* from ../utils/visual-gl.c */
370 if (string)
371 free (string);
372 if (v)
373 return v;
374 #endif /* USE_GL */
376 return get_visual_resource (screen, "visualID", "VisualID", False);
379 int main (int argc, char **argv)
381 Widget toplevel;
382 Screen *screen;
383 Visual *visual;
384 Colormap cmap;
385 XEvent event;
386 char version[255];
388 sprintf(version,"rockboxui %s",ROCKBOXUI_VERSION);
389 #ifdef HAVE_LCD_BITMAP
390 display_zoom=2;
392 char *env=getenv("RECORDER_ZOOM");
393 if (env) {
394 display_zoom=atoi(env);
397 #else
398 display_zoom=1;
400 char *env=getenv("PLAYER_ZOOM");
401 if (env) {
402 display_zoom=atoi(env);
405 #endif
407 if (argc > 1)
409 int x;
410 for (x=1; x<argc; x++) {
411 if (!strcmp("--old_lcd", argv[x])) {
412 having_new_lcd=FALSE;
413 printf("Using old LCD layout.\n");
414 } else if (!strcmp("--recorder_zoom", argv[x])) {
415 x++;
416 #ifdef HAVE_LCD_BITMAP
417 display_zoom=atoi(argv[x]);
418 printf("Window zoom is %d\n", display_zoom);
419 #endif
420 } else if (!strcmp("--player_zoom", argv[x])) {
421 x++;
422 #ifndef HAVE_LCD_BITMAP
423 display_zoom=atoi(argv[x]);
424 printf("Window zoom is %d\n", display_zoom);
425 #endif
426 } else {
427 printf("rockboxui\n");
428 printf("Arguments:\n");
429 printf(" --old_lcd \t [Player] simulate old playermodel (ROM version<4.51)\n");
430 printf(" --player_zoom \t [Player] window zoom\n");
431 printf(" --recorder_zoom \t [Recorder] window zoom\n");
432 printf(KEYBOARD_GENERIC KEYBOARD_SPECIFIC);
433 exit(0);
438 static char geometry[40];
439 #ifdef HAVE_LCD_BITMAP
440 unsigned int height = LCD_HEIGHT;
441 #ifdef LCD_REMOTE_HEIGHT
442 height += LCD_REMOTE_HEIGHT;
443 #endif
444 printf("height: %d\n", height);
445 snprintf(geometry, 40, "*geometry: %dx%d",
446 LCD_WIDTH*display_zoom+14, height*display_zoom+8);
447 #else
448 snprintf(geometry, 40, "*geometry: %dx%d", 280*display_zoom,
449 132*display_zoom);
450 #endif
451 default_defaults[GEOMETRY_POSITION]=geometry;
453 printf(KEYBOARD_GENERIC KEYBOARD_SPECIFIC);
455 merge_options ();
457 #ifdef __sgi
458 /* We have to do this on SGI to prevent the background color from being
459 overridden by the current desktop color scheme (we'd like our
460 backgrounds to be black, thanks.) This should be the same as setting
461 the "*useSchemes: none" resource, but it's not -- if that resource is
462 present in the `default_defaults' above, it doesn't work, though it
463 does work when passed as an -xrm arg on the command line. So screw it,
464 turn them off from C instead.
466 SgiUseSchemes ("none");
467 #endif /* __sgi */
469 XtToolkitThreadInitialize();
471 toplevel = XtAppInitialize (&app, progclass, merged_options,
472 merged_options_size, &argc, argv,
473 merged_defaults, 0, 0);
474 dpy = XtDisplay (toplevel);
475 screen = XtScreen (toplevel);
476 db = XtDatabase (dpy);
478 XtGetApplicationNameAndClass (dpy, &progname, &progclass);
480 /* half-assed way of avoiding buffer-overrun attacks. */
481 if (strlen (progname) >= 100) progname[100] = 0;
483 XSetErrorHandler (screenhack_ehandler);
485 XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
486 XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
489 if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
490 mono_p = True;
493 Boolean def_visual_p;
494 visual = pick_visual (screen);
496 if (toplevel->core.width <= 0)
497 toplevel->core.width = 600;
498 if (toplevel->core.height <= 0)
499 toplevel->core.height = 480;
501 def_visual_p = (visual == DefaultVisualOfScreen (screen));
503 if (!def_visual_p)
505 unsigned int bg, bd;
506 Widget new;
508 cmap = XCreateColormap (dpy, RootWindowOfScreen(screen),
509 visual, AllocNone);
510 bg = get_pixel_resource ("background", "Background", dpy, cmap);
511 bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
513 new = XtVaAppCreateShell (progname, progclass,
514 topLevelShellWidgetClass, dpy,
515 XtNmappedWhenManaged, False,
516 XtNvisual, visual,
517 XtNdepth, visual_depth (screen, visual),
518 XtNwidth, toplevel->core.width,
519 XtNheight, toplevel->core.height,
520 XtNcolormap, cmap,
521 XtNbackground, (Pixel) bg,
522 XtNborderColor, (Pixel) bd,
523 XtNinput, True, /* for WM_HINTS */
525 XtDestroyWidget (toplevel);
526 toplevel = new;
527 XtRealizeWidget (toplevel);
528 window = XtWindow (toplevel);
530 else
532 XtVaSetValues (toplevel,
533 XtNmappedWhenManaged, False,
534 XtNinput, True, /* for WM_HINTS */
536 XtRealizeWidget (toplevel);
537 window = XtWindow (toplevel);
539 if (get_boolean_resource ("installColormap", "InstallColormap"))
541 cmap = XCreateColormap (dpy, window,
542 DefaultVisualOfScreen (XtScreen
543 (toplevel)),
544 AllocNone);
545 XSetWindowColormap (dpy, window, cmap);
547 else
549 cmap = DefaultColormap (dpy, DefaultScreen (dpy));
553 XtPopup (toplevel, XtGrabNone);
555 XtVaSetValues(toplevel, XtNtitle, version, 0);
557 /* For screenhack_handle_events(): select KeyPress, and
558 announce that we accept WM_DELETE_WINDOW. */
560 XWindowAttributes xgwa;
561 XGetWindowAttributes (dpy, window, &xgwa);
562 XSelectInput (dpy, window,
563 xgwa.your_event_mask | KeyPressMask | KeyRelease |
564 ButtonPressMask | ExposureMask | FocusChangeMask );
565 XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
566 PropModeReplace,
567 (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
571 XSetWindowBackground (dpy, window,
572 get_pixel_resource ("background", "Background",
573 dpy, cmap));
574 XClearWindow (dpy, window);
576 /* wait for it to be mapped */
577 XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
579 XSync (dpy, False);
581 atexit(kb_restore_auto_repeat);
582 kb_disable_auto_repeat(true);
583 screenhack(); /* doesn't return */
584 return 0;