607 lines
24 KiB
Diff
607 lines
24 KiB
Diff
|
|
From c91b9ab12c19ea19171c63569064dc1a0e1c33bf Mon Sep 17 00:00:00 2001
|
|||
|
|
From: liuxinhao <liuxinhao@kylinsec.com.cn>
|
|||
|
|
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 <liuxinhao@kylinos.com.cn>
|
|||
|
|
*/
|
|||
|
|
-
|
|||
|
|
+
|
|||
|
|
#include "xlib-helper.h"
|
|||
|
|
|
|||
|
|
-#include <X11/Xlib.h>
|
|||
|
|
#include <X11/Xatom.h>
|
|||
|
|
-#include <unistd.h>
|
|||
|
|
+#include <X11/Xlib.h>
|
|||
|
|
#include <memory.h>
|
|||
|
|
+#include <unistd.h>
|
|||
|
|
+#include <QMap>
|
|||
|
|
|
|||
|
|
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<QString, Atom>& 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<QString, Atom> 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 <liuxinhao@kylinos.com.cn>
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
@@ -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 <liuxinhao@kylinos.com.cn>
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
@@ -30,21 +30,20 @@
|
|||
|
|
#include <QFontDatabase>
|
|||
|
|
#include <QGraphicsDropShadowEffect>
|
|||
|
|
#include <QMouseEvent>
|
|||
|
|
+#include <QPainter>
|
|||
|
|
+#include <QPainterPath>
|
|||
|
|
#include <QScreen>
|
|||
|
|
#include <QStyle>
|
|||
|
|
#include <QTimer>
|
|||
|
|
#include <QToolButton>
|
|||
|
|
#include <QWindow>
|
|||
|
|
-#include <QPainter>
|
|||
|
|
-#include <QPainterPath>
|
|||
|
|
-
|
|||
|
|
|
|||
|
|
-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
|
|||
|
|
|