diff --git a/contrib/config.sh b/contrib/config.sh
index 18c6d68..08ca6a2 100755
--- a/contrib/config.sh
+++ b/contrib/config.sh
@@ -38,24 +38,26 @@ riverctl map normal $mod+Shift H mod-master-count +1
riverctl map normal $mod+Shift L mod-master-count -1
for i in $(seq 1 9); do
- # Mod+[1-9] to focus tag [1-9]
- riverctl map normal $mod $i focus-tag $i
+ tagmask=$((1 << ($i - 1)))
- # Mod+Shift+[1-9] to tag focused view with tag [1-9]
- riverctl map normal $mod+Shift $i tag-view $i
+ # Mod+[1-9] to focus tag [0-8]
+ riverctl map normal $mod $i set-focused-tags $tagmask
- # Mod+Ctrl+[1-9] to toggle focus of tag [1-9]
- riverctl map normal $mod+Control $i toggle-tag-focus $i
+ # Mod+Shift+[1-9] to tag focused view with tag [0-8]
+ riverctl map normal $mod+Shift $i set-view-tags $tagmask
- # Mod+Shift+Ctrl+[1-9] to toggle tag [1-9] of focused view
- riverctl map normal $mod+Shift+Control $i toggle-view-tag $i
+ # Mod+Ctrl+[1-9] to toggle focus of tag [0-8]
+ riverctl map normal $mod+Control $i toggle-focused-tags $tagmask
+
+ # Mod+Shift+Ctrl+[1-9] to toggle tag [0-8] of focused view
+ riverctl map normal $mod+Shift+Control $i toggle-view-tags $tagmask
done
# Mod+0 to focus all tags
-riverctl map normal $mod 0 focus-all-tags
-
# Mod+Shift+0 to tag focused view with all tags
-riverctl map normal $mod+Shift 0 tag-view-all-tags
+all_tags_mask=$(((1 << 32) - 1))
+riverctl map normal $mod 0 set-focused-tags $all_tags_mask
+riverctl map normal $mod+Shift 0 set-view-tags $all_tags_mask
# Mod+Space to toggle float
riverctl map normal $mod Space toggle-float
diff --git a/river/command.zig b/river/command.zig
index fd3cd28..243acfa 100644
--- a/river/command.zig
+++ b/river/command.zig
@@ -24,21 +24,19 @@ const impl = struct {
const declareMode = @import("command/declare_mode.zig").declareMode;
const enterMode = @import("command/enter_mode.zig").enterMode;
const exit = @import("command/exit.zig").exit;
- const focusView = @import("command/focus_view.zig").focusView;
- const focusAllTags = @import("command/focus_all_tags.zig").focusAllTags;
const focusOutput = @import("command/focus_output.zig").focusOutput;
- const map = @import("command/map.zig").map;
- const focusTag = @import("command/focus_tag.zig").focusTag;
+ const focusView = @import("command/focus_view.zig").focusView;
const layout = @import("command/layout.zig").layout;
+ const map = @import("command/map.zig").map;
const modMasterCount = @import("command/mod_master_count.zig").modMasterCount;
const modMasterFactor = @import("command/mod_master_factor.zig").modMasterFactor;
const sendToOutput = @import("command/send_to_output.zig").sendToOutput;
+ const setFocusedTags = @import("command/tags.zig").setFocusedTags;
+ const setViewTags = @import("command/tags.zig").setViewTags;
const spawn = @import("command/spawn.zig").spawn;
- const tagView = @import("command/tag_view.zig").tagView;
- const tagViewAllTags = @import("command/tag_view_all_tags.zig").tagViewAllTags;
const toggleFloat = @import("command/toggle_float.zig").toggleFloat;
- const toggleTagFocus = @import("command/toggle_tag_focus.zig").toggleTagFocus;
- const toggleViewTag = @import("command/toggle_view_tag.zig").toggleViewTag;
+ const toggleFocusedTags = @import("command/tags.zig").toggleFocusedTags;
+ const toggleViewTags = @import("command/tags.zig").toggleViewTags;
const zoom = @import("command/zoom.zig").zoom;
};
@@ -56,34 +54,30 @@ pub const Direction = enum {
}
};
-const Definition = struct {
- name: []const u8,
- impl: fn (*std.mem.Allocator, *Seat, []const []const u8, *[]const u8) Error!void,
-};
-
// TODO: this could be replaced with a comptime hashmap
// zig fmt: off
-const str_to_impl_fn = [_]Definition{
- .{ .name = "close", .impl = impl.close },
- .{ .name = "declare-mode", .impl = impl.declareMode},
- .{ .name = "enter-mode", .impl = impl.enterMode },
- .{ .name = "exit", .impl = impl.exit },
- .{ .name = "focus-view", .impl = impl.focusView },
- .{ .name = "focus-all-tags", .impl = impl.focusAllTags },
- .{ .name = "focus-output", .impl = impl.focusOutput },
- .{ .name = "focus-tag", .impl = impl.focusTag },
- .{ .name = "layout", .impl = impl.layout },
- .{ .name = "mod-master-count", .impl = impl.modMasterCount },
- .{ .name = "mod-master-factor", .impl = impl.modMasterFactor },
- .{ .name = "send-to-output", .impl = impl.sendToOutput },
- .{ .name = "spawn", .impl = impl.spawn },
- .{ .name = "map", .impl = impl.map },
- .{ .name = "tag-view", .impl = impl.tagView },
- .{ .name = "tag-view-all-tags", .impl = impl.tagViewAllTags },
- .{ .name = "toggle-float", .impl = impl.toggleFloat },
- .{ .name = "toggle-tag-focus", .impl = impl.toggleTagFocus },
- .{ .name = "toggle-view-tag", .impl = impl.toggleViewTag },
- .{ .name = "zoom", .impl = impl.zoom },
+const str_to_impl_fn = [_]struct {
+ name: []const u8,
+ impl: fn (*std.mem.Allocator, *Seat, []const []const u8, *[]const u8) Error!void,
+}{
+ .{ .name = "close", .impl = impl.close },
+ .{ .name = "declare-mode", .impl = impl.declareMode },
+ .{ .name = "enter-mode", .impl = impl.enterMode },
+ .{ .name = "exit", .impl = impl.exit },
+ .{ .name = "focus-output", .impl = impl.focusOutput },
+ .{ .name = "focus-view", .impl = impl.focusView },
+ .{ .name = "layout", .impl = impl.layout },
+ .{ .name = "map", .impl = impl.map },
+ .{ .name = "mod-master-count", .impl = impl.modMasterCount },
+ .{ .name = "mod-master-factor", .impl = impl.modMasterFactor },
+ .{ .name = "send-to-output", .impl = impl.sendToOutput },
+ .{ .name = "set-focused-tags", .impl = impl.setFocusedTags },
+ .{ .name = "set-view-tags", .impl = impl.setViewTags },
+ .{ .name = "spawn", .impl = impl.spawn },
+ .{ .name = "toggle-float", .impl = impl.toggleFloat },
+ .{ .name = "toggle-focused-tags", .impl = impl.toggleFocusedTags },
+ .{ .name = "toggle-view-tags", .impl = impl.toggleViewTags },
+ .{ .name = "zoom", .impl = impl.zoom },
};
// zig fmt: on
diff --git a/river/command/focus_all_tags.zig b/river/command/focus_all_tags.zig
deleted file mode 100644
index 28e001d..0000000
--- a/river/command/focus_all_tags.zig
+++ /dev/null
@@ -1,32 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2020 Isaac Freund
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// 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 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, see .
-
-const std = @import("std");
-
-const Error = @import("../command.zig").Error;
-const Seat = @import("../Seat.zig");
-
-/// Set focus to all tags
-pub fn focusAllTags(
- allocator: *std.mem.Allocator,
- seat: *Seat,
- args: []const []const u8,
- failure_message: *[]const u8,
-) Error!void {
- seat.focused_output.pending_focused_tags = 0xFFFFFFFF;
- seat.input_manager.server.root.arrange();
-}
diff --git a/river/command/focus_tag.zig b/river/command/focus_tag.zig
deleted file mode 100644
index 8f69e6e..0000000
--- a/river/command/focus_tag.zig
+++ /dev/null
@@ -1,37 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2020 Isaac Freund
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// 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 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, see .
-
-const std = @import("std");
-
-const Error = @import("../command.zig").Error;
-const Seat = @import("../Seat.zig");
-
-/// Switch focus to the passed tag.
-pub fn focusTag(
- allocator: *std.mem.Allocator,
- seat: *Seat,
- args: []const []const u8,
- failure_message: *[]const u8,
-) Error!void {
- if (args.len < 2) return Error.NotEnoughArguments;
- if (args.len > 2) return Error.TooManyArguments;
-
- const tag = try std.fmt.parseInt(u32, args[1], 10);
- const tags = @as(u32, 1) << @intCast(u5, tag - 1);
- seat.focused_output.pending_focused_tags = tags;
- seat.input_manager.server.root.arrange();
-}
diff --git a/river/command/tag_view.zig b/river/command/tag_view.zig
deleted file mode 100644
index 735481d..0000000
--- a/river/command/tag_view.zig
+++ /dev/null
@@ -1,43 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2020 Isaac Freund
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// 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 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, see .
-
-const std = @import("std");
-
-const c = @import("../c.zig");
-
-const Error = @import("../command.zig").Error;
-const Seat = @import("../Seat.zig");
-
-/// Set the tag of the focused view.
-pub fn tagView(
- allocator: *std.mem.Allocator,
- seat: *Seat,
- args: []const []const u8,
- failure_message: *[]const u8,
-) Error!void {
- if (args.len < 2) return Error.NotEnoughArguments;
- if (args.len > 2) return Error.TooManyArguments;
-
- const tag = try std.fmt.parseInt(u32, args[1], 10);
- const tags = @as(u32, 1) << @intCast(u5, tag - 1);
- if (seat.focused_view) |view| {
- if (view.current_tags != tags) {
- view.pending_tags = tags;
- seat.input_manager.server.root.arrange();
- }
- }
-}
diff --git a/river/command/tag_view_all_tags.zig b/river/command/tag_view_all_tags.zig
deleted file mode 100644
index 2d187f3..0000000
--- a/river/command/tag_view_all_tags.zig
+++ /dev/null
@@ -1,38 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2020 Isaac Freund
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// 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 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, see .
-
-const std = @import("std");
-
-const c = @import("../c.zig");
-
-const Error = @import("../command.zig").Error;
-const Seat = @import("../Seat.zig");
-
-/// Tag the focused view with all tags.
-pub fn tagViewAllTags(
- allocator: *std.mem.Allocator,
- seat: *Seat,
- args: []const []const u8,
- failure_message: *[]const u8,
-) Error!void {
- if (seat.focused_view) |view| {
- if (view.current_tags != 0xFFFFFFFF) {
- view.pending_tags = 0xFFFFFFFF;
- seat.input_manager.server.root.arrange();
- }
- }
-}
diff --git a/river/command/tags.zig b/river/command/tags.zig
new file mode 100644
index 0000000..430b99e
--- /dev/null
+++ b/river/command/tags.zig
@@ -0,0 +1,102 @@
+// This file is part of river, a dynamic tiling wayland compositor.
+//
+// Copyright 2020 Isaac Freund
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// 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 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, see .
+
+const std = @import("std");
+
+const Error = @import("../command.zig").Error;
+const Seat = @import("../Seat.zig");
+
+/// Switch focus to the passed tags.
+pub fn setFocusedTags(
+ allocator: *std.mem.Allocator,
+ seat: *Seat,
+ args: []const []const u8,
+ failure_message: *[]const u8,
+) Error!void {
+ const tags = try parseTags(allocator, args, failure_message);
+ if (seat.focused_output.current_focused_tags != tags) {
+ seat.focused_output.pending_focused_tags = tags;
+ seat.input_manager.server.root.arrange();
+ }
+}
+
+/// Set the tags of the focused view.
+pub fn setViewTags(
+ allocator: *std.mem.Allocator,
+ seat: *Seat,
+ args: []const []const u8,
+ failure_message: *[]const u8,
+) Error!void {
+ const tags = try parseTags(allocator, args, failure_message);
+ if (seat.focused_view) |view| {
+ if (view.current_tags != tags) {
+ view.pending_tags = tags;
+ seat.input_manager.server.root.arrange();
+ }
+ }
+}
+
+/// Toggle focus of the passsed tags.
+pub fn toggleFocusedTags(
+ allocator: *std.mem.Allocator,
+ seat: *Seat,
+ args: []const []const u8,
+ failure_message: *[]const u8,
+) Error!void {
+ const tags = try parseTags(allocator, args, failure_message);
+ const output = seat.focused_output;
+ const new_focused_tags = output.current_focused_tags ^ tags;
+ if (new_focused_tags != 0) {
+ output.pending_focused_tags = new_focused_tags;
+ seat.input_manager.server.root.arrange();
+ }
+}
+
+/// Toggle the passed tags of the focused view
+pub fn toggleViewTags(
+ allocator: *std.mem.Allocator,
+ seat: *Seat,
+ args: []const []const u8,
+ failure_message: *[]const u8,
+) Error!void {
+ const tags = try parseTags(allocator, args, failure_message);
+ if (seat.focused_view) |view| {
+ const new_tags = view.current_tags ^ tags;
+ if (new_tags != 0) {
+ view.pending_tags = new_tags;
+ seat.input_manager.server.root.arrange();
+ }
+ }
+}
+
+fn parseTags(
+ allocator: *std.mem.Allocator,
+ args: []const []const u8,
+ failure_message: *[]const u8,
+) Error!u32 {
+ if (args.len < 2) return Error.NotEnoughArguments;
+ if (args.len > 2) return Error.TooManyArguments;
+
+ const tags = try std.fmt.parseInt(u32, args[1], 10);
+
+ if (tags == 0) {
+ failure_message.* = try std.fmt.allocPrint(allocator, "tagmask may not be 0", .{});
+ return Error.CommandFailed;
+ }
+
+ return tags;
+}
diff --git a/river/command/toggle_tag_focus.zig b/river/command/toggle_tag_focus.zig
deleted file mode 100644
index 09761c7..0000000
--- a/river/command/toggle_tag_focus.zig
+++ /dev/null
@@ -1,43 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2020 Isaac Freund
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// 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 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, see .
-
-const std = @import("std");
-
-const c = @import("../c.zig");
-
-const Error = @import("../command.zig").Error;
-const Seat = @import("../Seat.zig");
-
-/// Toggle focus of the passsed tags.
-pub fn toggleTagFocus(
- allocator: *std.mem.Allocator,
- seat: *Seat,
- args: []const []const u8,
- failure_message: *[]const u8,
-) Error!void {
- if (args.len < 2) return Error.NotEnoughArguments;
- if (args.len > 2) return Error.TooManyArguments;
-
- const tag = try std.fmt.parseInt(u32, args[1], 10);
- const tags = @as(u32, 1) << @intCast(u5, tag - 1);
- const output = seat.focused_output;
- const new_focused_tags = output.current_focused_tags ^ tags;
- if (new_focused_tags != 0) {
- output.pending_focused_tags = new_focused_tags;
- seat.input_manager.server.root.arrange();
- }
-}
diff --git a/river/command/toggle_view_tag.zig b/river/command/toggle_view_tag.zig
deleted file mode 100644
index 469a750..0000000
--- a/river/command/toggle_view_tag.zig
+++ /dev/null
@@ -1,44 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2020 Isaac Freund
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// 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 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, see .
-
-const std = @import("std");
-
-const c = @import("../c.zig");
-
-const Error = @import("../command.zig").Error;
-const Seat = @import("../Seat.zig");
-
-/// Toggle the passed tag of the focused view
-pub fn toggleViewTag(
- allocator: *std.mem.Allocator,
- seat: *Seat,
- args: []const []const u8,
- failure_message: *[]const u8,
-) Error!void {
- if (args.len < 2) return Error.NotEnoughArguments;
- if (args.len > 2) return Error.TooManyArguments;
-
- const tag = try std.fmt.parseInt(u32, args[1], 10);
- const tags = @as(u32, 1) << @intCast(u5, tag - 1);
- if (seat.focused_view) |view| {
- const new_tags = view.current_tags ^ tags;
- if (new_tags != 0) {
- view.pending_tags = new_tags;
- seat.input_manager.server.root.arrange();
- }
- }
-}