Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-03-18 18:09:20 +08:00
parent ebc20e23b6
commit 4d277a5eac
24 changed files with 686 additions and 203 deletions

View File

@ -115,22 +115,32 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
}
const auto mouseEvent = static_cast<QMouseEvent *>(event);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPointF localPos = mouseEvent->position();
const QPointF scenePos = mouseEvent->scenePosition();
#else
const QPointF localPos = mouseEvent->windowPos();
const QPointF scenePos = mouseEvent->windowPos();
#endif
if (type == QEvent::MouseMove) {
const Qt::CursorShape cs = Utils::calculateCursorShape(window, localPos);
switch (type) {
case QEvent::MouseMove: {
const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos);
if (cs == Qt::ArrowCursor) {
window->unsetCursor();
} else {
window->setCursor(cs);
}
} else if (type == QEvent::MouseButtonPress) {
const Qt::Edges edges = Utils::calculateWindowEdges(window, localPos);
if (edges != Qt::Edges{}) {
Utils::startSystemResize(window, edges);
} break;
case QEvent::MouseButtonPress: {
if (mouseEvent->button() != Qt::LeftButton) {
return false;
}
const Qt::Edges edges = Utils::calculateWindowEdges(window, scenePos);
if (edges == Qt::Edges{}) {
return false;
}
Utils::startSystemResize(window, edges);
return true;
}
default:
break;
}
return false;
}

View File

@ -222,9 +222,6 @@
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>

View File

@ -25,6 +25,9 @@
#include "mainwindow.h"
#include "ui_MainWindow.h"
#include "ui_TitleBar.h"
#include <utils.h>
FRAMELESSHELPER_USE_NAMESPACE
MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : FramelessMainWindow(parent, flags)
{
@ -43,6 +46,14 @@ MainWindow::~MainWindow()
}
}
void MainWindow::changeEvent(QEvent *event)
{
FramelessMainWindow::changeEvent(event);
if (event->type() == QEvent::WindowStateChange) {
Q_EMIT windowStateChanged();
}
}
void MainWindow::setupUi()
{
mainWindow = new Ui::MainWindow;
@ -52,6 +63,12 @@ void MainWindow::setupUi()
titleBar = new Ui::TitleBar;
titleBar->setupUi(titleBarWidget);
const SystemTheme theme = SystemTheme::Light;
const ResourceType resource = ResourceType::Icon;
titleBar->minimizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Minimize, theme, resource)));
titleBar->maximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Maximize, theme, resource)));
titleBar->closeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Close, theme, resource)));
QMenuBar *mb = menuBar();
titleBar->horizontalLayout->insertWidget(1, mb);
@ -65,19 +82,18 @@ void MainWindow::setupUi()
setHitTestVisible(titleBar->closeButton, true);
connect(titleBar->minimizeButton, &QPushButton::clicked, this, &MainWindow::showMinimized);
connect(titleBar->maximizeButton, &QPushButton::clicked, this, [this](){
if (isZoomed()) {
showNormal();
} else {
showMaximized();
}
});
connect(titleBar->maximizeButton, &QPushButton::clicked, this, &MainWindow::toggleMaximized);
connect(titleBar->closeButton, &QPushButton::clicked, this, &MainWindow::close);
connect(this, &MainWindow::windowIconChanged, titleBar->iconButton, &QPushButton::setIcon);
connect(this, &MainWindow::windowTitleChanged, titleBar->titleLabel, &QLabel::setText);
connect(this, &MainWindow::windowStateChanged, this, [this](){
const bool zoomed = isZoomed();
titleBar->maximizeButton->setChecked(zoomed);
const SystemTheme theme = SystemTheme::Light;
const SystemButtonType button = (zoomed ? SystemButtonType::Restore : SystemButtonType::Maximize);
const ResourceType resource = ResourceType::Icon;
titleBar->maximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(button, theme, resource)));
titleBar->maximizeButton->setToolTip(zoomed ? tr("Restore") : tr("Maximize"));
});
setWindowTitle(tr("Hello, World! - Qt MainWindow"));
}

View File

@ -41,6 +41,9 @@ public:
explicit MainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {});
~MainWindow() override;
protected:
void changeEvent(QEvent *event) override;
private:
void setupUi();

View File

