git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commitaa9bfc53a974bd143167c90a3003aee370c8e0c7
parent3efa63109e
authorLeon Henrik Plickat <[email protected]>
date2020-05-20 18:32
Add layout command

 src/Command.zig        |  2 ++
 src/Config.zig         | 29 +++++++++++++++++++++++++++++
 src/Output.zig         | 30 ++++++++++++++++++++++++++++--
 src/command/layout.zig | 29 +++++++++++++++++++++++++++++
 4 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/src/Command.zig b/src/Command.zig
index a7c2e1d..58c58d3 100644
--- a/src/Command.zig
+++ b/src/Command.zig
@@ -28,6 +28,7 @@ const command = struct {
     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 layout = @import("command/layout.zig").layout;
     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;
@@ -101,6 +102,7 @@ const str_to_read_fn = [_]Definition{
     .{ .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 = "layout",            .arg_type = .str,       .impl = command.layout},
     .{ .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 },
diff --git a/src/Config.zig b/src/Config.zig
index a1a8b05..54eb58a 100644
--- a/src/Config.zig
+++ b/src/Config.zig
@@ -211,6 +211,35 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void {
         .command = try Command.init(&[_][]const u8{ "mode", "normal" }, allocator),
     });
 
+    // Change master orientation with Mod+{Up,Right,Down,Left}
+    try normal.keybinds.append(.{
+        .keysym = c.XKB_KEY_Up,
+        .modifiers = mod,
+        .command = try Command.init(&[_][]const u8{ "layout", "TopMaster" }, allocator),
+    });
+    try normal.keybinds.append(.{
+        .keysym = c.XKB_KEY_Right,
+        .modifiers = mod,
+        .command = try Command.init(&[_][]const u8{ "layout", "RightMaster" }, allocator),
+    });
+    try normal.keybinds.append(.{
+        .keysym = c.XKB_KEY_Down,
+        .modifiers = mod,
+        .command = try Command.init(&[_][]const u8{ "layout", "BottomMaster" }, allocator),
+    });
+    try normal.keybinds.append(.{
+        .keysym = c.XKB_KEY_Left,
+        .modifiers = mod,
+        .command = try Command.init(&[_][]const u8{ "layout", "LeftMaster" }, allocator),
+    });
+
+    // Mod+f to change to Full layout
+    try normal.keybinds.append(.{
+        .keysym = c.XKB_KEY_f,
+        .modifiers = mod,
+        .command = try Command.init(&[_][]const u8{ "layout", "Full" }, allocator),
+    });
+
     // Float views with app_id "float"
     try self.float_filter.append("float");
 }
diff --git a/src/Output.zig b/src/Output.zig
index 11c467e..6dc999d 100644
--- a/src/Output.zig
+++ b/src/Output.zig
@@ -53,7 +53,7 @@ master_count: u32,
 master_factor: f64,
 
 /// Current layout of the output.
-layout: Layouts,
+layout: Layout,
 
 // All listeners for this output, in alphabetical order
 listen_destroy: c.wl_listener,
@@ -61,7 +61,7 @@ listen_frame: c.wl_listener,
 listen_mode: c.wl_listener,
 
 // All possible layouts.
-pub const Layouts = enum {
+pub const Layout = enum {
     TopMaster,
     RightMaster,
     BottomMaster,
@@ -69,6 +69,32 @@ pub const Layouts = enum {
     Full,
 };
 
+const LayoutName = struct {
+    name: []const u8,
+    layout: Layout,
+};
+
+// zig fmt: off
+const layout_names = [_]LayoutName {
+    .{ .name = "TopMaster",    .layout = Layout.TopMaster, },
+    .{ .name = "RightMaster",  .layout = Layout.RightMaster, },
+    .{ .name = "BottomMaster", .layout = Layout.BottomMaster, },
+    .{ .name = "LeftMaster",   .layout = Layout.LeftMaster, },
+    .{ .name = "Full",         .layout = Layout.Full, },
+};
+// zig fmt: on
+
+pub fn getLayoutByName(self: Self, name: []const u8) Layout {
+    for (layout_names) |current| {
+        if (std.mem.eql(u8, name, current.name)) {
+            return current.layout;
+        }
+    }
+    Log.Error.log("Layout '{}' does not exist", .{name});
+    // In case of error default to LeftMaster
+    return Layout.LeftMaster;
+}
+
 pub fn init(self: *Self, root: *Root, wlr_output: *c.wlr_output) !void {
     // Some backends don't have modes. DRM+KMS does, and we need to set a mode
     // before we can use the output. The mode is a tuple of (width, height,
diff --git a/src/command/layout.zig b/src/command/layout.zig
new file mode 100644
index 0000000..f895330
--- /dev/null
+++ b/src/command/layout.zig
@@ -0,0 +1,29 @@
+// This file is part of river, a dynamic tiling wayland compositor.
+//
+// Copyright 2020 Leon Henrik Plickat
+//
+// 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");
+
+pub fn layout(seat: *Seat, arg: Arg) void {
+    const layout_name = arg.str;
+    const config = seat.input_manager.server.config;
+    seat.focused_output.layout = seat.focused_output.getLayoutByName(layout_name);
+    seat.focused_output.arrangeViews();
+    seat.input_manager.server.root.startTransaction();
+}