Commit graph

42 commits

Author SHA1 Message Date
Ben Buhse
f16f07fa26
Fix zombie processes from keybind spawns
Previously, beansprout used std.process.Child.spawn without ever calling
wait(), leaving exited children as zombies. This commit switches to a
double-fork based off river-classic's spawn handling, where the actual
spawned process gets orphaned and reparented to PID 1. This way, the
parent (i.e. beansprout) only has to wait for the intermediate child.

Also switch tokenizeShell and expandTilde to produce [:0]const u8 tokens
so the argv array for execvpeZ can be built without copying each string.

Fixes: #12
2026-04-26 11:22:35 -05:00
Ben Buhse
e862aca887
Fix crash when killing WM with windows active
In commit 75308a04, I added an assertion to Output.destroy() to verify
that all of its windows had been removed already. The issue is, that
only happened when Output received a .removed event, but that never
came when killing the WM directly. Instead, I simplified the handling
for the .removed event and moved most of that into destroy().

I also changed where structs have their wl_list.link removed (to inside
of their destroys) to make it more consistent. Finally,
XkbBinding.sendWindowToOutput asserts that the current output is actually
focused. Users *should* never have a focused window if there's not also
a focused output.
2026-04-12 11:29:21 -05:00
Ben Buhse
91d17042f6
Add two log messages to XkbBindings.focusOutput() 2026-04-02 18:22:10 -05:00
Ben Buhse
581f4334be
Fix toggle_passthrough command
When I implemented it, I forgot to verify I actually added a way to shut
it off...
2026-03-21 20:24:45 -05:00
Ben Buhse
63f5fc1bcd
Implement variable single-window ratio 2026-03-19 15:15:28 -05:00
Ben Buhse
678d0563ed
Add exit_river keybinding
Recently, river removed the hardcoded Ctrl+Alt Delete keybinding that
exits river and replaces it with a new `exit_session` request. This adds
support for that request via the new `exit_session` bind. We also added
3 hardcoded default keybinds to: exit river, reload the config, and
open foot. This way, if the config fails to load or is missing, you
should still be able to try reload. I guess you're still SOL if you have
at least one keybind and it's not reload_config, but you do what you can
do.
2026-03-06 09:21:07 -06:00
Ben Buhse
3150d1a842
Switch TagOverlay to use river_shell_surface_v1
This follows the same patterns that Wallpaper and Bar did and makes
TagOverlay use the same manage/render cycle as the rest of the WM.

We also switched to just use a poll timer like river-tag-overlay instead
of using the timerfd. I realized that the Zig stdlib doesn't actually
support timerfds for FreeBSD right now and I don't feel like adding them.
2026-03-05 20:36:19 -06:00
Ben Buhse
ece7b7e5bd
Fix focus_next/prev_output command
I fixed trying to send windows to a new output before, but now this
fixes it for also switching output focus.
2026-03-02 15:16:10 -06:00
Ben Buhse
07794019dc
Move old TODO comments to docs/TODO.md 2026-02-24 16:40:58 -06:00
Ben Buhse
8e6c28da7b
Fix some memory leaks 2026-02-22 17:38:28 -06:00
Ben Buhse
9fef3f70f5
Add XkbBinding.deinit()
Also fixed a crash if two non-spawn keybinds had the same keys
2026-02-22 14:57:41 -06:00
Ben Buhse
1b37ab7afd
Implement passthrough mode
When active, key presses are passed directly to the focused window.
I've mostly used this for testing beansprout, but I'm sure there are
other uses.
2026-02-22 08:59:45 -06:00
Ben Buhse
5f4d80f313
Fix sendTo{Prev,Next}Output commands
Before, they would try send the window to the "next" output even if
there was only one output... which really just means sending the window
to the bottom of the stack. Instead, they should be a noop.