@ -26,7 +26,7 @@
#include <QtQml/qqmlapplicationengine.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuickControls2/qquickstyle.h>
#include <framelessquickhelper.h>
#include <framelesshelper_quick.h>
FRAMELESSHELPER_USE_NAMESPACE
@ -60,7 +60,7 @@ int main(int argc, char *argv[])
QQuickStyle::setStyle(QStringLiteral("Default"));
#endif
FramelessQuickHelper::registerTypes(&engine);
FramelessHelper::Quick::registerTypes(&engine);
const QUrl homepageUrl(QStringLiteral("qrc:///qml/MainWindow.qml"));
const QMetaObject::Connection connection = QObject::connect(

View File

@ -67,33 +67,12 @@ Window {
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
anchors.rightMargin: 30 * 1.5 * 3
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
onClicked: {
if (mouse.button === Qt.RightButton) {
FramelessUtils.showSystemMenu(window, Qt.point(mouse.x, mouse.y));
}
}
onDoubleClicked: {
if (mouse.button === Qt.LeftButton) {
maximizeButton.clicked();
}
}
onPositionChanged: {
if (containsPress && (window.visibility !== Window.FullScreen)) {
FramelessUtils.startSystemMove2(window);
}
}
}
Row {
anchors.top: parent.top
anchors.right: parent.right
MinimizeButton {
id: minimizeButton
onClicked: FramelessUtils.showMinimized2(window)
}
@ -110,6 +89,7 @@ Window {
}
CloseButton {
id: closeButton
onClicked: window.close()
}
}
@ -136,5 +116,11 @@ Window {
color: window.active ? FramelessUtils.frameBorderActiveColor : FramelessUtils.frameBorderInactiveColor
}
Component.onCompleted: FramelessHelper.addWindow(window)
Component.onCompleted: {
FramelessHelper.addWindow(window);
FramelessHelper.setTitleBarItem(window, titleBar);
FramelessHelper.setHitTestVisible(window, minimizeButton, true);
FramelessHelper.setHitTestVisible(window, maximizeButton, true);
FramelessHelper.setHitTestVisible(window, closeButton, true);
}
}

View File

@ -30,11 +30,11 @@
FRAMELESSHELPER_USE_NAMESPACE
Widget::Widget(QWidget *parent) : FramelessWidget(parent)
Widget::Widget(QWidget *parent) : FramelessWidget(parent, WindowLayout::Standard)
{
setupUi();
connect(this, &Widget::systemThemeChanged, this, &Widget::updateStyleSheet);
startTimer(500);
connect(this, &Widget::systemThemeChanged, this, &Widget::updateStyleSheet);
}
Widget::~Widget() = default;

View File

@ -8,6 +8,10 @@ set(SOURCES
framelessquickutils.cpp
framelesshelperimageprovider.h
framelesshelperimageprovider.cpp
framelessquickeventfilter.h
framelessquickeventfilter.cpp
framelesshelper_quick.h
framelesshelper_quick.cpp
)
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)

View File

