Xrandr.c revision fc98c8e2
1b042e37fSmrg/* 2b042e37fSmrg * Copyright © 2000 Compaq Computer Corporation, Inc. 3b042e37fSmrg * Copyright © 2002 Hewlett Packard Company, Inc. 4b042e37fSmrg * 5b042e37fSmrg * Permission to use, copy, modify, distribute, and sell this software and its 6b042e37fSmrg * documentation for any purpose is hereby granted without fee, provided that 7b042e37fSmrg * the above copyright notice appear in all copies and that both that 8b042e37fSmrg * copyright notice and this permission notice appear in supporting 9b042e37fSmrg * documentation, and that the name of Compaq or HP not be used in advertising 10b042e37fSmrg * or publicity pertaining to distribution of the software without specific, 11b042e37fSmrg * written prior permission. HP makes no representations about the 12b042e37fSmrg * suitability of this software for any purpose. It is provided "as is" 13b042e37fSmrg * without express or implied warranty. 14b042e37fSmrg * 15b042e37fSmrg * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16b042e37fSmrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ 17b042e37fSmrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18b042e37fSmrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 190597fb56Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20b042e37fSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21b042e37fSmrg * 22b042e37fSmrg * Author: Jim Gettys, HP Labs, HP. 23b042e37fSmrg */ 24b042e37fSmrg 25b042e37fSmrg#ifdef HAVE_CONFIG_H 26b042e37fSmrg#include <config.h> 27b042e37fSmrg#endif 28b042e37fSmrg 29b042e37fSmrg#include <stdio.h> 30b042e37fSmrg#include <X11/Xlib.h> 31b042e37fSmrg/* we need to be able to manipulate the Display structure on events */ 32b042e37fSmrg#include <X11/Xlibint.h> 33b042e37fSmrg#include <X11/extensions/render.h> 34b042e37fSmrg#include <X11/extensions/Xrender.h> 35b042e37fSmrg#include "Xrandrint.h" 36b042e37fSmrg 378c4a8e55Smrgstatic XExtensionInfo XRRExtensionInfo; 388c4a8e55Smrg_X_HIDDEN char XRRExtensionName[] = RANDR_NAME; 39b042e37fSmrg 40b042e37fSmrgstatic Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire); 41b042e37fSmrgstatic Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire); 42b042e37fSmrg 43b042e37fSmrgstatic int 44b042e37fSmrgXRRCloseDisplay (Display *dpy, XExtCodes *codes); 45b042e37fSmrg 46b042e37fSmrgstatic /* const */ XExtensionHooks rr_extension_hooks = { 47b042e37fSmrg NULL, /* create_gc */ 48b042e37fSmrg NULL, /* copy_gc */ 49b042e37fSmrg NULL, /* flush_gc */ 50b042e37fSmrg NULL, /* free_gc */ 51b042e37fSmrg NULL, /* create_font */ 52b042e37fSmrg NULL, /* free_font */ 53b042e37fSmrg XRRCloseDisplay, /* close_display */ 54b042e37fSmrg XRRWireToEvent, /* wire_to_event */ 55b042e37fSmrg XRREventToWire, /* event_to_wire */ 56b042e37fSmrg NULL, /* error */ 57b042e37fSmrg NULL, /* error_string */ 58b042e37fSmrg}; 59b042e37fSmrg 60b042e37fSmrgstatic Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire) 61b042e37fSmrg{ 62b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 63b042e37fSmrg 64b042e37fSmrg RRCheckExtension(dpy, info, False); 65b042e37fSmrg 66b042e37fSmrg switch ((wire->u.u.type & 0x7F) - info->codes->first_event) 67b042e37fSmrg { 68b042e37fSmrg case RRScreenChangeNotify: { 69b042e37fSmrg XRRScreenChangeNotifyEvent *aevent= (XRRScreenChangeNotifyEvent *) event; 70b042e37fSmrg xRRScreenChangeNotifyEvent *awire = (xRRScreenChangeNotifyEvent *) wire; 71b042e37fSmrg aevent->type = awire->type & 0x7F; 72b042e37fSmrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 73b042e37fSmrg aevent->send_event = (awire->type & 0x80) != 0; 74b042e37fSmrg aevent->display = dpy; 75b042e37fSmrg aevent->window = awire->window; 76b042e37fSmrg aevent->root = awire->root; 77b042e37fSmrg aevent->timestamp = awire->timestamp; 78b042e37fSmrg aevent->config_timestamp = awire->configTimestamp; 79b042e37fSmrg aevent->size_index = awire->sizeID; 80b042e37fSmrg aevent->subpixel_order = awire->subpixelOrder; 81b042e37fSmrg aevent->rotation = awire->rotation; 82b042e37fSmrg aevent->width = awire->widthInPixels; 83b042e37fSmrg aevent->height = awire->heightInPixels; 84b042e37fSmrg aevent->mwidth = awire->widthInMillimeters; 85b042e37fSmrg aevent->mheight = awire->heightInMillimeters; 86b042e37fSmrg return True; 87b042e37fSmrg } 88b042e37fSmrg case RRNotify: { 898c4a8e55Smrg switch (wire->u.u.detail) { 90b042e37fSmrg case RRNotify_OutputChange: { 91b042e37fSmrg XRROutputChangeNotifyEvent *aevent = (XRROutputChangeNotifyEvent *) event; 92b042e37fSmrg xRROutputChangeNotifyEvent *awire = (xRROutputChangeNotifyEvent *) wire; 938c4a8e55Smrg aevent->type = awire->type & 0x7F; 948c4a8e55Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 958c4a8e55Smrg aevent->send_event = (awire->type & 0x80) != 0; 968c4a8e55Smrg aevent->display = dpy; 978c4a8e55Smrg aevent->window = awire->window; 988c4a8e55Smrg aevent->subtype = awire->subCode; 99b042e37fSmrg aevent->output = awire->output; 100b042e37fSmrg aevent->crtc = awire->crtc; 101b042e37fSmrg aevent->mode = awire->mode; 102b042e37fSmrg aevent->rotation = awire->rotation; 103b042e37fSmrg aevent->connection = awire->connection; 104b042e37fSmrg aevent->subpixel_order = awire->subpixelOrder; 105b042e37fSmrg return True; 106b042e37fSmrg } 107b042e37fSmrg case RRNotify_CrtcChange: { 108b042e37fSmrg XRRCrtcChangeNotifyEvent *aevent = (XRRCrtcChangeNotifyEvent *) event; 109b042e37fSmrg xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire; 1108c4a8e55Smrg aevent->type = awire->type & 0x7F; 1118c4a8e55Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 1128c4a8e55Smrg aevent->send_event = (awire->type & 0x80) != 0; 1138c4a8e55Smrg aevent->display = dpy; 1148c4a8e55Smrg aevent->window = awire->window; 1158c4a8e55Smrg aevent->subtype = awire->subCode; 116b042e37fSmrg aevent->crtc = awire->crtc; 117b042e37fSmrg aevent->mode = awire->mode; 118b042e37fSmrg aevent->rotation = awire->rotation; 119b042e37fSmrg aevent->x = awire->x; 120b042e37fSmrg aevent->y = awire->y; 121b042e37fSmrg aevent->width = awire->width; 122b042e37fSmrg aevent->height = awire->height; 123b042e37fSmrg return True; 124b042e37fSmrg } 125b042e37fSmrg case RRNotify_OutputProperty: { 126b042e37fSmrg XRROutputPropertyNotifyEvent *aevent = (XRROutputPropertyNotifyEvent *) event; 127b042e37fSmrg xRROutputPropertyNotifyEvent *awire = (xRROutputPropertyNotifyEvent *) wire; 1288c4a8e55Smrg aevent->type = awire->type & 0x7F; 1298c4a8e55Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 1308c4a8e55Smrg aevent->send_event = (awire->type & 0x80) != 0; 1318c4a8e55Smrg aevent->display = dpy; 1328c4a8e55Smrg aevent->window = awire->window; 1338c4a8e55Smrg aevent->subtype = awire->subCode; 134b042e37fSmrg aevent->output = awire->output; 135b042e37fSmrg aevent->property = awire->atom; 136b042e37fSmrg aevent->timestamp = awire->timestamp; 137b042e37fSmrg aevent->state = awire->state; 138b042e37fSmrg return True; 139b042e37fSmrg } 1400597fb56Smrg case RRNotify_ProviderChange: { 1410597fb56Smrg XRRProviderChangeNotifyEvent *aevent = (XRRProviderChangeNotifyEvent *) event; 1420597fb56Smrg xRRProviderChangeNotifyEvent *awire = (xRRProviderChangeNotifyEvent *) wire; 1430597fb56Smrg aevent->type = awire->type & 0x7F; 1440597fb56Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 1450597fb56Smrg aevent->send_event = (awire->type & 0x80) != 0; 1460597fb56Smrg aevent->display = dpy; 1470597fb56Smrg aevent->window = awire->window; 1480597fb56Smrg aevent->subtype = awire->subCode; 1490597fb56Smrg aevent->provider = awire->provider; 1500597fb56Smrg aevent->timestamp = awire->timestamp; 1510597fb56Smrg return True; 1520597fb56Smrg } 1530597fb56Smrg case RRNotify_ProviderProperty: { 1540597fb56Smrg XRRProviderPropertyNotifyEvent *aevent = (XRRProviderPropertyNotifyEvent *) event; 1550597fb56Smrg xRRProviderPropertyNotifyEvent *awire = (xRRProviderPropertyNotifyEvent *) wire; 1560597fb56Smrg aevent->type = awire->type & 0x7F; 1570597fb56Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 1580597fb56Smrg aevent->send_event = (awire->type & 0x80) != 0; 1590597fb56Smrg aevent->display = dpy; 1600597fb56Smrg aevent->window = awire->window; 1610597fb56Smrg aevent->subtype = awire->subCode; 1620597fb56Smrg aevent->provider = awire->provider; 1630597fb56Smrg aevent->property = awire->atom; 1640597fb56Smrg aevent->timestamp = awire->timestamp; 1650597fb56Smrg aevent->state = awire->state; 1660597fb56Smrg return True; 1670597fb56Smrg } 1680597fb56Smrg case RRNotify_ResourceChange: { 1690597fb56Smrg XRRResourceChangeNotifyEvent *aevent = (XRRResourceChangeNotifyEvent *) event; 1700597fb56Smrg xRRResourceChangeNotifyEvent *awire = (xRRResourceChangeNotifyEvent *) wire; 1710597fb56Smrg aevent->type = awire->type & 0x7F; 1720597fb56Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 1730597fb56Smrg aevent->send_event = (awire->type & 0x80) != 0; 1740597fb56Smrg aevent->display = dpy; 1750597fb56Smrg aevent->window = awire->window; 1760597fb56Smrg aevent->subtype = awire->subCode; 1770597fb56Smrg aevent->timestamp = awire->timestamp; 1780597fb56Smrg return True; 1790597fb56Smrg } 180b042e37fSmrg break; 181b042e37fSmrg } 182b042e37fSmrg } 183b042e37fSmrg } 184b042e37fSmrg 185b042e37fSmrg return False; 186b042e37fSmrg} 187b042e37fSmrg 188b042e37fSmrgstatic Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire) 189b042e37fSmrg{ 190b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 191b042e37fSmrg 192b042e37fSmrg RRCheckExtension(dpy, info, False); 193b042e37fSmrg 194b042e37fSmrg switch ((event->type & 0x7F) - info->codes->first_event) 195b042e37fSmrg { 196b042e37fSmrg case RRScreenChangeNotify: { 197b042e37fSmrg xRRScreenChangeNotifyEvent *awire = (xRRScreenChangeNotifyEvent *) wire; 198b042e37fSmrg XRRScreenChangeNotifyEvent *aevent = (XRRScreenChangeNotifyEvent *) event; 199b042e37fSmrg awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); 200b042e37fSmrg awire->rotation = (CARD8) aevent->rotation; 201b042e37fSmrg awire->sequenceNumber = aevent->serial & 0xFFFF; 202b042e37fSmrg awire->timestamp = aevent->timestamp; 203b042e37fSmrg awire->configTimestamp = aevent->config_timestamp; 204b042e37fSmrg awire->root = aevent->root; 205b042e37fSmrg awire->window = aevent->window; 206b042e37fSmrg awire->sizeID = aevent->size_index; 207b042e37fSmrg awire->subpixelOrder = aevent->subpixel_order; 208b042e37fSmrg awire->widthInPixels = aevent->width; 209b042e37fSmrg awire->heightInPixels = aevent->height; 210b042e37fSmrg awire->widthInMillimeters = aevent->mwidth; 211b042e37fSmrg awire->heightInMillimeters = aevent->mheight; 212b042e37fSmrg return True; 213b042e37fSmrg } 214b042e37fSmrg case RRNotify: { 215b042e37fSmrg xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire; 216b042e37fSmrg XRRNotifyEvent *aevent = (XRRNotifyEvent *) event; 217b042e37fSmrg awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); 218b042e37fSmrg awire->sequenceNumber = aevent->serial & 0xFFFF; 219b042e37fSmrg awire->subCode = aevent->subtype; 220b042e37fSmrg switch (aevent->subtype) { 221b042e37fSmrg case RRNotify_OutputChange: { 222b042e37fSmrg xRROutputChangeNotifyEvent *awire = (xRROutputChangeNotifyEvent *) wire; 223b042e37fSmrg XRROutputChangeNotifyEvent *aevent = (XRROutputChangeNotifyEvent *) event; 2248c4a8e55Smrg awire->window = aevent->window; 225b042e37fSmrg awire->output = aevent->output; 226b042e37fSmrg awire->crtc = aevent->crtc; 227b042e37fSmrg awire->mode = aevent->mode; 228b042e37fSmrg awire->rotation = aevent->rotation; 229b042e37fSmrg awire->connection = aevent->connection; 230b042e37fSmrg awire->subpixelOrder = aevent->subpixel_order; 231b042e37fSmrg return True; 232b042e37fSmrg } 233b042e37fSmrg case RRNotify_CrtcChange: { 234b042e37fSmrg xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire; 235b042e37fSmrg XRRCrtcChangeNotifyEvent *aevent = (XRRCrtcChangeNotifyEvent *) event; 2368c4a8e55Smrg awire->window = aevent->window; 237b042e37fSmrg awire->crtc = aevent->crtc; 238b042e37fSmrg awire->mode = aevent->mode; 239b042e37fSmrg awire->rotation = aevent->rotation; 240b042e37fSmrg awire->x = aevent->x; 241b042e37fSmrg awire->y = aevent->y; 242b042e37fSmrg awire->width = aevent->width; 243b042e37fSmrg awire->height = aevent->height; 244b042e37fSmrg return True; 245b042e37fSmrg } 246b042e37fSmrg case RRNotify_OutputProperty: { 247b042e37fSmrg xRROutputPropertyNotifyEvent *awire = (xRROutputPropertyNotifyEvent *) wire; 248b042e37fSmrg XRROutputPropertyNotifyEvent *aevent = (XRROutputPropertyNotifyEvent *) event; 2498c4a8e55Smrg awire->window = aevent->window; 250b042e37fSmrg awire->output = aevent->output; 251b042e37fSmrg awire->atom = aevent->property; 252b042e37fSmrg awire->timestamp = aevent->timestamp; 253b042e37fSmrg awire->state = aevent->state; 254b042e37fSmrg return True; 255b042e37fSmrg } 2560597fb56Smrg case RRNotify_ProviderChange: { 2570597fb56Smrg xRRProviderChangeNotifyEvent *awire = (xRRProviderChangeNotifyEvent *) wire; 2580597fb56Smrg XRRProviderChangeNotifyEvent *aevent = (XRRProviderChangeNotifyEvent *) event; 2590597fb56Smrg awire->window = aevent->window; 2600597fb56Smrg awire->provider = aevent->provider; 2610597fb56Smrg return True; 2620597fb56Smrg } 2630597fb56Smrg case RRNotify_ProviderProperty: { 2640597fb56Smrg xRRProviderPropertyNotifyEvent *awire = (xRRProviderPropertyNotifyEvent *) wire; 2650597fb56Smrg XRRProviderPropertyNotifyEvent *aevent = (XRRProviderPropertyNotifyEvent *) event; 2660597fb56Smrg awire->window = aevent->window; 2670597fb56Smrg awire->provider = aevent->provider; 2680597fb56Smrg awire->atom = aevent->property; 2690597fb56Smrg awire->timestamp = aevent->timestamp; 2700597fb56Smrg awire->state = aevent->state; 2710597fb56Smrg return True; 2720597fb56Smrg } 2730597fb56Smrg case RRNotify_ResourceChange: { 2740597fb56Smrg xRRResourceChangeNotifyEvent *awire = (xRRResourceChangeNotifyEvent *) wire; 2750597fb56Smrg XRRResourceChangeNotifyEvent *aevent = (XRRResourceChangeNotifyEvent *) event; 2760597fb56Smrg awire->window = aevent->window; 2770597fb56Smrg awire->timestamp = aevent->timestamp; 2780597fb56Smrg return True; 2790597fb56Smrg } 280b042e37fSmrg } 281b042e37fSmrg } 282b042e37fSmrg } 283b042e37fSmrg return False; 284b042e37fSmrg} 285b042e37fSmrg 2868c4a8e55Smrg_X_HIDDEN XExtDisplayInfo * 287b042e37fSmrgXRRFindDisplay (Display *dpy) 288b042e37fSmrg{ 289b042e37fSmrg XExtDisplayInfo *dpyinfo; 290b042e37fSmrg XRandRInfo *xrri; 291b042e37fSmrg int i, numscreens; 292b042e37fSmrg 293b042e37fSmrg dpyinfo = XextFindDisplay (&XRRExtensionInfo, dpy); 294b042e37fSmrg if (!dpyinfo) { 2950597fb56Smrg dpyinfo = XextAddDisplay (&XRRExtensionInfo, dpy, 296b042e37fSmrg XRRExtensionName, 297b042e37fSmrg &rr_extension_hooks, 2988c4a8e55Smrg RRNumberEvents, NULL); 299b042e37fSmrg numscreens = ScreenCount(dpy); 3000597fb56Smrg xrri = Xmalloc (sizeof(XRandRInfo) + 301b042e37fSmrg sizeof(char *) * numscreens); 302b042e37fSmrg xrri->config = (XRRScreenConfiguration **)(xrri + 1); 3030597fb56Smrg for(i = 0; i < numscreens; i++) 304b042e37fSmrg xrri->config[i] = NULL; 305b042e37fSmrg xrri->major_version = -1; 306b042e37fSmrg dpyinfo->data = (char *) xrri; 307b042e37fSmrg } 308b042e37fSmrg return dpyinfo; 309b042e37fSmrg} 310b042e37fSmrg 311b042e37fSmrgstatic int 312b042e37fSmrgXRRCloseDisplay (Display *dpy, XExtCodes *codes) 313b042e37fSmrg{ 314b042e37fSmrg int i; 315b042e37fSmrg XRRScreenConfiguration **configs; 316b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay (dpy); 317b042e37fSmrg XRandRInfo *xrri; 318b042e37fSmrg 319b042e37fSmrg LockDisplay(dpy); 320b042e37fSmrg /* 321b042e37fSmrg * free cached data 322b042e37fSmrg */ 323b042e37fSmrg if (XextHasExtension(info)) { 324b042e37fSmrg xrri = (XRandRInfo *) info->data; 325b042e37fSmrg if (xrri) { 326b042e37fSmrg configs = xrri->config; 327b042e37fSmrg 328b042e37fSmrg for (i = 0; i < ScreenCount(dpy); i++) { 329b042e37fSmrg if (configs[i] != NULL) XFree (configs[i]); 330b042e37fSmrg } 331b042e37fSmrg XFree (xrri); 332b042e37fSmrg } 333b042e37fSmrg } 334b042e37fSmrg UnlockDisplay(dpy); 335b042e37fSmrg return XextRemoveDisplay (&XRRExtensionInfo, dpy); 336b042e37fSmrg} 337b042e37fSmrg 338b042e37fSmrgint XRRRootToScreen(Display *dpy, Window root) 339b042e37fSmrg{ 340b042e37fSmrg int snum; 341b042e37fSmrg for (snum = 0; snum < ScreenCount(dpy); snum++) { 342b042e37fSmrg if (RootWindow(dpy, snum) == root) return snum; 343b042e37fSmrg } 344b042e37fSmrg return -1; 345b042e37fSmrg} 346b042e37fSmrg 347b042e37fSmrg 3488c4a8e55SmrgBool XRRQueryExtension (Display *dpy, 3498c4a8e55Smrg int *event_base_return, 3508c4a8e55Smrg int *error_base_return) 351b042e37fSmrg{ 352b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay (dpy); 353b042e37fSmrg 354b042e37fSmrg if (XextHasExtension(info)) { 3558c4a8e55Smrg *event_base_return = info->codes->first_event; 3568c4a8e55Smrg *error_base_return = info->codes->first_error; 357b042e37fSmrg return True; 358b042e37fSmrg } else { 359b042e37fSmrg return False; 360b042e37fSmrg } 361b042e37fSmrg} 362b042e37fSmrg 3638c4a8e55Smrg_X_HIDDEN Bool 364b042e37fSmrg_XRRHasRates (int major, int minor) 365b042e37fSmrg{ 366b042e37fSmrg return major > 1 || (major == 1 && minor >= 1); 367b042e37fSmrg} 368b042e37fSmrg 369b042e37fSmrgStatus XRRQueryVersion (Display *dpy, 370b042e37fSmrg int *major_versionp, 371b042e37fSmrg int *minor_versionp) 372b042e37fSmrg{ 373b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay (dpy); 374b042e37fSmrg xRRQueryVersionReply rep; 375b042e37fSmrg xRRQueryVersionReq *req; 376b042e37fSmrg XRandRInfo *xrri; 377b042e37fSmrg 378b042e37fSmrg RRCheckExtension (dpy, info, 0); 379b042e37fSmrg 380b042e37fSmrg xrri = (XRandRInfo *) info->data; 381b042e37fSmrg 3820597fb56Smrg /* 383b042e37fSmrg * only get the version information from the server if we don't have it already 384b042e37fSmrg */ 385b042e37fSmrg if (xrri->major_version == -1) { 386b042e37fSmrg LockDisplay (dpy); 387b042e37fSmrg GetReq (RRQueryVersion, req); 388b042e37fSmrg req->reqType = info->codes->major_opcode; 389b042e37fSmrg req->randrReqType = X_RRQueryVersion; 390b042e37fSmrg req->majorVersion = RANDR_MAJOR; 391b042e37fSmrg req->minorVersion = RANDR_MINOR; 392b042e37fSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { 393b042e37fSmrg UnlockDisplay (dpy); 394b042e37fSmrg SyncHandle (); 395b042e37fSmrg return 0; 396b042e37fSmrg } 397b042e37fSmrg xrri->major_version = rep.majorVersion; 398b042e37fSmrg xrri->minor_version = rep.minorVersion; 399b042e37fSmrg xrri->has_rates = _XRRHasRates (xrri->major_version, xrri->minor_version); 400b042e37fSmrg UnlockDisplay (dpy); 401b042e37fSmrg SyncHandle (); 402b042e37fSmrg } 403b042e37fSmrg *major_versionp = xrri->major_version; 404b042e37fSmrg *minor_versionp = xrri->minor_version; 405b042e37fSmrg return 1; 406b042e37fSmrg} 407b042e37fSmrg 4088c4a8e55Smrg_X_HIDDEN Bool 409b042e37fSmrg_XRRVersionHandler (Display *dpy, 410b042e37fSmrg xReply *rep, 411b042e37fSmrg char *buf, 412b042e37fSmrg int len, 413b042e37fSmrg XPointer data) 414b042e37fSmrg{ 415b042e37fSmrg xRRQueryVersionReply replbuf; 416b042e37fSmrg xRRQueryVersionReply *repl; 417b042e37fSmrg _XRRVersionState *state = (_XRRVersionState *) data; 418b042e37fSmrg 419b042e37fSmrg if (dpy->last_request_read != state->version_seq) 420b042e37fSmrg return False; 421b042e37fSmrg if (rep->generic.type == X_Error) 422b042e37fSmrg { 423b042e37fSmrg state->error = True; 424b042e37fSmrg return False; 425b042e37fSmrg } 426b042e37fSmrg repl = (xRRQueryVersionReply *) 427b042e37fSmrg _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, 428b042e37fSmrg (SIZEOF(xRRQueryVersionReply) - SIZEOF(xReply)) >> 2, 429b042e37fSmrg True); 430b042e37fSmrg state->major_version = repl->majorVersion; 431b042e37fSmrg state->minor_version = repl->minorVersion; 432b042e37fSmrg return True; 433b042e37fSmrg} 434b042e37fSmrg 4350597fb56Smrg/* 436b042e37fSmrg * in protocol version 0.1, routine added to allow selecting for new events. 437b042e37fSmrg */ 438b042e37fSmrg 439b042e37fSmrgvoid XRRSelectInput (Display *dpy, Window window, int mask) 440b042e37fSmrg{ 441b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay (dpy); 442b042e37fSmrg xRRSelectInputReq *req; 443b042e37fSmrg 444b042e37fSmrg RRSimpleCheckExtension (dpy, info); 445b042e37fSmrg 446b042e37fSmrg LockDisplay (dpy); 447b042e37fSmrg GetReq (RRSelectInput, req); 448b042e37fSmrg req->reqType = info->codes->major_opcode; 449b042e37fSmrg req->randrReqType = X_RRSelectInput; 450b042e37fSmrg req->window = window; 451b042e37fSmrg req->enable = 0; 452b042e37fSmrg if (mask) req->enable = mask; 453b042e37fSmrg UnlockDisplay (dpy); 454b042e37fSmrg SyncHandle (); 455b042e37fSmrg return; 456b042e37fSmrg} 457b042e37fSmrg 458b042e37fSmrgint XRRUpdateConfiguration(XEvent *event) 459b042e37fSmrg{ 460b042e37fSmrg XRRScreenChangeNotifyEvent *scevent; 461b042e37fSmrg XConfigureEvent *rcevent; 462b042e37fSmrg Display *dpy = event->xany.display; 463b042e37fSmrg XExtDisplayInfo *info; 464b042e37fSmrg XRandRInfo *xrri; 465b042e37fSmrg int snum; 466b042e37fSmrg 467b042e37fSmrg /* first, see if it is a vanilla configure notify event */ 468b042e37fSmrg if (event->type == ConfigureNotify) { 469b042e37fSmrg rcevent = (XConfigureEvent *) event; 470b042e37fSmrg snum = XRRRootToScreen(dpy, rcevent->window); 4718c4a8e55Smrg if (snum != -1) { 4728c4a8e55Smrg dpy->screens[snum].width = rcevent->width; 4738c4a8e55Smrg dpy->screens[snum].height = rcevent->height; 4748c4a8e55Smrg return 1; 4758c4a8e55Smrg } 476b042e37fSmrg } 477b042e37fSmrg 478b042e37fSmrg info = XRRFindDisplay(dpy); 479b042e37fSmrg RRCheckExtension (dpy, info, 0); 480b042e37fSmrg 481b042e37fSmrg switch (event->type - info->codes->first_event) { 482b042e37fSmrg case RRScreenChangeNotify: 483b042e37fSmrg scevent = (XRRScreenChangeNotifyEvent *) event; 4840597fb56Smrg snum = XRRRootToScreen(dpy, 485b042e37fSmrg ((XRRScreenChangeNotifyEvent *) event)->root); 486fc98c8e2Smrg if (snum < 0) 487fc98c8e2Smrg return 0; 488fc98c8e2Smrg 489b042e37fSmrg if (scevent->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 490b042e37fSmrg dpy->screens[snum].width = scevent->height; 491b042e37fSmrg dpy->screens[snum].height = scevent->width; 492b042e37fSmrg dpy->screens[snum].mwidth = scevent->mheight; 493b042e37fSmrg dpy->screens[snum].mheight = scevent->mwidth; 494b042e37fSmrg } else { 495b042e37fSmrg dpy->screens[snum].width = scevent->width; 496b042e37fSmrg dpy->screens[snum].height = scevent->height; 497b042e37fSmrg dpy->screens[snum].mwidth = scevent->mwidth; 498b042e37fSmrg dpy->screens[snum].mheight = scevent->mheight; 499b042e37fSmrg } 500b042e37fSmrg XRenderSetSubpixelOrder (dpy, snum, scevent->subpixel_order); 501b042e37fSmrg break; 502b042e37fSmrg default: 503b042e37fSmrg return 0; 504b042e37fSmrg } 505b042e37fSmrg xrri = (XRandRInfo *) info->data; 5060597fb56Smrg /* 5070597fb56Smrg * so the next time someone wants some data, it will be fetched; 5080597fb56Smrg * it might be better to force the round trip immediately, but 509b042e37fSmrg * I dislike pounding the server simultaneously when not necessary 510b042e37fSmrg */ 511b042e37fSmrg if (xrri->config[snum] != NULL) { 512b042e37fSmrg XFree (xrri->config[snum]); 513b042e37fSmrg xrri->config[snum] = NULL; 514b042e37fSmrg } 515b042e37fSmrg return 1; 516b042e37fSmrg} 517