diff --git a/changelog/next.md b/changelog/next.md index fc6d79e..a8981b9 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -27,8 +27,6 @@ set shell id. - Added a way to detect if an icon is from the system icon theme or not. - Added vulkan support to screencopy. - Added generic WindowManager interface implementing ext-workspace. -- Added ext-background-effect window blur support. -- Added per-corner radius support to Region. ## Other Changes @@ -40,7 +38,6 @@ set shell id. - Added `QS_DISABLE_FILE_WATCHER` environment variable to disable file watching. - Added `QS_DISABLE_CRASH_HANDLER` environment variable to disable crash handling. - Added `QS_CRASHREPORT_URL` environment variable to allow overriding the crash reporter link. -- Added `AppId` pragma and `QS_APP_ID` environment variable to allow overriding the desktop application ID. ## Bug Fixes diff --git a/src/core/instanceinfo.cpp b/src/core/instanceinfo.cpp index b9b7b44..1f71b8a 100644 --- a/src/core/instanceinfo.cpp +++ b/src/core/instanceinfo.cpp @@ -3,14 +3,14 @@ #include QDataStream& operator<<(QDataStream& stream, const InstanceInfo& info) { - stream << info.instanceId << info.configPath << info.shellId << info.appId << info.launchTime - << info.pid << info.display; + stream << info.instanceId << info.configPath << info.shellId << info.launchTime << info.pid + << info.display; return stream; } QDataStream& operator>>(QDataStream& stream, InstanceInfo& info) { - stream >> info.instanceId >> info.configPath >> info.shellId >> info.appId >> info.launchTime - >> info.pid >> info.display; + stream >> info.instanceId >> info.configPath >> info.shellId >> info.launchTime >> info.pid + >> info.display; return stream; } diff --git a/src/core/instanceinfo.hpp b/src/core/instanceinfo.hpp index a4a7e66..977e4c2 100644 --- a/src/core/instanceinfo.hpp +++ b/src/core/instanceinfo.hpp @@ -9,7 +9,6 @@ struct InstanceInfo { QString instanceId; QString configPath; QString shellId; - QString appId; QDateTime launchTime; pid_t pid = -1; QString display; diff --git a/src/core/logging.cpp b/src/core/logging.cpp index 415cf61..893c56e 100644 --- a/src/core/logging.cpp +++ b/src/core/logging.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -221,7 +220,6 @@ void LogManager::messageHandler( } if (display) { - auto locker = QMutexLocker(&self->stdoutMutex); LogMessage::formatMessage( self->stdoutStream, message, diff --git a/src/core/logging.hpp b/src/core/logging.hpp index 7b6a758..bf81133 100644 --- a/src/core/logging.hpp +++ b/src/core/logging.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -136,7 +135,6 @@ private: QHash allFilters; QTextStream stdoutStream; - QMutex stdoutMutex; LoggingThreadProxy threadProxy; friend void initLogCategoryLevel(const char* name, QtMsgType defaultLevel); diff --git a/src/core/region.cpp b/src/core/region.cpp index 82cc2e7..11892d6 100644 --- a/src/core/region.cpp +++ b/src/core/region.cpp @@ -1,5 +1,4 @@ #include "region.hpp" -#include #include #include @@ -19,11 +18,6 @@ PendingRegion::PendingRegion(QObject* parent): QObject(parent) { QObject::connect(this, &PendingRegion::yChanged, this, &PendingRegion::changed); QObject::connect(this, &PendingRegion::widthChanged, this, &PendingRegion::changed); QObject::connect(this, &PendingRegion::heightChanged, this, &PendingRegion::changed); - QObject::connect(this, &PendingRegion::radiusChanged, this, &PendingRegion::changed); - QObject::connect(this, &PendingRegion::topLeftRadiusChanged, this, &PendingRegion::changed); - QObject::connect(this, &PendingRegion::topRightRadiusChanged, this, &PendingRegion::changed); - QObject::connect(this, &PendingRegion::bottomLeftRadiusChanged, this, &PendingRegion::changed); - QObject::connect(this, &PendingRegion::bottomRightRadiusChanged, this, &PendingRegion::changed); QObject::connect(this, &PendingRegion::childrenChanged, this, &PendingRegion::changed); } @@ -51,79 +45,6 @@ void PendingRegion::onItemDestroyed() { this->mItem = nullptr; } void PendingRegion::onChildDestroyed() { this->mRegions.removeAll(this->sender()); } -qint32 PendingRegion::radius() const { return this->mRadius; } - -void PendingRegion::setRadius(qint32 radius) { - if (radius == this->mRadius) return; - this->mRadius = radius; - emit this->radiusChanged(); - - if (!(this->mCornerOverrides & TopLeft)) emit this->topLeftRadiusChanged(); - if (!(this->mCornerOverrides & TopRight)) emit this->topRightRadiusChanged(); - if (!(this->mCornerOverrides & BottomLeft)) emit this->bottomLeftRadiusChanged(); - if (!(this->mCornerOverrides & BottomRight)) emit this->bottomRightRadiusChanged(); -} - -qint32 PendingRegion::topLeftRadius() const { - return (this->mCornerOverrides & TopLeft) ? this->mTopLeftRadius : this->mRadius; -} - -void PendingRegion::setTopLeftRadius(qint32 radius) { - this->mTopLeftRadius = radius; - this->mCornerOverrides |= TopLeft; - emit this->topLeftRadiusChanged(); -} - -void PendingRegion::resetTopLeftRadius() { - this->mCornerOverrides &= ~TopLeft; - emit this->topLeftRadiusChanged(); -} - -qint32 PendingRegion::topRightRadius() const { - return (this->mCornerOverrides & TopRight) ? this->mTopRightRadius : this->mRadius; -} - -void PendingRegion::setTopRightRadius(qint32 radius) { - this->mTopRightRadius = radius; - this->mCornerOverrides |= TopRight; - emit this->topRightRadiusChanged(); -} - -void PendingRegion::resetTopRightRadius() { - this->mCornerOverrides &= ~TopRight; - emit this->topRightRadiusChanged(); -} - -qint32 PendingRegion::bottomLeftRadius() const { - return (this->mCornerOverrides & BottomLeft) ? this->mBottomLeftRadius : this->mRadius; -} - -void PendingRegion::setBottomLeftRadius(qint32 radius) { - this->mBottomLeftRadius = radius; - this->mCornerOverrides |= BottomLeft; - emit this->bottomLeftRadiusChanged(); -} - -void PendingRegion::resetBottomLeftRadius() { - this->mCornerOverrides &= ~BottomLeft; - emit this->bottomLeftRadiusChanged(); -} - -qint32 PendingRegion::bottomRightRadius() const { - return (this->mCornerOverrides & BottomRight) ? this->mBottomRightRadius : this->mRadius; -} - -void PendingRegion::setBottomRightRadius(qint32 radius) { - this->mBottomRightRadius = radius; - this->mCornerOverrides |= BottomRight; - emit this->bottomRightRadiusChanged(); -} - -void PendingRegion::resetBottomRightRadius() { - this->mCornerOverrides &= ~BottomRight; - emit this->bottomRightRadiusChanged(); -} - QQmlListProperty PendingRegion::regions() { return QQmlListProperty( this, @@ -169,60 +90,6 @@ QRegion PendingRegion::build() const { region = QRegion(this->mX, this->mY, this->mWidth, this->mHeight, type); } - if (this->mShape == RegionShape::Rect && !region.isEmpty()) { - auto tl = std::max(this->topLeftRadius(), 0); - auto tr = std::max(this->topRightRadius(), 0); - auto bl = std::max(this->bottomLeftRadius(), 0); - auto br = std::max(this->bottomRightRadius(), 0); - - if (tl > 0 || tr > 0 || bl > 0 || br > 0) { - auto rect = region.boundingRect(); - auto x = rect.x(); - auto y = rect.y(); - auto w = rect.width(); - auto h = rect.height(); - - // Normalize so adjacent corners don't exceed their shared edge. - // Each corner is scaled by the tightest constraint of its two edges. - auto topScale = tl + tr > w ? static_cast(w) / (tl + tr) : 1.0; - auto bottomScale = bl + br > w ? static_cast(w) / (bl + br) : 1.0; - auto leftScale = tl + bl > h ? static_cast(h) / (tl + bl) : 1.0; - auto rightScale = tr + br > h ? static_cast(h) / (tr + br) : 1.0; - - tl = static_cast(tl * std::min(topScale, leftScale)); - tr = static_cast(tr * std::min(topScale, rightScale)); - bl = static_cast(bl * std::min(bottomScale, leftScale)); - br = static_cast(br * std::min(bottomScale, rightScale)); - - // Unlock each corner: subtract (cornerBox - quarterEllipse) from the - // full rect. Each corner only modifies pixels inside its own box, - // so no diagonal overlap is possible. - if (tl > 0) { - auto box = QRegion(x, y, tl, tl); - auto ellipse = QRegion(x, y, tl * 2, tl * 2, QRegion::Ellipse); - region -= box - (ellipse & box); - } - - if (tr > 0) { - auto box = QRegion(x + w - tr, y, tr, tr); - auto ellipse = QRegion(x + w - tr * 2, y, tr * 2, tr * 2, QRegion::Ellipse); - region -= box - (ellipse & box); - } - - if (bl > 0) { - auto box = QRegion(x, y + h - bl, bl, bl); - auto ellipse = QRegion(x, y + h - bl * 2, bl * 2, bl * 2, QRegion::Ellipse); - region -= box - (ellipse & box); - } - - if (br > 0) { - auto box = QRegion(x + w - br, y + h - br, br, br); - auto ellipse = QRegion(x + w - br * 2, y + h - br * 2, br * 2, br * 2, QRegion::Ellipse); - region -= box - (ellipse & box); - } - } - } - for (const auto& childRegion: this->mRegions) { region = childRegion->applyTo(region); } diff --git a/src/core/region.hpp b/src/core/region.hpp index dfd1566..6637d7b 100644 --- a/src/core/region.hpp +++ b/src/core/region.hpp @@ -66,29 +66,6 @@ class PendingRegion: public QObject { Q_PROPERTY(qint32 width MEMBER mWidth NOTIFY widthChanged); /// Defaults to 0. Does nothing if @@item is set. Q_PROPERTY(qint32 height MEMBER mHeight NOTIFY heightChanged); - // clang-format off - /// Corner radius for rounded rectangles. Only applies when @@shape is `Rect`. Defaults to 0. - /// - /// Acts as the default for @@topLeftRadius, @@topRightRadius, @@bottomLeftRadius, - /// and @@bottomRightRadius. - Q_PROPERTY(qint32 radius READ radius WRITE setRadius NOTIFY radiusChanged); - /// Top-left corner radius. Only applies when @@shape is `Rect`. - /// - /// Defaults to @@radius, and may be reset by assigning `undefined`. - Q_PROPERTY(qint32 topLeftRadius READ topLeftRadius WRITE setTopLeftRadius RESET resetTopLeftRadius NOTIFY topLeftRadiusChanged); - /// Top-right corner radius. Only applies when @@shape is `Rect`. - /// - /// Defaults to @@radius, and may be reset by assigning `undefined`. - Q_PROPERTY(qint32 topRightRadius READ topRightRadius WRITE setTopRightRadius RESET resetTopRightRadius NOTIFY topRightRadiusChanged); - /// Bottom-left corner radius. Only applies when @@shape is `Rect`. - /// - /// Defaults to @@radius, and may be reset by assigning `undefined`. - Q_PROPERTY(qint32 bottomLeftRadius READ bottomLeftRadius WRITE setBottomLeftRadius RESET resetBottomLeftRadius NOTIFY bottomLeftRadiusChanged); - /// Bottom-right corner radius. Only applies when @@shape is `Rect`. - /// - /// Defaults to @@radius, and may be reset by assigning `undefined`. - Q_PROPERTY(qint32 bottomRightRadius READ bottomRightRadius WRITE setBottomRightRadius RESET resetBottomRightRadius NOTIFY bottomRightRadiusChanged); - // clang-format on /// Regions to apply on top of this region. /// @@ -114,25 +91,6 @@ public: void setItem(QQuickItem* item); - [[nodiscard]] qint32 radius() const; - void setRadius(qint32 radius); - - [[nodiscard]] qint32 topLeftRadius() const; - void setTopLeftRadius(qint32 radius); - void resetTopLeftRadius(); - - [[nodiscard]] qint32 topRightRadius() const; - void setTopRightRadius(qint32 radius); - void resetTopRightRadius(); - - [[nodiscard]] qint32 bottomLeftRadius() const; - void setBottomLeftRadius(qint32 radius); - void resetBottomLeftRadius(); - - [[nodiscard]] qint32 bottomRightRadius() const; - void setBottomRightRadius(qint32 radius); - void resetBottomRightRadius(); - QQmlListProperty regions(); [[nodiscard]] bool empty() const; @@ -151,11 +109,6 @@ signals: void yChanged(); void widthChanged(); void heightChanged(); - void radiusChanged(); - void topLeftRadiusChanged(); - void topRightRadiusChanged(); - void bottomLeftRadiusChanged(); - void bottomRightRadiusChanged(); void childrenChanged(); /// Triggered when the region's geometry changes. @@ -177,25 +130,12 @@ private: static void regionsReplace(QQmlListProperty* prop, qsizetype i, PendingRegion* region); - enum CornerOverride : quint8 { - TopLeft = 0b1, - TopRight = 0b10, - BottomLeft = 0b100, - BottomRight = 0b1000, - }; - QQuickItem* mItem = nullptr; qint32 mX = 0; qint32 mY = 0; qint32 mWidth = 0; qint32 mHeight = 0; - qint32 mRadius = 0; - qint32 mTopLeftRadius = 0; - qint32 mTopRightRadius = 0; - qint32 mBottomLeftRadius = 0; - qint32 mBottomRightRadius = 0; - quint8 mCornerOverrides = 0; QList mRegions; }; diff --git a/src/crash/main.cpp b/src/crash/main.cpp index 30cf94d..05927f2 100644 --- a/src/crash/main.cpp +++ b/src/crash/main.cpp @@ -230,9 +230,7 @@ void qsCheckCrash(int argc, char** argv) { ); auto app = QApplication(argc, argv); - auto desktopId = - info.instance.appId.isEmpty() ? QStringLiteral("org.quickshell") : info.instance.appId; - QApplication::setDesktopFileName(desktopId); + QApplication::setDesktopFileName("org.quickshell"); auto crashDir = QsPaths::crashDir(info.instance.instanceId); diff --git a/src/launch/launch.cpp b/src/launch/launch.cpp index 0f5b090..3a9a2a5 100644 --- a/src/launch/launch.cpp +++ b/src/launch/launch.cpp @@ -76,7 +76,6 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio bool useSystemStyle = false; QString iconTheme = qEnvironmentVariable("QS_ICON_THEME"); QHash envOverrides; - QString appId = qEnvironmentVariable("QS_APP_ID"); QString dataDir; QString stateDir; QString cacheDir; @@ -105,8 +104,6 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio auto var = envPragma.sliced(0, splitIdx).trimmed(); auto val = envPragma.sliced(splitIdx + 1).trimmed(); pragmas.envOverrides.insert(var, val); - } else if (pragma.startsWith("AppId ")) { - pragmas.appId = pragma.sliced(6).trimmed(); } else if (pragma.startsWith("ShellId ")) { shellId = pragma.sliced(8).trimmed(); } else if (pragma.startsWith("DataDir ")) { @@ -131,13 +128,10 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio qInfo() << "Shell ID:" << shellId << "Path ID" << pathId; auto launchTime = qs::Common::LAUNCH_TIME.toSecsSinceEpoch(); - auto appId = pragmas.appId.isEmpty() ? QStringLiteral("org.quickshell") : pragmas.appId; - InstanceInfo::CURRENT = InstanceInfo { .instanceId = base36Encode(getpid()) + base36Encode(launchTime), .configPath = args.configPath, .shellId = shellId, - .appId = appId, .launchTime = qs::Common::LAUNCH_TIME, .pid = getpid(), .display = getDisplayConnection(), @@ -237,7 +231,7 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio app = new QGuiApplication(qArgC, argv); } - QGuiApplication::setDesktopFileName(appId); + QGuiApplication::setDesktopFileName("org.quickshell"); if (args.debugPort != -1) { QQmlDebuggingEnabler::enableDebugging(true); diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index cf84713..4a67558 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -68,7 +68,6 @@ function (wl_proto target name dir) target_include_directories(${target} INTERFACE ${PROTO_BUILD_PATH}) target_link_libraries(${target} wl-proto-${name}-wl Qt6::WaylandClient Qt6::WaylandClientPrivate) qs_pch(${target} SET wayland-protocol) - target_compile_options(wl-proto-${name}-wl PRIVATE ${wayland_CFLAGS}) endfunction() # ----- @@ -120,9 +119,6 @@ if (HYPRLAND) add_subdirectory(hyprland) endif() -add_subdirectory(background_effect) -list(APPEND WAYLAND_MODULES Quickshell.Wayland._BackgroundEffect) - add_subdirectory(idle_inhibit) list(APPEND WAYLAND_MODULES Quickshell.Wayland._IdleInhibitor) diff --git a/src/wayland/background_effect/CMakeLists.txt b/src/wayland/background_effect/CMakeLists.txt deleted file mode 100644 index f45f94d..0000000 --- a/src/wayland/background_effect/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -qt_add_library(quickshell-wayland-background-effect STATIC - manager.cpp - surface.cpp - qml.cpp -) - -qt_add_qml_module(quickshell-wayland-background-effect - URI Quickshell.Wayland._BackgroundEffect - VERSION 0.1 - DEPENDENCIES QtQml -) - -install_qml_module(quickshell-wayland-background-effect) - -wl_proto(wlp-background-effect ext-background-effect-v1 "${WAYLAND_PROTOCOLS}/staging/ext-background-effect") - -target_link_libraries(quickshell-wayland-background-effect PRIVATE - Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client - wlp-background-effect -) - -qs_module_pch(quickshell-wayland-background-effect) - -target_link_libraries(quickshell PRIVATE quickshell-wayland-background-effectplugin) diff --git a/src/wayland/background_effect/manager.cpp b/src/wayland/background_effect/manager.cpp deleted file mode 100644 index 4cb06f1..0000000 --- a/src/wayland/background_effect/manager.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "manager.hpp" -#include - -#include -#include -#include -#include - -#include "surface.hpp" - -namespace qs::wayland::background_effect::impl { - -BackgroundEffectManager::BackgroundEffectManager(): QWaylandClientExtensionTemplate(1) { - this->initialize(); -} - -BackgroundEffectSurface* -BackgroundEffectManager::createEffectSurface(QtWaylandClient::QWaylandWindow* window) { - return new BackgroundEffectSurface(this->get_background_effect(window->surface())); -} - -bool BackgroundEffectManager::blurAvailable() const { - return this->isActive() && this->mBlurAvailable; -} - -void BackgroundEffectManager::ext_background_effect_manager_v1_capabilities(uint32_t flags) { - auto available = static_cast(flags & capability_blur); - if (available == this->mBlurAvailable) return; - this->mBlurAvailable = available; - emit this->blurAvailableChanged(); -} - -BackgroundEffectManager* BackgroundEffectManager::instance() { - static auto* instance = new BackgroundEffectManager(); // NOLINT - return instance->isInitialized() ? instance : nullptr; -} - -} // namespace qs::wayland::background_effect::impl diff --git a/src/wayland/background_effect/manager.hpp b/src/wayland/background_effect/manager.hpp deleted file mode 100644 index 6c2e981..0000000 --- a/src/wayland/background_effect/manager.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "surface.hpp" - -namespace qs::wayland::background_effect::impl { - -class BackgroundEffectManager - : public QWaylandClientExtensionTemplate - , public QtWayland::ext_background_effect_manager_v1 { - Q_OBJECT; - -public: - explicit BackgroundEffectManager(); - - BackgroundEffectSurface* createEffectSurface(QtWaylandClient::QWaylandWindow* window); - - [[nodiscard]] bool blurAvailable() const; - - static BackgroundEffectManager* instance(); - -signals: - void blurAvailableChanged(); - -protected: - void ext_background_effect_manager_v1_capabilities(uint32_t flags) override; - -private: - bool mBlurAvailable = false; -}; - -} // namespace qs::wayland::background_effect::impl diff --git a/src/wayland/background_effect/qml.cpp b/src/wayland/background_effect/qml.cpp deleted file mode 100644 index b54a847..0000000 --- a/src/wayland/background_effect/qml.cpp +++ /dev/null @@ -1,246 +0,0 @@ -#include "qml.hpp" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../core/region.hpp" -#include "../../window/proxywindow.hpp" -#include "../../window/windowinterface.hpp" -#include "manager.hpp" -#include "surface.hpp" - -using QtWaylandClient::QWaylandWindow; - -namespace qs::wayland::background_effect { - -BackgroundEffect* BackgroundEffect::qmlAttachedProperties(QObject* object) { - auto* proxyWindow = qobject_cast(object); - - if (!proxyWindow) { - if (auto* iface = qobject_cast(object)) { - proxyWindow = iface->proxyWindow(); - } - } - - if (!proxyWindow) return nullptr; - return new BackgroundEffect(proxyWindow); -} - -BackgroundEffect::BackgroundEffect(ProxyWindowBase* window): QObject(nullptr), proxyWindow(window) { - QObject::connect( - window, - &ProxyWindowBase::windowConnected, - this, - &BackgroundEffect::onWindowConnected - ); - - QObject::connect(window, &ProxyWindowBase::polished, this, &BackgroundEffect::onWindowPolished); - - QObject::connect( - window, - &ProxyWindowBase::devicePixelRatioChanged, - this, - &BackgroundEffect::updateBlurRegion - ); - - QObject::connect(window, &QObject::destroyed, this, &BackgroundEffect::onProxyWindowDestroyed); - - if (window->backingWindow()) { - this->onWindowConnected(); - } -} - -PendingRegion* BackgroundEffect::blurRegion() const { return this->mBlurRegion; } - -void BackgroundEffect::setBlurRegion(PendingRegion* region) { - if (region == this->mBlurRegion) return; - - if (this->mBlurRegion) { - QObject::disconnect(this->mBlurRegion, nullptr, this, nullptr); - } - - this->mBlurRegion = region; - - if (region) { - QObject::connect(region, &QObject::destroyed, this, &BackgroundEffect::onBlurRegionDestroyed); - QObject::connect(region, &PendingRegion::changed, this, &BackgroundEffect::updateBlurRegion); - } - - this->updateBlurRegion(); - emit this->blurRegionChanged(); -} - -void BackgroundEffect::onBlurRegionDestroyed() { - this->mBlurRegion = nullptr; - this->updateBlurRegion(); - emit this->blurRegionChanged(); -} - -void BackgroundEffect::updateBlurRegion() { - if (!this->surface || !this->proxyWindow) return; - - this->pendingBlurRegion = true; - this->proxyWindow->schedulePolish(); -} - -void BackgroundEffect::onWindowPolished() { - if (!this->surface || !this->pendingBlurRegion) return; - if (!this->mWaylandWindow || !this->mWaylandWindow->surface()) { - this->pendingBlurRegion = false; - return; - } - - QRegion region; - if (this->mBlurRegion) { - region = - this->mBlurRegion->applyTo(QRect(0, 0, this->mWindow->width(), this->mWindow->height())); - - auto scale = QHighDpiScaling::factor(this->mWindow); - if (!qFuzzyCompare(scale, 1.0)) { - region = QHighDpi::scale(region, scale); - } - - auto margins = this->mWaylandWindow->clientSideMargins(); - region.translate(margins.left(), margins.top()); - } - - this->surface->setBlurRegion(region); - this->pendingBlurRegion = false; -} - -bool BackgroundEffect::eventFilter(QObject* object, QEvent* event) { - if (event->type() == QEvent::PlatformSurface) { - auto* surfaceEvent = dynamic_cast(event); - if (surfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) { - this->surface = nullptr; - this->pendingBlurRegion = false; - } - } - - return this->QObject::eventFilter(object, event); -} - -void BackgroundEffect::onWindowConnected() { - this->mWindow = this->proxyWindow->backingWindow(); - this->mWindow->installEventFilter(this); - - QObject::connect( - this->mWindow, - &QWindow::visibleChanged, - this, - &BackgroundEffect::onWindowVisibleChanged - ); - - this->onWindowVisibleChanged(); -} - -void BackgroundEffect::onWindowVisibleChanged() { - if (this->mWindow->isVisible()) { - if (!this->mWindow->handle()) { - this->mWindow->create(); - } - } - - auto* window = dynamic_cast(this->mWindow->handle()); - if (window == this->mWaylandWindow) return; - - if (this->mWaylandWindow) { - QObject::disconnect(this->mWaylandWindow, nullptr, this, nullptr); - } - - this->mWaylandWindow = window; - if (!window) return; - - QObject::connect( - this->mWaylandWindow, - &QObject::destroyed, - this, - &BackgroundEffect::onWaylandWindowDestroyed - ); - - QObject::connect( - this->mWaylandWindow, - &QWaylandWindow::surfaceCreated, - this, - &BackgroundEffect::onWaylandSurfaceCreated - ); - - QObject::connect( - this->mWaylandWindow, - &QWaylandWindow::surfaceDestroyed, - this, - &BackgroundEffect::onWaylandSurfaceDestroyed - ); - - if (this->mWaylandWindow->surface()) { - this->onWaylandSurfaceCreated(); - } -} - -void BackgroundEffect::onWaylandWindowDestroyed() { this->mWaylandWindow = nullptr; } - -void BackgroundEffect::onWaylandSurfaceCreated() { - auto* manager = impl::BackgroundEffectManager::instance(); - - if (!manager) { - qWarning() << "Cannot enable background effect as ext-background-effect-v1 is not supported " - "by the current compositor."; - return; - } - - // Steal protocol surface from previous BackgroundEffect to avoid duplicate-attachment on reload. - auto v = this->mWaylandWindow->property("qs_background_effect"); - if (v.canConvert()) { - auto* prev = v.value(); - if (prev != this && prev->surface) { - this->surface.swap(prev->surface); - } - } - - if (!this->surface) { - this->surface = std::unique_ptr( - manager->createEffectSurface(this->mWaylandWindow) - ); - } - - this->mWaylandWindow->setProperty("qs_background_effect", QVariant::fromValue(this)); - - this->pendingBlurRegion = this->mBlurRegion != nullptr; - if (this->pendingBlurRegion) { - this->proxyWindow->schedulePolish(); - } -} - -void BackgroundEffect::onWaylandSurfaceDestroyed() { - this->surface = nullptr; - this->pendingBlurRegion = false; - - if (!this->proxyWindow) { - this->deleteLater(); - } -} - -void BackgroundEffect::onProxyWindowDestroyed() { - // Don't delete the BackgroundEffect, and therefore the impl::BackgroundEffectSurface - // until the wl_surface is destroyed. Deleting it when the proxy window is deleted would - // cause a frame without blur between the destruction of the ext_background_effect_surface_v1 - // and wl_surface objects. - - this->proxyWindow = nullptr; - - if (this->surface == nullptr) { - this->deleteLater(); - } -} - -} // namespace qs::wayland::background_effect diff --git a/src/wayland/background_effect/qml.hpp b/src/wayland/background_effect/qml.hpp deleted file mode 100644 index dd93aec..0000000 --- a/src/wayland/background_effect/qml.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -#include "../../core/region.hpp" -#include "../../window/proxywindow.hpp" -#include "surface.hpp" - -namespace qs::wayland::background_effect { - -///! Background blur effect for Wayland surfaces. -/// Applies background blur behind a @@Quickshell.QsWindow or subclass, -/// as an attached object, using the [ext-background-effect-v1] Wayland protocol. -/// -/// > [!NOTE] Using a background effect requires the compositor support the -/// > [ext-background-effect-v1] protocol. -/// -/// [ext-background-effect-v1]: https://wayland.app/protocols/ext-background-effect-v1 -/// -/// #### Example -/// ```qml -/// @@Quickshell.PanelWindow { -/// id: root -/// color: "#80000000" -/// -/// BackgroundEffect.blurRegion: Region { item: root.contentItem } -/// } -/// ``` -class BackgroundEffect: public QObject { - Q_OBJECT; - // clang-format off - /// Region to blur behind the surface. Set to null to remove blur. - Q_PROPERTY(PendingRegion* blurRegion READ blurRegion WRITE setBlurRegion NOTIFY blurRegionChanged); - // clang-format on - QML_ELEMENT; - QML_UNCREATABLE("BackgroundEffect can only be used as an attached object."); - QML_ATTACHED(BackgroundEffect); - -public: - explicit BackgroundEffect(ProxyWindowBase* window); - - [[nodiscard]] PendingRegion* blurRegion() const; - void setBlurRegion(PendingRegion* region); - - static BackgroundEffect* qmlAttachedProperties(QObject* object); - - bool eventFilter(QObject* object, QEvent* event) override; - -signals: - void blurRegionChanged(); - -private slots: - void onWindowConnected(); - void onWindowVisibleChanged(); - void onWaylandWindowDestroyed(); - void onWaylandSurfaceCreated(); - void onWaylandSurfaceDestroyed(); - void onProxyWindowDestroyed(); - void onBlurRegionDestroyed(); - void onWindowPolished(); - void updateBlurRegion(); - -private: - ProxyWindowBase* proxyWindow = nullptr; - QWindow* mWindow = nullptr; - QtWaylandClient::QWaylandWindow* mWaylandWindow = nullptr; - - bool pendingBlurRegion = false; - PendingRegion* mBlurRegion = nullptr; - std::unique_ptr surface; -}; - -} // namespace qs::wayland::background_effect diff --git a/src/wayland/background_effect/surface.cpp b/src/wayland/background_effect/surface.cpp deleted file mode 100644 index 648361d..0000000 --- a/src/wayland/background_effect/surface.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "surface.hpp" - -#include -#include -#include -#include -#include - -namespace qs::wayland::background_effect::impl { - -BackgroundEffectSurface::BackgroundEffectSurface( - ::ext_background_effect_surface_v1* surface // NOLINT(misc-include-cleaner) -) - : QtWayland::ext_background_effect_surface_v1(surface) {} - -BackgroundEffectSurface::~BackgroundEffectSurface() { - if (!this->isInitialized()) return; - this->destroy(); -} - -void BackgroundEffectSurface::setBlurRegion(const QRegion& region) { - if (!this->isInitialized()) return; - - if (region.isEmpty()) { - this->set_blur_region(nullptr); - return; - } - - static const auto* waylandIntegration = QtWaylandClient::QWaylandIntegration::instance(); - auto* display = waylandIntegration->display(); - - auto* wlRegion = display->createRegion(region); - this->set_blur_region(wlRegion); - wl_region_destroy(wlRegion); // NOLINT(misc-include-cleaner) -} - -} // namespace qs::wayland::background_effect::impl diff --git a/src/wayland/background_effect/surface.hpp b/src/wayland/background_effect/surface.hpp deleted file mode 100644 index 65b0bc8..0000000 --- a/src/wayland/background_effect/surface.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace qs::wayland::background_effect::impl { - -class BackgroundEffectSurface: public QtWayland::ext_background_effect_surface_v1 { -public: - explicit BackgroundEffectSurface(::ext_background_effect_surface_v1* surface); - ~BackgroundEffectSurface() override; - Q_DISABLE_COPY_MOVE(BackgroundEffectSurface); - - void setBlurRegion(const QRegion& region); -}; - -} // namespace qs::wayland::background_effect::impl diff --git a/src/wayland/background_effect/test/manual/background_effect.qml b/src/wayland/background_effect/test/manual/background_effect.qml deleted file mode 100644 index 679cb01..0000000 --- a/src/wayland/background_effect/test/manual/background_effect.qml +++ /dev/null @@ -1,62 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import Quickshell -import Quickshell.Wayland - -FloatingWindow { - id: root - color: "transparent" - contentItem.palette.windowText: "white" - - ColumnLayout { - anchors.centerIn: parent - - CheckBox { - id: enableBox - checked: true - text: "Enable Blur" - } - - Button { - text: "Hide->Show" - onClicked: { - root.visible = false - showTimer.start() - } - } - - Timer { - id: showTimer - interval: 200 - onTriggered: root.visible = true - } - - Slider { - id: radiusSlider - from: 0 - to: 1000 - value: 100 - } - - component EdgeSlider: Slider { - from: -1 - to: 1000 - value: -1 - } - - EdgeSlider { id: topLeftSlider } - EdgeSlider { id: topRightSlider } - EdgeSlider { id: bottomLeftSlider } - EdgeSlider { id: bottomRightSlider } - } - - BackgroundEffect.blurRegion: Region { - item: enableBox.checked ? root.contentItem : null - radius: radiusSlider.value == -1 ? undefined : radiusSlider.value - topLeftRadius: topLeftSlider.value == -1 ? undefined : topLeftSlider.value - topRightRadius: topRightSlider.value == -1 ? undefined : topRightSlider.value - bottomLeftRadius: bottomLeftSlider.value == -1 ? undefined : bottomLeftSlider.value - bottomRightRadius: bottomRightSlider.value == -1 ? undefined : bottomRightSlider.value - } -} diff --git a/src/wayland/module.md b/src/wayland/module.md index 964fa76..9ad15ba 100644 --- a/src/wayland/module.md +++ b/src/wayland/module.md @@ -8,6 +8,5 @@ headers = [ "idle_inhibit/inhibitor.hpp", "idle_notify/monitor.hpp", "shortcuts_inhibit/inhibitor.hpp", - "background_effect/qml.hpp", ] -----