From ae66e24e639fec34486fb5f860c496d8e9dbc86a Mon Sep 17 00:00:00 2001 From: liuxinhao Date: Mon, 22 Jan 2024 17:34:24 +0800 Subject: [PATCH] feat(KiranTitlebarWindow): Customize title bar to send requests to the window manager and pop up a right-click menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 自定义标题栏发送请求给窗口管理器弹出右键菜单 Closes #24920 --- ...arWindow-Customize-title-bar-to-send.patch | 606 ++++++++++++++++++ kiran-widgets-qt5.spec | 8 +- 2 files changed, 612 insertions(+), 2 deletions(-) create mode 100644 0001-feat-KiranTitlebarWindow-Customize-title-bar-to-send.patch diff --git a/0001-feat-KiranTitlebarWindow-Customize-title-bar-to-send.patch b/0001-feat-KiranTitlebarWindow-Customize-title-bar-to-send.patch new file mode 100644 index 0000000..ab6100f --- /dev/null +++ b/0001-feat-KiranTitlebarWindow-Customize-title-bar-to-send.patch @@ -0,0 +1,606 @@ +From c91b9ab12c19ea19171c63569064dc1a0e1c33bf Mon Sep 17 00:00:00 2001 +From: liuxinhao +Date: Mon, 22 Jan 2024 17:31:18 +0800 +Subject: [PATCH] feat(KiranTitlebarWindow): Customize title bar to send + requests to the window manager and pop up a right-click menu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +- 自定义标题栏发送请求给窗口管理器弹出右键菜单 + +Closes #24920 +--- + src/public/xlib-helper.cpp | 140 ++++++++++++++---- + src/public/xlib-helper.h | 17 ++- + .../kiran-titlebar-window-private.cpp | 131 ++++++++-------- + 3 files changed, 189 insertions(+), 99 deletions(-) + +diff --git a/src/public/xlib-helper.cpp b/src/public/xlib-helper.cpp +index c25ffda..8047430 100644 +--- a/src/public/xlib-helper.cpp ++++ b/src/public/xlib-helper.cpp +@@ -1,27 +1,28 @@ + /** +- * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. ++ * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiranwidgets-qt5 is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- * ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * + * Author: liuxinhao + */ +- ++ + #include "xlib-helper.h" + +-#include + #include +-#include ++#include + #include ++#include ++#include + + using namespace Kiran; + +-bool sendWMMoveResizeEvent(Display* display,EwmhMoveResizeDirection direction,quint64 xid,int x,int y) ++bool sendWMMoveResizeEvent(Display* display, EwmhMoveResizeDirection direction, quint64 xid, int x, int y) + { + Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", False); + XEvent xEvent; +@@ -46,18 +47,19 @@ bool sendWMMoveResizeEvent(Display* display,EwmhMoveResizeDirection direction,qu + return sendEvRes; + } + +-bool XLibHelper::sendWMMoveEvent(Display *display, quint64 xid, int x, int y) ++bool XLibHelper::sendWMMoveEvent(Display* display, quint64 xid, int x, int y) + { +- return sendWMMoveResizeEvent(display,WM_MOVERESIZE_MOVE,xid,x,y); ++ return sendWMMoveResizeEvent(display, WM_MOVERESIZE_MOVE, xid, x, y); + } + +-bool XLibHelper::sendResizeEvent(Display *display, ++bool XLibHelper::sendResizeEvent(Display* display, + CursorPositionEnums postion, + quint64 xid, + int x, int y) + { + EwmhMoveResizeDirection direction = WM_MOVERESIZE_CANCEL; +- switch (postion) { ++ switch (postion) ++ { + case CursorPosition_LeftTop: + direction = WM_MOVERESIZE_SIZE_TOPLEFT; + break; +@@ -83,10 +85,10 @@ bool XLibHelper::sendResizeEvent(Display *display, + direction = WM_MOVERESIZE_SIZE_RIGHT; + break; + } +- return sendWMMoveResizeEvent(display,direction,xid,x,y); ++ return sendWMMoveResizeEvent(display, direction, xid, x, y); + } + +-int XLibHelper::SetShadowWidth(Display *xdisplay, ++int XLibHelper::SetShadowWidth(Display* xdisplay, + quint64 xid, + int left, + int right, +@@ -103,19 +105,103 @@ int XLibHelper::SetShadowWidth(Display *xdisplay, + frames[2] = top; + frames[3] = bottom; + int s = XChangeProperty(xdisplay, +- xid, +- atom, +- XA_CARDINAL, +- 32, +- PropModeReplace, +- (unsigned char *)frames, +- 4); ++ xid, ++ atom, ++ XA_CARDINAL, ++ 32, ++ PropModeReplace, ++ (unsigned char*)frames, ++ 4); + XFlush(xdisplay); + + return s; + } + +-bool XLibHelper::cancelWMMove(Display* display,quint64 xid,int x, int y) ++bool XLibHelper::cancelWMMove(Display* display, quint64 xid, int x, int y) ++{ ++ return sendWMMoveResizeEvent(display, WM_MOVERESIZE_CANCEL, xid, x, y); ++} ++ ++void reloadNetSupportedAtoms(Display* xdisplay, QMap& atomsMap) ++{ ++ atomsMap.clear(); ++ ++ // get _NET_SUPPORTED atom ++ Atom netSupportedAtom = XInternAtom(xdisplay, "_NET_SUPPORTED", 1); ++ if (netSupportedAtom == None) ++ { ++ return; ++ } ++ ++ // get _NET_SUPPORTED atom value from root window ++ Window rootWindow = QX11Info::appRootWindow(QX11Info::appScreen()); ++ Atom type; ++ int format; ++ unsigned long after; ++ unsigned long natoms; ++ Atom* atoms; ++ XGetWindowProperty(xdisplay, rootWindow, netSupportedAtom, 0, LONG_MAX, False, XA_ATOM, &type, &format, &natoms, &after, (unsigned char**)&atoms); ++ if (type != XA_ATOM || atoms == nullptr) ++ { ++ return; ++ } ++ ++ // cache root window _NET_SUPPORTED property ++ for (int i = 0; i < natoms; i++) ++ { ++ char* atomName = XGetAtomName(xdisplay, atoms[i]); ++ atomsMap.insert(atomName, atoms[i]); ++ ++ XFree(atomName); ++ } ++ ++ XFree(atoms); ++} ++ ++bool checkNetWmHintSupported(Display* xdisplay, const char* atomName) + { +- return sendWMMoveResizeEvent(display,WM_MOVERESIZE_CANCEL,xid,x,y); ++ static QMap supportedAtomMap; ++ ++ if (supportedAtomMap.isEmpty()) ++ { ++ reloadNetSupportedAtoms(xdisplay, supportedAtomMap); ++ } ++ ++ if (supportedAtomMap.contains(atomName)) ++ { ++ return true; ++ } ++ ++ return false; ++} ++ ++// _GTK_SHOW_WINDOW_MENU支持情况 ++// marco >= 1.20支持 ++// kwin >= 5.26支持 ++#define ATOM_WINDOW_SHOW_WINDOW_MENU "_GTK_SHOW_WINDOW_MENU" ++bool XLibHelper::showWindowMenuRequest(Display* xdisplay, quint64 xid, int root_x, int root_y) ++{ ++ if (!checkNetWmHintSupported(xdisplay, ATOM_WINDOW_SHOW_WINDOW_MENU)) ++ { ++ return false; ++ } ++ ++ Atom showWindowMenuAtom = XInternAtom(xdisplay, ATOM_WINDOW_SHOW_WINDOW_MENU, 1); ++ ++ XEvent xEvent; ++ memset(&xEvent, 0, sizeof(XEvent)); ++ xEvent.xclient.type = ClientMessage; ++ xEvent.xclient.message_type = showWindowMenuAtom; ++ xEvent.xclient.display = xdisplay; ++ xEvent.xclient.window = xid; ++ xEvent.xclient.format = 32; ++ xEvent.xclient.data.l[0] = 0; /*GTK device ID(unused)*/ ++ xEvent.xclient.data.l[1] = root_x; /* X coordinate relative to root */ ++ xEvent.xclient.data.l[2] = root_y; /* Y coordinate relative to root */ ++ ++ XSendEvent(xdisplay, QX11Info::appRootWindow(QX11Info::appScreen()), ++ False, SubstructureNotifyMask | SubstructureRedirectMask, ++ &xEvent); ++ XFlush(xdisplay); ++ return true; + } +\ No newline at end of file +diff --git a/src/public/xlib-helper.h b/src/public/xlib-helper.h +index 65842c2..2ec879c 100644 +--- a/src/public/xlib-helper.h ++++ b/src/public/xlib-helper.h +@@ -1,14 +1,14 @@ + /** +- * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. ++ * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiranwidgets-qt5 is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- * ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * + * Author: liuxinhao + */ + +@@ -24,6 +24,7 @@ namespace XLibHelper { + bool sendWMMoveEvent(Display* display,quint64 xid,int x,int y); + bool sendResizeEvent(Display* display,Kiran::CursorPositionEnums postion,quint64 xid,int x,int y); + int SetShadowWidth(Display *xdisplay,quint64 xid,int left,int right,int top,int bottom); ++ bool showWindowMenuRequest(Display *xdisplay,quint64 xid,int root_x,int root_y); + } + + #endif // XLIBHELPER_H +diff --git a/src/widgets/kiran-titlebar-window/kiran-titlebar-window-private.cpp b/src/widgets/kiran-titlebar-window/kiran-titlebar-window-private.cpp +index 8252d97..43cd51a 100644 +--- a/src/widgets/kiran-titlebar-window/kiran-titlebar-window-private.cpp ++++ b/src/widgets/kiran-titlebar-window/kiran-titlebar-window-private.cpp +@@ -1,14 +1,14 @@ + /** +- * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. ++ * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiranwidgets-qt5 is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- * ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * + * Author: liuxinhao + */ + +@@ -30,21 +30,20 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include + #include + #include +-#include +-#include +- + +-const int KiranTitlebarWindowPrivate::radius = 8; ++const int KiranTitlebarWindowPrivate::radius = 8; + +-const int KiranTitlebarWindowPrivate::shadowWidth = 15; +-const int KiranTitlebarWindowPrivate::shadowRadius = 15; +-const QColor KiranTitlebarWindowPrivate::shadowActiveColor = QColor(0,0,0,150); +-const QColor KiranTitlebarWindowPrivate::shadowInactiveColor = QColor(0,0,0,75); ++const int KiranTitlebarWindowPrivate::shadowWidth = 15; ++const int KiranTitlebarWindowPrivate::shadowRadius = 15; ++const QColor KiranTitlebarWindowPrivate::shadowActiveColor = QColor(0, 0, 0, 150); ++const QColor KiranTitlebarWindowPrivate::shadowInactiveColor = QColor(0, 0, 0, 75); + + extern void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); + +@@ -76,8 +75,8 @@ KiranTitlebarWindowPrivate::~KiranTitlebarWindowPrivate() + + void KiranTitlebarWindowPrivate::init() + { +- //app调色盘改变可以认为主题风格产生变化,需重新拿取图标更新 +- connect(qApp, &QApplication::paletteChanged, this,&KiranTitlebarWindowPrivate::updateTitlebarButtonIcon); ++ // app调色盘改变可以认为主题风格产生变化,需重新拿取图标更新 ++ connect(qApp, &QApplication::paletteChanged, this, &KiranTitlebarWindowPrivate::updateTitlebarButtonIcon); + + initOtherWidget(); + +@@ -88,8 +87,8 @@ void KiranTitlebarWindowPrivate::init() + + /// 初始化阴影边框 + m_isCompositingManagerRunning = QX11Info::isCompositingManagerRunning(); +- +- if( m_isCompositingManagerRunning ) ++ ++ if (m_isCompositingManagerRunning) + { + m_layout->setMargin(shadowWidth); + } +@@ -212,7 +211,7 @@ void KiranTitlebarWindowPrivate::handlerMouseButtonPressEvent(QMouseEvent *ev) + qDebug() << "titlebar frame contains:" << m_titlebarWidget->frameGeometry().contains(ev->pos()); + #endif + +- if (m_titlebarWidget->frameGeometry().contains(m_titlebarWidget->mapFrom(q_ptr,ev->pos()))) ++ if (m_titlebarWidget->frameGeometry().contains(m_titlebarWidget->mapFrom(q_ptr, ev->pos()))) + { + m_titlebarIsPressed = true; + } +@@ -227,11 +226,18 @@ void KiranTitlebarWindowPrivate::handlerMouseButtonReleaseEvent(QMouseEvent *ev) + m_titlebarIsPressed = false; + } + } ++ else if (ev->button() == Qt::RightButton) ++ { ++ QPoint pos = QCursor::pos(); ++ XLibHelper::showWindowMenuRequest(QX11Info::display(), ++ q_func()->winId(), ++ pos.x(), pos.y()); ++ } + } + + void KiranTitlebarWindowPrivate::handlerMouseMoveEvent(QMouseEvent *ev) + { +- ///判断是否点击标题栏区域 ++ /// 判断是否点击标题栏区域 + if (m_titlebarIsPressed) + { + QPoint pos = QCursor::pos(); +@@ -240,7 +246,7 @@ void KiranTitlebarWindowPrivate::handlerMouseMoveEvent(QMouseEvent *ev) + q_func()->winId(), + pos.x(), + pos.y()); +- ///NOTE:在此之后获取不到MouseRelease事件,需复位按钮按压 ++ /// NOTE:在此之后获取不到MouseRelease事件,需复位按钮按压 + m_titlebarIsPressed = false; + return; + } +@@ -268,13 +274,13 @@ void KiranTitlebarWindowPrivate::handlerMouseDoubleClickEvent(QMouseEvent *ev) + + void KiranTitlebarWindowPrivate::initOtherWidget() + { +- ///主布局 ++ /// 主布局 + m_layout = new QVBoxLayout(q_ptr); + m_layout->setObjectName("KiranTitlebarMainLayout"); + m_layout->setMargin(0); + m_layout->setSpacing(0); + +- ///背景 ++ /// 背景 + m_frame = new FramelessBackgroundFrame(q_ptr); + m_frame->setRadius(radius); + m_frame->setAttribute(Qt::WA_Hover); +@@ -285,7 +291,7 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + m_frameLayout->setMargin(0); + m_frameLayout->setSpacing(0); + +- ///标题栏 ++ /// 标题栏 + m_titlebarColorBlock = new KiranColorBlock(m_frame); + m_titlebarColorBlock->setDrawBackground(false); + m_titlebarColorBlock->setRoundedCorner(KiranColorBlock::CornersTop); +@@ -306,8 +312,8 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + m_titleBarLayout->setSpacing(0); + m_titleBarLayout->setObjectName("KiranTitlebarLayout"); + +- ///标题栏居左部分 +- //标题栏图标 ++ /// 标题栏居左部分 ++ // 标题栏图标 + m_titleIcon = new QLabel(m_titlebarWidget); + m_titleIcon->setObjectName("KiranTitlebarIcon"); + m_titleIcon->setAccessibleName("WindowTitlebarIcon"); +@@ -315,7 +321,7 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + m_titleBarLayout->setTitleBarIconLabel(m_titleIcon); + m_titleBarLayout->setTitleBarIconMargin(QMargins(12, 0, 0, 0)); + +- //标题 ++ // 标题 + m_title = new QLabel(m_titlebarWidget); + m_title->setFont(QFontDatabase::systemFont(QFontDatabase::TitleFont)); + m_title->setObjectName("KiranTitlebarTitle"); +@@ -325,8 +331,8 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + m_title->installEventFilter(this); + m_titleBarLayout->setTitleBarTitleLabel(m_title); + +- ///标题栏居中部分 +- //自定义控件区域 ++ /// 标题栏居中部分 ++ // 自定义控件区域 + m_titlebarCenterWidget = new QWidget(m_titlebarWidget); + m_titlebarCenterWidget->setObjectName("KiranTitlebarCenterWidget"); + m_titlebarCenterWidget->setAccessibleName("WindowTitlebarCenterWidget"); +@@ -337,7 +343,7 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + m_customLayout->setSpacing(0); + m_customLayout->setObjectName("KiranTitlebarCustomLayout"); + +- ///标题栏居右部分 ++ /// 标题栏居右部分 + m_titlebarRirghtWidget = new QWidget(m_titlebarWidget); + m_titlebarRirghtWidget->setObjectName("KiranTitlebarRightWidget"); + m_titlebarRirghtWidget->setAccessibleName("WindowTitlebarRightWidget"); +@@ -348,11 +354,11 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + titlebarRightlayout->setSpacing(0); + titlebarRightlayout->setMargin(0); + +- //占位 ++ // 占位 + QSpacerItem *spacerItem = new QSpacerItem(0, 20, QSizePolicy::Expanding); + titlebarRightlayout->addItem(spacerItem); + +- //最小化 ++ // 最小化 + m_btnMin = new QPushButton(m_titlebarWidget); + m_btnMin->setObjectName("KiranTitlebarMinButton"); + m_btnMin->setAccessibleName("WindowTitlebarMinimizeButton"); +@@ -363,11 +369,10 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + connect(m_btnMin, &QPushButton::clicked, [this](bool checked) + { + Q_UNUSED(checked); +- q_ptr->showMinimized(); +- }); ++ q_ptr->showMinimized(); }); + titlebarRightlayout->addWidget(m_btnMin, 0, Qt::AlignVCenter); + +- //最大化 ++ // 最大化 + m_btnMax = new QPushButton(m_titlebarWidget); + m_btnMax->setObjectName("KiranTitlebarMaxButton"); + m_btnMax->setAccessibleName("WindowTitlebarMaximizeButton"); +@@ -385,11 +390,10 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + else + { + q_ptr->showMaximized(); +- } +- }); ++ } }); + titlebarRightlayout->addWidget(m_btnMax, 0, Qt::AlignVCenter); + +- //关闭 ++ // 关闭 + m_btnClose = new QPushButton(m_titlebarWidget); + m_btnClose->setObjectName("KiranTitlebarCloseButton"); + m_btnClose->setAccessibleName("WindowTitlebarCloseButton"); +@@ -400,13 +404,12 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + connect(m_btnClose, &QPushButton::clicked, [this](bool checked) + { + Q_UNUSED(checked); +- q_ptr->close(); +- }); ++ q_ptr->close(); }); + titlebarRightlayout->addWidget(m_btnClose, 0, Qt::AlignVCenter); + + setButtonHints(m_buttonHints); + +- ///分割线 ++ /// 分割线 + m_tittlebarSpliteLine = new QFrame(m_frame); + m_tittlebarSpliteLine->setFixedHeight(1); + m_frameLayout->addWidget(m_tittlebarSpliteLine); +@@ -414,7 +417,7 @@ void KiranTitlebarWindowPrivate::initOtherWidget() + m_tittlebarSpliteLine->setFrameShape(QFrame::HLine); + m_tittlebarSpliteLine->setFrameShadow(QFrame::Sunken); + +- ///内容窗口包装 ++ /// 内容窗口包装 + m_windowContentWidgetWrapper = new QWidget(m_frame); + m_windowContentWidgetWrapper->setObjectName("KiranTitlebarContentWrapper"); + m_frameLayout->addWidget(m_windowContentWidgetWrapper); +@@ -461,47 +464,47 @@ CursorPositionEnums KiranTitlebarWindowPrivate::getCursorPosition(QPoint pos) + + void KiranTitlebarWindowPrivate::ensureShadowPixmapUpdated() + { +- if( !m_isCompositingManagerRunning ) ++ if (!m_isCompositingManagerRunning) + { + return; + } +- ++ + bool isActiveWindow = q_ptr->isActiveWindow(); + auto windowSize = q_ptr->size(); + auto windowRect = q_ptr->rect(); + +- if( ( isActiveWindow && (m_shadowActivePix.size() == windowSize) ) || +- ( !isActiveWindow && (m_shadowPix.size() == windowSize) ) ) ++ if ((isActiveWindow && (m_shadowActivePix.size() == windowSize)) || ++ (!isActiveWindow && (m_shadowPix.size() == windowSize))) + { +- //不需更新 ++ // 不需更新 + return; + } + + qDebug() << "update shadow pixmap..." << isActiveWindow << windowSize; + +- QPainterPath innerPath,outerPath; +- innerPath.addRoundedRect(windowRect.adjusted(shadowWidth,shadowWidth,-shadowWidth,-shadowWidth),radius,radius); +- outerPath.addRoundedRect(windowRect,radius,radius); ++ QPainterPath innerPath, outerPath; ++ innerPath.addRoundedRect(windowRect.adjusted(shadowWidth, shadowWidth, -shadowWidth, -shadowWidth), radius, radius); ++ outerPath.addRoundedRect(windowRect, radius, radius); + +- QImage img(windowSize,QImage::Format_ARGB32_Premultiplied); ++ QImage img(windowSize, QImage::Format_ARGB32_Premultiplied); + img.fill(0); + + QPainter imgPainter(&img); + imgPainter.setCompositionMode(QPainter::CompositionMode_Source); +- imgPainter.fillPath(innerPath,QBrush(Qt::white)); ++ imgPainter.fillPath(innerPath, QBrush(Qt::white)); + imgPainter.end(); + +- QImage blurredImg(img.size(),img.format()); ++ QImage blurredImg(img.size(), img.format()); + blurredImg.fill(0); + QPainter blurPainter(&blurredImg); +- qt_blurImage(&blurPainter,img,shadowRadius,false,true); ++ qt_blurImage(&blurPainter, img, shadowRadius, false, true); + blurPainter.end(); + + img = std::move(blurredImg); + + imgPainter.begin(&img); + imgPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); +- imgPainter.fillRect(img.rect(),isActiveWindow?shadowActiveColor:shadowInactiveColor); ++ imgPainter.fillRect(img.rect(), isActiveWindow ? shadowActiveColor : shadowInactiveColor); + imgPainter.end(); + + QPixmap pixmap(img.size()); +@@ -513,10 +516,10 @@ void KiranTitlebarWindowPrivate::ensureShadowPixmapUpdated() + + QPainter outputPainter(&pixmap); + outputPainter.setClipPath(clipPath); +- outputPainter.drawImage(img.rect(),img); ++ outputPainter.drawImage(img.rect(), img); + outputPainter.end(); + +- if( isActiveWindow ) ++ if (isActiveWindow) + { + m_shadowActivePix = pixmap; + } +@@ -532,7 +535,7 @@ void KiranTitlebarWindowPrivate::updateTitleFont(QFont font) + + bool KiranTitlebarWindowPrivate::eventFilter(QObject *obj, QEvent *event) + { +- //NOTE:用户标题栏暂时需要使用窗口管理器单独设置的字体,不和程序字体通用 ++ // NOTE:用户标题栏暂时需要使用窗口管理器单独设置的字体,不和程序字体通用 + if (obj == m_title && event->type() == QEvent::ApplicationFontChange) + { + return true; +@@ -546,9 +549,9 @@ bool KiranTitlebarWindowPrivate::eventFilter(QObject *obj, QEvent *event) + case QEvent::ShowToParent: + // 若在初始化时 createWinId 再调用下列方法设置属性,设置属性成功,但窗口管理器未能成功识别 + // 在接近显示时进行处理设置_GTK_FRAME_EXTENTS属性 +- if( m_isCompositingManagerRunning ) ++ if (m_isCompositingManagerRunning) + { +- int scaledShadowWidth = q_ptr->devicePixelRatio()*shadowWidth; ++ int scaledShadowWidth = q_ptr->devicePixelRatio() * shadowWidth; + XLibHelper::SetShadowWidth(QX11Info::display(), q_ptr->winId(), scaledShadowWidth, scaledShadowWidth, scaledShadowWidth, scaledShadowWidth); + } + break; +@@ -576,8 +579,8 @@ bool KiranTitlebarWindowPrivate::eventFilter(QObject *obj, QEvent *event) + case QEvent::StyleChange: + updateTitlebarButtonIcon(); + break; +- case QEvent::WindowStateChange: +- if( q_ptr->windowState() == Qt::WindowMaximized ) ++ case QEvent::WindowStateChange: ++ if (q_ptr->windowState() == Qt::WindowMaximized) + { + m_frame->setRadius(0); + } +-- +2.33.0 + diff --git a/kiran-widgets-qt5.spec b/kiran-widgets-qt5.spec index 034e1de..d75520c 100644 --- a/kiran-widgets-qt5.spec +++ b/kiran-widgets-qt5.spec @@ -1,6 +1,6 @@ Name: kiran-widgets-qt5 Version: 2.4.2 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Encapsulated QT Widget Summary(zh_CN): 封装的Qt小部件 @@ -8,6 +8,7 @@ License: MulanPSL-2.0 Source0: %{name}-%{version}.tar.gz Patch0000: 0000-fix-KiranPasswordEdit-default-password-input-does-no.patch +Patch0001: 0001-feat-KiranTitlebarWindow-Customize-title-bar-to-send.patch BuildRequires: cmake >= 3.5 BuildRequires: gcc-c++ @@ -78,6 +79,9 @@ make %{?_smp_mflags} rm -rf %{buildroot} %changelog +* Mon Jan 22 2024 liuxinhao - 2.4.2-3 +- KYOS-F: Customize title bar send requests to window manager and pop up a right-click menu(#24920) + * Thu Jan 18 2024 liuxinhao - 2.4.2-2.kb1 - KYOS-B: default password input does not provide clear text display function(#25230) @@ -216,4 +220,4 @@ rm -rf %{buildroot} - KYOS-F: Suitable for high DPI * Fri Sep 25 2020 liuxinhao - 2.0.0+alpha1 -- first build \ No newline at end of file +- first build -- Gitee