Refactor the Quick implementation, interface is now simpler
Now we use attached properties instead, it make things simpler. Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
d6fa6a163e
commit
306ebfc717
|
@ -6,8 +6,9 @@
|
|||
- Quick: Restored some 1.x interfaces which may be convenient for Qt Quick users.
|
||||
- Examples: Added QtWebEngine based demo projects for both Qt Widgets and Qt Quick.
|
||||
- Common: Added cross-platform customizable system menu for both Qt Widgets and Qt Quick. Also supports both light and dark theme.
|
||||
- Common: Removed bundled Qt internal classes that are licensed under Commercial/GPL/LGPL. This library is now pure MIT licensed.
|
||||
- Common: Bug fix and internal refactoring, improved stability on all supported platforms.
|
||||
- Misc: Removed bundled Qt internal classes that are licensed under Commercial/GPL/LGPL. This library is now pure MIT licensed.
|
||||
- Misc: Migrate to categorized logging output.
|
||||
- Misc: Bug fixes and internal refactorings, improved stability on all supported platforms.
|
||||
|
||||
## Highlights compared to 1.x
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity type="win32" name="org.wangwenx190.framelesshelper.demo" version="1.0.0.0"/>
|
||||
<description>FramelessHelper Demo</description>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||
|
@ -39,6 +40,8 @@
|
|||
</trustInfo>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 Version 1809 (October 2018 Update) -->
|
||||
<maxversiontested Id="10.0.17763.0"/>
|
||||
<!-- Windows Vista and Windows Server 2008 -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
<!-- Windows 7 and Windows Server 2008 R2 -->
|
||||
|
@ -55,6 +58,11 @@
|
|||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM, True</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor, System</dpiAwareness>
|
||||
<printerDriverIsolation xmlns="http://schemas.microsoft.com/SMI/2011/WindowsSettings">True</printerDriverIsolation>
|
||||
<disableWindowFiltering xmlns="http://schemas.microsoft.com/SMI/2011/WindowsSettings">True</disableWindowFiltering>
|
||||
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">True</longPathAware>
|
||||
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
|
||||
<heapType xmlns="http://schemas.microsoft.com/SMI/2020/WindowsSettings">SegmentHeap</heapType>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
|
|
|
@ -28,6 +28,8 @@ set(SOURCES
|
|||
mainwindow.h
|
||||
mainwindow.cpp
|
||||
main.cpp
|
||||
systembutton.h
|
||||
systembutton.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -151,7 +151,7 @@
|
|||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="minimizeButton">
|
||||
<widget class="SystemButton" name="minimizeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -188,7 +188,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="maximizeButton">
|
||||
<widget class="SystemButton" name="maximizeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -225,7 +225,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<widget class="SystemButton" name="closeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -264,6 +264,13 @@
|
|||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SystemButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>systembutton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 "systembutton.h"
|
||||
|
||||
SystemButton::SystemButton(QWidget *parent) : QPushButton(parent)
|
||||
{
|
||||
}
|
||||
|
||||
SystemButton::~SystemButton() = default;
|
||||
|
||||
void SystemButton::setHovered(const bool value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
Q_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void SystemButton::setPressed(const bool value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
Q_UNIMPLEMENTED();
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 <QtWidgets/qpushbutton.h>
|
||||
|
||||
class SystemButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SystemButton(QWidget *parent = nullptr);
|
||||
~SystemButton() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setHovered(const bool value);
|
||||
void setPressed(const bool value);
|
||||
};
|
|
@ -39,6 +39,8 @@ set(SOURCES
|
|||
mainwindow.h
|
||||
mainwindow.cpp
|
||||
main.cpp
|
||||
systembutton.h
|
||||
systembutton.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
#include "mainwindow.h"
|
||||
#include "glwidget.h"
|
||||
#include "systembutton.h"
|
||||
#include <QtWidgets/qboxlayout.h>
|
||||
#include <QtWidgets/qlabel.h>
|
||||
#include <QtWidgets/qpushbutton.h>
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
|
@ -51,16 +51,16 @@ void MainWindow::setupUi()
|
|||
f.setPointSize(kDefaultTitleBarFontPointSize);
|
||||
m_titleLabel->setFont(f);
|
||||
connect(this, &MainWindow::windowTitleChanged, m_titleLabel, &QLabel::setText);
|
||||
m_minBtn = new QPushButton(this);
|
||||
m_minBtn = new SystemButton(this);
|
||||
m_minBtn->setText(tr("MINIMIZE"));
|
||||
connect(m_minBtn, &QPushButton::clicked, this, &MainWindow::showMinimized);
|
||||
m_maxBtn = new QPushButton(this);
|
||||
connect(m_minBtn, &SystemButton::clicked, this, &MainWindow::showMinimized);
|
||||
m_maxBtn = new SystemButton(this);
|
||||
updateMaximizeButton();
|
||||
connect(m_maxBtn, &QPushButton::clicked, this, &MainWindow::toggleMaximized);
|
||||
connect(m_maxBtn, &SystemButton::clicked, this, &MainWindow::toggleMaximized);
|
||||
connect(this, &MainWindow::zoomedChanged, this, &MainWindow::updateMaximizeButton);
|
||||
m_closeBtn = new QPushButton(this);
|
||||
m_closeBtn = new SystemButton(this);
|
||||
m_closeBtn->setText(tr("CLOSE"));
|
||||
connect(m_closeBtn, &QPushButton::clicked, this, &MainWindow::close);
|
||||
connect(m_closeBtn, &SystemButton::clicked, this, &MainWindow::close);
|
||||
m_titleBarWidget = new QWidget(this);
|
||||
m_titleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_titleBarWidget->setFixedHeight(kDefaultTitleBarHeight);
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class GLWidget;
|
||||
class SystemButton;
|
||||
|
||||
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
|
||||
{
|
||||
|
@ -50,9 +50,9 @@ private:
|
|||
|
||||
private:
|
||||
QLabel *m_titleLabel = nullptr;
|
||||
QPushButton *m_minBtn = nullptr;
|
||||
QPushButton *m_maxBtn = nullptr;
|
||||
QPushButton *m_closeBtn = nullptr;
|
||||
SystemButton *m_minBtn = nullptr;
|
||||
SystemButton *m_maxBtn = nullptr;
|
||||
SystemButton *m_closeBtn = nullptr;
|
||||
QWidget *m_titleBarWidget = nullptr;
|
||||
GLWidget *m_glWidget = nullptr;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 "systembutton.h"
|
||||
|
||||
SystemButton::SystemButton(QWidget *parent) : QPushButton(parent)
|
||||
{
|
||||
}
|
||||
|
||||
SystemButton::~SystemButton() = default;
|
||||
|
||||
void SystemButton::setHovered(const bool value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
Q_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void SystemButton::setPressed(const bool value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
Q_UNIMPLEMENTED();
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 <QtWidgets/qpushbutton.h>
|
||||
|
||||
class SystemButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SystemButton(QWidget *parent = nullptr);
|
||||
~SystemButton() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setHovered(const bool value);
|
||||
void setPressed(const bool value);
|
||||
};
|
|
@ -29,11 +29,12 @@ import org.wangwenx190.FramelessHelper 1.0
|
|||
|
||||
FramelessWindow {
|
||||
id: window
|
||||
visible: true
|
||||
visible: true // Default is false, so won't be visible unless explicitly set to true.
|
||||
width: 800
|
||||
height: 600
|
||||
title: qsTr("Hello, World! - Qt Quick")
|
||||
color: FramelessUtils.darkModeEnabled ? FramelessUtils.defaultSystemDarkColor : FramelessUtils.defaultSystemLightColor
|
||||
title: qsTr("FramelessHelper demo application - Qt Quick")
|
||||
color: (FramelessUtils.systemTheme === FramelessHelperConstants.Dark)
|
||||
? FramelessUtils.defaultSystemDarkColor : FramelessUtils.defaultSystemLightColor
|
||||
|
||||
Timer {
|
||||
interval: 500
|
||||
|
@ -49,7 +50,7 @@ FramelessWindow {
|
|||
pointSize: 70
|
||||
bold: true
|
||||
}
|
||||
color: FramelessUtils.darkModeEnabled ? "white" : "black"
|
||||
color: (FramelessUtils.systemTheme === FramelessHelperConstants.Dark) ? "white" : "black"
|
||||
}
|
||||
|
||||
StandardTitleBar {
|
||||
|
@ -75,15 +76,15 @@ FramelessWindow {
|
|||
}
|
||||
Component.onCompleted: {
|
||||
// Make our homemade title bar snap to the window top frame border.
|
||||
window.snapToTopBorder(titleBar, FramelessHelper.Top, FramelessHelper.Bottom);
|
||||
window.snapToTopBorder(titleBar, FramelessHelperConstants.Top, FramelessHelperConstants.Bottom);
|
||||
// Make our homemade title bar draggable, and open the system menu
|
||||
// when the user right clicks on the title bar area.
|
||||
window.titleBarItem = titleBar;
|
||||
FramelessHelper.titleBarItem = titleBar;
|
||||
// Make our own items visible to the hit test and on Windows, enable
|
||||
// the snap layout feature (available since Windows 11).
|
||||
window.setSystemButton(minimizeButton, FramelessHelper.Minimize);
|
||||
window.setSystemButton(maximizeButton, FramelessHelper.Maximize);
|
||||
window.setSystemButton(closeButton, FramelessHelper.Close);
|
||||
FramelessHelper.setSystemButton(minimizeButton, FramelessHelperConstants.Minimize);
|
||||
FramelessHelper.setSystemButton(maximizeButton, FramelessHelperConstants.Maximize);
|
||||
FramelessHelper.setSystemButton(closeButton, FramelessHelperConstants.Close);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <QtQml/qqmlapplicationengine.h>
|
||||
#include <QtQuick/qquickwindow.h>
|
||||
#include <QtQuickControls2/qquickstyle.h>
|
||||
#include <framelessquickhelper.h>
|
||||
#include <framelessquickmodule.h>
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include <framelessquickmodule.h>
|
|
@ -25,33 +25,55 @@
|
|||
#pragma once
|
||||
|
||||
#include "framelesshelperquick_global.h"
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
# include <QtQml/qqmlextensionplugin.h>
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QQmlEngine;
|
||||
QT_END_NAMESPACE
|
||||
#include <QtQuick/qquickitem.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
namespace FramelessHelper::Quick
|
||||
{
|
||||
FRAMELESSHELPER_QUICK_API void registerTypes(QQmlEngine *engine);
|
||||
} // namespace FramelessHelper::Quick
|
||||
class FramelessQuickHelperPrivate;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
class FRAMELESSHELPER_QUICK_API FramelessHelperQuickPlugin : public QQmlEngineExtensionPlugin
|
||||
class FRAMELESSHELPER_QUICK_API FramelessQuickHelper : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
|
||||
#ifdef QML_NAMED_ELEMENT
|
||||
QML_NAMED_ELEMENT(FramelessHelper)
|
||||
#endif
|
||||
Q_DECLARE_PRIVATE(FramelessQuickHelper)
|
||||
Q_DISABLE_COPY_MOVE(FramelessQuickHelper)
|
||||
Q_PROPERTY(QQuickItem* titleBarItem READ titleBarItem WRITE setTitleBarItem NOTIFY titleBarItemChanged FINAL)
|
||||
|
||||
public:
|
||||
explicit FramelessHelperQuickPlugin(QObject *parent = nullptr);
|
||||
~FramelessHelperQuickPlugin() override;
|
||||
explicit FramelessQuickHelper(QQuickItem *parent = nullptr, const Global::UserSettings &settings = {});
|
||||
~FramelessQuickHelper() override;
|
||||
|
||||
void initializeEngine(QQmlEngine *engine, const char *uri) override;
|
||||
Q_NODISCARD static FramelessQuickHelper *qmlAttachedProperties(QObject *parentObject);
|
||||
|
||||
Q_NODISCARD QQuickItem *titleBarItem() const;
|
||||
Q_NODISCARD bool isWindowFixedSize() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setTitleBarItem(QQuickItem *value);
|
||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||
void setHitTestVisible(QQuickItem *item);
|
||||
|
||||
void showSystemMenu(const QPoint &pos);
|
||||
void windowStartSystemMove2(const QPoint &pos);
|
||||
void windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
||||
|
||||
void moveWindowToDesktopCenter();
|
||||
void bringWindowToFront();
|
||||
void setWindowFixedSize(const bool value, const bool force = false);
|
||||
|
||||
protected:
|
||||
void itemChange(const ItemChange change, const ItemChangeData &data) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void titleBarItemChanged();
|
||||
|
||||
private:
|
||||
QScopedPointer<FramelessQuickHelperPrivate> d_ptr;
|
||||
};
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
||||
QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickHelper))
|
||||
QML_DECLARE_TYPEINFO(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickHelper), QML_HAS_ATTACHED_PROPERTIES)
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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"
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
# include <QtQml/qqmlextensionplugin.h>
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QQmlEngine;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
namespace FramelessHelper::Quick
|
||||
{
|
||||
FRAMELESSHELPER_QUICK_API void registerTypes(QQmlEngine *engine);
|
||||
} // namespace FramelessHelper::Quick
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
class FRAMELESSHELPER_QUICK_API FramelessHelperQuickPlugin : public QQmlEngineExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
explicit FramelessHelperQuickPlugin(QObject *parent = nullptr);
|
||||
~FramelessHelperQuickPlugin() override;
|
||||
|
||||
void initializeEngine(QQmlEngine *engine, const char *uri) override;
|
||||
};
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QQuickWindow;
|
||||
class QQuickItem;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
@ -49,7 +48,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickUtils : public QObject
|
|||
Q_PROPERTY(qreal titleBarHeight READ titleBarHeight CONSTANT FINAL)
|
||||
Q_PROPERTY(bool frameBorderVisible READ frameBorderVisible CONSTANT FINAL)
|
||||
Q_PROPERTY(qreal frameBorderThickness READ frameBorderThickness CONSTANT FINAL)
|
||||
Q_PROPERTY(bool darkModeEnabled READ darkModeEnabled NOTIFY darkModeEnabledChanged FINAL)
|
||||
Q_PROPERTY(QuickGlobal::SystemTheme systemTheme READ systemTheme NOTIFY systemThemeChanged FINAL)
|
||||
Q_PROPERTY(QColor systemAccentColor READ systemAccentColor NOTIFY systemAccentColorChanged FINAL)
|
||||
Q_PROPERTY(bool titleBarColorized READ titleBarColorized NOTIFY titleBarColorizedChanged FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemLightColor READ defaultSystemLightColor CONSTANT FINAL)
|
||||
|
@ -63,24 +62,24 @@ public:
|
|||
explicit FramelessQuickUtils(QObject *parent = nullptr);
|
||||
~FramelessQuickUtils() override;
|
||||
|
||||
Q_NODISCARD static qreal titleBarHeight();
|
||||
Q_NODISCARD static bool frameBorderVisible();
|
||||
Q_NODISCARD static qreal frameBorderThickness();
|
||||
Q_NODISCARD static bool darkModeEnabled();
|
||||
Q_NODISCARD static QColor systemAccentColor();
|
||||
Q_NODISCARD static bool titleBarColorized();
|
||||
Q_NODISCARD static QColor defaultSystemLightColor();
|
||||
Q_NODISCARD static QColor defaultSystemDarkColor();
|
||||
Q_NODISCARD static QSizeF defaultSystemButtonSize();
|
||||
Q_NODISCARD static QSizeF defaultSystemButtonIconSize();
|
||||
Q_NODISCARD static QColor defaultSystemButtonBackgroundColor();
|
||||
Q_NODISCARD static QColor defaultSystemCloseButtonBackgroundColor();
|
||||
Q_NODISCARD qreal titleBarHeight() const;
|
||||
Q_NODISCARD bool frameBorderVisible() const;
|
||||
Q_NODISCARD qreal frameBorderThickness() const;
|
||||
Q_NODISCARD QuickGlobal::SystemTheme systemTheme() const;
|
||||
Q_NODISCARD QColor systemAccentColor() const;
|
||||
Q_NODISCARD bool titleBarColorized() const;
|
||||
Q_NODISCARD QColor defaultSystemLightColor() const;
|
||||
Q_NODISCARD QColor defaultSystemDarkColor() const;
|
||||
Q_NODISCARD QSizeF defaultSystemButtonSize() const;
|
||||
Q_NODISCARD QSizeF defaultSystemButtonIconSize() const;
|
||||
Q_NODISCARD QColor defaultSystemButtonBackgroundColor() const;
|
||||
Q_NODISCARD QColor defaultSystemCloseButtonBackgroundColor() const;
|
||||
|
||||
Q_NODISCARD Q_INVOKABLE static QColor getSystemButtonBackgroundColor(
|
||||
Q_NODISCARD Q_INVOKABLE QColor getSystemButtonBackgroundColor(
|
||||
const QuickGlobal::SystemButtonType button, const QuickGlobal::ButtonState state);
|
||||
|
||||
Q_SIGNALS:
|
||||
void darkModeEnabledChanged();
|
||||
void systemThemeChanged();
|
||||
void systemAccentColorChanged();
|
||||
void titleBarColorizedChanged();
|
||||
};
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "framelesshelperquick_global.h"
|
||||
#include <QtQuick/qquickitem.h>
|
||||
#include <QtQuick/qquickwindow.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
@ -45,10 +44,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow
|
|||
Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL)
|
||||
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
||||
Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL)
|
||||
Q_PROPERTY(bool fixedSize READ isFixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL)
|
||||
Q_PROPERTY(QColor frameBorderColor READ frameBorderColor NOTIFY frameBorderColorChanged FINAL)
|
||||
Q_PROPERTY(QuickGlobal::Options options READ options WRITE setOptions NOTIFY optionsChanged FINAL)
|
||||
Q_PROPERTY(QQuickItem* titleBarItem READ titleBarItem WRITE setTitleBarItem NOTIFY titleBarItemChanged FINAL)
|
||||
|
||||
public:
|
||||
explicit FramelessQuickWindow(QWindow *parent = nullptr, const Global::UserSettings &settings = {});
|
||||
|
@ -59,30 +55,13 @@ public:
|
|||
Q_NODISCARD bool isMinimized() const;
|
||||
Q_NODISCARD bool isZoomed() const;
|
||||
Q_NODISCARD bool isFullScreen() const;
|
||||
|
||||
Q_NODISCARD bool isFixedSize() const;
|
||||
void setFixedSize(const bool value);
|
||||
|
||||
Q_NODISCARD QColor frameBorderColor() const;
|
||||
|
||||
Q_NODISCARD QuickGlobal::Options options() const;
|
||||
void setOptions(const QuickGlobal::Options value);
|
||||
|
||||
Q_NODISCARD QQuickItem *titleBarItem() const;
|
||||
void setTitleBarItem(QQuickItem *item);
|
||||
|
||||
public Q_SLOTS:
|
||||
void showMinimized2();
|
||||
void toggleMaximized();
|
||||
void toggleFullScreen();
|
||||
void showSystemMenu(const QPoint &pos);
|
||||
void startSystemMove2(const QPoint &pos);
|
||||
void startSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
||||
void setHitTestVisible(QQuickItem *item);
|
||||
void moveToDesktopCenter();
|
||||
void bringToFront();
|
||||
void snapToTopBorder(QQuickItem *item, const QuickGlobal::Anchor itemAnchor, const QuickGlobal::Anchor topBorderAnchor);
|
||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||
|
||||
Q_SIGNALS:
|
||||
void hiddenChanged();
|
||||
|
@ -90,11 +69,7 @@ Q_SIGNALS:
|
|||
void minimizedChanged();
|
||||
void zoomedChanged();
|
||||
void fullScreenChanged();
|
||||
void fixedSizeChanged();
|
||||
void frameBorderColorChanged();
|
||||
void systemButtonStateChanged(const QuickGlobal::SystemButtonType, const QuickGlobal::ButtonState);
|
||||
void optionsChanged();
|
||||
void titleBarItemChanged();
|
||||
|
||||
private:
|
||||
QScopedPointer<FramelessQuickWindowPrivate> d_ptr;
|
||||
|
|
|
@ -72,7 +72,6 @@ Q_SIGNALS:
|
|||
void fixedSizeChanged();
|
||||
void titleBarWidgetChanged();
|
||||
void systemThemeChanged();
|
||||
void systemButtonStateChanged(const Global::SystemButtonType, const Global::ButtonState);
|
||||
|
||||
private:
|
||||
QScopedPointer<FramelessWidgetsHelper> d_ptr;
|
||||
|
|
|
@ -77,7 +77,6 @@ Q_SIGNALS:
|
|||
void titleBarWidgetChanged();
|
||||
void contentWidgetChanged();
|
||||
void systemThemeChanged();
|
||||
void systemButtonStateChanged(const Global::SystemButtonType, const Global::ButtonState);
|
||||
|
||||
private:
|
||||
QScopedPointer<FramelessWidgetsHelper> d_ptr;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/quuid.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include "framelesswindowsmanager.h"
|
||||
#include "framelesswindowsmanager_p.h"
|
||||
|
@ -58,7 +59,6 @@ Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
|||
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(Win32MessageTypeName, "windows_generic_MSG")
|
||||
static const QString qThemeSettingChangeEventName = QString::fromWCharArray(kThemeSettingChangeEventName);
|
||||
static constexpr const wchar_t kDragBarWindowClassName[] = L"FRAMELESSHELPER@DRAG_BAR_WINDOW_CLASS";
|
||||
FRAMELESSHELPER_STRING_CONSTANT(MonitorFromWindow)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(GetMonitorInfoW)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(ScreenToClient)
|
||||
|
@ -140,6 +140,7 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
if (data.params.isInsideSystemButtons(qtScenePos, &buttonType)) {
|
||||
switch (buttonType) {
|
||||
case SystemButtonType::Unknown:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
case SystemButtonType::WindowIcon:
|
||||
return HTSYSMENU;
|
||||
|
@ -156,7 +157,7 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
}
|
||||
// The parent window has quite some logic in the hit test handler, we
|
||||
// should forward this message to the parent window and return what it
|
||||
// returns to make sure our homemade titlebar is still functional.
|
||||
// returns to make sure our homemade title bar is still functional.
|
||||
return SendMessageW(parentWindowHandle, WM_NCHITTEST, 0, lParam);
|
||||
}
|
||||
case WM_NCMOUSEMOVE: {
|
||||
|
@ -197,7 +198,7 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
}
|
||||
// If we haven't previously asked for mouse tracking, request mouse
|
||||
// tracking. We need to do this so we can get the WM_NCMOUSELEAVE
|
||||
// message when the mouse leave the titlebar. Otherwise, we won't always
|
||||
// message when the mouse leave the title bar. Otherwise, we won't always
|
||||
// get that message (especially if the user moves the mouse _real
|
||||
// fast_).
|
||||
if (!data.trackingMouse && ((wParam == HTSYSMENU) || (wParam == HTHELP)
|
||||
|
@ -233,7 +234,7 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
case WM_NCLBUTTONDOWN:
|
||||
case WM_NCLBUTTONDBLCLK: {
|
||||
// Manual handling for mouse clicks in the drag bar. If it's in a
|
||||
// caption button, then tell the titlebar to "press" the button, which
|
||||
// caption button, then tell the title bar to "press" the button, which
|
||||
// should change its visual state.
|
||||
//
|
||||
// If it's not in a caption button, then just forward the message along
|
||||
|
@ -309,7 +310,7 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
}
|
||||
// Forward all the mouse events we don't handled here to the parent window,
|
||||
// this is a necessary step to make sure the child widgets/quick items can still
|
||||
// receive mouse events from our homemade titlebar.
|
||||
// receive mouse events from our homemade title bar.
|
||||
if (((uMsg >= WM_MOUSEFIRST) && (uMsg <= WM_MOUSELAST)) ||
|
||||
((uMsg >= WM_NCMOUSEMOVE) && (uMsg <= WM_NCXBUTTONDBLCLK))) {
|
||||
SendMessageW(parentWindowHandle, uMsg, wParam, lParam);
|
||||
|
@ -332,6 +333,12 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
}
|
||||
const int titleBarHeight = Utils::getTitleBarHeight(parentWindowId, true);
|
||||
const auto dragBarWindowHandle = reinterpret_cast<HWND>(dragBarWindowId);
|
||||
// As you can see from the code, we only use the drag bar window to activate the
|
||||
// snap layout feature introduced in Windows 11. So you may wonder, why not just
|
||||
// limit it to the rectangle of the three system buttons, instead of covering the
|
||||
// whole title bar area? Well, I've tried that solution already and unfortunately
|
||||
// it doesn't work. Since our current solution works well, I have no plan to dig
|
||||
// into all the magic behind it.
|
||||
if (SetWindowPos(dragBarWindowHandle, HWND_TOP, 0, 0, parentWindowClientRect.right,
|
||||
titleBarHeight, (SWP_NOACTIVATE | SWP_SHOWWINDOW)) == FALSE) {
|
||||
qWarning() << Utils::getSystemErrorMessage(kSetWindowPos);
|
||||
|
@ -358,12 +365,18 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
qWarning() << Utils::getSystemErrorMessage(kGetModuleHandleW);
|
||||
return false;
|
||||
}
|
||||
static const QString dragBarWindowClassName = QUuid::createUuid().toString();
|
||||
Q_ASSERT(!dragBarWindowClassName.isEmpty());
|
||||
if (dragBarWindowClassName.isEmpty()) {
|
||||
qWarning() << "Failed to generate a new UUID.";
|
||||
return false;
|
||||
}
|
||||
static const ATOM dragBarWindowClass = [instance]() -> ATOM {
|
||||
WNDCLASSEXW wcex;
|
||||
SecureZeroMemory(&wcex, sizeof(wcex));
|
||||
wcex.cbSize = sizeof(wcex);
|
||||
wcex.style = (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS);
|
||||
wcex.lpszClassName = kDragBarWindowClassName;
|
||||
wcex.lpszClassName = qUtf16Printable(dragBarWindowClassName);
|
||||
wcex.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
|
||||
wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
|
||||
wcex.lpfnWndProc = DragBarWindowProc;
|
||||
|
@ -376,7 +389,8 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
|||
return false;
|
||||
}
|
||||
const HWND dragBarWindowHandle = CreateWindowExW((WS_EX_LAYERED | WS_EX_NOREDIRECTIONBITMAP),
|
||||
kDragBarWindowClassName, nullptr, WS_CHILD, 0, 0, 0, 0, parentWindowHandle, nullptr, instance, nullptr);
|
||||
qUtf16Printable(dragBarWindowClassName), nullptr, WS_CHILD, 0, 0, 0, 0,
|
||||
parentWindowHandle, nullptr, instance, nullptr);
|
||||
Q_ASSERT(dragBarWindowHandle);
|
||||
if (!dragBarWindowHandle) {
|
||||
qWarning() << Utils::getSystemErrorMessage(kCreateWindowExW);
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
SOFTWARE.
|
||||
]]
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Qml QuickTemplates2 QuickControls2)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Qml QuickTemplates2 QuickControls2)
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS QuickTemplates2 QuickControls2)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS QuickTemplates2 QuickControls2)
|
||||
|
||||
set(SUB_PROJ_NAME FramelessHelperQuick)
|
||||
|
||||
|
@ -32,9 +32,10 @@ set(INCLUDE_PREFIX ../../include/FramelessHelper/Quick)
|
|||
set(SOURCES
|
||||
framelesshelperquick.qrc
|
||||
${INCLUDE_PREFIX}/framelesshelperquick_global.h
|
||||
${INCLUDE_PREFIX}/framelessquickutils.h
|
||||
${INCLUDE_PREFIX}/framelessquickhelper.h
|
||||
${INCLUDE_PREFIX}/framelessquickmodule.h
|
||||
${INCLUDE_PREFIX}/framelessquickwindow.h
|
||||
${INCLUDE_PREFIX}/framelessquickhelper.h
|
||||
${INCLUDE_PREFIX}/framelessquickutils.h
|
||||
quickstandardminimizebutton_p.h
|
||||
quickstandardminimizebutton.cpp
|
||||
quickstandardmaximizebutton_p.h
|
||||
|
@ -43,10 +44,12 @@ set(SOURCES
|
|||
quickstandardclosebutton.cpp
|
||||
quickstandardtitlebar_p.h
|
||||
quickstandardtitlebar.cpp
|
||||
framelessquickhelper_p.h
|
||||
framelessquickwindow_p.h
|
||||
framelessquickhelper.cpp
|
||||
framelessquickutils.cpp
|
||||
framelessquickmodule.cpp
|
||||
framelessquickwindow.cpp
|
||||
framelessquickhelper.cpp
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
|
||||
|
@ -91,7 +94,7 @@ if(MSVC)
|
|||
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_CO}
|
||||
)
|
||||
target_compile_options(${SUB_PROJ_NAME} PRIVATE
|
||||
/utf-8 /W4 /WX
|
||||
/utf-8 /W3 /WX # Can't use /W4 here due to the Q_D macro causes warnings.
|
||||
)
|
||||
else()
|
||||
target_compile_options(${SUB_PROJ_NAME} PRIVATE
|
||||
|
@ -100,7 +103,6 @@ else()
|
|||
endif()
|
||||
|
||||
target_link_libraries(${SUB_PROJ_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::QmlPrivate
|
||||
Qt${QT_VERSION_MAJOR}::QuickPrivate
|
||||
Qt${QT_VERSION_MAJOR}::QuickTemplates2Private
|
||||
Qt${QT_VERSION_MAJOR}::QuickControls2Private
|
||||
|
|
|
@ -23,97 +23,641 @@
|
|||
*/
|
||||
|
||||
#include "framelessquickhelper.h"
|
||||
#include "framelessquickutils.h"
|
||||
#include "framelessquickwindow.h"
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
# include "quickstandardminimizebutton_p.h"
|
||||
# include "quickstandardmaximizebutton_p.h"
|
||||
# include "quickstandardclosebutton_p.h"
|
||||
# include "quickstandardtitlebar_p.h"
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
|
||||
#ifndef QUICK_URI_SHORT
|
||||
# define QUICK_URI_SHORT FRAMELESSHELPER_QUICK_URI, 1
|
||||
#endif
|
||||
|
||||
#ifndef QUICK_URI_FULL
|
||||
# define QUICK_URI_FULL QUICK_URI_SHORT, 0
|
||||
#endif
|
||||
|
||||
#ifndef QUICK_URI_EXPAND
|
||||
# define QUICK_URI_EXPAND(name) QUICK_URI_FULL, name
|
||||
#endif
|
||||
#include "framelessquickhelper_p.h"
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtGui/qpa/qplatformwindow.h> // For QWINDOWSIZE_MAX
|
||||
#include <QtQuick/qquickwindow.h>
|
||||
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
|
||||
#include <framelesswindowsmanager.h>
|
||||
#include <utils.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
|
||||
using namespace Global;
|
||||
|
||||
struct QuickHelperData
|
||||
{
|
||||
Q_ASSERT(engine);
|
||||
if (!engine) {
|
||||
bool attached = false;
|
||||
UserSettings settings = {};
|
||||
SystemParameters params = {};
|
||||
QPointer<QQuickItem> titleBarItem = nullptr;
|
||||
QList<QQuickItem *> hitTestVisibleItems = {};
|
||||
};
|
||||
|
||||
struct QuickHelper
|
||||
{
|
||||
QMutex mutex;
|
||||
QHash<WId, QuickHelperData> data = {};
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(QuickHelper, g_quickHelper)
|
||||
|
||||
static constexpr const char QTQUICK_ITEM_CLASS_NAME[] = "QQuickItem";
|
||||
static constexpr const char QTQUICK_BUTTON_CLASS_NAME[] = "QQuickAbstractButton";
|
||||
|
||||
FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q, const UserSettings &settings) : QObject(q)
|
||||
{
|
||||
Q_ASSERT(q);
|
||||
if (!q) {
|
||||
return;
|
||||
}
|
||||
static bool inited = false;
|
||||
if (inited) {
|
||||
return;
|
||||
}
|
||||
inited = true;
|
||||
qRegisterMetaType<QuickGlobal::Options>();
|
||||
qRegisterMetaType<QuickGlobal::SystemTheme>();
|
||||
qRegisterMetaType<QuickGlobal::SystemButtonType>();
|
||||
qRegisterMetaType<QuickGlobal::ResourceType>();
|
||||
qRegisterMetaType<QuickGlobal::DwmColorizationArea>();
|
||||
qRegisterMetaType<QuickGlobal::Anchor>();
|
||||
qRegisterMetaType<QuickGlobal::ButtonState>();
|
||||
qmlRegisterUncreatableType<QuickGlobal>(QUICK_URI_FULL, "FramelessHelper",
|
||||
FRAMELESSHELPER_STRING_LITERAL("The FramelessHelper namespace is not creatable, you can only use it to access it's enums."));
|
||||
qmlRegisterSingletonType<FramelessQuickUtils>(QUICK_URI_EXPAND("FramelessUtils"),
|
||||
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
|
||||
Q_UNUSED(engine);
|
||||
Q_UNUSED(scriptEngine);
|
||||
return new FramelessQuickUtils;
|
||||
});
|
||||
qmlRegisterRevision<QWindow, 254>(QUICK_URI_FULL);
|
||||
qmlRegisterRevision<QQuickWindow, 254>(QUICK_URI_FULL);
|
||||
qmlRegisterRevision<QQuickItem, 254>(QUICK_URI_FULL);
|
||||
qmlRegisterType<FramelessQuickWindow>(QUICK_URI_EXPAND("FramelessWindow"));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qmlRegisterType<QuickStandardMinimizeButton>(QUICK_URI_EXPAND("StandardMinimizeButton"));
|
||||
qmlRegisterType<QuickStandardMaximizeButton>(QUICK_URI_EXPAND("StandardMaximizeButton"));
|
||||
qmlRegisterType<QuickStandardCloseButton>(QUICK_URI_EXPAND("StandardCloseButton"));
|
||||
qmlRegisterType<QuickStandardTitleBar>(QUICK_URI_EXPAND("StandardTitleBar"));
|
||||
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardMinimizeButton"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardMinimizeButton is not available until Qt6."));
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardMaximizeButton"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardMaximizeButton is not available until Qt6."));
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardCloseButton"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardCloseButton is not available until Qt6."));
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardTitleBar"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardTitleBar is not available until Qt6."));
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qmlRegisterModule(QUICK_URI_FULL);
|
||||
q_ptr = q;
|
||||
m_cachedSettings = settings;
|
||||
}
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
FramelessHelperQuickPlugin::FramelessHelperQuickPlugin(QObject *parent) : QQmlEngineExtensionPlugin(parent)
|
||||
FramelessQuickHelperPrivate::~FramelessQuickHelperPrivate() = default;
|
||||
|
||||
FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(FramelessQuickHelper *pub)
|
||||
{
|
||||
Q_ASSERT(pub);
|
||||
if (!pub) {
|
||||
return nullptr;
|
||||
}
|
||||
return pub->d_func();
|
||||
}
|
||||
|
||||
const FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(const FramelessQuickHelper *pub)
|
||||
{
|
||||
Q_ASSERT(pub);
|
||||
if (!pub) {
|
||||
return nullptr;
|
||||
}
|
||||
return pub->d_func();
|
||||
}
|
||||
|
||||
QQuickItem *FramelessQuickHelperPrivate::getTitleBarItem() const
|
||||
{
|
||||
return getWindowData().titleBarItem;
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::setTitleBarItem(QQuickItem *value)
|
||||
{
|
||||
Q_ASSERT(value);
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
QMutexLocker locker(&g_quickHelper()->mutex);
|
||||
QuickHelperData *data = getWindowDataMutable();
|
||||
if (data->titleBarItem == value) {
|
||||
return;
|
||||
}
|
||||
data->titleBarItem = value;
|
||||
Q_Q(FramelessQuickHelper);
|
||||
Q_EMIT q->titleBarItemChanged();
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::attachToWindow()
|
||||
{
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_quickHelper()->mutex.lock();
|
||||
QuickHelperData *data = getWindowDataMutable();
|
||||
const bool attached = data->attached;
|
||||
g_quickHelper()->mutex.unlock();
|
||||
|
||||
if (attached) {
|
||||
return;
|
||||
}
|
||||
|
||||
UserSettings settings = m_cachedSettings;
|
||||
m_cachedSettings = {};
|
||||
|
||||
SystemParameters params = {};
|
||||
params.getWindowId = [window]() -> WId { return window->winId(); };
|
||||
params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); };
|
||||
params.setWindowFlags = [window](const Qt::WindowFlags flags) -> void { window->setFlags(flags); };
|
||||
params.getWindowSize = [window]() -> QSize { return window->size(); };
|
||||
params.setWindowSize = [window](const QSize &size) -> void { window->resize(size); };
|
||||
params.getWindowPosition = [window]() -> QPoint { return window->position(); };
|
||||
params.setWindowPosition = [window](const QPoint &pos) -> void { window->setX(pos.x()); window->setY(pos.y()); };
|
||||
params.getWindowScreen = [window]() -> QScreen * { return window->screen(); };
|
||||
params.isWindowFixedSize = [this]() -> bool { return isWindowFixedSize(); };
|
||||
params.setWindowFixedSize = [this](const bool value) -> void { setWindowFixedSize(value); };
|
||||
params.getWindowState = [window]() -> Qt::WindowState { return window->windowState(); };
|
||||
params.setWindowState = [window](const Qt::WindowState state) -> void { window->setWindowState(state); };
|
||||
params.getWindowHandle = [q]() -> QWindow * { return q->window(); };
|
||||
params.windowToScreen = [window](const QPoint &pos) -> QPoint { return window->mapToGlobal(pos); };
|
||||
params.screenToWindow = [window](const QPoint &pos) -> QPoint { return window->mapFromGlobal(pos); };
|
||||
params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool {
|
||||
QuickGlobal::SystemButtonType button2 = QuickGlobal::SystemButtonType::Unknown;
|
||||
const bool result = isInSystemButtons(pos, &button2);
|
||||
*button = FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button2);
|
||||
return result;
|
||||
};
|
||||
params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); };
|
||||
params.getWindowDevicePixelRatio = [window]() -> qreal { return window->effectiveDevicePixelRatio(); };
|
||||
params.setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void {
|
||||
setSystemButtonState(FRAMELESSHELPER_ENUM_CORE_TO_QUICK(SystemButtonType, button),
|
||||
FRAMELESSHELPER_ENUM_CORE_TO_QUICK(ButtonState, state));
|
||||
};
|
||||
params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); };
|
||||
params.showSystemMenu = [this](const QPoint &pos) -> void { showSystemMenu(pos); };
|
||||
|
||||
g_quickHelper()->mutex.lock();
|
||||
data->params = params;
|
||||
data->attached = true;
|
||||
g_quickHelper()->mutex.unlock();
|
||||
|
||||
FramelessWindowsManager::instance()->addWindow(settings, params);
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
Q_ASSERT(buttonType != QuickGlobal::SystemButtonType::Unknown);
|
||||
if (!item || (buttonType == QuickGlobal::SystemButtonType::Unknown)) {
|
||||
return;
|
||||
}
|
||||
QMutexLocker locker(&g_quickHelper()->mutex);
|
||||
QuickHelperData *data = getWindowDataMutable();
|
||||
switch (buttonType) {
|
||||
case QuickGlobal::SystemButtonType::Unknown:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::WindowIcon:
|
||||
data->settings.windowIconButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Help:
|
||||
data->settings.contextHelpButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Minimize:
|
||||
data->settings.minimizeButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Maximize:
|
||||
case QuickGlobal::SystemButtonType::Restore:
|
||||
data->settings.maximizeButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Close:
|
||||
data->settings.closeButton = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::setHitTestVisible(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
QMutexLocker locker(&g_quickHelper()->mutex);
|
||||
QuickHelperData *data = getWindowDataMutable();
|
||||
static constexpr const bool visible = true;
|
||||
const bool exists = data->hitTestVisibleItems.contains(item);
|
||||
if (visible && !exists) {
|
||||
data->hitTestVisibleItems.append(item);
|
||||
}
|
||||
if constexpr (!visible && exists) {
|
||||
data->hitTestVisibleItems.removeAll(item);
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::showSystemMenu(const QPoint &pos)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Q_Q(FramelessQuickHelper);
|
||||
const QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
const QPoint globalPos = window->mapToGlobal(pos);
|
||||
const QPoint nativePos = QPointF(QPointF(globalPos) * window->effectiveDevicePixelRatio()).toPoint();
|
||||
Utils::showSystemMenu(window->winId(), nativePos, {}, false, {}, [this]() -> bool { return isWindowFixedSize(); });
|
||||
#else
|
||||
Q_UNUSED(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::windowStartSystemMove2(const QPoint &pos)
|
||||
{
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
Utils::startSystemMove(window, pos);
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos)
|
||||
{
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
if (edges == Qt::Edges{}) {
|
||||
return;
|
||||
}
|
||||
Utils::startSystemResize(window, edges, pos);
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::moveWindowToDesktopCenter()
|
||||
{
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
Utils::moveWindowToDesktopCenter([window]() -> QScreen * { return window->screen(); },
|
||||
[window]() -> QSize { return window->size(); },
|
||||
[window](const QPoint &pos) -> void { window->setX(pos.x()); window->setY(pos.y()); }, true);
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::bringWindowToFront()
|
||||
{
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
const QQuickWindow::Visibility visibility = window->visibility();
|
||||
if (visibility == QQuickWindow::Hidden) {
|
||||
window->show();
|
||||
}
|
||||
if (visibility == QQuickWindow::Minimized) {
|
||||
window->showNormal(); // ### FIXME
|
||||
}
|
||||
window->raise();
|
||||
window->requestActivate();
|
||||
}
|
||||
|
||||
bool FramelessQuickHelperPrivate::isWindowFixedSize() const
|
||||
{
|
||||
const QuickHelperData data = getWindowData();
|
||||
if (data.settings.options & Option::DisableResizing) {
|
||||
return true;
|
||||
}
|
||||
Q_Q(const FramelessQuickHelper);
|
||||
const QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
if (window->flags() & Qt::MSWindowsFixedSizeDialogHint) {
|
||||
return true;
|
||||
}
|
||||
const QSize minSize = window->minimumSize();
|
||||
const QSize maxSize = window->maximumSize();
|
||||
if (!minSize.isEmpty() && !maxSize.isEmpty() && (minSize == maxSize)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::setWindowFixedSize(const bool value, const bool force)
|
||||
{
|
||||
if ((isWindowFixedSize() == value) && !force) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
if (value) {
|
||||
const QSize size = window->size();
|
||||
window->setMinimumSize(size);
|
||||
window->setMaximumSize(size);
|
||||
window->setFlags(window->flags() | Qt::MSWindowsFixedSizeDialogHint);
|
||||
} else {
|
||||
window->setFlags(window->flags() & ~Qt::MSWindowsFixedSizeDialogHint);
|
||||
window->setMinimumSize(kDefaultWindowSize);
|
||||
window->setMaximumSize(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Utils::setAeroSnappingEnabled(window->winId(), !value);
|
||||
#endif
|
||||
}
|
||||
|
||||
QRect FramelessQuickHelperPrivate::mapItemGeometryToScene(const QQuickItem * const item) const
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return {};
|
||||
}
|
||||
const QPointF originPoint = item->mapToScene(QPointF(0.0, 0.0));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||
const QSizeF size = item->size();
|
||||
#else
|
||||
const QSizeF size = {item->width(), item->height()};
|
||||
#endif
|
||||
return QRectF(originPoint, size).toRect();
|
||||
}
|
||||
|
||||
bool FramelessQuickHelperPrivate::isInSystemButtons(const QPoint &pos, QuickGlobal::SystemButtonType *button) const
|
||||
{
|
||||
Q_ASSERT(button);
|
||||
if (!button) {
|
||||
return false;
|
||||
}
|
||||
*button = QuickGlobal::SystemButtonType::Unknown;
|
||||
const QuickHelperData data = getWindowData();
|
||||
if (data.settings.windowIconButton && data.settings.windowIconButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto iconBtn = qobject_cast<QQuickItem *>(data.settings.windowIconButton);
|
||||
if (mapItemGeometryToScene(iconBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::WindowIcon;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (data.settings.contextHelpButton && data.settings.contextHelpButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto helpBtn = qobject_cast<QQuickItem *>(data.settings.contextHelpButton);
|
||||
if (mapItemGeometryToScene(helpBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Help;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (data.settings.minimizeButton && data.settings.minimizeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto minBtn = qobject_cast<QQuickItem *>(data.settings.minimizeButton);
|
||||
if (mapItemGeometryToScene(minBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Minimize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (data.settings.maximizeButton && data.settings.maximizeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto maxBtn = qobject_cast<QQuickItem *>(data.settings.maximizeButton);
|
||||
if (mapItemGeometryToScene(maxBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Maximize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (data.settings.closeButton && data.settings.closeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto closeBtn = qobject_cast<QQuickItem *>(data.settings.closeButton);
|
||||
if (mapItemGeometryToScene(closeBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Close;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) const
|
||||
{
|
||||
const QuickHelperData data = getWindowData();
|
||||
if (!data.titleBarItem) {
|
||||
return false;
|
||||
}
|
||||
QRegion region = mapItemGeometryToScene(data.titleBarItem);
|
||||
const auto systemButtons = {data.settings.windowIconButton, data.settings.contextHelpButton,
|
||||
data.settings.minimizeButton, data.settings.maximizeButton, data.settings.closeButton};
|
||||
for (auto &&button : qAsConst(systemButtons)) {
|
||||
if (button && button->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto quickButton = qobject_cast<QQuickItem *>(button);
|
||||
region -= mapItemGeometryToScene(quickButton);
|
||||
}
|
||||
}
|
||||
if (!data.hitTestVisibleItems.isEmpty()) {
|
||||
for (auto &&item : qAsConst(data.hitTestVisibleItems)) {
|
||||
Q_ASSERT(item);
|
||||
if (item) {
|
||||
region -= mapItemGeometryToScene(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return region.contains(pos);
|
||||
}
|
||||
|
||||
bool FramelessQuickHelperPrivate::shouldIgnoreMouseEvents(const QPoint &pos) const
|
||||
{
|
||||
Q_Q(const FramelessQuickHelper);
|
||||
const QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
const bool withinFrameBorder = [&pos, window]() -> bool {
|
||||
if (pos.y() < kDefaultResizeBorderThickness) {
|
||||
return true;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (Utils::isWindowFrameBorderVisible()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return ((pos.x() < kDefaultResizeBorderThickness)
|
||||
|| (pos.x() >= (window->width() - kDefaultResizeBorderThickness)));
|
||||
}();
|
||||
return ((window->visibility() == QQuickWindow::Windowed) && withinFrameBorder);
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::setSystemButtonState(const QuickGlobal::SystemButtonType button,
|
||||
const QuickGlobal::ButtonState state)
|
||||
{
|
||||
Q_ASSERT(button != QuickGlobal::SystemButtonType::Unknown);
|
||||
if (button == QuickGlobal::SystemButtonType::Unknown) {
|
||||
return;
|
||||
}
|
||||
const QuickHelperData data = getWindowData();
|
||||
QQuickAbstractButton *quickButton = nullptr;
|
||||
switch (button) {
|
||||
case QuickGlobal::SystemButtonType::Unknown: {
|
||||
Q_ASSERT(false);
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::WindowIcon: {
|
||||
if (data.settings.windowIconButton && data.settings.windowIconButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.windowIconButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Help: {
|
||||
if (data.settings.contextHelpButton && data.settings.contextHelpButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.contextHelpButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Minimize: {
|
||||
if (data.settings.minimizeButton && data.settings.minimizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.minimizeButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Maximize:
|
||||
case QuickGlobal::SystemButtonType::Restore: {
|
||||
if (data.settings.maximizeButton && data.settings.maximizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.maximizeButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Close: {
|
||||
if (data.settings.closeButton && data.settings.closeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.closeButton);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
if (quickButton) {
|
||||
const auto updateButtonState = [state](QQuickAbstractButton *btn) -> void {
|
||||
Q_ASSERT(btn);
|
||||
if (!btn) {
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case QuickGlobal::ButtonState::Unspecified: {
|
||||
btn->setPressed(false);
|
||||
btn->setHovered(false);
|
||||
} break;
|
||||
case QuickGlobal::ButtonState::Hovered: {
|
||||
btn->setPressed(false);
|
||||
btn->setHovered(true);
|
||||
} break;
|
||||
case QuickGlobal::ButtonState::Pressed: {
|
||||
btn->setHovered(true);
|
||||
btn->setPressed(true);
|
||||
} break;
|
||||
case QuickGlobal::ButtonState::Clicked: {
|
||||
// Clicked: pressed --> released, so behave like hovered.
|
||||
btn->setPressed(false);
|
||||
btn->setHovered(true);
|
||||
// "QQuickAbstractButtonPrivate::click()"'s implementation is nothing but
|
||||
// emits the "clicked" signal of the public interface, so we just emit
|
||||
// the signal directly to avoid accessing the private implementation.
|
||||
Q_EMIT btn->clicked();
|
||||
} break;
|
||||
}
|
||||
};
|
||||
updateButtonState(quickButton);
|
||||
}
|
||||
}
|
||||
|
||||
QuickHelperData FramelessQuickHelperPrivate::getWindowData() const
|
||||
{
|
||||
Q_Q(const FramelessQuickHelper);
|
||||
const QQuickWindow * const window = q->window();
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return {};
|
||||
}
|
||||
const WId windowId = window->winId();
|
||||
QMutexLocker locker(&g_quickHelper()->mutex);
|
||||
if (!g_quickHelper()->data.contains(windowId)) {
|
||||
g_quickHelper()->data.insert(windowId, {});
|
||||
}
|
||||
return g_quickHelper()->data.value(windowId);
|
||||
}
|
||||
|
||||
QuickHelperData *FramelessQuickHelperPrivate::getWindowDataMutable() const
|
||||
{
|
||||
Q_Q(const FramelessQuickHelper);
|
||||
const QQuickWindow * const window = q->window();
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
const WId windowId = window->winId();
|
||||
if (!g_quickHelper()->data.contains(windowId)) {
|
||||
g_quickHelper()->data.insert(windowId, {});
|
||||
}
|
||||
return &g_quickHelper()->data[windowId];
|
||||
}
|
||||
|
||||
FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent, const UserSettings &settings)
|
||||
: QQuickItem(parent), d_ptr(new FramelessQuickHelperPrivate(this, settings))
|
||||
{
|
||||
}
|
||||
|
||||
FramelessHelperQuickPlugin::~FramelessHelperQuickPlugin() = default;
|
||||
FramelessQuickHelper::~FramelessQuickHelper() = default;
|
||||
|
||||
void FramelessHelperQuickPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
|
||||
FramelessQuickHelper *FramelessQuickHelper::qmlAttachedProperties(QObject *parentObject)
|
||||
{
|
||||
Q_ASSERT(engine);
|
||||
Q_ASSERT(uri);
|
||||
if (!engine || !uri) {
|
||||
return;
|
||||
Q_ASSERT(parentObject);
|
||||
if (!parentObject) {
|
||||
return nullptr;
|
||||
}
|
||||
Q_ASSERT(QLatin1String(uri) == QLatin1String(FRAMELESSHELPER_QUICK_URI));
|
||||
if (QLatin1String(uri) != QLatin1String(FRAMELESSHELPER_QUICK_URI)) {
|
||||
return;
|
||||
const auto item = new FramelessQuickHelper;
|
||||
const auto parentItem = qobject_cast<QQuickItem *>(parentObject);
|
||||
if (parentItem) {
|
||||
item->setParentItem(parentItem);
|
||||
} else {
|
||||
item->setParent(parentObject);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
QQuickItem *FramelessQuickHelper::titleBarItem() const
|
||||
{
|
||||
Q_D(const FramelessQuickHelper);
|
||||
return d->getTitleBarItem();
|
||||
}
|
||||
|
||||
bool FramelessQuickHelper::isWindowFixedSize() const
|
||||
{
|
||||
Q_D(const FramelessQuickHelper);
|
||||
return d->isWindowFixedSize();
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::setTitleBarItem(QQuickItem *value)
|
||||
{
|
||||
Q_ASSERT(value);
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->setTitleBarItem(value);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
Q_ASSERT(buttonType != QuickGlobal::SystemButtonType::Unknown);
|
||||
if (!item || (buttonType == QuickGlobal::SystemButtonType::Unknown)) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->setSystemButton(item, buttonType);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::setHitTestVisible(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->setHitTestVisible(item);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::showSystemMenu(const QPoint &pos)
|
||||
{
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->showSystemMenu(pos);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::windowStartSystemMove2(const QPoint &pos)
|
||||
{
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->windowStartSystemMove2(pos);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos)
|
||||
{
|
||||
if (edges == Qt::Edges{}) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->windowStartSystemResize2(edges, pos);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::moveWindowToDesktopCenter()
|
||||
{
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->moveWindowToDesktopCenter();
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::bringWindowToFront()
|
||||
{
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->bringWindowToFront();
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::setWindowFixedSize(const bool value, const bool force)
|
||||
{
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->setWindowFixedSize(value, force);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::itemChange(const ItemChange change, const ItemChangeData &data)
|
||||
{
|
||||
QQuickItem::itemChange(change, data);
|
||||
if ((change == FramelessQuickHelper::ItemSceneChange) && data.window) {
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->attachToWindow();
|
||||
}
|
||||
FramelessHelper::Quick::registerTypes(engine);
|
||||
}
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 QQuickItem;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
struct QuickHelperData;
|
||||
class FramelessQuickHelper;
|
||||
|
||||
class FRAMELESSHELPER_QUICK_API FramelessQuickHelperPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PUBLIC(FramelessQuickHelper)
|
||||
Q_DISABLE_COPY_MOVE(FramelessQuickHelperPrivate)
|
||||
|
||||
public:
|
||||
explicit FramelessQuickHelperPrivate(FramelessQuickHelper *q, const Global::UserSettings &settings = {});
|
||||
~FramelessQuickHelperPrivate() override;
|
||||
|
||||
Q_NODISCARD static FramelessQuickHelperPrivate *get(FramelessQuickHelper *pub);
|
||||
Q_NODISCARD static const FramelessQuickHelperPrivate *get(const FramelessQuickHelper *pub);
|
||||
|
||||
Q_NODISCARD QQuickItem *getTitleBarItem() const;
|
||||
void setTitleBarItem(QQuickItem *value);
|
||||
|
||||
void attachToWindow();
|
||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||
void setHitTestVisible(QQuickItem *item);
|
||||
void showSystemMenu(const QPoint &pos);
|
||||
void windowStartSystemMove2(const QPoint &pos);
|
||||
void windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
||||
|
||||
void moveWindowToDesktopCenter();
|
||||
void bringWindowToFront();
|
||||
|
||||
Q_NODISCARD bool isWindowFixedSize() const;
|
||||
void setWindowFixedSize(const bool value, const bool force = false);
|
||||
|
||||
private:
|
||||
Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const;
|
||||
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, QuickGlobal::SystemButtonType *button) const;
|
||||
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
|
||||
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
||||
void setSystemButtonState(const QuickGlobal::SystemButtonType button, const QuickGlobal::ButtonState state);
|
||||
Q_NODISCARD QuickHelperData getWindowData() const;
|
||||
Q_NODISCARD QuickHelperData *getWindowDataMutable() const;
|
||||
|
||||
private:
|
||||
FramelessQuickHelper *q_ptr = nullptr;
|
||||
Global::UserSettings m_cachedSettings = {};
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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 "framelessquickmodule.h"
|
||||
#include "framelessquickhelper.h"
|
||||
#include "framelessquickutils.h"
|
||||
#include "framelessquickwindow.h"
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
# include "quickstandardminimizebutton_p.h"
|
||||
# include "quickstandardmaximizebutton_p.h"
|
||||
# include "quickstandardclosebutton_p.h"
|
||||
# include "quickstandardtitlebar_p.h"
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
|
||||
#ifndef QUICK_URI_SHORT
|
||||
# define QUICK_URI_SHORT FRAMELESSHELPER_QUICK_URI, 1
|
||||
#endif
|
||||
|
||||
#ifndef QUICK_URI_FULL
|
||||
# define QUICK_URI_FULL QUICK_URI_SHORT, 0
|
||||
#endif
|
||||
|
||||
#ifndef QUICK_URI_EXPAND
|
||||
# define QUICK_URI_EXPAND(name) QUICK_URI_FULL, name
|
||||
#endif
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
|
||||
{
|
||||
Q_ASSERT(engine);
|
||||
if (!engine) {
|
||||
return;
|
||||
}
|
||||
static bool inited = false;
|
||||
if (inited) {
|
||||
return;
|
||||
}
|
||||
inited = true;
|
||||
qRegisterMetaType<QuickGlobal::Options>();
|
||||
qRegisterMetaType<QuickGlobal::SystemTheme>();
|
||||
qRegisterMetaType<QuickGlobal::SystemButtonType>();
|
||||
qRegisterMetaType<QuickGlobal::ResourceType>();
|
||||
qRegisterMetaType<QuickGlobal::DwmColorizationArea>();
|
||||
qRegisterMetaType<QuickGlobal::Anchor>();
|
||||
qRegisterMetaType<QuickGlobal::ButtonState>();
|
||||
qmlRegisterUncreatableType<QuickGlobal>(QUICK_URI_FULL, "FramelessHelperConstants",
|
||||
FRAMELESSHELPER_STRING_LITERAL("The FramelessHelperConstants namespace is not creatable, you can only use it to access it's enums."));
|
||||
qmlRegisterSingletonType<FramelessQuickUtils>(QUICK_URI_EXPAND("FramelessUtils"),
|
||||
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
|
||||
Q_UNUSED(engine);
|
||||
Q_UNUSED(scriptEngine);
|
||||
return new FramelessQuickUtils;
|
||||
});
|
||||
qmlRegisterRevision<QWindow, 254>(QUICK_URI_FULL);
|
||||
qmlRegisterRevision<QQuickWindow, 254>(QUICK_URI_FULL);
|
||||
qmlRegisterRevision<QQuickItem, 254>(QUICK_URI_FULL);
|
||||
qmlRegisterType<FramelessQuickHelper>(QUICK_URI_EXPAND("FramelessHelper"));
|
||||
qmlRegisterType<FramelessQuickWindow>(QUICK_URI_EXPAND("FramelessWindow"));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qmlRegisterType<QuickStandardMinimizeButton>(QUICK_URI_EXPAND("StandardMinimizeButton"));
|
||||
qmlRegisterType<QuickStandardMaximizeButton>(QUICK_URI_EXPAND("StandardMaximizeButton"));
|
||||
qmlRegisterType<QuickStandardCloseButton>(QUICK_URI_EXPAND("StandardCloseButton"));
|
||||
qmlRegisterType<QuickStandardTitleBar>(QUICK_URI_EXPAND("StandardTitleBar"));
|
||||
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardMinimizeButton"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardMinimizeButton is not available until Qt6."));
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardMaximizeButton"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardMaximizeButton is not available until Qt6."));
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardCloseButton"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardCloseButton is not available until Qt6."));
|
||||
qmlRegisterTypeNotAvailable(QUICK_URI_EXPAND("StandardTitleBar"),
|
||||
FRAMELESSHELPER_STRING_LITERAL("StandardTitleBar is not available until Qt6."));
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qmlRegisterModule(QUICK_URI_FULL);
|
||||
}
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
FramelessHelperQuickPlugin::FramelessHelperQuickPlugin(QObject *parent) : QQmlEngineExtensionPlugin(parent)
|
||||
{
|
||||
}
|
||||
|
||||
FramelessHelperQuickPlugin::~FramelessHelperQuickPlugin() = default;
|
||||
|
||||
void FramelessHelperQuickPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
|
||||
{
|
||||
Q_ASSERT(engine);
|
||||
Q_ASSERT(uri);
|
||||
if (!engine || !uri) {
|
||||
return;
|
||||
}
|
||||
Q_ASSERT(qstrcmp(uri, FRAMELESSHELPER_QUICK_URI) == 0);
|
||||
if (qstrcmp(uri, FRAMELESSHELPER_QUICK_URI) != 0) {
|
||||
return;
|
||||
}
|
||||
FramelessHelper::Quick::registerTypes(engine);
|
||||
}
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 "../../include/FramelessHelper/Quick/framelessquickmodule.h"
|
|
@ -33,7 +33,7 @@ using namespace Global;
|
|||
FramelessQuickUtils::FramelessQuickUtils(QObject *parent) : QObject(parent)
|
||||
{
|
||||
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, [this](){
|
||||
Q_EMIT darkModeEnabledChanged();
|
||||
Q_EMIT systemThemeChanged();
|
||||
Q_EMIT systemAccentColorChanged();
|
||||
Q_EMIT titleBarColorizedChanged();
|
||||
});
|
||||
|
@ -41,12 +41,12 @@ FramelessQuickUtils::FramelessQuickUtils(QObject *parent) : QObject(parent)
|
|||
|
||||
FramelessQuickUtils::~FramelessQuickUtils() = default;
|
||||
|
||||
qreal FramelessQuickUtils::titleBarHeight()
|
||||
qreal FramelessQuickUtils::titleBarHeight() const
|
||||
{
|
||||
return kDefaultTitleBarHeight;
|
||||
}
|
||||
|
||||
bool FramelessQuickUtils::frameBorderVisible()
|
||||
bool FramelessQuickUtils::frameBorderVisible() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return (Utils::isWindowFrameBorderVisible() && !Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2));
|
||||
|
@ -55,7 +55,7 @@ bool FramelessQuickUtils::frameBorderVisible()
|
|||
#endif
|
||||
}
|
||||
|
||||
qreal FramelessQuickUtils::frameBorderThickness()
|
||||
qreal FramelessQuickUtils::frameBorderThickness() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return kDefaultWindowFrameBorderThickness;
|
||||
|
@ -64,12 +64,12 @@ qreal FramelessQuickUtils::frameBorderThickness()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool FramelessQuickUtils::darkModeEnabled()
|
||||
QuickGlobal::SystemTheme FramelessQuickUtils::systemTheme() const
|
||||
{
|
||||
return Utils::shouldAppsUseDarkMode();
|
||||
return FRAMELESSHELPER_ENUM_CORE_TO_QUICK(SystemTheme, Utils::getSystemTheme());
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::systemAccentColor()
|
||||
QColor FramelessQuickUtils::systemAccentColor() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return Utils::getDwmColorizationColor();
|
||||
|
@ -82,37 +82,37 @@ QColor FramelessQuickUtils::systemAccentColor()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool FramelessQuickUtils::titleBarColorized()
|
||||
bool FramelessQuickUtils::titleBarColorized() const
|
||||
{
|
||||
return Utils::isTitleBarColorized();
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemLightColor()
|
||||
QColor FramelessQuickUtils::defaultSystemLightColor() const
|
||||
{
|
||||
return kDefaultSystemLightColor;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemDarkColor()
|
||||
QColor FramelessQuickUtils::defaultSystemDarkColor() const
|
||||
{
|
||||
return kDefaultSystemDarkColor;
|
||||
}
|
||||
|
||||
QSizeF FramelessQuickUtils::defaultSystemButtonSize()
|
||||
QSizeF FramelessQuickUtils::defaultSystemButtonSize() const
|
||||
{
|
||||
return kDefaultSystemButtonSize;
|
||||
}
|
||||
|
||||
QSizeF FramelessQuickUtils::defaultSystemButtonIconSize()
|
||||
QSizeF FramelessQuickUtils::defaultSystemButtonIconSize() const
|
||||
{
|
||||
return kDefaultSystemButtonIconSize;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemButtonBackgroundColor()
|
||||
QColor FramelessQuickUtils::defaultSystemButtonBackgroundColor() const
|
||||
{
|
||||
return kDefaultSystemButtonBackgroundColor;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::defaultSystemCloseButtonBackgroundColor()
|
||||
QColor FramelessQuickUtils::defaultSystemCloseButtonBackgroundColor() const
|
||||
{
|
||||
return kDefaultSystemCloseButtonBackgroundColor;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <QtQuick/private/qquickitem_p.h>
|
||||
#include <QtQuick/private/qquickrectangle_p.h>
|
||||
#include <QtQuick/private/qquickanchors_p.h>
|
||||
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
|
||||
#include <framelesswindowsmanager.h>
|
||||
#include <utils.h>
|
||||
|
||||
|
@ -35,67 +34,6 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
|||
|
||||
using namespace Global;
|
||||
|
||||
static constexpr const char QTQUICK_ITEM_CLASS_NAME[] = "QQuickItem";
|
||||
static constexpr const char QTQUICK_BUTTON_CLASS_NAME[] = "QQuickAbstractButton";
|
||||
|
||||
[[nodiscard]] static inline QuickGlobal::Options optionsCoreToQuick(const Options value)
|
||||
{
|
||||
QuickGlobal::Options result = {};
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, ForceHideWindowFrameBorder, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, ForceShowWindowFrameBorder, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontDrawTopWindowFrameBorder, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontForceSquareWindowCorners, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, TransparentWindowBackground, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DisableWindowsSnapLayout, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, CreateStandardWindowLayout, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, BeCompatibleWithQtFramelessWindowHint, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontTouchQtInternals, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontTouchWindowFrameBorderColor, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontInstallSystemMenuHook, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DisableSystemMenu, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, NoDoubleClickMaximizeToggle, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DisableResizing, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DisableDragging, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontTouchCursorShape, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontMoveWindowToDesktopCenter, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontTreatFullScreenAsZoomed, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontTouchHighDpiScalingPolicy, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontTouchScaleFactorRoundingPolicy, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontTouchProcessDpiAwarenessLevel, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, DontEnsureNonNativeWidgetSiblings, value, result)
|
||||
FRAMELESSHELPER_FLAGS_CORE_TO_QUICK(Option, SyncNativeControlsThemeWithSystem, value, result)
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline Options optionsQuickToCore(const QuickGlobal::Options value)
|
||||
{
|
||||
Options result = {};
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, ForceHideWindowFrameBorder, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, ForceShowWindowFrameBorder, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontDrawTopWindowFrameBorder, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontForceSquareWindowCorners, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, TransparentWindowBackground, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DisableWindowsSnapLayout, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, CreateStandardWindowLayout, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, BeCompatibleWithQtFramelessWindowHint, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontTouchQtInternals, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontTouchWindowFrameBorderColor, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontInstallSystemMenuHook, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DisableSystemMenu, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, NoDoubleClickMaximizeToggle, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DisableResizing, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DisableDragging, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontTouchCursorShape, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontMoveWindowToDesktopCenter, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontTreatFullScreenAsZoomed, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontTouchHighDpiScalingPolicy, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontTouchScaleFactorRoundingPolicy, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontTouchProcessDpiAwarenessLevel, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, DontEnsureNonNativeWidgetSiblings, value, result)
|
||||
FRAMELESSHELPER_FLAGS_QUICK_TO_CORE(Option, SyncNativeControlsThemeWithSystem, value, result)
|
||||
return result;
|
||||
}
|
||||
|
||||
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q, const UserSettings &settings) : QObject(q)
|
||||
{
|
||||
Q_ASSERT(q);
|
||||
|
@ -160,23 +98,6 @@ bool FramelessQuickWindowPrivate::isFullScreen() const
|
|||
return (q->visibility() == FramelessQuickWindow::FullScreen);
|
||||
}
|
||||
|
||||
bool FramelessQuickWindowPrivate::isFixedSize() const
|
||||
{
|
||||
if (m_settings.options & Option::DisableResizing) {
|
||||
return true;
|
||||
}
|
||||
Q_Q(const FramelessQuickWindow);
|
||||
if (q->flags() & Qt::MSWindowsFixedSizeDialogHint) {
|
||||
return true;
|
||||
}
|
||||
const QSize minSize = q->minimumSize();
|
||||
const QSize maxSize = q->maximumSize();
|
||||
if (!minSize.isEmpty() && !maxSize.isEmpty() && (minSize == maxSize)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QColor FramelessQuickWindowPrivate::getFrameBorderColor() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
@ -217,77 +138,6 @@ QQuickAnchorLine FramelessQuickWindowPrivate::getTopBorderVerticalCenter() const
|
|||
return QQuickAnchorLine(m_topBorderRectangle.data(), QQuickAnchors::VCenterAnchor);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setTitleBarItem(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
if (m_titleBarItem == item) {
|
||||
return;
|
||||
}
|
||||
m_titleBarItem = item;
|
||||
Q_Q(FramelessQuickWindow);
|
||||
Q_EMIT q->titleBarItemChanged();
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setHitTestVisible(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
static constexpr const bool visible = true;
|
||||
const bool exists = m_hitTestVisibleItems.contains(item);
|
||||
if (visible && !exists) {
|
||||
m_hitTestVisibleItems.append(item);
|
||||
}
|
||||
if constexpr (!visible && exists) {
|
||||
m_hitTestVisibleItems.removeAll(item);
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::moveToDesktopCenter()
|
||||
{
|
||||
Utils::moveWindowToDesktopCenter(m_params.getWindowScreen, m_params.getWindowSize,
|
||||
m_params.setWindowPosition, true);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setFixedSize(const bool value, const bool force)
|
||||
{
|
||||
if ((isFixedSize() == value) && !force) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (value) {
|
||||
const QSize size = q->size();
|
||||
q->setMinimumSize(size);
|
||||
q->setMaximumSize(size);
|
||||
q->setFlags(q->flags() | Qt::MSWindowsFixedSizeDialogHint);
|
||||
} else {
|
||||
q->setFlags(q->flags() & ~Qt::MSWindowsFixedSizeDialogHint);
|
||||
q->setMinimumSize(kDefaultWindowSize);
|
||||
q->setMaximumSize(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Utils::setAeroSnappingEnabled(q->winId(), !value);
|
||||
#endif
|
||||
Q_EMIT q->fixedSizeChanged();
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::bringToFront()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (isHidden()) {
|
||||
q->show();
|
||||
}
|
||||
if (isMinimized()) {
|
||||
q->showNormal(); // ### FIXME !!!
|
||||
}
|
||||
q->raise();
|
||||
q->requestActivate();
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::snapToTopBorder(QQuickItem *item, const QuickGlobal::Anchor itemAnchor, const QuickGlobal::Anchor topBorderAnchor)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
|
@ -340,74 +190,6 @@ void FramelessQuickWindowPrivate::snapToTopBorder(QQuickItem *item, const QuickG
|
|||
}
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setOptions(const QuickGlobal::Options value)
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (m_quickOptions == value) {
|
||||
return;
|
||||
}
|
||||
// ### TODO: re-evaluate some usable options.
|
||||
m_quickOptions = value;
|
||||
m_settings.options = optionsQuickToCore(m_quickOptions);
|
||||
Q_EMIT q->optionsChanged();
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
Q_ASSERT(buttonType != QuickGlobal::SystemButtonType::Unknown);
|
||||
if (!item || (buttonType == QuickGlobal::SystemButtonType::Unknown)) {
|
||||
return;
|
||||
}
|
||||
switch (buttonType) {
|
||||
case QuickGlobal::SystemButtonType::Unknown:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::WindowIcon:
|
||||
m_settings.windowIconButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Help:
|
||||
m_settings.contextHelpButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Minimize:
|
||||
m_settings.minimizeButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Maximize:
|
||||
case QuickGlobal::SystemButtonType::Restore:
|
||||
m_settings.maximizeButton = item;
|
||||
break;
|
||||
case QuickGlobal::SystemButtonType::Close:
|
||||
m_settings.closeButton = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool FramelessQuickWindowPrivate::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_ASSERT(object);
|
||||
Q_ASSERT(event);
|
||||
if (!object || !event) {
|
||||
return false;
|
||||
}
|
||||
if (!object->isWindowType()) {
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
const auto window = qobject_cast<FramelessQuickWindow *>(object);
|
||||
if (window != q) {
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
switch (event->type()) {
|
||||
case QEvent::Show: {
|
||||
const auto showEvent = static_cast<QShowEvent *>(event);
|
||||
showEventHandler(showEvent);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::showMinimized2()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
|
@ -424,9 +206,6 @@ void FramelessQuickWindowPrivate::showMinimized2()
|
|||
|
||||
void FramelessQuickWindowPrivate::toggleMaximized()
|
||||
{
|
||||
if (isFixedSize()) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (isZoomed()) {
|
||||
q->showNormal();
|
||||
|
@ -437,9 +216,6 @@ void FramelessQuickWindowPrivate::toggleMaximized()
|
|||
|
||||
void FramelessQuickWindowPrivate::toggleFullScreen()
|
||||
{
|
||||
if (isFixedSize()) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (isFullScreen()) {
|
||||
q->setVisibility(m_savedVisibility);
|
||||
|
@ -449,79 +225,12 @@ void FramelessQuickWindowPrivate::toggleFullScreen()
|
|||
}
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::showSystemMenu(const QPoint &pos)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Q_Q(FramelessQuickWindow);
|
||||
const QPoint globalPos = q->mapToGlobal(pos);
|
||||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->effectiveDevicePixelRatio()).toPoint();
|
||||
Utils::showSystemMenu(q->winId(), nativePos, m_settings.systemMenuOffset,
|
||||
false, m_settings.options, m_params.isWindowFixedSize);
|
||||
#else
|
||||
Q_UNUSED(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::startSystemMove2(const QPoint &pos)
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
Utils::startSystemMove(q, pos);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::startSystemResize2(const Qt::Edges edges, const QPoint &pos)
|
||||
{
|
||||
if (isFixedSize()) {
|
||||
return;
|
||||
}
|
||||
if (edges == Qt::Edges{}) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
Utils::startSystemResize(q, edges, pos);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::initialize()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
m_params.getWindowId = [q]() -> WId { return q->winId(); };
|
||||
m_params.getWindowFlags = [q]() -> Qt::WindowFlags { return q->flags(); };
|
||||
m_params.setWindowFlags = [q](const Qt::WindowFlags flags) -> void { q->setFlags(flags); };
|
||||
m_params.getWindowSize = [q]() -> QSize { return q->size(); };
|
||||
m_params.setWindowSize = [q](const QSize &size) -> void { q->resize(size); };
|
||||
m_params.getWindowPosition = [q]() -> QPoint { return q->position(); };
|
||||
m_params.setWindowPosition = [q](const QPoint &pos) -> void { q->setX(pos.x()); q->setY(pos.y()); };
|
||||
m_params.getWindowScreen = [q]() -> QScreen * { return q->screen(); };
|
||||
m_params.isWindowFixedSize = [this]() -> bool { return isFixedSize(); };
|
||||
m_params.setWindowFixedSize = [this](const bool value) -> void { setFixedSize(value); };
|
||||
m_params.getWindowState = [q]() -> Qt::WindowState { return q->windowState(); };
|
||||
m_params.setWindowState = [q](const Qt::WindowState state) -> void { q->setWindowState(state); };
|
||||
m_params.getWindowHandle = [q]() -> QWindow * { return q; };
|
||||
m_params.windowToScreen = [q](const QPoint &pos) -> QPoint { return q->mapToGlobal(pos); };
|
||||
m_params.screenToWindow = [q](const QPoint &pos) -> QPoint { return q->mapFromGlobal(pos); };
|
||||
m_params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool {
|
||||
QuickGlobal::SystemButtonType button2 = QuickGlobal::SystemButtonType::Unknown;
|
||||
const bool result = isInSystemButtons(pos, &button2);
|
||||
*button = FRAMELESSHELPER_ENUM_QUICK_TO_CORE(SystemButtonType, button2);
|
||||
return result;
|
||||
};
|
||||
m_params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); };
|
||||
m_params.getWindowDevicePixelRatio = [q]() -> qreal { return q->effectiveDevicePixelRatio(); };
|
||||
m_params.setSystemButtonState = [this](const SystemButtonType button, const ButtonState state) -> void {
|
||||
setSystemButtonState(FRAMELESSHELPER_ENUM_CORE_TO_QUICK(SystemButtonType, button),
|
||||
FRAMELESSHELPER_ENUM_CORE_TO_QUICK(ButtonState, state));
|
||||
};
|
||||
m_params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); };
|
||||
m_params.showSystemMenu = [this](const QPoint &pos) -> void { showSystemMenu(pos); };
|
||||
if (m_settings.options & Option::DisableResizing) {
|
||||
setFixedSize(true, true);
|
||||
}
|
||||
if (m_settings.options & Option::TransparentWindowBackground) {
|
||||
q->setColor(kDefaultTransparentColor);
|
||||
}
|
||||
m_quickOptions = optionsCoreToQuick(m_settings.options);
|
||||
FramelessWindowsManager * const manager = FramelessWindowsManager::instance();
|
||||
manager->addWindow(m_settings, m_params);
|
||||
q->installEventFilter(this);
|
||||
QQuickItem * const rootItem = q->contentItem();
|
||||
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||
|
@ -545,115 +254,12 @@ void FramelessQuickWindowPrivate::initialize()
|
|||
Q_EMIT q->fullScreenChanged();
|
||||
});
|
||||
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this, q](){
|
||||
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, [this, q](){
|
||||
updateTopBorderColor();
|
||||
Q_EMIT q->frameBorderColorChanged();
|
||||
});
|
||||
}
|
||||
|
||||
QRect FramelessQuickWindowPrivate::mapItemGeometryToScene(const QQuickItem * const item) const
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return {};
|
||||
}
|
||||
const QPointF originPoint = item->mapToScene(QPointF(0.0, 0.0));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||
const QSizeF size = item->size();
|
||||
#else
|
||||
const QSizeF size = {item->width(), item->height()};
|
||||
#endif
|
||||
return QRectF(originPoint, size).toRect();
|
||||
}
|
||||
|
||||
bool FramelessQuickWindowPrivate::isInSystemButtons(const QPoint &pos, QuickGlobal::SystemButtonType *button) const
|
||||
{
|
||||
Q_ASSERT(button);
|
||||
if (!button) {
|
||||
return false;
|
||||
}
|
||||
*button = QuickGlobal::SystemButtonType::Unknown;
|
||||
if (m_settings.windowIconButton && m_settings.windowIconButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto iconBtn = qobject_cast<QQuickItem *>(m_settings.windowIconButton);
|
||||
if (mapItemGeometryToScene(iconBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::WindowIcon;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_settings.contextHelpButton && m_settings.contextHelpButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto helpBtn = qobject_cast<QQuickItem *>(m_settings.contextHelpButton);
|
||||
if (mapItemGeometryToScene(helpBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Help;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_settings.minimizeButton && m_settings.minimizeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto minBtn = qobject_cast<QQuickItem *>(m_settings.minimizeButton);
|
||||
if (mapItemGeometryToScene(minBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Minimize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_settings.maximizeButton && m_settings.maximizeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto maxBtn = qobject_cast<QQuickItem *>(m_settings.maximizeButton);
|
||||
if (mapItemGeometryToScene(maxBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Maximize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_settings.closeButton && m_settings.closeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto closeBtn = qobject_cast<QQuickItem *>(m_settings.closeButton);
|
||||
if (mapItemGeometryToScene(closeBtn).contains(pos)) {
|
||||
*button = QuickGlobal::SystemButtonType::Close;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FramelessQuickWindowPrivate::isInTitleBarDraggableArea(const QPoint &pos) const
|
||||
{
|
||||
if (!m_titleBarItem) {
|
||||
return false;
|
||||
}
|
||||
QRegion region = mapItemGeometryToScene(m_titleBarItem);
|
||||
const auto systemButtons = {m_settings.windowIconButton, m_settings.contextHelpButton,
|
||||
m_settings.minimizeButton, m_settings.maximizeButton, m_settings.closeButton};
|
||||
for (auto &&button : qAsConst(systemButtons)) {
|
||||
if (button && button->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
||||
const auto quickButton = qobject_cast<QQuickItem *>(button);
|
||||
region -= mapItemGeometryToScene(quickButton);
|
||||
}
|
||||
}
|
||||
if (!m_hitTestVisibleItems.isEmpty()) {
|
||||
for (auto &&item : qAsConst(m_hitTestVisibleItems)) {
|
||||
Q_ASSERT(item);
|
||||
if (item) {
|
||||
region -= mapItemGeometryToScene(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return region.contains(pos);
|
||||
}
|
||||
|
||||
bool FramelessQuickWindowPrivate::shouldIgnoreMouseEvents(const QPoint &pos) const
|
||||
{
|
||||
Q_Q(const FramelessQuickWindow);
|
||||
const bool withinFrameBorder = [&pos, q]() -> bool {
|
||||
if (pos.y() < kDefaultResizeBorderThickness) {
|
||||
return true;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (Utils::isWindowFrameBorderVisible()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return ((pos.x() < kDefaultResizeBorderThickness)
|
||||
|| (pos.x() >= (q->width() - kDefaultResizeBorderThickness)));
|
||||
}();
|
||||
return (isNormal() && withinFrameBorder);
|
||||
}
|
||||
|
||||
bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
@ -664,120 +270,6 @@ bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const
|
|||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setSystemButtonState(const QuickGlobal::SystemButtonType button,
|
||||
const QuickGlobal::ButtonState state)
|
||||
{
|
||||
Q_ASSERT(button != QuickGlobal::SystemButtonType::Unknown);
|
||||
if (button == QuickGlobal::SystemButtonType::Unknown) {
|
||||
return;
|
||||
}
|
||||
QQuickAbstractButton *quickButton = nullptr;
|
||||
switch (button) {
|
||||
case QuickGlobal::SystemButtonType::Unknown: {
|
||||
Q_ASSERT(false);
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::WindowIcon: {
|
||||
if (m_settings.windowIconButton && m_settings.windowIconButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(m_settings.windowIconButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Help: {
|
||||
if (m_settings.contextHelpButton && m_settings.contextHelpButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(m_settings.contextHelpButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Minimize: {
|
||||
if (m_settings.minimizeButton && m_settings.minimizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(m_settings.minimizeButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Maximize:
|
||||
case QuickGlobal::SystemButtonType::Restore: {
|
||||
if (m_settings.maximizeButton && m_settings.maximizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(m_settings.maximizeButton);
|
||||
}
|
||||
} break;
|
||||
case QuickGlobal::SystemButtonType::Close: {
|
||||
if (m_settings.closeButton && m_settings.closeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||
quickButton = qobject_cast<QQuickAbstractButton *>(m_settings.closeButton);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
if (quickButton) {
|
||||
const auto updateButtonState = [state](QQuickAbstractButton *btn) -> void {
|
||||
Q_ASSERT(btn);
|
||||
if (!btn) {
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case QuickGlobal::ButtonState::Unspecified: {
|
||||
btn->setDown(false);
|
||||
btn->setPressed(false);
|
||||
btn->setHovered(false);
|
||||
} break;
|
||||
case QuickGlobal::ButtonState::Hovered: {
|
||||
btn->setDown(false);
|
||||
btn->setPressed(false);
|
||||
btn->setHovered(true);
|
||||
} break;
|
||||
case QuickGlobal::ButtonState::Pressed: {
|
||||
btn->setHovered(true);
|
||||
btn->setDown(true);
|
||||
btn->setPressed(true);
|
||||
} break;
|
||||
case QuickGlobal::ButtonState::Clicked: {
|
||||
// Clicked: pressed --> released, so behave like hovered.
|
||||
btn->setDown(false);
|
||||
btn->setPressed(false);
|
||||
btn->setHovered(true);
|
||||
// "QQuickAbstractButtonPrivate::click()"'s implementation is nothing but
|
||||
// emits the "clicked" signal of the public interface, so we just emit
|
||||
// the signal directly to avoid accessing the private implementation.
|
||||
Q_EMIT btn->clicked();
|
||||
} break;
|
||||
}
|
||||
};
|
||||
updateButtonState(quickButton);
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
Q_EMIT q->systemButtonStateChanged(button, state);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::showEventHandler(QShowEvent *event)
|
||||
{
|
||||
Q_ASSERT(event);
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
if (m_windowExposed) {
|
||||
return;
|
||||
}
|
||||
m_windowExposed = true;
|
||||
if (m_settings.options & Option::DontMoveWindowToDesktopCenter) {
|
||||
if (!m_settings.startupPosition.isNull()) {
|
||||
m_params.setWindowPosition(m_settings.startupPosition);
|
||||
}
|
||||
if (!m_settings.startupSize.isEmpty()) {
|
||||
m_params.setWindowSize(m_settings.startupSize);
|
||||
}
|
||||
if (m_settings.startupState != Qt::WindowNoState) {
|
||||
m_params.setWindowState(m_settings.startupState);
|
||||
}
|
||||
} else {
|
||||
moveToDesktopCenter();
|
||||
}
|
||||
}
|
||||
|
||||
QuickGlobal::Options FramelessQuickWindowPrivate::getOptions() const
|
||||
{
|
||||
return m_quickOptions;
|
||||
}
|
||||
|
||||
QQuickItem *FramelessQuickWindowPrivate::getTitleBarItem() const
|
||||
{
|
||||
return m_titleBarItem;
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::updateTopBorderColor()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
@ -799,9 +291,9 @@ void FramelessQuickWindowPrivate::updateTopBorderHeight()
|
|||
#endif
|
||||
}
|
||||
|
||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent, const UserSettings &settings) : QQuickWindow(parent)
|
||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent, const UserSettings &settings)
|
||||
: QQuickWindow(parent), d_ptr(new FramelessQuickWindowPrivate(this, settings))
|
||||
{
|
||||
d_ptr.reset(new FramelessQuickWindowPrivate(this, settings));
|
||||
}
|
||||
|
||||
FramelessQuickWindow::~FramelessQuickWindow() = default;
|
||||
|
@ -836,74 +328,12 @@ bool FramelessQuickWindow::isFullScreen() const
|
|||
return d->isFullScreen();
|
||||
}
|
||||
|
||||
bool FramelessQuickWindow::isFixedSize() const
|
||||
{
|
||||
Q_D(const FramelessQuickWindow);
|
||||
return d->isFixedSize();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::setFixedSize(const bool value)
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->setFixedSize(value);
|
||||
}
|
||||
|
||||
QColor FramelessQuickWindow::frameBorderColor() const
|
||||
{
|
||||
Q_D(const FramelessQuickWindow);
|
||||
return d->getFrameBorderColor();
|
||||
}
|
||||
|
||||
QuickGlobal::Options FramelessQuickWindow::options() const
|
||||
{
|
||||
Q_D(const FramelessQuickWindow);
|
||||
return d->getOptions();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::setOptions(const QuickGlobal::Options value)
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->setOptions(value);
|
||||
}
|
||||
|
||||
QQuickItem *FramelessQuickWindow::titleBarItem() const
|
||||
{
|
||||
Q_D(const FramelessQuickWindow);
|
||||
return d->getTitleBarItem();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::setTitleBarItem(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->setTitleBarItem(item);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::setHitTestVisible(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->setHitTestVisible(item);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::moveToDesktopCenter()
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->moveToDesktopCenter();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::bringToFront()
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->bringToFront();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::snapToTopBorder(QQuickItem *item, const QuickGlobal::Anchor itemAnchor, const QuickGlobal::Anchor topBorderAnchor)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
|
@ -914,17 +344,6 @@ void FramelessQuickWindow::snapToTopBorder(QQuickItem *item, const QuickGlobal::
|
|||
d->snapToTopBorder(item, itemAnchor, topBorderAnchor);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
Q_ASSERT(buttonType != QuickGlobal::SystemButtonType::Unknown);
|
||||
if (!item || (buttonType == QuickGlobal::SystemButtonType::Unknown)) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->setSystemButton(item, buttonType);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::showMinimized2()
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
|
@ -943,25 +362,4 @@ void FramelessQuickWindow::toggleFullScreen()
|
|||
d->toggleFullScreen();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::showSystemMenu(const QPoint &pos)
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->showSystemMenu(pos);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::startSystemMove2(const QPoint &pos)
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->startSystemMove2(pos);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::startSystemResize2(const Qt::Edges edges, const QPoint &pos)
|
||||
{
|
||||
if (edges == Qt::Edges{}) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->startSystemResize2(edges, pos);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "framelesshelperquick_global.h"
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtQuick/qquickwindow.h>
|
||||
#include <QtQuick/private/qquickanchors_p_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -55,7 +55,6 @@ public:
|
|||
Q_INVOKABLE Q_NODISCARD bool isMinimized() const;
|
||||
Q_INVOKABLE Q_NODISCARD bool isZoomed() const;
|
||||
Q_INVOKABLE Q_NODISCARD bool isFullScreen() const;
|
||||
Q_INVOKABLE Q_NODISCARD bool isFixedSize() const;
|
||||
|
||||
Q_INVOKABLE Q_NODISCARD QColor getFrameBorderColor() const;
|
||||
Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderTop() const;
|
||||
|
@ -65,39 +64,15 @@ public:
|
|||
Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderHorizontalCenter() const;
|
||||
Q_INVOKABLE Q_NODISCARD QQuickAnchorLine getTopBorderVerticalCenter() const;
|
||||
|
||||
Q_INVOKABLE void showEventHandler(QShowEvent *event);
|
||||
|
||||
Q_INVOKABLE Q_NODISCARD QuickGlobal::Options getOptions() const;
|
||||
|
||||
Q_INVOKABLE Q_NODISCARD QQuickItem *getTitleBarItem() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void showMinimized2();
|
||||
void toggleMaximized();
|
||||
void toggleFullScreen();
|
||||
void showSystemMenu(const QPoint &pos);
|
||||
void startSystemMove2(const QPoint &pos);
|
||||
void startSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
||||
void setTitleBarItem(QQuickItem *item);
|
||||
void setHitTestVisible(QQuickItem *item);
|
||||
void moveToDesktopCenter();
|
||||
void setFixedSize(const bool value, const bool force = false);
|
||||
void bringToFront();
|
||||
void snapToTopBorder(QQuickItem *item, const QuickGlobal::Anchor itemAnchor, const QuickGlobal::Anchor topBorderAnchor);
|
||||
void setOptions(const QuickGlobal::Options value);
|
||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||
|
||||
protected:
|
||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const;
|
||||
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, QuickGlobal::SystemButtonType *button) const;
|
||||
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
|
||||
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
||||
Q_NODISCARD bool shouldDrawFrameBorder() const;
|
||||
void setSystemButtonState(const QuickGlobal::SystemButtonType button, const QuickGlobal::ButtonState state);
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateTopBorderColor();
|
||||
|
@ -107,13 +82,9 @@ private:
|
|||
FramelessQuickWindow *q_ptr = nullptr;
|
||||
QScopedPointer<QQuickRectangle> m_topBorderRectangle;
|
||||
QScopedPointer<QQuickAnchors> m_topBorderAnchors;
|
||||
QWindow::Visibility m_savedVisibility = QWindow::Windowed;
|
||||
QQuickWindow::Visibility m_savedVisibility = QQuickWindow::Windowed;
|
||||
Global::UserSettings m_settings = {};
|
||||
Global::SystemParameters m_params = {};
|
||||
bool m_windowExposed = false;
|
||||
QPointer<QQuickItem> m_titleBarItem = nullptr;
|
||||
QList<QQuickItem *> m_hitTestVisibleItems = {};
|
||||
QuickGlobal::Options m_quickOptions = {};
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -39,7 +39,6 @@ using namespace Global;
|
|||
|
||||
static constexpr const char FRAMELESSHELPER_PROP_NAME[] = "__wwx190_FramelessWidgetsHelper_instance";
|
||||
static constexpr const char QTWIDGETS_MAINWINDOW_CLASS_NAME[] = "QMainWindow";
|
||||
static constexpr const char FRAMELESSHELPER_SYSTEMBUTTON_CLASS_NAME[] = "StandardSystemButton";
|
||||
|
||||
FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetColorTemplate, "color: %1;")
|
||||
FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetBackgroundColorTemplate, "background-color: %1;")
|
||||
|
@ -602,8 +601,6 @@ void FramelessWidgetsHelper::setSystemButtonState(const SystemButtonType button,
|
|||
};
|
||||
updateButtonState(widgetButton);
|
||||
}
|
||||
QMetaObject::invokeMethod(q, "systemButtonStateChanged",
|
||||
Q_ARG(Global::SystemButtonType, button), Q_ARG(Global::ButtonState, state));
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::updateContentsMargins()
|
||||
|
|
Loading…
Reference in New Issue