summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2015-12-27 19:31:30 -0800
committerKeith Packard <keithp@keithp.com>2015-12-27 19:37:01 -0800
commit617e5ed8bb6441ed85083881d34af8d7cf3ea7e4 (patch)
treef7391b3e0c4a8fe34d6a41a33832b6ffad5a0a2e
parentf0490d04c7cb171cd01a91dd51bf15ac4af5addf (diff)
Use mode ID instead of mode for autoconfigHEADmaster
This avoids any ambiguity over refresh rate parsing Signed-off-by: Keith Packard <keithp@keithp.com>
-rwxr-xr-xxrandr-auto211
1 files changed, 120 insertions, 91 deletions
diff --git a/xrandr-auto b/xrandr-auto
index df919e2..a97a3cb 100755
--- a/xrandr-auto
+++ b/xrandr-auto
@@ -17,6 +17,7 @@ typedef struct {
typedef struct {
string name;
string mode;
+ int mode_id;
bool connected;
bool primary;
int width, height;
@@ -72,9 +73,11 @@ const int priority_any = 0;
const int priority_preferred = 1;
const int priority_current = 2;
-typedef enum { start, start_output, output, skip_output, mode_get, mode_skip, done } state_t;
+typedef enum { start, start_output, output, skip_output,
+ mode_get, mode_skip, done } state_t;
-/* Parse xrandr results to compute the set of available monitors
+/* Parse xrandr results to compute the set of available monitors and
+ * current screen size
*/
output_t[]
get_outputs(*screen_t screen) {
@@ -193,7 +196,7 @@ get_outputs(*screen_t screen) {
}
if (this_priority > mode_priority) {
output.mode = words[0];
- string[] geom = String::wordsplit(words[0], "xi");
+ File::sscanf(words[1], "(0x%x)", &output.mode_id);
state = state_t.mode_get;
mode_priority = this_priority;
} else {
@@ -216,11 +219,23 @@ get_outputs(*screen_t screen) {
case state_t.mode_get:
case state_t.mode_skip:
if (words[0] == "h:") {
- if (state == state_t.mode_get)
- output.width = string_to_integer(words[2]);
+ if (state == state_t.mode_get) {
+ for (int h = 0; h < dim(words) - 1; h++) {
+ if (words[h] == "width") {
+ output.width = string_to_integer(words[h+1]);
+ break;
+ }
+ }
+ }
} else if (words[0] == "v:") {
- if (state == state_t.mode_get)
- output.height = string_to_integer(words[2]);
+ if (state == state_t.mode_get) {
+ for (int v = 0; v < dim(words) - 1; v++) {
+ if (words[v] == "height") {
+ output.height = string_to_integer(words[v+1]);
+ break;
+ }
+ }
+ }
} else {
state = state_t.output;
break;
@@ -259,6 +274,7 @@ monitor_t[] get_monitors(&output_t[] outputs) {
.name = sprintf("DP-GROUP-%d", output->tile.group_id),
.group_id = output->tile.group_id,
.outputs = outputs,
+ .primary = false,
.leader = 0,
.width = output->tile.number_h * output->width,
.height = output->tile.number_v * output->height,
@@ -282,6 +298,7 @@ monitor_t[] get_monitors(&output_t[] outputs) {
.group_id = -1,
.outputs = ((*output_t)[1]) { output },
.leader = 0,
+ .primary = false,
.width = output->width,
.height = output->height,
.x = -1,
@@ -302,19 +319,6 @@ is_internal_output(&output_t output) {
return false;
}
-int
-connector_priority(&output_t output) {
- if (String::index(output.name, "DP") >= 0)
- return 4;
- if (String::index(output.name, "DVI") >= 0)
- return 3;
- if (String::index(output.name, "HDMI") >= 0)
- return 2;
- if (String::index(output.name, "LVDS") >= 0)
- return 1;
- return 0;
-}
-
bool
is_internal_monitor(&monitor_t monitor) {
for (int o = 0; o < dim(monitor.outputs); o++)
@@ -323,42 +327,7 @@ is_internal_monitor(&monitor_t monitor) {
return false;
}
-int
-area(&monitor_t monitor) {
- return monitor.width * monitor.height;
-}
-
-void
-set_primary(&monitor_t[] monitors)
-{
- *monitor_t primary = &monitors[0];
-
- for (int m = 1; m < dim(monitors); m++) {
- *monitor_t monitor = &monitors[m];
-
- if (is_internal_monitor(primary)) {
- if (!is_internal_monitor(monitor)) {
- if (monitor->height > 1080)
- primary = monitor;
- }
- } else {
- if (is_internal_monitor(monitor)) {
- if (primary->height <= 1080)
- primary = monitor;
- } else {
- if (monitor->height > primary->height)
- primary = monitor;
- }
- }
- }
- for (int m = 0; m < dim(monitors); m++) {
- *monitor_t monitor = &monitors[m];
- monitor->primary = monitor == primary;
- if (monitor->primary)
- monitor->outputs[monitor->leader]->primary = true;
- }
-}
-
+/* Return the current primary monitor */
*monitor_t
get_primary(&monitor_t[] monitors)
{
@@ -372,6 +341,7 @@ get_primary(&monitor_t[] monitors)
return &monitors[0];
}
+/* Return the first internal monitor (LVDS or eDP) */
*monitor_t
get_internal(&monitor_t[] monitors)
{
@@ -383,40 +353,16 @@ get_internal(&monitor_t[] monitors)
return &monitors[0];
}
+/* Set output positions and primary status */
void
-set_pos(&monitor_t[] monitors)
+set_output(&monitor_t[] monitors)
{
- int nset = 0;
-
- /* Primary monitor goes upper left */
- *monitor_t primary = get_primary(&monitors);
-
- primary->x = 0;
- primary->y = 0;
-
- /* Set panel position, if not primary */
- *monitor_t internal = get_internal(&monitors);
- if (is_internal_monitor(internal) && !internal->primary) {
- internal->x = 0;
- internal->y = primary->height;
- }
-
- int x = primary->width;
-
- /* Set remaining positions, right of primary */
+ /* Set output positions and primary value */
for (int m = 0; m < dim(monitors); m++) {
*monitor_t monitor = &monitors[m];
- if (monitor->x < 0) {
- monitor->x = x;
- monitor->y = 0;
- x += monitor->width;
- }
- }
-
- /* Set output positions */
- for (int m = 0; m < dim(monitors); m++) {
- *monitor_t monitor = &monitors[m];
+ if (monitor->primary)
+ monitor->outputs[monitor->leader]->primary = true;
if (monitor->group_id >= 0) {
int tile_width = monitor->outputs[0]->width;
@@ -433,6 +379,7 @@ set_pos(&monitor_t[] monitors)
}
}
+/* Set overall screen size */
void
set_screen(&output_t[] outputs, *screen_t screen)
{
@@ -454,6 +401,83 @@ set_screen(&output_t[] outputs, *screen_t screen)
screen->height = height;
}
+/*
+ * Policy -- select the primary monitor
+ *
+ * Pick the largest external monitor if it's bigger than 1080p,
+ * otherwise pick the internal monitor
+ */
+void
+set_primary(&monitor_t[] monitors)
+{
+ *monitor_t primary = &monitors[0];
+
+ for (int m = 1; m < dim(monitors); m++) {
+ *monitor_t monitor = &monitors[m];
+
+ if (is_internal_monitor(primary)) {
+ if (!is_internal_monitor(monitor)) {
+ if (monitor->height > 1080)
+ primary = monitor;
+ }
+ } else {
+ if (is_internal_monitor(monitor)) {
+ if (primary->height <= 1080)
+ primary = monitor;
+ } else {
+ if (monitor->height > primary->height)
+ primary = monitor;
+ }
+ }
+ }
+ primary->primary = true;
+}
+
+/*
+ * Policy -- position the monitors
+ *
+ * Place the primary monitor at the upper left corner of the
+ * screen.
+ *
+ * If the internal monitor is not primary, place it just below the
+ * primary monitor.
+ *
+ * Place all other monitors to the right of the primary monitor
+ */
+
+void
+set_monitor_pos(&monitor_t[] monitors)
+{
+ int nset = 0;
+
+ /* Primary monitor goes upper left */
+ *monitor_t primary = get_primary(&monitors);
+
+ primary->x = 0;
+ primary->y = 0;
+
+ /* Set panel position, if not primary */
+ *monitor_t internal = get_internal(&monitors);
+ if (is_internal_monitor(internal) && !internal->primary) {
+ internal->x = 0;
+ internal->y = primary->height;
+ }
+
+ int x = primary->width;
+
+ /* Set remaining positions, right of primary */
+ for (int m = 0; m < dim(monitors); m++) {
+ *monitor_t monitor = &monitors[m];
+
+ if (monitor->x < 0) {
+ monitor->x = x;
+ monitor->y = 0;
+ x += monitor->width;
+ }
+ }
+
+}
+
string
tabs(int tab) {
static string[] t = { "", "\t", "\t\t", "\t\t\t", "t\t\t\t" };
@@ -466,7 +490,7 @@ print_output(*output_t output, int tab) {
printf ("%soutput %s\n", tabs(tab), output->name);
printf ("%sconnected %v\n", tabs(tab+1), output->connected);
if (output->connected) {
- printf ("%smode %s\n", tabs(tab+1), output->mode);
+ printf ("%smode %s (0x%x)\n", tabs(tab+1), output->mode, output->mode_id);
printf ("%sprimary %v\n", tabs(tab+1), output->primary);
printf ("%swidth, height %d,%d\n", tabs(tab+1), output->width, output->height);
printf ("%sx, y %d, %d\n", tabs(tab+1), output->x, output->y);
@@ -504,7 +528,7 @@ output_config(*output_t output) {
"--output",
output->name,
"--mode",
- output->mode,
+ sprintf ("0x%x", output->mode_id),
"--pos",
sprintf("%dx%d", output->x, output->y)
};
@@ -590,10 +614,14 @@ xrandr_auto()
screen_t screen;
screen_t temp_screen;
+ /* Implement our policy */
set_primary(&monitors);
+ set_monitor_pos(&monitors);
- set_pos(&monitors);
-
+ /* Using the specific configuration, place outputs
+ * and set the overall screen size
+ */
+ set_output(&monitors);
set_screen(&outputs, &screen);
temp_screen.width = max(orig_screen.width, screen.width);
@@ -628,11 +656,12 @@ xrandr_auto()
string[] xrandr_args = cat_args(args);
- if (dry_run) {
+ if (dry_run || verbose) {
for (int a = 0; a < dim(xrandr_args); a++)
printf("%s ", xrandr_args[a]);
printf ("\n");
- } else {
+ }
+ if (!dry_run) {
system("xrandr", xrandr_args ...);
}
}