-/* xscreensaver, Copyright (c) 1992, 1995, 1997, 1998, 2001, 2002, 2003
- * Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2014 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
The idea being that, when writing a graphics hack, you can just link
with this .o to get all of the uninteresting junk out of the way.
- - create a procedure `screenhack(dpy, window)'
+ Create a few static global procedures and variables:
- - create a variable `char *progclass' which names this program's
- resource class.
+ static void *YOURNAME_init (Display *, Window);
- - create a variable `char defaults []' for the default resources, and
- null-terminate it.
+ Return an opaque structure representing your drawing state.
- - create a variable `XrmOptionDescRec options[]' for the command-line,
- and null-terminate it.
+ static unsigned long YOURNAME_draw (Display *, Window, void *closure);
- And that's it...
+ Draw one frame.
+ The `closure' arg is your drawing state, that you created in `init'.
+ Return the number of microseconds to wait until the next frame.
+
+ This should return in some small fraction of a second.
+ Do not call `usleep' or loop excessively. For long loops, use a
+ finite state machine.
+
+ static void YOURNAME_reshape (Display *, Window, void *closure,
+ unsigned int width, unsigned int height);
+
+ Called when the size of the window changes with the new size.
+
+ static Bool YOURNAME_event (Display *, Window, void *closure,
+ XEvent *event);
+
+ Called when a keyboard or mouse event arrives.
+ Return True if you handle it in some way, False otherwise.
+
+ static void YOURNAME_free (Display *, Window, void *closure);
+
+ Called when you are done: free everything you've allocated,
+ including your private `state' structure.
+
+ NOTE: this is called in windowed-mode when the user typed
+ 'q' or clicks on the window's close box; but when
+ xscreensaver terminates this screenhack, it does so by
+ killing the process with SIGSTOP. So this callback is
+ mostly useless.
+
+ static char YOURNAME_defaults [] = { "...", "...", ... , 0 };
+
+ This variable is an array of strings, your default resources.
+ Null-terminate the list.
+
+ static XrmOptionDescRec YOURNAME_options[] = { { ... }, ... { 0,0,0,0 } }
+
+ This variable describes your command-line options.
+ Null-terminate the list.
+
+ Finally , invoke the XSCREENSAVER_MODULE() macro to tie it all together.
+
+ Additional caveats:
+
+ - Make sure that all functions in your module are static (check this
+ by running "nm -g" on the .o file).
+
+ - Do not use global variables: all such info must be stored in the
+ private `state' structure.
+
+ - Do not use static function-local variables, either. Put it in `state'.
+
+ Assume that there are N independent runs of this code going in the
+ same address space at the same time: they must not affect each other.
+
+ - Don't forget to write an XML file to describe the user interface
+ of your screen saver module. See .../hacks/config/README for details.
*/
+#define DEBUG_PAIR
+
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
-#include <X11/Xutil.h>
#include <X11/keysym.h>
#ifdef __sgi
#else
# include "xmu.h"
#endif
-#include "screenhack.h"
+
+#include "screenhackI.h"
#include "version.h"
#include "vroot.h"
+#include "fps.h"
+
+#ifdef HAVE_RECORD_ANIM
+# include "recanim.h"
+#endif
+
+#ifndef _XSCREENSAVER_VROOT_H_
+# error Error! You have an old version of vroot.h! Check -I args.
+#endif /* _XSCREENSAVER_VROOT_H_ */
#ifndef isupper
# define isupper(c) ((c) >= 'A' && (c) <= 'Z')
#endif
-char *progname;
-XrmDatabase db;
-XtAppContext app;
-Bool mono_p;
+/* This is defined by the SCREENHACK_MAIN() macro via screenhack.h.
+ */
+extern struct xscreensaver_function_table *xscreensaver_function_table;
+
+
+const char *progname; /* used by hacks in error messages */
+const char *progclass; /* used by ../utils/resources.c */
+Bool mono_p; /* used by hacks */
+
static XrmOptionDescRec default_options [] = {
{ "-root", ".root", XrmoptionNoArg, "True" },
{ "-noinstall",".installColormap", XrmoptionNoArg, "False" },
{ "-visual", ".visualID", XrmoptionSepArg, 0 },
{ "-window-id", ".windowID", XrmoptionSepArg, 0 },
+ { "-fps", ".doFPS", XrmoptionNoArg, "True" },
+ { "-no-fps", ".doFPS", XrmoptionNoArg, "False" },
+
+# ifdef DEBUG_PAIR
+ { "-pair", ".pair", XrmoptionNoArg, "True" },
+# endif /* DEBUG_PAIR */
+
+# ifdef HAVE_RECORD_ANIM
+ { "-record-animation", ".recordAnim", XrmoptionSepArg, 0 },
+# endif /* HAVE_RECORD_ANIM */
+
{ 0, 0, 0, 0 }
};
static char *default_defaults[] = {
".root: false",
- "*geometry: 600x480", /* this should be .geometry, but nooooo... */
+ "*geometry: 1280x720", /* this should be .geometry, but noooo... */
"*mono: false",
"*installColormap: false",
+ "*doFPS: false",
+ "*multiSample: false",
"*visualID: default",
"*windowID: ",
"*desktopGrabber: xscreensaver-getimage %s",
static int merged_options_size;
static char **merged_defaults;
+
static void
merge_options (void)
{
+ struct xscreensaver_function_table *ft = xscreensaver_function_table;
+
+ const XrmOptionDescRec *options = ft->options;
+ const char * const *defaults = ft->defaults;
+ const char *progclass = ft->progclass;
+
int def_opts_size, opts_size;
int def_defaults_size, defaults_size;
strcat (newr, oldr);
*s = newr;
}
+ else
+ *s = strdup (*s);
}
}
}
-#ifdef XLOCKMORE
-extern void pre_merge_options (void);
-#endif
-
-
static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW;
/* Dead-trivial event handling: exits if "q" or "ESC" are typed.
Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
+ Returns False if the screen saver should now terminate.
*/
-void
-screenhack_handle_event (Display *dpy, XEvent *event)
+static Bool
+screenhack_handle_event_1 (Display *dpy, XEvent *event)
{
switch (event->xany.type)
{
c == 'Q' ||
c == 3 || /* ^C */
c == 27) /* ESC */
- exit (0);
+ return False; /* exit */
else if (! (keysym >= XK_Shift_L && keysym <= XK_Hyper_R))
XBell (dpy, 0); /* beep for non-chord keys */
}
}
else
{
- exit (0);
+ return False; /* exit */
}
}
break;
}
-}
-
-
-void
-screenhack_handle_events (Display *dpy)
-{
- while (XPending (dpy))
- {
- XEvent event;
- XNextEvent (dpy, &event);
- screenhack_handle_event (dpy, &event);
- }
+ return True;
}
static Visual *
pick_visual (Screen *screen)
{
-#ifdef USE_GL
- /* If we're linking against GL (that is, this is the version of screenhack.o
- that the GL hacks will use, which is different from the one that the
- non-GL hacks will use) then try to pick the "best" visual by interrogating
- the GL library instead of by asking Xlib. GL knows better.
- */
- Visual *v = 0;
- char *string = get_string_resource ("visualID", "VisualID");
- char *s;
-
- if (string)
- for (s = string; *s; s++)
- if (isupper (*s)) *s = _tolower (*s);
-
- if (!string || !*string ||
- !strcmp (string, "gl") ||
- !strcmp (string, "best") ||
- !strcmp (string, "color") ||
- !strcmp (string, "default"))
- v = get_gl_visual (screen); /* from ../utils/visual-gl.c */
-
- if (string)
- free (string);
- if (v)
- return v;
-#endif /* USE_GL */
+ struct xscreensaver_function_table *ft = xscreensaver_function_table;
+
+ if (ft->pick_visual_hook)
+ {
+ Visual *v = ft->pick_visual_hook (screen);
+ if (v) return v;
+ }
return get_visual_resource (screen, "visualID", "VisualID", False);
}
visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
Bool window_p)
{
- char *visual_string = get_string_resource ("visualID", "VisualID");
+ struct xscreensaver_function_table *ft = xscreensaver_function_table;
+
+ char *visual_string = get_string_resource (DisplayOfScreen (screen),
+ "visualID", "VisualID");
Visual *desired_visual = pick_visual (screen);
char win[100];
char why[100];
if (visual == DefaultVisualOfScreen (screen) &&
has_writable_cells (screen, visual) &&
- get_boolean_resource ("installColormap", "InstallColormap"))
+ get_boolean_resource (DisplayOfScreen (screen),
+ "installColormap", "InstallColormap"))
{
fprintf (stderr, "%s: ignoring `-install' because of `%s'.\n",
progname, why);
progname, win, (unsigned long) cmap);
}
-# ifdef USE_GL
- if (!validate_gl_visual (stderr, screen, win, visual))
- exit (1);
-# endif /* USE_GL */
+ if (ft->validate_visual_hook)
+ {
+ if (! ft->validate_visual_hook (screen, win, visual))
+ exit (1);
+ }
}
}
+static Boolean
+screenhack_table_handle_events (Display *dpy,
+ const struct xscreensaver_function_table *ft,
+ Window window, void *closure
+#ifdef DEBUG_PAIR
+ , Window window2, void *closure2
+#endif
+ )
+{
+ XtAppContext app = XtDisplayToApplicationContext (dpy);
+
+ if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput))
+ XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput);
+
+ while (XPending (dpy))
+ {
+ XEvent event;
+ XNextEvent (dpy, &event);
+
+ if (event.xany.type == ConfigureNotify)
+ {
+ if (event.xany.window == window)
+ ft->reshape_cb (dpy, window, closure,
+ event.xconfigure.width, event.xconfigure.height);
+#ifdef DEBUG_PAIR
+ if (window2 && event.xany.window == window2)
+ ft->reshape_cb (dpy, window2, closure2,
+ event.xconfigure.width, event.xconfigure.height);
+#endif
+ }
+ else if (event.xany.type == ClientMessage ||
+ (! (event.xany.window == window
+ ? ft->event_cb (dpy, window, closure, &event)
+#ifdef DEBUG_PAIR
+ : (window2 && event.xany.window == window2)
+ ? ft->event_cb (dpy, window2, closure2, &event)
+#endif
+ : 0)))
+ if (! screenhack_handle_event_1 (dpy, &event))
+ return False;
+
+ if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput))
+ XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput);
+ }
+ return True;
+}
+
+
+static Boolean
+usleep_and_process_events (Display *dpy,
+ const struct xscreensaver_function_table *ft,
+ Window window, fps_state *fpst, void *closure,
+ unsigned long delay
+#ifdef DEBUG_PAIR
+ , Window window2, fps_state *fpst2, void *closure2,
+ unsigned long delay2
+#endif
+# ifdef HAVE_RECORD_ANIM
+ , record_anim_state *anim_state
+# endif
+ )
+{
+ do {
+ unsigned long quantum = 33333; /* 30 fps */
+ if (quantum > delay)
+ quantum = delay;
+ delay -= quantum;
+
+ XSync (dpy, False);
+
+#ifdef HAVE_RECORD_ANIM
+ if (anim_state) screenhack_record_anim (anim_state);
+#endif
+
+ if (quantum > 0)
+ {
+ usleep (quantum);
+ if (fpst) fps_slept (fpst, quantum);
+#ifdef DEBUG_PAIR
+ if (fpst2) fps_slept (fpst2, quantum);
+#endif
+ }
+
+ if (! screenhack_table_handle_events (dpy, ft, window, closure
+#ifdef DEBUG_PAIR
+ , window2, closure2
+#endif
+ ))
+ return False;
+ } while (delay > 0);
+
+ return True;
+}
+
+
+static void
+screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
+{
+ fps_compute (fpst, 0, -1);
+ fps_draw (fpst);
+}
+
+
+static void
+run_screenhack_table (Display *dpy,
+ Window window,
+# ifdef DEBUG_PAIR
+ Window window2,
+# endif
+# ifdef HAVE_RECORD_ANIM
+ record_anim_state *anim_state,
+# endif
+ const struct xscreensaver_function_table *ft)
+{
+
+ /* Kludge: even though the init_cb functions are declared to take 2 args,
+ actually call them with 3, for the benefit of xlockmore_init() and
+ xlockmore_setup().
+ */
+ void *(*init_cb) (Display *, Window, void *) =
+ (void *(*) (Display *, Window, void *)) ft->init_cb;
+
+ void (*fps_cb) (Display *, Window, fps_state *, void *) = ft->fps_cb;
+
+ void *closure = init_cb (dpy, window, ft->setup_arg);
+ fps_state *fpst = fps_init (dpy, window);
+
+#ifdef DEBUG_PAIR
+ void *closure2 = 0;
+ fps_state *fpst2 = 0;
+ if (window2) closure2 = init_cb (dpy, window2, ft->setup_arg);
+ if (window2) fpst2 = fps_init (dpy, window2);
+#endif
+
+ if (! closure) /* if it returns nothing, it can't possibly be re-entrant. */
+ abort();
+
+ if (! fps_cb) fps_cb = screenhack_do_fps;
+
+ while (1)
+ {
+ unsigned long delay = ft->draw_cb (dpy, window, closure);
+#ifdef DEBUG_PAIR
+ unsigned long delay2 = 0;
+ if (window2) delay2 = ft->draw_cb (dpy, window2, closure2);
+#endif
+
+ if (fpst) fps_cb (dpy, window, fpst, closure);
+#ifdef DEBUG_PAIR
+ if (fpst2) fps_cb (dpy, window, fpst2, closure);
+#endif
+
+ if (! usleep_and_process_events (dpy, ft,
+ window, fpst, closure, delay
+#ifdef DEBUG_PAIR
+ , window2, fpst2, closure2, delay2
+#endif
+#ifdef HAVE_RECORD_ANIM
+ , anim_state
+#endif
+ ))
+ break;
+ }
+
+#ifdef HAVE_RECORD_ANIM
+ /* Exiting before target frames hit: write the video anyway. */
+ if (anim_state) screenhack_record_anim_free (anim_state);
+#endif
+
+ ft->free_cb (dpy, window, closure);
+ if (fpst) fps_free (fpst);
+
+#ifdef DEBUG_PAIR
+ if (window2) ft->free_cb (dpy, window2, closure2);
+ if (fpst2) fps_free (fpst2);
+#endif
+}
+
+
+static Widget
+make_shell (Screen *screen, Widget toplevel, int width, int height)
+{
+ Display *dpy = DisplayOfScreen (screen);
+ Visual *visual = pick_visual (screen);
+ Boolean def_visual_p = (toplevel &&
+ visual == DefaultVisualOfScreen (screen));
+
+ if (width <= 0) width = 600;
+ if (height <= 0) height = 480;
+
+ if (def_visual_p)
+ {
+ Window window;
+ XtVaSetValues (toplevel,
+ XtNmappedWhenManaged, False,
+ XtNwidth, width,
+ XtNheight, height,
+ XtNinput, True, /* for WM_HINTS */
+ NULL);
+ XtRealizeWidget (toplevel);
+ window = XtWindow (toplevel);
+
+ if (get_boolean_resource (dpy, "installColormap", "InstallColormap"))
+ {
+ Colormap cmap =
+ XCreateColormap (dpy, window, DefaultVisualOfScreen (screen),
+ AllocNone);
+ XSetWindowColormap (dpy, window, cmap);
+ }
+ }
+ else
+ {
+ unsigned int bg, bd;
+ Widget new;
+ Colormap cmap = XCreateColormap (dpy, VirtualRootWindowOfScreen(screen),
+ visual, AllocNone);
+ bg = get_pixel_resource (dpy, cmap, "background", "Background");
+ bd = get_pixel_resource (dpy, cmap, "borderColor", "Foreground");
+
+ new = XtVaAppCreateShell (progname, progclass,
+ topLevelShellWidgetClass, dpy,
+ XtNmappedWhenManaged, False,
+ XtNvisual, visual,
+ XtNdepth, visual_depth (screen, visual),
+ XtNwidth, width,
+ XtNheight, height,
+ XtNcolormap, cmap,
+ XtNbackground, (Pixel) bg,
+ XtNborderColor, (Pixel) bd,
+ XtNinput, True, /* for WM_HINTS */
+ NULL);
+
+ if (!toplevel) /* kludge for the second window in -pair mode... */
+ XtVaSetValues (new, XtNx, 0, XtNy, 550, NULL);
+
+ XtRealizeWidget (new);
+ toplevel = new;
+ }
+
+ return toplevel;
+}
+
+static void
+init_window (Display *dpy, Widget toplevel, const char *title)
+{
+ Window window;
+ XWindowAttributes xgwa;
+ XtPopup (toplevel, XtGrabNone);
+ XtVaSetValues (toplevel, XtNtitle, title, NULL);
+
+ /* Select KeyPress, and announce that we accept WM_DELETE_WINDOW.
+ */
+ window = XtWindow (toplevel);
+ XGetWindowAttributes (dpy, window, &xgwa);
+ XSelectInput (dpy, window,
+ (xgwa.your_event_mask | KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask));
+ XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
+ PropModeReplace,
+ (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
+}
+
+
int
main (int argc, char **argv)
{
+ struct xscreensaver_function_table *ft = xscreensaver_function_table;
+
+ XWindowAttributes xgwa;
Widget toplevel;
Display *dpy;
Window window;
- Screen *screen;
- Visual *visual;
- Colormap cmap;
+# ifdef DEBUG_PAIR
+ Window window2 = 0;
+ Widget toplevel2 = 0;
+# endif
+#ifdef HAVE_RECORD_ANIM
+ record_anim_state *anim_state = 0;
+#endif
+ XtAppContext app;
Bool root_p;
Window on_window = 0;
XEvent event;
- Boolean dont_clear /*, dont_map */;
+ Boolean dont_clear;
char version[255];
fix_fds();
-#ifdef XLOCKMORE
- pre_merge_options ();
-#endif
+ progname = argv[0]; /* reset later */
+ progclass = ft->progclass;
+
+ if (ft->setup_cb)
+ ft->setup_cb (ft, ft->setup_arg);
+
merge_options ();
#ifdef __sgi
toplevel = XtAppInitialize (&app, progclass, merged_options,
merged_options_size, &argc, argv,
merged_defaults, 0, 0);
+
dpy = XtDisplay (toplevel);
- screen = XtScreen (toplevel);
- db = XtDatabase (dpy);
- XtGetApplicationNameAndClass (dpy, &progname, &progclass);
+ XtGetApplicationNameAndClass (dpy,
+ (char **) &progname,
+ (char **) &progclass);
/* half-assed way of avoiding buffer-overrun attacks. */
- if (strlen (progname) >= 100) progname[100] = 0;
+ if (strlen (progname) >= 100) ((char *) progname)[100] = 0;
XSetErrorHandler (screenhack_ehandler);
{
char *v = (char *) strdup(strchr(screensaver_id, ' '));
char *s1, *s2, *s3, *s4;
+ const char *ot = get_string_resource (dpy, "title", "Title");
s1 = (char *) strchr(v, ' '); s1++;
s2 = (char *) strchr(s1, ' ');
s3 = (char *) strchr(v, '('); s3++;
s4 = (char *) strchr(s3, ')');
*s2 = 0;
*s4 = 0;
- sprintf (version, "%s: from the XScreenSaver %s distribution (%s.)",
+ if (ot && !*ot) ot = 0;
+ sprintf (version, "%.50s%s%s: from the XScreenSaver %s distribution (%s)",
+ (ot ? ot : ""),
+ (ot ? ": " : ""),
progclass, s1, s3);
free(v);
}
const char *opt = merged_options [i].option;
const char *res = merged_options [i].specifier + 1;
const char *val = merged_options [i].value;
- char *s = get_string_resource ((char *) res, (char *) res);
+ char *s = get_string_resource (dpy, (char *) res, (char *) res);
if (s)
{
exit (help_p ? 0 : 1);
}
- dont_clear = get_boolean_resource ("dontClearRoot", "Boolean");
-/*dont_map = get_boolean_resource ("dontMapWindow", "Boolean"); */
- mono_p = get_boolean_resource ("mono", "Boolean");
+ {
+ char **s;
+ for (s = merged_defaults; *s; s++)
+ free(*s);
+ }
+
+ free (merged_options);
+ free (merged_defaults);
+ merged_options = 0;
+ merged_defaults = 0;
+
+ dont_clear = get_boolean_resource (dpy, "dontClearRoot", "Boolean");
+ mono_p = get_boolean_resource (dpy, "mono", "Boolean");
if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
mono_p = True;
- root_p = get_boolean_resource ("root", "Boolean");
+ root_p = get_boolean_resource (dpy, "root", "Boolean");
{
- char *s = get_string_resource ("windowID", "WindowID");
+ char *s = get_string_resource (dpy, "windowID", "WindowID");
if (s && *s)
- on_window = get_integer_resource ("windowID", "WindowID");
+ on_window = get_integer_resource (dpy, "windowID", "WindowID");
if (s) free (s);
}
if (on_window)
{
- XWindowAttributes xgwa;
window = (Window) on_window;
XtDestroyWidget (toplevel);
XGetWindowAttributes (dpy, window, &xgwa);
- cmap = xgwa.colormap;
- visual = xgwa.visual;
- screen = xgwa.screen;
- visual_warning (screen, window, visual, cmap, True);
+ visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, True);
- /* Select KeyPress events on the external window.
+ /* Select KeyPress and resize events on the external window.
*/
- xgwa.your_event_mask |= KeyPressMask;
+ xgwa.your_event_mask |= KeyPressMask | StructureNotifyMask;
XSelectInput (dpy, window, xgwa.your_event_mask);
/* Select ButtonPress and ButtonRelease events on the external window,
}
else if (root_p)
{
- XWindowAttributes xgwa;
- window = RootWindowOfScreen (XtScreen (toplevel));
+ window = VirtualRootWindowOfScreen (XtScreen (toplevel));
XtDestroyWidget (toplevel);
XGetWindowAttributes (dpy, window, &xgwa);
- cmap = xgwa.colormap;
- visual = xgwa.visual;
- visual_warning (screen, window, visual, cmap, False);
+ /* With RANDR, the root window can resize! */
+ XSelectInput (dpy, window, xgwa.your_event_mask | StructureNotifyMask);
+ visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, False);
}
else
{
- Boolean def_visual_p;
- visual = pick_visual (screen);
-
-# ifdef USE_GL
- if (!validate_gl_visual (stderr, screen, "window", visual))
- exit (1);
-# endif /* USE_GL */
-
- if (toplevel->core.width <= 0)
- toplevel->core.width = 600;
- if (toplevel->core.height <= 0)
- toplevel->core.height = 480;
-
- def_visual_p = (visual == DefaultVisualOfScreen (screen));
-
- if (!def_visual_p)
- {
- unsigned int bg, bd;
- Widget new;
-
- cmap = XCreateColormap (dpy, RootWindowOfScreen(screen),
- visual, AllocNone);
- bg = get_pixel_resource ("background", "Background", dpy, cmap);
- bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
-
- new = XtVaAppCreateShell (progname, progclass,
- topLevelShellWidgetClass, dpy,
- XtNmappedWhenManaged, False,
- XtNvisual, visual,
- XtNdepth, visual_depth (screen, visual),
- XtNwidth, toplevel->core.width,
- XtNheight, toplevel->core.height,
- XtNcolormap, cmap,
- XtNbackground, (Pixel) bg,
- XtNborderColor, (Pixel) bd,
- XtNinput, True, /* for WM_HINTS */
- NULL);
- XtDestroyWidget (toplevel);
- toplevel = new;
- XtRealizeWidget (toplevel);
- window = XtWindow (toplevel);
- }
- else
- {
- XtVaSetValues (toplevel,
- XtNmappedWhenManaged, False,
- XtNinput, True, /* for WM_HINTS */
- NULL);
- XtRealizeWidget (toplevel);
- window = XtWindow (toplevel);
-
- if (get_boolean_resource ("installColormap", "InstallColormap"))
- {
- cmap = XCreateColormap (dpy, window,
- DefaultVisualOfScreen (XtScreen (toplevel)),
- AllocNone);
- XSetWindowColormap (dpy, window, cmap);
- }
- else
- {
- cmap = DefaultColormap (dpy, DefaultScreen (dpy));
- }
- }
-
-/*
- if (dont_map)
- {
- XtVaSetValues (toplevel, XtNmappedWhenManaged, False, NULL);
- XtRealizeWidget (toplevel);
- }
- else
-*/
- {
- XtPopup (toplevel, XtGrabNone);
- }
+ Widget new = make_shell (XtScreen (toplevel), toplevel,
+ toplevel->core.width,
+ toplevel->core.height);
+ if (new != toplevel)
+ {
+ XtDestroyWidget (toplevel);
+ toplevel = new;
+ }
- XtVaSetValues(toplevel, XtNtitle, version, NULL);
+ init_window (dpy, toplevel, version);
+ window = XtWindow (toplevel);
+ XGetWindowAttributes (dpy, window, &xgwa);
- /* For screenhack_handle_events(): select KeyPress, and
- announce that we accept WM_DELETE_WINDOW. */
- {
- XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, window, &xgwa);
- XSelectInput (dpy, window,
- (xgwa.your_event_mask | KeyPressMask |
- ButtonPressMask | ButtonReleaseMask));
- XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
- }
+# ifdef DEBUG_PAIR
+ if (get_boolean_resource (dpy, "pair", "Boolean"))
+ {
+ toplevel2 = make_shell (xgwa.screen, 0,
+ toplevel->core.width,
+ toplevel->core.height);
+ init_window (dpy, toplevel2, version);
+ window2 = XtWindow (toplevel2);
+ }
+# endif /* DEBUG_PAIR */
}
if (!dont_clear)
{
- XSetWindowBackground (dpy, window,
- get_pixel_resource ("background", "Background",
- dpy, cmap));
+ unsigned int bg = get_pixel_resource (dpy, xgwa.colormap,
+ "background", "Background");
+ XSetWindowBackground (dpy, window, bg);
XClearWindow (dpy, window);
+# ifdef DEBUG_PAIR
+ if (window2)
+ {
+ XSetWindowBackground (dpy, window2, bg);
+ XClearWindow (dpy, window2);
+ }
+# endif
}
if (!root_p && !on_window)
# undef ya_rand_init
ya_rand_init (0);
- screenhack (dpy, window); /* doesn't return */
+
+#ifdef HAVE_RECORD_ANIM
+ {
+ int frames = get_integer_resource (dpy, "recordAnim", "Integer");
+ if (frames > 0)
+ anim_state = screenhack_record_anim_init (xgwa.screen, window, frames);
+ }
+#endif
+
+ run_screenhack_table (dpy, window,
+# ifdef DEBUG_PAIR
+ window2,
+# endif
+# ifdef HAVE_RECORD_ANIM
+ anim_state,
+# endif
+ ft);
+
+#ifdef HAVE_RECORD_ANIM
+ if (anim_state) screenhack_record_anim_free (anim_state);
+#endif
+
+ XtDestroyWidget (toplevel);
+ XtDestroyApplicationContext (app);
+
return 0;
}