Commit graph

36 commits

Author SHA1 Message Date
Ben Buhse
08be768d99
Fix two crashes
One was where WM was assuming that a seat existed during first manage,
but that's not always true, so we have to check that before running the
initialization code. I also split that off into its own function like in
Window.

The other crash was when trying to calculate the layout with the
output's width and/or height equal to zero, it would crash subtracting
the border width.

I discovered both of these when try to restart beansprout without
restarting River.
2026-02-18 15:35:14 -06:00
Ben Buhse
433e377237
Rename calculatePrimaryStackLayout
It's the only layout, so just rename to calculateLayout()
2026-02-17 16:55:35 -06:00
Ben Buhse
c4da4ef30a
Make window rules frame perfect
This moves window initialization earlier in the manage sequence.
Previously, it was on the Window's first manage() call, but this is
after the layout has already been calculated, which matters both because
of tags and whether the window starts floating or not.

Now, initialization is handled in a separate function that gets called
in Output.calculatePrimaryStackLayout() instead.
2026-02-17 16:54:14 -06:00
Ben Buhse
9b0bac12ff
Fix text scaling in Bar
Before, we were missing the initial events from the wl_output, including
the scale. This meant that we weren't scaling the bar clock correctly.
To fix it, we just moved the wl_global binding into the .wl_output event

We also got rid of the hashmap of outputs in Globals and Context.
2026-02-16 19:09:33 -06:00
Ben Buhse
a37f72f0d7
Apply Rect to Buffer.borderedRectangle
Also set it to have all fields with a default of 0 since we use that
quite a bit and it saves writing it.
2026-02-16 17:32:46 -06:00
Ben Buhse
515e94320b
Apply Rect to Output 2026-02-16 17:27:31 -06:00
Ben Buhse
5333b4cbe0
Create utils.Rect struct for geometries
Also fixed a crash that I'm really not sure how I didn't have happen
before during Output.create()

Right now, only Window is updated to use Rect. I'll try updating all
instances of x,y,width,height combo to use it.
2026-02-16 17:16:25 -06:00
Ben Buhse
5922107579
Implement configuration for the Bar
This adds a few new options for the bar (instead of hardcoding all of
them). fonts, text_color, background_color, positoon, and margins.

Also fixed a couple of bugs when reloading the config and destroying
layer shell and wl surfaces in the wrong order.
2026-02-16 16:07:02 -06:00
Ben Buhse
dbf32e793c
Finish wiring up the TagOverlay
We had to fix a couple of compile errors that weren't showing while it
wasn't wired up (since I never just tried to compile TagOverlay.zig on
its own). We also changed the lifecycle to re-create/destroy the surface
to show/hide it, similar to the way that river-tag-overlay actually did
it.

Finally, I added @branchHint(.cold) to a few places in the event loop
where, if we're in the branch, the wm is definitely exiting, so it's
fine if they're cold (should almost never happen).
2026-02-16 11:33:48 -06:00
Ben Buhse
2c642d6cfc
Create initial version of TagOverlay
It's an almost one-to-one clone of Leon Plickat's river-tag-overlay.
Right now, it's not wired up, so it doesn't do anything yet.
2026-02-15 20:30:59 -06:00
Ben Buhse
43ebdd273c
Refactor Bar/Output surfaces into anon struct
Both the wl_surface and layer_surface in each are always expected to
exist at the same time. Since they're optional, it makes more sense to
combine them into a single optional struct.
2026-02-15 18:02:48 -06:00
Ben Buhse
83946ce97a
Fix wallpaper and bar rendering when scale >1
We track the scale for wallpaper and render now and have to re-render
when the  scale changes. For the bar, this includes recreated the
fcft fonts.
2026-02-15 16:59:18 -06:00
Ben Buhse
1cfafc4fb3
Implement the rest of river_layer_shell_v1
I still needed to call setDefault, as well as handle the .focus_*
events from the river_layer_shell_seat_v1.

I also fixed a memory leak where the output wasn't destroying its
river_layer_shell_output_v1.
2026-02-14 15:34:46 -06:00
Ben Buhse
5c427234d7
Add layer shell support and fix floating windows
Now, I actually save the river-layer-shell-v1 and keep track of the
non-exclusive area. The layout calculation uses the usable area instead
of the entire output's geometry.