@ -0,0 +1,54 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "framelesshelper_quick.h"
#include <QtQml/qqmlengine.h>
#include "framelesshelperimageprovider.h"
#include "framelessquickhelper.h"
#include "framelessquickutils.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
static constexpr const char FRAMELESSHELPER_QUICK_URI[] = "org.wangwenx190.FramelessHelper";
void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
{
Q_ASSERT(engine);
if (!engine) {
return;
}
engine->addImageProvider(QStringLiteral("framelesshelper"), new FramelessHelperImageProvider);
qmlRegisterSingletonType<FramelessQuickHelper>(FRAMELESSHELPER_QUICK_URI, 1, 0, "FramelessHelper", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new FramelessQuickHelper;
});
qmlRegisterSingletonType<FramelessQuickUtils>(FRAMELESSHELPER_QUICK_URI, 1, 0, "FramelessUtils", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new FramelessQuickUtils;
});
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,42 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include "framelesshelperquick_global.h"
QT_BEGIN_NAMESPACE
class QQmlEngine;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
namespace FramelessHelper::Quick
{
FRAMELESSHELPER_QUICK_API void registerTypes(QQmlEngine *engine);
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -94,7 +94,7 @@ QPixmap FramelessHelperImageProvider::requestPixmap(const QString &id, QSize *si
if (!pixmapVar.isValid()) {
return {};
}
if (static_cast<QMetaType::Type>(pixmapVar.typeId()) != QMetaType::QPixmap) {
if (static_cast<QMetaType::Type>(pixmapVar.userType()) != QMetaType::QPixmap) {
return {};
}
if (size) {

View File

@ -31,14 +31,16 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
class FRAMELESSHELPER_QUICK_API FramelessHelperImageProvider : public QQuickImageProvider
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
Q_OBJECT
#endif
Q_DISABLE_COPY_MOVE(FramelessHelperImageProvider)
public:
explicit FramelessHelperImageProvider();
~FramelessHelperImageProvider() override;
Q_NODISCARD QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize) override;
Q_NODISCARD QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,252 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "framelessquickeventfilter.h"
#include <QtCore/qmutex.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuick/qquickitem.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
struct EventFilterDataInternal
{
QQuickWindow *window = nullptr;
FramelessQuickEventFilter *eventFilter = nullptr;
QQuickItem *titleBarItem = nullptr;
QList<QQuickItem *> hitTestVisibleItems = {};
};
struct EventFilterData
{
QMutex mutex = {};
QHash<QQuickWindow *, EventFilterDataInternal> data = {};
explicit EventFilterData() = default;
~EventFilterData() = default;
private:
Q_DISABLE_COPY_MOVE(EventFilterData)
};
Q_GLOBAL_STATIC(EventFilterData, g_data)
[[nodiscard]] static inline bool isInTitleBarDraggableArea(QQuickWindow *window, const QPointF &pos)
{
Q_ASSERT(window);
if (!window) {
return false;
}
g_data()->mutex.lock();
if (!g_data()->data.contains(window)) {
g_data()->mutex.unlock();
return false;
}
const EventFilterDataInternal data = g_data()->data.value(window);
g_data()->mutex.unlock();
if (!data.titleBarItem) {
return false;
}
const auto mapGeometryToScene = [](const QQuickItem * const item) -> QRectF {
Q_ASSERT(item);
if (!item) {
return {};
}
return QRectF(item->mapToScene(QPointF(0.0, 0.0)), item->size());
};
QRegion region = mapGeometryToScene(data.titleBarItem).toRect();
if (!data.hitTestVisibleItems.isEmpty()) {
for (auto &&item : qAsConst(data.hitTestVisibleItems)) {
Q_ASSERT(item);
if (item) {
region -= mapGeometryToScene(item).toRect();
}
}
}
return region.contains(pos.toPoint());
}
FramelessQuickEventFilter::FramelessQuickEventFilter(QObject *parent) : QObject(parent) {}
FramelessQuickEventFilter::~FramelessQuickEventFilter() = default;
void FramelessQuickEventFilter::addWindow(QQuickWindow *window)
{
Q_ASSERT(window);
if (!window) {
return;
}
g_data()->mutex.lock();
if (g_data()->data.contains(window)) {
g_data()->mutex.unlock();
return;
}
auto data = EventFilterDataInternal{};
data.window = window;
data.eventFilter = new FramelessQuickEventFilter(window);
g_data()->data.insert(window, data);
g_data()->mutex.unlock();
window->installEventFilter(data.eventFilter);
}
void FramelessQuickEventFilter::removeWindow(QQuickWindow *window)
{
Q_ASSERT(window);
if (!window) {
return;
}
g_data()->mutex.lock();
if (!g_data()->data.contains(window)) {
g_data()->mutex.unlock();
return;
}
const EventFilterDataInternal data = g_data()->data.value(window);
g_data()->data.remove(window);
g_data()->mutex.unlock();
window->removeEventFilter(data.eventFilter);
delete data.eventFilter;
}
void FramelessQuickEventFilter::setTitleBarItem(QQuickWindow *window, QQuickItem *item)
{
Q_ASSERT(window);
Q_ASSERT(item);
if (!window || !item) {
return;
}
QMutexLocker locker(&g_data()->mutex);
if (!g_data()->data.contains(window)) {
return;
}
g_data()->data[window].titleBarItem = item;
}
void FramelessQuickEventFilter::setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible)
{
Q_ASSERT(window);
Q_ASSERT(item);
if (!window || !item) {
return;
}
QMutexLocker locker(&g_data()->mutex);
if (!g_data()->data.contains(window)) {
return;
}
auto &items = g_data()->data[window].hitTestVisibleItems;
const bool exists = items.contains(item);
if (visible && !exists) {
items.append(item);
}
if (!visible && exists) {
items.removeAll(item);
}
}
bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
{
Q_ASSERT(object);
Q_ASSERT(event);
if (!object || !event) {
return false;
}
if (!object->isWindowType()) {
return false;
}
const auto window = qobject_cast<QQuickWindow *>(object);
if (!window) {
return false;
}
g_data()->mutex.lock();
if (!g_data()->data.contains(window)) {
g_data()->mutex.unlock();
return false;
}
g_data()->mutex.unlock();
const QEvent::Type eventType = event->type();
if ((eventType != QEvent::MouseButtonPress)
&& (eventType != QEvent::MouseButtonRelease) && (eventType != QEvent::MouseButtonDblClick)) {
return false;
}
const auto mouseEvent = static_cast<QMouseEvent *>(event);
const Qt::MouseButton button = mouseEvent->button();
if ((button != Qt::LeftButton) && (button != Qt::RightButton)) {
return false;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPointF scenePos = mouseEvent->scenePosition();
#else
const QPointF scenePos = mouseEvent->windowPos();
#endif
const bool titleBar = isInTitleBarDraggableArea(window, scenePos);
switch (eventType) {
case QEvent::MouseButtonPress: {
if (button != Qt::LeftButton) {
return false;
}
if (!titleBar) {
return false;
}
Utils::startSystemMove(window);
return true;
}
case QEvent::MouseButtonRelease: {
if (button != Qt::RightButton) {
return false;
}
if (!titleBar) {
return false;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPointF globalPos = mouseEvent->globalPosition();
#else
const QPointF globalPos = mouseEvent->globalPos();
#endif
const QPointF nativePos = QPointF(globalPos * window->effectiveDevicePixelRatio());
Utils::showSystemMenu(window->winId(), nativePos);
return true;
}
case QEvent::MouseButtonDblClick: {
if (button != Qt::LeftButton) {
return false;
}
if (!titleBar) {
return false;
}
const QQuickWindow::Visibility visibility = window->visibility();
if ((visibility == QQuickWindow::Maximized) || (visibility == QQuickWindow::FullScreen)) {
window->showNormal();
} else {
window->showMaximized();
}
return true;
}
default:
break;
}
return false;
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,55 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include "framelesshelperquick_global.h"
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
class QQuickWindow;
class QQuickItem;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
class FRAMELESSHELPER_QUICK_API FramelessQuickEventFilter : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(FramelessQuickEventFilter)
public:
explicit FramelessQuickEventFilter(QObject *parent = nullptr);
~FramelessQuickEventFilter() override;
Q_INVOKABLE static void addWindow(QQuickWindow *window);
Q_INVOKABLE static void removeWindow(QQuickWindow *window);
Q_INVOKABLE static void setTitleBarItem(QQuickWindow *window, QQuickItem *item);
Q_INVOKABLE static void setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible);
protected:
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -23,56 +23,54 @@
*/
#include "framelessquickhelper.h"
#include <QtQml/qqmlengine.h>
#include "framelesshelperimageprovider.h"
#include "framelessquickutils.h"
#include <QtQuick/qquickwindow.h>
#include <framelesswindowsmanager.h>
#include "framelessquickeventfilter.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
static constexpr const char FRAMELESSHELPER_QUICK_URI[] = "org.wangwenx190.FramelessHelper";
FramelessQuickHelper::FramelessQuickHelper(QObject *parent) : QObject(parent) {}
FramelessQuickHelper::~FramelessQuickHelper() = default;
void FramelessQuickHelper::registerTypes(QQmlEngine *engine)
{
Q_ASSERT(engine);
if (!engine) {
return;
}
engine->addImageProvider(QStringLiteral("framelesshelper"), new FramelessHelperImageProvider);
qmlRegisterSingletonType<FramelessQuickHelper>(FRAMELESSHELPER_QUICK_URI, 1, 0, "FramelessHelper", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
const auto framelessHelper = new FramelessQuickHelper;
return framelessHelper;
});
qmlRegisterSingletonType<FramelessQuickUtils>(FRAMELESSHELPER_QUICK_URI, 1, 0, "FramelessUtils", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
const auto framelessUtils = new FramelessQuickUtils;
return framelessUtils;
});
}
void FramelessQuickHelper::addWindow(QWindow *window)
void FramelessQuickHelper::addWindow(QQuickWindow *window)
{
Q_ASSERT(window);
if (!window) {
return;
}
FramelessWindowsManager::instance()->addWindow(window);
FramelessQuickEventFilter::addWindow(window);
}
void FramelessQuickHelper::removeWindow(QWindow *window)
void FramelessQuickHelper::removeWindow(QQuickWindow *window)
{
Q_ASSERT(window);
if (!window) {
return;
}
FramelessQuickEventFilter::removeWindow(window);
FramelessWindowsManager::instance()->removeWindow(window);
}
void FramelessQuickHelper::setTitleBarItem(QQuickWindow *window, QQuickItem *item)
{
Q_ASSERT(window);
Q_ASSERT(item);
if (!window || !item) {
return;
}
FramelessQuickEventFilter::setTitleBarItem(window, item);
}
void FramelessQuickHelper::setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible)
{
Q_ASSERT(window);
Q_ASSERT(item);
if (!window || !item) {
return;
}
FramelessQuickEventFilter::setHitTestVisible(window, item, visible);
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -28,8 +28,8 @@
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
class QWindow;
class QQmlEngine;
class QQuickWindow;
class QQuickItem;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -49,10 +49,10 @@ public:
explicit FramelessQuickHelper(QObject *parent = nullptr);
~FramelessQuickHelper() override;
Q_INVOKABLE static void registerTypes(QQmlEngine *engine);
Q_INVOKABLE static void addWindow(QWindow *window);
Q_INVOKABLE static void removeWindow(QWindow *window);
Q_INVOKABLE static void addWindow(QQuickWindow *window);
Q_INVOKABLE static void removeWindow(QQuickWindow *window);
Q_INVOKABLE static void setTitleBarItem(QQuickWindow *window, QQuickItem *item);
Q_INVOKABLE static void setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible);
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -23,6 +23,7 @@
*/
#include "framelessquickutils.h"
#include <QtQuick/qquickwindow.h>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))
# include <QtGui/qpa/qplatformtheme.h>
# include <QtGui/private/qguiapplication_p.h>
@ -119,7 +120,7 @@ bool FramelessQuickUtils::titleBarColorVisible()
#endif
}
void FramelessQuickUtils::showMinimized2(QWindow *window)
void FramelessQuickUtils::showMinimized2(QQuickWindow *window)
{
Q_ASSERT(window);
if (!window) {
@ -136,7 +137,7 @@ void FramelessQuickUtils::showMinimized2(QWindow *window)
#endif
}
void FramelessQuickUtils::showSystemMenu(QWindow *window, const QPointF &pos)
void FramelessQuickUtils::showSystemMenu(QQuickWindow *window, const QPointF &pos)
{
Q_ASSERT(window);
if (!window) {
@ -144,15 +145,16 @@ void FramelessQuickUtils::showSystemMenu(QWindow *window, const QPointF &pos)
}
#ifdef Q_OS_WINDOWS
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPointF globalPos = window->mapToGlobal(pos) * window->devicePixelRatio();
const QPointF globalPos = window->mapToGlobal(pos);
# else
const QPointF globalPos = QPointF(window->mapToGlobal(pos.toPoint())) * window->devicePixelRatio();
const QPointF globalPos = window->mapToGlobal(pos.toPoint());
# endif
Utils::showSystemMenu(window->winId(), globalPos);
const QPointF nativePos = QPointF(globalPos * window->effectiveDevicePixelRatio());
Utils::showSystemMenu(window->winId(), nativePos);
#endif
}
void FramelessQuickUtils::startSystemMove2(QWindow *window)
void FramelessQuickUtils::startSystemMove2(QQuickWindow *window)
{
Q_ASSERT(window);
if (!window) {
@ -165,7 +167,7 @@ void FramelessQuickUtils::startSystemMove2(QWindow *window)
#endif
}
void FramelessQuickUtils::startSystemResize2(QWindow *window, const Qt::Edges edges)
void FramelessQuickUtils::startSystemResize2(QQuickWindow *window, const Qt::Edges edges)
{
Q_ASSERT(window);
if (!window) {

View File

@ -29,7 +29,7 @@
#include <QtGui/qcolor.h>
QT_BEGIN_NAMESPACE
class QWindow;
class QQuickWindow;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -66,10 +66,10 @@ public:
Q_NODISCARD static QColor systemAccentColor();
Q_NODISCARD static bool titleBarColorVisible();
Q_INVOKABLE static void showMinimized2(QWindow *window);
Q_INVOKABLE static void showSystemMenu(QWindow *window, const QPointF &pos);
Q_INVOKABLE static void startSystemMove2(QWindow *window);
Q_INVOKABLE static void startSystemResize2(QWindow *window, const Qt::Edges edges);
Q_INVOKABLE static void showMinimized2(QQuickWindow *window);
Q_INVOKABLE static void showSystemMenu(QQuickWindow *window, const QPointF &pos);
Q_INVOKABLE static void startSystemMove2(QQuickWindow *window);
Q_INVOKABLE static void startSystemResize2(QQuickWindow *window, const Qt::Edges edges);
Q_SIGNALS:
void frameBorderActiveColorChanged();

View File

@ -29,8 +29,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
FramelessMainWindow::FramelessMainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags)
{
m_helper.reset(new FramelessWidgetsHelper(this, this));
m_helper->initialize();
m_helper.reset(new FramelessWidgetsHelper(this, WindowLayout::Custom));
}
FramelessMainWindow::~FramelessMainWindow() = default;
@ -60,6 +59,11 @@ void FramelessMainWindow::setHitTestVisible(QWidget *widget, const bool visible)
m_helper->setHitTestVisible(widget, visible);
}
void FramelessMainWindow::toggleMaximized()
{
m_helper->toggleMaximized();
}
void FramelessMainWindow::showEvent(QShowEvent *event)
{
QMainWindow::showEvent(event);
@ -84,6 +88,12 @@ void FramelessMainWindow::mousePressEvent(QMouseEvent *event)
m_helper->mousePressEventHandler(event);
}
void FramelessMainWindow::mouseReleaseEvent(QMouseEvent *event)
{
QMainWindow::mouseReleaseEvent(event);
m_helper->mouseReleaseEventHandler(event);
}
void FramelessMainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
QMainWindow::mouseDoubleClickEvent(event);

View File

@ -38,23 +38,25 @@ class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow
Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL)
public:
explicit FramelessMainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {},
const WindowLayout wl = WindowLayout::Standard);
explicit FramelessMainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {});
~FramelessMainWindow() override;
Q_NODISCARD bool isNormal() const;
Q_NODISCARD bool isZoomed() const;
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
Q_NODISCARD Q_INVOKABLE bool isZoomed() const;
void setTitleBarWidget(QWidget *widget);
Q_NODISCARD QWidget *titleBarWidget() const;
Q_INVOKABLE void setHitTestVisible(QWidget *widget, const bool visible);
Q_INVOKABLE void toggleMaximized();
protected:
void showEvent(QShowEvent *event) override;
void changeEvent(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
Q_SIGNALS:

View File

@ -27,10 +27,9 @@
FRAMELESSHELPER_BEGIN_NAMESPACE
FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
FramelessWidget::FramelessWidget(QWidget *parent, const WindowLayout wl) : QWidget(parent)
{
m_helper.reset(new FramelessWidgetsHelper(this, this));
m_helper->initialize();
m_helper.reset(new FramelessWidgetsHelper(this, wl));
}
FramelessWidget::~FramelessWidget() = default;
@ -70,6 +69,11 @@ void FramelessWidget::setHitTestVisible(QWidget *widget, const bool visible)
m_helper->setHitTestVisible(widget, visible);
}
void FramelessWidget::toggleMaximized()
{
m_helper->toggleMaximized();
}
void FramelessWidget::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
@ -94,6 +98,12 @@ void FramelessWidget::mousePressEvent(QMouseEvent *event)
m_helper->mousePressEventHandler(event);
}
void FramelessWidget::mouseReleaseEvent(QMouseEvent *event)
{
QWidget::mouseReleaseEvent(event);
m_helper->mouseReleaseEventHandler(event);
}
void FramelessWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
QWidget::mouseDoubleClickEvent(event);

