diff --git a/src/seat/helper.cpp b/src/seat/helper.cpp index 9a98da794..99dbb678b 100644 --- a/src/seat/helper.cpp +++ b/src/seat/helper.cpp @@ -134,38 +134,6 @@ #define WLR_FRACTIONAL_SCALE_V1_VERSION 1 #define DEFAULT_SEAT_NAME "seat0" -static QByteArray readWindowProperty(xcb_connection_t *connection, - xcb_window_t win, - xcb_atom_t atom, - xcb_atom_t type) -{ - QByteArray data; - int offset = 0; - int remaining = 0; - - do { - xcb_get_property_cookie_t cookie = - xcb_get_property(connection, false, win, atom, type, offset, 1024); - xcb_get_property_reply_t *reply = xcb_get_property_reply(connection, cookie, NULL); - if (!reply) - break; - - remaining = 0; - - if (reply->type == type) { - int len = xcb_get_property_value_length(reply); - char *datas = (char *)xcb_get_property_value(reply); - data.append(datas, len); - remaining = reply->bytes_after; - offset += len; - } - - free(reply); - } while (remaining > 0); - - return data; -} - static bool hasSavedOutputState(OutputConfig *config) { return config && (!config->widthIsDefaultValue() @@ -1744,34 +1712,15 @@ void Helper::onSurfaceWrapperAdded(SurfaceWrapper *wrapper) auto xwaylandSurface = qobject_cast(wrapper->shellSurface()); auto updateDecorationTitleBar = [wrapper, xwaylandSurface, sessionManager = m_sessionManager]() { auto *xwayland = xwaylandSurface->xwayland(); - xcb_connection_t *connection = xwayland ? xwayland->xcbConnection() : nullptr; - xcb_atom_t atom; - if (xwayland) { - if (auto session = sessionManager->sessionForXWayland(xwayland)) - atom = session->noTitlebarAtom(); - else - atom = XCB_ATOM_NONE; - } else { - atom = XCB_ATOM_NONE; - } - if (!xwaylandSurface->isBypassManager()) { - if (atom && connection - && !readWindowProperty(connection, - xwaylandSurface->handle()->window_id, - atom, - XCB_ATOM_CARDINAL) - .isEmpty()) { - wrapper->setNoTitleBar(true); - } else { - wrapper->setNoTitleBar(xwaylandSurface->decorationsFlags() - & WXWaylandSurface::DecorationsNoTitle); - } - wrapper->setNoDecoration(xwaylandSurface->decorationsFlags() - & WXWaylandSurface::DecorationsNoBorder); - } else { - wrapper->setNoTitleBar(true); - wrapper->setNoDecoration(true); - } + const auto session = xwayland + ? sessionManager->sessionForXWayland(xwayland) + : std::shared_ptr(); + xcb_atom_t noTitlebarAtom = XCB_ATOM_NONE; + if (session) + noTitlebarAtom = session->noTitlebarAtom(); + const auto flags = xwaylandSurface->effectiveDecorationsFlags(noTitlebarAtom); + wrapper->setNoTitleBar(flags & WXWaylandSurface::DecorationsNoTitle); + wrapper->setNoDecoration(flags & WXWaylandSurface::DecorationsNoBorder); }; // When x11 surface dissociate, SurfaceWrapper will be destroyed immediately // but WXWaylandSurface will not, so must connect to `wrapper` diff --git a/waylib/src/server/protocols/wxwayland.cpp b/waylib/src/server/protocols/wxwayland.cpp index 2c1860c9f..bdf6afde3 100644 --- a/waylib/src/server/protocols/wxwayland.cpp +++ b/waylib/src/server/protocols/wxwayland.cpp @@ -589,6 +589,39 @@ wl_global *WXWayland::global() const return nullptr; } +QByteArray WXWayland::windowProperty(xcb_window_t window, + xcb_atom_t atom, + xcb_atom_t type) const +{ + auto *connection = xcbConnection(); + if (!connection || atom == XCB_ATOM_NONE) + return {}; + + QByteArray data; + uint32_t offset = 0; + uint32_t remaining = 0; + + do { + const auto cookie = + xcb_get_property(connection, false, window, atom, type, offset, 1024); + auto *reply = xcb_get_property_reply(connection, cookie, nullptr); + if (!reply) + break; + + remaining = 0; + if (reply->type == type) { + const int length = xcb_get_property_value_length(reply); + data.append(static_cast(xcb_get_property_value(reply)), length); + remaining = reply->bytes_after; + offset += length; + } + + free(reply); + } while (remaining > 0); + + return data; +} + void WXWayland::readAsyncProperties( xcb_window_t windowId, const QVector &requests, diff --git a/waylib/src/server/protocols/wxwayland.h b/waylib/src/server/protocols/wxwayland.h index ccb454cdc..7f24d528f 100644 --- a/waylib/src/server/protocols/wxwayland.h +++ b/waylib/src/server/protocols/wxwayland.h @@ -83,6 +83,9 @@ class WAYLIB_SERVER_EXPORT WXWayland : public QObject, public WWaylandResource, xcb_connection_t *xcbConnection() const; xcb_screen_t *xcbScreen() const; + QByteArray windowProperty(xcb_window_t window, + xcb_atom_t atom, + xcb_atom_t type) const; QVector surfaceList() const; diff --git a/waylib/src/server/protocols/wxwaylandsurface.cpp b/waylib/src/server/protocols/wxwaylandsurface.cpp index 233b7b2a1..877b99dbb 100644 --- a/waylib/src/server/protocols/wxwaylandsurface.cpp +++ b/waylib/src/server/protocols/wxwaylandsurface.cpp @@ -537,6 +537,24 @@ WXWaylandSurface::DecorationsFlags WXWaylandSurface::decorationsFlags() const return WXWaylandSurface::DecorationsFlags::fromInt(d->handle()->decorations); } +WXWaylandSurface::DecorationsFlags +WXWaylandSurface::effectiveDecorationsFlags(xcb_atom_t noTitlebarAtom) const +{ + if (isBypassManager()) + return DecorationsFlags(DecorationsNoBorder) | DecorationsNoTitle; + + auto flags = decorationsFlags(); + if (noTitlebarAtom != XCB_ATOM_NONE + && !xwayland()->windowProperty(handle()->window_id, + noTitlebarAtom, + XCB_ATOM_CARDINAL) + .isEmpty()) { + flags |= DecorationsNoTitle; + } + + return flags; +} + bool WXWaylandSurface::checkNewSize(const QSize &size, QSize *clipedSize) { const QSize minSize = this->minSize(); diff --git a/waylib/src/server/protocols/wxwaylandsurface.h b/waylib/src/server/protocols/wxwaylandsurface.h index 677d09cdf..e0cd61215 100644 --- a/waylib/src/server/protocols/wxwaylandsurface.h +++ b/waylib/src/server/protocols/wxwaylandsurface.h @@ -7,6 +7,8 @@ #include #include +#include + WAYLIB_SERVER_BEGIN_NAMESPACE class WXWayland; @@ -116,6 +118,7 @@ class WAYLIB_SERVER_EXPORT WXWaylandSurface : public WToplevelSurface bool isModal() const; WindowTypes windowTypes() const; DecorationsFlags decorationsFlags() const; + DecorationsFlags effectiveDecorationsFlags(xcb_atom_t noTitlebarAtom = XCB_ATOM_NONE) const; public Q_SLOTS: bool checkNewSize(const QSize &size, QSize *clipedSize = nullptr) override;