xwayland: support HiDPI scale

This supports the xorg-xwayland patch at https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733

Ported from 5a7c65cab1
This commit is contained in:
MoetaYuko 2024-06-11 16:54:34 +08:00 committed by Moeta Yuko
parent 8237d7e1a4
commit 5f12989a85
4 changed files with 48 additions and 8 deletions

View file

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

View file

@ -36,7 +36,8 @@ void CXWM::handleCreate(xcb_create_notify_event_t* e) {
if (isWMWindow(e->window))
return;
const auto XSURF = surfaces.emplace_back(SP<CXWaylandSurface>(new CXWaylandSurface(e->window, CBox{e->x, e->y, e->width, e->height}, e->override_redirect)));
const auto XSURF = surfaces.emplace_back(
SP<CXWaylandSurface>(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);
@ -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<CXWaylandSurface> 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<CXWaylandSurface> 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;

View file

@ -122,12 +122,16 @@ class CXWM {
std::string getAtomName(uint32_t atom);
void readProp(SP<CXWaylandSurface> 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;

View file

@ -126,4 +126,5 @@ inline std::unordered_map<std::string, uint32_t> HYPRATOMS = {
HYPRATOM("DELETE"),
HYPRATOM("TEXT"),
HYPRATOM("INCR"),
HYPRATOM("_XWAYLAND_GLOBAL_OUTPUT_SCALE"),
};