The window module re-entered the same shared_mutex while refreshing IPC state:
update() took the lock and then called queryActiveWorkspace(), which tried to
lock it again. That is undefined behavior for std::shared_mutex and could
manifest as a deadlock.
Remove the recursive lock path and reset the derived window state before each
IPC refresh. That keeps solo/floating/swallowing/fullscreen classes from
sticking around when the client lookup fails or a workspace becomes empty.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
This commit addresses memory churn caused by implicit deep copies during traversal and allocation of complex structures:
- Replaced pass-by-value 'Json::Value' in std::ranges and range-based for loops with 'const auto&' or 'const Json::Value&' in Hyprland modules, preventing large JSON tree duplications on every update.
- Fixed implicit string and pair copies in UPower and CPU Frequency loops by converting 'auto' to 'const auto&' where possible.
- Added 'std::vector::reserve' calls before 'push_back' loops in MPRIS, Niri, and CFFI modules to prevent exponential vector reallocation during initialization.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
- Move GTK operations from IPC thread to GTK main thread in Window module
- Move GTK operations from IPC thread to GTK main thread in WindowCount module
- Move GTK style class operations from IPC thread to GTK main thread in Submap module
- Language and Workspaces modules already safe (only update internal state)
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
Both flags are wrong, because:
- the active group member can be fullscreened.
- technically, a grouped window can be solo as well, because only the active group member is shown, the other members are hidden. Also you can have a group consisting of only one window.
Gracefully handle lack of response from the IPC. If socket isn't
available, we already log the IPC isn't running. We dont need to crash
program just because we couldn't get responses. We can just return an
empty object.
There were two main issues with fmtlib and C++20 mode:
- `fmt::format` defaults to compile-time argument checking and requires
using `fmt::runtime(format_string)` to bypass that.
- `std::format` implementation introduces conflicting declarations and
we have to specify the namespace for all `format`/`format_to` calls.
The first crash occurs when trying to parse the
ID of a workspace as an uint, since named
workspaces has negative IDs. This is fixed by
using ints for workspace IDs instead of uints.
The second crash occurs when converting a
workspace name that isn't a number to an integer.
This is fixed by wrapping std::stoi in a try
block and only sorting by number, when both names
can successfully be converted to integers.