summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:49 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:49 +0000
commit52d0891b9e3c51d43fd13d0b2680b7e24b2f2e2d (patch)
treef0ca247f48828ad5c2c131150ca7bc80ffb4e7fd
Initial revision
-rw-r--r--include/X11/extensions/Xrandr.h151
-rw-r--r--man/Xrandr.man319
-rw-r--r--src/Xrandr.c733
-rw-r--r--src/Xrandrint.h87
4 files changed, 1290 insertions, 0 deletions
diff --git a/include/X11/extensions/Xrandr.h b/include/X11/extensions/Xrandr.h
new file mode 100644
index 0000000..7a0d6c5
--- /dev/null
+++ b/include/X11/extensions/Xrandr.h
@@ -0,0 +1,151 @@
+/*
+ * $XFree86: xc/lib/Xrandr/Xrandr.h,v 1.11 2002/10/14 18:01:39 keithp 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 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.
+ */
+
+#ifndef _XRANDR_H_
+#define _XRANDR_H_
+
+#include <X11/extensions/randr.h>
+
+#include <X11/Xfuncproto.h>
+
+_XFUNCPROTOBEGIN
+
+
+typedef struct {
+ int width, height;
+ int mwidth, mheight;
+} XRRScreenSize;
+
+/*
+ * Events.
+ */
+
+typedef struct {
+ int type; /* event base */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* window which selected for this event */
+ Window root; /* Root window for changed screen */
+ Time timestamp; /* when the screen change occurred */
+ Time config_timestamp; /* when the last configuration change */
+ SizeID size_index;
+ SubpixelOrder subpixel_order;
+ Rotation rotation;
+ int width;
+ int height;
+ int mwidth;
+ int mheight;
+} XRRScreenChangeNotifyEvent;
+
+
+/* internal representation is private to the library */
+typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
+
+Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep);
+Status XRRQueryVersion (Display *dpy,
+ int *major_versionp,
+ int *minor_versionp);
+
+XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy,
+ Drawable draw);
+
+void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config);
+
+/*
+ * Note that screen configuration changes are only permitted if the client can
+ * prove it has up to date configuration information. We are trying to
+ * insist that it become possible for screens to change dynamically, so
+ * we want to ensure the client knows what it is talking about when requesting
+ * changes.
+ */
+Status XRRSetScreenConfig (Display *dpy,
+ XRRScreenConfiguration *config,
+ Drawable draw,
+ int size_index,
+ Rotation rotation,
+ Time timestamp);
+
+/* added in v1.1, sorry for the lame name */
+Status XRRSetScreenConfigAndRate (Display *dpy,
+ XRRScreenConfiguration *config,
+ Drawable draw,
+ int size_index,
+ Rotation rotation,
+ short rate,
+ Time timestamp);
+
+
+Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation);
+
+Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp);
+
+XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes);
+
+short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates);
+
+SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config,
+ Rotation *rotation);
+
+short XRRConfigCurrentRate (XRRScreenConfiguration *config);
+
+int XRRRootToScreen(Display *dpy, Window root);
+
+/*
+ * returns the screen configuration for the specified screen; does a lazy
+ * evalution to delay getting the information, and caches the result.
+ * These routines should be used in preference to XRRGetScreenInfo
+ * to avoid unneeded round trips to the X server. These are new
+ * in protocol version 0.1.
+ */
+
+
+XRRScreenConfiguration *XRRScreenConfig(Display *dpy, int screen);
+XRRScreenConfiguration *XRRConfig(Screen *screen);
+void XRRSelectInput(Display *dpy, Window window, int mask);
+
+/*
+ * the following are always safe to call, even if RandR is not implemented
+ * on a screen
+ */
+
+
+Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation);
+XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes);
+short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates);
+Time XRRTimes (Display *dpy, int screen, Time *config_timestamp);
+
+
+/*
+ * intended to take RRScreenChangeNotify, or
+ * ConfigureNotify (on the root window)
+ * returns 1 if it is an event type it understands, 0 if not
+ */
+int XRRUpdateConfiguration(XEvent *event);
+
+_XFUNCPROTOEND
+
+#endif /* _XRANDR_H_ */
diff --git a/man/Xrandr.man b/man/Xrandr.man
new file mode 100644
index 0000000..71fbdf0
--- /dev/null
+++ b/man/Xrandr.man
@@ -0,0 +1,319 @@
+.\"
+.\" $XFree86: xc/lib/Xrandr/Xrandr.man,v 1.3 2002/10/08 13:00:48 keithp Exp $
+.\"
+.\" Copyright © 2002 Hewlett-Packard Company
+.\"
+.\" 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 Hewlett-Packard Company not be used in
+.\" advertising or publicity pertaining to distribution of the software without
+.\" specific, written prior permission. Hewlett Packard Company makes no
+.\" representations about the suitability of this software for any purpose. It
+.\" is provided "as is" without express or implied warranty.
+.\"
+.\" Hewlett-Packard DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+.\" EVENT SHALL KEITH PACKARD 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.
+.\"
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.TH XRANDR 3 "Version 1.0" "XFree86"
+
+.SH NAME
+ Xrandr \- X Resize, Rotate and Reflection extension.
+.SH SYNTAX
+\&#include <X11/extensions/Xrandr.h>
+.nf
+.sp
+Bool XRRQueryExtension \^(\^Display *\fIdpy\fP,
+ int *\fIevent_basep\fP, int *\fIerror_basep\fP\^);
+.sp
+Status XRRQueryVersion \^(\^Display *\fIdpy\fP,
+ int *\fImajor_versionp\fP,
+ int *\fIminor_versionp\fP\^);
+.sp
+XRRScreenConfiguration *XRRGetScreenInfo \^(\^Display *dpy,
+ Drawable \fIdraw\fP\^);
+.sp
+void XRRFreeScreenConfigInfo \^(\^
+ \fIXRRScreenConfiguration *config\fP\^);
+.sp
+Status XRRSetScreenConfig \^(\^Display *\fIdpy\fP,
+ XRRScreenConfiguration *\fIconfig\fP,
+ Drawable \fIdraw\fP,
+ int \fIsize_index\fP,
+ Rotation \fIrotation\fP,
+ Time \fItimestamp\fP\^);
+.sp
+Rotation XRRConfigRotations\^(\^
+ XRRScreenConfiguration *\fIconfig\fP,
+ Rotation *\fIcurrent_rotation\fP\^);
+.sp
+Time XRRConfigTimes \^(\^
+ XRRScreenConfiguration *\fIconfig\fP,
+ Time *\fIconfig_timestamp\fP\^);
+.sp
+XRRScreenSize *XRRConfigSizes\^(\^
+ XRRScreenConfiguration *\fIconfig\fP,
+ int *\fInsizes\fP\^);
+.sp
+SizeID XRRConfigCurrentConfiguration \^(\^
+ XRRScreenConfiguration *\fIconfig\fP,
+ Rotation *\fIrotation\fP\^);
+.sp
+int XRRRootToScreen\^(\^
+ Display *\fIdpy\fP,
+ Window \fIroot\fP\^);
+.sp
+XRRScreenConfiguration *XRRScreenConfig\^(\^
+ Display *\fIdpy\fP, int \fIscreen\fP\^);
+.sp
+XRRScreenConfiguration *XRRConfig\^(\^Screen *\fIscreen\fP\^);
+.sp
+void XRRSelectInput\^(\^Display *\fIdpy\fP, Window \fIwindow\fP, int \fImask\fP\^);
+.sp
+/*
+ * intended to take RRScreenChangeNotify, or
+ * ConfigureNotify \^(\^\fIon the root window\fP\^)
+ * returns 1 if it is an event type it understands, 0 if not
+ */
+int XRRUpdateConfiguration\^(\^XEvent *\fIevent\fP^);
+.sp
+/*
+ * the following are always safe to call, even if RandR is
+ * not implemented on a screen
+ */
+.br
+Rotation XRRRotations\^(\^
+ Display *\fIdpy\fP, int \fIscreen\fP,
+ Rotation *\fIcurrent_rotation\fP\^);
+.sp
+XRRScreenSize *XRRSizes\^(\^Display *\fIdpy\fP,
+ int \fIscreen\fP, int *\fInsizes\fP\^);
+.sp
+Time XRRTimes \^(\^Display *\fIdpy\fP, int \fIscreen\fP, Time *\fIconfig_timestamp\fP\^);
+.fi
+.SH ARGUMENTS
+.IP \fIdisplay\fP 1i
+Specifies the connection to the X server.
+.IP \fIscreen\fP 1i
+Specifies which screen.
+.IP \fIdraw\fP 1i
+Specifies the screen.
+.IP \fIrotation\fP 1i
+Specifies the rotations or reflections possible of the screen.
+.IP \fIcurrent_rotation\fP 1i
+Specifies the current rotations and reflection of the screen.
+.IP \fItimestamp\fP 1i
+Specifies the server timestamp.
+.IP \fIconfig_timestamp\fP 1i
+Specifies the timestamp when the screen was last (re)configured.
+.IP \fIconfig\fP 1i
+Specifies the screen configuration being used.
+.IP \fIsizes\fP 1i
+Specifies the array of sizes supported.
+
+.SH DATATYPES
+
+.PP
+.B Rotations/Reflections
+.PP
+Can be any of:
+.nf
+#define RR_Rotate_0 1
+#define RR_Rotate_90 2
+#define RR_Rotate_180 4
+#define RR_Rotate_270 8
+
+/* new in 1.0 protocol, to allow reflection of screen */
+/* reflection is applied after rotation */
+
+#define RR_Reflect_X 16
+#define RR_Reflect_Y 32
+
+
+typedef struct {
+ int width, height;
+ int mwidth, mheight;
+} XRRScreenSize;
+
+typedef struct {
+ int type; /* event base */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* window which selected for this event */
+ Window root; /* Root window for changed screen */
+ Time timestamp; /* when the screen change occurred */
+ Time config_timestamp; /* when the last configuration change */
+ SizeID size_index;
+ SubpixelOrder subpixel_order;
+ Rotation rotation;
+ int width;
+ int height;
+ int mwidth;
+ int mheight;
+} XRRScreenChangeNotifyEvent;
+.sp
+.fi
+.B XRRScreenSize
+structure contains a possible root size in pixels and in millimeters.
+.B XRRScreenChangeNotifyEvent
+Is sent to a client that has requested notification whenever the screen
+configuration is changed.
+
+.B XRRScreenConfiguration
+This is an opaque data type containing the configuration information
+for a screen.
+
+.B Timestamps
+.PP
+Time stamps are included and must be used to ensure the client is playing
+with a full deck: the screen may change properties
+on the fly and this ensures its knowledge of the configuration is up to date.
+This is to help issues when screens may become hot-pluggable in the future.
+
+.SH DESCRIPTION
+.B Xrandr
+is a simple library designed to interface the X Resize and Rotate
+Extension. This allows clients to change the size and rotation of the
+root window of a screen, along with the ability to reflect the screen
+about either axis (if supported by the impementation). Rotation and
+reflection may be implemented by software and may result in slower
+performance if rotation and reflection are implemented in this fashion
+(as are all implementations as of October 2002).
+.PP
+The Xrandr library does some minimal caching to avoid roundtrips to
+provide clients frequently used information. See "The X Resize and
+Rotate Extension" for a detailed description; also note that depth
+switching, as described in the document is not implemented, and may
+(or may not) ever be implemented, as display memory is growing rapidly,
+and toolkits are already beginning to support migration, mitigating the
+need for depth switching. If it is implemented in the future, we
+expect to do so via an upward compatible extension to the
+current library/protocol; functionality described here should continue
+to work.
+.PP
+Rotation and reflection and how they interact can be confusing. In
+Randr, the coordinate system is rotated in a counter-clockwise
+direction relative to the normal orientation. Reflection is along the
+window system coordinate system, not the physical screen X and Y axis,
+so that rotation and reflection do not interact. The other way to
+consider reflection is to is specified in the "normal" orientation,
+before rotation, if you find the other way confusing.
+.PP
+The
+.B XRRScreenChangeNotify
+event is sent to clients that ask to be informed whenever the root window
+configuration changes. Configuration changes may include resolution,
+physical size, subpixel order (see XRender(3)), and rotation. Note
+that changes to any or all of these could occur due to external events
+(user control in the X server, a different monitor/flat panel display
+being hot-plugged) and is not only the result of a protocol/library
+request to the X server.
+.PP
+Additionally, to eliminate a potential race condition,
+this event may be generated
+immediately upon selecting for notification if the screen has changed
+since the client of Xrandr connected to the X server, to enable
+reliable screen resolution changing when a user may log in and
+change the configuration while one or many clients are starting up.
+.PP
+.B Xlib notification
+.PP
+Clients must call back into Xlib using
+.B XRRUpdateConfiguration
+when screen configuration change notify events are generated
+(or root window configuration changes occur, to update Xlib's
+view of the resolution, size, rotation, reflection or subpixel order.
+Generally, toolkits will perform this operation on behalf of applications;
+we did not want to change display structure data behind the back of toolkits,
+as in multithreaded clients, various race conditions might occur.
+Toolkits should provide clients some mechanism for notification of
+screen change, of couse.
+
+.SH FUNCTIONS
+There are two classes of interfaces: those which can be safely called
+even if RandR is not implemented on a screen (to make common idioms not
+dependent on the server having support), and those which will return
+errors if the extension is not present.
+.PP
+.B XRRRotations
+returns both the possible set of rotations/reflections supported
+(as a bitmask) as the value of the function, along with the current
+rotation/reflection of the screen.
+.PP
+.B XRRSizes
+returns the size and a pointer to the current sizes supported by
+the specified screen. The first size specified is the default size
+of the server. If RandR is not supported, it returns 0 for
+the number of sizes.
+.PP
+.B XRRTimes
+returns the time last reported by the server along with the
+timestamp the last configuration changed.
+If the configuration has changed since the client last updated
+its view of the server time, requests to change the configuration
+will fail until the client has an up to date timestamp.
+.PP
+.B XRRRootToScreen
+returns the screen number given a root window (for example, from
+an \fBXRRScreenChangeNotifyEvent\fI.
+.PP
+The rest of the functions will fail if applied to screens not
+implementing the RandR extension.
+.B XRRSetScreenConfig
+sets the screen size and rotation and reflection to the desired
+values on the screen specified by \fIdraw\fP, or returns a
+.B BadValue
+error.
+\fIsize_index\fP specifies which size configuration is to be used,
+\fIrotation\fP specifies which rotatation or reflection is to
+be used (or a
+.B BadValue
+error is returned).
+The \fItimestamp\fP is used by the server to make sure the client
+has up to date configuration information. Status is returned
+to indicate success or failure; a client must refresh its configuration
+information if it fails and try the call again (by calling
+\fBXRRGetScreenInfo\fP).
+.PP
+.B XRRConfigRotations,
+.B XRRConfigSizes,
+.B XRRConfigCurrentConfiguration,
+and
+.B XRRConfigTimes
+are used to get specific configuration information out of a screen
+configuration.
+.PP
+.B XRRGetScreenInfo
+Returns a screen configuration for later use; the information is
+private to the library.
+Call
+.B XRRFreeScreenConfigInfo
+to free this information when you are finished with it.
+It forces a round trip to the server.
+
+Other functions include:
+.B XRRQueryExtension
+which returns the event and error base codes,
+.B XRRQueryVersion
+, which returns the current version of the extension (this information
+is cached by the library).
+.SH RESTRICTIONS
+.B Xrandr
+will remain upward compatible after the current 1.0 release.
+.SH "SEE ALSO"
+Xrender(3)
+.SH AUTHOR
+Jim Gettys, HP, and Keith Packard, member of the XFree86 Project, Inc. and
+HP.
diff --git a/src/Xrandr.c b/src/Xrandr.c
new file mode 100644
index 0000000..e464431
--- /dev/null
+++ b/src/Xrandr.c
@@ -0,0 +1,733 @@
+/*
+ * $XFree86: xc/lib/Xrandr/Xrandr.c,v 1.13 2003/02/07 11:21:07 eich 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;
+ int snum;
+ 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, (snum = 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;
+}
diff --git a/src/Xrandrint.h b/src/Xrandrint.h
new file mode 100644
index 0000000..2ec5d86
--- /dev/null
+++ b/src/Xrandrint.h
@@ -0,0 +1,87 @@
+/*
+ * $XFree86: xc/lib/Xrandr/Xrandrint.h,v 1.4 2002/10/14 18:01:40 keithp Exp $
+ *
+ *
+ * Copyright © 2000, Compaq Computer Corporation,
+ * Copyright © 2002, Hewlett Packard, 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 HP
+ * 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, Hewlett-Packard, Inc.
+ */
+
+#ifndef _XRANDRINT_H_
+#define _XRANDRINT_H_
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include "Xext.h" /* in ../include */
+#include "extutil.h" /* in ../include */
+#include "Xrandr.h"
+#include "randr.h"
+#include "randrproto.h"
+
+extern XExtensionInfo XrandrExtensionInfo;
+extern char XrandrExtensionName[];
+
+#define RRCheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, XRRExtensionName, val)
+#define RRSimpleCheckExtension(dpy,i) \
+ XextSimpleCheckExtension (dpy, i, XRRExtensionName)
+
+XExtDisplayInfo *XRRFindDisplay (Display *dpy);
+
+
+/* deliberately opaque internal data structure; can be extended,
+ but not reordered */
+struct _XRRScreenConfiguration {
+ Screen *screen; /* the root window in GetScreenInfo */
+ XRRScreenSize *sizes;
+ Rotation rotations;
+ Rotation current_rotation;
+ int nsizes;
+ int current_size;
+ short current_rate;
+ Time timestamp;
+ Time config_timestamp;
+ int subpixel_order; /* introduced in randr v0.1 */
+ short *rates; /* introduced in randr v1.1 */
+ int nrates;
+};
+
+/*
+ * if a configure notify on the root is recieved, or
+ * an XRRScreenChangeNotify is recieved,
+ * XRRUpdateConfiguration should be called to update the X library's
+ * view of the screen configuration; it will also invalidate the cache
+ * provided by XRRScreenConfig and XRRConfig, and force a round trip
+ * when next used. Returns invalid status if not an event type
+ * the library routine understand.
+ */
+
+/* we cache one screen configuration/screen */
+
+typedef struct _XRandRInfo {
+ XRRScreenConfiguration **config;
+ int major_version, minor_version; /* major_version = -1 means we don't know */
+ Bool has_rates; /* Server supports refresh rates */
+} XRandRInfo;
+
+#endif /* _XRANDRINT_H_ */