[PATCH app/xrandr] xrandr: add --bottom-align and --right-align sub-options

Pavel Kretov firegurafiku at gmail.com
Sat Nov 22 04:12:26 PST 2014


XRandr options for specifying outputs relative position can only top-align
or left-align outputs, while in many cases it seems practical to align
outputs by bottom or right edges too. There are two new sub-options
to allow syntax like that:

 * xrandr --output A --left-of [--bottom-align] B
 * xrandr --output A --right-of [--bottom-align] B
 * xrandr --output A --above [--right-align] B
 * xrandr --output A --below [--right-align] B

Signed-off-by: Pavel Kretov <firegurafiku at gmail.com>
---
Why I think there options are useful.

For example, I use a laptop which gets occasionally connected to
different external monitors: one at home and another at work. Laptop
built-in screen is lot smaller and physically placed much lower then
external one, so it's unconvenient to just use --left-of option.
I could workaround this using explicit --pos in pixels, but monitors
have different resolutions and I have to keep two variants of the
command. But:

 $ xrandr --output DP1 --left-of --bottom-align LVDS1

gives me usable configuration for both cases (and I can just put this
line in .xinitrc and forget about it).

I know I could just write a wrapper script to extract geometry from
xrandr's output, calculate offsets and run xrandr --output DP1 --pos,
but I thought sending a patch here was a better way since xrandr
already has --left-of and other relative positioning options. Adding
sub-options seemed better for me then adding options with names
like --left-bottom-of, but I do not really insist on that exact way.

I'm also not very experienced in submitting patches, so tell me please
if something is wrong.

 man/xrandr.man | 11 +++++----
 xrandr.c       | 72 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 67 insertions(+), 16 deletions(-)

diff --git a/man/xrandr.man b/man/xrandr.man
index 73d337c..21c09d7 100644
--- a/man/xrandr.man
+++ b/man/xrandr.man
@@ -54,10 +54,10 @@ xrandr \- primitive command line interface to RandR extension
 [\-\-rate \fIrate\fP]
 [\-\-reflect \fIreflection\fP]
 [\-\-rotate \fIorientation\fP]
-[\-\-left\-of \fIoutput\fP\]
-[\-\-right\-of \fIoutput\fP\]
-[\-\-above \fIoutput\fP\]
-[\-\-below \fIoutput\fP\]
+[\-\-left\-of [\-\-bottom\-align] \fIoutput\fP\]
+[\-\-right\-of [\-\-bottom\-align] \fIoutput\fP\]
+[\-\-above [\-\-right\-align] \fIoutput\fP\]
+[\-\-below [\-\-right\-align] \fIoutput\fP\]
 [\-\-same-as \fIoutput\fP\]
 [\-\-set \fIproperty\fP \fIvalue\fP]
 [\-\-off]
@@ -278,6 +278,9 @@ rotation.
 .IP "\-\-left\-of, \-\-right\-of, \-\-above, \-\-below, \-\-same-as \fIanother-output\fP"
 Use one of these options to position the output relative to the position of
 another output. This allows convenient tiling of outputs within the screen.
+By default \-\-left\-of and \-\-right\-of aligns output by top edge, \-\-above
+and \-\-below aligns by left. Use additional \-\-bottom\-align or \-\-right\-align
+options to change this behavior.
 The position is always computed relative to the new position of the other
 output, so it is not valid to say \-\-output a \-\-left\-of b \-\-output
 b \-\-left\-of a.
diff --git a/xrandr.c b/xrandr.c
index 366f6dc..6470e3a 100644
--- a/xrandr.c
+++ b/xrandr.c
@@ -126,10 +126,10 @@ usage(void)
            "      --rate <rate> or --refresh <rate>\n"
            "      --reflect normal,x,y,xy\n"
            "      --rotate normal,inverted,left,right\n"
-           "      --left-of <output>\n"
-           "      --right-of <output>\n"
-           "      --above <output>\n"
-           "      --below <output>\n"
+           "      --left-of [--bottom-align] <output>\n"
+           "      --right-of [--bottom-align] <output>\n"
+           "      --above [--right-align] <output>\n"
+           "      --below [--right-align] <output>\n"
            "      --same-as <output>\n"
            "      --set <property> <value>\n"
            "      --scale <x>x<y>\n"