I removed boundary clamping for the floating windows because it was a
bit janky when hitting the edges. I'll probably add it back at some
point. I also made windows default to 75% of the usable area instead of
keeping their tiled size so that maximized windows look decent when
floating for the first time. Finally, since I removed the clamping, I
added a center_float keybind to center a floating window. If you're
cycling through focused windows and one isn't on the screen, you can use
the center_float bind to get the window visible again.

Replaced all divTrunc with divFloor to be consistent. I think they
should all be positive, anyways, so they'd be the same, but I like just
having one.
2026-02-14 11:30:37 -06:00
Ben Buhse
6bf607b759
Change errdefers in create()/init() functions
They should use gpa.destroy() instead of foo.destroy() because (most) of
them have fields that may not be initialized by the first error, so
the foo.destroy() could crash.
2026-02-13 19:30:21 -06:00
Ben Buhse
29a1c93e6a
Add clock to the bar
This implements more of the text rendering and a clock was the easiest
part. I still need to add the tag bit. I'd also like to hide the tags
but still show the clock like beanclock when windows are fullscreened
2026-02-13 12:20:35 -06:00
Ben Buhse
40088b4ab6
Add initial bar support
Right now it just renders a black bar at the top of the screen, nothing
useful is in it and it has no configuration.
2026-02-13 10:07:48 -06:00
Ben Buhse
95425aa73f
Rename utils.allocator to utils.gpa
it seems like `gpa` has become pretty much the universally agreed upon
name for your... gpa, so we're renaming.
2026-02-12 14:10:28 -06:00
Ben Buhse
1df6820b1d
Implement per-tag primary_count and primary_ratio
By default, each tag mask will use the default count and ratio. If the
mask gets modified by any of the commands, it gets added to a hash map.
When changing tag masks, the current count and ratio are stored, and
they're used again later if you switch back to that mask.

This commit also adds primary_count and primary_ratio to the general
settings for the config, so users can set a default count/ratio to use.
2026-02-12 14:10:21 -06:00
Ben Buhse
bb612c273e
Add REUSE licensing for non-code files
CC-BY-4.0 for documentation, CC0-1.0 for examples and .gitignore,
HPND for wlr-layer-shell protocol.

Also switch to GPL-3.0-only
2026-02-11 14:50:04 -06:00
Ben Buhse
72c1f33c28
Implement river-input-management-v1 and river-libinput-config-v1
Right now, the support is still incomplete (no way to set config) but
we get the devices and set them up and handle current/support events
for the river_libinput_device_v1 devices.
2026-02-09 12:55:47 -06:00
Ben Buhse
54421ef8f5
Fix Output.prevWindow/nextWindow
Before, they were ignoring tags, so you could cycle to windows on
other tags instead of only the same tag.
2026-02-08 15:49:05 -06:00
Ben Buhse
4d379a272c
Change many "orelse return" sections to log.err
Beansprout will still continue gracefully, but I added handling so that
they'll log errors so we should have some record of something beind
wrong.
2026-02-08 15:11:03 -06:00
Ben Buhse
225ddf0a53
Fix buffer pool race condition, pixman transform, and pixel conversion
Mark reused buffers as busy before returning from nextBuffer (before,
they only got marked busy on init).

Re-attach wl_buffer listener after re-initializing a buffer. This lets
the re-inited buffer still get a released event.

Combine scale and translate matrices with multiply instead of overwriting

Use appendAssumeCapacity for pixel conversion loop (since we already
initialized the list with the correct size).
2026-02-08 10:51:33 -06:00
Ben Buhse
3c16929a6a
Complete wallpaper support with new config
Load wallpaper_image_path from config with tilde expansion (environment
variables are not supported)

