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: { 22267594505Smrg xRROutputChangeNotifyEvent *sawire = (xRROutputChangeNotifyEvent *) wire; 22367594505Smrg XRROutputChangeNotifyEvent *saevent = (XRROutputChangeNotifyEvent *) event; 22467594505Smrg sawire->window = saevent->window; 22567594505Smrg sawire->output = saevent->output; 22667594505Smrg sawire->crtc = saevent->crtc; 22767594505Smrg sawire->mode = saevent->mode; 22867594505Smrg sawire->rotation = saevent->rotation; 22967594505Smrg sawire->connection = saevent->connection; 23067594505Smrg sawire->subpixelOrder = saevent->subpixel_order; 231b042e37fSmrg return True; 232b042e37fSmrg } 233b042e37fSmrg case RRNotify_CrtcChange: { 23467594505Smrg xRRCrtcChangeNotifyEvent *sawire = (xRRCrtcChangeNotifyEvent *) wire; 23567594505Smrg XRRCrtcChangeNotifyEvent *saevent = (XRRCrtcChangeNotifyEvent *) event; 23667594505Smrg sawire->window = saevent->window; 23767594505Smrg sawire->crtc = saevent->crtc; 23867594505Smrg sawire->mode = saevent->mode; 23967594505Smrg sawire->rotation = saevent->rotation; 24067594505Smrg sawire->x = saevent->x; 24167594505Smrg sawire->y = saevent->y; 24267594505Smrg sawire->width = saevent->width; 24367594505Smrg sawire->height = saevent->height; 244b042e37fSmrg return True; 245b042e37fSmrg } 246b042e37fSmrg case RRNotify_OutputProperty: { 24767594505Smrg xRROutputPropertyNotifyEvent *sawire = (xRROutputPropertyNotifyEvent *) wire; 24867594505Smrg XRROutputPropertyNotifyEvent *saevent = (XRROutputPropertyNotifyEvent *) event; 24967594505Smrg sawire->window = saevent->window; 25067594505Smrg sawire->output = saevent->output; 25167594505Smrg sawire->atom = saevent->property; 25267594505Smrg sawire->timestamp = saevent->timestamp; 25367594505Smrg sawire->state = saevent->state; 254b042e37fSmrg return True; 255b042e37fSmrg } 2560597fb56Smrg case RRNotify_ProviderChange: { 25767594505Smrg xRRProviderChangeNotifyEvent *sawire = (xRRProviderChangeNotifyEvent *) wire; 25867594505Smrg XRRProviderChangeNotifyEvent *saevent = (XRRProviderChangeNotifyEvent *) event; 25967594505Smrg sawire->window = saevent->window; 26067594505Smrg sawire->provider = saevent->provider; 2610597fb56Smrg return True; 2620597fb56Smrg } 2630597fb56Smrg case RRNotify_ProviderProperty: { 26467594505Smrg xRRProviderPropertyNotifyEvent *sawire = (xRRProviderPropertyNotifyEvent *) wire; 26567594505Smrg XRRProviderPropertyNotifyEvent *saevent = (XRRProviderPropertyNotifyEvent *) event; 26667594505Smrg sawire->window = saevent->window; 26767594505Smrg sawire->provider = saevent->provider; 26867594505Smrg sawire->atom = saevent->property; 26967594505Smrg sawire->timestamp = saevent->timestamp; 27067594505Smrg sawire->state = saevent->state; 2710597fb56Smrg return True; 2720597fb56Smrg } 2730597fb56Smrg case RRNotify_ResourceChange: { 27467594505Smrg xRRResourceChangeNotifyEvent *sawire = (xRRResourceChangeNotifyEvent *) wire; 27567594505Smrg XRRResourceChangeNotifyEvent *saevent = (XRRResourceChangeNotifyEvent *) event; 27667594505Smrg sawire->window = saevent->window; 27767594505Smrg sawire->timestamp = saevent->timestamp; 2780597fb56Smrg return True; 2790597fb56Smrg } 280b042e37fSmrg } 281b042e37fSmrg } 282b042e37fSmrg } 283b042e37fSmrg return False; 284b042e37fSmrg} 285b042e37fSmrg 2868c4a8e55Smrg_X_HIDDEN XExtDisplayInfo * 287b042e37fSmrgXRRFindDisplay (Display *dpy) 288b042e37fSmrg{ 2898d0bc965Smrg XExtDisplayInfo *dpyinfo = XextFindDisplay (&XRRExtensionInfo, dpy); 290b042e37fSmrg 291b042e37fSmrg if (!dpyinfo) { 2928d0bc965Smrg XRandRInfo *xrri; 2938d0bc965Smrg int numscreens; 2948d0bc965Smrg 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); 3038d0bc965Smrg for (int 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 XExtDisplayInfo *info = XRRFindDisplay (dpy); 315b042e37fSmrg 316b042e37fSmrg LockDisplay(dpy); 317b042e37fSmrg /* 318b042e37fSmrg * free cached data 319b042e37fSmrg */ 320b042e37fSmrg if (XextHasExtension(info)) { 3218d0bc965Smrg XRandRInfo *xrri = (XRandRInfo *) info->data; 322b042e37fSmrg if (xrri) { 3238d0bc965Smrg XRRScreenConfiguration **configs = xrri->config; 324b042e37fSmrg 3258d0bc965Smrg for (int i = 0; i < ScreenCount(dpy); i++) { 326b042e37fSmrg if (configs[i] != NULL) XFree (configs[i]); 327b042e37fSmrg } 328b042e37fSmrg XFree (xrri); 329b042e37fSmrg } 330b042e37fSmrg } 331b042e37fSmrg UnlockDisplay(dpy); 332b042e37fSmrg return XextRemoveDisplay (&XRRExtensionInfo, dpy); 333b042e37fSmrg} 334b042e37fSmrg 335b042e37fSmrgint XRRRootToScreen(Display *dpy, Window root) 336b042e37fSmrg{ 3378d0bc965Smrg for (int snum = 0; snum < ScreenCount(dpy); snum++) { 338b042e37fSmrg if (RootWindow(dpy, snum) == root) return snum; 339b042e37fSmrg } 340b042e37fSmrg return -1; 341b042e37fSmrg} 342b042e37fSmrg 343b042e37fSmrg 3448c4a8e55SmrgBool XRRQueryExtension (Display *dpy, 3458c4a8e55Smrg int *event_base_return, 3468c4a8e55Smrg int *error_base_return) 347b042e37fSmrg{ 348b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay (dpy); 349b042e37fSmrg 350b042e37fSmrg if (XextHasExtension(info)) { 3518c4a8e55Smrg *event_base_return = info->codes->first_event; 3528c4a8e55Smrg *error_base_return = info->codes->first_error; 353b042e37fSmrg return True; 354b042e37fSmrg } else { 355b042e37fSmrg return False; 356b042e37fSmrg } 357b042e37fSmrg} 358b042e37fSmrg 3598c4a8e55Smrg_X_HIDDEN Bool 360b042e37fSmrg_XRRHasRates (int major, int minor) 361b042e37fSmrg{ 362b042e37fSmrg return major > 1 || (major == 1 && minor >= 1); 363b042e37fSmrg} 364b042e37fSmrg 365b042e37fSmrgStatus XRRQueryVersion (Display *dpy, 366b042e37fSmrg int *major_versionp, 367b042e37fSmrg int *minor_versionp) 368b042e37fSmrg{ 369b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay (dpy); 370b042e37fSmrg xRRQueryVersionReply rep; 371b042e37fSmrg xRRQueryVersionReq *req; 372b042e37fSmrg XRandRInfo *xrri; 373b042e37fSmrg 374b042e37fSmrg RRCheckExtension (dpy, info, 0); 375b042e37fSmrg 376b042e37fSmrg xrri = (XRandRInfo *) info->data; 377b042e37fSmrg 3780597fb56Smrg /* 379b042e37fSmrg * only get the version information from the server if we don't have it already 380b042e37fSmrg */ 381b042e37fSmrg if (xrri->major_version == -1) { 382b042e37fSmrg LockDisplay (dpy); 383b042e37fSmrg GetReq (RRQueryVersion, req); 384b042e37fSmrg req->reqType = info->codes->major_opcode; 385b042e37fSmrg req->randrReqType = X_RRQueryVersion; 386b042e37fSmrg req->majorVersion = RANDR_MAJOR; 387b042e37fSmrg req->minorVersion = RANDR_MINOR; 388b042e37fSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { 389b042e37fSmrg UnlockDisplay (dpy); 390b042e37fSmrg SyncHandle (); 391b042e37fSmrg return 0; 392b042e37fSmrg } 393b042e37fSmrg xrri->major_version = rep.majorVersion; 394b042e37fSmrg xrri->minor_version = rep.minorVersion; 395b042e37fSmrg xrri->has_rates = _XRRHasRates (xrri->major_version, xrri->minor_version); 396b042e37fSmrg UnlockDisplay (dpy); 397b042e37fSmrg SyncHandle (); 398b042e37fSmrg } 399b042e37fSmrg *major_versionp = xrri->major_version; 400b042e37fSmrg *minor_versionp = xrri->minor_version; 401b042e37fSmrg return 1; 402b042e37fSmrg} 403b042e37fSmrg 4048c4a8e55Smrg_X_HIDDEN Bool 405b042e37fSmrg_XRRVersionHandler (Display *dpy, 406b042e37fSmrg xReply *rep, 407b042e37fSmrg char *buf, 408b042e37fSmrg int len, 409b042e37fSmrg XPointer data) 410b042e37fSmrg{ 411b042e37fSmrg xRRQueryVersionReply replbuf; 412b042e37fSmrg xRRQueryVersionReply *repl; 413b042e37fSmrg _XRRVersionState *state = (_XRRVersionState *) data; 414b042e37fSmrg 415b042e37fSmrg if (dpy->last_request_read != state->version_seq) 416b042e37fSmrg return False; 417b042e37fSmrg if (rep->generic.type == X_Error) 418b042e37fSmrg { 419b042e37fSmrg state->error = True; 420b042e37fSmrg return False; 421b042e37fSmrg } 422b042e37fSmrg repl = (xRRQueryVersionReply *) 423b042e37fSmrg _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, 424b042e37fSmrg (SIZEOF(xRRQueryVersionReply) - SIZEOF(xReply)) >> 2, 425b042e37fSmrg True); 426b042e37fSmrg state->major_version = repl->majorVersion; 427b042e37fSmrg state->minor_version = repl->minorVersion; 428b042e37fSmrg return True; 429b042e37fSmrg} 430b042e37fSmrg 4310597fb56Smrg/* 432b042e37fSmrg * in protocol version 0.1, routine added to allow selecting for new events. 433b042e37fSmrg */ 434b042e37fSmrg 435b042e37fSmrgvoid XRRSelectInput (Display *dpy, Window window, int mask) 436b042e37fSmrg{ 437b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay (dpy); 438b042e37fSmrg xRRSelectInputReq *req; 439b042e37fSmrg 440b042e37fSmrg RRSimpleCheckExtension (dpy, info); 441b042e37fSmrg 442b042e37fSmrg LockDisplay (dpy); 443b042e37fSmrg GetReq (RRSelectInput, req); 444b042e37fSmrg req->reqType = info->codes->major_opcode; 445b042e37fSmrg req->randrReqType = X_RRSelectInput; 446b042e37fSmrg req->window = window; 447b042e37fSmrg req->enable = 0; 448b042e37fSmrg if (mask) req->enable = mask; 449b042e37fSmrg UnlockDisplay (dpy); 450b042e37fSmrg SyncHandle (); 451b042e37fSmrg return; 452b042e37fSmrg} 453b042e37fSmrg 454b042e37fSmrgint XRRUpdateConfiguration(XEvent *event) 455b042e37fSmrg{ 456b042e37fSmrg XRRScreenChangeNotifyEvent *scevent; 457b042e37fSmrg XConfigureEvent *rcevent; 458b042e37fSmrg Display *dpy = event->xany.display; 459b042e37fSmrg XExtDisplayInfo *info; 460b042e37fSmrg XRandRInfo *xrri; 461b042e37fSmrg int snum; 462b042e37fSmrg 463b042e37fSmrg /* first, see if it is a vanilla configure notify event */ 464b042e37fSmrg if (event->type == ConfigureNotify) { 465b042e37fSmrg rcevent = (XConfigureEvent *) event; 466b042e37fSmrg snum = XRRRootToScreen(dpy, rcevent->window); 4678c4a8e55Smrg if (snum != -1) { 4688c4a8e55Smrg dpy->screens[snum].width = rcevent->width; 4698c4a8e55Smrg dpy->screens[snum].height = rcevent->height; 4708c4a8e55Smrg return 1; 4718c4a8e55Smrg } 472b042e37fSmrg } 473b042e37fSmrg 474b042e37fSmrg info = XRRFindDisplay(dpy); 475b042e37fSmrg RRCheckExtension (dpy, info, 0); 476b042e37fSmrg 477b042e37fSmrg switch (event->type - info->codes->first_event) { 478b042e37fSmrg case RRScreenChangeNotify: 479b042e37fSmrg scevent = (XRRScreenChangeNotifyEvent *) event; 4800597fb56Smrg snum = XRRRootToScreen(dpy, 481b042e37fSmrg ((XRRScreenChangeNotifyEvent *) event)->root); 482fc98c8e2Smrg if (snum < 0) 483fc98c8e2Smrg return 0; 484fc98c8e2Smrg 485b042e37fSmrg if (scevent->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 486b042e37fSmrg dpy->screens[snum].width = scevent->height; 487b042e37fSmrg dpy->screens[snum].height = scevent->width; 488b042e37fSmrg dpy->screens[snum].mwidth = scevent->mheight; 489b042e37fSmrg dpy->screens[snum].mheight = scevent->mwidth; 490b042e37fSmrg } else { 491b042e37fSmrg dpy->screens[snum].width = scevent->width; 492b042e37fSmrg dpy->screens[snum].height = scevent->height; 493b042e37fSmrg dpy->screens[snum].mwidth = scevent->mwidth; 494b042e37fSmrg dpy->screens[snum].mheight = scevent->mheight; 495b042e37fSmrg } 496b042e37fSmrg XRenderSetSubpixelOrder (dpy, snum, scevent->subpixel_order); 497b042e37fSmrg break; 498b042e37fSmrg default: 499b042e37fSmrg return 0; 500b042e37fSmrg } 501b042e37fSmrg xrri = (XRandRInfo *) info->data; 5020597fb56Smrg /* 5030597fb56Smrg * so the next time someone wants some data, it will be fetched; 5040597fb56Smrg * it might be better to force the round trip immediately, but 505b042e37fSmrg * I dislike pounding the server simultaneously when not necessary 506b042e37fSmrg */ 507b042e37fSmrg if (xrri->config[snum] != NULL) { 508b042e37fSmrg XFree (xrri->config[snum]); 509b042e37fSmrg xrri->config[snum] = NULL; 510b042e37fSmrg } 511b042e37fSmrg return 1; 512b042e37fSmrg} 513