summaryrefslogtreecommitdiff
path: root/app/xrandr/xrandr.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/xrandr/xrandr.c')
-rw-r--r--app/xrandr/xrandr.c1264
1 files changed, 863 insertions, 401 deletions
diff --git a/app/xrandr/xrandr.c b/app/xrandr/xrandr.c
index 10d034d44..0e3818fbe 100644
--- a/app/xrandr/xrandr.c
+++ b/app/xrandr/xrandr.c
@@ -2,6 +2,7 @@
* Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
* Copyright © 2002 Hewlett Packard Company, Inc.
* Copyright © 2006 Intel Corporation
+ * Copyright © 2013 NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -32,8 +33,11 @@
#include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/Xrender.h> /* we share subpixel information */
+#include <strings.h>
#include <string.h>
#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
#include <stdarg.h>
#include <math.h>
@@ -49,14 +53,14 @@ static Bool properties = False;
static Bool grab_server = True;
static Bool no_primary = False;
-static char *direction[5] = {
+static const char *direction[5] = {
"normal",
"left",
"inverted",
"right",
"\n"};
-static char *reflections[5] = {
+static const char *reflections[5] = {
"normal",
"x",
"y",
@@ -64,7 +68,7 @@ static char *reflections[5] = {
"\n"};
/* subpixel order */
-static char *order[6] = {
+static const char *order[6] = {
"unknown",
"horizontal rgb",
"horizontal bgr",
@@ -73,7 +77,7 @@ static char *order[6] = {
"no subpixels"};
static const struct {
- char *string;
+ const char *string;
unsigned long flag;
} mode_flags[] = {
{ "+HSync", RR_HSyncPositive },
@@ -88,65 +92,68 @@ static const struct {
{ NULL, 0 }
};
-static void _X_NORETURN
+static void
usage(void)
{
- fprintf(stderr, "usage: %s [options]\n", program_name);
- fprintf(stderr, " where options are:\n");
- fprintf(stderr, " -display <display> or -d <display>\n");
- fprintf(stderr, " -help\n");
- fprintf(stderr, " -o <normal,inverted,left,right,0,1,2,3>\n");
- fprintf(stderr, " or --orientation <normal,inverted,left,right,0,1,2,3>\n");
- fprintf(stderr, " -q or --query\n");
- fprintf(stderr, " -s <size>/<width>x<height> or --size <size>/<width>x<height>\n");
- fprintf(stderr, " -r <rate> or --rate <rate> or --refresh <rate>\n");
- fprintf(stderr, " -v or --version\n");
- fprintf(stderr, " -x (reflect in x)\n");
- fprintf(stderr, " -y (reflect in y)\n");
- fprintf(stderr, " --screen <screen>\n");
- fprintf(stderr, " --verbose\n");
- fprintf(stderr, " --current\n");
- fprintf(stderr, " --dryrun\n");
- fprintf(stderr, " --nograb\n");
- fprintf(stderr, " --prop or --properties\n");
- fprintf(stderr, " --fb <width>x<height>\n");
- fprintf(stderr, " --fbmm <width>x<height>\n");
- fprintf(stderr, " --dpi <dpi>/<output>\n");
- fprintf(stderr, " --output <output>\n");
- fprintf(stderr, " --auto\n");
- fprintf(stderr, " --mode <mode>\n");
- fprintf(stderr, " --preferred\n");
- fprintf(stderr, " --pos <x>x<y>\n");
- fprintf(stderr, " --rate <rate> or --refresh <rate>\n");
- fprintf(stderr, " --reflect normal,x,y,xy\n");
- fprintf(stderr, " --rotate normal,inverted,left,right\n");
- fprintf(stderr, " --left-of <output>\n");
- fprintf(stderr, " --right-of <output>\n");
- fprintf(stderr, " --above <output>\n");
- fprintf(stderr, " --below <output>\n");
- fprintf(stderr, " --same-as <output>\n");
- fprintf(stderr, " --set <property> <value>\n");
- fprintf(stderr, " --scale <x>x<y>\n");
- fprintf(stderr, " --transform <a>,<b>,<c>,<d>,<e>,<f>,<g>,<h>,<i>\n");
- fprintf(stderr, " --off\n");
- fprintf(stderr, " --crtc <crtc>\n");
- fprintf(stderr, " --panning <w>x<h>[+<x>+<y>[/<track:w>x<h>+<x>+<y>[/<border:l>/<t>/<r>/<b>]]]\n");
- fprintf(stderr, " --gamma <r>:<g>:<b>\n");
- fprintf(stderr, " --primary\n");
- fprintf(stderr, " --noprimary\n");
- fprintf(stderr, " --newmode <name> <clock MHz>\n");
- fprintf(stderr, " <hdisp> <hsync-start> <hsync-end> <htotal>\n");
- fprintf(stderr, " <vdisp> <vsync-start> <vsync-end> <vtotal>\n");
- fprintf(stderr, " [+HSync] [-HSync] [+VSync] [-VSync]\n");
- fprintf(stderr, " --rmmode <name>\n");
- fprintf(stderr, " --addmode <output> <name>\n");
- fprintf(stderr, " --delmode <output> <name>\n");
-
- exit(1);
- /*NOTREACHED*/
-}
-
-static void _X_NORETURN
+ printf("usage: %s [options]\n", program_name);
+ printf(" where options are:\n");
+ printf(" -display <display> or -d <display>\n");
+ printf(" --help\n");
+ printf(" -o <normal,inverted,left,right,0,1,2,3>\n");
+ printf(" or --orientation <normal,inverted,left,right,0,1,2,3>\n");
+ printf(" -q or --query\n");
+ printf(" -s <size>/<width>x<height> or --size <size>/<width>x<height>\n");
+ printf(" -r <rate> or --rate <rate> or --refresh <rate>\n");
+ printf(" -v or --version\n");
+ printf(" -x (reflect in x)\n");
+ printf(" -y (reflect in y)\n");
+ printf(" --screen <screen>\n");
+ printf(" --verbose\n");
+ printf(" --current\n");
+ printf(" --dryrun\n");
+ printf(" --nograb\n");
+ printf(" --prop or --properties\n");
+ printf(" --fb <width>x<height>\n");
+ printf(" --fbmm <width>x<height>\n");
+ printf(" --dpi <dpi>/<output>\n");
+ printf(" --output <output>\n");
+ printf(" --auto\n");
+ printf(" --mode <mode>\n");
+ printf(" --preferred\n");
+ printf(" --pos <x>x<y>\n");
+ printf(" --rate <rate> or --refresh <rate>\n");
+ printf(" --reflect normal,x,y,xy\n");
+ printf(" --rotate normal,inverted,left,right\n");
+ printf(" --left-of <output>\n");
+ printf(" --right-of <output>\n");
+ printf(" --above <output>\n");
+ printf(" --below <output>\n");
+ printf(" --same-as <output>\n");
+ printf(" --set <property> <value>\n");
+ printf(" --scale <x>x<y>\n");
+ printf(" --scale-from <w>x<h>\n");
+ printf(" --transform <a>,<b>,<c>,<d>,<e>,<f>,<g>,<h>,<i>\n");
+ printf(" --off\n");
+ printf(" --crtc <crtc>\n");
+ printf(" --panning <w>x<h>[+<x>+<y>[/<track:w>x<h>+<x>+<y>[/<border:l>/<t>/<r>/<b>]]]\n");
+ printf(" --gamma <r>:<g>:<b>\n");
+ printf(" --primary\n");
+ printf(" --noprimary\n");
+ printf(" --newmode <name> <clock MHz>\n");
+ printf(" <hdisp> <hsync-start> <hsync-end> <htotal>\n");
+ printf(" <vdisp> <vsync-start> <vsync-end> <vtotal>\n");
+ printf(" [flags...]\n");
+ printf(" Valid flags: +HSync -HSync +VSync -VSync\n");
+ printf(" +CSync -CSync CSync Interlace DoubleScan\n");
+ printf(" --rmmode <name>\n");
+ printf(" --addmode <output> <name>\n");
+ printf(" --delmode <output> <name>\n");
+ printf(" --listproviders\n");
+ printf(" --setprovideroutputsource <prov-xid> <source-xid>\n");
+ printf(" --setprovideroffloadsink <prov-xid> <sink-xid>\n");
+}
+
+static void _X_NORETURN _X_ATTRIBUTE_PRINTF(1,2)
fatal (const char *format, ...)
{
va_list ap;
@@ -159,7 +166,7 @@ fatal (const char *format, ...)
/*NOTREACHED*/
}
-static void
+static void _X_ATTRIBUTE_PRINTF(1,2)
warning (const char *format, ...)
{
va_list ap;
@@ -170,13 +177,27 @@ warning (const char *format, ...)
va_end (ap);
}
+static void _X_NORETURN _X_ATTRIBUTE_PRINTF(1,2)
+argerr (const char *format, ...)
+{
+ va_list ap;
+
+ va_start (ap, format);
+ fprintf (stderr, "%s: ", program_name);
+ vfprintf (stderr, format, ap);
+ fprintf (stderr, "Try '%s --help' for more information.\n", program_name);
+ va_end (ap);
+ exit (1);
+ /*NOTREACHED*/
+}
+
/* Because fmin requires C99 suppport */
static inline double dmin (double x, double y)
{
return x < y ? x : y;
}
-static char *
+static const char *
rotation_name (Rotation rotation)
{
int i;
@@ -189,7 +210,7 @@ rotation_name (Rotation rotation)
return "invalid rotation";
}
-static char *
+static const char *
reflection_name (Rotation rotation)
{
rotation &= (RR_Reflect_X|RR_Reflect_Y);
@@ -206,6 +227,22 @@ reflection_name (Rotation rotation)
return "invalid reflection";
}
+static char *
+capability_name (int cap_bit)
+{
+ switch (cap_bit) {
+ case RR_Capability_SourceOutput:
+ return "Source Output";
+ case RR_Capability_SinkOutput:
+ return "Sink Output";
+ case RR_Capability_SourceOffload:
+ return "Source Offload";
+ case RR_Capability_SinkOffload:
+ return "Sink Offload";
+ }
+ return "invalid capability";
+}
+
typedef enum _relation {
relation_left_of,
relation_right_of,
@@ -263,10 +300,11 @@ typedef struct _output output_t;
typedef struct _transform transform_t;
typedef struct _umode umode_t;
typedef struct _output_prop output_prop_t;
+typedef struct _provider provider_t;
struct _transform {
XTransform transform;
- char *filter;
+ const char *filter;
int nparams;
XFixed *params;
};
@@ -321,6 +359,7 @@ struct _output {
XRRPanning panning;
Bool automatic;
+ int scale_from_w, scale_from_h;
transform_t transform;
struct {
@@ -350,7 +389,12 @@ struct _umode {
name_t name;
};
-static char *connection[3] = {
+struct _provider {
+ name_t provider;
+ XRRProviderInfo *info;
+};
+
+static const char *connection[3] = {
"connected",
"disconnected",
"unknown connection"};
@@ -368,20 +412,23 @@ static char *connection[3] = {
#define POS_UNSET -1
-static output_t *outputs = NULL;
-static output_t **outputs_tail = &outputs;
+static output_t *all_outputs = NULL;
+static output_t **all_outputs_tail = &all_outputs;
static crtc_t *crtcs;
+static provider_t *providers;
static umode_t *umodes;
-static int num_crtcs;
+static int num_crtcs, num_providers;
static XRRScreenResources *res;
static int fb_width = 0, fb_height = 0;
static int fb_width_mm = 0, fb_height_mm = 0;
static double dpi = 0;
-static char *dpi_output = NULL;
+static char *dpi_output_name = NULL;
static Bool dryrun = False;
static int minWidth, maxWidth, minHeight, maxHeight;
static Bool has_1_2 = False;
static Bool has_1_3 = False;
+static Bool has_1_4 = False;
+static name_t provider_name, output_source_provider_name, offload_sink_provider_name;
static int
mode_height (XRRModeInfo *mode_info, Rotation rotation)
@@ -429,14 +476,15 @@ transform_point (XTransform *transform, double *xp, double *yp)
v = 0;
for (i = 0; i < 3; i++)
v += (XFixedToDouble (transform->matrix[j][i]) * vector[i]);
- if (v > 32767 || v < -32767)
- return False;
result[j] = v;
}
if (!result[2])
return False;
- for (j = 0; j < 2; j++)
+ for (j = 0; j < 2; j++) {
vector[j] = result[j] / result[2];
+ if (vector[j] > 32767 || vector[j] < -32767)
+ return False;
+ }
*xp = vector[0];
*yp = vector[1];
return True;
@@ -493,10 +541,22 @@ static double
mode_refresh (XRRModeInfo *mode_info)
{
double rate;
+ unsigned int vTotal = mode_info->vTotal;
+
+ if (mode_info->modeFlags & RR_DoubleScan) {
+ /* doublescan doubles the number of lines */
+ vTotal *= 2;
+ }
+
+ if (mode_info->modeFlags & RR_Interlace) {
+ /* interlace splits the frame into two fields */
+ /* the field rate is what is typically reported by monitors */
+ vTotal /= 2;
+ }
- if (mode_info->hTotal && mode_info->vTotal)
+ if (mode_info->hTotal && vTotal)
rate = ((double) mode_info->dotClock /
- ((double) mode_info->hTotal * (double) mode_info->vTotal));
+ ((double) mode_info->hTotal * (double) vTotal));
else
rate = 0;
return rate;
@@ -536,10 +596,10 @@ set_name_xid (name_t *name, XID xid)
}
static void
-set_name_index (name_t *name, int index)
+set_name_index (name_t *name, int idx)
{
name->kind |= name_index;
- name->index = index;
+ name->index = idx;
}
static void
@@ -565,16 +625,27 @@ set_name (name_t *name, char *string, name_kind_t valid)
{
unsigned int xid; /* don't make it XID (which is unsigned long):
scanf() takes unsigned int */
- int index;
+ int idx;
if ((valid & name_xid) && sscanf (string, "0x%x", &xid) == 1)
set_name_xid (name, xid);
- else if ((valid & name_index) && sscanf (string, "%d", &index) == 1)
- set_name_index (name, index);
+ else if ((valid & name_index) && sscanf (string, "%d", &idx) == 1)
+ set_name_index (name, idx);
else if (valid & name_string)
set_name_string (name, string);
else
- usage ();
+ argerr ("invalid name '%s'\n", string);
+}
+
+static int
+print_name (const name_t *name)
+{
+ name_kind_t kind = name->kind;
+
+ if ((kind & name_xid)) return printf("XID 0x%x", (unsigned int)name->xid);
+ else if ((kind & name_string)) return printf("name %s", name->string);
+ else if ((kind & name_index)) return printf("index %d", name->index);
+ else return printf("unknown name");
}
static void
@@ -592,11 +663,12 @@ init_transform (transform_t *transform)
static void
set_transform (transform_t *dest,
XTransform *transform,
- char *filter,
+ const char *filter,
XFixed *params,
int nparams)
{
dest->transform = *transform;
+ /* note: this string is leaked */
dest->filter = strdup (filter);
dest->nparams = nparams;
dest->params = malloc (nparams * sizeof (XFixed));
@@ -634,8 +706,8 @@ add_output (void)
output->next = NULL;
output->found = False;
output->brightness = 1.0;
- *outputs_tail = output;
- outputs_tail = &output->next;
+ *all_outputs_tail = output;
+ all_outputs_tail = &output->next;
return output;
}
@@ -644,7 +716,7 @@ find_output (name_t *name)
{
output_t *output;
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
name_kind_t common = name->kind & output->output.kind;
@@ -957,7 +1029,7 @@ find_last_non_clamped(CARD16 array[], int size) {
static void
set_gamma_info(output_t *output)
{
- XRRCrtcGamma *gamma;
+ XRRCrtcGamma *crtc_gamma;
double i1, v1, i2, v2;
int size, middle, last_best, last_red, last_green, last_blue;
CARD16 *best_array;
@@ -971,8 +1043,8 @@ set_gamma_info(output_t *output)
return;
}
- gamma = XRRGetCrtcGamma(dpy, output->crtc_info->crtc.xid);
- if (!gamma) {
+ crtc_gamma = XRRGetCrtcGamma(dpy, output->crtc_info->crtc.xid);
+ if (!crtc_gamma) {
warning("Failed to get gamma for output %s\n", output->output.string);
return;
}
@@ -991,18 +1063,18 @@ set_gamma_info(output_t *output)
* clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal
* cases), then b = v2.
*/
- last_red = find_last_non_clamped(gamma->red, size);
- last_green = find_last_non_clamped(gamma->green, size);
- last_blue = find_last_non_clamped(gamma->blue, size);
- best_array = gamma->red;
+ last_red = find_last_non_clamped(crtc_gamma->red, size);
+ last_green = find_last_non_clamped(crtc_gamma->green, size);
+ last_blue = find_last_non_clamped(crtc_gamma->blue, size);
+ best_array = crtc_gamma->red;
last_best = last_red;
if (last_green > last_best) {
last_best = last_green;
- best_array = gamma->green;
+ best_array = crtc_gamma->green;
}
if (last_blue > last_best) {
last_best = last_blue;
- best_array = gamma->blue;
+ best_array = crtc_gamma->blue;
}
if (last_best == 0)
last_best = 1;
@@ -1022,15 +1094,15 @@ set_gamma_info(output_t *output)
output->brightness = v2;
else
output->brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2));
- output->gamma.red = log((double)(gamma->red[last_red / 2]) / output->brightness
+ output->gamma.red = log((double)(crtc_gamma->red[last_red / 2]) / output->brightness
/ 65535) / log((double)((last_red / 2) + 1) / size);
- output->gamma.green = log((double)(gamma->green[last_green / 2]) / output->brightness
+ output->gamma.green = log((double)(crtc_gamma->green[last_green / 2]) / output->brightness
/ 65535) / log((double)((last_green / 2) + 1) / size);
- output->gamma.blue = log((double)(gamma->blue[last_blue / 2]) / output->brightness
+ output->gamma.blue = log((double)(crtc_gamma->blue[last_blue / 2]) / output->brightness
/ 65535) / log((double)((last_blue / 2) + 1) / size);
}
- XRRFreeGamma(gamma);
+ XRRFreeGamma(crtc_gamma);
}
static void
@@ -1060,19 +1132,25 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
if (!output->crtc_info)
{
if (output->crtc.kind & name_xid)
- fatal ("cannot find crtc 0x%x\n", output->crtc.xid);
+ fatal ("cannot find crtc 0x%lx\n", output->crtc.xid);
if (output->crtc.kind & name_index)
fatal ("cannot find crtc %d\n", output->crtc.index);
}
if (!output_can_use_crtc (output, output->crtc_info))
- fatal ("output %s cannot use crtc 0x%x\n", output->output.string,
+ fatal ("output %s cannot use crtc 0x%lx\n", output->output.string,
output->crtc_info->crtc.xid);
}
/* set mode name and info */
if (!(output->changes & changes_mode))
{
- if (output->crtc_info)
+ crtc_t *crtc = NULL;
+
+ if (output_info->crtc)
+ crtc = find_crtc_by_xid(output_info->crtc);
+ if (crtc && crtc->crtc_info)
+ set_name_xid (&output->mode, crtc->crtc_info->mode);
+ else if (output->crtc_info)
set_name_xid (&output->mode, output->crtc_info->crtc_info->mode);
else
set_name_xid (&output->mode, None);
@@ -1080,7 +1158,7 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
{
output->mode_info = find_mode_by_xid (output->mode.xid);
if (!output->mode_info)
- fatal ("server did not report mode 0x%x for output %s\n",
+ fatal ("server did not report mode 0x%lx for output %s\n",
output->mode.xid, output->output.string);
}
else
@@ -1101,7 +1179,7 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
if (output->mode.kind & name_string)
fatal ("cannot find mode %s\n", output->mode.string);
if (output->mode.kind & name_xid)
- fatal ("cannot find mode 0x%x\n", output->mode.xid);
+ fatal ("cannot find mode 0x%lx\n", output->mode.xid);
}
if (!output_can_use_mode (output, output->mode_info))
fatal ("output %s cannot use mode %s\n", output->output.string,
@@ -1156,6 +1234,30 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
copy_transform (&output->transform, &output->crtc_info->current_transform);
else
init_transform (&output->transform);
+ } else {
+ /* transform was already set for --scale or --transform */
+
+ /* for --scale-from, figure out the mode size and compute the transform
+ * for the target framebuffer area */
+ if (output->scale_from_w > 0 && output->mode_info) {
+ double sx = (double)output->scale_from_w /
+ output->mode_info->width;
+ double sy = (double)output->scale_from_h /
+ output->mode_info->height;
+ if (verbose)
+ printf("scaling %s by %lfx%lf\n", output->output.string, sx,
+ sy);
+ init_transform (&output->transform);
+ output->transform.transform.matrix[0][0] = XDoubleToFixed (sx);
+ output->transform.transform.matrix[1][1] = XDoubleToFixed (sy);
+ output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0);
+ if (sx != 1 || sy != 1)
+ output->transform.filter = "bilinear";
+ else
+ output->transform.filter = "nearest";
+ output->transform.nparams = 0;
+ output->transform.params = NULL;
+ }
}
/* set primary */
@@ -1168,7 +1270,10 @@ get_screen (Bool current)
{
if (!has_1_2)
fatal ("Server RandR version before 1.2\n");
-
+
+ if (res)
+ return;
+
XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight,
&maxWidth, &maxHeight);
@@ -1207,7 +1312,7 @@ get_crtcs (void)
set_name_xid (&crtcs[c].crtc, res->crtcs[c]);
set_name_index (&crtcs[c].crtc, c);
- if (!crtc_info) fatal ("could not get crtc 0x%x information\n", res->crtcs[c]);
+ if (!crtc_info) fatal ("could not get crtc 0x%lx information\n", res->crtcs[c]);
crtcs[c].crtc_info = crtc_info;
crtcs[c].panning_info = panning_info;
if (crtc_info->mode == None)
@@ -1256,7 +1361,7 @@ set_crtcs (void)
{
output_t *output;
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
if (!output->mode_info) continue;
crtc_add_output (output->crtc_info, output);
@@ -1268,7 +1373,7 @@ set_panning (void)
{
output_t *output;
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
if (! output->crtc_info)
continue;
@@ -1286,10 +1391,13 @@ set_gamma(void)
{
output_t *output;
- for (output = outputs; output; output = output->next) {
- int i, size;
+ for (output = all_outputs; output; output = output->next) {
+ int i, size, shift;
crtc_t *crtc;
- XRRCrtcGamma *gamma;
+ XRRCrtcGamma *crtc_gamma;
+ float gammaRed;
+ float gammaGreen;
+ float gammaBlue;
if (!(output->changes & changes_gamma))
continue;
@@ -1308,41 +1416,71 @@ set_gamma(void)
continue;
}
- gamma = XRRAllocGamma(size);
- if (!gamma) {
+ /*
+ * The gamma-correction lookup table managed through XRR[GS]etCrtcGamma
+ * is 2^n in size, where 'n' is the number of significant bits in
+ * the X Color. Because an X Color is 16 bits, size cannot be larger
+ * than 2^16.
+ */
+ if (size > 65536) {
+ fatal("Gamma correction table is impossibly large.\n");
+ continue;
+ }
+
+ /*
+ * The hardware color lookup table has a number of significant
+ * bits equal to ffs(size) - 1; compute all values so that
+ * they are in the range [0,size) then shift the values so
+ * that they occupy the MSBs of the 16-bit X Color.
+ */
+ shift = 16 - (ffs(size) - 1);
+
+ crtc_gamma = XRRAllocGamma(size);
+ if (!crtc_gamma) {
fatal("Gamma allocation failed.\n");
continue;
}
- if(output->gamma.red == 0.0 && output->gamma.green == 0.0 && output->gamma.blue == 0.0)
- output->gamma.red = output->gamma.green = output->gamma.blue = 1.0;
+ if (output->gamma.red == 0.0)
+ output->gamma.red = 1.0;
+ if (output->gamma.green == 0.0)
+ output->gamma.green = 1.0;
+ if (output->gamma.blue == 0.0)
+ output->gamma.blue = 1.0;
+
+ gammaRed = 1.0 / output->gamma.red;
+ gammaGreen = 1.0 / output->gamma.green;
+ gammaBlue = 1.0 / output->gamma.blue;
for (i = 0; i < size; i++) {
- if (output->gamma.red == 1.0 && output->brightness == 1.0)
- gamma->red[i] = (i << 8) + i;
+ if (gammaRed == 1.0 && output->brightness == 1.0)
+ crtc_gamma->red[i] = i;
else
- gamma->red[i] = dmin(pow((double)i/(double)(size - 1),
- output->gamma.red) * output->brightness,
- 1.0) * 65535.0;
+ crtc_gamma->red[i] = dmin(pow((double)i/(double)(size - 1),
+ gammaRed) * output->brightness,
+ 1.0) * (double)(size - 1);
+ crtc_gamma->red[i] <<= shift;
- if (output->gamma.green == 1.0 && output->brightness == 1.0)
- gamma->green[i] = (i << 8) + i;
+ if (gammaGreen == 1.0 && output->brightness == 1.0)
+ crtc_gamma->green[i] = i;
else
- gamma->green[i] = dmin(pow((double)i/(double)(size - 1),
- output->gamma.green) * output->brightness,
- 1.0) * 65535.0;
+ crtc_gamma->green[i] = dmin(pow((double)i/(double)(size - 1),
+ gammaGreen) * output->brightness,
+ 1.0) * (double)(size - 1);
+ crtc_gamma->green[i] <<= shift;
- if (output->gamma.blue == 1.0 && output->brightness == 1.0)
- gamma->blue[i] = (i << 8) + i;
+ if (gammaBlue == 1.0 && output->brightness == 1.0)
+ crtc_gamma->blue[i] = i;
else
- gamma->blue[i] = dmin(pow((double)i/(double)(size - 1),
- output->gamma.blue) * output->brightness,
- 1.0) * 65535.0;
+ crtc_gamma->blue[i] = dmin(pow((double)i/(double)(size - 1),
+ gammaBlue) * output->brightness,
+ 1.0) * (double)(size - 1);
+ crtc_gamma->blue[i] <<= shift;
}
- XRRSetCrtcGamma(dpy, crtc->crtc.xid, gamma);
+ XRRSetCrtcGamma(dpy, crtc->crtc.xid, crtc_gamma);
- free(gamma);
+ free(crtc_gamma);
}
}
@@ -1354,7 +1492,7 @@ set_primary(void)
if (no_primary) {
XRRSetOutputPrimary(dpy, root, None);
} else {
- for (output = outputs; output; output = output->next) {
+ for (output = all_outputs; output; output = output->next) {
if (!(output->changes & changes_primary))
continue;
if (output->primary)
@@ -1512,7 +1650,7 @@ static void _X_NORETURN
panic (Status s, crtc_t *crtc)
{
int c = crtc->crtc.index;
- char *message;
+ const char *message;
switch (s) {
case RRSetConfigSuccess: message = "succeeded"; break;
@@ -1631,7 +1769,7 @@ get_outputs (void)
XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]);
output_t *output;
name_t output_name;
- if (!output_info) fatal ("could not get output 0x%x information\n", res->outputs[o]);
+ if (!output_info) fatal ("could not get output 0x%lx information\n", res->outputs[o]);
set_name_xid (&output_name, res->outputs[o]);
set_name_index (&output_name, o);
set_name_string (&output_name, output_info->name);
@@ -1694,7 +1832,7 @@ get_outputs (void)
set_output_info (output, res->outputs[o], output_info);
}
- for (q = outputs; q; q = q->next)
+ for (q = all_outputs; q; q = q->next)
{
if (!q->found)
{
@@ -1719,7 +1857,7 @@ mark_changing_crtcs (void)
for (o = 0; o < crtc->crtc_info->noutput; o++)
{
output = find_output_by_xid (crtc->crtc_info->outputs[o]);
- if (!output) fatal ("cannot find output 0x%x\n",
+ if (!output) fatal ("cannot find output 0x%lx\n",
crtc->crtc_info->outputs[o]);
if (output->changes)
crtc->changing = True;
@@ -1749,7 +1887,7 @@ check_crtc_for_output (crtc_t *crtc, output_t *output)
break;
if (c == output->output_info->ncrtc)
return False;
- for (other = outputs; other; other = other->next)
+ for (other = all_outputs; other; other = other->next)
{
if (other == output)
continue;
@@ -1810,7 +1948,7 @@ find_crtc_for_output (output_t *output)
crtc_t *crtc;
crtc = find_crtc_by_xid (output->output_info->crtcs[c]);
- if (!crtc) fatal ("cannot find crtc 0x%x\n", output->output_info->crtcs[c]);
+ if (!crtc) fatal ("cannot find crtc 0x%lx\n", output->output_info->crtcs[c]);
if (check_crtc_for_output (crtc, output))
return crtc;
@@ -1830,7 +1968,7 @@ set_positions (void)
{
any_set = False;
keep_going = False;
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
output_t *relation;
name_t relation_name;
@@ -1897,7 +2035,7 @@ set_positions (void)
*/
min_x = 32768;
min_y = 32768;
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
if (output->mode_info == NULL) continue;
@@ -1907,7 +2045,7 @@ set_positions (void)
if (min_x || min_y)
{
/* move all outputs */
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
if (output->mode_info == NULL) continue;
@@ -1924,7 +2062,7 @@ set_screen_size (void)
output_t *output;
Bool fb_specified = fb_width != 0 && fb_height != 0;
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
XRRModeInfo *mode_info = output->mode_info;
int x, y, w, h;
@@ -2027,7 +2165,7 @@ pick_crtcs_score (output_t *outputs)
crtc = find_crtc_by_xid (output->output_info->crtcs[c]);
if (!crtc)
- fatal ("cannot find crtc 0x%x\n", output->output_info->crtcs[c]);
+ fatal ("cannot find crtc 0x%lx\n", output->output_info->crtcs[c]);
/* reset crtc allocation for following outputs */
disable_outputs (outputs);
@@ -2068,7 +2206,7 @@ pick_crtcs (void)
/*
* First try to match up newly enabled outputs with spare crtcs
*/
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
if (output->changes && output->mode_info)
{
@@ -2093,10 +2231,10 @@ pick_crtcs (void)
* When the simple way fails, see if there is a way
* to swap crtcs around and make things work
*/
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
output->current_crtc_info = output->crtc_info;
- pick_crtcs_score (outputs);
- for (output = outputs; output; output = output->next)
+ pick_crtcs_score (all_outputs);
+ for (output = all_outputs; output; output = output->next)
{
if (output->mode_info && !output->crtc_info)
fatal ("cannot find crtc for output %s\n", output->output.string);
@@ -2111,7 +2249,7 @@ check_strtol(char *s)
char *endptr;
int result = strtol(s, &endptr, 10);
if (s == endptr)
- usage();
+ argerr ("failed to parse '%s' as a number\n", s);
return result;
}
@@ -2121,10 +2259,212 @@ check_strtod(char *s)
char *endptr;
double result = strtod(s, &endptr);
if (s == endptr)
- usage();
+ argerr ("failed to parse '%s' as a number\n", s);
return result;
}
+
+static void *
+property_values_from_string(const char *str, const Atom type, const int format,
+ int *returned_nitems)
+{
+ char *token, *tmp;
+ void *returned_bytes = NULL;
+ int nitems = 0, bytes_per_item = format / 8;
+
+ if ((type != XA_INTEGER && type != XA_CARDINAL) ||
+ (format != 8 && format != 16 && format != 32))
+ {
+ return NULL;
+ }
+
+ tmp = strdup (str);
+
+ for (token = strtok (tmp, ","); token; token = strtok (NULL, ","))
+ {
+ char *endptr;
+ long int val = strtol (token, &endptr, 0);
+
+ if (token == endptr || *endptr != '\0')
+ {
+ argerr ("failed to parse '%s' as a number\n", token);
+ }
+
+ returned_bytes = realloc (returned_bytes, (nitems + 1) * bytes_per_item);
+
+ if (type == XA_INTEGER && format == 8)
+ {
+ int8_t *ptr = returned_bytes;
+ ptr[nitems] = (int8_t) val;
+ }
+ else if (type == XA_INTEGER && format == 16)
+ {
+ int16_t *ptr = returned_bytes;
+ ptr[nitems] = (int16_t) val;
+ }
+ else if (type == XA_INTEGER && format == 32)
+ {
+ int32_t *ptr = returned_bytes;
+ ptr[nitems] = (int32_t) val;
+ }
+ else if (type == XA_CARDINAL && format == 8)
+ {
+ uint8_t *ptr = returned_bytes;
+ ptr[nitems] = (uint8_t) val;
+ }
+ else if (type == XA_CARDINAL && format == 16)
+ {
+ uint16_t *ptr = returned_bytes;
+ ptr[nitems] = (uint16_t) val;
+ }
+ else if (type == XA_CARDINAL && format == 32)
+ {
+ uint32_t *ptr = returned_bytes;
+ ptr[nitems] = (uint32_t) val;
+ }
+ else
+ {
+ free (tmp);
+ free (returned_bytes);
+ return NULL;
+ }
+
+ nitems++;
+ }
+
+ free (tmp);
+
+ *returned_nitems = nitems;
+ return returned_bytes;
+}
+
+
+static void
+print_output_property_value(Bool is_edid,
+ int value_format, /* 8, 16, 32 */
+ Atom value_type, /* XA_{ATOM,INTEGER,CARDINAL} */
+ const void *value_bytes)
+{
+ /* special-case the EDID */
+ if (is_edid && value_format == 8)
+ {
+ const uint8_t *val = value_bytes;
+ printf ("%02" PRIx8, *val);
+ return;
+ }
+
+ if (value_type == XA_ATOM && value_format == 32)
+ {
+ const Atom *val = value_bytes;
+ char *str = XGetAtomName (dpy, *val);
+ if (str != NULL)
+ {
+ printf ("%s", str);
+ XFree (str);
+ return;
+ }
+ }
+
+ if (value_type == XA_INTEGER)
+ {
+ if (value_format == 8)
+ {
+ const int8_t *val = value_bytes;
+ printf ("%" PRId8, *val);
+ return;
+ }
+ if (value_format == 16)
+ {
+ const int16_t *val = value_bytes;
+ printf ("%" PRId16, *val);
+ return;
+ }
+ if (value_format == 32)
+ {
+ const int32_t *val = value_bytes;
+ printf ("%" PRId32, *val);
+ return;
+ }
+ }
+
+ if (value_type == XA_CARDINAL)
+ {
+ if (value_format == 8)
+ {
+ const uint8_t *val = value_bytes;
+ printf ("%" PRIu8, *val);
+ return;
+ }
+ if (value_format == 16)
+ {
+ const uint16_t *val = value_bytes;
+ printf ("%" PRIu16, *val);
+ return;
+ }
+ if (value_format == 32)
+ {
+ const uint32_t *val = value_bytes;
+ printf ("%" PRIu32, *val);
+ return;
+ }
+ }
+
+ printf ("?");
+}
+
+static void
+get_providers (void)
+{
+ XRRProviderResources *pr;
+ int i;
+
+ if (!has_1_4 || providers)
+ return;
+
+ pr = XRRGetProviderResources(dpy, root);
+ num_providers = pr->nproviders;
+ providers = calloc (num_providers, sizeof (provider_t));
+ if (!providers)
+ fatal ("out of memory\n");
+
+ for (i = 0; i < num_providers; i++) {
+ provider_t *provider = &providers[i];
+ name_t *name = &provider->provider;
+ XRRProviderInfo *info = XRRGetProviderInfo(dpy, res, pr->providers[i]);
+
+ provider->info = info;
+ set_name_xid (name, pr->providers[i]);
+ set_name_index (name, i);
+ set_name_string (name, info->name);
+ }
+
+ XRRFreeProviderResources(pr);
+}
+
+static provider_t *
+find_provider (name_t *name)
+{
+ int i;
+
+ for (i = 0; i < num_providers; i++) {
+ provider_t *p = &providers[i];
+ name_kind_t common = name->kind & p->provider.kind;
+
+ if ((common & name_xid) && name->xid == p->provider.xid)
+ return p;
+ if ((common & name_string) && !strcmp (name->string, p->provider.string))
+ return p;
+ if ((common & name_index) && name->index == p->provider.index)
+ return p;
+ }
+
+ printf ("Could not find provider with ");
+ print_name (name);
+ printf ("\n");
+ exit (1);
+}
+
+
int
main (int argc, char **argv)
{
@@ -2137,11 +2477,11 @@ main (int argc, char **argv)
int rot = -1;
int query = False;
int action_requested = False;
- Rotation rotation, current_rotation, rotations;
+ Rotation current_rotation;
XEvent event;
XRRScreenChangeNotifyEvent *sce;
char *display_name = NULL;
- int i, j;
+ int i;
SizeID current_size;
short current_rate;
double rate = -1;
@@ -2154,26 +2494,28 @@ main (int argc, char **argv)
int width = 0, height = 0;
Bool have_pixel_size = False;
int ret = 0;
- output_t *output = NULL;
+ output_t *config_output = NULL;
Bool setit_1_2 = False;
Bool query_1_2 = False;
Bool modeit = False;
Bool propit = False;
Bool query_1 = False;
+ Bool list_providers = False;
+ Bool provsetoutsource = False;
+ Bool provsetoffsink = False;
int major, minor;
Bool current = False;
program_name = argv[0];
for (i = 1; i < argc; i++) {
if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
display_name = argv[i];
continue;
}
- if (!strcmp("-help", argv[i])) {
+ if (!strcmp("-help", argv[i]) || !strcmp("--help", argv[i])) {
usage();
- action_requested = True;
- continue;
+ exit(0);
}
if (!strcmp ("--verbose", argv[i])) {
verbose = True;
@@ -2194,12 +2536,12 @@ main (int argc, char **argv)
}
if (!strcmp ("-s", argv[i]) || !strcmp ("--size", argv[i])) {
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
if (sscanf (argv[i], "%dx%d", &width, &height) == 2) {
have_pixel_size = True;
} else {
size = check_strtol(argv[i]);
- if (size < 0) usage();
+ if (size < 0) argerr ("--size argument must be nonnegative\n");
}
setit = True;
action_requested = True;
@@ -2210,13 +2552,13 @@ main (int argc, char **argv)
!strcmp ("--rate", argv[i]) ||
!strcmp ("--refresh", argv[i]))
{
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
rate = check_strtod(argv[i]);
setit = True;
- if (output)
+ if (config_output)
{
- output->refresh = rate;
- output->changes |= changes_refresh;
+ config_output->refresh = rate;
+ config_output->changes |= changes_refresh;
setit_1_2 = True;
}
action_requested = True;
@@ -2242,9 +2584,9 @@ main (int argc, char **argv)
continue;
}
if (!strcmp ("--screen", argv[i])) {
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
screen = check_strtol(argv[i]);
- if (screen < 0) usage();
+ if (screen < 0) argerr ("--screen argument must be nonnegative\n");
continue;
}
if (!strcmp ("-q", argv[i]) || !strcmp ("--query", argv[i])) {
@@ -2253,14 +2595,15 @@ main (int argc, char **argv)
}
if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) {
char *endptr;
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
dirind = strtol(argv[i], &endptr, 10);
if (argv[i] == endptr) {
for (dirind = 0; dirind < 4; dirind++) {
if (strcmp (direction[dirind], argv[i]) == 0) break;
}
- if ((dirind < 0) || (dirind > 3)) usage();
}
+ if ((dirind < 0) || (dirind > 3))
+ argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]);
rot = dirind;
setit = True;
action_requested = True;
@@ -2277,12 +2620,12 @@ main (int argc, char **argv)
continue;
}
if (!strcmp ("--output", argv[i])) {
- if (++i >= argc) usage();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
- output = find_output_by_name (argv[i]);
- if (!output) {
- output = add_output ();
- set_name (&output->output, argv[i], name_string|name_xid);
+ config_output = find_output_by_name (argv[i]);
+ if (!config_output) {
+ config_output = add_output ();
+ set_name (&config_output->output, argv[i], name_string|name_xid);
}
setit_1_2 = True;
@@ -2290,105 +2633,105 @@ main (int argc, char **argv)
continue;
}
if (!strcmp ("--crtc", argv[i])) {
- if (++i >= argc) usage();
- if (!output) usage();
- set_name (&output->crtc, argv[i], name_xid|name_index);
- output->changes |= changes_crtc;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ set_name (&config_output->crtc, argv[i], name_xid|name_index);
+ config_output->changes |= changes_crtc;
continue;
}
if (!strcmp ("--mode", argv[i])) {
- if (++i >= argc) usage();
- if (!output) usage();
- set_name (&output->mode, argv[i], name_string|name_xid);
- output->changes |= changes_mode;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ set_name (&config_output->mode, argv[i], name_string|name_xid);
+ config_output->changes |= changes_mode;
continue;
}
if (!strcmp ("--preferred", argv[i])) {
- if (!output) usage();
- set_name_preferred (&output->mode);
- output->changes |= changes_mode;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ set_name_preferred (&config_output->mode);
+ config_output->changes |= changes_mode;
continue;
}
if (!strcmp ("--pos", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
if (sscanf (argv[i], "%dx%d",
- &output->x, &output->y) != 2)
- usage ();
- output->changes |= changes_position;
+ &config_output->x, &config_output->y) != 2)
+ argerr ("failed to parse '%s' as a position\n", argv[i]);
+ config_output->changes |= changes_position;
continue;
}
if (!strcmp ("--rotation", argv[i]) || !strcmp ("--rotate", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
for (dirind = 0; dirind < 4; dirind++) {
if (strcmp (direction[dirind], argv[i]) == 0) break;
}
if (dirind == 4)
- usage ();
- output->rotation &= ~0xf;
- output->rotation |= 1 << dirind;
- output->changes |= changes_rotation;
+ argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]);
+ config_output->rotation &= ~0xf;
+ config_output->rotation |= 1 << dirind;
+ config_output->changes |= changes_rotation;
continue;
}
if (!strcmp ("--reflect", argv[i]) || !strcmp ("--reflection", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
for (dirind = 0; dirind < 4; dirind++) {
if (strcmp (reflections[dirind], argv[i]) == 0) break;
}
if (dirind == 4)
- usage ();
- output->rotation &= ~(RR_Reflect_X|RR_Reflect_Y);
- output->rotation |= dirind * RR_Reflect_X;
- output->changes |= changes_reflection;
+ argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]);
+ config_output->rotation &= ~(RR_Reflect_X|RR_Reflect_Y);
+ config_output->rotation |= dirind * RR_Reflect_X;
+ config_output->changes |= changes_reflection;
continue;
}
if (!strcmp ("--left-of", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
- output->relation = relation_left_of;
- output->relative_to = argv[i];
- output->changes |= changes_relation;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ config_output->relation = relation_left_of;
+ config_output->relative_to = argv[i];
+ config_output->changes |= changes_relation;
continue;
}
if (!strcmp ("--right-of", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
- output->relation = relation_right_of;
- output->relative_to = argv[i];
- output->changes |= changes_relation;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ config_output->relation = relation_right_of;
+ config_output->relative_to = argv[i];
+ config_output->changes |= changes_relation;
continue;
}
if (!strcmp ("--above", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
- output->relation = relation_above;
- output->relative_to = argv[i];
- output->changes |= changes_relation;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ config_output->relation = relation_above;
+ config_output->relative_to = argv[i];
+ config_output->changes |= changes_relation;
continue;
}
if (!strcmp ("--below", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
- output->relation = relation_below;
- output->relative_to = argv[i];
- output->changes |= changes_relation;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ config_output->relation = relation_below;
+ config_output->relative_to = argv[i];
+ config_output->changes |= changes_relation;
continue;
}
if (!strcmp ("--same-as", argv[i])) {
- if (++i>=argc) usage ();
- if (!output) usage();
- output->relation = relation_same_as;
- output->relative_to = argv[i];
- output->changes |= changes_relation;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ config_output->relation = relation_same_as;
+ config_output->relative_to = argv[i];
+ config_output->changes |= changes_relation;
continue;
}
if (!strcmp ("--panning", argv[i])) {
XRRPanning *pan;
- if (++i>=argc) usage ();
- if (!output) usage();
- pan = &output->panning;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ pan = &config_output->panning;
switch (sscanf (argv[i], "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d",
&pan->width, &pan->height, &pan->left, &pan->top,
&pan->track_width, &pan->track_height,
@@ -2409,34 +2752,34 @@ main (int argc, char **argv)
case 12:
break;
default:
- usage ();
+ argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]);
}
- output->changes |= changes_panning;
+ config_output->changes |= changes_panning;
continue;
}
if (!strcmp ("--gamma", argv[i])) {
- if (!output) usage();
- if (++i>=argc) usage ();
- if (sscanf(argv[i], "%f:%f:%f", &output->gamma.red,
- &output->gamma.green, &output->gamma.blue) != 3)
- usage ();
- output->changes |= changes_gamma;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ if (sscanf(argv[i], "%f:%f:%f", &config_output->gamma.red,
+ &config_output->gamma.green, &config_output->gamma.blue) != 3)
+ argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]);
+ config_output->changes |= changes_gamma;
setit_1_2 = True;
continue;
}
if (!strcmp ("--brightness", argv[i])) {
- if (!output) usage();
- if (++i>=argc) usage();
- if (sscanf(argv[i], "%f", &output->brightness) != 1)
- usage ();
- output->changes |= changes_gamma;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ if (sscanf(argv[i], "%f", &config_output->brightness) != 1)
+ argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]);
+ config_output->changes |= changes_gamma;
setit_1_2 = True;
continue;
}
if (!strcmp ("--primary", argv[i])) {
- if (!output) usage();
- output->changes |= changes_primary;
- output->primary = True;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ config_output->changes |= changes_primary;
+ config_output->primary = True;
setit_1_2 = True;
continue;
}
@@ -2447,45 +2790,58 @@ main (int argc, char **argv)
}
if (!strcmp ("--set", argv[i])) {
output_prop_t *prop;
- if (!output) usage();
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (i+2 >= argc) argerr ("%s requires two arguments\n", argv[i]);
prop = malloc (sizeof (output_prop_t));
- prop->next = output->props;
- output->props = prop;
- if (++i>=argc) usage ();
- prop->name = argv[i];
- if (++i>=argc) usage ();
- prop->value = argv[i];
+ prop->next = config_output->props;
+ config_output->props = prop;
+ prop->name = argv[++i];
+ prop->value = argv[++i];
propit = True;
- output->changes |= changes_property;
+ config_output->changes |= changes_property;
setit_1_2 = True;
continue;
}
if (!strcmp ("--scale", argv[i]))
{
double sx, sy;
- if (!output) usage();
- if (++i>=argc) usage();
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
if (sscanf (argv[i], "%lfx%lf", &sx, &sy) != 2)
- usage ();
- init_transform (&output->transform);
- output->transform.transform.matrix[0][0] = XDoubleToFixed (sx);
- output->transform.transform.matrix[1][1] = XDoubleToFixed (sy);
- output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0);
+ argerr ("failed to parse '%s' as a scaling factor\n", argv[i]);
+ init_transform (&config_output->transform);
+ config_output->transform.transform.matrix[0][0] = XDoubleToFixed (sx);
+ config_output->transform.transform.matrix[1][1] = XDoubleToFixed (sy);
+ config_output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0);
if (sx != 1 || sy != 1)
- output->transform.filter = "bilinear";
+ config_output->transform.filter = "bilinear";
else
- output->transform.filter = "nearest";
- output->transform.nparams = 0;
- output->transform.params = NULL;
- output->changes |= changes_transform;
+ config_output->transform.filter = "nearest";
+ config_output->transform.nparams = 0;
+ config_output->transform.params = NULL;
+ config_output->changes |= changes_transform;
+ continue;
+ }
+ if (!strcmp ("--scale-from", argv[i]))
+ {
+ int w, h;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ if (sscanf (argv[i], "%dx%d", &w, &h) != 2)
+ argerr ("failed to parse '%s' as a scale-from size\n", argv[i]);
+ if (w <=0 || h <= 0)
+ argerr ("--scale-from dimensions must be nonnegative\n");
+ config_output->scale_from_w = w;
+ config_output->scale_from_h = h;
+ config_output->changes |= changes_transform;
continue;
}
if (!strcmp ("--transform", argv[i])) {
double transform[3][3];
int k, l;
- if (!output) usage();
- if (++i>=argc) usage ();
- init_transform (&output->transform);
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ init_transform (&config_output->transform);
if (strcmp (argv[i], "none") != 0)
{
if (sscanf(argv[i], "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf",
@@ -2493,62 +2849,62 @@ main (int argc, char **argv)
&transform[1][0],&transform[1][1],&transform[1][2],
&transform[2][0],&transform[2][1],&transform[2][2])
!= 9)
- usage ();
- init_transform (&output->transform);
+ argerr ("failed to parse '%s' as a transformation\n", argv[i]);
+ init_transform (&config_output->transform);
for (k = 0; k < 3; k++)
for (l = 0; l < 3; l++) {
- output->transform.transform.matrix[k][l] = XDoubleToFixed (transform[k][l]);
+ config_output->transform.transform.matrix[k][l] = XDoubleToFixed (transform[k][l]);
}
- output->transform.filter = "bilinear";
- output->transform.nparams = 0;
- output->transform.params = NULL;
+ config_output->transform.filter = "bilinear";
+ config_output->transform.nparams = 0;
+ config_output->transform.params = NULL;
}
- output->changes |= changes_transform;
+ config_output->changes |= changes_transform;
continue;
}
if (!strcmp ("--off", argv[i])) {
- if (!output) usage();
- set_name_xid (&output->mode, None);
- set_name_xid (&output->crtc, None);
- output->changes |= changes_mode;
+ if (!config_output) argerr ("%s must be used after --output\n", argv[i]);
+ set_name_xid (&config_output->mode, None);
+ set_name_xid (&config_output->crtc, None);
+ config_output->changes |= changes_mode;
continue;
}
if (!strcmp ("--fb", argv[i])) {
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
if (sscanf (argv[i], "%dx%d",
&fb_width, &fb_height) != 2)
- usage ();
+ argerr ("failed to parse '%s' as a framebuffer size\n", argv[i]);
setit_1_2 = True;
action_requested = True;
continue;
}
if (!strcmp ("--fbmm", argv[i])) {
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
if (sscanf (argv[i], "%dx%d",
&fb_width_mm, &fb_height_mm) != 2)
- usage ();
+ argerr ("failed to parse '%s' as a physical size\n", argv[i]);
setit_1_2 = True;
action_requested = True;
continue;
}
if (!strcmp ("--dpi", argv[i])) {
char *strtod_error;
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
dpi = strtod(argv[i], &strtod_error);
if (argv[i] == strtod_error)
{
dpi = 0.0;
- dpi_output = argv[i];
+ dpi_output_name = argv[i];
}
setit_1_2 = True;
action_requested = True;
continue;
}
if (!strcmp ("--auto", argv[i])) {
- if (output)
+ if (config_output)
{
- output->automatic = True;
- output->changes |= changes_automatic;
+ config_output->automatic = True;
+ config_output->changes |= changes_automatic;
}
else
automatic = True;
@@ -2572,7 +2928,8 @@ main (int argc, char **argv)
double clock;
++i;
- if (i + 9 >= argc) usage ();
+ if (i + 9 >= argc)
+ argerr ("failed to parse '%s' as a mode specification\n", argv[i]);
m->mode.name = argv[i];
m->mode.nameLength = strlen (argv[i]);
i++;
@@ -2611,7 +2968,7 @@ main (int argc, char **argv)
{
umode_t *m = malloc (sizeof (umode_t));
- if (++i>=argc) usage ();
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
set_name (&m->name, argv[i], name_string|name_xid);
m->action = umode_destroy;
m->next = umodes;
@@ -2624,10 +2981,9 @@ main (int argc, char **argv)
{
umode_t *m = malloc (sizeof (umode_t));
- if (++i>=argc) usage ();
- set_name (&m->output, argv[i], name_string|name_xid);
- if (++i>=argc) usage();
- set_name (&m->name, argv[i], name_string|name_xid);
+ if (i+2 >= argc) argerr ("%s requires two arguments\n", argv[i]);
+ set_name (&m->output, argv[++i], name_string|name_xid);
+ set_name (&m->name, argv[++i], name_string|name_xid);
m->action = umode_add;
m->next = umodes;
umodes = m;
@@ -2639,10 +2995,9 @@ main (int argc, char **argv)
{
umode_t *m = malloc (sizeof (umode_t));
- if (++i>=argc) usage ();
- set_name (&m->output, argv[i], name_string|name_xid);
- if (++i>=argc) usage();
- set_name (&m->name, argv[i], name_string|name_xid);
+ if (i+2 >= argc) argerr ("%s requires two arguments\n", argv[i]);
+ set_name (&m->output, argv[++i], name_string|name_xid);
+ set_name (&m->name, argv[++i], name_string|name_xid);
m->action = umode_delete;
m->next = umodes;
umodes = m;
@@ -2650,7 +3005,38 @@ main (int argc, char **argv)
action_requested = True;
continue;
}
- usage();
+ if (!strcmp ("--listproviders", argv[i]))
+ {
+ list_providers = True;
+ action_requested = True;
+ continue;
+ }
+ if (!strcmp("--setprovideroutputsource", argv[i]))
+ {
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ set_name (&provider_name, argv[i], name_string|name_xid|name_index);
+ if (++i>=argc)
+ set_name_xid (&output_source_provider_name, 0);
+ else
+ set_name (&output_source_provider_name, argv[i], name_string|name_xid|name_index);
+ action_requested = True;
+ provsetoutsource = True;
+ continue;
+ }
+ if (!strcmp("--setprovideroffloadsink", argv[i]))
+ {
+ if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
+ set_name (&provider_name, argv[i], name_string|name_xid|name_index);
+ if (++i>=argc)
+ set_name_xid (&offload_sink_provider_name, 0);
+ else
+ set_name (&offload_sink_provider_name, argv[i], name_string|name_xid|name_index);
+ action_requested = True;
+ provsetoffsink = True;
+ continue;
+ }
+
+ argerr ("unrecognized option '%s'\n", argv[i]);
}
if (!action_requested)
query = True;
@@ -2689,6 +3075,8 @@ main (int argc, char **argv)
has_1_2 = True;
if (major > 1 || (major == 1 && minor >= 3))
has_1_3 = True;
+ if (major > 1 || (major == 1 && minor >= 4))
+ has_1_4 = True;
if (has_1_2 && modeit)
{
@@ -2741,12 +3129,13 @@ main (int argc, char **argv)
}
if (has_1_2 && propit)
{
-
+ output_t *output;
+
get_screen (current);
get_crtcs();
get_outputs();
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
output_prop_t *prop;
@@ -2755,7 +3144,7 @@ main (int argc, char **argv)
Atom name = XInternAtom (dpy, prop->name, False);
Atom type;
int format = 0;
- unsigned char *data;
+ unsigned char *data, *malloced_data = NULL;
int nelements;
int int_value;
unsigned long ulong_value;
@@ -2779,8 +3168,17 @@ main (int argc, char **argv)
type = actual_type;
format = actual_format;
}
-
- if ((type == XA_INTEGER || type == AnyPropertyType) &&
+
+ malloced_data = property_values_from_string
+ (prop->value, type, actual_format, &nelements);
+
+ if (malloced_data)
+ {
+ data = malloced_data;
+ type = actual_type;
+ format = actual_format;
+ }
+ else if (type == AnyPropertyType &&
(sscanf (prop->value, "%d", &int_value) == 1 ||
sscanf (prop->value, "0x%x", &int_value) == 1))
{
@@ -2808,6 +3206,7 @@ main (int argc, char **argv)
XRRChangeOutputProperty (dpy, output->output.xid,
name, type, format, PropModeReplace,
data, nelements);
+ free (malloced_data);
}
}
if (!setit_1_2)
@@ -2816,6 +3215,36 @@ main (int argc, char **argv)
exit (0);
}
}
+ if (provsetoutsource)
+ {
+ provider_t *provider, *source;
+
+ if (!has_1_4)
+ fatal ("--setprovideroutputsource requires RandR 1.4\n");
+
+ get_screen (current);
+ get_providers ();
+
+ provider = find_provider (&provider_name);
+ source = find_provider(&output_source_provider_name);
+
+ XRRSetProviderOutputSource(dpy, provider->provider.xid, source->provider.xid);
+ }
+ if (provsetoffsink)
+ {
+ provider_t *provider, *sink;
+
+ if (!has_1_4)
+ fatal ("--setprovideroffloadsink requires RandR 1.4\n");
+
+ get_screen (current);
+ get_providers ();
+
+ provider = find_provider (&provider_name);
+ sink = find_provider(&offload_sink_provider_name);
+
+ XRRSetProviderOffloadSink(dpy, provider->provider.xid, sink->provider.xid);
+ }
if (setit_1_2)
{
get_screen (current);
@@ -2839,15 +3268,15 @@ main (int argc, char **argv)
/*
* If an output was specified to track dpi, use it
*/
- if (dpi_output)
+ if (dpi_output_name)
{
- output_t *output = find_output_by_name (dpi_output);
+ output_t *dpi_output = find_output_by_name (dpi_output_name);
XRROutputInfo *output_info;
XRRModeInfo *mode_info;
- if (!output)
- fatal ("Cannot find output %s\n", dpi_output);
- output_info = output->output_info;
- mode_info = output->mode_info;
+ if (!dpi_output)
+ fatal ("Cannot find output %s\n", dpi_output_name);
+ output_info = dpi_output->output_info;
+ mode_info = dpi_output->mode_info;
if (output_info && mode_info && output_info->mm_height)
{
/*
@@ -2922,19 +3351,22 @@ main (int argc, char **argv)
DisplayWidth (dpy, screen), DisplayHeight(dpy, screen),
maxWidth, maxHeight);
- for (output = outputs; output; output = output->next)
+ for (output = all_outputs; output; output = output->next)
{
XRROutputInfo *output_info = output->output_info;
- crtc_t *crtc = output->crtc_info;
- XRRCrtcInfo *crtc_info = crtc ? crtc->crtc_info : NULL;
- XRRModeInfo *mode = output->mode_info;
+ crtc_t *cur_crtc = output->crtc_info;
+ XRRCrtcInfo *crtc_info = cur_crtc ? cur_crtc->crtc_info : NULL;
+ XRRModeInfo *cur_mode = output->mode_info;
Atom *props;
- int j, k, nprop;
+ int j, nprop;
Bool *mode_shown;
Rotation rotations = output_rotations (output);
printf ("%s %s", output_info->name, connection[output_info->connection]);
- if (mode)
+ if (output->primary) {
+ printf(" primary");
+ }
+ if (cur_mode)
{
if (crtc_info) {
printf (" %dx%d+%d+%d",
@@ -2942,10 +3374,11 @@ main (int argc, char **argv)
crtc_info->x, crtc_info->y);
} else {
printf (" %dx%d+%d+%d",
- mode->width, mode->height, output->x, output->y);
+ cur_mode->width, cur_mode->height, output->x,
+ output->y);
}
if (verbose)
- printf (" (0x%x)", (int)mode->id);
+ printf (" (0x%x)", (int)cur_mode->id);
if (output->rotation != RR_Rotate_0 || verbose)
{
printf (" %s",
@@ -2977,15 +3410,16 @@ main (int argc, char **argv)
printf (")");
}
- if (mode)
+ if (cur_mode)
{
printf (" %dmm x %dmm",
(int)output_info->mm_width, (int)output_info->mm_height);
}
- if (crtc && crtc->panning_info && crtc->panning_info->width > 0)
+ if (cur_crtc && cur_crtc->panning_info &&
+ cur_crtc->panning_info->width > 0)
{
- XRRPanning *pan = crtc->panning_info;
+ XRRPanning *pan = cur_crtc->panning_info;
printf (" panning %dx%d+%d+%d",
pan->width, pan->height, pan->left, pan->top);
if ((pan->track_width != 0 &&
@@ -3072,7 +3506,10 @@ main (int argc, char **argv)
unsigned long nitems, bytes_after;
Atom actual_type;
XRRPropertyInfo *propinfo;
-
+ char *atom_name = XGetAtomName (dpy, props[j]);
+ Bool is_edid = strcmp (atom_name, "EDID") == 0;
+ int bytes_per_item, k;
+
XRRGetOutputProperty (dpy, output->output.xid, props[j],
0, 100, False, False,
AnyPropertyType,
@@ -3082,76 +3519,65 @@ main (int argc, char **argv)
propinfo = XRRQueryOutputProperty(dpy, output->output.xid,
props[j]);
- if (actual_type == XA_INTEGER && actual_format == 8) {
- int k;
-
- printf("\t%s:\n", XGetAtomName (dpy, props[j]));
- for (k = 0; k < nitems; k++) {
- if (k % 16 == 0)
- printf ("\t\t");
- printf("%02x", (unsigned char)prop[k]);
- if (k % 16 == 15)
- printf("\n");
- }
- } else if (actual_type == XA_INTEGER &&
- actual_format == 32)
- {
- printf("\t%s: ", XGetAtomName (dpy, props[j]));
- for (k = 0; k < nitems; k++) {
- if (k > 0)
- printf ("\n\t\t\t");
- printf("%d (0x%08x)",
- (int)((INT32 *)prop)[k], (int)((INT32 *)prop)[k]);
- }
+ bytes_per_item = actual_format / 8;
- if (propinfo->range && propinfo->num_values > 0) {
- if (nitems > 1)
- printf ("\n\t\t");
- printf("\trange%s: ",
- (propinfo->num_values == 2) ? "" : "s");
+ printf ("\t%s: ", atom_name);
- for (k = 0; k < propinfo->num_values / 2; k++)
- printf(" (%d,%d)", (int)propinfo->values[k * 2],
- (int)propinfo->values[k * 2 + 1]);
- }
+ if (is_edid)
+ {
+ printf ("\n\t\t");
+ }
- printf("\n");
- } else if (actual_type == XA_ATOM &&
- actual_format == 32)
+ for (k = 0; k < nitems; k++)
{
- printf("\t%s:", XGetAtomName (dpy, props[j]));
- for (k = 0; k < nitems; k++) {
- if (k > 0 && (k & 1) == 0)
+ if (k != 0)
+ {
+ if ((k % 16) == 0)
+ {
printf ("\n\t\t");
- printf("\t%s", XGetAtomName (dpy, ((Atom *)prop)[k]));
+ }
}
+ print_output_property_value (is_edid, actual_format,
+ actual_type,
+ prop + (k * bytes_per_item));
+ if (!is_edid)
+ {
+ printf (" ");
+ }
+ }
+ printf ("\n");
- if (!propinfo->range && propinfo->num_values > 0) {
- printf("\n\t\tsupported:");
-
- for (k = 0; k < propinfo->num_values; k++)
- {
- printf(" %-12.12s", XGetAtomName (dpy,
- propinfo->values[k]));
- if (k % 4 == 3 && k < propinfo->num_values - 1)
- printf ("\n\t\t ");
- }
+ if (propinfo->range && propinfo->num_values > 0)
+ {
+ printf ("\t\trange%s: ",
+ (propinfo->num_values == 2) ? "" : "s");
+ for (k = 0; k < propinfo->num_values / 2; k++)
+ {
+ printf ("(");
+ print_output_property_value (False, 32, actual_type,
+ (unsigned char *) &(propinfo->values[k * 2]));
+ printf (", ");
+ print_output_property_value (False, 32, actual_type,
+ (unsigned char *) &(propinfo->values[k * 2 + 1]));
+ printf (")");
+ }
+ printf ("\n");
+ }
+ if (!propinfo->range && propinfo->num_values > 0)
+ {
+ printf ("\t\tsupported: ");
+ for (k = 0; k < propinfo->num_values; k++)
+ {
+ print_output_property_value (False, 32, actual_type,
+ (unsigned char *) &(propinfo->values[k]));
}
- printf("\n");
- } else if (actual_format == 8) {
- printf ("\t%s: %s%s\n", XGetAtomName (dpy, props[j]),
- prop, bytes_after ? "..." : "");
- } else {
- char *type = actual_type ? XGetAtomName (dpy, actual_type) : "none";
- printf ("\t%s: %s(%d) (format %d items %d) ????\n",
- XGetAtomName (dpy, props[j]),
- type, (int)actual_type, actual_format, (int)nitems);
+ printf ("\n");
}
free(propinfo);
}
}
-
+
if (verbose)
{
for (j = 0; j < output_info->nmode; j++)
@@ -3186,6 +3612,7 @@ main (int argc, char **argv)
for (j = 0; j < output_info->nmode; j++)
{
XRRModeInfo *jmode, *kmode;
+ int k;
if (mode_shown[j]) continue;
@@ -3233,7 +3660,36 @@ main (int argc, char **argv)
}
exit (0);
}
-
+ if (list_providers) {
+ int k;
+
+ if (!has_1_4) {
+ printf ("RandR 1.4 not supported\n");
+ exit (0);
+ }
+
+ get_screen (current);
+ get_providers ();
+
+ if (providers) {
+ int j;
+
+ printf("Providers: number : %d\n", num_providers);
+
+ for (j = 0; j < num_providers; j++) {
+ provider_t *provider = &providers[j];
+ XRRProviderInfo *info = provider->info;
+
+ printf("Provider %d: id: 0x%x cap: 0x%x", j, (int)provider->provider.xid, info->capabilities);
+ for (k = 0; k < 4; k++)
+ if (info->capabilities & (1 << k))
+ printf(", %s", capability_name(1<<k));
+
+ printf(" crtcs: %d outputs: %d associated providers: %d name:%s\n", info->ncrtcs, info->noutputs, info->nassociatedproviders, info->name);
+ }
+ }
+ }
+
sc = XRRGetScreenInfo (dpy, root);
if (sc == NULL)
@@ -3302,6 +3758,8 @@ main (int argc, char **argv)
if (query || query_1) {
printf(" SZ: Pixels Physical Refresh\n");
for (i = 0; i < nsize; i++) {
+ int j;
+
printf ("%c%-2d %5d x %-5d (%4dmm x%4dmm )",
i == current_size ? '*' : ' ',
i, sizes[i].width, sizes[i].height,
@@ -3316,31 +3774,32 @@ main (int argc, char **argv)
}
}
- rotations = XRRConfigRotations(sc, &current_rotation);
+ {
+ Rotation rotations = XRRConfigRotations(sc, &current_rotation);
- rotation = 1 << rot ;
- if (query) {
- printf("Current rotation - %s\n",
- rotation_name (current_rotation));
+ if (query) {
+ printf("Current rotation - %s\n",
+ rotation_name (current_rotation));
- printf("Current reflection - %s\n",
- reflection_name (current_rotation));
+ printf("Current reflection - %s\n",
+ reflection_name (current_rotation));
- printf ("Rotations possible - ");
- for (i = 0; i < 4; i ++) {
- if ((rotations >> i) & 1) printf("%s ", direction[i]);
- }
- printf ("\n");
+ printf ("Rotations possible - ");
+ for (i = 0; i < 4; i ++) {
+ if ((rotations >> i) & 1) printf("%s ", direction[i]);
+ }
+ printf ("\n");
- printf ("Reflections possible - ");
- if (rotations & (RR_Reflect_X|RR_Reflect_Y))
- {
- if (rotations & RR_Reflect_X) printf ("X Axis ");
- if (rotations & RR_Reflect_Y) printf ("Y Axis");
+ printf ("Reflections possible - ");
+ if (rotations & (RR_Reflect_X|RR_Reflect_Y))
+ {
+ if (rotations & RR_Reflect_X) printf ("X Axis ");
+ if (rotations & RR_Reflect_Y) printf ("Y Axis");
+ }
+ else
+ printf ("none");
+ printf ("\n");
}
- else
- printf ("none");
- printf ("\n");
}
if (verbose) {
@@ -3366,9 +3825,12 @@ main (int argc, char **argv)
if (setit && !dryrun) XRRSelectInput (dpy, root,
RRScreenChangeNotifyMask);
- if (setit && !dryrun) status = XRRSetScreenConfigAndRate (dpy, sc,
- root,
- (SizeID) size, (Rotation) (rotation | reflection), rate, CurrentTime);
+ if (setit && !dryrun) {
+ Rotation rotation = 1 << rot;
+ status = XRRSetScreenConfigAndRate (dpy, sc, root, (SizeID) size,
+ (Rotation) (rotation | reflection),
+ rate, CurrentTime);
+ }
if (setit && !dryrun && status == RRSetConfigFailed) {
printf ("Failed to change the screen configuration!\n");