On the way for this commit, I also had to:
- Fix wallpaper not rendering on startup by triggering init from
the .wl_output handler, since wl_output.done is lost during the
initial roundtrip
- Re-render wallpapers on config reload when the path changes
- Fix crash in deinitWallpaperLayerSurface when wl_surface is null
2026-02-07 19:11:10 -06:00
Ben Buhse
00835cea08
Fix crash when wallpaper_image_path is missing
This makes the WM run fine even if wallpaper_image fails to load for any
other reason. Right now, it's still just a black background. At some
point, I plan to add the ability to also just set a color as a
background but that's a fairly low priority.
2026-02-07 17:56:05 -06:00
Ben Buhse
e186a2d017
Implement wallpaper rendering with multi-output support
This actually renders a wallpaper for each output using the newly added
Buffer and BufferPool for shared-memory surfaces and creates a
wlr-layer-shell surface per output. Right now, each wallpaper
shares the same wallpaper (though scaled to each).

wl_output globals get added to a HashMap that is used by Output when it
gets an output event.

Fix null-safety in WindowManager when no seats/outputs exist and route
Window dimensions through pending_manage.
2026-02-07 17:27:24 -06:00
Ben Buhse
6d4352a217
Implement floating windows
As of this commit, there's not-yet a way to resize or move floating
windows, but it's possible to create one and focus through all windows.

Floating windows are always above tiled windows and, if floating window
is focused, that window is always above any another floating windows.

Windows have a separate float_{x, y, width, height} to remember their
floating location if they go from float=>tiled=>float again.
2026-02-05 17:14:46 -06:00
Ben Buhse
5ff05ab09e
Implement changeable primary count
There are new increment_primary_count and decrement_primary_count config options
2026-02-04 15:43:30 -06:00
Ben Buhse
0f85278aea
Add multi-output support
Primary ratio is per-output.

If an output is disconnected/disabled, its windows get sent to the
previous output in the output list. If all outputs are disconnected,
windows are added to an orphan list in the WM. Once an output is
re-added, the orphans are all given to that output.

When a window is sent to a new output, it keeps the same tags as it
had before. I may add an option to take the new output's tags.

- Rename focus_next/focus_prev to focus_next_window/focus_prev_window
- Add focus_next_output/focus_prev_output
- Add send_to_next_output/send_to_prev_output commands to move windows
    between outputs

Split Seat.PendingManage.PendingFocus into separate pending output
and pending window structs

Fix window outputs when closing outputs
2026-02-03 20:10:33 -06:00
Ben Buhse
43e3d268c9
Implement initial config loading
Config goes in $XDG_CONFIG_HOME/beansprout/config.kdl or
$HOME/.config/beansprout/config.kdl

Config is in the kdl format. Right now, the supported options are

```zig
/// Width of window borders in pixels
border_width: u8 = 2,
/// Color of focused window's border in 0xRRGGBBAA or 0xRRGGBB form
border_color_focused: RiverColor = utils.parseRgbaComptime("0x89b4fa"),
/// Color of uffocused windows' borders in 0xRRGGBBAA or 0xRRGGBB form
border_color_unfocused: RiverColor = utils.parseRgbaComptime("0x1e1e2e"),

/// Where a new window should attach, top or bottom of the stack
attach_mode: AttachMode = .top,
/// Should focus change when the cursor moves onto a new window
focus_follows_pointer: bool = true,
/// Should the pointer warp to the center of newly-focused windows
pointer_warp_on_focus_change: bool = true,
```

I plan to add Keybinds shortly. If parsing the configuration fails,
the default config will be used and the WM will continue loading.
2026-01-27 14:54:27 -06:00
Ben Buhse
b8d31de3ef
Start adding tags
Right now, essentially nothing has changed, there is still no multi-
output support and not even a way to change/set/toggle/view/etc. tags.

However, tags *are* implemented at a core level. Next step is to add
keybinds for the various tag actions.

After that, I will work on multi-output support.
2026-01-26 15:04:41 -06:00
Ben Buhse
87ec2d4f60
Working on refactoring inits 2026-01-26 13:10:51 -06:00
Ben Buhse
30231f1149
Refactor initialization and Context struct
I tried to make it a little bit easier to follow and get rid of the
need to call back to context.x.y.z (as much) [I hope]
2026-01-24 17:48:01 -06:00
Ben Buhse
9d64ca0124
Add focus to my single window 2025-08-03 20:49:06 -05:00
Ben Buhse
bad5007670
Display a single window! 2025-08-03 09:31:27 -05:00