From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- README.hacking | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 README.hacking (limited to 'README.hacking') diff --git a/README.hacking b/README.hacking new file mode 100644 index 0000000..6fc2fe5 --- /dev/null +++ b/README.hacking @@ -0,0 +1,198 @@ + +========================================================================== + + Writing new XScreenSaver modules + +========================================================================== + +Any program that can be made to render on an X window created by another +process can be used as a screen saver. Just get the window ID out of +$XSCREENSAVER_WINDOW, draw on that, and you're done. + +In theory, you can write a screen saver in any language you like. In +practice, however, languages other than C or C++ tend not to allow you to +draw to windows that they did not create themselves. Unfortunately, this +means that if you want to write a screen saver, you must write it in C. + +Given that you're going to be writing in C, you might as well take +advantage of the various utility functions that I have written to make +that easier. Writing a new screen saver in C using the frameworks +included with xscreensaver simplifies things enormously. + +Generally, the best way to learn how to do something is to find a similar +program, and play around with it until you understand it. Another +approach is to not worry about understanding it, but to just hack it out. +Either way, your best bet is probably to start with one of the existing +xscreensaver demos, included in the "hacks/" directory, rename the file, +and edit it until it does what you want. + +The "Greynetic" and "Deluxe" hacks are probably good ones to start with, +since they are so very simple. For OpenGL programs, "DangerBall" is a +good example. + + +========================================================================== +Requirements for inclusion with the XScreenSaver collection +========================================================================== + + If you come up with anything, send it to me! If it's good, I'd love to + include it in the xscreensaver distribution. However, there are a few + requirements for me to distribute it: + + - Write in portable ANSI C. No C++. No nonstandard libraries. + + - Write a .man page describing all command-line options. + + - Write an .xml file describing the graphical configuration dialog box. + + - Include a BSD-like copyright/license notice at the top of each source + file (preferably, just use the one from "screenhack.h", and include + your name and the current year). The GNU GPL is not compatible with + the rest of XScreenSaver. + + +========================================================================== +The XScreenSaver API +========================================================================== + + - Start with #include "screenhack.h" + + - Define 2 global variables: + + yoursavername_defaults -- Default values for the resources you use. + yoursavername_options -- The command-line options you accept. + + - Define 5 functions: + + yoursavername_init -- Return an object holding your global state. + yoursavername_draw -- Draw a single frame, quickly. + yoursavername_free -- Free everything you've allocated. + yoursavername_reshape -- Called when the window is resized. + yoursavername_event -- Called when a keyboard or mouse event happens. + + The "event" function will only be called when running in a window + (not as a screen saver). The "reshape" event will be called when the + window size changes, or (as a screen saver) when the display size + changes as a result of a RANDR event (e.g., plugging in a new monitor). + + It's ok for both the "event" and "resize" functions to do nothing. + + - All other functions should be static. + + - The last line of the file should be + XSCREENSAVER_MODULE ("YourSaverName", yoursavername) + + - Finally, edit the Makefile to add a rule for your program. + Just cut-and-paste one of the existing rules. + + Your "draw" must not run for more than a fraction of a second without + returning. This means "don't call usleep()". Everything has to be a + state machine. + + You may not store global state in global variables, or in function-local + static variables. All of your runtime state must be encapsulted in the + "state" object created by your "init" function. If you use global or + static variables, your screen saver will not work properly on macOS. + + Do not call XSync() or XFlush(). If you think you need to do that, it + probably means that you are you are relying on the speed of the graphics + card for timing, which probably means that your "draw" function is + taking too long. + + +========================================================================== +The xlockmore API +========================================================================== + + Some of the display modes that come with xscreensaver were ported from + xlock, and so, for historical reasons, they follow a slightly different + programming convention. For newly-written Xlib programs, you'd be + better off following the pattern used in hacks like "Deluxe" than in + hacks like "Flag". The xlockmore ones are the ones that begin with + "#ifdef STANDALONE" and #include "xlockmore.h". + + But, all OpenGL screen savers have to follow the xlockmore API. + + The xlockmore API is similar to the XScreenSaver API, in that you define + (roughly) the same set of functions, but the naming conventions are + slightly different. Instead of "hackname_init", it's "init_hackname", + and it should be preceeded with the pseudo-declaration ENTRYPOINT. + + One annoying mis-feature of the xlockmore API is that it *requires* you + to make use of global variables for two things: first, for each of your + command line options; and second, for an array that holds your global + state objects. These are the only exceptions to the "never use global + variables" rule. + + There are a few important differences between the original xlockmore API + and XScreenSaver's implementation: + + - XScreenSaver does not use refresh_hackname or change_hackname. + + - XScreenSaver provides two additional hooks not present in xlockmore: + reshape_hackname, and hackname_handle_event. These are respectively + equivalent to hackname_reshape and hackname_event in the XScreenSaver + API. + + - Under Xlib, MI_CLEARWINDOW doesn't clear the window immediately. + Instead, due to double buffering on macOS/iOS/Android, it waits until + after init_hackname or draw_hackname returns before clearing. Make + sure not to issue any Xlib drawing calls immediately after a call to + MI_CLEARWINDOW, as these will be erased. To clear the window + immediately, just use XClearWindow. + + +========================================================================== +Programming Tips +========================================================================== + + - Your screen saver should look reasonable at 20-30 frames per second. + That is, do not assume that your "draw" function will be called more + than 20 times a second. Even if you return a smaller requested delay + than that, you might not get it. Likewise, if your "draw" function + takes longer than 1/20th of a second to run, your screen saver may be + consuming too much CPU. + + - Don't make assumptions about the depth of the display, or whether it + is colormapped. You must allocate all your colors explicitly: do not + assume you can construct an RGB value and use that as a pixel value + directly. In particular, you can't make assumptions about whether + pixels are RGB, RGBA, ARGB, ABGR, or even whether they are 32, 24, + 16 or 8 bits. Use the utility routines provided by "utils/colors.h" + to simplify color allocation. + + - It is better to eliminate flicker by double-buffering to a Pixmap + than by erasing and re-drawing objects. Do not use drawing tricks + involving XOR. + + - If you use double-buffering, have a resource to turn it off. (MacOS, + iOS and Android have double-buffering built in, so you'd end up + triple-buffering.) + + - Understand the differences between Pixmaps and XImages, and keep in + mind which operations are happening in client memory and which are in + server memory, and which cause latency due to server round-trips. + Sometimes using the Shared Memory extension can be helpful, but + probably not as often as you might think. + + - On modern machines, OpenGL will always run faster than Xlib. It's + also more portable. Consider writing in OpenGL whenever possible. + + +========================================================================== +macOS, iOS and Android +========================================================================== + + Though XScreenSaver started its life as an X11 program, it also now runs + on macOS, iOS and Android, due to a maniacal collection of compatibility + shims. If you do your development on an X11 system, and follow the + usual XScreenSaver APIs, you shouldn't need to do anything special for + it to also work on macOS and on phones. + + See the READMEs in the OSX/ and android/ directories for instructions on + compiling for those platforms. + + To check that an X11 saver will fit well on a mobile device, test it + with -geometry 640x1136 and 640x960. That's a good first step, anyway. + +========================================================================== -- cgit v1.2.3-55-g7522