From dd3b6e1bf084a92b835f005d954a0cf4858b656f Mon Sep 17 00:00:00 2001 From: Grigory Vasilyev Date: Mon, 27 Nov 2023 11:05:37 +0300 Subject: [PATCH] Fix float windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add parameter general:float_min_crop for support minimal size window cropping for windows that cannot transition to float. - Add parameter general:float_center_screen to control spawn new float windows. 1 - New float windows spawn in center screen. 0 - Сonsider the trimming at the top and bottom to calculate the center of the screen. For example, consider the size of the waybar. - Fix float windows - Fix togglefloat - Fix windows that start float and then go into a normal window, aka program launchers. Example: Blizzard battle.net client. The bug render full-screen programs partially behind the screen. Now the xwayland games launch normally. - Code cleanup and refactoring. - Replaced vec() with goalv() in logic other than animation, it seemed to me more correct because goalv() is used in many places. Not sure if this is correct. --- src/Window.hpp | 2 ++ src/config/ConfigManager.cpp | 2 ++ src/events/Windows.cpp | 42 ++++++++++++++++++++-------- src/layout/IHyprLayout.cpp | 47 +++++++++++++++++++++++++++----- src/managers/XWaylandManager.cpp | 19 ++++++------- 5 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/Window.hpp b/src/Window.hpp index 4e1ab9c1..e5536885 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -214,6 +214,8 @@ class CWindow { // for restoring floating statuses Vector2D m_vLastFloatingSize; Vector2D m_vLastFloatingPosition; + Vector2D m_vLastFloatingCropSize; + bool m_vLastFloatingCenterScreen; // this is used for pseudotiling bool m_bIsPseudotiled = false; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 257446ee..65380421 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -94,6 +94,8 @@ void CConfigManager::setDefaultVars() { configValues["general:resize_on_border"].intValue = 0; configValues["general:extend_border_grab_area"].intValue = 15; configValues["general:hover_icon_on_border"].intValue = 1; + configValues["general:float_min_crop"].vecValue = Vector2D(0.25, 0.25); + configValues["general:float_center_screen"].intValue = 0; configValues["general:layout"].strValue = "dwindle"; configValues["general:allow_tearing"].intValue = 0; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 2ee70264..be7890e7 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1043,13 +1043,21 @@ void Events::listener_configureX11(void* owner, void* data) { PWINDOW->m_vRealPosition.setValueAndWarp(LOGICALPOS); PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height)); + auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + if (!PMONITOR) { + PMONITOR = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.0); + PWINDOW->m_iMonitorID = PMONITOR->ID; + } static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { - const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale; - PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); - PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0); - } + PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); + static auto* const FLOATCENTERSCREEN = &g_pConfigManager->getConfigValuePtr("general:float_center_screen")->intValue; + PWINDOW->m_vLastFloatingCenterScreen = *FLOATCENTERSCREEN; + if (*FLOATCENTERSCREEN) + PWINDOW->m_vRealPosition.setValueAndWarp(PMONITOR->vecPosition + (PMONITOR->vecSize - PWINDOW->m_vRealSize.goalv()) / 2.0); + else + PWINDOW->m_vRealPosition.setValueAndWarp(PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft + + (PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight - PWINDOW->m_vRealSize.goalv()) / 2.0); } PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec(); @@ -1057,7 +1065,7 @@ void Events::listener_configureX11(void* owner, void* data) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); - PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace; + PWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace; g_pCompositor->changeWindowZOrder(PWINDOW, true); @@ -1108,18 +1116,28 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height)); + auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + if (!PMONITOR) { + PMONITOR = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.0); + PWINDOW->m_iMonitorID = PMONITOR->ID; + } + if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { - const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale; - PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); - PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0); - } + PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); + static auto* const FLOATCENTERSCREEN = &g_pConfigManager->getConfigValuePtr("general:float_center_screen")->intValue; + PWINDOW->m_vLastFloatingCenterScreen = *FLOATCENTERSCREEN; + if (*FLOATCENTERSCREEN) + PWINDOW->m_vRealPosition.setValueAndWarp(PMONITOR->vecPosition + (PMONITOR->vecSize - PWINDOW->m_vRealSize.goalv()) / 2.0); + else + PWINDOW->m_vRealPosition.setValueAndWarp(PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft + + (PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight - PWINDOW->m_vRealSize.goalv()) / + 2.0); } PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv(); PWINDOW->m_vSize = PWINDOW->m_vRealSize.goalv(); - PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace; + PWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace; g_pCompositor->changeWindowZOrder(PWINDOW, true); PWINDOW->updateWindowDecos(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index acd84684..5332fe26 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -455,9 +455,10 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { // if the window is pseudo, update its size if (!pWindow->m_bDraggingTiled) - pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv(); + pWindow->m_vPseudoSize = PSAVEDSIZE; - pWindow->m_vLastFloatingSize = PSAVEDSIZE; + pWindow->m_vLastFloatingPosition = PSAVEDPOS; + pWindow->m_vLastFloatingSize = PSAVEDSIZE; // move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back. pWindow->m_vPosition = Vector2D(-999999, -999999); @@ -477,18 +478,50 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { g_pCompositor->changeWindowZOrder(pWindow, true); - if (DELTALESSTHAN(pWindow->m_vRealSize.vec().x, pWindow->m_vLastFloatingSize.x, 10) && DELTALESSTHAN(pWindow->m_vRealSize.vec().y, pWindow->m_vLastFloatingSize.y, 10)) { - pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f + Vector2D{10, 10}; - pWindow->m_vRealSize = pWindow->m_vLastFloatingSize - Vector2D{20, 20}; + auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + if (!PMONITOR) { + PMONITOR = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.0); + pWindow->m_iMonitorID = PMONITOR->ID; + } + + const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv(); + static auto* const FLOATMINCROP = &g_pConfigManager->getConfigValuePtr("general:float_min_crop")->vecValue; + Vector2D cropSize = {0, 0}; + if (FLOATMINCROP->x > 0 && FLOATMINCROP->x < 1.0) + cropSize.x = PSAVEDSIZE.x * FLOATMINCROP->x; + else + cropSize.x = FLOATMINCROP->x; + if (FLOATMINCROP->y > 0 && FLOATMINCROP->y < 1.0) + cropSize.y = PSAVEDSIZE.y * FLOATMINCROP->y; + else + cropSize.y = FLOATMINCROP->y; + + if ((pWindow->m_vLastFloatingCropSize.x > 0 && pWindow->m_vLastFloatingCropSize.y > 0 && pWindow->m_vLastFloatingCropSize.x != cropSize.x && + pWindow->m_vLastFloatingCropSize.y != cropSize.y) || + (DELTALESSTHAN(PSAVEDSIZE.x, pWindow->m_vLastFloatingSize.x, cropSize.x) && DELTALESSTHAN(PSAVEDSIZE.y, pWindow->m_vLastFloatingSize.y, cropSize.y))) { + pWindow->m_vLastFloatingSize = PSAVEDSIZE - cropSize; + pWindow->m_vLastFloatingPosition = {0, 0}; + pWindow->m_vLastFloatingCropSize = cropSize; + } + + static auto* const FLOATCENTERSCREEN = &g_pConfigManager->getConfigValuePtr("general:float_center_screen")->intValue; + if (pWindow->m_vLastFloatingPosition.x <= 0 || pWindow->m_vLastFloatingPosition.y <= 0) { + if (*FLOATCENTERSCREEN) { + pWindow->m_vLastFloatingPosition = PMONITOR->vecPosition + (PMONITOR->vecSize - pWindow->m_vLastFloatingSize) / 2.0; + } else { + pWindow->m_vLastFloatingPosition = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft + + (PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight - pWindow->m_vLastFloatingSize) / 2.0; + } + pWindow->m_vLastFloatingCenterScreen = *FLOATCENTERSCREEN; } - pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; + pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; pWindow->m_vSize = pWindow->m_vRealSize.goalv(); pWindow->m_vPosition = pWindow->m_vRealPosition.goalv(); - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); + g_pHyprRenderer->damageMonitor(PMONITOR); pWindow->updateSpecialRenderData(); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 2883f205..a2293baa 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -172,16 +172,13 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f pWindow->m_fX11SurfaceScaledBy = 1.f; - if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); PMONITOR) { + if (pWindow->m_bIsX11) { + if (*PXWLFORCESCALEZERO) { size = size * PMONITOR->scale; pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale; } - } - - if (pWindow->m_bIsX11) wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y); - else + } else pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y), size.floor())); } @@ -242,13 +239,15 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) { return true; // override_redirect const auto SIZEHINTS = pWindow->m_uSurface.xwayland->size_hints; - if (SIZEHINTS && (pWindow->m_uSurface.xwayland->parent || ((SIZEHINTS->min_width == SIZEHINTS->max_width) && (SIZEHINTS->min_height == SIZEHINTS->max_height)))) + if (SIZEHINTS && + (pWindow->m_uSurface.xwayland->parent || + (SIZEHINTS->min_width > 0 && SIZEHINTS->min_height > 0 && SIZEHINTS->min_width == SIZEHINTS->max_width && SIZEHINTS->min_height == SIZEHINTS->max_height))) return true; } else { const auto PSTATE = &pWindow->m_uSurface.xdg->toplevel->current; - - if ((PSTATE->min_width != 0 && PSTATE->min_height != 0 && (PSTATE->min_width == PSTATE->max_width || PSTATE->min_height == PSTATE->max_height)) || - pWindow->m_uSurface.xdg->toplevel->parent) + if (PSTATE && + (pWindow->m_uSurface.xdg->toplevel->parent || + (PSTATE->min_width > 0 && PSTATE->min_height > 0 && PSTATE->min_width == PSTATE->max_width && PSTATE->min_height == PSTATE->max_height))) return true; }