From 5f12989a852b7786017a86766fa58bbec6bf2dda Mon Sep 17 00:00:00 2001 From: MoetaYuko Date: Tue, 11 Jun 2024 16:54:34 +0800 Subject: [PATCH] xwayland: support HiDPI scale This supports the xorg-xwayland patch at https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733 Ported from https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/5a7c65cab11c9f3c3dc79f9c4cfb8a6acf6cbaae --- src/xwayland/XSurface.cpp | 3 ++- src/xwayland/XWM.cpp | 48 +++++++++++++++++++++++++++++++++------ src/xwayland/XWM.hpp | 4 ++++ src/xwayland/XWayland.hpp | 1 + 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 02fe2b3b2b7..f42a31dd24c 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -167,7 +167,8 @@ void CXWaylandSurface::configure(const CBox& box) { geometry = box; uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_BORDER_WIDTH; - uint32_t values[] = {box.x, box.y, box.width, box.height, 0}; + uint32_t values[] = {g_pXWayland->pWM->applyScale(box.x), g_pXWayland->pWM->applyScale(box.y), g_pXWayland->pWM->applyScale(box.width), + g_pXWayland->pWM->applyScale(box.height), 0}; xcb_configure_window(g_pXWayland->pWM->connection, xID, mask, values); g_pXWayland->pWM->updateClientList(); diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index e8e2258a119..9d8806b8d29 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -36,8 +36,9 @@ void CXWM::handleCreate(xcb_create_notify_event_t* e) { if (isWMWindow(e->window)) return; - const auto XSURF = surfaces.emplace_back(SP(new CXWaylandSurface(e->window, CBox{e->x, e->y, e->width, e->height}, e->override_redirect))); - XSURF->self = XSURF; + const auto XSURF = surfaces.emplace_back( + SP(new CXWaylandSurface(e->window, CBox{applyUnScale(e->x), applyUnScale(e->y), applyUnScale(e->width), applyUnScale(e->height)}, e->override_redirect))); + XSURF->self = XSURF; Debug::log(LOG, "[xwm] New XSurface at {:x} with xid of {}", (uintptr_t)XSURF.get(), e->window); const auto WINDOW = CWindow::create(XSURF); @@ -67,8 +68,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.configure.emit(CBox{MASK & XCB_CONFIG_WINDOW_X ? applyUnScale(e->x) : XSURF->geometry.x, MASK & XCB_CONFIG_WINDOW_Y ? applyUnScale(e->y) : XSURF->geometry.y, + MASK & XCB_CONFIG_WINDOW_WIDTH ? applyUnScale(e->width) : XSURF->geometry.width, + MASK & XCB_CONFIG_WINDOW_HEIGHT ? applyUnScale(e->height) : XSURF->geometry.height}); } void CXWM::handleConfigureNotify(xcb_configure_notify_event_t* e) { @@ -77,10 +79,11 @@ void CXWM::handleConfigureNotify(xcb_configure_notify_event_t* e) { if (!XSURF) return; - if (XSURF->geometry == CBox{e->x, e->y, e->width, e->height}) + const CBox geom = {applyUnScale(e->x), applyUnScale(e->y), applyUnScale(e->width), applyUnScale(e->height)}; + if (XSURF->geometry == geom) return; - XSURF->geometry = {e->x, e->y, e->width, e->height}; + XSURF->geometry = geom; updateOverrideRedirect(XSURF, e->override_redirect); XSURF->events.setGeometry.emit(); } @@ -250,6 +253,17 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ xcb_icccm_get_wm_size_hints_from_reply(XSURF->sizeHints.get(), reply); + XSURF->sizeHints->x = applyUnScale(XSURF->sizeHints->x); + XSURF->sizeHints->y = applyUnScale(XSURF->sizeHints->y); + XSURF->sizeHints->width = applyUnScale(XSURF->sizeHints->width); + XSURF->sizeHints->height = applyUnScale(XSURF->sizeHints->height); + XSURF->sizeHints->min_width = applyUnScale(XSURF->sizeHints->min_width); + XSURF->sizeHints->min_height = applyUnScale(XSURF->sizeHints->min_height); + XSURF->sizeHints->max_width = applyUnScale(XSURF->sizeHints->max_width); + XSURF->sizeHints->max_height = applyUnScale(XSURF->sizeHints->max_height); + XSURF->sizeHints->base_width = applyUnScale(XSURF->sizeHints->base_width); + XSURF->sizeHints->base_height = applyUnScale(XSURF->sizeHints->base_height); + const int32_t FLAGS = XSURF->sizeHints->flags; const bool HASMIN = (FLAGS & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE); const bool HASBASE = (FLAGS & XCB_ICCCM_SIZE_HINT_BASE_SIZE); @@ -283,8 +297,20 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ void CXWM::handlePropertyNotify(xcb_property_notify_event_t* e) { const auto XSURF = windowForXID(e->window); - if (!XSURF) + if (!XSURF) { + if (e->atom == HYPRATOMS["_XWAYLAND_GLOBAL_OUTPUT_SCALE"]) { + xcb_get_property_cookie_t cookie = xcb_get_property(connection, 0, e->window, e->atom, XCB_ATOM_ANY, 0, 2048); + xcb_get_property_reply_t* reply = xcb_get_property_reply(connection, cookie, nullptr); + if (!reply) { + return; + } + if (reply->type == XCB_ATOM_CARDINAL) { + scale = *(uint32_t*)xcb_get_property_value(reply); + } + free(reply); + } return; + } xcb_get_property_cookie_t cookie = xcb_get_property(connection, 0, XSURF->xID, e->atom, XCB_ATOM_ANY, 0, 2048); xcb_get_property_reply_t* reply = xcb_get_property_reply(connection, cookie, nullptr); @@ -1169,6 +1195,14 @@ void CXWM::setCursor(unsigned char* pixData, uint32_t stride, const Vector2D& si xcb_flush(connection); } +double CXWM::applyScale(double val) { + return std::floor(val * scale); +} + +double CXWM::applyUnScale(double val) { + return std::ceil(val / scale); +} + void SXSelection::onSelection() { if (g_pSeatManager->selection.currentSelection && g_pSeatManager->selection.currentSelection->type() == DATA_SOURCE_TYPE_X11) return; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 5969572077e..6cc7c516369 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -122,12 +122,16 @@ class CXWM { std::string getAtomName(uint32_t atom); void readProp(SP XSURF, uint32_t atom, xcb_get_property_reply_t* reply); + double applyScale(double val); + double applyUnScale(double val); + // xcb_connection_t* connection = nullptr; xcb_errors_context_t* errors = nullptr; xcb_screen_t* screen = nullptr; xcb_window_t wmWindow; + double scale = 1.0; wl_event_source* eventSource = nullptr; diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index 96253d193c0..43f34d555b1 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -126,4 +126,5 @@ inline std::unordered_map HYPRATOMS = { HYPRATOM("DELETE"), HYPRATOM("TEXT"), HYPRATOM("INCR"), + HYPRATOM("_XWAYLAND_GLOBAL_OUTPUT_SCALE"), };