summaryrefslogtreecommitdiff
path: root/src/Xrandr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Xrandr.c')
-rw-r--r--src/Xrandr.c506
1 files changed, 99 insertions, 407 deletions
diff --git a/src/Xrandr.c b/src/Xrandr.c
index 32537b4..577a6dd 100644
--- a/src/Xrandr.c
+++ b/src/Xrandr.c
@@ -42,8 +42,6 @@ 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);
@@ -64,19 +62,16 @@ static /* const */ XExtensionHooks rr_extension_hooks = {
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;
+ case RRScreenChangeNotify: {
+ XRRScreenChangeNotifyEvent *aevent= (XRRScreenChangeNotifyEvent *) event;
+ xRRScreenChangeNotifyEvent *awire = (xRRScreenChangeNotifyEvent *) wire;
aevent->type = awire->type & 0x7F;
- aevent->serial = _XSetLastRequestRead(dpy,
- (xGenericReply *) wire);
+ aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
aevent->send_event = (awire->type & 0x80) != 0;
aevent->display = dpy;
aevent->window = awire->window;
@@ -91,6 +86,53 @@ static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
aevent->mwidth = awire->widthInMillimeters;
aevent->mheight = awire->heightInMillimeters;
return True;
+ }
+ case RRNotify: {
+ XRRNotifyEvent *aevent = (XRRNotifyEvent *) event;
+ xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire;
+ 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->subtype = awire->subCode;
+ switch (aevent->subtype) {
+ case RRNotify_OutputChange: {
+ XRROutputChangeNotifyEvent *aevent = (XRROutputChangeNotifyEvent *) event;
+ xRROutputChangeNotifyEvent *awire = (xRROutputChangeNotifyEvent *) wire;
+ aevent->output = awire->output;
+ aevent->crtc = awire->crtc;
+ aevent->mode = awire->mode;
+ aevent->rotation = awire->rotation;
+ aevent->connection = awire->connection;
+ aevent->subpixel_order = awire->subpixelOrder;
+ return True;
+ }
+ case RRNotify_CrtcChange: {
+ XRRCrtcChangeNotifyEvent *aevent = (XRRCrtcChangeNotifyEvent *) event;
+ xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire;
+ aevent->crtc = awire->crtc;
+ aevent->mode = awire->mode;
+ aevent->rotation = awire->rotation;
+ aevent->x = awire->x;
+ aevent->y = awire->y;
+ aevent->width = awire->height;
+ aevent->height = awire->height;
+ return True;
+ }
+ case RRNotify_OutputProperty: {
+ XRROutputPropertyNotifyEvent *aevent = (XRROutputPropertyNotifyEvent *) event;
+ xRROutputPropertyNotifyEvent *awire = (xRROutputPropertyNotifyEvent *) wire;
+ aevent->output = awire->output;
+ aevent->property = awire->atom;
+ aevent->timestamp = awire->timestamp;
+ aevent->state = awire->state;
+ return True;
+ }
+
+ break;
+ }
+ }
}
return False;
@@ -99,16 +141,14 @@ static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
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;
+ case RRScreenChangeNotify: {
+ xRRScreenChangeNotifyEvent *awire = (xRRScreenChangeNotifyEvent *) wire;
+ XRRScreenChangeNotifyEvent *aevent = (XRRScreenChangeNotifyEvent *) event;
awire->type = aevent->type | (aevent->send_event ? 0x80 : 0);
awire->rotation = (CARD8) aevent->rotation;
awire->sequenceNumber = aevent->serial & 0xFFFF;
@@ -123,6 +163,49 @@ static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire)
awire->widthInMillimeters = aevent->mwidth;
awire->heightInMillimeters = aevent->mheight;
return True;
+ }
+ case RRNotify: {
+ xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire;
+ XRRNotifyEvent *aevent = (XRRNotifyEvent *) event;
+ awire->type = aevent->type | (aevent->send_event ? 0x80 : 0);
+ awire->sequenceNumber = aevent->serial & 0xFFFF;
+ awire->window = aevent->window;
+ awire->subCode = aevent->subtype;
+ switch (aevent->subtype) {
+ case RRNotify_OutputChange: {
+ xRROutputChangeNotifyEvent *awire = (xRROutputChangeNotifyEvent *) wire;
+ XRROutputChangeNotifyEvent *aevent = (XRROutputChangeNotifyEvent *) event;
+ awire->output = aevent->output;
+ awire->crtc = aevent->crtc;
+ awire->mode = aevent->mode;
+ awire->rotation = aevent->rotation;
+ awire->connection = aevent->connection;
+ awire->subpixelOrder = aevent->subpixel_order;
+ return True;
+ }
+ case RRNotify_CrtcChange: {
+ xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire;
+ XRRCrtcChangeNotifyEvent *aevent = (XRRCrtcChangeNotifyEvent *) event;
+ awire->crtc = aevent->crtc;
+ awire->mode = aevent->mode;
+ awire->rotation = aevent->rotation;
+ awire->x = aevent->x;
+ awire->y = aevent->y;
+ awire->width = aevent->height;
+ awire->height = aevent->height;
+ return True;
+ }
+ case RRNotify_OutputProperty: {
+ xRROutputPropertyNotifyEvent *awire = (xRROutputPropertyNotifyEvent *) wire;
+ XRROutputPropertyNotifyEvent *aevent = (XRROutputPropertyNotifyEvent *) event;
+ awire->output = aevent->output;
+ awire->atom = aevent->property;
+ awire->timestamp = aevent->timestamp;
+ awire->state = aevent->state;
+ return True;
+ }
+ }
+ }
}
return False;
}
@@ -178,157 +261,6 @@ XRRCloseDisplay (Display *dpy, XExtCodes *codes)
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)
{
@@ -353,7 +285,7 @@ Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep)
}
}
-static Bool
+Bool
_XRRHasRates (int major, int minor)
{
return major > 1 || (major == 1 && minor >= 1);
@@ -398,14 +330,7 @@ Status XRRQueryVersion (Display *dpy,
return 1;
}
-typedef struct _randrVersionState {
- unsigned long version_seq;
- Bool error;
- int major_version;
- int minor_version;
-} _XRRVersionState;
-
-static Bool
+Bool
_XRRVersionHandler (Display *dpy,
xReply *rep,
char *buf,
@@ -431,167 +356,6 @@ _XRRVersionHandler (Display *dpy,
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;
- XRRFindDisplay(dpy);
- 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.
@@ -616,78 +380,6 @@ void XRRSelectInput (Display *dpy, Window window, int mask)
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;