diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7c0cb741..7b7f954d 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -95,15 +95,15 @@ CWindow::CWindow(SP resource) : m_pXDGSurface(resource) { CWindow::CWindow(SP surface) : m_pXWaylandSurface(surface) { m_pWLSurface = CWLSurface::create(); - listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); }); - listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); }); - listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); }); - listeners.commit = m_pXWaylandSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); }); - listeners.configure = m_pXWaylandSurface->events.configure.registerListener([this](std::any d) { onX11Configure(std::any_cast(d)); }); - listeners.updateState = m_pXWaylandSurface->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); }); - listeners.updateMetadata = m_pXWaylandSurface->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); }); - listeners.resourceChange = m_pXWaylandSurface->events.resourceChange.registerListener([this](std::any d) { onResourceChangeX11(); }); - listeners.activate = m_pXWaylandSurface->events.activate.registerListener([this](std::any d) { Events::listener_activateX11(this, nullptr); }); + listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); }); + listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); }); + listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); }); + listeners.commit = m_pXWaylandSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); }); + listeners.configureRequest = m_pXWaylandSurface->events.configureRequest.registerListener([this](std::any d) { onX11ConfigureRequest(std::any_cast(d)); }); + listeners.updateState = m_pXWaylandSurface->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); }); + listeners.updateMetadata = m_pXWaylandSurface->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); }); + listeners.resourceChange = m_pXWaylandSurface->events.resourceChange.registerListener([this](std::any d) { onResourceChangeX11(); }); + listeners.activate = m_pXWaylandSurface->events.activate.registerListener([this](std::any d) { Events::listener_activateX11(this, nullptr); }); if (m_pXWaylandSurface->overrideRedirect) listeners.setGeometry = m_pXWaylandSurface->events.setGeometry.registerListener([this](std::any d) { Events::listener_unmanagedSetGeometry(this, nullptr); }); @@ -1530,14 +1530,14 @@ void CWindow::onResourceChangeX11() { Debug::log(LOG, "xwayland window {:x} -> association to {:x}", (uintptr_t)m_pXWaylandSurface.get(), (uintptr_t)m_pWLSurface->resource().get()); } -void CWindow::onX11Configure(CBox box) { +void CWindow::onX11ConfigureRequest(CBox box) { if (!m_pXWaylandSurface->surface || !m_pXWaylandSurface->mapped || !m_bIsMapped) { m_pXWaylandSurface->configure(box); m_vPendingReportedSize = box.size(); m_vReportedSize = box.size(); - if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) - m_fX11SurfaceScaledBy = PMONITOR->scale; + m_vReportedPosition = box.pos(); + updateX11SurfaceScale(); return; } @@ -1555,25 +1555,20 @@ void CWindow::onX11Configure(CBox box) { else setHidden(true); - const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos()); - - m_vRealPosition->setValueAndWarp(LOGICALPOS); - m_vRealSize->setValueAndWarp(box.size()); - - static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) { - m_vRealSize->setValueAndWarp(m_vRealSize->goal() / PMONITOR->scale); - m_fX11SurfaceScaledBy = PMONITOR->scale; - } - } + m_vRealPosition->setValueAndWarp(xwaylandPositionToReal(box.pos())); + m_vRealSize->setValueAndWarp(xwaylandSizeToReal(box.size())); m_vPosition = m_vRealPosition->goal(); m_vSize = m_vRealSize->goal(); - m_vPendingReportedSize = box.size(); - m_vReportedSize = box.size(); + if (m_vPendingReportedSize != box.size() || m_vReportedPosition != box.pos()) { + m_pXWaylandSurface->configure(box); + m_vReportedSize = box.size(); + m_vPendingReportedSize = box.size(); + m_vReportedPosition = box.pos(); + } + updateX11SurfaceScale(); updateWindowDecos(); if (!m_pWorkspace || !m_pWorkspace->isVisible()) @@ -1700,37 +1695,74 @@ Vector2D CWindow::requestedMaxSize() { return maxSize; } -void CWindow::sendWindowSize(bool force) { +Vector2D CWindow::realToReportSize() { + if (!m_bIsX11) + return m_vRealSize->goal().clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - const auto PMONITOR = m_pMonitor.lock(); + + const auto REPORTSIZE = m_vRealSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto PMONITOR = m_pMonitor.lock(); + + if (*PXWLFORCESCALEZERO && PMONITOR) + return REPORTSIZE * PMONITOR->scale; + + return REPORTSIZE; +} + +Vector2D CWindow::realToReportPosition() { + if (!m_bIsX11) + return m_vRealPosition->goal(); + + return g_pXWaylandManager->waylandToXWaylandCoords(m_vRealPosition->goal()); +} + +Vector2D CWindow::xwaylandSizeToReal(Vector2D size) { + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + + const auto PMONITOR = m_pMonitor.lock(); + const auto SIZE = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto SCALE = *PXWLFORCESCALEZERO ? PMONITOR->scale : 1.0f; + + return SIZE / SCALE; +} + +Vector2D CWindow::xwaylandPositionToReal(Vector2D pos) { + return g_pXWaylandManager->xwaylandToWaylandCoords(pos); +} + +void CWindow::updateX11SurfaceScale() { + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + + m_fX11SurfaceScaledBy = 1.0f; + if (m_bIsX11 && *PXWLFORCESCALEZERO) { + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) + m_fX11SurfaceScaledBy = PMONITOR->scale; + } +} + +void CWindow::sendWindowSize(bool force) { + const auto PMONITOR = m_pMonitor.lock(); Debug::log(TRACE, "sendWindowSize: window:{:x},title:{} with real pos {}, real size {} (force: {})", (uintptr_t)this, this->m_szTitle, m_vRealPosition->goal(), m_vRealSize->goal(), force); // TODO: this should be decoupled from setWindowSize IMO - Vector2D windowPos = m_vRealPosition->goal(); - Vector2D size = m_vRealSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto REPORTPOS = realToReportPosition(); - if (m_bIsX11 && PMONITOR) { - windowPos = g_pXWaylandManager->waylandToXWaylandCoords(windowPos); - if (*PXWLFORCESCALEZERO) - size *= PMONITOR->scale; - } + const auto REPORTSIZE = realToReportSize(); - if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11)) + if (!force && m_vPendingReportedSize == REPORTSIZE && (m_vReportedPosition == REPORTPOS || !m_bIsX11)) return; - m_vReportedPosition = windowPos; - m_vPendingReportedSize = size; - m_fX11SurfaceScaledBy = 1.0f; - - if (*PXWLFORCESCALEZERO && m_bIsX11 && PMONITOR) - m_fX11SurfaceScaledBy = PMONITOR->scale; + m_vReportedPosition = REPORTPOS; + m_vPendingReportedSize = REPORTSIZE; + updateX11SurfaceScale(); if (m_bIsX11 && m_pXWaylandSurface) - m_pXWaylandSurface->configure({windowPos, size}); + m_pXWaylandSurface->configure({REPORTPOS, REPORTSIZE}); else if (m_pXDGSurface && m_pXDGSurface->toplevel) - m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(size), size.floor()); + m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(REPORTSIZE), REPORTPOS.floor()); } NContentType::eContentType CWindow::getContentType() { diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 171a15f4..bc32bab4 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -460,7 +460,7 @@ class CWindow { void onFocusAnimUpdate(); void onUpdateState(); void onUpdateMeta(); - void onX11Configure(CBox box); + void onX11ConfigureRequest(CBox box); void onResourceChangeX11(); std::string fetchTitle(); std::string fetchClass(); @@ -471,6 +471,11 @@ class CWindow { bool isModal(); Vector2D requestedMinSize(); Vector2D requestedMaxSize(); + Vector2D realToReportSize(); + Vector2D realToReportPosition(); + Vector2D xwaylandSizeToReal(Vector2D size); + Vector2D xwaylandPositionToReal(Vector2D size); + void updateX11SurfaceScale(); void sendWindowSize(bool force = false); NContentType::eContentType getContentType(); void setContentType(NContentType::eContentType contentType); @@ -497,7 +502,7 @@ class CWindow { CHyprSignalListener commit; CHyprSignalListener destroy; CHyprSignalListener activate; - CHyprSignalListener configure; + CHyprSignalListener configureRequest; CHyprSignalListener setGeometry; CHyprSignalListener updateState; CHyprSignalListener updateMetadata; diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 7584354e..55e96078 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -50,7 +50,7 @@ class CXWaylandSurface { CSignal resourceChange; // associated / dissociated CSignal setGeometry; - CSignal configure; // CBox + CSignal configureRequest; // CBox CSignal map; CSignal unmap; @@ -116,4 +116,4 @@ class CXWaylandSurface { } listeners; friend class CXWM; -}; \ No newline at end of file +}; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index f2a9b794..a4e3289b 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -59,7 +59,7 @@ void CXWM::handleDestroy(xcb_destroy_notify_event_t* e) { std::erase_if(surfaces, [XSURF](const auto& other) { return XSURF == other; }); } -void CXWM::handleConfigure(xcb_configure_request_event_t* e) { +void CXWM::handleConfigureRequest(xcb_configure_request_event_t* e) { const auto XSURF = windowForXID(e->window); if (!XSURF) @@ -70,8 +70,9 @@ void CXWM::handleConfigure(xcb_configure_request_event_t* e) { if (!(MASK & GEOMETRY)) return; - XSURF->events.configure.emit(CBox{MASK & XCB_CONFIG_WINDOW_X ? e->x : XSURF->geometry.x, MASK & XCB_CONFIG_WINDOW_Y ? e->y : XSURF->geometry.y, - MASK & XCB_CONFIG_WINDOW_WIDTH ? e->width : XSURF->geometry.width, MASK & XCB_CONFIG_WINDOW_HEIGHT ? e->height : XSURF->geometry.height}); + XSURF->events.configureRequest.emit(CBox{MASK & XCB_CONFIG_WINDOW_X ? e->x : XSURF->geometry.x, MASK & XCB_CONFIG_WINDOW_Y ? e->y : XSURF->geometry.y, + MASK & XCB_CONFIG_WINDOW_WIDTH ? e->width : XSURF->geometry.width, + MASK & XCB_CONFIG_WINDOW_HEIGHT ? e->height : XSURF->geometry.height}); } void CXWM::handleConfigureNotify(xcb_configure_notify_event_t* e) { @@ -758,7 +759,7 @@ int CXWM::onEvent(int fd, uint32_t mask) { switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { case XCB_CREATE_NOTIFY: handleCreate((xcb_create_notify_event_t*)event); break; case XCB_DESTROY_NOTIFY: handleDestroy((xcb_destroy_notify_event_t*)event); break; - case XCB_CONFIGURE_REQUEST: handleConfigure((xcb_configure_request_event_t*)event); break; + case XCB_CONFIGURE_REQUEST: handleConfigureRequest((xcb_configure_request_event_t*)event); break; case XCB_CONFIGURE_NOTIFY: handleConfigureNotify((xcb_configure_notify_event_t*)event); break; case XCB_MAP_REQUEST: handleMapRequest((xcb_map_request_event_t*)event); break; case XCB_MAP_NOTIFY: handleMapNotify((xcb_map_notify_event_t*)event); break; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index f6dcee54..4326c77b 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -148,7 +148,7 @@ class CXWM { // event handlers void handleCreate(xcb_create_notify_event_t* e); void handleDestroy(xcb_destroy_notify_event_t* e); - void handleConfigure(xcb_configure_request_event_t* e); + void handleConfigureRequest(xcb_configure_request_event_t* e); void handleConfigureNotify(xcb_configure_notify_event_t* e); void handleMapRequest(xcb_map_request_event_t* e); void handleMapNotify(xcb_map_notify_event_t* e);