diff --git a/hyprtester/src/tests/main/dwindle.cpp b/hyprtester/src/tests/main/dwindle.cpp new file mode 100644 index 000000000..a75646c8d --- /dev/null +++ b/hyprtester/src/tests/main/dwindle.cpp @@ -0,0 +1,53 @@ +#include "../shared.hpp" +#include "../../shared.hpp" +#include "../../hyprctlCompat.hpp" +#include "tests.hpp" + +static int ret = 0; + +static void testFloatClamp() { + for (auto const& win : {"a", "b", "c"}) { + if (!Tests::spawnKitty(win)) { + NLog::log("{}Failed to spawn kitty with win class `{}`", Colors::RED, win); + ++TESTS_FAILED; + ret = 1; + return; + } + } + + OK(getFromSocket("/keyword dwindle:force_split 2")); + OK(getFromSocket("/dispatch focuswindow class:c")); + OK(getFromSocket("/dispatch setfloating class:c")); + OK(getFromSocket("/dispatch resizewindowpixel exact 1200 900,class:c")); + OK(getFromSocket("/dispatch settiled class:c")); + OK(getFromSocket("/dispatch setfloating class:c")); + + { + auto str = getFromSocket("/clients"); + EXPECT_CONTAINS(str, "at: 718,178"); + EXPECT_CONTAINS(str, "size: 1200,900"); + } + + OK(getFromSocket("/keyword dwindle:force_split 0")); + + // clean up + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); +} + +static bool test() { + NLog::log("{}Testing Dwindle layout", Colors::GREEN); + + // test + NLog::log("{}Testing float clamp", Colors::GREEN); + testFloatClamp(); + + // clean up + NLog::log("Cleaning up", Colors::YELLOW); + getFromSocket("/dispatch workspace 1"); + OK(getFromSocket("/reload")); + + return !ret; +} + +REGISTER_TEST_FN(test); diff --git a/hyprtester/src/tests/main/gestures.cpp b/hyprtester/src/tests/main/gestures.cpp index 4c56e904d..9b31cdb6d 100644 --- a/hyprtester/src/tests/main/gestures.cpp +++ b/hyprtester/src/tests/main/gestures.cpp @@ -45,11 +45,15 @@ static bool test() { EXPECT(Tests::windowCount(), 1); // Give the shell a moment to initialize - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); - OK(getFromSocket("/dispatch plugin:test:gesture up,4")); + OK(getFromSocket("/dispatch plugin:test:gesture up,5")); + OK(getFromSocket("/dispatch plugin:test:gesture down,5")); + OK(getFromSocket("/dispatch plugin:test:gesture left,5")); + OK(getFromSocket("/dispatch plugin:test:gesture right,5")); + OK(getFromSocket("/dispatch plugin:test:gesture right,4")); - EXPECT(waitForWindowCount(0, "Gesture sent ctrl+d to kitty"), true); + EXPECT(waitForWindowCount(0, "Gesture sent paste exit + enter to kitty"), true); EXPECT(Tests::windowCount(), 0); diff --git a/hyprtester/test.conf b/hyprtester/test.conf index e6d8cee3e..047001c26 100644 --- a/hyprtester/test.conf +++ b/hyprtester/test.conf @@ -350,7 +350,11 @@ gesture = 3, down, mod:ALT, float gesture = 3, horizontal, mod:ALT, workspace -gesture = 4, up, dispatcher, sendshortcut, ctrl, d, activewindow +gesture = 5, up, dispatcher, sendshortcut, , e, activewindow +gesture = 5, down, dispatcher, sendshortcut, , x, activewindow +gesture = 5, left, dispatcher, sendshortcut, , i, activewindow +gesture = 5, right, dispatcher, sendshortcut, , t, activewindow +gesture = 4, right, dispatcher, sendshortcut, , return, activewindow gesture = 4, left, dispatcher, movecursortocorner, 1 windowrule = float, pin, class:wr_kitty diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 2d3d4db94..fbf632439 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -257,7 +257,10 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) { return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y}; } - CBox box = {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y}; + const auto POS = m_realPosition->value(); + const auto SIZE = m_realSize->value(); + + CBox box{POS, SIZE}; box.addExtents(getWindowExtentsUnified(properties)); return box; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index e21cd886e..4ae41d575 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -790,17 +790,16 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { CBox wb = {pWindow->m_realPosition->goal() + (pWindow->m_realSize->goal() - pWindow->m_lastFloatingSize) / 2.f, pWindow->m_lastFloatingSize}; wb.round(); - if (!(pWindow->m_isFloating && pWindow->m_isPseudotiled) && DELTALESSTHAN(pWindow->m_realSize->value().x, pWindow->m_lastFloatingSize.x, 10) && - DELTALESSTHAN(pWindow->m_realSize->value().y, pWindow->m_lastFloatingSize.y, 10)) { + if (!(pWindow->m_isFloating && pWindow->m_isPseudotiled) && DELTALESSTHAN(pWindow->m_realSize->goal().x, pWindow->m_lastFloatingSize.x, 10) && + DELTALESSTHAN(pWindow->m_realSize->goal().y, pWindow->m_lastFloatingSize.y, 10)) { wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}}; } - *pWindow->m_realPosition = wb.pos(); - *pWindow->m_realSize = wb.size(); - pWindow->m_size = wb.size(); pWindow->m_position = wb.pos(); + fitFloatingWindowOnMonitor(pWindow, wb); + g_pHyprRenderer->damageMonitor(pWindow->m_monitor.lock()); pWindow->unsetWindowData(PRIORITY_LAYOUT); @@ -815,6 +814,36 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pHyprRenderer->damageWindow(pWindow); } +void IHyprLayout::fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional tb) { + if (!w->m_isFloating) + return; + + const auto PMONITOR = w->m_monitor.lock(); + + if (!PMONITOR) + return; + + const auto EXTENTS = w->getWindowExtentsUnified(RESERVED_EXTENTS | INPUT_EXTENTS); + CBox targetBoxMonLocal = tb.value_or(w->getWindowMainSurfaceBox()).translate(-PMONITOR->m_position).addExtents(EXTENTS); + + if (targetBoxMonLocal.w < PMONITOR->m_size.x) { + if (targetBoxMonLocal.x < 0) + targetBoxMonLocal.x = 0; + else if (targetBoxMonLocal.x + targetBoxMonLocal.w > PMONITOR->m_size.x) + targetBoxMonLocal.x = PMONITOR->m_size.x - targetBoxMonLocal.w; + } + + if (targetBoxMonLocal.h < PMONITOR->m_size.y) { + if (targetBoxMonLocal.y < 0) + targetBoxMonLocal.y = 0; + else if (targetBoxMonLocal.y + targetBoxMonLocal.h > PMONITOR->m_size.y) + targetBoxMonLocal.y = PMONITOR->m_size.y - targetBoxMonLocal.h; + } + + *w->m_realPosition = (targetBoxMonLocal.pos() + PMONITOR->m_position + EXTENTS.topLeft).round(); + *w->m_realSize = (targetBoxMonLocal.size() - EXTENTS.topLeft - EXTENTS.bottomRight).round(); +} + void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) { const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_lastWindow.lock(); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 027c95a58..d97a2ba8e 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -225,6 +225,11 @@ class IHyprLayout { */ virtual void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode MODE, const int CORNER, const Vector2D& BEGINSIZE); + /* + Fits a floating window on its monitor + */ + virtual void fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional targetBox = std::nullopt); + private: int m_mouseMoveEventCount; Vector2D m_beginDragXY;