X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fscreenhack.c;h=4850911db59bb5415c966d692e7905d17a846f90;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hp=443d3f423745562b89165e8df92fa620caad08ec;hpb=de460e831dc8578acfa8b72251ab9346c99c1f96;p=xscreensaver diff --git a/hacks/screenhack.c b/hacks/screenhack.c index 443d3f42..4850911d 100644 --- a/hacks/screenhack.c +++ b/hacks/screenhack.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-2017 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -43,10 +43,16 @@ Called when a keyboard or mouse event arrives. Return True if you handle it in some way, False otherwise. - static void YOURNAME_event (Display *, Window, void *closure); + static void YOURNAME_free (Display *, Window, void *closure); Called when you are done: free everything you've allocated, - including your private `state' structure. + 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 }; @@ -68,7 +74,7 @@ - Do not use global variables: all such info must be stored in the private `state' structure. - - Do not static function-local variables, either. Put it in `state'. + - 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. @@ -77,7 +83,6 @@ of your screen saver module. See .../hacks/config/README for details. */ -#define DEBUG_TIMING #define DEBUG_PAIR #include @@ -105,6 +110,11 @@ #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. @@ -136,18 +146,27 @@ static XrmOptionDescRec default_options [] = { { "-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", @@ -158,6 +177,7 @@ static XrmOptionDescRec *merged_options; static int merged_options_size; static char **merged_defaults; + static void merge_options (void) { @@ -211,6 +231,8 @@ merge_options (void) strcat (newr, oldr); *s = newr; } + else + *s = strdup (*s); } } @@ -407,65 +429,6 @@ fix_fds (void) } -#ifdef DEBUG_TIMING - -static void -check_timing (unsigned long delay) -{ - static unsigned long frame_count = 0; - static unsigned long delay_sum = 0; - static struct timeval prev1 = { 0, }; - static struct timeval prev2 = { 0, }; - struct timeval now; - double uprev1, uprev2, unow; - -# ifdef GETTIMEOFDAY_TWO_ARGS - gettimeofday (&now, 0); -# else - gettimeofday (&now); -# endif - - if (prev1.tv_sec == 0) - prev1 = prev2 = now; - - frame_count++; - - uprev1 = prev1.tv_sec + ((double) prev1.tv_usec * 0.000001); - uprev2 = prev2.tv_sec + ((double) prev2.tv_usec * 0.000001); - unow = now.tv_sec + ((double) now.tv_usec * 0.000001); - - if (unow >= uprev1 + 1.5) - fprintf (stderr, - "%s: warning: blocked event processing for %.1f secs!\n", - progname, unow - uprev1); - prev1 = now; - - if (unow >= uprev2 + 10.0) - { - double fps = frame_count / (unow - uprev2); - double elapsed = unow - uprev2; - double slept = (delay_sum * 0.000001); - double sleep_ratio = slept / elapsed; - - if (sleep_ratio < 0.10) { - fprintf (stderr, - "%s: warning: only %.0f%% idle over the" - " last %2.0f secs (at %.1f FPS)\n", - progname, 100 * sleep_ratio, elapsed, fps); - } - - prev2 = now; - frame_count = 0; - delay_sum = 0; - } - - delay_sum += delay; -} - -#else /* !DEBUG_TIMING */ -# define check_timing(delay) /**/ -#endif /* !DEBUG_TIMING */ - static Boolean screenhack_table_handle_events (Display *dpy, const struct xscreensaver_function_table *ft, @@ -491,7 +454,7 @@ screenhack_table_handle_events (Display *dpy, ft->reshape_cb (dpy, window, closure, event.xconfigure.width, event.xconfigure.height); #ifdef DEBUG_PAIR - if (event.xany.window == window2) + if (window2 && event.xany.window == window2) ft->reshape_cb (dpy, window2, closure2, event.xconfigure.width, event.xconfigure.height); #endif @@ -500,7 +463,7 @@ screenhack_table_handle_events (Display *dpy, (! (event.xany.window == window ? ft->event_cb (dpy, window, closure, &event) #ifdef DEBUG_PAIR - : event.xany.window == window2 + : (window2 && event.xany.window == window2) ? ft->event_cb (dpy, window2, closure2, &event) #endif : 0))) @@ -517,27 +480,37 @@ screenhack_table_handle_events (Display *dpy, static Boolean usleep_and_process_events (Display *dpy, const struct xscreensaver_function_table *ft, - Window window, void *closure, unsigned long delay + Window window, fps_state *fpst, void *closure, + unsigned long delay #ifdef DEBUG_PAIR - , Window window2, void *closure2, unsigned long delay2 + , 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 = 100000; /* 1/10th second */ + unsigned long quantum = 33333; /* 30 fps */ if (quantum > delay) quantum = delay; delay -= quantum; XSync (dpy, False); - if (quantum > 0) - usleep (quantum); - check_timing (quantum); +#ifdef HAVE_RECORD_ANIM + if (anim_state) screenhack_record_anim (anim_state); +#endif - /* The above isn't quite right in pair-mode: we always run both windows - with the timing of window 2. But, it's just a debugging hack, so - that doesn't really matter that much... */ + 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 @@ -551,11 +524,22 @@ usleep_and_process_events (Display *dpy, } +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) { @@ -567,16 +551,23 @@ run_screenhack_table (Display *dpy, 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); @@ -585,20 +576,34 @@ run_screenhack_table (Display *dpy, 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, window2, fpst2, closure2); +#endif + if (! usleep_and_process_events (dpy, ft, - window, closure, delay + window, fpst, closure, delay #ifdef DEBUG_PAIR - , window2, closure2, delay2 + , 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 (window2) ft->free_cb (dpy, window2, closure2); + if (fpst2) fps_free (fpst2); #endif } @@ -614,11 +619,6 @@ make_shell (Screen *screen, Widget toplevel, int width, int height) if (width <= 0) width = 600; if (height <= 0) height = 480; -# ifdef USE_GL - if (!validate_gl_visual (stderr, screen, "window", visual)) - exit (1); -# endif /* USE_GL */ - if (def_visual_p) { Window window; @@ -705,6 +705,9 @@ main (int argc, char **argv) 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; @@ -755,13 +758,17 @@ main (int argc, char **argv) { 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); } @@ -776,7 +783,7 @@ main (int argc, char **argv) !strcmp(argv[1], "--help")); fprintf (stderr, "%s\n", version); for (s = progclass; *s; s++) fprintf(stderr, " "); - fprintf (stderr, " http://www.jwz.org/xscreensaver/\n\n"); + fprintf (stderr, " https://www.jwz.org/xscreensaver/\n\n"); if (!help_p) fprintf(stderr, "Unrecognised option: %s\n", argv[1]); @@ -837,6 +844,12 @@ main (int argc, char **argv) exit (help_p ? 0 : 1); } + { + char **s; + for (s = merged_defaults; *s; s++) + free(*s); + } + free (merged_options); free (merged_defaults); merged_options = 0; @@ -940,12 +953,28 @@ main (int argc, char **argv) # undef ya_rand_init ya_rand_init (0); + +#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);