XScrnSaver.c revision 7bf574cc
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 const 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->root = 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 = (CARD8) (se->type | (se->send_event ? 0x80 : 0));
133	sevent->sequenceNumber = se->serial & 0xffff;
134	sevent->root = (CARD32) se->root;
135	sevent->window = (CARD32) se->window;
136	sevent->state = (BYTE) se->state;
137	sevent->kind = (BYTE) se->kind;
138	sevent->forced = xFalse;
139	if (se->forced == True)
140	    sevent->forced = xTrue;
141	sevent->timestamp = (CARD32) 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 = (CARD8) 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 = (CARD8) info->codes->major_opcode;
218    req->saverReqType = X_ScreenSaverQueryInfo;
219    req->drawable = (CARD32) 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 = (CARD8) info->codes->major_opcode;
249    req->saverReqType = X_ScreenSaverSelectInput;
250    req->drawable = (CARD32) drawable;
251    req->eventMask = (CARD32) 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] = { 0 };
264    register unsigned long *value = values;
265    unsigned long 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++ = (unsigned long) attributes->bit_gravity;
281
282    if (valuemask & CWWinGravity)
283	*value++ = (unsigned long) attributes->win_gravity;
284
285    if (valuemask & CWBackingStore)
286	*value++ = (unsigned long) 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++ = (unsigned long) attributes->override_redirect;
296
297    if (valuemask & CWSaveUnder)
298	*value++ = (unsigned long) attributes->save_under;
299
300    if (valuemask & CWEventMask)
301	*value++ = (unsigned long) attributes->event_mask;
302
303    if (valuemask & CWDontPropagate)
304	*value++ = (unsigned long) 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    nvalues = (unsigned long) (value - values);
313    req->length += nvalues;
314
315    nvalues <<= 2;			    /* watch out for macros... */
316    Data32 (dpy, (long *) values, (long)nvalues);
317
318}
319
320void XScreenSaverSetAttributes (
321    Display			*dpy,
322    Drawable			 drawable,
323    int				 x,
324    int				 y,
325    unsigned int		 width,
326    unsigned int		 height,
327    unsigned int		 border_width,
328    int				 depth,
329    unsigned int		 class,
330    Visual			*visual,
331    unsigned long		 valuemask,
332    XSetWindowAttributes	*attributes)
333{
334    XExtDisplayInfo *info = find_display (dpy);
335    register xScreenSaverSetAttributesReq   *req;
336
337    ScreenSaverSimpleCheckExtension (dpy, info);
338
339    LockDisplay (dpy);
340    GetReq (ScreenSaverSetAttributes, req);
341    req->reqType = (CARD8) info->codes->major_opcode;
342    req->saverReqType = X_ScreenSaverSetAttributes;
343    req->drawable = (CARD32) drawable;
344    req->x = (INT16) x;
345    req->y = (INT16) y;
346    req->width = (CARD16) width;
347    req->height = (CARD16) height;
348    req->borderWidth = (CARD16) border_width;
349    req->c_class = (BYTE) class;
350    req->depth = (CARD8) depth;
351    if (visual == (Visual *)CopyFromParent)
352	req->visualID = CopyFromParent;
353    else
354	req->visualID = (CARD32) visual->visualid;
355    /* abuse an Xlib internal interface - is this legal for us? */
356    if ((req->mask = (CARD32) valuemask) != 0)
357	XScreenSaverProcessWindowAttributes (dpy,
358			(xChangeWindowAttributesReq *)req,
359			valuemask, attributes);
360    UnlockDisplay (dpy);
361    SyncHandle ();
362}
363
364
365void XScreenSaverUnsetAttributes (
366    register Display	*dpy,
367    Drawable		 drawable)
368{
369    XExtDisplayInfo *info = find_display (dpy);
370    register xScreenSaverUnsetAttributesReq   *req;
371
372    ScreenSaverSimpleCheckExtension (dpy, info);
373
374    LockDisplay (dpy);
375    GetReq (ScreenSaverUnsetAttributes, req);
376    req->reqType = (CARD8) info->codes->major_opcode;
377    req->saverReqType = X_ScreenSaverUnsetAttributes;
378    req->drawable = (CARD32) drawable;
379    UnlockDisplay (dpy);
380    SyncHandle ();
381}
382
383
384Status XScreenSaverRegister (
385    Display	*dpy,
386    int		 screen,
387    XID		 xid,
388    Atom	 type)
389{
390    Atom prop;
391    unsigned long ul;
392
393    prop = XInternAtom (dpy, ScreenSaverPropertyName, False);
394    if (!prop)
395	return 0;
396
397    ul = (unsigned long) xid;
398    XChangeProperty (dpy, RootWindow(dpy,screen), prop, type, 32,
399		     PropModeReplace, (unsigned char *) &ul, 1);
400    return 1;
401}
402
403
404
405Status XScreenSaverUnregister (
406    Display	*dpy,
407    int		 screen)
408{
409    Atom prop;
410
411    prop = XInternAtom (dpy, ScreenSaverPropertyName, False);
412    if (!prop)
413	return 0;
414
415    XDeleteProperty (dpy, RootWindow(dpy,screen), prop);
416    return 1;
417}
418
419
420
421Status XScreenSaverGetRegistered (
422    Display	*dpy,
423    int		 screen,
424    XID		*xid,
425    Atom	*type)
426{
427    Atom actual_type = None;
428    int actual_format;
429    unsigned long nitems, bytesafter;
430    unsigned long *ulp = (unsigned long *) 0;
431    Atom prop;
432    int retval = 0;
433
434    prop = XInternAtom (dpy, ScreenSaverPropertyName, False);
435    if (!prop)
436	return retval;
437
438    if (XGetWindowProperty (dpy, RootWindow(dpy,screen), prop, 0L, 1L, False,
439			    AnyPropertyType, &actual_type,  &actual_format,
440			    &nitems, &bytesafter, (unsigned char **) &ulp)
441	!= Success)
442	return retval;
443
444    if (ulp) {
445	if (actual_format == 32) {
446	    *xid = (XID) ulp[0];
447	    *type = actual_type;
448	    retval = 1;
449	}
450	XFree ((char *) ulp);
451    }
452    return retval;
453}
454
455void
456XScreenSaverSuspend (Display *dpy, Bool suspend)
457{
458    XExtDisplayInfo *info = find_display (dpy);
459    xScreenSaverSuspendReq   *req;
460
461    ScreenSaverSimpleCheckExtension (dpy, info);
462
463    LockDisplay (dpy);
464    GetReq (ScreenSaverSuspend, req);
465    req->reqType = (CARD8) info->codes->major_opcode;
466    req->saverReqType = X_ScreenSaverSuspend;
467    req->suspend = (CARD32) suspend;
468    UnlockDisplay (dpy);
469    SyncHandle ();
470}
471