From cee41e925dc0a9d7460806c9f8386512b207edf3 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 19 May 2020 22:59:50 +0200 Subject: [PATCH] Implement command execution through riverctl --- src/Command.zig | 141 ++++++++++++++++++ src/Config.zig | 77 ++++------ src/Keybind.zig | 5 +- src/Mode.zig | 1 + src/Seat.zig | 2 +- src/Server.zig | 1 + src/WindowManagement.zig | 11 +- src/command.zig | 50 ------- src/command/{close_view.zig => close.zig} | 4 +- src/command/{exit_compositor.zig => exit.zig} | 4 +- src/command/{focus_view.zig => focus.zig} | 4 +- src/command/focus_all_tags.zig | 25 ++++ src/command/focus_output.zig | 2 +- src/command/{focus_tags.zig => focus_tag.zig} | 10 +- ..._master_count.zig => mod_master_count.zig} | 4 +- ...aster_factor.zig => mod_master_factor.zig} | 4 +- src/command/mode.zig | 2 +- src/command/send_to_output.zig | 2 +- src/command/spawn.zig | 2 +- .../{set_view_tags.zig => tag_view.zig} | 8 +- src/command/tag_view_all_tags.zig | 31 ++++ src/command/toggle_float.zig | 2 +- .../{toggle_tags.zig => toggle_tag_focus.zig} | 6 +- ...ggle_view_tags.zig => toggle_view_tag.zig} | 8 +- src/command/zoom.zig | 2 +- 25 files changed, 271 insertions(+), 137 deletions(-) create mode 100644 src/Command.zig delete mode 100644 src/command.zig rename src/command/{close_view.zig => close.zig} (91%) rename src/command/{exit_compositor.zig => exit.zig} (90%) rename src/command/{focus_view.zig => focus.zig} (96%) create mode 100644 src/command/focus_all_tags.zig rename src/command/{focus_tags.zig => focus_tag.zig} (82%) rename src/command/{modify_master_count.zig => mod_master_count.zig} (92%) rename src/command/{modify_master_factor.zig => mod_master_factor.zig} (92%) rename src/command/{set_view_tags.zig => tag_view.zig} (84%) create mode 100644 src/command/tag_view_all_tags.zig rename src/command/{toggle_tags.zig => toggle_tag_focus.zig} (87%) rename src/command/{toggle_view_tags.zig => toggle_view_tag.zig} (84%) diff --git a/src/Command.zig b/src/Command.zig new file mode 100644 index 0000000..a7c2e1d --- /dev/null +++ b/src/Command.zig @@ -0,0 +1,141 @@ +// 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 Self = @This(); + +const std = @import("std"); + +const Seat = @import("Seat.zig"); + +const command = struct { + const close = @import("command/close.zig").close; + const exit = @import("command/exit.zig").exit; + const focus = @import("command/focus.zig").focus; + const focusAllTags = @import("command/focus_all_tags.zig").focusAllTags; + const focusOutput = @import("command/focus_output.zig").focusOutput; + const focusTag = @import("command/focus_tag.zig").focusTag; + const modMasterCount = @import("command/mod_master_count.zig").modMasterCount; + const modMasterFactor = @import("command/mod_master_factor.zig").modMasterFactor; + const mode = @import("command/mode.zig").mode; + const sendToOutput = @import("command/send_to_output.zig").sendToOutput; + 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 zoom = @import("command/zoom.zig").zoom; +}; + +const Direction = enum { + Next, + Prev, +}; + +pub const Arg = union(enum) { + int: i32, + uint: u32, + float: f64, + str: []const u8, + direction: Direction, + none: void, + + fn parse( + arg_type: @TagType(Arg), + args: []const []const u8, + allocator: *std.mem.Allocator, + ) !Arg { + switch (arg_type) { + .int, .uint, .float, .direction => { + if (args.len == 0) return error.NotEnoughArguments; + if (args.len > 1) return error.TooManyArguments; + return switch (arg_type) { + .int => .{ .int = try std.fmt.parseInt(i32, args[0], 10) }, + .uint => .{ .uint = try std.fmt.parseInt(u32, args[0], 10) }, + .float => .{ .float = try std.fmt.parseFloat(f64, args[0]) }, + .direction => if (std.mem.eql(u8, args[0], "next")) + Arg{ .direction = .Next } + else if (std.mem.eql(u8, args[0], "previous")) + Arg{ .direction = .Prev } + else + error.InvalidDirection, + else => unreachable, + }; + }, + .str => { + if (args.len == 0) return error.NotEnoughArguments; + return Arg{ .str = try std.mem.join(allocator, " ", args) }; + }, + .none => return if (args.len == 0) .{ .none = {} } else error.TooManyArguments, + } + } +}; + +const ImplFn = fn (seat: *Seat, arg: Arg) void; + +const Definition = struct { + name: []const u8, + arg_type: @TagType(Arg), + impl: ImplFn, +}; + +// zig fmt: off +const str_to_read_fn = [_]Definition{ + .{ .name = "close", .arg_type = .none, .impl = command.close }, + .{ .name = "exit", .arg_type = .none, .impl = command.exit }, + .{ .name = "focus", .arg_type = .direction, .impl = command.focus }, + .{ .name = "focus_all_tags", .arg_type = .none, .impl = command.focusAllTags }, + .{ .name = "focus_output", .arg_type = .direction, .impl = command.focusOutput }, + .{ .name = "focus_tag", .arg_type = .uint, .impl = command.focusTag }, + .{ .name = "mod_master_count", .arg_type = .int, .impl = command.modMasterCount }, + .{ .name = "mod_master_factor", .arg_type = .float, .impl = command.modMasterFactor }, + .{ .name = "mode", .arg_type = .str, .impl = command.mode }, + .{ .name = "send_to_output", .arg_type = .direction, .impl = command.sendToOutput }, + .{ .name = "spawn", .arg_type = .str, .impl = command.spawn }, + .{ .name = "tag_view", .arg_type = .uint, .impl = command.tagView }, + .{ .name = "tag_view_all_tags", .arg_type = .none, .impl = command.tagViewAllTags }, + .{ .name = "toggle_float", .arg_type = .none, .impl = command.toggleFloat }, + .{ .name = "toggle_tag_focus", .arg_type = .uint, .impl = command.toggleTagFocus }, + .{ .name = "toggle_view_tag", .arg_type = .uint, .impl = command.toggleViewTag }, + .{ .name = "zoom", .arg_type = .none, .impl = command.zoom }, +}; +// zig fmt: on + +impl: ImplFn, +arg: Arg, + +pub fn init(args: []const []const u8, allocator: *std.mem.Allocator) !Self { + if (args.len == 0) return error.NoCommand; + const name = args[0]; + + const definition = for (str_to_read_fn) |definition| { + if (std.mem.eql(u8, name, definition.name)) break definition; + } else return error.UnknownCommand; + + return Self{ + .impl = definition.impl, + .arg = try Arg.parse(definition.arg_type, args[1..], allocator), + }; +} + +pub fn deinit(self: Self, allocator: *std.mem.Allocator) void { + if (self.arg == .str) allocator.free(self.arg.str); +} + +pub fn run(self: Self, seat: *Seat) void { + self.impl(seat, self.arg); +} diff --git a/src/Config.zig b/src/Config.zig index 85c9b32..a1a8b05 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -20,8 +20,8 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); -const command = @import("command.zig"); +const Command = @import("Command.zig"); const Log = @import("log.zig").Log; const Mode = @import("Mode.zig"); const Server = @import("Server.zig"); @@ -58,38 +58,33 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { try normal.keybinds.append(.{ .keysym = c.XKB_KEY_Return, .modifiers = mod | c.WLR_MODIFIER_SHIFT, - .command = command.spawn, - .arg = .{ .str = "alacritty" }, + .command = try Command.init(&[_][]const u8{ "spawn", "alacritty" }, allocator), }); // Mod+Q to close the focused view try normal.keybinds.append(.{ .keysym = c.XKB_KEY_q, .modifiers = mod, - .command = command.close_view, - .arg = .{ .none = {} }, + .command = try Command.init(&[_][]const u8{"close"}, allocator), }); // Mod+E to exit river try normal.keybinds.append(.{ .keysym = c.XKB_KEY_e, .modifiers = mod, - .command = command.exitCompositor, - .arg = .{ .none = {} }, + .command = try Command.init(&[_][]const u8{"exit"}, allocator), }); // Mod+J and Mod+K to focus the next/previous view in the layout stack try normal.keybinds.append(.{ .keysym = c.XKB_KEY_j, .modifiers = mod, - .command = command.focusView, - .arg = .{ .direction = .Next }, + .command = try Command.init(&[_][]const u8{ "focus", "next" }, allocator), }); try normal.keybinds.append(.{ .keysym = c.XKB_KEY_k, .modifiers = mod, - .command = command.focusView, - .arg = .{ .direction = .Prev }, + .command = try Command.init(&[_][]const u8{ "focus", "previous" }, allocator), }); // Mod+Return to bump the focused view to the top of the layout stack, @@ -97,22 +92,19 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { try normal.keybinds.append(.{ .keysym = c.XKB_KEY_Return, .modifiers = mod, - .command = command.zoom, - .arg = .{ .none = {} }, + .command = try Command.init(&[_][]const u8{"zoom"}, allocator), }); // Mod+H and Mod+L to increase/decrease the width of the master column try normal.keybinds.append(.{ .keysym = c.XKB_KEY_h, .modifiers = mod, - .command = command.modifyMasterFactor, - .arg = .{ .float = 0.05 }, + .command = try Command.init(&[_][]const u8{ "mod_master_factor", "+0.05" }, allocator), }); try normal.keybinds.append(.{ .keysym = c.XKB_KEY_l, .modifiers = mod, - .command = command.modifyMasterFactor, - .arg = .{ .float = -0.05 }, + .command = try Command.init(&[_][]const u8{ "mod_master_factor", "-0.05" }, allocator), }); // Mod+Shift+H and Mod+Shift+L to increment/decrement the number of @@ -120,45 +112,40 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { try normal.keybinds.append(.{ .keysym = c.XKB_KEY_h, .modifiers = mod | c.WLR_MODIFIER_SHIFT, - .command = command.modifyMasterCount, - .arg = .{ .int = 1 }, + .command = try Command.init(&[_][]const u8{ "mod_master_count", "+1" }, allocator), }); try normal.keybinds.append(.{ .keysym = c.XKB_KEY_l, .modifiers = mod | c.WLR_MODIFIER_SHIFT, - .command = command.modifyMasterCount, - .arg = .{ .int = -1 }, + .command = try Command.init(&[_][]const u8{ "mod_master_count", "+1" }, allocator), }); comptime var i = 0; inline while (i < 9) : (i += 1) { + const str = &[_]u8{i + '0' + 1}; // Mod+[1-9] to focus tag [1-9] try normal.keybinds.append(.{ .keysym = c.XKB_KEY_1 + i, .modifiers = mod, - .command = command.focusTags, - .arg = .{ .uint = 1 << i }, + .command = try Command.init(&[_][]const u8{ "focus_tag", str }, allocator), }); // Mod+Shift+[1-9] to tag focused view with tag [1-9] try normal.keybinds.append(.{ .keysym = c.XKB_KEY_1 + i, .modifiers = mod | c.WLR_MODIFIER_SHIFT, - .command = command.setViewTags, - .arg = .{ .uint = 1 << i }, + .command = try Command.init(&[_][]const u8{ "tag_view", str }, allocator), }); // Mod+Ctrl+[1-9] to toggle focus of tag [1-9] try normal.keybinds.append(.{ .keysym = c.XKB_KEY_1 + i, .modifiers = mod | c.WLR_MODIFIER_CTRL, - .command = command.toggleTags, - .arg = .{ .uint = 1 << i }, + .command = try Command.init(&[_][]const u8{ "toggle_tag_focus", str }, allocator), }); // Mod+Shift+Ctrl+[1-9] to toggle tag [1-9] of focused view try normal.keybinds.append(.{ .keysym = c.XKB_KEY_1 + i, .modifiers = mod | c.WLR_MODIFIER_CTRL | c.WLR_MODIFIER_SHIFT, - .command = command.toggleViewTags, - .arg = .{ .uint = 1 << i }, + .command = try Command.init(&[_][]const u8{ "toggle_view_tag", str }, allocator), }); } @@ -166,30 +153,26 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { try normal.keybinds.append(.{ .keysym = c.XKB_KEY_0, .modifiers = mod, - .command = command.focusTags, - .arg = .{ .uint = 0xFFFFFFFF }, + .command = try Command.init(&[_][]const u8{"focus_all_tags"}, allocator), }); // Mod+Shift+0 to tag focused view with all tags try normal.keybinds.append(.{ .keysym = c.XKB_KEY_0, .modifiers = mod | c.WLR_MODIFIER_SHIFT, - .command = command.setViewTags, - .arg = .{ .uint = 0xFFFFFFFF }, + .command = try Command.init(&[_][]const u8{"tag_view_all_tags"}, allocator), }); // Mod+Period and Mod+Comma to focus the next/previous output try normal.keybinds.append(.{ .keysym = c.XKB_KEY_period, .modifiers = mod, - .command = command.focusOutput, - .arg = .{ .direction = .Next }, + .command = try Command.init(&[_][]const u8{ "focus_output", "next" }, allocator), }); try normal.keybinds.append(.{ .keysym = c.XKB_KEY_comma, .modifiers = mod, - .command = command.focusOutput, - .arg = .{ .direction = .Prev }, + .command = try Command.init(&[_][]const u8{ "focus_output", "previous" }, allocator), }); // Mod+Shift+Period/Comma to send the focused view to the the @@ -197,30 +180,26 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { try normal.keybinds.append(.{ .keysym = c.XKB_KEY_period, .modifiers = mod | c.WLR_MODIFIER_SHIFT, - .command = command.sendToOutput, - .arg = .{ .direction = .Next }, + .command = try Command.init(&[_][]const u8{ "send_to_output", "next" }, allocator), }); try normal.keybinds.append(.{ .keysym = c.XKB_KEY_comma, .modifiers = mod | c.WLR_MODIFIER_SHIFT, - .command = command.sendToOutput, - .arg = .{ .direction = .Prev }, + .command = try Command.init(&[_][]const u8{ "send_to_output", "previous" }, allocator), }); // Mod+Space to toggle float try normal.keybinds.append(.{ .keysym = c.XKB_KEY_space, .modifiers = mod, - .command = command.toggleFloat, - .arg = .{ .none = {} }, + .command = try Command.init(&[_][]const u8{"toggle_float"}, allocator), }); // Mod+F11 to enter passthrough mode try normal.keybinds.append(.{ .keysym = c.XKB_KEY_F11, .modifiers = mod, - .command = command.mode, - .arg = .{ .str = "passthrough" }, + .command = try Command.init(&[_][]const u8{ "mode", "passthrough" }, allocator), }); try self.modes.append(try Mode.init("passthrough", allocator)); @@ -229,14 +208,18 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { try self.modes.items[1].keybinds.append(.{ .keysym = c.XKB_KEY_F11, .modifiers = mod, - .command = command.mode, - .arg = .{ .str = "normal" }, + .command = try Command.init(&[_][]const u8{ "mode", "normal" }, allocator), }); // Float views with app_id "float" try self.float_filter.append("float"); } +pub fn deinit(self: Self, allocator: *std.mem.Allocator) void { + for (self.modes.items) |*mode| mode.deinit(); + self.modes.deinit(); +} + pub fn getMode(self: Self, name: []const u8) *Mode { for (self.modes.items) |*mode| if (std.mem.eql(u8, mode.name, name)) return mode; diff --git a/src/Keybind.zig b/src/Keybind.zig index 9a156ad..d82be7a 100644 --- a/src/Keybind.zig +++ b/src/Keybind.zig @@ -16,9 +16,8 @@ // along with this program. If not, see . const c = @import("c.zig"); -const command = @import("command.zig"); +const Command = @import("Command.zig"); keysym: c.xkb_keysym_t, modifiers: u32, -command: command.Command, -arg: command.Arg, +command: Command, diff --git a/src/Mode.zig b/src/Mode.zig index 9210db6..dfc4f54 100644 --- a/src/Mode.zig +++ b/src/Mode.zig @@ -38,5 +38,6 @@ pub fn init(name: []const u8, allocator: *std.mem.Allocator) !Self { pub fn deinit(self: Self) void { const allocator = self.keybinds.allocator; allocator.free(self.name); + for (self.keybinds.items) |keybind| keybind.command.deinit(allocator); self.keybinds.deinit(); } diff --git a/src/Seat.zig b/src/Seat.zig index c697010..3ff3667 100644 --- a/src/Seat.zig +++ b/src/Seat.zig @@ -252,7 +252,7 @@ pub fn handleKeybinding(self: *Self, keysym: c.xkb_keysym_t, modifiers: u32) boo for (self.mode.keybinds.items) |keybind| { if (modifiers == keybind.modifiers and keysym == keybind.keysym) { // Execute the bound command - keybind.command(self, keybind.arg); + keybind.command.run(self); return true; } } diff --git a/src/Server.zig b/src/Server.zig index 622b76f..a75ead0 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -143,6 +143,7 @@ pub fn deinit(self: *Self) void { c.wl_display_destroy(self.wl_display); self.input_manager.deinit(); self.root.deinit(); + self.config.deinit(self.allocator); } /// Create the socket, set WAYLAND_DISPLAY, and start the backend diff --git a/src/WindowManagement.zig b/src/WindowManagement.zig index 7c14838..c95aa23 100644 --- a/src/WindowManagement.zig +++ b/src/WindowManagement.zig @@ -21,6 +21,7 @@ const std = @import("std"); const c = @import("c.zig"); +const Command = @import("Command.zig"); const Log = @import("log.zig").Log; const Server = @import("Server.zig"); @@ -73,15 +74,15 @@ fn resourceDestroy(wl_resource: ?*c.wl_resource) callconv(.C) void { // TODO } -fn runCommand(wl_client: ?*c.wl_client, wl_resource: ?*c.wl_resource, command: ?*c.wl_array) callconv(.C) void { +fn runCommand(wl_client: ?*c.wl_client, wl_resource: ?*c.wl_resource, wl_array: ?*c.wl_array) callconv(.C) void { const self = @ptrCast(*Self, @alignCast(@alignOf(*Self), c.wl_resource_get_user_data(wl_resource))); const allocator = self.server.allocator; var args = std.ArrayList([]const u8).init(allocator); var i: usize = 0; - const data = @ptrCast([*]const u8, command.?.data); - while (i < command.?.size) { + const data = @ptrCast([*]const u8, wl_array.?.data); + while (i < wl_array.?.size) { const slice = std.mem.spanZ(@ptrCast([*:0]const u8, &data[i])); args.append(std.mem.dupe(allocator, u8, slice) catch unreachable) catch unreachable; @@ -91,4 +92,8 @@ fn runCommand(wl_client: ?*c.wl_client, wl_resource: ?*c.wl_resource, command: ? for (args.items) |x| { std.debug.warn("{}\n", .{x}); } + + // TODO: send the error event on failure instead of crashing + const command = Command.init(args.items, allocator) catch unreachable; + command.run(self.server.input_manager.default_seat); } diff --git a/src/command.zig b/src/command.zig deleted file mode 100644 index 95baf20..0000000 --- a/src/command.zig +++ /dev/null @@ -1,50 +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 Seat = @import("Seat.zig"); - -pub const Direction = enum { - Next, - Prev, -}; - -pub const Arg = union { - int: i32, - uint: u32, - float: f64, - str: []const u8, - direction: Direction, - none: void, -}; - -pub const Command = fn (seat: *Seat, arg: Arg) void; - -pub usingnamespace @import("command/close_view.zig"); -pub usingnamespace @import("command/exit_compositor.zig"); -pub usingnamespace @import("command/focus_output.zig"); -pub usingnamespace @import("command/focus_tags.zig"); -pub usingnamespace @import("command/focus_view.zig"); -pub usingnamespace @import("command/mode.zig"); -pub usingnamespace @import("command/modify_master_count.zig"); -pub usingnamespace @import("command/modify_master_factor.zig"); -pub usingnamespace @import("command/send_to_output.zig"); -pub usingnamespace @import("command/set_view_tags.zig"); -pub usingnamespace @import("command/spawn.zig"); -pub usingnamespace @import("command/toggle_float.zig"); -pub usingnamespace @import("command/toggle_tags.zig"); -pub usingnamespace @import("command/toggle_view_tags.zig"); -pub usingnamespace @import("command/zoom.zig"); diff --git a/src/command/close_view.zig b/src/command/close.zig similarity index 91% rename from src/command/close_view.zig rename to src/command/close.zig index 7bee0b6..c5be01c 100644 --- a/src/command/close_view.zig +++ b/src/command/close.zig @@ -17,11 +17,11 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); /// Close the focused view, if any. -pub fn close_view(seat: *Seat, arg: Arg) void { +pub fn close(seat: *Seat, arg: Arg) void { if (seat.focused_view) |view| { // Note: we don't call arrange() here as it will be called // automatically when the view is unmapped. diff --git a/src/command/exit_compositor.zig b/src/command/exit.zig similarity index 90% rename from src/command/exit_compositor.zig rename to src/command/exit.zig index 7736452..799b12c 100644 --- a/src/command/exit_compositor.zig +++ b/src/command/exit.zig @@ -17,10 +17,10 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); /// Exit the compositor, terminating the wayland session. -pub fn exitCompositor(seat: *Seat, arg: Arg) void { +pub fn exit(seat: *Seat, arg: Arg) void { c.wl_display_terminate(seat.input_manager.server.wl_display); } diff --git a/src/command/focus_view.zig b/src/command/focus.zig similarity index 96% rename from src/command/focus_view.zig rename to src/command/focus.zig index 225fa5e..930a36c 100644 --- a/src/command/focus_view.zig +++ b/src/command/focus.zig @@ -17,14 +17,14 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); const View = @import("../View.zig"); const ViewStack = @import("../view_stack.zig").ViewStack; /// Focus either the next or the previous visible view, depending on the enum /// passed. Does nothing if there are 1 or 0 views in the stack. -pub fn focusView(seat: *Seat, arg: Arg) void { +pub fn focus(seat: *Seat, arg: Arg) void { const direction = arg.direction; const output = seat.focused_output; if (seat.focused_view) |current_focus| { diff --git a/src/command/focus_all_tags.zig b/src/command/focus_all_tags.zig new file mode 100644 index 0000000..d2eef88 --- /dev/null +++ b/src/command/focus_all_tags.zig @@ -0,0 +1,25 @@ +// 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 Arg = @import("../Command.zig").Arg; +const Seat = @import("../Seat.zig"); + +/// Set focus to all tags +pub fn focusAllTags(seat: *Seat, arg: Arg) void { + seat.focused_output.pending_focused_tags = 0xFFFFFFFF; + seat.input_manager.server.root.arrange(); +} diff --git a/src/command/focus_output.zig b/src/command/focus_output.zig index 5140943..02b7999 100644 --- a/src/command/focus_output.zig +++ b/src/command/focus_output.zig @@ -19,7 +19,7 @@ const std = @import("std"); const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Output = @import("../Output.zig"); const Seat = @import("../Seat.zig"); diff --git a/src/command/focus_tags.zig b/src/command/focus_tag.zig similarity index 82% rename from src/command/focus_tags.zig rename to src/command/focus_tag.zig index aa29b7c..edb3292 100644 --- a/src/command/focus_tags.zig +++ b/src/command/focus_tag.zig @@ -15,14 +15,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -const c = @import("../c.zig"); - -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); -/// Switch focus to the passed tags. -pub fn focusTags(seat: *Seat, arg: Arg) void { - const tags = arg.uint; +/// Switch focus to the passed tag. +pub fn focusTag(seat: *Seat, arg: Arg) void { + const tags = @as(u32, 1) << @intCast(u5, arg.uint - 1); seat.focused_output.pending_focused_tags = tags; seat.input_manager.server.root.arrange(); } diff --git a/src/command/modify_master_count.zig b/src/command/mod_master_count.zig similarity index 92% rename from src/command/modify_master_count.zig rename to src/command/mod_master_count.zig index c7a5ac1..bd2fde0 100644 --- a/src/command/modify_master_count.zig +++ b/src/command/mod_master_count.zig @@ -19,11 +19,11 @@ const std = @import("std"); const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); /// Modify the number of master views -pub fn modifyMasterCount(seat: *Seat, arg: Arg) void { +pub fn modMasterCount(seat: *Seat, arg: Arg) void { const delta = arg.int; const output = seat.focused_output; output.master_count = @intCast( diff --git a/src/command/modify_master_factor.zig b/src/command/mod_master_factor.zig similarity index 92% rename from src/command/modify_master_factor.zig rename to src/command/mod_master_factor.zig index b2af06f..2e2a73c 100644 --- a/src/command/modify_master_factor.zig +++ b/src/command/mod_master_factor.zig @@ -19,11 +19,11 @@ const std = @import("std"); const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); /// Modify the percent of the width of the screen that the master views occupy. -pub fn modifyMasterFactor(seat: *Seat, arg: Arg) void { +pub fn modMasterFactor(seat: *Seat, arg: Arg) void { const delta = arg.float; const output = seat.focused_output; const new_master_factor = std.math.min( diff --git a/src/command/mode.zig b/src/command/mode.zig index cf0d709..706533c 100644 --- a/src/command/mode.zig +++ b/src/command/mode.zig @@ -15,7 +15,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); /// Switch to the given mode diff --git a/src/command/send_to_output.zig b/src/command/send_to_output.zig index f0658ca..7e0bbbf 100644 --- a/src/command/send_to_output.zig +++ b/src/command/send_to_output.zig @@ -19,7 +19,7 @@ const std = @import("std"); const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Output = @import("../Output.zig"); const Seat = @import("../Seat.zig"); diff --git a/src/command/spawn.zig b/src/command/spawn.zig index 53566fa..61aedab 100644 --- a/src/command/spawn.zig +++ b/src/command/spawn.zig @@ -19,7 +19,7 @@ const std = @import("std"); const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Log = @import("../log.zig").Log; const Seat = @import("../Seat.zig"); diff --git a/src/command/set_view_tags.zig b/src/command/tag_view.zig similarity index 84% rename from src/command/set_view_tags.zig rename to src/command/tag_view.zig index 562d311..fd74285 100644 --- a/src/command/set_view_tags.zig +++ b/src/command/tag_view.zig @@ -17,12 +17,12 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); -/// Set the tags of the focused view. -pub fn setViewTags(seat: *Seat, arg: Arg) void { - const tags = arg.uint; +/// Set the tag of the focused view. +pub fn tagView(seat: *Seat, arg: Arg) void { + const tags = @as(u32, 1) << @intCast(u5, arg.uint - 1); if (seat.focused_view) |view| { if (view.current_tags != tags) { view.pending_tags = tags; diff --git a/src/command/tag_view_all_tags.zig b/src/command/tag_view_all_tags.zig new file mode 100644 index 0000000..1b93233 --- /dev/null +++ b/src/command/tag_view_all_tags.zig @@ -0,0 +1,31 @@ +// 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 c = @import("../c.zig"); + +const Arg = @import("../Command.zig").Arg; +const Seat = @import("../Seat.zig"); + +/// Tag the focused view with all tags. +pub fn tagViewAllTags(seat: *Seat, arg: Arg) void { + if (seat.focused_view) |view| { + if (view.current_tags != 0xFFFFFFFF) { + view.pending_tags = 0xFFFFFFFF; + seat.input_manager.server.root.arrange(); + } + } +} diff --git a/src/command/toggle_float.zig b/src/command/toggle_float.zig index 27e3186..e890d73 100644 --- a/src/command/toggle_float.zig +++ b/src/command/toggle_float.zig @@ -17,7 +17,7 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); /// Make the focused view float or stop floating, depending on its current diff --git a/src/command/toggle_tags.zig b/src/command/toggle_tag_focus.zig similarity index 87% rename from src/command/toggle_tags.zig rename to src/command/toggle_tag_focus.zig index 2d9f86e..8a1a707 100644 --- a/src/command/toggle_tags.zig +++ b/src/command/toggle_tag_focus.zig @@ -17,12 +17,12 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); /// Toggle focus of the passsed tags. -pub fn toggleTags(seat: *Seat, arg: Arg) void { - const tags = arg.uint; +pub fn toggleTagFocus(seat: *Seat, arg: Arg) void { + const tags = @as(u32, 1) << @intCast(u5, arg.uint - 1); const output = seat.focused_output; const new_focused_tags = output.current_focused_tags ^ tags; if (new_focused_tags != 0) { diff --git a/src/command/toggle_view_tags.zig b/src/command/toggle_view_tag.zig similarity index 84% rename from src/command/toggle_view_tags.zig rename to src/command/toggle_view_tag.zig index 2f5ba3e..fa869b5 100644 --- a/src/command/toggle_view_tags.zig +++ b/src/command/toggle_view_tag.zig @@ -17,12 +17,12 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); -/// Toggle the passed tags of the focused view -pub fn toggleViewTags(seat: *Seat, arg: Arg) void { - const tags = arg.uint; +/// Toggle the passed tag of the focused view +pub fn toggleViewTag(seat: *Seat, arg: Arg) void { + const tags = @as(u32, 1) << @intCast(u5, arg.uint - 1); if (seat.focused_view) |view| { const new_tags = view.current_tags ^ tags; if (new_tags != 0) { diff --git a/src/command/zoom.zig b/src/command/zoom.zig index b1f7ba6..b603a69 100644 --- a/src/command/zoom.zig +++ b/src/command/zoom.zig @@ -17,7 +17,7 @@ const c = @import("../c.zig"); -const Arg = @import("../command.zig").Arg; +const Arg = @import("../Command.zig").Arg; const Seat = @import("../Seat.zig"); const View = @import("../View.zig"); const ViewStack = @import("../view_stack.zig").ViewStack;