@@ -248,9 +248,13 @@ capability_name (int cap_bit)
 
 typedef enum _relation {
     relation_left_of,
+    relation_left_of_bottom_align,
     relation_right_of,
+    relation_right_of_bottom_align,
     relation_above,
+    relation_above_right_align,
     relation_below,
+    relation_below_right_align,
     relation_same_as,
 } relation_t;
 
@@ -1997,18 +2001,38 @@ set_positions (void)
 		output->y = relation->y;
 		output->x = relation->x - mode_width (output->mode_info, output->rotation);
 		break;
+	    case relation_left_of_bottom_align:
+		output->x = relation->x - mode_width (output->mode_info, output->rotation);
+		output->y = relation->y + mode_height (relation->mode_info, relation->rotation)
+                                        - mode_height (output->mode_info, output->rotation);
+		break;
 	    case relation_right_of:
 		output->y = relation->y;
 		output->x = relation->x + mode_width (relation->mode_info, relation->rotation);
 		break;
+	    case relation_right_of_bottom_align:
+		output->x = relation->x + mode_width (relation->mode_info, relation->rotation);
+		output->y = relation->y + mode_height (relation->mode_info, relation->rotation)
+                                        - mode_height (output->mode_info, output->rotation);
+		break;
 	    case relation_above:
 		output->x = relation->x;
 		output->y = relation->y - mode_height (output->mode_info, output->rotation);
 		break;
+	    case relation_above_right_align:
+		output->y = relation->y - mode_height (output->mode_info, output->rotation);
+		output->x = relation->x + mode_width (relation->mode_info, relation->rotation)
+                                        - mode_width (output->mode_info, output->rotation);
+		break;
 	    case relation_below:
 		output->x = relation->x;
 		output->y = relation->y + mode_height (relation->mode_info, relation->rotation);
 		break;
+	    case relation_below_right_align:
+		output->y = relation->y + mode_height (relation->mode_info, relation->rotation);
+		output->x = relation->x + mode_width (relation->mode_info, relation->rotation)
+                                        - mode_width (output->mode_info, output->rotation);
+		break;
 	    case relation_same_as:
 		output->x = relation->x;
 		output->y = relation->y;
@@ -2760,32 +2784,56 @@ main (int argc, char **argv)
 	if (!strcmp ("--left-of", argv[i])) {
 	    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];
+            if (strcmp(argv[i], "--bottom-align")) {
+	        config_output->relation = relation_left_of;
+	        config_output->relative_to = argv[i];
+            } else {
+                if (++i >= argc) argerr ("%s %s requires an argument\n", argv[i-2], argv[i-1]);
+	        config_output->relation = relation_left_of_bottom_align;
+	        config_output->relative_to = argv[i];
+            }
 	    config_output->changes |= changes_relation;
 	    continue;
 	}
 	if (!strcmp ("--right-of", argv[i])) {
 	    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];
+            if (strcmp(argv[i], "--bottom-align")) {
+	        config_output->relation = relation_right_of;
+	        config_output->relative_to = argv[i];
+            } else {
+                if (++i >= argc) argerr ("%s %s requires an argument\n", argv[i-2], argv[i-1]);
+	        config_output->relation = relation_right_of_bottom_align;
+	        config_output->relative_to = argv[i];
+            }
 	    config_output->changes |= changes_relation;
 	    continue;
 	}
 	if (!strcmp ("--above", argv[i])) {
 	    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];
+            if (strcmp(argv[i], "--right-align")) {
+	        config_output->relation = relation_above;
+	        config_output->relative_to = argv[i];
+            } else {
+                if (++i >= argc) argerr ("%s %s requires an argument\n", argv[i-2], argv[i-1]);
+	        config_output->relation = relation_above_right_align;
+	        config_output->relative_to = argv[i];
+            }
 	    config_output->changes |= changes_relation;
 	    continue;
 	}
 	if (!strcmp ("--below", argv[i])) {
 	    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];
+            if (strcmp(argv[i], "--right-align")) {
+	        config_output->relation = relation_below;
+	        config_output->relative_to = argv[i];
+            } else {
+                if (++i >= argc) argerr ("%s %s requires an argument\n", argv[i-2], argv[i-1]);
+	        config_output->relation = relation_below_right_align;
+	        config_output->relative_to = argv[i];
+            }
 	    config_output->changes |= changes_relation;
 	    continue;
 	}
-- 
1.9.3



More information about the xorg-devel mailing list