1 /* xscreensaver, Copyright (c) 1992-2010 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
11 * And remember: X Windows is to graphics hacking as roman numerals are to
12 * the square root of pi.
15 /* This file contains simple code to open a window or draw on the root.
16 The idea being that, when writing a graphics hack, you can just link
17 with this .o to get all of the uninteresting junk out of the way.
19 Create a few static global procedures and variables:
21 static void *YOURNAME_init (Display *, Window);
23 Return an opaque structure representing your drawing state.
25 static unsigned long YOURNAME_draw (Display *, Window, void *closure);
28 The `closure' arg is your drawing state, that you created in `init'.
29 Return the number of microseconds to wait until the next frame.
31 This should return in some small fraction of a second.
32 Do not call `usleep' or loop excessively. For long loops, use a
35 static void YOURNAME_reshape (Display *, Window, void *closure,
36 unsigned int width, unsigned int height);
38 Called when the size of the window changes with the new size.
40 static Bool YOURNAME_event (Display *, Window, void *closure,
43 Called when a keyboard or mouse event arrives.
44 Return True if you handle it in some way, False otherwise.
46 static void YOURNAME_free (Display *, Window, void *closure);
48 Called when you are done: free everything you've allocated,
49 including your private `state' structure.
51 NOTE: this is called in windowed-mode when the user typed
52 'q' or clicks on the window's close box; but when
53 xscreensaver terminates this screenhack, it does so by
54 killing the process with SIGSTOP. So this callback is
57 static char YOURNAME_defaults [] = { "...", "...", ... , 0 };
59 This variable is an array of strings, your default resources.
60 Null-terminate the list.
62 static XrmOptionDescRec YOURNAME_options[] = { { ... }, ... { 0,0,0,0 } }
64 This variable describes your command-line options.
65 Null-terminate the list.
67 Finally , invoke the XSCREENSAVER_MODULE() macro to tie it all together.
71 - Make sure that all functions in your module are static (check this
72 by running "nm -g" on the .o file).
74 - Do not use global variables: all such info must be stored in the
75 private `state' structure.
77 - Do not use static function-local variables, either. Put it in `state'.
79 Assume that there are N independent runs of this code going in the
80 same address space at the same time: they must not affect each other.
82 - Don't forget to write an XML file to describe the user interface
83 of your screen saver module. See .../hacks/config/README for details.
89 #include <X11/Intrinsic.h>
90 #include <X11/IntrinsicP.h>
91 #include <X11/CoreP.h>
92 #include <X11/Shell.h>
93 #include <X11/StringDefs.h>
94 #include <X11/keysym.h>
95 #include <dbus/dbus.h>
98 # include <X11/SGIScheme.h> /* for SgiUseSchemes() */
103 # include <X11/Xmu/Error.h>
105 # include <Xmu/Error.h>
111 #include "screenhackI.h"
116 #ifndef _XSCREENSAVER_VROOT_H_
117 # error Error! You have an old version of vroot.h! Check -I args.
118 #endif /* _XSCREENSAVER_VROOT_H_ */
121 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
124 # define _tolower(c) ((c) - 'A' + 'a')
128 /* This is defined by the SCREENHACK_MAIN() macro via screenhack.h.
130 extern struct xscreensaver_function_table *xscreensaver_function_table;
133 const char *progname; /* used by hacks in error messages */
134 const char *progclass; /* used by ../utils/resources.c */
135 Bool mono_p; /* used by hacks */
138 static XrmOptionDescRec default_options [] = {
139 { "-root", ".root", XrmoptionNoArg, "True" },
140 { "-window", ".root", XrmoptionNoArg, "False" },
141 { "-mono", ".mono", XrmoptionNoArg, "True" },
142 { "-install", ".installColormap", XrmoptionNoArg, "True" },
143 { "-noinstall",".installColormap", XrmoptionNoArg, "False" },
144 { "-visual", ".visualID", XrmoptionSepArg, 0 },
145 { "-window-id", ".windowID", XrmoptionSepArg, 0 },
146 { "-fps", ".doFPS", XrmoptionNoArg, "True" },
147 { "-no-fps", ".doFPS", XrmoptionNoArg, "False" },
148 { "-view", ".view", XrmoptionSepArg, 1 },
151 { "-pair", ".pair", XrmoptionNoArg, "True" },
152 # endif /* DEBUG_PAIR */
156 static char *default_defaults[] = {
158 "*geometry: 600x480", /* this should be .geometry, but nooooo... */
160 "*installColormap: false",
162 "*visualID: default",
164 "*desktopGrabber: xscreensaver-getimage %s",
168 static XrmOptionDescRec *merged_options;
169 static int merged_options_size;
170 static char **merged_defaults;
176 struct xscreensaver_function_table *ft = xscreensaver_function_table;
178 const XrmOptionDescRec *options = ft->options;
179 const char * const *defaults = ft->defaults;
180 const char *progclass = ft->progclass;
182 int def_opts_size, opts_size;
183 int def_defaults_size, defaults_size;
185 for (def_opts_size = 0; default_options[def_opts_size].option;
188 for (opts_size = 0; options[opts_size].option; opts_size++)
191 merged_options_size = def_opts_size + opts_size;
192 merged_options = (XrmOptionDescRec *)
193 malloc ((merged_options_size + 1) * sizeof(*default_options));
194 memcpy (merged_options, default_options,
195 (def_opts_size * sizeof(*default_options)));
196 memcpy (merged_options + def_opts_size, options,
197 ((opts_size + 1) * sizeof(*default_options)));
199 for (def_defaults_size = 0; default_defaults[def_defaults_size];
202 for (defaults_size = 0; defaults[defaults_size]; defaults_size++)
204 merged_defaults = (char **)
205 malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));;
206 memcpy (merged_defaults, default_defaults,
207 def_defaults_size * sizeof(*defaults));
208 memcpy (merged_defaults + def_defaults_size, defaults,
209 (defaults_size + 1) * sizeof(*defaults));
211 /* This totally sucks. Xt should behave like this by default.
212 If the string in `defaults' looks like ".foo", change that
217 for (s = merged_defaults; *s; s++)
220 const char *oldr = *s;
221 char *newr = (char *) malloc(strlen(oldr) + strlen(progclass) + 3);
222 strcpy (newr, progclass);
232 /* Make the X errors print out the name of this program, so we have some
233 clue which one has a bug when they die under the screensaver.
237 screenhack_ehandler (Display *dpy, XErrorEvent *error)
239 fprintf (stderr, "\nX error in %s:\n", progname);
240 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
243 fprintf (stderr, " (nonfatal.)\n");
248 MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
250 return (event->xany.type == MapNotify &&
251 event->xvisibility.window == (Window) window);
255 static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW;
257 /* Dead-trivial event handling: exits if "q" or "ESC" are typed.
258 Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
259 Returns False if the screen saver should now terminate.
262 screenhack_handle_event_1 (Display *dpy, XEvent *event)
264 switch (event->xany.type)
270 XLookupString (&event->xkey, &c, 1, &keysym, 0);
275 return False; /* exit */
276 else if (! (keysym >= XK_Shift_L && keysym <= XK_Hyper_R))
277 XBell (dpy, 0); /* beep for non-chord keys */
285 if (event->xclient.message_type != XA_WM_PROTOCOLS)
287 char *s = XGetAtomName(dpy, event->xclient.message_type);
288 if (!s) s = "(null)";
289 fprintf (stderr, "%s: unknown ClientMessage %s received!\n",
292 else if (event->xclient.data.l[0] != XA_WM_DELETE_WINDOW)
294 char *s1 = XGetAtomName(dpy, event->xclient.message_type);
295 char *s2 = XGetAtomName(dpy, event->xclient.data.l[0]);
296 if (!s1) s1 = "(null)";
297 if (!s2) s2 = "(null)";
298 fprintf (stderr, "%s: unknown ClientMessage %s[%s] received!\n",
303 return False; /* exit */
313 pick_visual (Screen *screen)
315 struct xscreensaver_function_table *ft = xscreensaver_function_table;
317 if (ft->pick_visual_hook)
319 Visual *v = ft->pick_visual_hook (screen);
323 return get_visual_resource (screen, "visualID", "VisualID", False);
327 /* Notice when the user has requested a different visual or colormap
328 on a pre-existing window (e.g., "-root -visual truecolor" or
329 "-window-id 0x2c00001 -install") and complain, since when drawing
330 on an existing window, we have no choice about these things.
333 visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
336 struct xscreensaver_function_table *ft = xscreensaver_function_table;
338 char *visual_string = get_string_resource (DisplayOfScreen (screen),
339 "visualID", "VisualID");
340 Visual *desired_visual = pick_visual (screen);
344 if (window == RootWindowOfScreen (screen))
345 strcpy (win, "root window");
347 sprintf (win, "window 0x%lx", (unsigned long) window);
350 sprintf (why, "-window-id 0x%lx", (unsigned long) window);
352 strcpy (why, "-root");
354 if (visual_string && *visual_string)
357 for (s = visual_string; *s; s++)
358 if (isupper (*s)) *s = _tolower (*s);
360 if (!strcmp (visual_string, "default") ||
361 !strcmp (visual_string, "default") ||
362 !strcmp (visual_string, "best"))
363 /* don't warn about these, just silently DWIM. */
365 else if (visual != desired_visual)
367 fprintf (stderr, "%s: ignoring `-visual %s' because of `%s'.\n",
368 progname, visual_string, why);
369 fprintf (stderr, "%s: using %s's visual 0x%lx.\n",
370 progname, win, XVisualIDFromVisual (visual));
372 free (visual_string);
375 if (visual == DefaultVisualOfScreen (screen) &&
376 has_writable_cells (screen, visual) &&
377 get_boolean_resource (DisplayOfScreen (screen),
378 "installColormap", "InstallColormap"))
380 fprintf (stderr, "%s: ignoring `-install' because of `%s'.\n",
382 fprintf (stderr, "%s: using %s's colormap 0x%lx.\n",
383 progname, win, (unsigned long) cmap);
386 if (ft->validate_visual_hook)
388 if (! ft->validate_visual_hook (screen, win, visual))
397 /* Bad Things Happen if stdin, stdout, and stderr have been closed
398 (as by the `sh incantation "attraction >&- 2>&-"). When you do
399 that, the X connection gets allocated to one of these fds, and
400 then some random library writes to stderr, and random bits get
401 stuffed down the X pipe, causing "Xlib: sequence lost" errors.
402 So, we cause the first three file descriptors to be open to
403 /dev/null if they aren't open to something else already. This
404 must be done before any other files are opened (or the closing
405 of that other file will again free up one of the "magic" first
408 We do this by opening /dev/null three times, and then closing
409 those fds, *unless* any of them got allocated as #0, #1, or #2,
410 in which case we leave them open. Gag.
412 Really, this crap is technically required of *every* X program,
413 if you want it to be robust in the face of "2>&-".
415 int fd0 = open ("/dev/null", O_RDWR);
416 int fd1 = open ("/dev/null", O_RDWR);
417 int fd2 = open ("/dev/null", O_RDWR);
418 if (fd0 > 2) close (fd0);
419 if (fd1 > 2) close (fd1);
420 if (fd2 > 2) close (fd2);
425 screenhack_table_handle_events (Display *dpy,
426 const struct xscreensaver_function_table *ft,
427 Window window, void *closure
429 , Window window2, void *closure2
433 XtAppContext app = XtDisplayToApplicationContext (dpy);
435 if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput))
436 XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput);
438 while (XPending (dpy))
441 XNextEvent (dpy, &event);
443 if (event.xany.type == ConfigureNotify)
445 if (event.xany.window == window)
446 ft->reshape_cb (dpy, window, closure,
447 event.xconfigure.width, event.xconfigure.height);
449 if (event.xany.window == window2)
450 ft->reshape_cb (dpy, window2, closure2,
451 event.xconfigure.width, event.xconfigure.height);
454 else if (event.xany.type == ClientMessage ||
455 (! (event.xany.window == window
456 ? ft->event_cb (dpy, window, closure, &event)
458 : event.xany.window == window2
459 ? ft->event_cb (dpy, window2, closure2, &event)
462 if (! screenhack_handle_event_1 (dpy, &event))
465 if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput))
466 XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput);
473 usleep_and_process_events (Display *dpy,
474 const struct xscreensaver_function_table *ft,
475 Window window, fps_state *fpst, void *closure,
478 , Window window2, fps_state *fpst2, void *closure2,
484 unsigned long quantum = 100000; /* 1/10th second */
493 if (fpst) fps_slept (fpst, quantum);
495 if (fpst2) fps_slept (fpst2, quantum);
499 if (! screenhack_table_handle_events (dpy, ft, window, closure
512 screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
514 fps_compute (fpst, 0);
520 run_screenhack_table (Display *dpy,
525 const struct xscreensaver_function_table *ft,
528 #define LIVEWP_SIGNAL_INTERFACE "org.maemo.livewp"
529 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW1 "pause_livebg_on_view1"
530 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW2 "pause_livebg_on_view2"
531 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW3 "pause_livebg_on_view3"
532 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW4 "pause_livebg_on_view4"
533 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW5 "pause_livebg_on_view5"
534 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW6 "pause_livebg_on_view6"
535 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW7 "pause_livebg_on_view7"
536 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW8 "pause_livebg_on_view8"
537 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW9 "pause_livebg_on_view9"
538 #define LIVEWP_PAUSE_LIVEBG_ON_VIEW "pause_livebg_on_view"
539 #define LIVEWP_PLAY_LIVEBG_ON_VIEW1 "play_livebg_on_view1"
540 #define LIVEWP_PLAY_LIVEBG_ON_VIEW2 "play_livebg_on_view2"
541 #define LIVEWP_PLAY_LIVEBG_ON_VIEW3 "play_livebg_on_view3"
542 #define LIVEWP_PLAY_LIVEBG_ON_VIEW4 "play_livebg_on_view4"
543 #define LIVEWP_PLAY_LIVEBG_ON_VIEW5 "play_livebg_on_view5"
544 #define LIVEWP_PLAY_LIVEBG_ON_VIEW6 "play_livebg_on_view6"
545 #define LIVEWP_PLAY_LIVEBG_ON_VIEW7 "play_livebg_on_view7"
546 #define LIVEWP_PLAY_LIVEBG_ON_VIEW8 "play_livebg_on_view8"
547 #define LIVEWP_PLAY_LIVEBG_ON_VIEW9 "play_livebg_on_view9"
548 #define LIVEWP_PLAY_LIVEBG_ON_VIEW "play_livebg_on_view"
550 DBusConnection* conn;
552 DBusMessageIter args;
556 int start_frame = 200;
558 /* Kludge: even though the init_cb functions are declared to take 2 args,
559 actually call them with 3, for the benefit of xlockmore_init() and
562 void *(*init_cb) (Display *, Window, void *) =
563 (void *(*) (Display *, Window, void *)) ft->init_cb;
565 void (*fps_cb) (Display *, Window, fps_state *, void *) = ft->fps_cb;
567 void *closure = init_cb (dpy, window, ft->setup_arg);
568 fps_state *fpst = fps_init (dpy, window);
572 fps_state *fpst2 = 0;
573 if (window2) closure2 = init_cb (dpy, window2, ft->setup_arg);
574 if (window2) fpst2 = fps_init (dpy, window2);
577 if (! closure) /* if it returns nothing, it can't possibly be re-entrant. */
580 if (! fps_cb) fps_cb = screenhack_do_fps;
582 /* initialise the error */
583 dbus_error_init(&err);
584 conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
585 if (dbus_error_is_set(&err)) {
586 fprintf(stderr, "Connection Error (%s)\n", err.message);
587 dbus_error_free(&err);
590 fprintf(stderr, "Connection Null\n");
594 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view1'", NULL);
595 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view1'", NULL);
598 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view2'", NULL);
599 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view2'", NULL);
602 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view3'", NULL);
603 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view3'", NULL);
606 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view4'", NULL);
607 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view4'", NULL);
610 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view5'", NULL);
611 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view5'", NULL);
614 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view6'", NULL);
615 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view6'", NULL);
618 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view7'", NULL);
619 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view7'", NULL);
622 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view8'", NULL);
623 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view8'", NULL);
626 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='pause_livebg_on_view9'", NULL);
627 dbus_bus_add_match (conn, "type='signal', interface='org.maemo.livewp', member='play_livebg_on_view9'", NULL);
630 dbus_connection_flush(conn);
635 unsigned long delay = ft->draw_cb (dpy, window, closure);
637 unsigned long delay2 = 0;
638 if (window2) delay2 = ft->draw_cb (dpy, window2, closure2);
642 if (fpst) fps_cb (dpy, window, fpst, closure);
644 if (fpst2) fps_cb (dpy, window, fpst2, closure);
646 if (! usleep_and_process_events (dpy, ft,
647 window, fpst, closure, delay
649 , window2, fpst2, closure2, delay2
655 if (start_frame > 0) {
661 /* non blocking read of the next available message */
662 dbus_connection_read_write(conn, 0);
664 /* blocking read of the next available message */
665 dbus_connection_read_write(conn, 20000);
667 msg = dbus_connection_pop_message(conn);
672 /* check this is a method call for the right interface & method */
673 if ((view == 1 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW1))||
674 (view == 2 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW2))||
675 (view == 3 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW3))||
676 (view == 4 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW4))||
677 (view == 5 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW5))||
678 (view == 6 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW6))||
679 (view == 7 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW7))||
680 (view == 8 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW8))||
681 (view == 9 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW9))){
682 /* fprintf(stderr, "Pause scene visible %i\n", view); */
684 dbus_message_unref (msg);
687 if ((view == 1 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW1))||
688 (view == 2 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW2))||
689 (view == 3 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW3))||
690 (view == 4 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW4))||
691 (view == 5 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW5))||
692 (view == 6 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW6))||
693 (view == 7 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW7))||
694 (view == 8 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW8))||
695 (view == 9 && dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW9))){
696 /* fprintf(stderr, "Play scene visible %i\n", view); */
698 dbus_message_unref (msg);
702 /* dbus_connection_steal_borrowed_message(conn, msg); */
703 /* fprintf (stderr, "APPLICATION PATH11111111111111111111 %s %s %s\n", dbus_message_get_path(msg), dbus_message_get_interface (msg), dbus_message_get_member (msg));*/
704 /*dbus_connection_return_message(conn, msg);*/
705 if (dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW) ||
706 dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW)){
707 if (!dbus_message_iter_init(msg, &args))
708 fprintf(stderr, "dbus message has no param\n");
709 else if (DBUS_TYPE_INT32 != dbus_message_iter_get_arg_type(&args))
710 fprintf(stderr, "dbus message param is not int \n");
712 dbus_message_iter_get_basic(&args, ¶m);
713 fprintf(stderr, "dbus param = %i\n", param);
716 if (dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PAUSE_LIVEBG_ON_VIEW)){
717 fprintf(stderr, "dbus Pause scene visible %i\n", param);
720 if (dbus_message_is_signal(msg, LIVEWP_SIGNAL_INTERFACE, LIVEWP_PLAY_LIVEBG_ON_VIEW)){
721 fprintf(stderr, "dbus Play scene visible %i\n", param);
724 /*msg = dbus_connection_pop_message(conn);*/
725 fprintf(stderr, "dbus steal message serial = %i\n", dbus_message_get_serial(msg));
726 /*dbus_connection_steal_borrowed_message(conn, msg);*/
728 fprintf(stderr, "dbus return message\n");
729 /*dbus_connection_return_message(conn, msg);*/
733 /* dbus_message_unref (msg); */
736 ft->free_cb (dpy, window, closure);
737 if (fpst) fps_free (fpst);
740 if (window2) ft->free_cb (dpy, window2, closure2);
741 if (window2) fps_free (fpst2);
743 /* close the connection */
744 dbus_connection_close(conn);
749 make_shell (Screen *screen, Widget toplevel, int width, int height)
751 Display *dpy = DisplayOfScreen (screen);
752 Visual *visual = pick_visual (screen);
753 Boolean def_visual_p = (toplevel &&
754 visual == DefaultVisualOfScreen (screen));
756 if (width <= 0) width = 600;
757 if (height <= 0) height = 480;
762 XtVaSetValues (toplevel,
763 XtNmappedWhenManaged, False,
766 XtNinput, True, /* for WM_HINTS */
768 XtRealizeWidget (toplevel);
769 window = XtWindow (toplevel);
771 if (get_boolean_resource (dpy, "installColormap", "InstallColormap"))
774 XCreateColormap (dpy, window, DefaultVisualOfScreen (screen),
776 XSetWindowColormap (dpy, window, cmap);
783 Colormap cmap = XCreateColormap (dpy, VirtualRootWindowOfScreen(screen),
785 bg = get_pixel_resource (dpy, cmap, "background", "Background");
786 bd = get_pixel_resource (dpy, cmap, "borderColor", "Foreground");
788 new = XtVaAppCreateShell (progname, progclass,
789 topLevelShellWidgetClass, dpy,
790 XtNmappedWhenManaged, False,
792 XtNdepth, visual_depth (screen, visual),
796 XtNbackground, (Pixel) bg,
797 XtNborderColor, (Pixel) bd,
798 XtNinput, True, /* for WM_HINTS */
801 if (!toplevel) /* kludge for the second window in -pair mode... */
802 XtVaSetValues (new, XtNx, 0, XtNy, 550, NULL);
804 XtRealizeWidget (new);
812 init_window (Display *dpy, Widget toplevel, const char *title)
815 XWindowAttributes xgwa;
816 XtPopup (toplevel, XtGrabNone);
817 XtVaSetValues (toplevel, XtNtitle, title, NULL);
819 /* Select KeyPress, and announce that we accept WM_DELETE_WINDOW.
821 window = XtWindow (toplevel);
822 XGetWindowAttributes (dpy, window, &xgwa);
823 XSelectInput (dpy, window,
824 (xgwa.your_event_mask | KeyPressMask | KeyReleaseMask |
825 ButtonPressMask | ButtonReleaseMask));
826 XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
828 (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
833 main (int argc, char **argv)
835 struct xscreensaver_function_table *ft = xscreensaver_function_table;
837 /* osso_context_t *osso; */
839 XWindowAttributes xgwa;
845 Widget toplevel2 = 0;
849 Window on_window = 0;
857 progname = argv[0]; /* reset later */
858 progclass = ft->progclass;
861 ft->setup_cb (ft, ft->setup_arg);
866 /* We have to do this on SGI to prevent the background color from being
867 overridden by the current desktop color scheme (we'd like our backgrounds
868 to be black, thanks.) This should be the same as setting the
869 "*useSchemes: none" resource, but it's not -- if that resource is
870 present in the `default_defaults' above, it doesn't work, though it
871 does work when passed as an -xrm arg on the command line. So screw it,
872 turn them off from C instead.
874 SgiUseSchemes ("none");
877 toplevel = XtAppInitialize (&app, progclass, merged_options,
878 merged_options_size, &argc, argv,
879 merged_defaults, 0, 0);
881 dpy = XtDisplay (toplevel);
883 XtGetApplicationNameAndClass (dpy,
885 (char **) &progclass);
887 /* half-assed way of avoiding buffer-overrun attacks. */
888 if (strlen (progname) >= 100) ((char *) progname)[100] = 0;
890 XSetErrorHandler (screenhack_ehandler);
892 XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
893 XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
896 char *v = (char *) strdup(strchr(screensaver_id, ' '));
897 char *s1, *s2, *s3, *s4;
898 s1 = (char *) strchr(v, ' '); s1++;
899 s2 = (char *) strchr(s1, ' ');
900 s3 = (char *) strchr(v, '('); s3++;
901 s4 = (char *) strchr(s3, ')');
904 sprintf (version, "%s: from the XScreenSaver %s distribution (%s.)",
915 Bool help_p = (!strcmp(argv[1], "-help") ||
916 !strcmp(argv[1], "--help"));
917 fprintf (stderr, "%s\n", version);
918 for (s = progclass; *s; s++) fprintf(stderr, " ");
919 fprintf (stderr, " http://www.jwz.org/xscreensaver/\n\n");
922 fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
923 fprintf (stderr, "Options include: ");
924 for (i = 0; i < merged_options_size; i++)
926 char *sw = merged_options [i].option;
927 Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
928 int size = strlen (sw) + (argp ? 6 : 0) + 2;
931 fprintf (stderr, "\n\t\t ");
935 fprintf (stderr, "%s", sw);
936 if (argp) fprintf (stderr, " <arg>");
937 if (i != merged_options_size - 1) fprintf (stderr, ", ");
940 fprintf (stderr, ".\n");
945 fprintf (stderr, "\nResources:\n\n");
946 for (i = 0; i < merged_options_size; i++)
948 const char *opt = merged_options [i].option;
949 const char *res = merged_options [i].specifier + 1;
950 const char *val = merged_options [i].value;
951 char *s = get_string_resource (dpy, (char *) res, (char *) res);
956 while (L > 0 && (s[L-1] == ' ' || s[L-1] == '\t'))
960 fprintf (stderr, " %-16s %-18s ", opt, res);
961 if (merged_options [i].argKind == XrmoptionSepArg)
963 fprintf (stderr, "[%s]", (s ? s : "?"));
967 fprintf (stderr, "%s", (val ? val : "(null)"));
968 if (val && s && !strcasecmp (val, s))
969 fprintf (stderr, " [default]");
971 fprintf (stderr, "\n");
973 fprintf (stderr, "\n");
977 exit (help_p ? 0 : 1);
982 for (s = merged_defaults; *s; s++)
986 free (merged_options);
987 free (merged_defaults);
991 dont_clear = get_boolean_resource (dpy, "dontClearRoot", "Boolean");
992 mono_p = get_boolean_resource (dpy, "mono", "Boolean");
993 if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
996 root_p = get_boolean_resource (dpy, "root", "Boolean");
999 char *s = get_string_resource (dpy, "windowID", "WindowID");
1001 on_window = get_integer_resource (dpy, "windowID", "WindowID");
1005 view = get_integer_resource (dpy, "view", "view");
1006 fprintf(stderr, "View %i\n", view);
1009 window = (Window) on_window;
1010 XtDestroyWidget (toplevel);
1011 XGetWindowAttributes (dpy, window, &xgwa);
1012 visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, True);
1014 /* Select KeyPress and resize events on the external window.
1016 xgwa.your_event_mask |= KeyPressMask | StructureNotifyMask;
1017 XSelectInput (dpy, window, xgwa.your_event_mask);
1019 /* Select ButtonPress and ButtonRelease events on the external window,
1020 if no other app has already selected them (only one app can select
1021 ButtonPress at a time: BadAccess results.)
1023 if (! (xgwa.all_event_masks & (ButtonPressMask | ButtonReleaseMask)))
1024 XSelectInput (dpy, window,
1025 (xgwa.your_event_mask |
1026 ButtonPressMask | ButtonReleaseMask));
1030 window = VirtualRootWindowOfScreen (XtScreen (toplevel));
1031 XtDestroyWidget (toplevel);
1032 XGetWindowAttributes (dpy, window, &xgwa);
1033 /* With RANDR, the root window can resize! */
1034 XSelectInput (dpy, window, xgwa.your_event_mask | StructureNotifyMask);
1035 visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, False);
1039 Widget new = make_shell (XtScreen (toplevel), toplevel,
1040 toplevel->core.width,
1041 toplevel->core.height);
1042 if (new != toplevel)
1044 XtDestroyWidget (toplevel);
1048 init_window (dpy, toplevel, version);
1049 window = XtWindow (toplevel);
1050 XGetWindowAttributes (dpy, window, &xgwa);
1053 if (get_boolean_resource (dpy, "pair", "Boolean"))
1055 toplevel2 = make_shell (xgwa.screen, 0,
1056 toplevel->core.width,
1057 toplevel->core.height);
1058 init_window (dpy, toplevel2, version);
1059 window2 = XtWindow (toplevel2);
1061 # endif /* DEBUG_PAIR */
1066 unsigned int bg = get_pixel_resource (dpy, xgwa.colormap,
1067 "background", "Background");
1068 XSetWindowBackground (dpy, window, bg);
1069 XClearWindow (dpy, window);
1073 XSetWindowBackground (dpy, window2, bg);
1074 XClearWindow (dpy, window2);
1079 if (!root_p && !on_window)
1080 /* wait for it to be mapped */
1081 XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
1085 /* This is the one and only place that the random-number generator is
1086 seeded in any screenhack. You do not need to seed the RNG again,
1087 it is done for you before your code is invoked. */
1088 # undef ya_rand_init
1091 run_screenhack_table (dpy, window,
1097 XtDestroyWidget (toplevel);
1098 XtDestroyApplicationContext (app);