XScrnSaver.c revision 21bb84c3
1/*
2 *
3Copyright (c) 1992  X Consortium
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of the X Consortium shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from the X Consortium.
25 *
26 * Author:  Keith Packard, MIT X Consortium
27 */
28
29#include <X11/Xlibint.h>
30#include <X11/Xutil.h>
31#include <X11/extensions/Xext.h>
32#include <X11/extensions/extutil.h>
33#include <X11/extensions/saverproto.h>
34#include <X11/extensions/scrnsaver.h>
35
36
37static XExtensionInfo _screen_saver_info_data;
38static XExtensionInfo *screen_saver_info = &_screen_saver_info_data;
39static char *screen_saver_extension_name = ScreenSaverName;
40
41#define ScreenSaverCheckExtension(dpy,i,val) \
42  XextCheckExtension (dpy, i, screen_saver_extension_name, val)
43#define ScreenSaverSimpleCheckExtension(dpy,i) \
44  XextSimpleCheckExtension (dpy, i, screen_saver_extension_name)
45
46static int close_display(
47    Display *		/* dpy */,
48    XExtCodes *		/* codes */
49);
50
51static Bool wire_to_event(
52    Display *		/* dpy */,
53    XEvent *		/* re */,
54    xEvent *		/* event */
55);
56
57static Status event_to_wire(
58    Display *		/* dpy */,
59    XEvent *		/* re */,
60    xEvent *		/* event */
61);
62
63static /* const */ XExtensionHooks screen_saver_extension_hooks = {
64    NULL,				/* create_gc */
65    NULL,				/* copy_gc */
66    NULL,				/* flush_gc */
67    NULL,				/* free_gc */
68    NULL,				/* create_font */
69    NULL,				/* free_font */
70    close_display,			/* close_display */
71    wire_to_event,			/* wire_to_event */
72    event_to_wire,			/* event_to_wire */
73    NULL,				/* error */
74    NULL,				/* error_string */
75};
76
77static XEXT_GENERATE_FIND_DISPLAY (find_display, screen_saver_info,
78				   screen_saver_extension_name,
79				   &screen_saver_extension_hooks,
80				   ScreenSaverNumberEvents, NULL)
81
82static XEXT_GENERATE_CLOSE_DISPLAY (close_display, screen_saver_info)
83
84
85static Bool wire_to_event (
86    Display	*dpy,
87    XEvent	*re,
88    xEvent	*event)
89{
90    XExtDisplayInfo *info = find_display (dpy);
91    XScreenSaverNotifyEvent	*se;
92    xScreenSaverNotifyEvent	*sevent;
93
94    ScreenSaverCheckExtension (dpy, info, False);
95
96    switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
97    case ScreenSaverNotify:
98    	se = (XScreenSaverNotifyEvent *) re;
99	sevent = (xScreenSaverNotifyEvent *) event;
100    	se->type = sevent->type & 0x7f;
101    	se->serial = _XSetLastRequestRead(dpy,(xGenericReply *) event);
102    	se->send_event = (sevent->type & 0x80) != 0;
103    	se->display = dpy;
104    	se->window = sevent->window;
105    	se->window = sevent->root;
106    	se->state = sevent->state;
107	se->kind = sevent->kind;
108	se->forced = True;
109	if (sevent->forced == xFalse)
110	    se->forced = False;
111	se->time = sevent->timestamp;
112    	return True;
113    }
114    return False;
115}
116
117static Status event_to_wire (
118    Display	*dpy,
119    XEvent	*re,
120    xEvent	*event)
121{
122    XExtDisplayInfo *info = find_display (dpy);
123    XScreenSaverNotifyEvent	*se;
124    xScreenSaverNotifyEvent	*sevent;
125
126    ScreenSaverCheckExtension (dpy, info, 0);
127
128    switch ((re->type & 0x7f) - info->codes->first_event) {
129    case ScreenSaverNotify:
130    	se = (XScreenSaverNotifyEvent *) re;
131	sevent = (xScreenSaverNotifyEvent *) event;
132    	sevent->type = se->type | (se->send_event ? 0x80 : 0);
133    	sevent->sequenceNumber = se->serial & 0xffff;
134    	sevent->root = se->root;
135    	sevent->window = se->window;
136    	sevent->state = se->state;
137	sevent->kind = se->kind;
138	sevent->forced = xFalse;
139	if (se->forced == True)
140	    sevent->forced = xTrue;
141	sevent->timestamp = se->time;
142    	return 1;
143    }
144    return 0;
145}
146
147/****************************************************************************
148 *                                                                          *
149 *			    ScreenSaver public interfaces                         *
150 *                                                                          *
151 ****************************************************************************/
152
153Bool XScreenSaverQueryExtension (
154    Display	*dpy,
155    int		*event_base_return,
156    int		*error_base_return)
157{
158    XExtDisplayInfo *info = find_display (dpy);
159
160    if (XextHasExtension(info)) {
161	*event_base_return = info->codes->first_event;
162	*error_base_return = info->codes->first_error;
163	return True;
164    } else {
165	return False;
166    }
167}
168
169
170Status XScreenSaverQueryVersion(
171    Display	*dpy,
172    int		*major_version_return,
173    int		*minor_version_return)
174{
175    XExtDisplayInfo *info = find_display (dpy);
176    xScreenSaverQueryVersionReply	    rep;
177    register xScreenSaverQueryVersionReq  *req;
178
179    ScreenSaverCheckExtension (dpy, info, 0);
180
181    LockDisplay (dpy);
182    GetReq (ScreenSaverQueryVersion, req);
183    req->reqType = info->codes->major_opcode;
184    req->saverReqType = X_ScreenSaverQueryVersion;
185    req->clientMajor = ScreenSaverMajorVersion;
186    req->clientMinor = ScreenSaverMinorVersion;
187    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
188	UnlockDisplay (dpy);
189	SyncHandle ();
190	return 0;
191    }
192    *major_version_return = rep.majorVersion;
193    *minor_version_return = rep.minorVersion;
194    UnlockDisplay (dpy);
195    SyncHandle ();
196    return 1;
197}
198
199XScreenSaverInfo *XScreenSaverAllocInfo (void)
200{
201    return (XScreenSaverInfo *) Xmalloc (sizeof (XScreenSaverInfo));
202}
203
204Status XScreenSaverQueryInfo (
205    Display		*dpy,
206    Drawable		 drawable,
207    XScreenSaverInfo	*saver_info)
208{
209    XExtDisplayInfo			*info = find_display (dpy);
210    xScreenSaverQueryInfoReply		rep;
211    register xScreenSaverQueryInfoReq	*req;
212
213    ScreenSaverCheckExtension (dpy, info, 0);
214
215    LockDisplay (dpy);
216    GetReq (ScreenSaverQueryInfo, req);
217    req->reqType = info->codes->major_opcode;
218    req->saverReqType = X_ScreenSaverQueryInfo;
219    req->drawable = drawable;
220    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
221	UnlockDisplay (dpy);
222	SyncHandle ();
223	return 0;
224    }
225    UnlockDisplay (dpy);
226    SyncHandle ();
227    saver_info->window = rep.window;
228    saver_info->state = rep.state;
229    saver_info->kind = rep.kind;
230    saver_info->til_or_since = rep.tilOrSince;
231    saver_info->idle = rep.idle;
232    saver_info->eventMask = rep.eventMask;
233    return 1;
234}
235
236void XScreenSaverSelectInput (
237    register Display	*dpy,
238    Drawable		 drawable,
239    unsigned long	 mask)
240{
241    XExtDisplayInfo *info = find_display (dpy);
242    register xScreenSaverSelectInputReq   *req;
243
244    ScreenSaverSimpleCheckExtension (dpy, info);
245
246    LockDisplay (dpy);
247    GetReq (ScreenSaverSelectInput, req);
248    req->reqType = info->codes->major_opcode;
249    req->saverReqType = X_ScreenSaverSelectInput;
250    req->drawable = drawable;
251    req->eventMask = mask;
252    UnlockDisplay (dpy);
253    SyncHandle ();
254}
255
256static void
257XScreenSaverProcessWindowAttributes (
258    register Display			*dpy,
259    xChangeWindowAttributesReq		*req,
260    register unsigned long		 valuemask,
261    register XSetWindowAttributes	*attributes)
262    {
263    unsigned long values[32];
264    register unsigned long *value = values;
265    unsigned int nvalues;
266
267    if (valuemask & CWBackPixmap)
268	*value++ = attributes->background_pixmap;
269
270    if (valuemask & CWBackPixel)
271    	*value++ = attributes->background_pixel;
272
273    if (valuemask & CWBorderPixmap)
274    	*value++ = attributes->border_pixmap;
275
276    if (valuemask & CWBorderPixel)
277    	*value++ = attributes->border_pixel;
278
279    if (valuemask & CWBitGravity)
280    	*value++ = attributes->bit_gravity;
281
282    if (valuemask & CWWinGravity)
283	*value++ = attributes->win_gravity;
284
285    if (valuemask & CWBackingStore)
286        *value++ = attributes->backing_store;
287
288    if (valuemask & CWBackingPlanes)
289	*value++ = attributes->backing_planes;
290
291    if (valuemask & CWBackingPixel)
292    	*value++ = attributes->backing_pixel;
293
294    if (valuemask & CWOverrideRedirect)
295    	*value++ = attributes->override_redirect;
296
297    if (valuemask & CWSaveUnder)
298    	*value++ = attributes->save_under;
299
300    if (valuemask & CWEventMask)
301	*value++ = attributes->event_mask;
302
303    if (valuemask & CWDontPropagate)
304	*value++ = attributes->do_not_propagate_mask;
305
306    if (valuemask & CWColormap)
307	*value++ = attributes->colormap;
308
309    if (valuemask & CWCursor)
310	*value++ = attributes->cursor;
311
312    req->length += (nvalues = value - values);
313
314    nvalues <<= 2;			    /* watch out for macros... */
315    Data32 (dpy, (long *) values, (long)nvalues);
316
317    }
318
319void XScreenSaverSetAttributes (
320    Display			*dpy,
321    Drawable			 drawable,
322    int				 x,
323    int				 y,
324    unsigned int		 width,
325    unsigned int		 height,
326    unsigned int		 border_width,
327    int				 depth,
328    unsigned int		 class,
329    Visual			*visual,
330    unsigned long		 valuemask,
331    XSetWindowAttributes	*attributes)
332{
333    XExtDisplayInfo *info = find_display (dpy);
334    register xScreenSaverSetAttributesReq   *req;
335
336    ScreenSaverSimpleCheckExtension (dpy, info);
337
338    LockDisplay (dpy);
339    GetReq (ScreenSaverSetAttributes, req);
340    req->reqType = info->codes->major_opcode;
341    req->saverReqType = X_ScreenSaverSetAttributes;
342    req->drawable = drawable;
343    req->x = x;
344    req->y = y;
345    req->width = width;
346    req->height = height;
347    req->borderWidth = border_width;
348    req->c_class = class;
349    req->depth = depth;
350    if (visual == (Visual *)CopyFromParent)
351	req->visualID = CopyFromParent;
352    else
353	req->visualID = visual->visualid;
354    /* abuse an Xlib internal interface - is this legal for us? */
355    if ((req->mask = valuemask))
356        XScreenSaverProcessWindowAttributes (dpy,
357			(xChangeWindowAttributesReq *)req,
358			valuemask, attributes);
359    UnlockDisplay (dpy);
360    SyncHandle ();
361}
362
363
364void XScreenSaverUnsetAttributes (
365    register Display	*dpy,
366    Drawable		 drawable)
367{
368    XExtDisplayInfo *info = find_display (dpy);
369    register xScreenSaverUnsetAttributesReq   *req;
370
371    ScreenSaverSimpleCheckExtension (dpy, info);
372
373    LockDisplay (dpy);
374    GetReq (ScreenSaverUnsetAttributes, req);
375    req->reqType = info->codes->major_opcode;
376    req->saverReqType = X_ScreenSaverUnsetAttributes;
377    req->drawable = drawable;
378    UnlockDisplay (dpy);
379    SyncHandle ();
380}
381
382
383Status XScreenSaverRegister (
384    Display	*dpy,
385    int		 screen,
386    XID		 xid,
387    Atom	 type)
388{
389    Atom prop;
390    unsigned long ul;
391
392    prop = XInternAtom (dpy, ScreenSaverPropertyName, False);
393    if (!prop)
394	return 0;
395
396    ul = (unsigned long) xid;
397    XChangeProperty (dpy, RootWindow(dpy,screen), prop, type, 32,
398		     PropModeReplace, (unsigned char *) &ul, 1);
399    return 1;
400}
401
402
403
404Status XScreenSaverUnregister (
405    Display	*dpy,
406    int		 screen)
407{
408    Atom prop;
409
410    prop = XInternAtom (dpy, ScreenSaverPropertyName, False);
411    if (!prop)
412	return 0;
413
414    XDeleteProperty (dpy, RootWindow(dpy,screen), prop);
415    return 1;
416}
417
418
419
420Status XScreenSaverGetRegistered (
421    Display	*dpy,
422    int		 screen,
423    XID		*xid,
424    Atom	*type)
425{
426    Atom actual_type = None;
427    int actual_format;
428    unsigned long nitems, bytesafter;
429    unsigned long *ulp = (unsigned long *) 0;
430    Atom prop;
431    int retval = 0;
432
433    prop = XInternAtom (dpy, ScreenSaverPropertyName, False);
434    if (!prop)
435	return retval;
436
437    if (XGetWindowProperty (dpy, RootWindow(dpy,screen), prop, 0L, 1L, False,
438			    AnyPropertyType, &actual_type,  &actual_format,
439			    &nitems, &bytesafter, (unsigned char **) &ulp)
440	!= Success)
441	return retval;
442
443    if (ulp) {
444	if (actual_format == 32) {
445	    *xid = (XID) ulp[0];
446	    *type = actual_type;
447	    retval = 1;
448	}
449	XFree ((char *) ulp);
450    }
451    return retval;
452}
453
454void
455XScreenSaverSuspend (Display *dpy, Bool suspend)
456{
457    XExtDisplayInfo *info = find_display (dpy);
458    xScreenSaverSuspendReq   *req;
459
460    ScreenSaverSimpleCheckExtension (dpy, info);
461
462    LockDisplay (dpy);
463    GetReq (ScreenSaverSuspend, req);
464    req->reqType = info->codes->major_opcode;
465    req->saverReqType = X_ScreenSaverSuspend;
466    req->suspend = suspend;
467    UnlockDisplay (dpy);
468    SyncHandle ();
469}
470
471