summaryrefslogtreecommitdiff
path: root/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c')
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
new file mode 100644
index 0000000..829c439
--- /dev/null
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
@@ -0,0 +1,329 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+/*
+ * XRandR backend
+ *
+ * Currently only rotation is supported.
+ *
+ */
+
+#include <sys/utsname.h>
+
+#include <stdlib.h> /* 64 bit malloc */
+
+#include <dlfcn.h> /* To dynamically load libXrandr.so.2 */
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h> /* Xrandr */
+
+#include "NvCtrlAttributes.h"
+#include "NvCtrlAttributesPrivate.h"
+#include "NVCtrlLib.h"
+
+#include "msg.h"
+#include "parse.h"
+
+
+
+/******************************************************************************
+ *
+ * Sets the requested rotation orientation.
+ *
+ ****/
+
+static ReturnStatus
+set_rotation(NvCtrlAttributePrivateHandle *h, Rotation rotation)
+{
+ XRRScreenConfiguration *sc;
+ Rotation cur_rotation;
+ SizeID cur_size;
+ Status status;
+
+
+ /* Check orientation is supported */
+ if ( !( h->xrandr->rotations & rotation ) ) {
+ return NvCtrlBadArgument;
+ }
+
+ /* Get current size & orientation */
+ sc = h->xrandr->XRRGetScreenInfo(h->dpy, DefaultRootWindow(h->dpy));
+ if ( !sc ) {
+ return NvCtrlError;
+ }
+ cur_size = h->xrandr->XRRConfigCurrentConfiguration(sc, &cur_rotation);
+
+ status = h->xrandr->XRRSetScreenConfig (h->dpy, sc,
+ DefaultRootWindow(h->dpy),
+ cur_size, rotation, CurrentTime);
+ h->xrandr->XRRFreeScreenConfigInfo(sc);
+
+ if ( status != Success ) {
+ return NvCtrlError;
+ }
+
+ return NvCtrlSuccess;
+
+} /* set_rotation() */
+
+
+
+/******************************************************************************
+ *
+ * Initializes the NvCtrlXrandrAttributes Extension by linking the
+ * libXrandr.so.2 library and resolving functions used.
+ *
+ ****/
+
+NvCtrlXrandrAttributes *
+NvCtrlInitXrandrAttributes (NvCtrlAttributePrivateHandle *h)
+{
+ NvCtrlXrandrAttributes *xrandr = NULL;
+ const char *error = NULL; /* libXrandr error string */
+ Bool ret;
+ Rotation rotation;
+ XRRScreenSize *sizes;
+
+
+ /* Check parameter */
+ if ( h == NULL || h->dpy == NULL ) {
+ goto fail;
+ }
+
+
+ /* Allocate attributes structure */
+ xrandr = (NvCtrlXrandrAttributes *)
+ calloc(1, sizeof (NvCtrlXrandrAttributes));
+ if ( xrandr == NULL ) {
+ error = "Out of memory.";
+ goto fail;
+ }
+
+
+ /* Link the libXrandr lib */
+ xrandr->libXrandr = dlopen("libXrandr.so.2", RTLD_LAZY);
+ if ( xrandr->libXrandr == NULL ) {
+ /* Silently fail */
+ goto fail;
+ }
+
+
+ /* Resolve XRandR functions */
+ xrandr->XRRQueryExtension = dlsym(xrandr->libXrandr,
+ "XRRQueryExtension");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRSelectInput = dlsym(xrandr->libXrandr, "XRRSelectInput");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRConfigCurrentConfiguration = dlsym(xrandr->libXrandr,
+ "XRRConfigCurrentConfiguration");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRGetScreenInfo = dlsym(xrandr->libXrandr,
+ "XRRGetScreenInfo");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRConfigRotations = dlsym(xrandr->libXrandr, "XRRConfigRotations");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRFreeScreenConfigInfo = dlsym(xrandr->libXrandr,
+ "XRRFreeScreenConfigInfo");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRSetScreenConfig = dlsym(xrandr->libXrandr,
+ "XRRSetScreenConfig");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRRotations = dlsym(xrandr->libXrandr, "XRRRotations");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRSizes = dlsym(xrandr->libXrandr, "XRRSizes");
+ if ((error = dlerror()) != NULL) goto fail;
+
+
+ /* Verify rotation is supported */
+ ret = xrandr->XRRQueryExtension(h->dpy, &xrandr->event_base,
+ &xrandr->error_base);
+ if ( !ret ) goto fail;
+
+ xrandr->rotations = xrandr->XRRRotations(h->dpy, h->screen, &rotation);
+ sizes = xrandr->XRRSizes(h->dpy, h->screen, &(xrandr->nsizes));
+
+ /* Must support more than one rotation orientation */
+ if ( (xrandr->rotations == 1) || (xrandr->rotations == 2) ||
+ (xrandr->rotations == 4) || (xrandr->rotations == 8) ) {
+ goto fail;
+ }
+
+
+ /* Register to recieve XRandR events */
+ xrandr->XRRSelectInput(h->dpy, DefaultRootWindow(h->dpy),
+ RRScreenChangeNotifyMask);
+
+ // xrandr->rotations = 1;
+
+ return xrandr;
+
+
+ /* Handle failures */
+ fail:
+ if ( error != NULL ) {
+ nv_error_msg("libXrandr setup error : %s\n", error);
+ }
+ if ( xrandr != NULL ) {
+ if ( xrandr->libXrandr != NULL ) {
+ dlclose(xrandr->libXrandr);
+ }
+ free(xrandr);
+ }
+
+ return NULL;
+
+} /* NvCtrlInitXrandrAttributes() */
+
+
+
+/******************************************************************************
+ *
+ * Frees and relinquishes any resource used by the NvCtrlXrandrAttributes
+ * extension.
+ *
+ ****/
+
+void
+NvCtrlXrandrAttributesClose (NvCtrlAttributePrivateHandle *h)
+{
+ if ( h == NULL || h->xrandr == NULL ) {
+ return;
+ }
+
+ if ( h->xrandr->libXrandr != NULL ) {
+ dlclose( h->xrandr->libXrandr );
+ }
+
+ free(h->xrandr);
+ h->xrandr = NULL;
+
+} /* NvCtrlXrandrAttributesClose() */
+
+
+
+/******************************************************************************
+ *
+ * Retrieves XRandR integer attributes
+ *
+ ****/
+
+ReturnStatus
+NvCtrlXrandrGetAttribute (NvCtrlAttributePrivateHandle *h,
+ int attr, int *val)
+{
+ XRRScreenConfiguration *sc;
+ Rotation rotation;
+
+
+ /* Validate Arguments */
+ if ( h == NULL ) {
+ return NvCtrlBadHandle;
+ }
+ if ( h->xrandr == NULL ) {
+ return NvCtrlMissingExtension;
+ }
+ if ( val == NULL ) {
+ return NvCtrlBadArgument;
+ }
+
+
+ /* Fetch right attribute */
+ switch ( attr ) {
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION_SUPPORTED:
+ *val = ( (h->xrandr!=NULL)?1:0 );
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATIONS:
+ *val = h->xrandr->rotations;
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION:
+ sc = h->xrandr->XRRGetScreenInfo(h->dpy, DefaultRootWindow(h->dpy));
+ h->xrandr->XRRConfigRotations(sc, &rotation);
+ h->xrandr->XRRFreeScreenConfigInfo(sc);
+
+ *val = (int)rotation;
+ break;
+
+ default:
+ return NvCtrlNoAttribute;
+ break;
+ } /* Done fetching attribute */
+
+ return NvCtrlSuccess;
+
+} /* NvCtrlXrandrGetAttribute */
+
+
+
+/******************************************************************************
+ *
+ * Sets XRandR integer attributes
+ *
+ ****/
+
+ReturnStatus
+NvCtrlXrandrSetAttribute (NvCtrlAttributePrivateHandle *h,
+ int attr, int val)
+{
+ /* Validate Arguments */
+ if ( h == NULL ) {
+ return NvCtrlBadHandle;
+ }
+ if ( h->xrandr == NULL ) {
+ return NvCtrlMissingExtension;
+ }
+
+
+ /* Set right attribute */
+ switch ( attr ) {
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION_SUPPORTED:
+ return NvCtrlReadOnlyAttribute;
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATIONS:
+ return NvCtrlReadOnlyAttribute;
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION:
+ return set_rotation(h, (Rotation) val);
+ break;
+
+ default:
+ return NvCtrlNoAttribute;
+ break;
+ } /* Done setting attribute */
+
+ return NvCtrlSuccess;
+
+} /* NvCtrlXrandrSetAttribute */