Commit graph

198 commits

Author SHA1 Message Date
Ben Buhse
ce9a972b60
Create config/input.zig
This mvoes all of the input {} block parsing into its own file
2026-02-16 14:05:42 -06:00
Ben Buhse
fc0482902e
Create config/pointer_binds.zig
This moves all of the pointer_binds {} block parsing into its own file
2026-02-16 14:05:42 -06:00
Ben Buhse
5d61663220
Create config/keybinds.zig
This moves all of the keybinds {} block parsing into its own file
2026-02-16 14:05:42 -06:00
Ben Buhse
ef5b4369a6
Create config/tag_overlay.zig
This moves all over the tag_overlay {} block parsing into its own file
2026-02-16 14:05:39 -06:00
Ben Buhse
83f8d00081
Create config/borders.zig
This moves all of the borders {} block parsing into its own file
2026-02-16 13:25:41 -06:00
Ben Buhse
8b43e491e7
Create config/helpers.zig
This moves all the helper functions from Config.zig into their own file
2026-02-16 12:01:47 -06:00
Ben Buhse
c1c9eb24f7 Merge pull request 'Implement river-tag-overlay clone' (#13) from tag-overlay into main
Reviewed-on: https://codeberg.org/bwbuhse/beansprout/pulls/13
2026-02-16 18:36:35 +01: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
2bef233d8f
Wire up TagOverlay into Config
The tag overlay still isn't actually created anywhere, but now it can
be configured.
2026-02-16 11:33:43 -06:00
Ben Buhse
ceabd231fe
Add fcft to README
I forgot to add this when I added the Bar
2026-02-16 09:13:34 -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
bcc0e9705e
Move Bar.inits() env into Context
Since each bar has its own, it's easier to just share it. This does
create a consistent slight overhead, but may be useful anyways if we
care about the Env more further down the line.
2026-02-15 17:20:59 -06:00
Ben Buhse
a122f1a439
Add Capabilities and State to LibinputDevice
These are two new sub-structs to keep a cleaner separation of state
and capabilities. Functionality should be the same.
2026-02-15 17:12:33 -06:00
Ben Buhse
dff3749710 Merge pull request 'Implement a basic bar' (#12) from bar into main
Reviewed-on: https://codeberg.org/bwbuhse/beansprout/pulls/12
2026-02-16 00:00:23 +01: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
2b336299eb
Add x/y paramaters to renderChars and renderGlyphs 2026-02-13 19:17:34 -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
5501ccbe26
Split main() up by adding parseArgs() and run()
parseArgs() contains all of the argument parsing logic in a single fn.

run() handles the event loop. To work with the bar, I had to re-write
the loop to use polling similar to the loop in `beanclock` instead of
just `while (true) dispatch`.
2026-02-13 11:10:42 -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
b48032bbba
Change two uses of alloc to use stack buffers
I was looking for places where it might have made sense to use something
like an arena or a fba instead of the C allocator, but almost all of the
allocations are for Wayland interfaces that are fairly long lived (and,
since they're using libwayland, need the C allocator).

Instead, I just found two places that could use buffers on the stack
instead. In Config.zig, we *were* allocating the config path with
fmt.AllocPrint, but std.fs.max_path_bytes exists, so we can just make
a buf of that size and save a heap allocation. This is only at start up
and on config reload so it doesn't do too much, but I'd like to remove
allocations when possible.

The other change is for utils.parseModifiers(). It was using
std.ascii.allocLowerString(), but we clamp the length of the string to
3-5 characters, so we can just make a 5 character buffer and then use
ascii.lowerString() instead. Again, not super helpful since the function
is (currently) only called when creating Configs, but it's still nice to
get rid of a heap alloc.
2026-02-12 14:10:28 -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
8e93395360
Update README.md, add docs/CONFIGURATION.md
I've finally added a somewhat usable README and also explained
configuration in docs/CONFIGURATION.md
2026-02-11 20:22:41 -06:00
Ben Buhse
0970702263
Add some unit tests for a few functions
Mostly only testing the easily-testable helpers in utils and Config
2026-02-11 16:14:29 -06:00
Ben Buhse
3ceaf8a004
Move TODOs into separate file, update README
I still have lots to do for the README, but I'll do that once I actually
am able to daily-drive beansprout.
2026-02-11 15:15:48 -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
604bf52150
Fix comment in README.md 2026-02-11 14:14:42 -06:00
Ben Buhse
bd74682096
Update input config to use "name=" property
This is to match behavior with how the new per-host configuration works
2026-02-11 14:12:23 -06:00
Ben Buhse
0b7e15d7ed
Add support for per-host user configuration
This uses KDL properties, i.e. "host=<hostname>" and can be applied to
any config type. An example is includes in examples/config.kdl.

```kdl
    wallpaper_image_path "~/Pictures/desktop.png" host="desktop"
    wallpaper_image_path "~/Pictures/laptop.png" host="laptop"
```
2026-02-11 13:59:37 -06:00
Ben Buhse
e29c4d01e1
Add support for 'None' modifier for keybinds
This is mostly useful for media and brightness keys, but could be used
for other stuff, too.
2026-02-11 13:01:12 -06:00
Ben Buhse
7f571da187 Merge pull request 'Implement input configuration' (#11) from input-config into main
Reviewed-on: https://codeberg.org/bwbuhse/beansprout/pulls/11
2026-02-11 19:39:55 +01:00
Ben Buhse
6d62a7175d
Fix possible race in LibinputDevice.manage()
Only clear should_manage once the device is fully initialized (has an
associated input_device with a name). Previously, should_manage was
cleared unconditionally, so if manage_start fired before the device was
fully linked, configs would never be applied.
2026-02-11 12:30:35 -06:00
Ben Buhse
296f875993
Implement libinput device configuration
We need to defer config application to the first manage_start event
using a should_manage flag so that all *_support events have arrived
before we try applying the configs

This commit also has two other fixes
- fixes a potential use-after-free by telling InputDevice when a
 LibinputDevice is .removed.
- fix logFn (removed "if (scope != .default) return;")

I used kwm to help figure out the manage pattern for the input config.
Link to kwm: https://github.com/kewuaa/kwm
2026-02-10 20:06:17 -06:00
Ben Buhse
3ce98712df
Update zig-kdl
This uses the latest commit that includes my fix for integer underflow
and includes a license (MPL).
2026-02-09 16:46:12 -06:00
Ben Buhse
f84defc8e9
Add input configuration to Config
It's a new node "input" that, if taking a name, includes the specific
input device the block should apply to. If no name is supplied,
the block applies to all inputs. Order matters and later config blocks
can override previous ones.

The config isn't actually used yet.
2026-02-09 16:45:55 -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
ec7474c9af
Implement some simple flags and runtime log-levels
I used flags.zig from Isaac Freund for parsing basic CLI arguments,
I don't need much else since most configuration is in Kdl.
e967499fb1/common/flags.zig

I also removed some of the duplicated bits for the exe_check step
since I realized I can just use the beansprout executable for all of it.
2026-02-08 16:25:30 -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
6dec98ae09 Merge pull request 'Implement wallpapers for outputs' (#10) from wallpaper into main
Reviewed-on: https://codeberg.org/bwbuhse/beansprout/pulls/10
2026-02-08 18:07:59 +01: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
fb8817ebf9
Begin work to add wallpaper support to beansprout
Added pixman and zigimg dependencies
Set up in build.zig, added to both exe and exe_check

Add new protocols:
     river-layer-shell-v1
     wlr-layer-shell-unstable-v1
     xdg-shell (dep of wlr-layer-shell-unstable-v1)

Update Context.zig to hold wl_output, wl_shm, and a WallpaperImage
Also re-ordered all of its fields into alphabetical order
Context.create() now takes a Context.Options struct so that it takes
     one arg instead of many smaller args.

Added new WallpaperImage.zig, but it's not yet actually used
2026-02-06 16:37:33 -06:00
Ben Buhse
e5d439e27d Merge pull request 'floating-windows' (#9) from floating-windows into main
Reviewed-on: https://codeberg.org/bwbuhse/beansprout/pulls/9
2026-02-06 21:39:50 +01:00