diff --git a/CHANGELOG.md b/CHANGELOG.md index 481cdc6..e7f91e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased + +### Fixed +- A window dragged to another monitor now moves to that monitor's workspace. Before, Hyprland still filed it under the old monitor, so the controls were drawn off-screen and disappeared. + ## 0.2.0 A rewrite of the plugin's internals. Every v0.1 feature is still there, and your existing `~/.config/omarchy/mouse-first.json` keeps working. diff --git a/src/DragController.qml b/src/DragController.qml index 5e01f17..f008d15 100644 --- a/src/DragController.qml +++ b/src/DragController.qml @@ -135,6 +135,8 @@ Item { } else if (root.rect) { root.tracker.dispatch(Hypr.move(root.address, root.rect.x, root.rect.y)) } + // A window dropped on another monitor still belongs to the old one. + if (root.rect) root.tracker.evalLua(Hypr.evalAdopt(root.address, root.rect)) restoreAnimTimer.pendingAddress = root.address restoreAnimTimer.restart() } diff --git a/src/js/hypr.js b/src/js/hypr.js index 15cf3f2..9e82645 100644 --- a/src/js/hypr.js +++ b/src/js/hypr.js @@ -86,6 +86,11 @@ function evalRestore(address, workspace) { return a ? "MOUSE_FIRST.restore(" + luaString(a) + ", " + luaString(workspace || "") + ")" : "" } +function evalAdopt(address, r) { + var a = normalizeAddress(address) + return a && r ? "MOUSE_FIRST.adopt(" + luaString(a) + ", " + int(r.x) + ", " + int(r.y) + ", " + int(r.w) + ", " + int(r.h) + ")" : "" +} + function evalFloatRule(enabled, center) { return "MOUSE_FIRST.set_float_rule(" + (enabled ? "true" : "false") + ", " + (center ? "true" : "false") + ")" } diff --git a/src/lua/mousefirst.lua b/src/lua/mousefirst.lua index 855e603..a6b5713 100644 --- a/src/lua/mousefirst.lua +++ b/src/lua/mousefirst.lua @@ -251,6 +251,32 @@ function M.restore(address, workspace) hl.dispatch(hl.dsp.focus({ window = "address:" .. address })) end +-- The shell moves windows with absolute coordinates, which never changes the +-- monitor or workspace Hyprland files them under. After a drag drops a window +-- on another monitor, move it to that monitor's active workspace and put the +-- geometry back (the workspace move shifts floating windows on its own). +function M.adopt(address, x, y, w, h) + local win = hl.get_window("address:" .. address) + if not win then return end + local cx, cy = x + w / 2, y + math.min(h / 2, 8) + for _, m in ipairs(hl.get_monitors()) do + local scale = (m.scale and m.scale > 0) and m.scale or 1 + local mw, mh = m.width / scale, m.height / scale + if (tonumber(m.transform) or 0) % 2 == 1 then mw, mh = mh, mw end + if cx >= m.x and cx < m.x + mw and cy >= m.y and cy < m.y + mh then + if win.monitor and win.monitor.name == m.name then return end + local ws = m.active_workspace + if not ws then return end + local target = "address:" .. address + hl.dispatch(hl.dsp.window.move({ workspace = tostring(ws.id), window = target, follow = true })) + hl.dispatch(hl.dsp.window.resize({ x = w, y = h, window = target })) + hl.dispatch(hl.dsp.window.move({ x = x, y = y, relative = false, window = target })) + hl.dispatch(hl.dsp.focus({ window = target })) + return + end + end +end + -- v0.1 parked windows on special:mf-minimized; move them to the shared one. function M.migrate_legacy_minimized() for _, w in ipairs(hl.get_windows() or {}) do