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:
Ben Buhse 2026-01-23 16:23:14 -06:00
commit 578e2f449e
No known key found for this signature in database
GPG key ID: 7916ACFCD38FD0B4
7 changed files with 235 additions and 23 deletions

View file

@ -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
@ -19,6 +19,8 @@ new_height: u31 = 0,
new_x: i32 = 0,
new_y: i32 = 0,
is_maximized: bool = false,
link: wl.list.Link,
pub fn init(window: *Window, context: *Context, river_window_v1: *river.WindowV1) void {
@ -42,8 +44,8 @@ fn windowListener(river_window_v1: *river.WindowV1, event: river.WindowV1.Event,
{
var it = window.context.wm.seats.iterator(.forward);
while (it.next()) |seat| {
if (seat.hovered == window) {
seat.hovered = null;
if (seat.focused == window) {
seat.focused = null;
}
}
}
@ -66,14 +68,15 @@ fn windowListener(river_window_v1: *river.WindowV1, event: river.WindowV1.Event,
}
pub fn manage(window: *Window) void {
// Use server-side decoration (no client-drawn title bars)
// TODO: Probably shouldn't send this for every manage(?)
window.window_v1.useSsd();
// Layout has been pre-computed by WindowManager.calculatePrimaryStackLayout()
// Apply the computed dimensions
if (window.new_width > 0 and window.new_height > 0) {
window.window_v1.proposeDimensions(window.new_width, window.new_height);
// Use server-side decoration (no client-drawn title bars)
window.window_v1.useSsd();
// Inform the window about its tiled/fullscreen state
if (window.context.wm.window_count == 1) {
// Single window is fullscreen
@ -81,8 +84,8 @@ pub fn manage(window: *Window) void {
window.window_v1.informFullscreen();
} else {
// Tiled windows - set tiled edges
window.window_v1.informNotFullscreen();
window.window_v1.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true });
window.window_v1.informNotFullscreen();
}
}
}
@ -90,6 +93,28 @@ pub fn manage(window: *Window) void {
pub fn render(window: *Window) void {
// Set the window position using the pre-computed layout
window.node_v1.setPosition(window.new_x, window.new_y);
// Set borders
if (!window.is_maximized) {
const border_width = window.context.config.border_width;
if (window.isFocused()) {
const border_color_focused = window.context.config.border_color_focused;
window.window_v1.setBorders(.{ .top = true, .bottom = true, .left = true, .right = true }, border_width, border_color_focused.red, border_color_focused.green, border_color_focused.blue, border_color_focused.alpha);
} else {
const border_color_unfocused = window.context.config.border_color_unfocused;
window.window_v1.setBorders(.{ .top = true, .bottom = true, .left = true, .right = true }, border_width, border_color_unfocused.red, border_color_unfocused.green, border_color_unfocused.blue, border_color_unfocused.alpha);
}
}
}
fn isFocused(window: *Window) bool {
var it = window.context.wm.seats.iterator(.forward);
while (it.next()) |seat| {
if (seat.focused == window) {
return true;
}
}
return false;
}
const std = @import("std");