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