aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrestis Floros <orestisflo@gmail.com>2022-11-19 18:11:26 +0100
committerGitHub <noreply@github.com>2022-11-19 18:11:26 +0100
commit30131ed69795387ddc576b5dab24b5649e5b8583 (patch)
tree5a153948cd9aee7e070495433e89681b650c6049
parenta1e4b449550a411493d80376425ad589c4dff05c (diff)
downloadi3-30131ed69795387ddc576b5dab24b5649e5b8583.tar.gz
i3-30131ed69795387ddc576b5dab24b5649e5b8583.zip
Support nonprimary output keyword (#5273)
Fixes #4878
-rw-r--r--docs/userguide14
-rw-r--r--release-notes/changes/3-nonprimary1
-rw-r--r--src/commands.c11
-rw-r--r--src/randr.c7
-rw-r--r--testcases/t/166-assign.t36
-rw-r--r--testcases/t/297-assign-workspace-to-output.t6
-rw-r--r--testcases/t/544-focus-multiple-outputs.t17
7 files changed, 82 insertions, 10 deletions
diff --git a/docs/userguide b/docs/userguide
index d1c7810c..120e4b90 100644
--- a/docs/userguide
+++ b/docs/userguide
@@ -965,7 +965,7 @@ considered.
*Syntax*:
------------------------------------------------------------
assign <criteria> [→] [workspace] [number] <workspace>
-assign <criteria> [→] output left|right|up|down|primary|<output>
+assign <criteria> [→] output left|right|up|down|primary|nonprimary|<output>
------------------------------------------------------------
*Examples*:
@@ -997,6 +997,9 @@ assign [class="^URxvt$"] → output right
# Assign urxvt to the primary output
assign [class="^URxvt$"] → output primary
+
+# Assign urxvt to the first non-primary output
+assign [class="^URxvt$"] → output nonprimary
----------------------
Note that you might not have a primary output configured yet. To do so, run:
@@ -2423,7 +2426,7 @@ output::
focus left|right|down|up
focus parent|child|floating|tiling|mode_toggle
focus next|prev [sibling]
-focus output left|right|down|up|current|primary|next|<output1> [output2]…
+focus output left|right|down|up|current|primary|nonprimary|next|<output1> [output2]…
----------------------------------------------
*Examples*:
@@ -2455,6 +2458,9 @@ bindsym $mod+x focus output HDMI-2
# Focus the primary output
bindsym $mod+x focus output primary
+# Cycle focus through non-primary outputs
+bindsym $mod+x focus output nonprimary
+
# Cycle focus between outputs VGA1 and LVDS1 but not DVI0
bindsym $mod+x move workspace to output VGA1 LVDS1
-------------------------------------------------
@@ -2719,8 +2725,8 @@ To move a container to another RandR output (addressed by names like +LVDS1+ or
*Syntax*:
-------------------------------------------------------------------------------------
-move container to output left|right|down|up|current|primary|next|<output1> [output2]…
-move workspace to output left|right|down|up|current|primary|next|<output1> [output2]…
+move container to output left|right|down|up|current|primary|nonprimary|next|<output1> [output2]…
+move workspace to output left|right|down|up|current|primary|nonprimary|next|<output1> [output2]…
-------------------------------------------------------------------------------------
*Examples*:
diff --git a/release-notes/changes/3-nonprimary b/release-notes/changes/3-nonprimary
new file mode 100644
index 00000000..f27bba76
--- /dev/null
+++ b/release-notes/changes/3-nonprimary
@@ -0,0 +1 @@
+Support nonprimary keyword for outputs
diff --git a/src/commands.c b/src/commands.c
index 551e4bcd..8a87877c 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -1032,11 +1032,16 @@ typedef struct user_output_name {
typedef TAILQ_HEAD(user_output_names_head, user_output_name) user_output_names_head;
static void user_output_names_add(user_output_names_head *list, const char *name) {
- if (strcmp(name, "next") == 0) {
- /* "next" here works like a wildcard: It "expands" to all available
- * outputs. */
+ const bool get_non_primary = (strcasecmp("nonprimary", name) == 0);
+ if (get_non_primary || strcmp(name, "next") == 0) {
+ /* "next" (or "nonprimary") here work like a wildcard: It "expands" to
+ * all available (or non-primary) outputs. */
Output *output;
TAILQ_FOREACH (output, &outputs, outputs) {
+ if (get_non_primary && output->primary) {
+ continue;
+ }
+
user_output_name *co = scalloc(sizeof(user_output_name), 1);
co->name = sstrdup(output_primary_name(output));
TAILQ_INSERT_TAIL(list, co, user_output_names);
diff --git a/src/randr.c b/src/randr.c
index 26b4ca34..fb733205 100644
--- a/src/randr.c
+++ b/src/randr.c
@@ -48,8 +48,10 @@ static Output *get_output_by_id(xcb_randr_output_t id) {
*
*/
Output *get_output_by_name(const char *name, const bool require_active) {
+ const bool get_primary = (strcasecmp("primary", name) == 0);
+ const bool get_non_primary = (strcasecmp("nonprimary", name) == 0);
+
Output *output;
- bool get_primary = (strcasecmp("primary", name) == 0);
TAILQ_FOREACH (output, &outputs, outputs) {
if (require_active && !output->active) {
continue;
@@ -57,6 +59,9 @@ Output *get_output_by_name(const char *name, const bool require_active) {
if (output->primary && get_primary) {
return output;
}
+ if (!output->primary && get_non_primary) {
+ return output;
+ }
struct output_name *output_name;
SLIST_FOREACH (output_name, &output->names_head, names) {
if (strcasecmp(output_name->name, name) == 0) {
diff --git a/testcases/t/166-assign.t b/testcases/t/166-assign.t
index f7a08647..249bbf87 100644
--- a/testcases/t/166-assign.t
+++ b/testcases/t/166-assign.t
@@ -327,6 +327,42 @@ kill_all_windows;
exit_gracefully($pid);
#####################################################################
+# Test assignments to primary / nonprimary outputs
+#####################################################################
+$config = <<'EOT';
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+fake-outputs 1024x768+0+0P,1024x768+1024+0
+
+workspace primary output fake-0
+workspace nonprimary output fake-1
+
+assign [class="current"] → output current
+assign [class="^primary$"] → output primary
+assign [class="nonprimary"] → output nonprimary
+EOT
+
+$pid = launch_with_config($config);
+
+cmd 'workspace primary';
+open_special(wm_class => 'current');
+sync_with_i3;
+is_num_children('primary', 1, 'one window in current workspace');
+
+open_special(wm_class => 'nonprimary');
+sync_with_i3;
+is_num_children('nonprimary', 1, 'one child on nonprimary');
+
+cmd 'workspace nonprimary';
+open_special(wm_class => 'primary');
+sync_with_i3;
+is_num_children('primary', 2, 'two children on primary');
+
+kill_all_windows;
+exit_gracefully($pid);
+
+#####################################################################
# regression test: dock clients with floating assignments should not crash
# (instead, nothing should happen - dock clients can’t float)
# ticket #501
diff --git a/testcases/t/297-assign-workspace-to-output.t b/testcases/t/297-assign-workspace-to-output.t
index 4e251e5d..68aa1f89 100644
--- a/testcases/t/297-assign-workspace-to-output.t
+++ b/testcases/t/297-assign-workspace-to-output.t
@@ -86,6 +86,8 @@ workspace 5 output fake-0
workspace 5:xxx output fake-1
workspace 6:xxx output fake-0
workspace 6 output fake-1
+workspace 7 output nonprimary primary
+workspace 8 output doesnotexist primary
EOT
$pid = launch_with_config($config);
@@ -98,7 +100,9 @@ do_test('5', 'fake-0', 'Numbered assignment ok');
do_test('5:xxx', 'fake-1', 'Named assignment overrides number');
do_test('6', 'fake-1', 'Numbered assignment ok');
do_test('6:xxx', 'fake-0', 'Named assignment overrides number');
-do_test('7', 'fake-2', 'Numbered initialization for fake-2');
+do_test('7', 'fake-1', 'Non-primary output');
+do_test('8', 'fake-0', 'Primary output');
+do_test('9', 'fake-2', 'Numbered initialization for fake-2');
cmd 'focus output fake-0, workspace foo';
check_output('foo', 'fake-0', 'Workspace with only non-existing assigned outputs opened in current output');
diff --git a/testcases/t/544-focus-multiple-outputs.t b/testcases/t/544-focus-multiple-outputs.t
index 504b8d11..2d09dfba 100644
--- a/testcases/t/544-focus-multiple-outputs.t
+++ b/testcases/t/544-focus-multiple-outputs.t
@@ -20,7 +20,7 @@ use i3test i3_config => <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-fake-outputs 1024x768+0+0,1024x768+1024+0,1024x768+0+768,1024x768+1024+768
+fake-outputs 1024x768+0+0P,1024x768+1024+0,1024x768+0+768,1024x768+1024+768
EOT
###############################################################################
@@ -64,4 +64,19 @@ for (my $i = 0; $i < 10; $i++) {
is(focused_output, "fake-$out", 'focus output next cycle');
}
+###############################################################################
+# Use nonprimary to cycle outputs
+###############################################################################
+
+cmd 'focus output fake-0';
+is(focused_output, "fake-0", 'start from fake-0 which is the primary');
+
+my @order = (1, 2, 3);
+for (my $i = 0; $i < 10; $i++) {
+ cmd 'focus output nonprimary';
+
+ my $out = $order[$i % 3];
+ is(focused_output, "fake-$out", 'focus output nonprimary cycle');
+}
+
done_testing;