mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-12 14:20:54 -04:00
733 lines
20 KiB
C
733 lines
20 KiB
C
/*
|
|
* $XFree86: xc/lib/Xrandr/Xrandr.c,v 1.14 2003/05/27 22:26:42 tsi Exp $
|
|
*
|
|
* Copyright © 2000 Compaq Computer Corporation, Inc.
|
|
* Copyright © 2002 Hewlett Packard Company, Inc.
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Compaq or HP not be used in advertising
|
|
* or publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. HP makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*
|
|
* HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ
|
|
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Author: Jim Gettys, HP Labs, HP.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <X11/Xlib.h>
|
|
/* we need to be able to manipulate the Display structure on events */
|
|
#include <X11/Xlibint.h>
|
|
#include <X11/extensions/render.h>
|
|
#include <X11/extensions/Xrender.h>
|
|
#include "Xrandrint.h"
|
|
|
|
XExtensionInfo XRRExtensionInfo;
|
|
char XRRExtensionName[] = RANDR_NAME;
|
|
|
|
static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire);
|
|
static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire);
|
|
|
|
static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window);
|
|
|
|
static int
|
|
XRRCloseDisplay (Display *dpy, XExtCodes *codes);
|
|
|
|
static /* const */ XExtensionHooks rr_extension_hooks = {
|
|
NULL, /* create_gc */
|
|
NULL, /* copy_gc */
|
|
NULL, /* flush_gc */
|
|
NULL, /* free_gc */
|
|
NULL, /* create_font */
|
|
NULL, /* free_font */
|
|
XRRCloseDisplay, /* close_display */
|
|
XRRWireToEvent, /* wire_to_event */
|
|
XRREventToWire, /* event_to_wire */
|
|
NULL, /* error */
|
|
NULL, /* error_string */
|
|
};
|
|
|
|
static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay(dpy);
|
|
XRRScreenChangeNotifyEvent *aevent;
|
|
xRRScreenChangeNotifyEvent *awire;
|
|
|
|
RRCheckExtension(dpy, info, False);
|
|
|
|
switch ((wire->u.u.type & 0x7F) - info->codes->first_event)
|
|
{
|
|
case RRScreenChangeNotify:
|
|
awire = (xRRScreenChangeNotifyEvent *) wire;
|
|
aevent = (XRRScreenChangeNotifyEvent *) event;
|
|
aevent->type = awire->type & 0x7F;
|
|
aevent->serial = _XSetLastRequestRead(dpy,
|
|
(xGenericReply *) wire);
|
|
aevent->send_event = (awire->type & 0x80) != 0;
|
|
aevent->display = dpy;
|
|
aevent->window = awire->window;
|
|
aevent->root = awire->root;
|
|
aevent->timestamp = awire->timestamp;
|
|
aevent->config_timestamp = awire->configTimestamp;
|
|
aevent->size_index = awire->sizeID;
|
|
aevent->subpixel_order = awire->subpixelOrder;
|
|
aevent->rotation = awire->rotation;
|
|
aevent->width = awire->widthInPixels;
|
|
aevent->height = awire->heightInPixels;
|
|
aevent->mwidth = awire->widthInMillimeters;
|
|
aevent->mheight = awire->heightInMillimeters;
|
|
return True;
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay(dpy);
|
|
XRRScreenChangeNotifyEvent *aevent;
|
|
xRRScreenChangeNotifyEvent *awire;
|
|
|
|
RRCheckExtension(dpy, info, False);
|
|
|
|
switch ((event->type & 0x7F) - info->codes->first_event)
|
|
{
|
|
case RRScreenChangeNotify:
|
|
awire = (xRRScreenChangeNotifyEvent *) wire;
|
|
aevent = (XRRScreenChangeNotifyEvent *) event;
|
|
awire->type = aevent->type | (aevent->send_event ? 0x80 : 0);
|
|
awire->rotation = (CARD8) aevent->rotation;
|
|
awire->sequenceNumber = aevent->serial & 0xFFFF;
|
|
awire->timestamp = aevent->timestamp;
|
|
awire->configTimestamp = aevent->config_timestamp;
|
|
awire->root = aevent->root;
|
|
awire->window = aevent->window;
|
|
awire->sizeID = aevent->size_index;
|
|
awire->subpixelOrder = aevent->subpixel_order;
|
|
awire->widthInPixels = aevent->width;
|
|
awire->heightInPixels = aevent->height;
|
|
awire->widthInMillimeters = aevent->mwidth;
|
|
awire->heightInMillimeters = aevent->mheight;
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
XExtDisplayInfo *
|
|
XRRFindDisplay (Display *dpy)
|
|
{
|
|
XExtDisplayInfo *dpyinfo;
|
|
XRandRInfo *xrri;
|
|
int i, numscreens;
|
|
|
|
dpyinfo = XextFindDisplay (&XRRExtensionInfo, dpy);
|
|
if (!dpyinfo) {
|
|
dpyinfo = XextAddDisplay (&XRRExtensionInfo, dpy,
|
|
XRRExtensionName,
|
|
&rr_extension_hooks,
|
|
RRNumberEvents, 0);
|
|
numscreens = ScreenCount(dpy);
|
|
xrri = Xmalloc (sizeof(XRandRInfo) +
|
|
sizeof(char *) * numscreens);
|
|
xrri->config = (XRRScreenConfiguration **)(xrri + 1);
|
|
for(i = 0; i < numscreens; i++)
|
|
xrri->config[i] = NULL;
|
|
xrri->major_version = -1;
|
|
dpyinfo->data = (char *) xrri;
|
|
}
|
|
return dpyinfo;
|
|
}
|
|
|
|
static int
|
|
XRRCloseDisplay (Display *dpy, XExtCodes *codes)
|
|
{
|
|
int i;
|
|
XRRScreenConfiguration **configs;
|
|
XExtDisplayInfo *info = XRRFindDisplay (dpy);
|
|
XRandRInfo *xrri;
|
|
|
|
LockDisplay(dpy);
|
|
/*
|
|
* free cached data
|
|
*/
|
|
if (XextHasExtension(info)) {
|
|
xrri = (XRandRInfo *) info->data;
|
|
if (xrri) {
|
|
configs = xrri->config;
|
|
|
|
for (i = 0; i < ScreenCount(dpy); i++) {
|
|
if (configs[i] != NULL) XFree (configs[i]);
|
|
}
|
|
XFree (xrri);
|
|
}
|
|
}
|
|
UnlockDisplay(dpy);
|
|
return XextRemoveDisplay (&XRRExtensionInfo, dpy);
|
|
}
|
|
|
|
|
|
Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation)
|
|
{
|
|
*current_rotation = config->current_rotation;
|
|
return config->rotations;
|
|
}
|
|
|
|
XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes)
|
|
{
|
|
*nsizes = config->nsizes;
|
|
return config->sizes;
|
|
}
|
|
|
|
short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates)
|
|
{
|
|
short *r = config->rates;
|
|
int nents = config->nrates;
|
|
|
|
/* Skip over the intervening rate lists */
|
|
while (sizeID > 0 && nents > 0)
|
|
{
|
|
int i = (*r + 1);
|
|
r += i;
|
|
nents -= i;
|
|
sizeID--;
|
|
}
|
|
if (!nents)
|
|
{
|
|
*nrates = 0;
|
|
return 0;
|
|
}
|
|
*nrates = (int) *r;
|
|
return r + 1;
|
|
}
|
|
|
|
Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp)
|
|
{
|
|
*config_timestamp = config->config_timestamp;
|
|
return config->timestamp;
|
|
}
|
|
|
|
|
|
SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config,
|
|
Rotation *rotation)
|
|
{
|
|
*rotation = (Rotation) config->current_rotation;
|
|
return (SizeID) config->current_size;
|
|
}
|
|
|
|
short XRRConfigCurrentRate (XRRScreenConfiguration *config)
|
|
{
|
|
return config->current_rate;
|
|
}
|
|
|
|
/*
|
|
* Go get the screen configuration data and salt it away for future use;
|
|
* returns NULL if extension not supported
|
|
*/
|
|
static XRRScreenConfiguration *_XRRValidateCache (Display *dpy, int screen)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay (dpy);
|
|
XRRScreenConfiguration **configs;
|
|
XRandRInfo *xrri;
|
|
|
|
if (XextHasExtension(info)) {
|
|
xrri = (XRandRInfo *) info->data;
|
|
configs = xrri->config;
|
|
|
|
if (configs[screen] == NULL)
|
|
configs[screen] = _XRRGetScreenInfo (dpy, RootWindow(dpy, screen));
|
|
return configs[screen];
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* given a screen, return the information from the (possibly) cached data */
|
|
Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation)
|
|
{
|
|
XRRScreenConfiguration *config;
|
|
Rotation cr;
|
|
LockDisplay(dpy);
|
|
if ((config = _XRRValidateCache(dpy, screen))) {
|
|
*current_rotation = config->current_rotation;
|
|
cr = config->rotations;
|
|
UnlockDisplay(dpy);
|
|
return cr;
|
|
}
|
|
else {
|
|
UnlockDisplay(dpy);
|
|
*current_rotation = RR_Rotate_0;
|
|
return 0; /* no rotations supported */
|
|
}
|
|
}
|
|
|
|
/* given a screen, return the information from the (possibly) cached data */
|
|
XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes)
|
|
{
|
|
XRRScreenConfiguration *config;
|
|
XRRScreenSize *sizes;
|
|
|
|
LockDisplay(dpy);
|
|
if ((config = _XRRValidateCache(dpy, screen))) {
|
|
*nsizes = config->nsizes;
|
|
sizes = config->sizes;
|
|
UnlockDisplay(dpy);
|
|
return sizes;
|
|
}
|
|
else {
|
|
UnlockDisplay(dpy);
|
|
*nsizes = 0;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates)
|
|
{
|
|
XRRScreenConfiguration *config;
|
|
short *rates;
|
|
|
|
LockDisplay(dpy);
|
|
if ((config = _XRRValidateCache(dpy, screen))) {
|
|
rates = XRRConfigRates (config, sizeID, nrates);
|
|
UnlockDisplay(dpy);
|
|
return rates;
|
|
}
|
|
else {
|
|
UnlockDisplay(dpy);
|
|
*nrates = 0;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* given a screen, return the information from the (possibly) cached data */
|
|
Time XRRTimes (Display *dpy, int screen, Time *config_timestamp)
|
|
{
|
|
XRRScreenConfiguration *config;
|
|
Time ts;
|
|
|
|
LockDisplay(dpy);
|
|
if ((config = _XRRValidateCache(dpy, screen))) {
|
|
*config_timestamp = config->config_timestamp;
|
|
ts = config->timestamp;
|
|
UnlockDisplay(dpy);
|
|
return ts;
|
|
} else {
|
|
UnlockDisplay(dpy);
|
|
return CurrentTime;
|
|
}
|
|
}
|
|
|
|
int XRRRootToScreen(Display *dpy, Window root)
|
|
{
|
|
int snum;
|
|
for (snum = 0; snum < ScreenCount(dpy); snum++) {
|
|
if (RootWindow(dpy, snum) == root) return snum;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay (dpy);
|
|
|
|
if (XextHasExtension(info)) {
|
|
*event_basep = info->codes->first_event;
|
|
*error_basep = info->codes->first_error;
|
|
return True;
|
|
} else {
|
|
return False;
|
|
}
|
|
}
|
|
|
|
static Bool
|
|
_XRRHasRates (int major, int minor)
|
|
{
|
|
return major > 1 || (major == 1 && minor >= 1);
|
|
}
|
|
|
|
Status XRRQueryVersion (Display *dpy,
|
|
int *major_versionp,
|
|
int *minor_versionp)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay (dpy);
|
|
xRRQueryVersionReply rep;
|
|
xRRQueryVersionReq *req;
|
|
XRandRInfo *xrri;
|
|
|
|
RRCheckExtension (dpy, info, 0);
|
|
|
|
xrri = (XRandRInfo *) info->data;
|
|
|
|
/*
|
|
* only get the version information from the server if we don't have it already
|
|
*/
|
|
if (xrri->major_version == -1) {
|
|
LockDisplay (dpy);
|
|
GetReq (RRQueryVersion, req);
|
|
req->reqType = info->codes->major_opcode;
|
|
req->randrReqType = X_RRQueryVersion;
|
|
req->majorVersion = RANDR_MAJOR;
|
|
req->minorVersion = RANDR_MINOR;
|
|
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
|
|
UnlockDisplay (dpy);
|
|
SyncHandle ();
|
|
return 0;
|
|
}
|
|
xrri->major_version = rep.majorVersion;
|
|
xrri->minor_version = rep.minorVersion;
|
|
xrri->has_rates = _XRRHasRates (xrri->major_version, xrri->minor_version);
|
|
}
|
|
*major_versionp = xrri->major_version;
|
|
*minor_versionp = xrri->minor_version;
|
|
UnlockDisplay (dpy);
|
|
SyncHandle ();
|
|
return 1;
|
|
}
|
|
|
|
typedef struct _randrVersionState {
|
|
unsigned long version_seq;
|
|
Bool error;
|
|
int major_version;
|
|
int minor_version;
|
|
} _XRRVersionState;
|
|
|
|
static Bool
|
|
_XRRVersionHandler (Display *dpy,
|
|
xReply *rep,
|
|
char *buf,
|
|
int len,
|
|
XPointer data)
|
|
{
|
|
xRRQueryVersionReply replbuf;
|
|
xRRQueryVersionReply *repl;
|
|
_XRRVersionState *state = (_XRRVersionState *) data;
|
|
|
|
if (dpy->last_request_read != state->version_seq)
|
|
return False;
|
|
if (rep->generic.type == X_Error)
|
|
{
|
|
state->error = True;
|
|
return False;
|
|
}
|
|
repl = (xRRQueryVersionReply *)
|
|
_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
|
|
(SIZEOF(xRRQueryVersionReply) - SIZEOF(xReply)) >> 2,
|
|
True);
|
|
state->major_version = repl->majorVersion;
|
|
state->minor_version = repl->minorVersion;
|
|
return True;
|
|
}
|
|
/* need a version that does not hold the display lock */
|
|
static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay(dpy);
|
|
xRRGetScreenInfoReply rep;
|
|
xRRGetScreenInfoReq *req;
|
|
_XAsyncHandler async;
|
|
_XRRVersionState async_state;
|
|
int nbytes, nbytesRead, rbytes;
|
|
int i;
|
|
xScreenSizes size;
|
|
struct _XRRScreenConfiguration *scp;
|
|
XRRScreenSize *ssp;
|
|
short *rates;
|
|
xRRQueryVersionReq *vreq;
|
|
XRandRInfo *xrri;
|
|
Bool getting_version = False;
|
|
|
|
RRCheckExtension (dpy, info, 0);
|
|
|
|
xrri = (XRandRInfo *) info->data;
|
|
|
|
if (xrri->major_version == -1)
|
|
{
|
|
/* hide a version query in the request */
|
|
GetReq (RRQueryVersion, vreq);
|
|
vreq->reqType = info->codes->major_opcode;
|
|
vreq->randrReqType = X_RRQueryVersion;
|
|
vreq->majorVersion = RANDR_MAJOR;
|
|
vreq->minorVersion = RANDR_MINOR;
|
|
|
|
async_state.version_seq = dpy->request;
|
|
async_state.error = False;
|
|
async.next = dpy->async_handlers;
|
|
async.handler = _XRRVersionHandler;
|
|
async.data = (XPointer) &async_state;
|
|
dpy->async_handlers = &async;
|
|
|
|
getting_version = True;
|
|
}
|
|
|
|
GetReq (RRGetScreenInfo, req);
|
|
req->reqType = info->codes->major_opcode;
|
|
req->randrReqType = X_RRGetScreenInfo;
|
|
req->window = window;
|
|
|
|
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
|
|
{
|
|
if (getting_version)
|
|
DeqAsyncHandler (dpy, &async);
|
|
SyncHandle ();
|
|
return NULL;
|
|
}
|
|
if (getting_version)
|
|
{
|
|
DeqAsyncHandler (dpy, &async);
|
|
if (async_state.error)
|
|
{
|
|
SyncHandle();
|
|
}
|
|
xrri->major_version = async_state.major_version;
|
|
xrri->minor_version = async_state.minor_version;
|
|
xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version);
|
|
}
|
|
|
|
/*
|
|
* Make the reply compatible with v1.1
|
|
*/
|
|
if (!xrri->has_rates)
|
|
{
|
|
rep.rate = 0;
|
|
rep.nrateEnts = 0;
|
|
}
|
|
|
|
nbytes = (long) rep.length << 2;
|
|
|
|
nbytesRead = (long) (rep.nSizes * SIZEOF (xScreenSizes) +
|
|
((rep.nrateEnts + 1)& ~1) * 2 /* SIZEOF (CARD16) */);
|
|
|
|
/*
|
|
* first we must compute how much space to allocate for
|
|
* randr library's use; we'll allocate the structures in a single
|
|
* allocation, on cleanlyness grounds.
|
|
*/
|
|
|
|
rbytes = sizeof (XRRScreenConfiguration) +
|
|
(rep.nSizes * sizeof (XRRScreenSize) +
|
|
rep.nrateEnts * sizeof (int));
|
|
|
|
scp = (struct _XRRScreenConfiguration *) Xmalloc(rbytes);
|
|
if (scp == NULL) {
|
|
_XEatData (dpy, (unsigned long) nbytes);
|
|
SyncHandle ();
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ssp = (XRRScreenSize *)(scp + 1);
|
|
rates = (short *) (ssp + rep.nSizes);
|
|
|
|
/* set up the screen configuration structure */
|
|
scp->screen =
|
|
ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root));
|
|
|
|
scp->sizes = ssp;
|
|
scp->rates = rates;
|
|
scp->rotations = rep.setOfRotations;
|
|
scp->current_size = rep.sizeID;
|
|
scp->current_rate = rep.rate;
|
|
scp->current_rotation = rep.rotation;
|
|
scp->timestamp = rep.timestamp;
|
|
scp->config_timestamp = rep.configTimestamp;
|
|
scp->nsizes = rep.nSizes;
|
|
scp->nrates = rep.nrateEnts;
|
|
|
|
/*
|
|
* Time to unpack the data from the server.
|
|
*/
|
|
|
|
/*
|
|
* First the size information
|
|
*/
|
|
for (i = 0; i < rep.nSizes; i++) {
|
|
_XReadPad (dpy, (char *) &size, SIZEOF (xScreenSizes));
|
|
|
|
ssp[i].width = size.widthInPixels;
|
|
ssp[i].height = size.heightInPixels;
|
|
ssp[i].mwidth = size.widthInMillimeters;
|
|
ssp[i].mheight = size.heightInMillimeters;
|
|
}
|
|
/*
|
|
* And the rates
|
|
*/
|
|
_XRead16Pad (dpy, rates, 2 /* SIZEOF (CARD16) */ * rep.nrateEnts);
|
|
|
|
/*
|
|
* Skip any extra data
|
|
*/
|
|
if (nbytes > nbytesRead)
|
|
_XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
|
|
|
|
return (XRRScreenConfiguration *)(scp);
|
|
}
|
|
|
|
XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, Window window)
|
|
{
|
|
XRRScreenConfiguration *config;
|
|
LockDisplay (dpy);
|
|
config = _XRRGetScreenInfo(dpy, window);
|
|
UnlockDisplay (dpy);
|
|
SyncHandle ();
|
|
return config;
|
|
}
|
|
|
|
|
|
void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config)
|
|
{
|
|
Xfree (config);
|
|
}
|
|
|
|
|
|
/*
|
|
* in protocol version 0.1, routine added to allow selecting for new events.
|
|
*/
|
|
|
|
void XRRSelectInput (Display *dpy, Window window, int mask)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay (dpy);
|
|
xRRSelectInputReq *req;
|
|
|
|
RRSimpleCheckExtension (dpy, info);
|
|
|
|
LockDisplay (dpy);
|
|
GetReq (RRSelectInput, req);
|
|
req->reqType = info->codes->major_opcode;
|
|
req->randrReqType = X_RRSelectInput;
|
|
req->window = window;
|
|
req->enable = 0;
|
|
if (mask) req->enable = mask;
|
|
UnlockDisplay (dpy);
|
|
SyncHandle ();
|
|
return;
|
|
}
|
|
|
|
Status XRRSetScreenConfigAndRate (Display *dpy,
|
|
XRRScreenConfiguration *config,
|
|
Drawable draw,
|
|
int size_index,
|
|
Rotation rotation,
|
|
short rate,
|
|
Time timestamp)
|
|
{
|
|
XExtDisplayInfo *info = XRRFindDisplay (dpy);
|
|
xRRSetScreenConfigReply rep;
|
|
XRandRInfo *xrri;
|
|
int major, minor;
|
|
|
|
RRCheckExtension (dpy, info, 0);
|
|
|
|
/* Make sure has_rates is set */
|
|
if (!XRRQueryVersion (dpy, &major, &minor))
|
|
return 0;
|
|
|
|
LockDisplay (dpy);
|
|
xrri = (XRandRInfo *) info->data;
|
|
if (xrri->has_rates)
|
|
{
|
|
xRRSetScreenConfigReq *req;
|
|
GetReq (RRSetScreenConfig, req);
|
|
req->reqType = info->codes->major_opcode;
|
|
req->randrReqType = X_RRSetScreenConfig;
|
|
req->drawable = draw;
|
|
req->sizeID = size_index;
|
|
req->rotation = rotation;
|
|
req->timestamp = timestamp;
|
|
req->configTimestamp = config->config_timestamp;
|
|
req->rate = rate;
|
|
}
|
|
else
|
|
{
|
|
xRR1_0SetScreenConfigReq *req;
|
|
GetReq (RR1_0SetScreenConfig, req);
|
|
req->reqType = info->codes->major_opcode;
|
|
req->randrReqType = X_RRSetScreenConfig;
|
|
req->drawable = draw;
|
|
req->sizeID = size_index;
|
|
req->rotation = rotation;
|
|
req->timestamp = timestamp;
|
|
req->configTimestamp = config->config_timestamp;
|
|
}
|
|
|
|
(void) _XReply (dpy, (xReply *) &rep, 0, xTrue);
|
|
|
|
if (rep.status == RRSetConfigSuccess) {
|
|
/* if we succeed, set our view of reality to what we set it to */
|
|
config->config_timestamp = rep.newConfigTimestamp;
|
|
config->timestamp = rep.newTimestamp;
|
|
config->screen = ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root));
|
|
config->current_size = size_index;
|
|
config->current_rotation = rotation;
|
|
}
|
|
UnlockDisplay (dpy);
|
|
SyncHandle ();
|
|
return(rep.status);
|
|
}
|
|
|
|
Status XRRSetScreenConfig (Display *dpy,
|
|
XRRScreenConfiguration *config,
|
|
Drawable draw,
|
|
int size_index,
|
|
Rotation rotation, Time timestamp)
|
|
{
|
|
return XRRSetScreenConfigAndRate (dpy, config, draw, size_index,
|
|
rotation, 0, timestamp);
|
|
}
|
|
|
|
int XRRUpdateConfiguration(XEvent *event)
|
|
{
|
|
XRRScreenChangeNotifyEvent *scevent;
|
|
XConfigureEvent *rcevent;
|
|
Display *dpy = event->xany.display;
|
|
XExtDisplayInfo *info;
|
|
XRandRInfo *xrri;
|
|
int snum;
|
|
|
|
/* first, see if it is a vanilla configure notify event */
|
|
if (event->type == ConfigureNotify) {
|
|
rcevent = (XConfigureEvent *) event;
|
|
snum = XRRRootToScreen(dpy, rcevent->window);
|
|
dpy->screens[snum].width = rcevent->width;
|
|
dpy->screens[snum].height = rcevent->height;
|
|
return 1;
|
|
}
|
|
|
|
info = XRRFindDisplay(dpy);
|
|
RRCheckExtension (dpy, info, 0);
|
|
|
|
switch (event->type - info->codes->first_event) {
|
|
case RRScreenChangeNotify:
|
|
scevent = (XRRScreenChangeNotifyEvent *) event;
|
|
snum = XRRRootToScreen(dpy,
|
|
((XRRScreenChangeNotifyEvent *) event)->root);
|
|
dpy->screens[snum].width = scevent->width;
|
|
dpy->screens[snum].height = scevent->height;
|
|
dpy->screens[snum].mwidth = scevent->mwidth;
|
|
dpy->screens[snum].mheight = scevent->mheight;
|
|
XRenderSetSubpixelOrder (dpy, snum, scevent->subpixel_order);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
xrri = (XRandRInfo *) info->data;
|
|
/*
|
|
* so the next time someone wants some data, it will be fetched;
|
|
* it might be better to force the round trip immediately, but
|
|
* I dislike pounding the server simultaneously when not necessary
|
|
*/
|
|
if (xrri->config[snum] != NULL) {
|
|
XFree (xrri->config[snum]);
|
|
xrri->config[snum] = NULL;
|
|
}
|
|
return 1;
|
|
}
|