xwayland: configure on a configure request and cleanup geometry conversion (#9375)

* xwayland: configure the window on a configure request

* xwayland: move coordinate conversion handling to their own functions

* xwayland: rename configure to configureRequest
This commit is contained in:
Maximilian Seidler
2025-02-16 00:20:42 +00:00
committed by GitHub
parent 94a30889a7
commit 897ee276dc
5 changed files with 91 additions and 53 deletions

View File

@@ -95,15 +95,15 @@ CWindow::CWindow(SP<CXDGSurfaceResource> resource) : m_pXDGSurface(resource) {
CWindow::CWindow(SP<CXWaylandSurface> 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<CBox>(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<CBox>(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<Hyprlang::INT>("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<double>::infinity(), std::numeric_limits<double>::infinity()});
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
const auto PMONITOR = m_pMonitor.lock();
const auto REPORTSIZE = m_vRealSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::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<Hyprlang::INT>("xwayland:force_zero_scaling");
const auto PMONITOR = m_pMonitor.lock();
const auto SIZE = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::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<Hyprlang::INT>("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<double>::infinity(), std::numeric_limits<double>::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() {

View File

@@ -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;

View File

@@ -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;
};
};

View File

@@ -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;

View File

@@ -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);