Implement command execution through riverctl
This commit is contained in:
		
							
								
								
									
										141
									
								
								src/Command.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/Command.zig
									
									
									
									
									
										Normal file
									
								
							@ -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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -16,9 +16,8 @@
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
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");
 | 
			
		||||
@ -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.
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
@ -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| {
 | 
			
		||||
							
								
								
									
										25
									
								
								src/command/focus_all_tags.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/command/focus_all_tags.zig
									
									
									
									
									
										Normal file
									
								
							@ -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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
}
 | 
			
		||||
@ -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");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,14 +15,12 @@
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
}
 | 
			
		||||
@ -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(
 | 
			
		||||
@ -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(
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
const Arg = @import("../command.zig").Arg;
 | 
			
		||||
const Arg = @import("../Command.zig").Arg;
 | 
			
		||||
const Seat = @import("../Seat.zig");
 | 
			
		||||
 | 
			
		||||
/// Switch to the given mode
 | 
			
		||||
 | 
			
		||||
@ -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");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
							
								
								
									
										31
									
								
								src/command/tag_view_all_tags.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/command/tag_view_all_tags.zig
									
									
									
									
									
										Normal file
									
								
							@ -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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
@ -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) {
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user