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