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
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
25 - create a variable `char defaults []' for the default resources, and
28 - create a variable `XrmOptionDescRec options[]' for the command-line,
29 and null-terminate it.
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>
44 # include <X11/SGIScheme.h> /* for SgiUseSchemes() */
49 # include <X11/Xmu/Error.h>
51 # include <Xmu/Error.h>
56 #include "screenhack.h"
64 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
67 # define _tolower(c) ((c) - 'A' + 'a')
70 #define KEYBOARD_GENERIC \
71 "Keyboard Rockbox\n" \
72 "-------- ------------\n" \
76 #if CONFIG_KEYPAD == PLAYER_PAD
77 #define KEYBOARD_SPECIFIC \
83 #elif CONFIG_KEYPAD == RECORDER_PAD
84 #define KEYBOARD_SPECIFIC \
94 #elif CONFIG_KEYPAD == ONDIO_PAD
95 #define KEYBOARD_SPECIFIC \
101 #elif CONFIG_KEYPAD == IRIVER_H100_PAD
102 #define KEYBOARD_SPECIFIC \
105 "5, Space SELECT\n" \
111 #elif CONFIG_KEYPAD == GMINI100_PAD
112 #define KEYBOARD_SPECIFIC \
123 char having_new_lcd
=True
;
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 },
143 static char *default_defaults
[] = {
145 #define GEOMETRY_POSITION 1
147 #ifdef HAVE_LCD_BITMAP
150 "280x132" /* A bit larger that necessary */
152 , /* this should be .geometry, but nooooo... */
154 "*installColormap: false",
155 "*visualID: default",
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
;
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
];
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
206 for (s
= merged_defaults
; *s
; s
++)
209 const char *oldr
= *s
;
210 char *newr
= (char *) malloc(strlen(oldr
)
211 + strlen(progclass
) + 3);
212 strcpy (newr
, progclass
);
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
))
230 fprintf (stderr
, " (nonfatal.)\n");
234 static Bool
MapNotify_event_p (Display
*dpy
, XEvent
*event
, XPointer window
)
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
)
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
)
267 switch (event
->xany
.type
) {
272 XLookupString (&event
->xkey
, &c
, 1, &keysym
, 0);
275 DEBUGF("Got keypress: %c (%02x) %x, tick %ld\n", c
, c
,
276 event
->xkey
.keycode
, current_tick
);
284 XLookupString (&event
->xkey
, &c
, 1, &keysym
, 0);
287 DEBUGF("Got keyrelease: %c (%02x) %x, tick %ld\n", c
, c
,
288 event
->xkey
.keycode
, current_tick
);
297 kb_disable_auto_repeat(true);
300 kb_disable_auto_repeat(false);
303 if (event
->xclient
.message_type
!= XA_WM_PROTOCOLS
) {
304 char *s
= XGetAtomName(dpy
, event
->xclient
.message_type
);
307 fprintf (stderr
, "%s: unknown ClientMessage %s received!\n",
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]);
317 fprintf (stderr
, "%s: unknown ClientMessage %s[%s] received!\n",
331 int screenhack_handle_events(bool *release
)
338 XNextEvent(dpy
, &event
);
339 key
=screenhack_handle_event(&event
, release
);
346 static Visual
*pick_visual (Screen
*screen
)
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
356 char *string
= get_string_resource ("visualID", "VisualID");
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 */
376 return get_visual_resource (screen
, "visualID", "VisualID", False
);
379 int main (int argc
, char **argv
)
388 sprintf(version
,"rockboxui %s",ROCKBOXUI_VERSION
);
389 #ifdef HAVE_LCD_BITMAP
392 char *env
=getenv("RECORDER_ZOOM");
394 display_zoom
=atoi(env
);
400 char *env
=getenv("PLAYER_ZOOM");
402 display_zoom
=atoi(env
);
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
])) {
416 #ifdef HAVE_LCD_BITMAP
417 display_zoom
=atoi(argv
[x
]);
418 printf("Window zoom is %d\n", display_zoom
);
420 } else if (!strcmp("--player_zoom", argv
[x
])) {
422 #ifndef HAVE_LCD_BITMAP
423 display_zoom
=atoi(argv
[x
]);
424 printf("Window zoom is %d\n", display_zoom
);
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
);
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
;
444 printf("height: %d\n", height
);
445 snprintf(geometry
, 40, "*geometry: %dx%d",
446 LCD_WIDTH
*display_zoom
+14, height
*display_zoom
+8);
448 snprintf(geometry
, 40, "*geometry: %dx%d", 280*display_zoom
,
451 default_defaults
[GEOMETRY_POSITION
]=geometry
;
453 printf(KEYBOARD_GENERIC KEYBOARD_SPECIFIC
);
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");
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)
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
));
508 cmap
= XCreateColormap (dpy
, RootWindowOfScreen(screen
),
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
,
517 XtNdepth
, visual_depth (screen
, visual
),
518 XtNwidth
, toplevel
->core
.width
,
519 XtNheight
, toplevel
->core
.height
,
521 XtNbackground
, (Pixel
) bg
,
522 XtNborderColor
, (Pixel
) bd
,
523 XtNinput
, True
, /* for WM_HINTS */
525 XtDestroyWidget (toplevel
);
527 XtRealizeWidget (toplevel
);
528 window
= XtWindow (toplevel
);
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
545 XSetWindowColormap (dpy
, window
, cmap
);
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,
567 (unsigned char *) &XA_WM_DELETE_WINDOW
, 1);
571 XSetWindowBackground (dpy
, window
,
572 get_pixel_resource ("background", "Background",
574 XClearWindow (dpy
, window
);
576 /* wait for it to be mapped */
577 XIfEvent (dpy
, &event
, MapNotify_event_p
, (XPointer
) window
);
581 atexit(kb_restore_auto_repeat
);
582 kb_disable_auto_repeat(true);
583 screenhack(); /* doesn't return */