At least tag rules seem to be working (but they're not frame perfect).
I might need to investigate more for float/no_float.
Rules are ANDed and only apply during window's first manage sequence,
so changing an appid/title doesn't affect anything.
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.
This helps us with de-duplication. Previously, if you had host-specific
keybinds on the same key combination, the compositor would choose the
first... which is the opposite of how everything else in our config
handling works.
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.
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.
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.
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).
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.
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.
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.
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.
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.
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
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`.
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.
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.
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"
```
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.
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