Add borders to windows; add navigation keybinds
Right now, colors are hardcoded in the Config in main.zig. This commit also adds a couple of new keybinds for navigating between windows. All keybinds are hardcoded as well right now.
This commit is contained in:
parent
42494ae5d1
commit
578e2f449e
7 changed files with 235 additions and 23 deletions
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2025-2026 Ben Buhse <me@benbuhse.email>
|
||||
// SPDX-FileCopyrightText: 2025 Ben Buhse <me@benbuhse.email>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
|
@ -16,6 +16,30 @@ windows: wl.list.Head(Window, .link),
|
|||
|
||||
window_count: u8 = 0,
|
||||
|
||||
/// Get the next window in the list, wrapping to first if at end
|
||||
pub fn getNextWindow(wm: *WindowManager, current: *Window) ?*Window {
|
||||
var it = wm.windows.iterator(.forward);
|
||||
while (it.next()) |window| {
|
||||
if (window == current) {
|
||||
return it.next() orelse wm.windows.first();
|
||||
}
|
||||
}
|
||||
return wm.windows.first();
|
||||
}
|
||||
|
||||
/// Get the previous window in the list, wrapping to last if at beginning
|
||||
pub fn getPrevWindow(wm: *WindowManager, current: *Window) ?*Window {
|
||||
var prev: ?*Window = null;
|
||||
var it = wm.windows.iterator(.forward);
|
||||
while (it.next()) |window| {
|
||||
if (window == current) {
|
||||
return prev orelse wm.windows.last();
|
||||
}
|
||||
prev = window;
|
||||
}
|
||||
return wm.windows.last();
|
||||
}
|
||||
|
||||
pub fn init(wm: *WindowManager, context: *Context, window_manager_v1: *river.WindowManagerV1) void {
|
||||
assert(wm == &context.wm);
|
||||
wm.* = .{
|
||||
|
|
@ -36,7 +60,7 @@ pub fn init(wm: *WindowManager, context: *Context, window_manager_v1: *river.Win
|
|||
/// Calculate primary/stack layout positions for all windows.
|
||||
/// - Single window: fullscreen
|
||||
/// - Multiple windows: stack (45% left, vertically tiled), primary (55% right)
|
||||
pub fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
||||
fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
||||
const count = wm.window_count;
|
||||
if (count == 0) return;
|
||||
|
||||
|
|
@ -52,16 +76,20 @@ pub fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
|||
while (it.next()) |window| {
|
||||
if (count == 1) {
|
||||
// Single window: fullscreen
|
||||
// TODO: Disable borders when maximized
|
||||
window.new_x = output_x;
|
||||
window.new_y = output_y;
|
||||
window.new_width = output_width;
|
||||
window.new_height = output_height;
|
||||
window.is_maximized = true;
|
||||
} else {
|
||||
// Multiple windows: primary/stack layout
|
||||
// TODO: Support multiple primaries
|
||||
const primary_width: u31 = @intFromFloat(@as(f32, @floatFromInt(output_width)) * PRIMARY_RATIO);
|
||||
const stack_width: u31 = output_width - primary_width;
|
||||
const stack_count = count - 1;
|
||||
const stack_height: u31 = @divFloor(output_height, stack_count);
|
||||
window.is_maximized = false;
|
||||
|
||||
if (index == 0) {
|
||||
// Primary window (first window) - right side
|
||||
|
|
@ -70,7 +98,7 @@ pub fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
|||
window.new_width = primary_width;
|
||||
window.new_height = output_height;
|
||||
} else {
|
||||
// Stack window - left side
|
||||
// Stack window(s) - left side
|
||||
const stack_index = index - 1;
|
||||
window.new_x = output_x;
|
||||
window.new_y = output_y + @as(i32, stack_index) * @as(i32, stack_height);
|
||||
|
|
@ -82,6 +110,14 @@ pub fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
|||
window.new_height = stack_height;
|
||||
}
|
||||
}
|
||||
|
||||
// Make space for borders; this is the same for all windows
|
||||
// (unless we disable borders when maximized?)
|
||||
const border_width = wm.context.config.border_width;
|
||||
window.new_height -= 2 * border_width;
|
||||
window.new_width -= 2 * border_width;
|
||||
window.new_x += border_width;
|
||||
window.new_y += border_width;
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
|
@ -97,9 +133,17 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
|
|||
},
|
||||
.manage_start => {
|
||||
if (!context.initialized) {
|
||||
// This code (should) only be run once while initializing the WM, so let's
|
||||
// mark it as cold.
|
||||
@branchHint(.cold);
|
||||
context.initialized = true;
|
||||
context.xkb_bindings.addBinding(xkbcommon.Keysym.t, .{ .mod1 = true });
|
||||
context.xkb_bindings.addBinding(xkbcommon.Keysym.t, .{ .mod4 = true }, .{ .spawn = &.{"foot"} });
|
||||
context.xkb_bindings.addBinding(xkbcommon.Keysym.j, .{ .mod4 = true }, .focus_next);
|
||||
context.xkb_bindings.addBinding(xkbcommon.Keysym.k, .{ .mod4 = true }, .focus_prev);
|
||||
context.xkb_bindings.addBinding(xkbcommon.Keysym.q, .{ .mod4 = true, .shift = true }, XkbBindings.Command.close_window);
|
||||
context.xkb_bindings.addBinding(xkbcommon.Keysym.e, .{ .mod4 = true, .shift = true }, XkbBindings.Command.exit);
|
||||
}
|
||||
|
||||
{
|
||||
var it = wm.seats.iterator(.forward);
|
||||
while (it.next()) |seat| {
|
||||
|
|
@ -182,5 +226,6 @@ const Context = @import("main.zig").Context;
|
|||
const Output = @import("Output.zig");
|
||||
const Seat = @import("Seat.zig");
|
||||
const Window = @import("Window.zig");
|
||||
const XkbBindings = @import("XkbBindings.zig");
|
||||
|
||||
const log = std.log.scoped(.WindowManager);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue