xwayland: use a completely separate coordinate system

Use a completely separate coordinate system for XWayland. This fixes all issues with force_zero_scaling overlaps.

Fixes #2916
This commit is contained in:
Vaxry 2023-08-15 19:15:37 +02:00
parent 2b4537606f
commit 91e28bbe9d
5 changed files with 41 additions and 52 deletions

View file

@ -2487,6 +2487,8 @@ void CCompositor::setIdleActivityInhibit(bool enabled) {
} }
void CCompositor::arrangeMonitors() { void CCompositor::arrangeMonitors() {
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
std::vector<CMonitor*> toArrange; std::vector<CMonitor*> toArrange;
std::vector<CMonitor*> arranged; std::vector<CMonitor*> arranged;
@ -2522,4 +2524,12 @@ void CCompositor::arrangeMonitors() {
m->moveTo({maxOffset, 0}); m->moveTo({maxOffset, 0});
maxOffset += m->vecPosition.x + m->vecSize.x; maxOffset += m->vecPosition.x + m->vecSize.x;
} }
// reset maxOffset (reuse)
// and set xwayland positions aka auto for all
maxOffset = 0;
for (auto& m : m_vMonitors) {
m->vecXWaylandPosition = {maxOffset, 0};
maxOffset += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x);
}
} }

View file

@ -356,6 +356,9 @@ void CWindow::moveToWorkspace(int workspaceID) {
m_pSwallowed->moveToWorkspace(workspaceID); m_pSwallowed->moveToWorkspace(workspaceID);
m_pSwallowed->m_iMonitorID = m_iMonitorID; m_pSwallowed->m_iMonitorID = m_iMonitorID;
} }
// update xwayland coords
g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec());
} }
CWindow* CWindow::X11TransientFor() { CWindow* CWindow::X11TransientFor() {
@ -687,7 +690,7 @@ void CWindow::setGroupCurrent(CWindow* pWindow) {
g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode); g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode);
PCURRENT->setHidden(true); PCURRENT->setHidden(true);
pWindow->setHidden(false); // can remove m_pLastWindow pWindow->setHidden(false); // can remove m_pLastWindow
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow); g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);

View file

@ -30,10 +30,11 @@ class CMonitor {
CMonitor(); CMonitor();
~CMonitor(); ~CMonitor();
Vector2D vecPosition = Vector2D(-1, -1); // means unset Vector2D vecPosition = Vector2D(-1, -1); // means unset
Vector2D vecSize = Vector2D(0, 0); Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset
Vector2D vecPixelSize = Vector2D(0, 0); Vector2D vecSize = Vector2D(0, 0);
Vector2D vecTransformedSize = Vector2D(0, 0); Vector2D vecPixelSize = Vector2D(0, 0);
Vector2D vecTransformedSize = Vector2D(0, 0);
bool primary = false; bool primary = false;

View file

@ -54,6 +54,7 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
if (pWindow->m_bIsX11) { if (pWindow->m_bIsX11) {
setWindowSize(pWindow, pWindow->m_vRealSize.vec()); // update xwayland output pos
if (activate) { if (activate) {
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false); wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false);
@ -142,14 +143,28 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool force) { void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool force) {
if (!force && static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
if (!PMONITOR)
return; return;
pWindow->m_vReportedPosition = pWindow->m_vRealPosition.vec(); // calculate pos
pWindow->m_vReportedSize = size; // TODO: this should be decoupled from setWindowSize IMO
Vector2D windowPos = pWindow->m_vRealPosition.vec();
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; if (pWindow->m_bIsX11) {
windowPos = windowPos - PMONITOR->vecPosition; // normalize to monitor
if (*PXWLFORCESCALEZERO)
windowPos = windowPos * PMONITOR->scale; // scale if applicable
windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland
}
if (!force && ((pWindow->m_vReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
return;
pWindow->m_vReportedPosition = windowPos;
pWindow->m_vReportedSize = size;
pWindow->m_fX11SurfaceScaledBy = 1.f; pWindow->m_fX11SurfaceScaledBy = 1.f;
@ -160,10 +175,8 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f
} }
} }
const Vector2D POS = *PXWLFORCESCALEZERO && pWindow->m_bIsX11 ? pWindow->m_vRealPosition.vec() * pWindow->m_fX11SurfaceScaledBy : pWindow->m_vRealPosition.vec();
if (pWindow->m_bIsX11) if (pWindow->m_bIsX11)
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, POS.x, POS.y, size.x, size.y); wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y);
else else
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y);
} }

View file

@ -107,7 +107,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r
void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
const auto POS = pOutput->overridePosition.value_or(pOutput->monitor->vecPosition); const auto POS = pOutput->isXWayland ? pOutput->monitor->vecXWaylandPosition : pOutput->monitor->vecPosition;
zxdg_output_v1_send_logical_position(pOutput->resource->resource(), POS.x, POS.y); zxdg_output_v1_send_logical_position(pOutput->resource->resource(), POS.x, POS.y);
if (*PXWLFORCESCALEZERO && pOutput->isXWayland) if (*PXWLFORCESCALEZERO && pOutput->isXWayland)
@ -120,47 +120,9 @@ void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
} }
void CXDGOutputProtocol::updateAllOutputs() { void CXDGOutputProtocol::updateAllOutputs() {
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
std::vector<SXDGOutput*> xwlOutputs;
for (auto& o : m_vXDGOutputs) { for (auto& o : m_vXDGOutputs) {
if (o->isXWayland && *PXWLFORCESCALEZERO) {
xwlOutputs.push_back(o.get());
o->overridePosition.reset();
continue;
}
updateOutputDetails(o.get()); updateOutputDetails(o.get());
wlr_output_schedule_done(o->monitor->output); wlr_output_schedule_done(o->monitor->output);
} }
// all of this will be noop if force_zero_scaling is off
std::sort(xwlOutputs.begin(), xwlOutputs.end(), [&](const auto& a, const auto& b) { return a->monitor->vecPosition < b->monitor->vecPosition; });
for (auto& o : xwlOutputs) {
Vector2D suggestedPos = o->monitor->vecPosition;
// check for overlaps
for (auto& o1 : xwlOutputs) {
if (!o1->overridePosition.has_value())
continue;
const auto OPOS = o1->overridePosition.value();
if (OPOS.x + o1->monitor->vecTransformedSize.x > suggestedPos.x && /* Y overlap */
!(suggestedPos.y + o->monitor->vecTransformedSize.y <= OPOS.y || OPOS.y + o1->monitor->vecTransformedSize.y <= suggestedPos.y))
suggestedPos.x = OPOS.x + o1->monitor->vecTransformedSize.x;
if (OPOS.y + o1->monitor->vecTransformedSize.y > suggestedPos.y && /* X overlap */
!(suggestedPos.x + o->monitor->vecTransformedSize.x <= OPOS.x || OPOS.x + o1->monitor->vecTransformedSize.x <= suggestedPos.x))
suggestedPos.y = OPOS.y + o1->monitor->vecTransformedSize.y;
}
o->overridePosition = suggestedPos;
updateOutputDetails(o);
wlr_output_schedule_done(o->monitor->output);
}
} }