Also fixed a bug when removing all outputs where the seat wouldn't
clear its focused output.
2026-02-19 14:01:51 -06:00
Ben Buhse
03fd4d0087
Make focus follow window when using swapWindow 2026-02-17 11:32:04 -06:00
Ben Buhse
5824f84c35
Fix zoom keybind bugs
There were two bugs:
1) If we were focused on the first window and then tried to use the
   zoom keybind, we looked for the next tiled window in the list
   (correctly skipping floating windows), but we didn't also check the
   tags. This meant that if the next window was on a non-visible tag,
   it didn't work.
2) After fixing that, we weren't updating the focus to the newly
   promoted window, so the border would flash around the window that got
   moved to 2nd for a frame. We just needed to update the pending focus
   window for seat if we had to swap windows.
2026-02-17 11:20:43 -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
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
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
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
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
07fbe91c13
Implement floating windows with pointer and keyboard controls
Add interactive move/resize operations using configurable pointer bindings
(Mod4+BTN_LEFT to move, Mod4+BTN_RIGHT to resize). Tiled windows
automatically float when dragged or resized.

Add keyboard commands for floating windows:
- move_up/down/left/right: move by pixel amount
- resize_width/height: resize by pixel amount
- swap_next/swap_prev: swap position in window stack

Fix float dimension initialization when windows first become floating,
and fix clamp crash when resizing windows larger than output bounds.

Update example config with documented keybinds and new pointer_binds block.
2026-02-06 14:36:12 -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
4157dd67f6
Fix use-after-free by moving config-reload into the manage cycle 2026-01-31 14:08:46 -06:00
Ben Buhse
cd32463d52
Add a keybind to reload config; still needs more testing 2026-01-31 10:47:20 -06:00
Ben Buhse
365c000b6e
Add change_ratio keybind 2026-01-30 21:47:16 -06:00
Ben Buhse
4e02a07bf1
Implement zoom keybind 2026-01-30 21:09:02 -06:00
Ben Buhse
fd8b6d0d41
Implement configuration for keybindings
Keybinds go in a "keybinds" block and follow the format

<command> <modifiers> <keysym> <options>

But there's also a special "tag_bind" command that just takes modifiers
and one of set_output_tags, set_window_tags, toggle_output_tags, and
toggle_window_tags. It will automatically be used to loop through the
1-9 keys on tags 1<<0 to 1<<9, however, you can still implement those
commands individually if you want.
2026-01-30 20:33:16 -06:00
Ben Buhse
9030de6b64
Get tags working with actual tag-switching support
I added 7 new Commands to XkbKeybinds.Commands, though 3 of them don't
work yet.

The new commands that *work* are

+    set_output_tags: u32,
+    set_window_tags: u32,
+    toggle_output_tags: u32,
+    toggle_window_tags: u32,

They each take a 32-bit value as a bitmask to set (or toggle) tags.

The 3 unimplemented commands are

+    spawn_tagmask: u32,
+    focus_previous_tags,
+    send_to_previous_tags,

and they will all panic if they're used.

For now, default keybinds are hardcoded as part of WindowManager's
initializing in the first \`manage_start\` event. Multi-output support
is not added yet, so this will still all happen on a single Output.
2026-01-26 17:44:34 -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
e1a0b89ced
Standardize panic messages and clean up code 2026-01-25 20:57:05 -06:00
Ben Buhse
c953fe3d68
Fix pointer warp for new and closed windows 2026-01-25 13:26:57 -06:00
Ben Buhse
bfa41f36b0
Add PendingState to Seat 2026-01-25 12:10:00 -06:00
Ben Buhse
137eac9364
Update comments; Check river.SeatV1 version; Prepend new windows 2026-01-24 18:23:13 -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
92e82f38f5
Implement fullscreening 2026-01-24 14:45:33 -06:00
Ben Buhse
578e2f449e
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.
2026-01-23 16:23:14 -06:00
Ben Buhse
2c18946703
Add river-xkb-bindings and implement Alt+T to open foot
This is the only keybind for now.
2026-01-19 14:32:46 -06:00