Conversation
Replace LayoutManager include path (managers/ -> layout/), add EventBus and Time headers, and update render function pointer typedefs to use Time::steady_tp instead of timespec* and PHLLS instead of PHLLSREF.
Replace timespec*/clock_gettime with Time::steady_tp/steadyNow(), update renderLayerStub to pass PHLLS directly and add lockscreen param, and remove the drag window/mode trick from renderWindowStub since those fields no longer exist on InputManager.
Replace g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ownerID) with g_layoutManager->recalculateMonitor(pMonitor) which now takes a PHLMONITOR instead of a MONITORID.
Replace g_pInputManager->m_currentlyDraggedWindow and direct layout calls with g_layoutManager->dragController()->target() and g_layoutManager->endDragTarget().
Replace all registerCallbackDynamic() calls with Event::bus()->m_events.*.listen() using the new typed signal system. Update all event handler signatures to receive typed arguments directly instead of std::any. Replace HOOK_CALLBACK_FN shared pointers with CHyprSignalListener. Key changes per handler: - onRender: receives eRenderStage directly - onMouseButton/Axis: typed event + SCallbackInfo - onSwipe*: typed event + SCallbackInfo - onKeyPress: typed event, keyboard from SeatManager - onTouch*: typed events + SCallbackInfo - onWorkspaceChange: receives PHLWORKSPACE directly - Drag window access via g_layoutManager->dragController()
|
I really tried but couldn't get this working on NixOS with 0.54. Several glitches, making changes to your code I got the stage where it would shortly show the overview. It's mostly pushing down my waybar/windows and then staying stuck here. Hopefully someone else can also test and maybe find where things go wrong.. |
|
Kinda same for me. After some hustle I managed to build, load and run the plugin but it also pushes waybar down and leaves it there and it will only work without any other open tiles. As soon as there's only one other tile open, toggling Hyprspace will crash Hyprland and throw me into the fallback config. It also crashes when clicking around on the workspace overlays a bunch. This is under Arch EndeavourOS btw. hyprspaceCrash.mp4 |
|
@jemabaris The same thing happened to me yesterday when I enabled it, and it made me wonder if it's something on my side! Thank you for the recording, it's going to help clarify the issue. |
|
A workaround for the effects shown in this video recording: plugin:overview:affectStrut = false |
This fixes Waybar being pushed down but the rest is still broken. Toggling Hyprspace with any other app open immediately crashes, so still unusable. |
|
I'm on latest version of hyprland and getting the same library errors when compiling Hyprland detailsBuilding Plugin |
|
I did continue a bit on this one. I made it work for me quite stable. I am running on EnveavourOS as well. main...pascal-fischer:Hyprspace:main |
Thanks Bro It's Work 👍 |
I got it working on NixOS with Hyprland 54.2. 🏆 Now for the weirdness: When I first login to my session the plugin is unusable, windows become opaque, the overview shows 1 workspace glitching every time I glitch-small.mp4Any wizzards that could explain what is going on? Do these recording apps somehow refresh something in the Wayland protocol that makes this start working? Tried rebooting, reloading wayland config. Different amount of applications that are started. Happy for now at least. |
The .listen() method on Cancellable<T> signals does not properly thread SCallbackInfo& back to handlers, so info.cancelled was silently ignored, causing double-firing and crashes on Hyprland 0.54.x. Add listenCancellable<EventType>() template in Globals.hpp that uses registerListenerInternal to unpack void* args as std::tuple<const EventType&, Event::SCallbackInfo&>*.
Migrate mouse button/axis, touch down/motion/up, swipe begin/update/end, and keyboard key hooks from .listen() to listenCancellable<EventType>() so SCallbackInfo.cancelled is properly propagated to Hyprland. Also pass e.axis to axisEvent and remove the WL_POINTER_AXIS_SOURCE_WHEEL filter (replaced by per-axis routing in axisEvent itself). Disable gestures by default (disableGestures = 1) as they are unstable on Hyprland 0.54.x.
Storing a truncated 32-bit pointer in prevFullscreen and resolving it via getWindowFromHandle() is fragile and can crash when a window is destroyed between show() and hide(). Change prevFullscreen type to std::vector<std::tuple<PHLWINDOWREF, eFullscreenMode>>, store PHLWINDOWREF(w) on open, and call .lock() with a null check on restore.
CFakeDamageElement was a one-off IPassElement subclass used only to
force blur recomputation via needsLiveBlur(). Replace with a second
damageMonitor() call which achieves the same result cleanly.
Also fix modifs.push_back() calls to use std::make_pair(type, std::any(value))
instead of aggregate {type, value} init which does not correctly construct
the std::any member.
Remove the unused #include "src/helpers/memory/Memory.hpp".
Add wl_pointer_axis axis parameter to axisEvent. Horizontal scroll always pans the panel; vertical scroll switches workspace or pans the panel when cursor is over it. Hardcode swipe fingers to 3 — the gestures:workspace_swipe_fingers config key does not exist in Hyprland 0.54.x.
Add early return if getOwner() returns null to prevent a crash when updateLayout() is called on a widget whose monitor has been unplugged.
The KZDKM refactor moved arrangeLayersForMonitor() before the m_reservedArea assignment, then read pMonitor->m_reservedArea.top() and added currentHeight to it. This double-counts on every call because arrangeLayersForMonitor() already applied layer surface reservations. Restore the correct ordering: set our panel reservation first (replacing the value entirely), then call arrangeLayersForMonitor() so it adds LS reservations on top without double-counting. Also restore the active=false branch to reset m_reservedArea to an empty CReservedArea() so the panel space is fully released on hide.
|
Hello folks! I added a bunch of other commits, but since I'm using I also tried to support Hyperland 0.54.0, 0.54.1 and 0.54.2, lets see how it goes =) |
|
Still crashing with the new additions for me, attached the logs. |
findFunctionsByName returns ALL matching symbols — on some systems Screenshare::CScreenshareFrame::renderWindow() appears first, causing renderWindowStub to call the wrong function and SEGV. Use the existing findFunctionBySymbol() helper to filter by demangled class name (CHyprRenderer::renderWindow / CHyprRenderer::renderLayer), restoring the behaviour from before the KZDKM refactoring commit. Fixes: KZDKM#223 (comment)
|
@martijnboers Thanks for the detailed backtrace — that was exactly what was needed to track this down. The crash is caused by Fix is in commit ec0f45d on the Could you rebuild from |
|
Thank you for your fixes, Douglas. Now we're definitely getting somewhere. Although it's still not quite working out for me. Pretty much any other app's window, except for the terminal's glitch out shortly after toggling Hyprspace. It's much better though than before, where doing so would immediately result in a crash. video_2026-03-14_00-02-17.mp4 |
|
Small update: I just realized that, similar to the description of another user on here, the issue with the disappearing windows seems to be gone after taking a screenshot once. It really looks like taking a screenshot or video wakes up something that's needed for hyprspace to function fully. |
hide() was missing a damageMonitor() call, causing windows to appear glitched/invisible after the close animation finished. draw() exits early once active=false and the animation is done, so no further damage was ever issued. Three fixes: - Add damageMonitor() to hide() before scheduleFrameForMonitor(), matching what show() already does. - Add curYOffset->setCallbackOnEnd callback (remove=false) in constructor and updateConfig() to issue a final damage+scheduleFrame once the close animation completes. - Remove duplicate rounding().unset() in renderWindowStub() (Render.cpp). Fixes the regression reported in PR KZDKM#223 by @jemabaris and @martijnboers.
|
@douglas I just rebuilt with the changes in your latest commit but the problem still persists sadly. Maybe I made a mistake, idk, but I couldn't see any improvement of the disappearing window glitch. I've rebuilt it even a second time to make sure but without success. |
|
@jemabaris The disappearing windows issue you're describing (fixed by taking a screenshot) is exactly what the latest commit The root cause: The fix adds two things:
Could you rebuild from the |
nearestNeighbor().set() at PRIORITY_SET_PROP was never balanced with unset() at the same priority level, permanently overriding nearest-neighbor rendering for every window rendered as a thumbnail.
damageMonitor() alone is insufficient: windows damaged at thumbnail coordinates during draw() are considered up-to-date by the compositor at their real positions after the overview closes. Fix by iterating all mapped windows on the monitor in hide() and the animation-end callback and calling damageWindow() on each, forcing a repaint at their real coordinates. Addresses the disappearing window glitch reported in PR KZDKM#223.
Add windowBoxes field (mirrors workspaceBoxes) populated during draw(). Each rendered window thumbnail position is converted to input coordinates and stored alongside a PHLWINDOWREF. Windows currently being dragged are skipped so their thumbnail disappears during drag. Extracted common window rendering into a renderAndTrackWindow lambda to reduce duplication.
Replace the broken CKeybindManager::mouse("1movewindow") approach —
it hit-tests at the real cursor position which fails in the overview panel.
New approach uses draggedWindowRef (PHLWINDOWREF) on the widget:
- Press: hit-test windowBoxes, set draggedWindowRef on match
- Release: if draggedWindowRef is set and cursor is over a workspace,
moveWindowToWorkspaceSafe + clear draggedWindowRef
- No dependency on Hyprland's internal drag API (CWindowTarget::create
is not exported, beginDragTarget unusable from plugins)
Also removed dead code: the old targetWindow/pMouseKeybind paths that
could never trigger because targetWorkspace was never null in the panel.
4ef1c4f to
db9c78c
Compare
|
@douglas I just did another build with the latest changes and the issue still persists. It's interesting though that you don't seem to have these issues yourself. Wonder why that is? |
Summary
Hyprland 0.54.0 introduces several breaking API changes. This PR updates Hyprspace to be compatible with the new APIs.
Breaking changes addressed
Event system rewrite:
registerCallbackDynamic()is deprecated (now a no-op). Migrated all 15 event hooks to the new typedEvent::bus()->m_events.*.listen()system usingCHyprSignalListenerhandles. All handlers now receive typed arguments directly instead ofstd::any.Layout system rewrite:
g_pLayoutManager->getCurrentLayout()was removed. Replaced withg_layoutManager->recalculateMonitor(PHLMONITOR)which now takes a monitor handle instead of a monitor ID.Drag state moved:
g_pInputManager->m_currentlyDraggedWindowandm_dragModeno longer exist on InputManager. Replaced withg_layoutManager->dragController()->target()->window()andg_layoutManager->endDragTarget().Renderer signatures:
renderWindow/renderLayernow useTime::steady_tpinstead oftimespec*.renderLayertakesPHLLSinstead ofPHLLSREFand has a newlockscreenparameter.Keyboard event: No longer packed in
std::unordered_map<std::string, std::any>. Handler receivesIKeyboard::SKeyEventdirectly, keyboard obtained viag_pSeatManager->m_keyboard.Mouse axis event: No longer wrapped in a map. Handler receives
IPointer::SAxisEventdirectly.Touch events: All touch handlers updated to receive typed event structs directly (
SDownEvent,SMotionEvent,SUpEvent).Commits
Organized as atomic, incremental changes:
Globals.hppRender.cpprecalculateMonitorchanges inLayout.cppInput.cppmain.cppTest plan
make allagainst Hyprland 0.54.0 headers (verified locally)