diff --git a/examples/config.kdl b/examples/config.kdl index 38a1fae..d405f8f 100644 --- a/examples/config.kdl +++ b/examples/config.kdl @@ -7,15 +7,17 @@ borders { color_unfocused "0x1e1e2e" } keybinds { - spawn mod4 t foot - focus_next mod4 j - focus_prev mod4 k - zoom mod4 z - toggle_fullscreen mod4 f - close_window mod4+Shift q + spawn Mod4 T foot + focus_next Mod4 J + focus_prev Mod4 K + zoom Mod4 Z + change_ratio Mod4 H +0.05 + change_ratio Mod4 L -0.05 + toggle_fullscreen Mod4 F + close_window Mod4+Shift Q // Generates keybinds for keys 1-9 → tags 1<<0 through 1<<9 - tag_bind mod4 set_output_tags - tag_bind mod4+shift set_window_tags - tag_bind mod4+ctrl toggle_output_tags - tag_bind mod4+ctrl+shift toggle_window_tags + tag_bind Mod4 set_output_tags + tag_bind Mod4+shift set_window_tags + tag_bind Mod4+ctrl toggle_output_tags + tag_bind Mod4+ctrl+shift toggle_window_tags } diff --git a/src/Config.zig b/src/Config.zig index 6be61bb..09893fd 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -322,6 +322,17 @@ fn loadKeybindsChildBlock(config: *Config, parser: *kdl.Parser) !void { .zoom => { break :sw .zoom; }, + .change_ratio => { + const diff_str = utils.stripQuotes(node.arg(parser, 2) orelse { + logWarnMissingNodeArg(name, "diff"); + continue; + }); + const diff = fmt.parseFloat(f32, diff_str) catch { + logWarnInvalidNodeArg(name, diff_str); + continue; + }; + break :sw .{ .change_ratio = diff }; + }, .toggle_fullscreen => { break :sw .toggle_fullscreen; }, diff --git a/src/WindowManager.zig b/src/WindowManager.zig index 2dccd99..d125c0a 100644 --- a/src/WindowManager.zig +++ b/src/WindowManager.zig @@ -4,8 +4,6 @@ const WindowManager = @This(); -const PRIMARY_RATIO: f32 = 0.55; - const MIN_RIVER_SEAT_V1_VERSION: u2 = 3; context: *Context, @@ -18,6 +16,15 @@ windows: wl.list.Head(Window, .link), window_count: u8 = 0, +primary_ratio: f32 = 0.55, + +/// State consumed in manage phase, reset at end of manage_start(). +pending_manage: PendingManage = .{}, + +pub const PendingManage = struct { + primary_ratio: ?f32 = null, +}; + pub fn create(context: *Context, window_manager_v1: *river.WindowManagerV1) !*WindowManager { const wm = try utils.allocator.create(WindowManager); errdefer wm.destroy(); @@ -133,7 +140,7 @@ fn calculatePrimaryStackLayout(wm: *WindowManager) void { } else { // Multiple windows: primary/stack layout // TODO: Support multiple windows in primary stack - const primary_width: u31 = @intFromFloat(@as(f32, @floatFromInt(output_width)) * PRIMARY_RATIO); + const primary_width: u31 = @intFromFloat(@as(f32, @floatFromInt(output_width)) * wm.primary_ratio); const stack_width: u31 = output_width - primary_width; const stack_count = active_count - 1; const stack_height: u31 = @divFloor(output_height, stack_count); @@ -175,6 +182,8 @@ fn calculatePrimaryStackLayout(wm: *WindowManager) void { } fn manage_start(wm: *WindowManager) void { + defer wm.pending_manage = .{}; + const river_window_manager_v1 = wm.river_window_manager_v1; const context = wm.context; if (!context.initialized) { @@ -211,6 +220,13 @@ fn manage_start(wm: *WindowManager) void { } } + // Manage the WM itself first + if (wm.pending_manage.primary_ratio) |primary_ratio| { + // Ratios outside of this range can cause crashes anyways (when doing the layout calulcation) + std.debug.assert(primary_ratio >= 0.10 and primary_ratio <= 0.90); + wm.primary_ratio = primary_ratio; + } + { var it = wm.outputs.iterator(.forward); while (it.next()) |output| { diff --git a/src/XkbBindings.zig b/src/XkbBindings.zig index d8b9e52..5b8428c 100644 --- a/src/XkbBindings.zig +++ b/src/XkbBindings.zig @@ -9,8 +9,7 @@ pub const Command = union(enum) { focus_next, focus_prev, zoom, - // ratio_up, // TODO - // ratio_down, // TODO + change_ratio: f32, // reload_config, // TODO toggle_fullscreen, close_window, @@ -128,6 +127,12 @@ const XkbBinding = struct { }; current_focus.link.swapWith(&first_window.link); }, + .change_ratio => |diff| { + const new_ratio = context.wm.primary_ratio + diff; + if (new_ratio >= 0.10 and new_ratio <= 0.90) { + context.wm.pending_manage.primary_ratio = context.wm.primary_ratio + diff; + } + }, .toggle_fullscreen => { const seat = context.wm.seats.first() orelse return; const window = seat.focused orelse return; diff --git a/src/utils.zig b/src/utils.zig index 5b0193a..f2de860 100644 --- a/src/utils.zig +++ b/src/utils.zig @@ -108,7 +108,6 @@ pub fn tokenizeToOwnedSlices(input: []const u8, delimiter: u8) ![]const []const while (it.next()) |part| { const duped = try allocator.dupe(u8, part); try list.append(utils.allocator, duped); - log.debug("{s}", .{duped}); } return list.toOwnedSlice(utils.allocator); }