From 9b49cca2a56e0d8d2d9f1875e5f341c74b2fee64 Mon Sep 17 00:00:00 2001 From: reionwong Date: Tue, 31 Aug 2021 19:41:32 +0800 Subject: [PATCH] Improve roundedwindow --- debian/control | 1 + plugins/decoration/CMakeLists.txt | 4 +- plugins/decoration/decoration.cpp | 27 ++----- plugins/decoration/decoration.h | 5 +- plugins/decoration/x11shadow.cpp | 31 +++++++++ plugins/decoration/x11shadow.h | 18 +++++ plugins/roundedwindow/roundedwindow.cpp | 93 ++++++++++++++++++++----- plugins/roundedwindow/roundedwindow.h | 11 ++- 8 files changed, 147 insertions(+), 43 deletions(-) create mode 100644 plugins/decoration/x11shadow.cpp create mode 100644 plugins/decoration/x11shadow.h diff --git a/debian/control b/debian/control index cccd304..5d7c9b8 100644 --- a/debian/control +++ b/debian/control @@ -12,6 +12,7 @@ Build-Depends: cmake, libkdecorations2-dev, libkf5coreaddons-dev, libqt5opengl5-dev, + libqt5x11extras5-dev, qtbase5-dev, qtbase5-private-dev, qtdeclarative5-dev, diff --git a/plugins/decoration/CMakeLists.txt b/plugins/decoration/CMakeLists.txt index bb3b065..a90b7fa 100644 --- a/plugins/decoration/CMakeLists.txt +++ b/plugins/decoration/CMakeLists.txt @@ -5,10 +5,11 @@ find_package(KF5CoreAddons REQUIRED) find_package(KF5Config REQUIRED) find_package(KF5WindowSystem REQUIRED) find_package(KDecoration2 REQUIRED) -find_package(Qt5 CONFIG REQUIRED COMPONENTS Gui Core) +find_package(Qt5 CONFIG REQUIRED COMPONENTS Gui Core X11Extras) set (decoration_SRCS decoration.cpp + x11shadow.cpp button.cpp resources.qrc ) @@ -21,6 +22,7 @@ target_link_libraries (cutefishdecoration PUBLIC Qt5::Core Qt5::Gui + Qt5::X11Extras KF5::ConfigCore KF5::ConfigGui KF5::CoreAddons diff --git a/plugins/decoration/decoration.cpp b/plugins/decoration/decoration.cpp index bd72ab0..1b1a83d 100644 --- a/plugins/decoration/decoration.cpp +++ b/plugins/decoration/decoration.cpp @@ -52,10 +52,11 @@ static QColor g_shadowColor = Qt::black; static QSharedPointer g_sShadow; Decoration::Decoration(QObject *parent, const QVariantList &args) - : KDecoration2::Decoration(parent, args), - m_settings(new QSettings(QSettings::UserScope, "cutefishos", "theme")), - m_settingsFile(m_settings->fileName()), - m_fileWatcher(new QFileSystemWatcher) + : KDecoration2::Decoration(parent, args) + , m_settings(new QSettings(QSettings::UserScope, "cutefishos", "theme")) + , m_settingsFile(m_settings->fileName()) + , m_fileWatcher(new QFileSystemWatcher) + , m_x11Shadow(new X11Shadow) { ++g_sDecoCount; } @@ -95,7 +96,6 @@ void Decoration::paint(QPainter *painter, const QRect &repaintRegion) m_rightButtons->paint(painter, repaintRegion); } - // paintTitleBarBackground(painter, repaintRegion); paintCaption(painter, repaintRegion); paintButtons(painter, repaintRegion); } @@ -366,7 +366,8 @@ bool Decoration::darkMode() const bool Decoration::radiusAvailable() const { - return client().toStrongRef().data()->adjacentScreenEdges() == Qt::Edges(); + return !isMaximized(); + // return client().toStrongRef().data()->adjacentScreenEdges() == Qt::Edges(); } bool Decoration::isMaximized() const @@ -408,20 +409,6 @@ QColor Decoration::titleBarForegroundColor() const return color; } -void Decoration::paintTitleBarBackground(QPainter *painter, const QRect &repaintRegion) const -{ - Q_UNUSED(repaintRegion) - - const auto *decoratedClient = client().toStrongRef().data(); - - painter->save(); - painter->setRenderHint(QPainter::Antialiasing); - painter->setPen(Qt::NoPen); - painter->setBrush(Qt::red); - painter->drawRoundedRect(QRect(0, 0, decoratedClient->width(), titleBarHeight()), 6, 6); - painter->restore(); -} - void Decoration::paintCaption(QPainter *painter, const QRect &repaintRegion) const { Q_UNUSED(repaintRegion) diff --git a/plugins/decoration/decoration.h b/plugins/decoration/decoration.h index 2b8bd47..0e34ef9 100644 --- a/plugins/decoration/decoration.h +++ b/plugins/decoration/decoration.h @@ -28,6 +28,8 @@ #include #include +#include "x11shadow.h" + namespace Cutefish { @@ -78,7 +80,6 @@ private: bool isMaximized() const; void paintFrameBackground(QPainter *painter, const QRect &repaintRegion) const; - void paintTitleBarBackground(QPainter *painter, const QRect &repaintRegion) const; void paintCaption(QPainter *painter, const QRect &repaintRegion) const; void paintButtons(QPainter *painter, const QRect &repaintRegion) const; @@ -109,6 +110,8 @@ private: QPixmap m_maximizeBtnPixmap; QPixmap m_minimizeBtnPixmap; QPixmap m_restoreBtnPixmap; + + X11Shadow *m_x11Shadow; }; } diff --git a/plugins/decoration/x11shadow.cpp b/plugins/decoration/x11shadow.cpp new file mode 100644 index 0000000..70ad4a7 --- /dev/null +++ b/plugins/decoration/x11shadow.cpp @@ -0,0 +1,31 @@ +#include "x11shadow.h" + +#include +#include + +static xcb_atom_t internAtom(const char *name, bool only_if_exists) +{ + if (!name || *name == 0) + return XCB_NONE; + + if (!QX11Info::isPlatformX11()) + return XCB_NONE; + + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(QX11Info::connection(), only_if_exists, strlen(name), name); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(QX11Info::connection(), cookie, 0); + + if (!reply) + return XCB_NONE; + + xcb_atom_t atom = reply->atom; + free(reply); + + return atom; +} + +X11Shadow::X11Shadow(QObject *parent) + : QObject(parent) +{ + m_atom_net_wm_shadow = internAtom("_KDE_NET_WM_SHADOW", false); + m_atom_net_wm_window_type = internAtom("_NET_WM_WINDOW_TYPE", false); +} diff --git a/plugins/decoration/x11shadow.h b/plugins/decoration/x11shadow.h new file mode 100644 index 0000000..a9cae6c --- /dev/null +++ b/plugins/decoration/x11shadow.h @@ -0,0 +1,18 @@ +#ifndef X11SHADOW_H +#define X11SHADOW_H + +#include + +class X11Shadow : public QObject +{ + Q_OBJECT + +public: + explicit X11Shadow(QObject *parent = nullptr); + +private: + quint32 m_atom_net_wm_shadow; + quint32 m_atom_net_wm_window_type; +}; + +#endif // X11SHADOW_H diff --git a/plugins/roundedwindow/roundedwindow.cpp b/plugins/roundedwindow/roundedwindow.cpp index b2474ec..fe29132 100644 --- a/plugins/roundedwindow/roundedwindow.cpp +++ b/plugins/roundedwindow/roundedwindow.cpp @@ -32,6 +32,22 @@ Q_DECLARE_METATYPE(QPainterPath) typedef void (* SetDepth)(void *, int); static SetDepth setDepthfunc = nullptr; +static QStringList allowList = { "netease-cloud-music netease-cloud-music", + "com.alibabainc.dingtalk com.alibabainc.dingtalk", + "tenvideo_universal tenvideo_universal", + "com.eusoft.ting.en com.eusoft.ting.en", + "i4toolslinux i4tools", + "youku-app youku-app", + "qqmusic qqmusic", + "mytime mytime", + "feishu feishu", + "xmind xmind", + "mtxx mtxx", + + // Open source software + "code code" + }; + // From ubreffect static KWin::GLShader *getShader() { @@ -170,11 +186,28 @@ static KWin::GLTexture *getTexture(int borderRadius) RoundedWindow::RoundedWindow(QObject *, const QVariantList &) : KWin::Effect() , m_frameRadius(12) - , m_corner(m_frameRadius, m_frameRadius) -{ +{ setDepthfunc = (SetDepth) QLibrary::resolve("kwin.so." + qApp->applicationVersion(), "_ZN4KWin8Toplevel8setDepthEi"); - m_newShader = getShader(); + QString name = "_NET_WM_STATE"; + xcb_intern_atom_cookie_t cookie = xcb_intern_atom_unchecked(KWin::connection(), false, name.length(), name.toUtf8()); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(KWin::connection(), cookie, nullptr); + m_netWMStateAtom = reply->atom; + free(reply); + + name = "_NET_WM_STATE_MAXIMIZED_HORZ"; + cookie = xcb_intern_atom_unchecked(KWin::connection(), false, name.length(), name.toUtf8()); + reply = xcb_intern_atom_reply(KWin::connection(), cookie, nullptr); + m_netWMStateMaxHorzAtom = reply->atom; + free(reply); + + name = "_NET_WM_STATE_MAXIMIZED_VERT"; + cookie = xcb_intern_atom_unchecked(KWin::connection(), false, name.length(), name.toUtf8()); + reply = xcb_intern_atom_reply(KWin::connection(), cookie, nullptr); + m_netWMStateMaxVertAtom = reply->atom; + free(reply); + + m_shader = getShader(); m_texure = getTexture(m_frameRadius); } @@ -201,14 +234,34 @@ bool RoundedWindow::hasShadow(KWin::WindowQuadList &qds) return false; } +bool RoundedWindow::isMaximized(KWin::EffectWindow *w) +{ + if (m_netWMStateAtom == 0) + return false; + + QByteArray rawAtomData = w->readProperty(m_netWMStateAtom, XCB_ATOM_ATOM, 32); + if (!rawAtomData.isEmpty()) { + for (int i = 0; i < rawAtomData.length(); i += sizeof(xcb_atom_t)) { + xcb_atom_t atom = static_cast(rawAtomData.data()[i]) + 512; + if (atom == m_netWMStateMaxHorzAtom || atom == m_netWMStateMaxVertAtom) + return true; + } + } + + return false; +} + void RoundedWindow::drawWindow(KWin::EffectWindow *w, int mask, const QRegion ®ion, KWin::WindowPaintData &data) { if (!w->isPaintingEnabled() || ((mask & PAINT_WINDOW_LANCZOS))) { return KWin::Effect::drawWindow(w, mask, region, data); } - if (!m_newShader->isValid() - || KWin::effects->hasActiveFullScreenEffect() + if (isMaximized(w)) { + return KWin::Effect::drawWindow(w, mask, region, data); + } + + if (KWin::effects->hasActiveFullScreenEffect() || w->isDesktop() || w->isMenu() || w->isDock() @@ -216,7 +269,8 @@ void RoundedWindow::drawWindow(KWin::EffectWindow *w, int mask, const QRegion &r || w->isPopupMenu() || w->isFullScreen() || !hasShadow(data.quads)) { - return KWin::Effect::drawWindow(w, mask, region, data); + if (!allowList.contains(w->windowClass())) + return KWin::Effect::drawWindow(w, mask, region, data); } // 设置 alpha 通道混合 @@ -226,8 +280,6 @@ void RoundedWindow::drawWindow(KWin::EffectWindow *w, int mask, const QRegion &r } } - KWin::WindowPaintData paintData = data; - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -257,28 +309,31 @@ void RoundedWindow::drawWindow(KWin::EffectWindow *w, int mask, const QRegion &r glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); glActiveTexture(GL_TEXTURE0); - paintData.shader = m_newShader; - KWin::ShaderManager::instance()->pushShader(m_newShader); + KWin::GLShader *oldShader = data.shader; + data.shader = m_shader; + KWin::ShaderManager::instance()->pushShader(m_shader); - m_newShader->setUniform("topleft", 10); - m_newShader->setUniform("scale", QVector2D(w->width() * 1.0 / textureTopLeft->width(), + m_shader->setUniform("topleft", 10); + m_shader->setUniform("scale", QVector2D(w->width() * 1.0 / textureTopLeft->width(), w->height() * 1.0 / textureTopLeft->height())); - m_newShader->setUniform("topright", 11); - m_newShader->setUniform("scale1", QVector2D(w->width() * 1.0 / textureTopRight->width(), + m_shader->setUniform("topright", 11); + m_shader->setUniform("scale1", QVector2D(w->width() * 1.0 / textureTopRight->width(), w->height() * 1.0 / textureTopRight->height())); - m_newShader->setUniform("bottomleft", 12); - m_newShader->setUniform("scale2", QVector2D(w->width() * 1.0 / textureBottomLeft->width(), + m_shader->setUniform("bottomleft", 12); + m_shader->setUniform("scale2", QVector2D(w->width() * 1.0 / textureBottomLeft->width(), w->height() * 1.0 / textureBottomLeft->height())); - m_newShader->setUniform("bottomright", 13); - m_newShader->setUniform("scale3", QVector2D(w->width() * 1.0 / textureBottomRight->width(), + m_shader->setUniform("bottomright", 13); + m_shader->setUniform("scale3", QVector2D(w->width() * 1.0 / textureBottomRight->width(), w->height() * 1.0 / textureBottomRight->height())); - KWin::Effect::drawWindow(w, mask, region, paintData); + KWin::Effect::drawWindow(w, mask, region, data); KWin::ShaderManager::instance()->popShader(); + data.shader = oldShader; + glActiveTexture(GL_TEXTURE10); textureTopLeft->unbind(); glActiveTexture(GL_TEXTURE0); diff --git a/plugins/roundedwindow/roundedwindow.h b/plugins/roundedwindow/roundedwindow.h index ecb7777..c15ac01 100644 --- a/plugins/roundedwindow/roundedwindow.h +++ b/plugins/roundedwindow/roundedwindow.h @@ -25,6 +25,8 @@ #include #include +#include + class RoundedWindow : public KWin::Effect { Q_OBJECT @@ -43,16 +45,21 @@ public: static bool supported(); static bool enabledByDefault(); + bool hasShadow(KWin::WindowQuadList &qds); + bool isMaximized(KWin::EffectWindow *w); void drawWindow(KWin::EffectWindow* w, int mask, const QRegion ®ion, KWin::WindowPaintData& data) override; private: - KWin::GLShader *m_newShader; + KWin::GLShader *m_shader; KWin::GLTexture *m_texure; + xcb_atom_t m_netWMStateAtom = 0; + xcb_atom_t m_netWMStateMaxHorzAtom = 0; + xcb_atom_t m_netWMStateMaxVertAtom = 0; + int m_frameRadius; - QSize m_corner; }; #endif