View File

@ -42,8 +42,8 @@ public:
explicit FramelessWidget(QWidget *parent = nullptr, const WindowLayout wl = WindowLayout::Standard);
~FramelessWidget() override;
Q_NODISCARD bool isNormal() const;
Q_NODISCARD bool isZoomed() const;
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
Q_NODISCARD Q_INVOKABLE bool isZoomed() const;
void setTitleBarWidget(QWidget *widget);
Q_NODISCARD QWidget *titleBarWidget() const;
@ -53,11 +53,14 @@ public:
Q_INVOKABLE void setHitTestVisible(QWidget *widget, const bool visible);
Q_INVOKABLE void toggleMaximized();
protected:
void showEvent(QShowEvent *event) override;
void changeEvent(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
Q_SIGNALS:

View File

@ -34,8 +34,6 @@
FRAMELESSHELPER_BEGIN_NAMESPACE
static constexpr const char QT_MAINWINDOW_CLASS_NAME[] = "QMainWindow";
static const QString kSystemButtonStyleSheet = QStringLiteral(R"(
QPushButton {
border-style: none;
@ -82,18 +80,19 @@ void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
if (m_userTitleBarWidget == widget) {
return;
}
if (isStandardLayout()) {
if (m_systemTitleBarWidget && m_systemTitleBarWidget->isVisible()) {
m_mainLayout->removeWidget(m_systemTitleBarWidget);
m_systemTitleBarWidget->hide();
}
if (isMainWindow()) {
m_userTitleBarWidget = widget;
} else {
if (m_userTitleBarWidget) {
m_mainLayout->removeWidget(m_userTitleBarWidget);
m_userTitleBarWidget = nullptr;
}
m_userTitleBarWidget = widget;
m_mainLayout->insertWidget(0, m_userTitleBarWidget);
} else {
m_userTitleBarWidget = widget;
}
QMetaObject::invokeMethod(q, "titleBarWidgetChanged");
}
@ -109,7 +108,7 @@ void FramelessWidgetsHelper::setContentWidget(QWidget *widget)
if (!widget) {
return;
}
if (isMainWindow()) {
if (isCustomLayout()) {
return;
}
if (m_userContentWidget == widget) {
@ -126,9 +125,6 @@ void FramelessWidgetsHelper::setContentWidget(QWidget *widget)
QWidget *FramelessWidgetsHelper::contentWidget() const
{
if (isMainWindow()) {
return nullptr;
}
return m_userContentWidget;
}
@ -149,33 +145,46 @@ void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visib
void FramelessWidgetsHelper::showEventHandler(QShowEvent *event)
{
Q_UNUSED(event);
Q_ASSERT(event);
if (!event) {
return;
}
setupFramelessHelperOnce();
}
void FramelessWidgetsHelper::changeEventHandler(QEvent *event)
{
bool shouldUpdate = false;
if (event->type() == QEvent::WindowStateChange) {
Q_ASSERT(event);
if (!event) {
return;
}
const QEvent::Type type = event->type();
if ((type != QEvent::WindowStateChange) && (type != QEvent::ActivationChange)) {
return;
}
if (type == QEvent::WindowStateChange) {
if (isStandardLayout()) {
if (isZoomed()) {
m_systemMaximizeButton->setToolTip(tr("Restore"));
} else {
m_systemMaximizeButton->setToolTip(tr("Maximize"));
}
updateContentsMargins();
updateSystemButtonsIcon();
shouldUpdate = true;
} else if (event->type() == QEvent::ActivationChange) {
shouldUpdate = true;
}
if (shouldUpdate) {
updateContentsMargins();
}
if (isStandardLayout()) {
updateSystemTitleBarStyleSheet();
}
q->update();
}
void FramelessWidgetsHelper::paintEventHandler(QPaintEvent *event)
{
Q_UNUSED(event);
Q_ASSERT(event);
if (!event) {
return;
}
if (!shouldDrawFrameBorder()) {
return;
}
@ -191,39 +200,63 @@ void FramelessWidgetsHelper::paintEventHandler(QPaintEvent *event)
void FramelessWidgetsHelper::mousePressEventHandler(QMouseEvent *event)
{
const Qt::MouseButton button = event->button();
if ((button != Qt::LeftButton) && (button != Qt::RightButton)) {
Q_ASSERT(event);
if (!event) {
return;
}
if (event->button() != Qt::LeftButton) {
return;
}
if (!isInTitleBarDraggableArea(event->pos())) {
return;
}
if (isInTitleBarDraggableArea(event->pos())) {
if (button == Qt::LeftButton) {
Utils::startSystemMove(q->windowHandle());
} else {
}
void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
if (event->button() != Qt::RightButton) {
return;
}
if (!isInTitleBarDraggableArea(event->pos())) {
return;
}
#ifdef Q_OS_WINDOWS
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPointF globalPos = event->globalPosition();
# else
const QPointF globalPos = event->globalPos();
# endif
const QPointF pos = globalPos * q->devicePixelRatioF();
Utils::showSystemMenu(q->winId(), pos);
const QPointF nativePos = QPointF(globalPos * q->devicePixelRatioF());
Utils::showSystemMenu(q->winId(), nativePos);
#endif
}
}
}
void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
if (event->button() != Qt::LeftButton) {
return;
}
if (isInTitleBarDraggableArea(event->pos())) {
m_systemMaximizeButton->click();
if (!isInTitleBarDraggableArea(event->pos())) {
return;
}
toggleMaximized();
}
void FramelessWidgetsHelper::initialize()
{
if (m_initialized) {
return;
}
m_initialized = true;
q->setAttribute(Qt::WA_DontCreateNativeAncestors);
q->createWinId();
setupInitialUi();
@ -231,15 +264,18 @@ void FramelessWidgetsHelper::initialize()
void FramelessWidgetsHelper::setupFramelessHelperOnce()
{
if (m_framelessHelperInited) {
if (m_framelessHelperSetup) {
return;
}
m_framelessHelperInited = true;
m_framelessHelperSetup = true;
FramelessWindowsManager *manager = FramelessWindowsManager::instance();
manager->addWindow(q->windowHandle());
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this](){
if (isStandardLayout()) {
updateSystemTitleBarStyleSheet();
updateSystemButtonsIcon();
q->update();
}
QMetaObject::invokeMethod(q, "systemThemeChanged");
});
connect(manager, &FramelessWindowsManager::systemMenuRequested, this, [this](const QPointF &pos){
@ -249,7 +285,7 @@ void FramelessWidgetsHelper::setupFramelessHelperOnce()
void FramelessWidgetsHelper::createSystemTitleBar()
{
if (isCustomWindow()) {
if (isCustomLayout()) {
return;
}
m_systemTitleBarWidget = new QWidget(q);
@ -271,14 +307,7 @@ void FramelessWidgetsHelper::createSystemTitleBar()
m_systemMaximizeButton->setFixedSize(kDefaultSystemButtonSize);
m_systemMaximizeButton->setIconSize(kDefaultSystemButtonIconSize);
m_systemMaximizeButton->setToolTip(tr("Maximize"));
connect(m_systemMaximizeButton, &QPushButton::clicked, this, [this](){
if (isZoomed()) {
q->showNormal();
} else {
q->showMaximized();
}
updateSystemButtonsIcon();
});
connect(m_systemMaximizeButton, &QPushButton::clicked, this, &FramelessWidgetsHelper::toggleMaximized);
m_systemCloseButton = new QPushButton(m_systemTitleBarWidget);
m_systemCloseButton->setFixedSize(kDefaultSystemButtonSize);
m_systemCloseButton->setIconSize(kDefaultSystemButtonIconSize);
@ -299,7 +328,7 @@ void FramelessWidgetsHelper::createSystemTitleBar()
void FramelessWidgetsHelper::createUserContentContainer()
{
if (isCustomWindow() || isMainWindow()) {
if (isCustomLayout()) {
return;
}
m_userContentContainerWidget = new QWidget(q);
@ -312,11 +341,8 @@ void FramelessWidgetsHelper::createUserContentContainer()
void FramelessWidgetsHelper::setupInitialUi()
{
if (isStandardWindow()) {
if (isStandardLayout()) {
createSystemTitleBar();
if (isMainWindow()) {
// ### TODO
} else {
createUserContentContainer();
m_mainLayout = new QVBoxLayout(q);
m_mainLayout->setContentsMargins(0, 0, 0, 0);
@ -324,8 +350,8 @@ void FramelessWidgetsHelper::setupInitialUi()
m_mainLayout->addWidget(m_systemTitleBarWidget);
m_mainLayout->addWidget(m_userContentContainerWidget);
q->setLayout(m_mainLayout);
}
updateSystemTitleBarStyleSheet();
q->update();
}
updateContentsMargins();
}
@ -333,23 +359,30 @@ void FramelessWidgetsHelper::setupInitialUi()
bool FramelessWidgetsHelper::isInTitleBarDraggableArea(const QPoint &pos) const
{
const QRegion draggableRegion = [this]() -> QRegion {
const auto mapGeometryToScene = [this](const QWidget * const widget) -> QRect {
Q_ASSERT(widget);
if (!widget) {
return {};
}
return QRect(widget->mapTo(q, QPoint(0, 0)), widget->size());
};
if (m_userTitleBarWidget) {
QRegion region = {QRect(QPoint(0, 0), m_userTitleBarWidget->size())};
QRegion region = mapGeometryToScene(m_userTitleBarWidget);
if (!m_hitTestVisibleWidgets.isEmpty()) {
for (auto &&widget : qAsConst(m_hitTestVisibleWidgets)) {
Q_ASSERT(widget);
if (widget) {
region -= widget->geometry();
region -= mapGeometryToScene(widget);
}
}
}
return region;
}
if (isStandardWindow()) {
QRegion region = {QRect(QPoint(0, 0), m_systemTitleBarWidget->size())};
region -= m_systemMinimizeButton->geometry();
region -= m_systemMaximizeButton->geometry();
region -= m_systemCloseButton->geometry();
if (isStandardLayout()) {
QRegion region = mapGeometryToScene(m_systemTitleBarWidget);
region -= mapGeometryToScene(m_systemMinimizeButton);
region -= mapGeometryToScene(m_systemMaximizeButton);
region -= mapGeometryToScene(m_systemCloseButton);
return region;
}
return {};
@ -366,20 +399,12 @@ bool FramelessWidgetsHelper::shouldDrawFrameBorder() const
#endif
}
bool FramelessWidgetsHelper::isMainWindow() const
{
if (!q) {
return false;
}
return q->inherits(QT_MAINWINDOW_CLASS_NAME);
}
bool FramelessWidgetsHelper::isStandardWindow() const
bool FramelessWidgetsHelper::isStandardLayout() const
{
return (m_windowLayout == WindowLayout::Standard);
}
bool FramelessWidgetsHelper::isCustomWindow()
bool FramelessWidgetsHelper::isCustomLayout() const
{
return (m_windowLayout == WindowLayout::Custom);
}
@ -393,7 +418,7 @@ void FramelessWidgetsHelper::updateContentsMargins()
void FramelessWidgetsHelper::updateSystemTitleBarStyleSheet()
{
if (isCustomWindow()) {
if (isCustomLayout()) {
return;
}
const bool active = q->isActiveWindow();
@ -424,22 +449,31 @@ void FramelessWidgetsHelper::updateSystemTitleBarStyleSheet()
m_systemMaximizeButton->setStyleSheet(kSystemButtonStyleSheet);
m_systemCloseButton->setStyleSheet(kSystemButtonStyleSheet);
m_systemTitleBarWidget->setStyleSheet(QStringLiteral("background-color: %1;").arg(systemTitleBarWidgetBackgroundColor.name()));
q->update();
}
void FramelessWidgetsHelper::updateSystemButtonsIcon()
{
if (isCustomWindow()) {
if (isCustomLayout()) {
return;
}
const SystemTheme theme = ((Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()) ? SystemTheme::Dark : SystemTheme::Light);
m_systemMinimizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Minimize, theme, ResourceType::Icon)));
const ResourceType resource = ResourceType::Icon;
m_systemMinimizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Minimize, theme, resource)));
if (isZoomed()) {
m_systemMaximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Restore, theme, ResourceType::Icon)));
m_systemMaximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Restore, theme, resource)));
} else {
m_systemMaximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Maximize, theme, ResourceType::Icon)));
m_systemMaximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Maximize, theme, resource)));
}
m_systemCloseButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Close, theme, resource)));
}
void FramelessWidgetsHelper::toggleMaximized()
{
if (isZoomed()) {
q->showNormal();
} else {
q->showMaximized();
}
m_systemCloseButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Close, theme, ResourceType::Icon)));
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -59,11 +59,14 @@ public:
Q_INVOKABLE void setHitTestVisible(QWidget *widget, const bool visible);
void showEventHandler(QShowEvent *event);
void changeEventHandler(QEvent *event);
void paintEventHandler(QPaintEvent *event);
void mousePressEventHandler(QMouseEvent *event);
void mouseDoubleClickEventHandler(QMouseEvent *event);
Q_INVOKABLE void toggleMaximized();
Q_INVOKABLE void showEventHandler(QShowEvent *event);
Q_INVOKABLE void changeEventHandler(QEvent *event);
Q_INVOKABLE void paintEventHandler(QPaintEvent *event);
Q_INVOKABLE void mousePressEventHandler(QMouseEvent *event);
Q_INVOKABLE void mouseReleaseEventHandler(QMouseEvent *event);
Q_INVOKABLE void mouseDoubleClickEventHandler(QMouseEvent *event);
private:
void initialize();
@ -73,9 +76,8 @@ private:
void setupInitialUi();
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
Q_NODISCARD bool shouldDrawFrameBorder() const;
Q_NODISCARD bool isMainWindow() const;
Q_NODISCARD bool isStandardWindow() const;
Q_NODISCARD bool isCustomWindow();
Q_NODISCARD bool isStandardLayout() const;
Q_NODISCARD bool isCustomLayout() const;
private Q_SLOTS:
void updateContentsMargins();
@ -84,7 +86,8 @@ private Q_SLOTS:
private:
QWidget *q = nullptr;
bool m_framelessHelperInited = false;
bool m_initialized = false;
bool m_framelessHelperSetup = false;
WindowLayout m_windowLayout = WindowLayout::Standard;
QWidget *m_systemTitleBarWidget = nullptr;
QLabel *m_systemWindowTitleLabel = nullptr;