1 /*
2  *
3 Copyright (c) 1992  X Consortium
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in 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 
37 static XExtensionInfo _screen_saver_info_data;
38 static XExtensionInfo *screen_saver_info = &_screen_saver_info_data;
39 static 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 
46 static int close_display(
47     Display *		/* dpy */,
48     XExtCodes *		/* codes */
49 );
50 
51 static Bool wire_to_event(
52     Display *		/* dpy */,
53     XEvent *		/* re */,
54     xEvent *		/* event */
55 );
56 
57 static Status event_to_wire(
58     Display *		/* dpy */,
59     XEvent *		/* re */,
60     xEvent *		/* event */
61 );
62 
63 static /* 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 
77 static XEXT_GENERATE_FIND_DISPLAY (find_display, screen_saver_info,
78 				   screen_saver_extension_name,
79 				   &screen_saver_extension_hooks,
80 				   ScreenSaverNumberEvents, NULL)
81 
XEXT_GENERATE_CLOSE_DISPLAY(close_display,screen_saver_info)82 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, screen_saver_info)
83 
84 
85 static 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 
event_to_wire(Display * dpy,XEvent * re,xEvent * event)117 static 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 
XScreenSaverQueryExtension(Display * dpy,int * event_base_return,int * error_base_return)153 Bool 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 
XScreenSaverQueryVersion(Display * dpy,int * major_version_return,int * minor_version_return)170 Status 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 
XScreenSaverAllocInfo(void)199 XScreenSaverInfo *XScreenSaverAllocInfo (void)
200 {
201     return (XScreenSaverInfo *) Xmalloc (sizeof (XScreenSaverInfo));
202 }
203 
XScreenSaverQueryInfo(Display * dpy,Drawable drawable,XScreenSaverInfo * saver_info)204 Status 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 
XScreenSaverSelectInput(register Display * dpy,Drawable drawable,unsigned long mask)236 void 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 
256 static void
XScreenSaverProcessWindowAttributes(register Display * dpy,xChangeWindowAttributesReq * req,register unsigned long valuemask,register XSetWindowAttributes * attributes)257 XScreenSaverProcessWindowAttributes (
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 
XScreenSaverSetAttributes(Display * dpy,Drawable drawable,int x,int y,unsigned int width,unsigned int height,unsigned int border_width,int depth,unsigned int class,Visual * visual,unsigned long valuemask,XSetWindowAttributes * attributes)319 void 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 
XScreenSaverUnsetAttributes(register Display * dpy,Drawable drawable)364 void 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 
XScreenSaverRegister(Display * dpy,int screen,XID xid,Atom type)383 Status 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 
XScreenSaverUnregister(Display * dpy,int screen)404 Status 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 
XScreenSaverGetRegistered(Display * dpy,int screen,XID * xid,Atom * type)420 Status 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 
454 void
XScreenSaverSuspend(Display * dpy,Bool suspend)455 XScreenSaverSuspend (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