forked from github_mirror/framelesshelper
refactor widgets interface
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
306ebfc717
commit
81e736570f
21
README.md
21
README.md
|
@ -44,19 +44,6 @@
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
- 2.1
|
|
||||||
- [ ] All: Add cross-platform system menu for both Qt Widgets and Qt Quick. Support both light and dark theme. Can be triggered by right-clicking on the title bar area or pressing the system menu shortcut (ALT + SPACE).
|
|
||||||
- [ ] All: Add QtWebEngine demo applications for both Qt Widgets and Qt Quick.
|
|
||||||
- [ ] All: Make more settings and options configurable through environment variables and configuration files.
|
|
||||||
- [ ] Windows: Snap layout feature introduced in Windows 11.
|
|
||||||
- Future versions
|
|
||||||
- [ ] Linux: Support runtime theme switching.
|
|
||||||
- [ ] Linux: Move window resize area outside of the client area.
|
|
||||||
- [ ] macOS: Move window resize area outside of the client area.
|
|
||||||
- [ ] More feature requests are welcome!
|
|
||||||
|
|
||||||
## Requiredments
|
## Requiredments
|
||||||
|
|
||||||
- Compiler: a modern compiler which supports C++17 at least.
|
- Compiler: a modern compiler which supports C++17 at least.
|
||||||
|
@ -74,7 +61,7 @@ cmake -DCMAKE_PREFIX_PATH=<YOUR_QT_SDK_DIR_PATH> -DCMAKE_BUILD_TYPE=Release -GNi
|
||||||
cmake --build . --config Release --target all --parallel
|
cmake --build . --config Release --target all --parallel
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: On Linux you need to install the GTK3 and X11 development packages first.
|
**Note**: On Linux you need to install the _GTK3_ and _X11_ development packages first.
|
||||||
|
|
||||||
## Use
|
## Use
|
||||||
|
|
||||||
|
@ -97,6 +84,12 @@ Please refer to the demo applications to see more detailed usages: [examples](./
|
||||||
- Force your application use pure software rendering instead of rendering through OpenGL.
|
- Force your application use pure software rendering instead of rendering through OpenGL.
|
||||||
- Or just don't use OpenGL at all, try to use Direct3D/Vulkan/Metal instead.
|
- Or just don't use OpenGL at all, try to use Direct3D/Vulkan/Metal instead.
|
||||||
- Due to there are many sub-versions of Windows 10, it's highly recommended to use the latest version of Windows 10, at least no older than Windows 10 1809. If you try to use this framework on some very old Windows 10 versions such as 1507 or 1607, there may be some compatibility issues. Using this framework on Windows 7 is also supported but not recommended. To get the most stable behavior and the best appearance, you should use it on the latest version of Windows 10 or Windows 11.
|
- Due to there are many sub-versions of Windows 10, it's highly recommended to use the latest version of Windows 10, at least no older than Windows 10 1809. If you try to use this framework on some very old Windows 10 versions such as 1507 or 1607, there may be some compatibility issues. Using this framework on Windows 7 is also supported but not recommended. To get the most stable behavior and the best appearance, you should use it on the latest version of Windows 10 or Windows 11.
|
||||||
|
- To make the snap layout work as expected, there are some additional requirements for your homemade system buttons to follow:
|
||||||
|
- Make sure there are two public invokable functions (slot functions are always invokable): `void setHovered(bool)` and `void setPressed(bool)`. These two functions will be invoked by FramelessHelper when the button is being hovered or pressed. You should change the button's visual state inside these functions.
|
||||||
|
- Make sure there's a public signal: `void clicked()`. When the button is being clicked, that signal will be triggered by FramelessHelper. You should connect your event handler to that signal.
|
||||||
|
- Don't forget to call `setSystemButton()` for each button to let FramelessHelper know which is the minimize/maximize/close button.
|
||||||
|
- System buttons will not be able to receive any actual mouse events so there's no need to handle any mouse events inside these buttons. That's also why we need to set the button's visual state manually.
|
||||||
|
- I know this is making everything complicated but unfortunately we can't avoid this mess if we need to support the snap layout feature. Snap layout is really only designed for the original standard window frame, so if we want to forcely support it without a standard window frame, many black magic will be needed.
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,10 @@
|
||||||
]]
|
]]
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
TitleBar.ui
|
mainwindow.ui
|
||||||
MainWindow.ui
|
|
||||||
mainwindow.h
|
mainwindow.h
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
systembutton.h
|
|
||||||
systembutton.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
|
@ -1,276 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>TitleBar</class>
|
|
||||||
<widget class="QWidget" name="TitleBar">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>552</width>
|
|
||||||
<height>30</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QMenuBar {
|
|
||||||
background-color: transparent;
|
|
||||||
height: 23px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#iconButton, #minimizeButton, #maximizeButton, #closeButton {
|
|
||||||
border-style: none;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
#minimizeButton:hover, #maximizeButton:hover {
|
|
||||||
background-color: #c7c7c7;
|
|
||||||
}
|
|
||||||
|
|
||||||
#minimizeButton:pressed, #maximizeButton:pressed {
|
|
||||||
background-color: #808080;
|
|
||||||
}
|
|
||||||
|
|
||||||
#closeButton:hover {
|
|
||||||
background-color: #e81123;
|
|
||||||
}
|
|
||||||
|
|
||||||
#closeButton:pressed {
|
|
||||||
background-color: #8c0a15;
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="iconButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>30</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>30</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="titleLabel">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Segoe UI</family>
|
|
||||||
<pointsize>9</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Hello, World!</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="SystemButton" name="minimizeButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>45</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>45</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::NoContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Minimize</string>
|
|
||||||
</property>
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>16</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="SystemButton" name="maximizeButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>45</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>45</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::NoContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Maximize</string>
|
|
||||||
</property>
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>16</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="SystemButton" name="closeButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>45</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>45</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::NoContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Close</string>
|
|
||||||
</property>
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>16</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>SystemButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>systembutton.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
|
@ -23,9 +23,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "ui_MainWindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "ui_TitleBar.h"
|
#include <QtWidgets/qboxlayout.h>
|
||||||
#include <Utils>
|
#include <Utils>
|
||||||
|
#include <StandardTitleBar>
|
||||||
|
#include <StandardSystemButton>
|
||||||
|
#include <FramelessWidgetsHelper>
|
||||||
|
|
||||||
FRAMELESSHELPER_USE_NAMESPACE
|
FRAMELESSHELPER_USE_NAMESPACE
|
||||||
|
|
||||||
|
@ -33,62 +36,31 @@ using namespace Global;
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent, const Qt::WindowFlags flags) : FramelessMainWindow(parent, flags)
|
MainWindow::MainWindow(QWidget *parent, const Qt::WindowFlags flags) : FramelessMainWindow(parent, flags)
|
||||||
{
|
{
|
||||||
setupUi();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() = default;
|
MainWindow::~MainWindow() = default;
|
||||||
|
|
||||||
void MainWindow::changeEvent(QEvent *event)
|
void MainWindow::initialize()
|
||||||
{
|
{
|
||||||
FramelessMainWindow::changeEvent(event);
|
m_titleBar.reset(new StandardTitleBar(this));
|
||||||
if (event->type() == QEvent::WindowStateChange) {
|
m_mainWindow.reset(new Ui::MainWindow);
|
||||||
Q_EMIT windowStateChanged();
|
m_mainWindow->setupUi(this);
|
||||||
}
|
|
||||||
}
|
QMenuBar * const mb = menuBar();
|
||||||
|
const auto titleBarLayout = static_cast<QHBoxLayout *>(m_titleBar->layout());
|
||||||
void MainWindow::setupUi()
|
titleBarLayout->insertWidget(0, mb);
|
||||||
{
|
|
||||||
mainWindow.reset(new Ui::MainWindow);
|
// "setMenuWidget()" will insert the menu widget on the window's top, just below
|
||||||
mainWindow->setupUi(this);
|
// system's title bar (if it's still there).
|
||||||
|
setMenuWidget(m_titleBar.data());
|
||||||
const auto titleBarWidget = new QWidget(this);
|
|
||||||
titleBar.reset(new Ui::TitleBar);
|
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
||||||
titleBar->setupUi(titleBarWidget);
|
helper->setTitleBarWidget(m_titleBar.data());
|
||||||
|
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||||
const SystemTheme theme = SystemTheme::Light;
|
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||||
const ResourceType resource = ResourceType::Icon;
|
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
||||||
titleBar->minimizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Minimize, theme, resource)));
|
helper->setHitTestVisible(mb); // IMPORTANT!
|
||||||
titleBar->maximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Maximize, theme, resource)));
|
|
||||||
titleBar->closeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(SystemButtonType::Close, theme, resource)));
|
setWindowTitle(tr("FramelessHelper demo application - Qt MainWindow"));
|
||||||
|
|
||||||
QMenuBar *mb = menuBar();
|
|
||||||
titleBar->horizontalLayout->insertWidget(1, mb);
|
|
||||||
|
|
||||||
// This call to the setMenuWidget() function is only needed by this example
|
|
||||||
// application to achieve some special effects, don't use it in your own
|
|
||||||
// code if you don't know what's it for!
|
|
||||||
setMenuWidget(titleBarWidget);
|
|
||||||
|
|
||||||
setTitleBarWidget(titleBarWidget);
|
|
||||||
|
|
||||||
setHitTestVisible(mb); // IMPORTANT!
|
|
||||||
setSystemButton(titleBar->minimizeButton, SystemButtonType::Minimize);
|
|
||||||
setSystemButton(titleBar->maximizeButton, SystemButtonType::Maximize);
|
|
||||||
setSystemButton(titleBar->closeButton, SystemButtonType::Close);
|
|
||||||
|
|
||||||
connect(titleBar->minimizeButton, &QPushButton::clicked, this, &MainWindow::showMinimized);
|
|
||||||
connect(titleBar->maximizeButton, &QPushButton::clicked, this, &MainWindow::toggleMaximized);
|
|
||||||
connect(titleBar->closeButton, &QPushButton::clicked, this, &MainWindow::close);
|
|
||||||
connect(this, &MainWindow::windowIconChanged, titleBar->iconButton, &QPushButton::setIcon);
|
|
||||||
connect(this, &MainWindow::windowTitleChanged, titleBar->titleLabel, &QLabel::setText);
|
|
||||||
connect(this, &MainWindow::windowStateChanged, this, [this](){
|
|
||||||
const bool zoomed = isZoomed();
|
|
||||||
const SystemTheme theme = SystemTheme::Light;
|
|
||||||
const SystemButtonType button = (zoomed ? SystemButtonType::Restore : SystemButtonType::Maximize);
|
|
||||||
const ResourceType resource = ResourceType::Icon;
|
|
||||||
titleBar->maximizeButton->setIcon(qvariant_cast<QIcon>(Utils::getSystemButtonIconResource(button, theme, resource)));
|
|
||||||
titleBar->maximizeButton->setToolTip(zoomed ? tr("Restore") : tr("Maximize"));
|
|
||||||
});
|
|
||||||
|
|
||||||
setWindowTitle(tr("Hello, World! - Qt MainWindow"));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,12 @@
|
||||||
|
|
||||||
#include <FramelessMainWindow>
|
#include <FramelessMainWindow>
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
class StandardTitleBar;
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
class TitleBar;
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,16 +44,10 @@ public:
|
||||||
explicit MainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {});
|
explicit MainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {});
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
void changeEvent(QEvent *event) override;
|
void initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupUi();
|
QScopedPointer<FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar)> m_titleBar;
|
||||||
|
QScopedPointer<Ui::MainWindow> m_mainWindow;
|
||||||
Q_SIGNALS:
|
|
||||||
void windowStateChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QScopedPointer<Ui::TitleBar> titleBar;
|
|
||||||
QScopedPointer<Ui::MainWindow> mainWindow;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,8 +39,6 @@ set(SOURCES
|
||||||
mainwindow.h
|
mainwindow.h
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
systembutton.h
|
|
||||||
systembutton.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
|
@ -24,9 +24,10 @@
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "glwidget.h"
|
#include "glwidget.h"
|
||||||
#include "systembutton.h"
|
|
||||||
#include <QtWidgets/qboxlayout.h>
|
#include <QtWidgets/qboxlayout.h>
|
||||||
#include <QtWidgets/qlabel.h>
|
#include <FramelessWidgetsHelper>
|
||||||
|
#include <StandardTitleBar>
|
||||||
|
#include <StandardSystemButton>
|
||||||
|
|
||||||
FRAMELESSHELPER_USE_NAMESPACE
|
FRAMELESSHELPER_USE_NAMESPACE
|
||||||
|
|
||||||
|
@ -34,58 +35,27 @@ using namespace Global;
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) : FramelessWidget(parent)
|
MainWindow::MainWindow(QWidget *parent) : FramelessWidget(parent)
|
||||||
{
|
{
|
||||||
setupUi();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() = default;
|
MainWindow::~MainWindow() = default;
|
||||||
|
|
||||||
void MainWindow::updateMaximizeButton()
|
void MainWindow::initialize()
|
||||||
{
|
{
|
||||||
m_maxBtn->setText(isZoomed() ? tr("RESTORE") : tr("MAXIMIZE"));
|
resize(800, 600);
|
||||||
}
|
setWindowTitle(tr("FramelessHelper demo application - QOpenGLWidget"));
|
||||||
|
m_titleBar = new StandardTitleBar(this);
|
||||||
void MainWindow::setupUi()
|
|
||||||
{
|
|
||||||
m_titleLabel = new QLabel(this);
|
|
||||||
QFont f = font();
|
|
||||||
f.setPointSize(kDefaultTitleBarFontPointSize);
|
|
||||||
m_titleLabel->setFont(f);
|
|
||||||
connect(this, &MainWindow::windowTitleChanged, m_titleLabel, &QLabel::setText);
|
|
||||||
m_minBtn = new SystemButton(this);
|
|
||||||
m_minBtn->setText(tr("MINIMIZE"));
|
|
||||||
connect(m_minBtn, &SystemButton::clicked, this, &MainWindow::showMinimized);
|
|
||||||
m_maxBtn = new SystemButton(this);
|
|
||||||
updateMaximizeButton();
|
|
||||||
connect(m_maxBtn, &SystemButton::clicked, this, &MainWindow::toggleMaximized);
|
|
||||||
connect(this, &MainWindow::zoomedChanged, this, &MainWindow::updateMaximizeButton);
|
|
||||||
m_closeBtn = new SystemButton(this);
|
|
||||||
m_closeBtn->setText(tr("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);
|
|
||||||
const auto titleBarLayout = new QHBoxLayout(m_titleBarWidget);
|
|
||||||
titleBarLayout->setSpacing(0);
|
|
||||||
titleBarLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
titleBarLayout->addSpacerItem(new QSpacerItem(kDefaultTitleBarTitleLabelMargin, kDefaultTitleBarTitleLabelMargin));
|
|
||||||
titleBarLayout->addWidget(m_titleLabel);
|
|
||||||
titleBarLayout->addStretch();
|
|
||||||
titleBarLayout->addWidget(m_minBtn);
|
|
||||||
titleBarLayout->addWidget(m_maxBtn);
|
|
||||||
titleBarLayout->addWidget(m_closeBtn);
|
|
||||||
m_titleBarWidget->setLayout(titleBarLayout);
|
|
||||||
m_glWidget = new GLWidget(this);
|
m_glWidget = new GLWidget(this);
|
||||||
const auto mainLayout = new QVBoxLayout(this);
|
const auto mainLayout = new QVBoxLayout(this);
|
||||||
mainLayout->setSpacing(0);
|
mainLayout->setSpacing(0);
|
||||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
mainLayout->addWidget(m_titleBarWidget);
|
mainLayout->addWidget(m_titleBar);
|
||||||
mainLayout->addWidget(m_glWidget);
|
mainLayout->addWidget(m_glWidget);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
setTitleBarWidget(m_titleBarWidget);
|
|
||||||
resize(800, 600);
|
|
||||||
setWindowTitle(tr("QOpenGLWidget demo"));
|
|
||||||
|
|
||||||
setSystemButton(m_minBtn, SystemButtonType::Minimize);
|
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
||||||
setSystemButton(m_maxBtn, SystemButtonType::Maximize);
|
helper->setTitleBarWidget(m_titleBar);
|
||||||
setSystemButton(m_closeBtn, SystemButtonType::Close);
|
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||||
|
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||||
|
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <framelesswidget.h>
|
#include <FramelessWidget>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
class QLabel;
|
class StandardTitleBar;
|
||||||
QT_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
||||||
class GLWidget;
|
class GLWidget;
|
||||||
class SystemButton;
|
|
||||||
|
|
||||||
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
|
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
|
||||||
{
|
{
|
||||||
|
@ -42,17 +41,10 @@ public:
|
||||||
explicit MainWindow(QWidget *parent = nullptr);
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
public Q_SLOTS:
|
private:
|
||||||
void updateMaximizeButton();
|
void initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupUi();
|
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *m_titleBar = nullptr;
|
||||||
|
|
||||||
private:
|
|
||||||
QLabel *m_titleLabel = nullptr;
|
|
||||||
SystemButton *m_minBtn = nullptr;
|
|
||||||
SystemButton *m_maxBtn = nullptr;
|
|
||||||
SystemButton *m_closeBtn = nullptr;
|
|
||||||
QWidget *m_titleBarWidget = nullptr;
|
|
||||||
GLWidget *m_glWidget = nullptr;
|
GLWidget *m_glWidget = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,29 +26,21 @@
|
||||||
#include <QtCore/qdatetime.h>
|
#include <QtCore/qdatetime.h>
|
||||||
#include <QtWidgets/qlabel.h>
|
#include <QtWidgets/qlabel.h>
|
||||||
#include <QtWidgets/qboxlayout.h>
|
#include <QtWidgets/qboxlayout.h>
|
||||||
|
#include <FramelessWindowsManager>
|
||||||
#include <Utils>
|
#include <Utils>
|
||||||
|
#include <FramelessWidgetsHelper>
|
||||||
|
#include <StandardTitleBar>
|
||||||
|
#include <StandardSystemButton>
|
||||||
|
|
||||||
FRAMELESSHELPER_USE_NAMESPACE
|
FRAMELESSHELPER_USE_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
static const UserSettings settings =
|
Widget::Widget(QWidget *parent) : FramelessWidget(parent)
|
||||||
{
|
{
|
||||||
/* startupPosition */ QPoint(),
|
initialize();
|
||||||
/* startupSize */ QSize(),
|
|
||||||
/* startupState */ Qt::WindowNoState,
|
|
||||||
/* options */ { Option::CreateStandardWindowLayout }, // Only needed by this demo application, you most probably don't need this option.
|
|
||||||
/* systemMenuOffset */ QPoint(),
|
|
||||||
/* minimizeButton */ nullptr,
|
|
||||||
/* maximizeButton */ nullptr,
|
|
||||||
/* closeButton */ nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
Widget::Widget(QWidget *parent) : FramelessWidget(parent, settings)
|
|
||||||
{
|
|
||||||
setupUi();
|
|
||||||
startTimer(500);
|
startTimer(500);
|
||||||
connect(this, &Widget::systemThemeChanged, this, &Widget::updateStyleSheet);
|
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &Widget::updateStyleSheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget::~Widget() = default;
|
Widget::~Widget() = default;
|
||||||
|
@ -62,27 +54,36 @@ void Widget::timerEvent(QTimerEvent *event)
|
||||||
m_clockLabel->setText(QTime::currentTime().toString(FRAMELESSHELPER_STRING_LITERAL("hh:mm:ss")));
|
m_clockLabel->setText(QTime::currentTime().toString(FRAMELESSHELPER_STRING_LITERAL("hh:mm:ss")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::setupUi()
|
void Widget::initialize()
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Hello, World! - Qt Widgets"));
|
setWindowTitle(tr("FramelessHelper demo application - Qt Widgets"));
|
||||||
resize(800, 600);
|
resize(800, 600);
|
||||||
|
m_titleBar.reset(new StandardTitleBar(this));
|
||||||
m_clockLabel.reset(new QLabel(this));
|
m_clockLabel.reset(new QLabel(this));
|
||||||
m_clockLabel->setFrameShape(QFrame::NoFrame);
|
m_clockLabel->setFrameShape(QFrame::NoFrame);
|
||||||
QFont clockFont = font();
|
QFont clockFont = font();
|
||||||
clockFont.setBold(true);
|
clockFont.setBold(true);
|
||||||
clockFont.setPointSize(70);
|
clockFont.setPointSize(70);
|
||||||
m_clockLabel->setFont(clockFont);
|
m_clockLabel->setFont(clockFont);
|
||||||
const auto widget = new QWidget(this);
|
const auto contentLayout = new QHBoxLayout;
|
||||||
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
const auto contentLayout = new QHBoxLayout(widget);
|
|
||||||
contentLayout->setContentsMargins(0, 0, 0, 0);
|
contentLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
contentLayout->setSpacing(0);
|
contentLayout->setSpacing(0);
|
||||||
contentLayout->addStretch();
|
contentLayout->addStretch();
|
||||||
contentLayout->addWidget(m_clockLabel.data());
|
contentLayout->addWidget(m_clockLabel.data());
|
||||||
contentLayout->addStretch();
|
contentLayout->addStretch();
|
||||||
widget->setLayout(contentLayout);
|
const auto mainLayout = new QVBoxLayout(this);
|
||||||
setContentWidget(widget);
|
mainLayout->setSpacing(0);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
mainLayout->addWidget(m_titleBar.data());
|
||||||
|
mainLayout->addLayout(contentLayout);
|
||||||
|
setLayout(mainLayout);
|
||||||
updateStyleSheet();
|
updateStyleSheet();
|
||||||
|
|
||||||
|
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
|
||||||
|
helper->setTitleBarWidget(m_titleBar.data());
|
||||||
|
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||||
|
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||||
|
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::updateStyleSheet()
|
void Widget::updateStyleSheet()
|
||||||
|
|
|
@ -30,6 +30,10 @@ QT_BEGIN_NAMESPACE
|
||||||
class QLabel;
|
class QLabel;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
class StandardTitleBar;
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
||||||
class Widget : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
|
class Widget : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -43,11 +47,12 @@ protected:
|
||||||
void timerEvent(QTimerEvent *event) override;
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupUi();
|
void initialize();
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void updateStyleSheet();
|
void updateStyleSheet();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<QLabel> m_clockLabel;
|
QScopedPointer<QLabel> m_clockLabel;
|
||||||
|
QScopedPointer<FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar)> m_titleBar;
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
explicit FramelessHelperQt(QObject *parent = nullptr);
|
explicit FramelessHelperQt(QObject *parent = nullptr);
|
||||||
~FramelessHelperQt() override;
|
~FramelessHelperQt() override;
|
||||||
|
|
||||||
static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms);
|
static void addWindow(const Global::SystemParameters ¶ms);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
explicit FramelessHelperWin();
|
explicit FramelessHelperWin();
|
||||||
~FramelessHelperWin() override;
|
~FramelessHelperWin() override;
|
||||||
|
|
||||||
static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms);
|
static void addWindow(const Global::SystemParameters ¶ms);
|
||||||
|
|
||||||
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,10 +25,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <QtCore/qobject.h>
|
|
||||||
#include <QtCore/qpoint.h>
|
#include <QtCore/qpoint.h>
|
||||||
#include <QtCore/qsize.h>
|
#include <QtCore/qsize.h>
|
||||||
#include <QtCore/qpointer.h>
|
#include <QtCore/qobject.h>
|
||||||
#include <QtGui/qcolor.h>
|
#include <QtGui/qcolor.h>
|
||||||
#include <QtGui/qwindowdefs.h>
|
#include <QtGui/qwindowdefs.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -192,37 +191,6 @@ FRAMELESSHELPER_STRING_CONSTANT2(UsePureQtImplKeyPath, "Options/UsePureQtImpleme
|
||||||
FRAMELESSHELPER_STRING_CONSTANT2(ForceHideFrameBorderKeyPath, "Options/ForceHideFrameBorder")
|
FRAMELESSHELPER_STRING_CONSTANT2(ForceHideFrameBorderKeyPath, "Options/ForceHideFrameBorder")
|
||||||
FRAMELESSHELPER_STRING_CONSTANT2(ForceShowFrameBorderKeyPath, "Options/ForceShowFrameBorder")
|
FRAMELESSHELPER_STRING_CONSTANT2(ForceShowFrameBorderKeyPath, "Options/ForceShowFrameBorder")
|
||||||
|
|
||||||
enum class Option
|
|
||||||
{
|
|
||||||
ForceHideWindowFrameBorder = 0x00000001, // Windows only, force hide the window frame border even on Windows 10 and onwards.
|
|
||||||
ForceShowWindowFrameBorder = 0x00000002, // Windows only, force show the window frame border even on Windows 7 (~ 8.1).
|
|
||||||
DontDrawTopWindowFrameBorder = 0x00000004, // Windows only, don't draw the top window frame border even if the window frame border is visible.
|
|
||||||
DontForceSquareWindowCorners = 0x00000008, // Windows only, don't force the window corners to be square if the default corner style is not square.
|
|
||||||
TransparentWindowBackground = 0x00000010, // Make the window's background become transparent.
|
|
||||||
DisableWindowsSnapLayout = 0x00000020, // Windows only, don't enable the snap layout feature (available since Windows 11) unconditionally.
|
|
||||||
CreateStandardWindowLayout = 0x00000040, // Using this option will cause FramelessHelper create a homemade titlebar and a window layout to contain it. If your window has a layout already, the newly created layout will mess up your own layout.
|
|
||||||
BeCompatibleWithQtFramelessWindowHint = 0x00000080, // Windows only, make the code compatible with Qt::FramelessWindowHint. Don't use this option unless you really need that flag.
|
|
||||||
DontTouchQtInternals = 0x00000100, // Windows only, don't modify Qt's internal data.
|
|
||||||
DontTouchWindowFrameBorderColor = 0x00000200, // Windows only, don't change the window frame border color.
|
|
||||||
DontInstallSystemMenuHook = 0x00000400, // Windows only, don't install the system menu hook.
|
|
||||||
DisableSystemMenu = 0x00000800, // Windows only, don't open the system menu when right clicks the titlebar.
|
|
||||||
NoDoubleClickMaximizeToggle = 0x00001000, // Don't toggle the maximized state when user double clicks the titlebar.
|
|
||||||
DisableResizing = 0x00002000, // Disable resizing of the window.
|
|
||||||
DisableDragging = 0x00004000, // Disable dragging through the titlebar of the window.
|
|
||||||
DontTouchCursorShape = 0x00008000, // Don't change the cursor shape while the mouse is hovering above the window.
|
|
||||||
DontMoveWindowToDesktopCenter = 0x00010000, // Don't move the window to the desktop center before it's first shown.
|
|
||||||
DontTreatFullScreenAsZoomed = 0x00020000, // Don't treat fullscreen as zoomed (maximized).
|
|
||||||
DontTouchHighDpiScalingPolicy = 0x00040000, // Don't change Qt's default high DPI scaling policy. Qt5 default: disabled, Qt6 default: enabled.
|
|
||||||
DontTouchScaleFactorRoundingPolicy = 0x00080000, // Don't change Qt's default scale factor rounding policy. Qt5 default: round, Qt6 default: pass through.
|
|
||||||
DontTouchProcessDpiAwarenessLevel = 0x00100000, // Windows only, don't change the current process's DPI awareness level.
|
|
||||||
DontEnsureNonNativeWidgetSiblings = 0x00200000, // Don't ensure that siblings of native widgets stay non-native.
|
|
||||||
SyncNativeControlsThemeWithSystem = 0x00400000 // Windows only, sync the native Win32 controls' theme with system theme.
|
|
||||||
};
|
|
||||||
Q_ENUM_NS(Option)
|
|
||||||
Q_DECLARE_FLAGS(Options, Option)
|
|
||||||
Q_FLAG_NS(Options)
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Options)
|
|
||||||
|
|
||||||
enum class SystemTheme
|
enum class SystemTheme
|
||||||
{
|
{
|
||||||
Unknown = -1,
|
Unknown = -1,
|
||||||
|
@ -409,20 +377,6 @@ using ShouldIgnoreMouseEventsCallback = std::function<bool(const QPoint &)>;
|
||||||
|
|
||||||
using ShowSystemMenuCallback = std::function<void(const QPoint &)>;
|
using ShowSystemMenuCallback = std::function<void(const QPoint &)>;
|
||||||
|
|
||||||
struct UserSettings
|
|
||||||
{
|
|
||||||
QPoint startupPosition = {};
|
|
||||||
QSize startupSize = {};
|
|
||||||
Qt::WindowState startupState = Qt::WindowNoState;
|
|
||||||
Options options = {};
|
|
||||||
QPoint systemMenuOffset = {};
|
|
||||||
QPointer<QObject> windowIconButton = nullptr;
|
|
||||||
QPointer<QObject> contextHelpButton = nullptr;
|
|
||||||
QPointer<QObject> minimizeButton = nullptr;
|
|
||||||
QPointer<QObject> maximizeButton = nullptr;
|
|
||||||
QPointer<QObject> closeButton = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SystemParameters
|
struct SystemParameters
|
||||||
{
|
{
|
||||||
GetWindowFlagsCallback getWindowFlags = nullptr;
|
GetWindowFlagsCallback getWindowFlags = nullptr;
|
||||||
|
@ -528,11 +482,10 @@ static_assert((sizeof(WindowsVersions) / sizeof(WindowsVersions[0])) == (static_
|
||||||
|
|
||||||
namespace FramelessHelper::Core
|
namespace FramelessHelper::Core
|
||||||
{
|
{
|
||||||
FRAMELESSHELPER_CORE_API void initialize(const Global::Options options = {});
|
FRAMELESSHELPER_CORE_API void initialize();
|
||||||
} // namespace FramelessHelper::Core
|
} // namespace FramelessHelper::Core
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber)
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber)
|
||||||
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::UserSettings)
|
|
||||||
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::SystemParameters)
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::SystemParameters)
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
Q_NODISCARD QColor systemAccentColor() const;
|
Q_NODISCARD QColor systemAccentColor() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms);
|
void addWindow(const Global::SystemParameters ¶ms);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void systemThemeChanged();
|
void systemThemeChanged();
|
||||||
|
|
|
@ -70,9 +70,7 @@ FRAMELESSHELPER_CORE_API void syncWmPaintWithDwm();
|
||||||
FRAMELESSHELPER_CORE_API void showSystemMenu(
|
FRAMELESSHELPER_CORE_API void showSystemMenu(
|
||||||
const WId windowId,
|
const WId windowId,
|
||||||
const QPoint &pos,
|
const QPoint &pos,
|
||||||
const QPoint &offset,
|
|
||||||
const bool selectFirstEntry,
|
const bool selectFirstEntry,
|
||||||
const Global::Options options,
|
|
||||||
const Global::IsWindowFixedSizeCallback &isWindowFixedSize);
|
const Global::IsWindowFixedSizeCallback &isWindowFixedSize);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmColorizationColor();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmColorizationColor();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::DwmColorizationArea getDwmColorizationArea();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::DwmColorizationArea getDwmColorizationArea();
|
||||||
|
@ -93,8 +91,6 @@ FRAMELESSHELPER_CORE_API void fixupQtInternals(const WId windowId);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized();
|
||||||
FRAMELESSHELPER_CORE_API void installSystemMenuHook(
|
FRAMELESSHELPER_CORE_API void installSystemMenuHook(
|
||||||
const WId windowId,
|
const WId windowId,
|
||||||
const Global::Options options,
|
|
||||||
const QPoint &offset,
|
|
||||||
const Global::IsWindowFixedSizeCallback &isWindowFixedSize,
|
const Global::IsWindowFixedSizeCallback &isWindowFixedSize,
|
||||||
const Global::IsInsideTitleBarDraggableAreaCallback &isInTitleBarArea,
|
const Global::IsInsideTitleBarDraggableAreaCallback &isInTitleBarArea,
|
||||||
const Global::GetWindowDevicePixelRatioCallback &getDevicePixelRatio);
|
const Global::GetWindowDevicePixelRatioCallback &getDevicePixelRatio);
|
||||||
|
|
|
@ -76,36 +76,6 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
struct FRAMELESSHELPER_QUICK_API QuickGlobal
|
struct FRAMELESSHELPER_QUICK_API QuickGlobal
|
||||||
{
|
{
|
||||||
enum class Option
|
|
||||||
{
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, ForceHideWindowFrameBorder)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, ForceShowWindowFrameBorder)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontDrawTopWindowFrameBorder)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontForceSquareWindowCorners)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, TransparentWindowBackground)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableWindowsSnapLayout)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, CreateStandardWindowLayout)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, BeCompatibleWithQtFramelessWindowHint)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchQtInternals)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchWindowFrameBorderColor)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontInstallSystemMenuHook)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableSystemMenu)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, NoDoubleClickMaximizeToggle)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableResizing)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DisableDragging)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchCursorShape)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontMoveWindowToDesktopCenter)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTreatFullScreenAsZoomed)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchHighDpiScalingPolicy)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchScaleFactorRoundingPolicy)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontTouchProcessDpiAwarenessLevel)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, DontEnsureNonNativeWidgetSiblings)
|
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(Option, SyncNativeControlsThemeWithSystem)
|
|
||||||
};
|
|
||||||
Q_ENUM(Option)
|
|
||||||
Q_DECLARE_FLAGS(Options, Option)
|
|
||||||
Q_FLAG(Options)
|
|
||||||
|
|
||||||
enum class SystemTheme
|
enum class SystemTheme
|
||||||
{
|
{
|
||||||
FRAMELESSHELPER_QUICK_ENUM_VALUE(SystemTheme, Unknown)
|
FRAMELESSHELPER_QUICK_ENUM_VALUE(SystemTheme, Unknown)
|
||||||
|
@ -175,6 +145,4 @@ private:
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QuickGlobal::Options)
|
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -42,7 +42,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickHelper : public QQuickItem
|
||||||
Q_PROPERTY(QQuickItem* titleBarItem READ titleBarItem WRITE setTitleBarItem NOTIFY titleBarItemChanged FINAL)
|
Q_PROPERTY(QQuickItem* titleBarItem READ titleBarItem WRITE setTitleBarItem NOTIFY titleBarItemChanged FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickHelper(QQuickItem *parent = nullptr, const Global::UserSettings &settings = {});
|
explicit FramelessQuickHelper(QQuickItem *parent = nullptr);
|
||||||
~FramelessQuickHelper() override;
|
~FramelessQuickHelper() override;
|
||||||
|
|
||||||
Q_NODISCARD static FramelessQuickHelper *qmlAttachedProperties(QObject *parentObject);
|
Q_NODISCARD static FramelessQuickHelper *qmlAttachedProperties(QObject *parentObject);
|
||||||
|
@ -61,7 +61,7 @@ public Q_SLOTS:
|
||||||
|
|
||||||
void moveWindowToDesktopCenter();
|
void moveWindowToDesktopCenter();
|
||||||
void bringWindowToFront();
|
void bringWindowToFront();
|
||||||
void setWindowFixedSize(const bool value, const bool force = false);
|
void setWindowFixedSize(const bool value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void itemChange(const ItemChange change, const ItemChangeData &data) override;
|
void itemChange(const ItemChange change, const ItemChangeData &data) override;
|
||||||
|
|
|
@ -44,10 +44,9 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow
|
||||||
Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL)
|
Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL)
|
||||||
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
||||||
Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL)
|
Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL)
|
||||||
Q_PROPERTY(QColor frameBorderColor READ frameBorderColor NOTIFY frameBorderColorChanged FINAL)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickWindow(QWindow *parent = nullptr, const Global::UserSettings &settings = {});
|
explicit FramelessQuickWindow(QWindow *parent = nullptr);
|
||||||
~FramelessQuickWindow() override;
|
~FramelessQuickWindow() override;
|
||||||
|
|
||||||
Q_NODISCARD bool isHidden() const;
|
Q_NODISCARD bool isHidden() const;
|
||||||
|
@ -55,7 +54,6 @@ public:
|
||||||
Q_NODISCARD bool isMinimized() const;
|
Q_NODISCARD bool isMinimized() const;
|
||||||
Q_NODISCARD bool isZoomed() const;
|
Q_NODISCARD bool isZoomed() const;
|
||||||
Q_NODISCARD bool isFullScreen() const;
|
Q_NODISCARD bool isFullScreen() const;
|
||||||
Q_NODISCARD QColor frameBorderColor() const;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void showMinimized2();
|
void showMinimized2();
|
||||||
|
@ -69,7 +67,6 @@ Q_SIGNALS:
|
||||||
void minimizedChanged();
|
void minimizedChanged();
|
||||||
void zoomedChanged();
|
void zoomedChanged();
|
||||||
void fullScreenChanged();
|
void fullScreenChanged();
|
||||||
void frameBorderColorChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<FramelessQuickWindowPrivate> d_ptr;
|
QScopedPointer<FramelessQuickWindowPrivate> d_ptr;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include <framelesswidgetshelper.h>
|
|
@ -0,0 +1 @@
|
||||||
|
#include <standardtitlebar.h>
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class FramelessWidgetsHelper;
|
class WidgetsSharedHelper;
|
||||||
|
|
||||||
class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow
|
class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
|
@ -38,43 +38,26 @@ class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow
|
||||||
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL)
|
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL)
|
||||||
Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL)
|
Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL)
|
||||||
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
||||||
Q_PROPERTY(bool fixedSize READ isFixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL)
|
|
||||||
Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessMainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {}, const Global::UserSettings &settings = {});
|
explicit FramelessMainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {});
|
||||||
~FramelessMainWindow() override;
|
~FramelessMainWindow() override;
|
||||||
|
|
||||||
Q_NODISCARD bool isNormal() const;
|
Q_NODISCARD bool isNormal() const;
|
||||||
Q_NODISCARD bool isZoomed() const;
|
Q_NODISCARD bool isZoomed() const;
|
||||||
|
|
||||||
Q_NODISCARD bool isFixedSize() const;
|
|
||||||
void setFixedSize(const bool value);
|
|
||||||
|
|
||||||
void setTitleBarWidget(QWidget *widget);
|
|
||||||
Q_NODISCARD QWidget *titleBarWidget() const;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setHitTestVisible(QWidget *widget);
|
|
||||||
void toggleMaximized();
|
void toggleMaximized();
|
||||||
void toggleFullScreen();
|
void toggleFullScreen();
|
||||||
void moveToDesktopCenter();
|
|
||||||
void bringToFront();
|
|
||||||
void showSystemMenu(const QPoint &pos);
|
|
||||||
void startSystemMove2(const QPoint &pos);
|
|
||||||
void startSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
|
||||||
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void hiddenChanged();
|
void hiddenChanged();
|
||||||
void normalChanged();
|
void normalChanged();
|
||||||
void zoomedChanged();
|
void zoomedChanged();
|
||||||
void fixedSizeChanged();
|
|
||||||
void titleBarWidgetChanged();
|
|
||||||
void systemThemeChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<FramelessWidgetsHelper> d_ptr;
|
QScopedPointer<WidgetsSharedHelper> m_helper;
|
||||||
|
Qt::WindowState m_savedWindowState = Qt::WindowNoState;
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class FramelessWidgetsHelper;
|
class WidgetsSharedHelper;
|
||||||
|
|
||||||
class FRAMELESSHELPER_WIDGETS_API FramelessWidget : public QWidget
|
class FRAMELESSHELPER_WIDGETS_API FramelessWidget : public QWidget
|
||||||
{
|
{
|
||||||
|
@ -38,48 +38,26 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidget : public QWidget
|
||||||
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL)
|
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL)
|
||||||
Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL)
|
Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL)
|
||||||
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
||||||
Q_PROPERTY(bool fixedSize READ isFixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL)
|
|
||||||
Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL)
|
|
||||||
Q_PROPERTY(QWidget* contentWidget READ contentWidget WRITE setContentWidget NOTIFY contentWidgetChanged FINAL)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessWidget(QWidget *parent = nullptr, const Global::UserSettings &settings = {});
|
explicit FramelessWidget(QWidget *parent = nullptr);
|
||||||
~FramelessWidget() override;
|
~FramelessWidget() override;
|
||||||
|
|
||||||
Q_NODISCARD bool isNormal() const;
|
Q_NODISCARD bool isNormal() const;
|
||||||
Q_NODISCARD bool isZoomed() const;
|
Q_NODISCARD bool isZoomed() const;
|
||||||
|
|
||||||
Q_NODISCARD bool isFixedSize() const;
|
|
||||||
void setFixedSize(const bool value);
|
|
||||||
|
|
||||||
void setTitleBarWidget(QWidget *widget);
|
|
||||||
Q_NODISCARD QWidget *titleBarWidget() const;
|
|
||||||
|
|
||||||
void setContentWidget(QWidget *widget);
|
|
||||||
Q_NODISCARD QWidget *contentWidget() const;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setHitTestVisible(QWidget *widget);
|
|
||||||
void toggleMaximized();
|
void toggleMaximized();
|
||||||
void toggleFullScreen();
|
void toggleFullScreen();
|
||||||
void moveToDesktopCenter();
|
|
||||||
void bringToFront();
|
|
||||||
void showSystemMenu(const QPoint &pos);
|
|
||||||
void startSystemMove2(const QPoint &pos);
|
|
||||||
void startSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
|
||||||
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void hiddenChanged();
|
void hiddenChanged();
|
||||||
void normalChanged();
|
void normalChanged();
|
||||||
void zoomedChanged();
|
void zoomedChanged();
|
||||||
void fixedSizeChanged();
|
|
||||||
void titleBarWidgetChanged();
|
|
||||||
void contentWidgetChanged();
|
|
||||||
void systemThemeChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<FramelessWidgetsHelper> d_ptr;
|
QScopedPointer<WidgetsSharedHelper> m_helper;
|
||||||
|
Qt::WindowState m_savedWindowState = Qt::WindowNoState;
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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 "framelesshelperwidgets_global.h"
|
||||||
|
#include <QtCore/qobject.h>
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class FramelessWidgetsHelperPrivate;
|
||||||
|
|
||||||
|
class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DECLARE_PRIVATE(FramelessWidgetsHelper)
|
||||||
|
Q_DISABLE_COPY_MOVE(FramelessWidgetsHelper)
|
||||||
|
Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FramelessWidgetsHelper(QObject *parent = nullptr);
|
||||||
|
~FramelessWidgetsHelper() override;
|
||||||
|
|
||||||
|
Q_NODISCARD static FramelessWidgetsHelper *get(QObject *object);
|
||||||
|
|
||||||
|
Q_NODISCARD QWidget *titleBarWidget() const;
|
||||||
|
Q_NODISCARD bool isWindowFixedSize() const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void attach();
|
||||||
|
|
||||||
|
void setTitleBarWidget(QWidget *widget);
|
||||||
|
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
||||||
|
void setHitTestVisible(QWidget *widget);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void titleBarWidgetChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QScopedPointer<FramelessWidgetsHelperPrivate> d_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -22,22 +22,38 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "systembutton.h"
|
#pragma once
|
||||||
|
|
||||||
SystemButton::SystemButton(QWidget *parent) : QPushButton(parent)
|
#include "framelesshelperwidgets_global.h"
|
||||||
|
#include <QtWidgets/qwidget.h>
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class StandardTitleBarPrivate;
|
||||||
|
class StandardSystemButton;
|
||||||
|
|
||||||
|
class FRAMELESSHELPER_WIDGETS_API StandardTitleBar : public QWidget
|
||||||
{
|
{
|
||||||
}
|
Q_OBJECT
|
||||||
|
Q_DECLARE_PRIVATE(StandardTitleBar)
|
||||||
|
Q_DISABLE_COPY_MOVE(StandardTitleBar)
|
||||||
|
Q_PROPERTY(StandardSystemButton* minimizeButton READ minimizeButton CONSTANT FINAL)
|
||||||
|
Q_PROPERTY(StandardSystemButton* maximizeButton READ maximizeButton CONSTANT FINAL)
|
||||||
|
Q_PROPERTY(StandardSystemButton* closeButton READ closeButton CONSTANT FINAL)
|
||||||
|
|
||||||
SystemButton::~SystemButton() = default;
|
public:
|
||||||
|
explicit StandardTitleBar(QWidget *parent = nullptr);
|
||||||
|
~StandardTitleBar() override;
|
||||||
|
|
||||||
void SystemButton::setHovered(const bool value)
|
Q_NODISCARD StandardSystemButton *minimizeButton() const;
|
||||||
{
|
Q_NODISCARD StandardSystemButton *maximizeButton() const;
|
||||||
Q_UNUSED(value);
|
Q_NODISCARD StandardSystemButton *closeButton() const;
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemButton::setPressed(const bool value)
|
protected:
|
||||||
{
|
void paintEvent(QPaintEvent *event) override;
|
||||||
Q_UNUSED(value);
|
|
||||||
Q_UNIMPLEMENTED();
|
private:
|
||||||
}
|
QScopedPointer<StandardTitleBarPrivate> d_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -48,8 +48,6 @@ if(WIN32)
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
${INCLUDE_PREFIX}/framelesshelper_windows.h
|
${INCLUDE_PREFIX}/framelesshelper_windows.h
|
||||||
${INCLUDE_PREFIX}/framelesshelper_win.h
|
${INCLUDE_PREFIX}/framelesshelper_win.h
|
||||||
qwinregistry_p.h
|
|
||||||
qwinregistry.cpp
|
|
||||||
utils_win.cpp
|
utils_win.cpp
|
||||||
framelesshelper_win.cpp
|
framelesshelper_win.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -36,7 +36,6 @@ using namespace Global;
|
||||||
|
|
||||||
struct QtHelperData
|
struct QtHelperData
|
||||||
{
|
{
|
||||||
UserSettings settings = {};
|
|
||||||
SystemParameters params = {};
|
SystemParameters params = {};
|
||||||
FramelessHelperQt *eventFilter = nullptr;
|
FramelessHelperQt *eventFilter = nullptr;
|
||||||
bool cursorShapeChanged = false;
|
bool cursorShapeChanged = false;
|
||||||
|
@ -55,7 +54,7 @@ FramelessHelperQt::FramelessHelperQt(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
FramelessHelperQt::~FramelessHelperQt() = default;
|
FramelessHelperQt::~FramelessHelperQt() = default;
|
||||||
|
|
||||||
void FramelessHelperQt::addWindow(const UserSettings &settings, const SystemParameters ¶ms)
|
void FramelessHelperQt::addWindow(const SystemParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_ASSERT(params.isValid());
|
Q_ASSERT(params.isValid());
|
||||||
if (!params.isValid()) {
|
if (!params.isValid()) {
|
||||||
|
@ -68,7 +67,6 @@ void FramelessHelperQt::addWindow(const UserSettings &settings, const SystemPara
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QtHelperData data = {};
|
QtHelperData data = {};
|
||||||
data.settings = settings;
|
|
||||||
data.params = params;
|
data.params = params;
|
||||||
QWindow *window = params.getWindowHandle();
|
QWindow *window = params.getWindowHandle();
|
||||||
// Give it a parent so that it can be deleted even if we forget to do so.
|
// Give it a parent so that it can be deleted even if we forget to do so.
|
||||||
|
@ -148,7 +146,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
QMutexLocker locker(&g_qtHelper()->mutex);
|
QMutexLocker locker(&g_qtHelper()->mutex);
|
||||||
g_qtHelper()->data[windowId].leftButtonPressed = false;
|
g_qtHelper()->data[windowId].leftButtonPressed = false;
|
||||||
}
|
}
|
||||||
if ((button == Qt::RightButton) && !(data.settings.options & Option::DisableSystemMenu)) {
|
if (button == Qt::RightButton) {
|
||||||
if (!ignoreThisEvent && insideTitleBar) {
|
if (!ignoreThisEvent && insideTitleBar) {
|
||||||
data.params.showSystemMenu(scenePos);
|
data.params.showSystemMenu(scenePos);
|
||||||
return true;
|
return true;
|
||||||
|
@ -156,8 +154,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case QEvent::MouseButtonDblClick: {
|
case QEvent::MouseButtonDblClick: {
|
||||||
if ((button == Qt::LeftButton) && !windowFixedSize && !ignoreThisEvent
|
if ((button == Qt::LeftButton) && !windowFixedSize && !ignoreThisEvent && insideTitleBar) {
|
||||||
&& insideTitleBar && !(data.settings.options & Option::NoDoubleClickMaximizeToggle)) {
|
|
||||||
Qt::WindowState newWindowState = Qt::WindowNoState;
|
Qt::WindowState newWindowState = Qt::WindowNoState;
|
||||||
if (data.params.getWindowState() != Qt::WindowMaximized) {
|
if (data.params.getWindowState() != Qt::WindowMaximized) {
|
||||||
newWindowState = Qt::WindowMaximized;
|
newWindowState = Qt::WindowMaximized;
|
||||||
|
@ -166,7 +163,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case QEvent::MouseMove: {
|
case QEvent::MouseMove: {
|
||||||
if (!windowFixedSize && !(data.settings.options & Option::DontTouchCursorShape)) {
|
if (!windowFixedSize) {
|
||||||
const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos);
|
const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos);
|
||||||
if (cs == Qt::ArrowCursor) {
|
if (cs == Qt::ArrowCursor) {
|
||||||
if (data.cursorShapeChanged) {
|
if (data.cursorShapeChanged) {
|
||||||
|
@ -180,7 +177,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
g_qtHelper()->data[windowId].cursorShapeChanged = true;
|
g_qtHelper()->data[windowId].cursorShapeChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.leftButtonPressed && !(data.settings.options & Option::DisableDragging)) {
|
if (data.leftButtonPressed) {
|
||||||
if (!ignoreThisEvent && insideTitleBar) {
|
if (!ignoreThisEvent && insideTitleBar) {
|
||||||
Utils::startSystemMove(window, globalPos);
|
Utils::startSystemMove(window, globalPos);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -41,7 +41,6 @@ using namespace Global;
|
||||||
|
|
||||||
struct Win32HelperData
|
struct Win32HelperData
|
||||||
{
|
{
|
||||||
UserSettings settings = {};
|
|
||||||
SystemParameters params = {};
|
SystemParameters params = {};
|
||||||
bool trackingMouse = false;
|
bool trackingMouse = false;
|
||||||
WId dragBarWindowId = 0;
|
WId dragBarWindowId = 0;
|
||||||
|
@ -353,9 +352,8 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
||||||
if (!parentWindowId) {
|
if (!parentWindowId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Utils::isWindowsVersionOrGreater(WindowsVersion::_8)) {
|
if (!Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
|
||||||
qWarning() << "Our drag bar window needs the WS_EX_LAYERED style, however, "
|
qWarning() << "The drag bar window is only supported on Windows 10 and onwards.";
|
||||||
"it's not supported for child windows until Windows 8.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto parentWindowHandle = reinterpret_cast<HWND>(parentWindowId);
|
const auto parentWindowHandle = reinterpret_cast<HWND>(parentWindowId);
|
||||||
|
@ -415,7 +413,7 @@ FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {}
|
||||||
|
|
||||||
FramelessHelperWin::~FramelessHelperWin() = default;
|
FramelessHelperWin::~FramelessHelperWin() = default;
|
||||||
|
|
||||||
void FramelessHelperWin::addWindow(const UserSettings &settings, const SystemParameters ¶ms)
|
void FramelessHelperWin::addWindow(const SystemParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_ASSERT(params.isValid());
|
Q_ASSERT(params.isValid());
|
||||||
if (!params.isValid()) {
|
if (!params.isValid()) {
|
||||||
|
@ -428,44 +426,27 @@ void FramelessHelperWin::addWindow(const UserSettings &settings, const SystemPar
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Win32HelperData data = {};
|
Win32HelperData data = {};
|
||||||
data.settings = settings;
|
|
||||||
data.params = params;
|
data.params = params;
|
||||||
if ((settings.options & Option::ForceHideWindowFrameBorder)
|
|
||||||
&& (settings.options & Option::ForceShowWindowFrameBorder)) {
|
|
||||||
data.settings.options &= ~(Option::ForceHideWindowFrameBorder | Option::ForceShowWindowFrameBorder);
|
|
||||||
qWarning() << "You can't use both \"Option::ForceHideWindowFrameBorder\" and "
|
|
||||||
"\"Option::ForceShowWindowFrameBorder\" at the same time.";
|
|
||||||
}
|
|
||||||
g_win32Helper()->data.insert(windowId, data);
|
g_win32Helper()->data.insert(windowId, data);
|
||||||
if (g_win32Helper()->nativeEventFilter.isNull()) {
|
if (g_win32Helper()->nativeEventFilter.isNull()) {
|
||||||
g_win32Helper()->nativeEventFilter.reset(new FramelessHelperWin);
|
g_win32Helper()->nativeEventFilter.reset(new FramelessHelperWin);
|
||||||
qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
|
qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
|
||||||
}
|
}
|
||||||
g_win32Helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
if (!(settings.options & Option::DontTouchQtInternals)) {
|
Utils::fixupQtInternals(windowId);
|
||||||
Utils::fixupQtInternals(windowId);
|
|
||||||
}
|
|
||||||
Utils::updateInternalWindowFrameMargins(params.getWindowHandle(), true);
|
Utils::updateInternalWindowFrameMargins(params.getWindowHandle(), true);
|
||||||
Utils::updateWindowFrameMargins(windowId, false);
|
Utils::updateWindowFrameMargins(windowId, false);
|
||||||
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_8)) {
|
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
|
||||||
if (!(settings.options & Option::DisableWindowsSnapLayout)) {
|
if (!createDragBarWindow(windowId)) {
|
||||||
if (!createDragBarWindow(windowId)) {
|
qWarning() << "Failed to create the drag bar window.";
|
||||||
qWarning() << "Failed to create the drag bar window.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607)) {
|
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1607)) {
|
||||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||||
if (!(settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||||
Utils::updateWindowFrameBorderColor(windowId, dark);
|
|
||||||
}
|
|
||||||
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) {
|
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) {
|
||||||
if (settings.options & Option::SyncNativeControlsThemeWithSystem) {
|
//Utils::updateGlobalWin32ControlsTheme(windowId, dark); // Causes some QtWidgets paint incorrectly.
|
||||||
Utils::updateGlobalWin32ControlsTheme(windowId, dark);
|
|
||||||
}
|
|
||||||
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)) {
|
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)) {
|
||||||
if (!(settings.options & Option::DontForceSquareWindowCorners)) {
|
Utils::forceSquareCornersForWindow(windowId, true);
|
||||||
Utils::forceSquareCornersForWindow(windowId, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,15 +480,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
}
|
}
|
||||||
const Win32HelperData data = g_win32Helper()->data.value(windowId);
|
const Win32HelperData data = g_win32Helper()->data.value(windowId);
|
||||||
g_win32Helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
const bool frameBorderVisible = [&data]() -> bool {
|
const bool frameBorderVisible = Utils::isWindowFrameBorderVisible();
|
||||||
if (data.settings.options & Option::ForceShowWindowFrameBorder) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (data.settings.options & Option::ForceHideWindowFrameBorder) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Utils::isWindowFrameBorderVisible();
|
|
||||||
}();
|
|
||||||
const UINT uMsg = msg->message;
|
const UINT uMsg = msg->message;
|
||||||
const WPARAM wParam = msg->wParam;
|
const WPARAM wParam = msg->wParam;
|
||||||
const LPARAM lParam = msg->lParam;
|
const LPARAM lParam = msg->lParam;
|
||||||
|
@ -832,8 +805,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
const bool buttonSwapped = (GetSystemMetrics(SM_SWAPBUTTON) != FALSE);
|
const bool buttonSwapped = (GetSystemMetrics(SM_SWAPBUTTON) != FALSE);
|
||||||
const bool leftButtonPressed = (buttonSwapped ?
|
const bool leftButtonPressed = (buttonSwapped ?
|
||||||
(GetAsyncKeyState(VK_RBUTTON) < 0) : (GetAsyncKeyState(VK_LBUTTON) < 0));
|
(GetAsyncKeyState(VK_RBUTTON) < 0) : (GetAsyncKeyState(VK_LBUTTON) < 0));
|
||||||
const bool isTitleBar = (data.params.isInsideTitleBarDraggableArea(qtScenePos) &&
|
const bool isTitleBar = (data.params.isInsideTitleBarDraggableArea(qtScenePos) && leftButtonPressed);
|
||||||
leftButtonPressed && !(data.settings.options & Option::DisableDragging));
|
|
||||||
if (frameBorderVisible) {
|
if (frameBorderVisible) {
|
||||||
// This will handle the left, right and bottom parts of the frame
|
// This will handle the left, right and bottom parts of the frame
|
||||||
// because we didn't change them.
|
// because we didn't change them.
|
||||||
|
@ -1040,13 +1012,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
.compare(qThemeSettingChangeEventName, Qt::CaseInsensitive) == 0)) {
|
.compare(qThemeSettingChangeEventName, Qt::CaseInsensitive) == 0)) {
|
||||||
systemThemeChanged = true;
|
systemThemeChanged = true;
|
||||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||||
if (!(data.settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||||
Utils::updateWindowFrameBorderColor(windowId, dark);
|
|
||||||
}
|
|
||||||
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) {
|
if (Utils::isWindowsVersionOrGreater(WindowsVersion::_10_1809)) {
|
||||||
if (data.settings.options & Option::SyncNativeControlsThemeWithSystem) {
|
//Utils::updateGlobalWin32ControlsTheme(windowId, dark);
|
||||||
Utils::updateGlobalWin32ControlsTheme(windowId, dark);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ QColor FramelessWindowsManagerPrivate::systemAccentColor() const
|
||||||
return m_accentColor;
|
return m_accentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWindowsManagerPrivate::addWindow(const UserSettings &settings, const SystemParameters ¶ms)
|
void FramelessWindowsManagerPrivate::addWindow(const SystemParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_ASSERT(params.isValid());
|
Q_ASSERT(params.isValid());
|
||||||
if (!params.isValid()) {
|
if (!params.isValid()) {
|
||||||
|
@ -151,16 +151,14 @@ void FramelessWindowsManagerPrivate::addWindow(const UserSettings &settings, con
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (pureQt) {
|
if (pureQt) {
|
||||||
FramelessHelperQt::addWindow(settings, params);
|
FramelessHelperQt::addWindow(params);
|
||||||
}
|
}
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (!pureQt) {
|
if (!pureQt) {
|
||||||
FramelessHelperWin::addWindow(settings, params);
|
FramelessHelperWin::addWindow(params);
|
||||||
}
|
|
||||||
if (!(settings.options & Option::DontInstallSystemMenuHook)) {
|
|
||||||
Utils::installSystemMenuHook(windowId, settings.options, settings.systemMenuOffset,
|
|
||||||
params.isWindowFixedSize, params.isInsideTitleBarDraggableArea, params.getWindowDevicePixelRatio);
|
|
||||||
}
|
}
|
||||||
|
Utils::installSystemMenuHook(windowId, params.isWindowFixedSize,
|
||||||
|
params.isInsideTitleBarDraggableArea, params.getWindowDevicePixelRatio);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,13 +240,13 @@ QColor FramelessWindowsManager::systemAccentColor() const
|
||||||
return d->systemAccentColor();
|
return d->systemAccentColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWindowsManager::addWindow(const UserSettings &settings, const SystemParameters ¶ms)
|
void FramelessWindowsManager::addWindow(const SystemParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_D(FramelessWindowsManager);
|
Q_D(FramelessWindowsManager);
|
||||||
d->addWindow(settings, params);
|
d->addWindow(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessHelper::Core::initialize(const Options options)
|
void FramelessHelper::Core::initialize()
|
||||||
{
|
{
|
||||||
static bool inited = false;
|
static bool inited = false;
|
||||||
if (inited) {
|
if (inited) {
|
||||||
|
@ -256,7 +254,7 @@ void FramelessHelper::Core::initialize(const Options options)
|
||||||
}
|
}
|
||||||
inited = true;
|
inited = true;
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
// Qt's Wayland experience is not good, so we force the X11 backend here.
|
// Qt's Wayland experience is not good, so we force the XCB backend here.
|
||||||
// TODO: Remove this hack once Qt's Wayland implementation is good enough.
|
// TODO: Remove this hack once Qt's Wayland implementation is good enough.
|
||||||
// We are setting the preferred QPA backend, so we have to set it early
|
// We are setting the preferred QPA backend, so we have to set it early
|
||||||
// enough, that is, before the construction of any Q(Gui)Application
|
// enough, that is, before the construction of any Q(Gui)Application
|
||||||
|
@ -269,42 +267,33 @@ void FramelessHelper::Core::initialize(const Options options)
|
||||||
qputenv(MAC_LAYER_ENV_VAR, kValueOne);
|
qputenv(MAC_LAYER_ENV_VAR, kValueOne);
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (!(options & Option::DontTouchProcessDpiAwarenessLevel)) {
|
// This is equivalent to set the "dpiAware" and "dpiAwareness" field in
|
||||||
// This is equivalent to set the "dpiAware" and "dpiAwareness" field in
|
// your manifest file. It works through out Windows Vista to Windows 11.
|
||||||
// your manifest file. It works through out Windows Vista to Windows 11.
|
// It's highly recommended to enable the highest DPI awareness level
|
||||||
// It's highly recommended to enable the highest DPI awareness level
|
// (currently it's PerMonitor Version 2, or PMv2 for short) for any GUI
|
||||||
// (currently it's PerMonitor Version 2, or PMv2 for short) for any GUI
|
// applications, to allow your user interface scale to an appropriate
|
||||||
// applications, to allow your user interface scale to an appropriate
|
// size and still stay sharp, though you will have to do the calculation
|
||||||
// size and still stay sharp, though you will have to do the calculation
|
// and resize by yourself.
|
||||||
// and resize by yourself.
|
Utils::tryToEnableHighestDpiAwarenessLevel();
|
||||||
Utils::tryToEnableHighestDpiAwarenessLevel();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (!(options & Option::DontEnsureNonNativeWidgetSiblings)) {
|
// This attribute is known to be __NOT__ compatible with QGLWidget.
|
||||||
// This attribute is known to be __NOT__ compatible with QGLWidget.
|
// Please consider migrating to the recommended QOpenGLWidget instead.
|
||||||
// Please consider migrating to the recommended QOpenGLWidget instead.
|
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
|
||||||
}
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
if (!(options & Option::DontTouchHighDpiScalingPolicy)) {
|
// Enable high DPI scaling by default, but only for Qt5 applications,
|
||||||
// Enable high DPI scaling by default, but only for Qt5 applications,
|
// because this has become the default setting since Qt6 and it can't
|
||||||
// because this has become the default setting since Qt6 and it can't
|
// be changed from outside anymore (except for internal testing purposes).
|
||||||
// be changed from outside anymore (except for internal testing purposes).
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||||
if (!(options & Option::DontTouchScaleFactorRoundingPolicy)) {
|
// Non-integer scale factors will cause Qt have some painting defects
|
||||||
// Non-integer scale factors will cause Qt have some painting defects
|
// for both Qt Widgets and Qt Quick applications, and it's still not
|
||||||
// for both Qt Widgets and Qt Quick applications, and it's still not
|
// totally fixed till now (Qt 6.4), so we round the scale factors to
|
||||||
// totally fixed till now (Qt 6.4), so we round the scale factors to
|
// get a better looking. Non-integer scale factors will also cause
|
||||||
// get a better looking. Non-integer scale factors will also cause
|
// flicker and jitter during window resizing.
|
||||||
// flicker and jitter during window resizing.
|
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
||||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
qRegisterMetaType<Option>();
|
|
||||||
qRegisterMetaType<SystemTheme>();
|
qRegisterMetaType<SystemTheme>();
|
||||||
qRegisterMetaType<SystemButtonType>();
|
qRegisterMetaType<SystemButtonType>();
|
||||||
qRegisterMetaType<ResourceType>();
|
qRegisterMetaType<ResourceType>();
|
||||||
|
@ -313,7 +302,6 @@ void FramelessHelper::Core::initialize(const Options options)
|
||||||
qRegisterMetaType<ButtonState>();
|
qRegisterMetaType<ButtonState>();
|
||||||
qRegisterMetaType<WindowsVersion>();
|
qRegisterMetaType<WindowsVersion>();
|
||||||
qRegisterMetaType<VersionNumber>();
|
qRegisterMetaType<VersionNumber>();
|
||||||
qRegisterMetaType<UserSettings>();
|
|
||||||
qRegisterMetaType<SystemParameters>();
|
qRegisterMetaType<SystemParameters>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,8 @@ public:
|
||||||
Q_NODISCARD Global::SystemTheme systemTheme() const;
|
Q_NODISCARD Global::SystemTheme systemTheme() const;
|
||||||
Q_NODISCARD QColor systemAccentColor() const;
|
Q_NODISCARD QColor systemAccentColor() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
static void addWindow(const Global::SystemParameters ¶ms);
|
||||||
static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms);
|
Q_INVOKABLE void notifySystemThemeHasChangedOrNot();
|
||||||
void notifySystemThemeHasChangedOrNot();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the QtCore module of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:LGPL$
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
||||||
** packaging of this file. Please review the following information to
|
|
||||||
** ensure the GNU Lesser General Public License version 3 requirements
|
|
||||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 2.0 or (at your option) the GNU General
|
|
||||||
** Public license version 3 or any later version approved by the KDE Free
|
|
||||||
** Qt Foundation. The licenses are as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
||||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "qwinregistry_p.h"
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
|
|
||||||
#include <QtCore/qvarlengtharray.h>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
QWinRegistryKey::QWinRegistryKey()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open a key with the specified permissions (KEY_READ/KEY_WRITE).
|
|
||||||
// "access" is to explicitly use the 32- or 64-bit branch.
|
|
||||||
QWinRegistryKey::QWinRegistryKey(HKEY parentHandle, QStringView subKey,
|
|
||||||
REGSAM permissions, REGSAM access)
|
|
||||||
{
|
|
||||||
if (RegOpenKeyExW(parentHandle, qUtf16Printable(subKey), 0,
|
|
||||||
permissions | access, &m_key) != ERROR_SUCCESS) {
|
|
||||||
m_key = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QWinRegistryKey::~QWinRegistryKey()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QWinRegistryKey::close()
|
|
||||||
{
|
|
||||||
if (isValid()) {
|
|
||||||
RegCloseKey(m_key);
|
|
||||||
m_key = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QWinRegistryKey::stringValue(QStringView subKey) const
|
|
||||||
{
|
|
||||||
QString result = {};
|
|
||||||
if (!isValid()) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
DWORD type = 0;
|
|
||||||
DWORD size = 0;
|
|
||||||
if ((RegQueryValueExW(m_key, qUtf16Printable(subKey), nullptr, &type, nullptr, &size) != ERROR_SUCCESS)
|
|
||||||
|| ((type != REG_SZ) && (type != REG_EXPAND_SZ)) || (size <= 2)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// Reserve more for rare cases where trailing '\0' are missing in registry.
|
|
||||||
// Rely on 0-termination since strings of size 256 padded with 0 have been
|
|
||||||
// observed (QTBUG-84455).
|
|
||||||
size += 2;
|
|
||||||
QVarLengthArray<unsigned char> buffer(static_cast<int>(size));
|
|
||||||
std::fill(buffer.data(), buffer.data() + size, 0u);
|
|
||||||
if (RegQueryValueExW(m_key, qUtf16Printable(subKey), nullptr, &type, buffer.data(), &size) == ERROR_SUCCESS) {
|
|
||||||
result = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buffer.constData()));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPair<DWORD, bool> QWinRegistryKey::dwordValue(QStringView subKey) const
|
|
||||||
{
|
|
||||||
if (!isValid()) {
|
|
||||||
return qMakePair(0, false);
|
|
||||||
}
|
|
||||||
DWORD type = 0;
|
|
||||||
if ((RegQueryValueExW(m_key, qUtf16Printable(subKey), nullptr, &type, nullptr, nullptr) != ERROR_SUCCESS)
|
|
||||||
|| (type != REG_DWORD)) {
|
|
||||||
return qMakePair(0, false);
|
|
||||||
}
|
|
||||||
DWORD value = 0;
|
|
||||||
DWORD size = sizeof(value);
|
|
||||||
const bool ok =
|
|
||||||
RegQueryValueExW(m_key, qUtf16Printable(subKey), nullptr, nullptr,
|
|
||||||
reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS;
|
|
||||||
return qMakePair(value, ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
|
|
@ -1,95 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the QtCore module of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:LGPL$
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
||||||
** packaging of this file. Please review the following information to
|
|
||||||
** ensure the GNU Lesser General Public License version 3 requirements
|
|
||||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 2.0 or (at your option) the GNU General
|
|
||||||
** Public license version 3 or any later version approved by the KDE Free
|
|
||||||
** Qt Foundation. The licenses are as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
||||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
//
|
|
||||||
// W A R N I N G
|
|
||||||
// -------------
|
|
||||||
//
|
|
||||||
// This file is not part of the Qt API. It exists purely as an
|
|
||||||
// implementation detail. This header file may change from version to
|
|
||||||
// version without notice, or even be removed.
|
|
||||||
//
|
|
||||||
// We mean it.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "framelesshelpercore_global.h"
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
|
||||||
#include <QtCore/private/qwinregistry_p.h>
|
|
||||||
#else // QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
|
||||||
#include <QtCore/qpair.h>
|
|
||||||
#include <QtCore/qstring.h>
|
|
||||||
#include "framelesshelper_windows.h"
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class FRAMELESSHELPER_CORE_API QWinRegistryKey
|
|
||||||
{
|
|
||||||
Q_DISABLE_COPY(QWinRegistryKey)
|
|
||||||
|
|
||||||
public:
|
|
||||||
QWinRegistryKey();
|
|
||||||
explicit QWinRegistryKey(HKEY parentHandle, QStringView subKey,
|
|
||||||
REGSAM permissions = KEY_READ, REGSAM access = 0);
|
|
||||||
~QWinRegistryKey();
|
|
||||||
|
|
||||||
QWinRegistryKey(QWinRegistryKey &&other) noexcept
|
|
||||||
: m_key(std::exchange(other.m_key, nullptr)) {}
|
|
||||||
QWinRegistryKey &operator=(QWinRegistryKey &&other) noexcept {
|
|
||||||
QWinRegistryKey moved(std::move(other));
|
|
||||||
swap(moved);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
void swap(QWinRegistryKey &other) noexcept { std::swap(m_key, other.m_key); }
|
|
||||||
|
|
||||||
[[nodiscard]] bool isValid() const { return m_key != nullptr; }
|
|
||||||
[[nodiscard]] operator HKEY() const { return m_key; }
|
|
||||||
void close();
|
|
||||||
|
|
||||||
[[nodiscard]] QString stringValue(QStringView subKey) const;
|
|
||||||
[[nodiscard]] QPair<DWORD, bool> dwordValue(QStringView subKey) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
HKEY m_key = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
|
|
@ -35,7 +35,6 @@
|
||||||
#else
|
#else
|
||||||
# include <QtGui/qpa/qplatformwindow_p.h>
|
# include <QtGui/qpa/qplatformwindow_p.h>
|
||||||
#endif
|
#endif
|
||||||
#include "qwinregistry_p.h"
|
|
||||||
#include "framelesswindowsmanager.h"
|
#include "framelesswindowsmanager.h"
|
||||||
#include "framelesshelper_windows.h"
|
#include "framelesshelper_windows.h"
|
||||||
#include <atlbase.h>
|
#include <atlbase.h>
|
||||||
|
@ -50,8 +49,6 @@ using namespace Global;
|
||||||
struct Win32UtilsHelperData
|
struct Win32UtilsHelperData
|
||||||
{
|
{
|
||||||
WNDPROC originalWindowProc = nullptr;
|
WNDPROC originalWindowProc = nullptr;
|
||||||
Options options = {};
|
|
||||||
QPoint offset = {};
|
|
||||||
IsWindowFixedSizeCallback isWindowFixedSize = nullptr;
|
IsWindowFixedSizeCallback isWindowFixedSize = nullptr;
|
||||||
IsInsideTitleBarDraggableAreaCallback isInTitleBarArea = nullptr;
|
IsInsideTitleBarDraggableAreaCallback isInTitleBarArea = nullptr;
|
||||||
GetWindowDevicePixelRatioCallback getDevicePixelRatio = nullptr;
|
GetWindowDevicePixelRatioCallback getDevicePixelRatio = nullptr;
|
||||||
|
@ -127,6 +124,7 @@ FRAMELESSHELPER_STRING_CONSTANT(SetMenuDefaultItem)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(HiliteMenuItem)
|
FRAMELESSHELPER_STRING_CONSTANT(HiliteMenuItem)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(TrackPopupMenu)
|
FRAMELESSHELPER_STRING_CONSTANT(TrackPopupMenu)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(ClientToScreen)
|
FRAMELESSHELPER_STRING_CONSTANT(ClientToScreen)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT2(HKEY_CURRENT_USER, "HKEY_CURRENT_USER")
|
||||||
|
|
||||||
[[nodiscard]] static inline bool
|
[[nodiscard]] static inline bool
|
||||||
doCompareWindowsVersion(const DWORD dwMajor, const DWORD dwMinor, const DWORD dwBuild)
|
doCompareWindowsVersion(const DWORD dwMajor, const DWORD dwMinor, const DWORD dwBuild)
|
||||||
|
@ -244,14 +242,13 @@ FRAMELESSHELPER_STRING_CONSTANT(ClientToScreen)
|
||||||
const auto getNativePosFromMouse = [lParam]() -> QPoint {
|
const auto getNativePosFromMouse = [lParam]() -> QPoint {
|
||||||
return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||||
};
|
};
|
||||||
const auto getNativeGlobalPosFromKeyboard = [hWnd, windowId, &data]() -> QPoint {
|
const auto getNativeGlobalPosFromKeyboard = [hWnd, windowId]() -> QPoint {
|
||||||
RECT windowPos = {};
|
RECT windowPos = {};
|
||||||
if (GetWindowRect(hWnd, &windowPos) == FALSE) {
|
if (GetWindowRect(hWnd, &windowPos) == FALSE) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(kGetWindowRect);
|
qWarning() << Utils::getSystemErrorMessage(kGetWindowRect);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const bool maxOrFull = (IsMaximized(hWnd) ||
|
const bool maxOrFull = (IsMaximized(hWnd) || Utils::isFullScreen(windowId));
|
||||||
((data.options & Option::DontTreatFullScreenAsZoomed) ? false : Utils::isFullScreen(windowId)));
|
|
||||||
const int frameSizeX = Utils::getResizeBorderThickness(windowId, true, true);
|
const int frameSizeX = Utils::getResizeBorderThickness(windowId, true, true);
|
||||||
const bool frameBorderVisible = Utils::isWindowFrameBorderVisible();
|
const bool frameBorderVisible = Utils::isWindowFrameBorderVisible();
|
||||||
const int horizontalOffset = ((maxOrFull || !frameBorderVisible) ? 0 : frameSizeX);
|
const int horizontalOffset = ((maxOrFull || !frameBorderVisible) ? 0 : frameSizeX);
|
||||||
|
@ -320,8 +317,7 @@ FRAMELESSHELPER_STRING_CONSTANT(ClientToScreen)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (shouldShowSystemMenu) {
|
if (shouldShowSystemMenu) {
|
||||||
Utils::showSystemMenu(windowId, nativeGlobalPos, data.offset,
|
Utils::showSystemMenu(windowId, nativeGlobalPos, broughtByKeyboard, data.isWindowFixedSize);
|
||||||
broughtByKeyboard, data.options, data.isWindowFixedSize);
|
|
||||||
// QPA's internal code will handle system menu events separately, and its
|
// QPA's internal code will handle system menu events separately, and its
|
||||||
// behavior is not what we would want to see because it doesn't know our
|
// behavior is not what we would want to see because it doesn't know our
|
||||||
// window doesn't have any window frame now, so return early here to avoid
|
// window doesn't have any window frame now, so return early here to avoid
|
||||||
|
@ -351,9 +347,10 @@ bool Utils::isDwmCompositionEnabled()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const auto resultFromRegistry = []() -> bool {
|
const auto resultFromRegistry = []() -> bool {
|
||||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, qDwmRegistryKey);
|
const QSettings registry(kHKEY_CURRENT_USER + u'\\' + qDwmRegistryKey, QSettings::NativeFormat);
|
||||||
const auto result = registry.dwordValue(kComposition);
|
bool ok = false;
|
||||||
return (result.second && (result.first != 0));
|
const DWORD value = registry.value(kComposition).toULongLong(&ok);
|
||||||
|
return (ok && (value != 0));
|
||||||
};
|
};
|
||||||
static const auto pDwmIsCompositionEnabled =
|
static const auto pDwmIsCompositionEnabled =
|
||||||
reinterpret_cast<decltype(&DwmIsCompositionEnabled)>(
|
reinterpret_cast<decltype(&DwmIsCompositionEnabled)>(
|
||||||
|
@ -472,9 +469,10 @@ QString Utils::getSystemErrorMessage(const QString &function)
|
||||||
QColor Utils::getDwmColorizationColor()
|
QColor Utils::getDwmColorizationColor()
|
||||||
{
|
{
|
||||||
const auto resultFromRegistry = []() -> QColor {
|
const auto resultFromRegistry = []() -> QColor {
|
||||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, qDwmRegistryKey);
|
const QSettings registry(kHKEY_CURRENT_USER + u'\\' + qDwmRegistryKey, QSettings::NativeFormat);
|
||||||
const auto result = registry.dwordValue(kColorizationColor);
|
bool ok = false;
|
||||||
return (result.second ? QColor::fromRgba(result.first) : kDefaultDarkGrayColor);
|
const DWORD value = registry.value(kColorizationColor).toULongLong(&ok);
|
||||||
|
return (ok ? QColor::fromRgba(value) : kDefaultDarkGrayColor);
|
||||||
};
|
};
|
||||||
static const auto pDwmGetColorizationColor =
|
static const auto pDwmGetColorizationColor =
|
||||||
reinterpret_cast<decltype(&DwmGetColorizationColor)>(
|
reinterpret_cast<decltype(&DwmGetColorizationColor)>(
|
||||||
|
@ -498,12 +496,14 @@ DwmColorizationArea Utils::getDwmColorizationArea()
|
||||||
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
|
if (!isWindowsVersionOrGreater(WindowsVersion::_10_1507)) {
|
||||||
return DwmColorizationArea::None_;
|
return DwmColorizationArea::None_;
|
||||||
}
|
}
|
||||||
const QWinRegistryKey themeRegistry(HKEY_CURRENT_USER, qPersonalizeRegistryKey);
|
const QSettings themeRegistry(kHKEY_CURRENT_USER + u'\\' + qPersonalizeRegistryKey, QSettings::NativeFormat);
|
||||||
const auto themeValue = themeRegistry.dwordValue(qDwmColorKeyName);
|
bool themeOk = false;
|
||||||
const QWinRegistryKey dwmRegistry(HKEY_CURRENT_USER, qDwmRegistryKey);
|
const DWORD themeValue = themeRegistry.value(qDwmColorKeyName).toULongLong(&themeOk);
|
||||||
const auto dwmValue = dwmRegistry.dwordValue(qDwmColorKeyName);
|
const QSettings dwmRegistry(kHKEY_CURRENT_USER + u'\\' + qDwmRegistryKey, QSettings::NativeFormat);
|
||||||
const bool theme = themeValue.second && (themeValue.first != 0);
|
bool dwmOk = false;
|
||||||
const bool dwm = dwmValue.second && (dwmValue.first != 0);
|
const DWORD dwmValue = dwmRegistry.value(qDwmColorKeyName).toULongLong(&dwmOk);
|
||||||
|
const bool theme = (themeOk && (themeValue != 0));
|
||||||
|
const bool dwm = (dwmOk && (dwmValue != 0));
|
||||||
if (theme && dwm) {
|
if (theme && dwm) {
|
||||||
return DwmColorizationArea::All;
|
return DwmColorizationArea::All;
|
||||||
} else if (theme) {
|
} else if (theme) {
|
||||||
|
@ -514,8 +514,7 @@ DwmColorizationArea Utils::getDwmColorizationArea()
|
||||||
return DwmColorizationArea::None_;
|
return DwmColorizationArea::None_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const QPoint &offset,
|
void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool selectFirstEntry,
|
||||||
const bool selectFirstEntry, const Options options,
|
|
||||||
const IsWindowFixedSizeCallback &isWindowFixedSize)
|
const IsWindowFixedSizeCallback &isWindowFixedSize)
|
||||||
{
|
{
|
||||||
Q_ASSERT(windowId);
|
Q_ASSERT(windowId);
|
||||||
|
@ -531,8 +530,7 @@ void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const QPoint &
|
||||||
// as an error so just ignore it and return early.
|
// as an error so just ignore it and return early.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bool maxOrFull = (IsMaximized(hWnd) ||
|
const bool maxOrFull = (IsMaximized(hWnd) || isFullScreen(windowId));
|
||||||
((options & Option::DontTreatFullScreenAsZoomed) ? false : isFullScreen(windowId)));
|
|
||||||
const bool fixedSize = isWindowFixedSize();
|
const bool fixedSize = isWindowFixedSize();
|
||||||
EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
// The first menu item should be selected by default if the menu is brought
|
// The first menu item should be selected by default if the menu is brought
|
||||||
|
@ -545,7 +543,7 @@ void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const QPoint &
|
||||||
// highlight bar to indicate the current selected menu item, which will make
|
// highlight bar to indicate the current selected menu item, which will make
|
||||||
// the menu look kind of weird. Currently I don't know how to fix this issue.
|
// the menu look kind of weird. Currently I don't know how to fix this issue.
|
||||||
HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
|
HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
|
||||||
EnableMenuItem(hMenu, SC_MOVE, (MF_BYCOMMAND | ((!maxOrFull && !(options & Option::DisableDragging)) ? MFS_ENABLED : MFS_DISABLED)));
|
EnableMenuItem(hMenu, SC_MOVE, (MF_BYCOMMAND | (!maxOrFull ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
EnableMenuItem(hMenu, SC_SIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
EnableMenuItem(hMenu, SC_SIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
EnableMenuItem(hMenu, SC_MINIMIZE, (MF_BYCOMMAND | MFS_ENABLED));
|
EnableMenuItem(hMenu, SC_MINIMIZE, (MF_BYCOMMAND | MFS_ENABLED));
|
||||||
EnableMenuItem(hMenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
EnableMenuItem(hMenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
|
@ -554,16 +552,8 @@ void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const QPoint &
|
||||||
// menu item per menu at most. Set the item ID to "UINT_MAX" (or simply "-1")
|
// menu item per menu at most. Set the item ID to "UINT_MAX" (or simply "-1")
|
||||||
// can clear the default item for the given menu.
|
// can clear the default item for the given menu.
|
||||||
SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
|
SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
|
||||||
// If you need to adjust the menu popup position (such as in a fully
|
|
||||||
// customized window frame), you should pass in the "offset" parameter.
|
|
||||||
// But it will not be needed when the window is maximized or fullscreen
|
|
||||||
// because in that case the menu should always align to the left edge
|
|
||||||
// of the screen.
|
|
||||||
const QPoint adjustment = (maxOrFull ? QPoint(0, 0) : offset);
|
|
||||||
const int xPos = (pos.x() + adjustment.x());
|
|
||||||
const int yPos = (pos.y() + adjustment.y());
|
|
||||||
const int result = TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft()
|
const int result = TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft()
|
||||||
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), xPos, yPos, 0, hWnd, nullptr);
|
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), pos.x(), pos.y(), 0, hWnd, nullptr);
|
||||||
// TrackPopupMenu returns 0: the user cancelled the menu, or some error occurred.
|
// TrackPopupMenu returns 0: the user cancelled the menu, or some error occurred.
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
const DWORD dwError = GetLastError();
|
const DWORD dwError = GetLastError();
|
||||||
|
@ -1063,7 +1053,7 @@ bool Utils::isFrameBorderColorized()
|
||||||
return isTitleBarColorized();
|
return isTitleBarColorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::installSystemMenuHook(const WId windowId, const Options options, const QPoint &offset,
|
void Utils::installSystemMenuHook(const WId windowId,
|
||||||
const IsWindowFixedSizeCallback &isWindowFixedSize,
|
const IsWindowFixedSizeCallback &isWindowFixedSize,
|
||||||
const IsInsideTitleBarDraggableAreaCallback &isInTitleBarArea,
|
const IsInsideTitleBarDraggableAreaCallback &isInTitleBarArea,
|
||||||
const GetWindowDevicePixelRatioCallback &getDevicePixelRatio)
|
const GetWindowDevicePixelRatioCallback &getDevicePixelRatio)
|
||||||
|
@ -1093,8 +1083,6 @@ void Utils::installSystemMenuHook(const WId windowId, const Options options, con
|
||||||
//triggerFrameChange(windowId); // Crash
|
//triggerFrameChange(windowId); // Crash
|
||||||
Win32UtilsHelperData data = {};
|
Win32UtilsHelperData data = {};
|
||||||
data.originalWindowProc = originalWindowProc;
|
data.originalWindowProc = originalWindowProc;
|
||||||
data.options = options;
|
|
||||||
data.offset = offset;
|
|
||||||
data.isWindowFixedSize = isWindowFixedSize;
|
data.isWindowFixedSize = isWindowFixedSize;
|
||||||
data.isInTitleBarArea = isInTitleBarArea;
|
data.isInTitleBarArea = isInTitleBarArea;
|
||||||
data.getDevicePixelRatio = getDevicePixelRatio;
|
data.getDevicePixelRatio = getDevicePixelRatio;
|
||||||
|
@ -1302,9 +1290,10 @@ bool Utils::shouldAppsUseDarkMode_windows()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto resultFromRegistry = []() -> bool {
|
const auto resultFromRegistry = []() -> bool {
|
||||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, qPersonalizeRegistryKey);
|
const QSettings registry(kHKEY_CURRENT_USER + u'\\' + qPersonalizeRegistryKey, QSettings::NativeFormat);
|
||||||
const auto result = registry.dwordValue(kAppsUseLightTheme);
|
bool ok = false;
|
||||||
return (result.second && (result.first == 0));
|
const DWORD value = registry.value(kAppsUseLightTheme).toULongLong(&ok);
|
||||||
|
return (ok && (value == 0));
|
||||||
};
|
};
|
||||||
static const auto pShouldAppsUseDarkMode =
|
static const auto pShouldAppsUseDarkMode =
|
||||||
reinterpret_cast<BOOL(WINAPI *)(VOID)>(
|
reinterpret_cast<BOOL(WINAPI *)(VOID)>(
|
||||||
|
|
|
@ -25,7 +25,11 @@
|
||||||
#include "framelessquickhelper.h"
|
#include "framelessquickhelper.h"
|
||||||
#include "framelessquickhelper_p.h"
|
#include "framelessquickhelper_p.h"
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtGui/qpa/qplatformwindow.h> // For QWINDOWSIZE_MAX
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
# include <QtGui/qpa/qplatformwindow.h> // For QWINDOWSIZE_MAX
|
||||||
|
#else
|
||||||
|
# include <QtGui/private/qwindow_p.h> // For QWINDOWSIZE_MAX
|
||||||
|
#endif
|
||||||
#include <QtQuick/qquickwindow.h>
|
#include <QtQuick/qquickwindow.h>
|
||||||
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
|
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
|
||||||
#include <framelesswindowsmanager.h>
|
#include <framelesswindowsmanager.h>
|
||||||
|
@ -38,10 +42,14 @@ using namespace Global;
|
||||||
struct QuickHelperData
|
struct QuickHelperData
|
||||||
{
|
{
|
||||||
bool attached = false;
|
bool attached = false;
|
||||||
UserSettings settings = {};
|
|
||||||
SystemParameters params = {};
|
SystemParameters params = {};
|
||||||
QPointer<QQuickItem> titleBarItem = nullptr;
|
QPointer<QQuickItem> titleBarItem = nullptr;
|
||||||
QList<QQuickItem *> hitTestVisibleItems = {};
|
QList<QQuickItem *> hitTestVisibleItems = {};
|
||||||
|
QPointer<QQuickItem> windowIconButton = nullptr;
|
||||||
|
QPointer<QQuickItem> contextHelpButton = nullptr;
|
||||||
|
QPointer<QQuickItem> minimizeButton = nullptr;
|
||||||
|
QPointer<QQuickItem> maximizeButton = nullptr;
|
||||||
|
QPointer<QQuickItem> closeButton = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QuickHelper
|
struct QuickHelper
|
||||||
|
@ -52,17 +60,15 @@ struct QuickHelper
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(QuickHelper, g_quickHelper)
|
Q_GLOBAL_STATIC(QuickHelper, g_quickHelper)
|
||||||
|
|
||||||
static constexpr const char QTQUICK_ITEM_CLASS_NAME[] = "QQuickItem";
|
|
||||||
static constexpr const char QTQUICK_BUTTON_CLASS_NAME[] = "QQuickAbstractButton";
|
static constexpr const char QTQUICK_BUTTON_CLASS_NAME[] = "QQuickAbstractButton";
|
||||||
|
|
||||||
FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q, const UserSettings &settings) : QObject(q)
|
FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q) : QObject(q)
|
||||||
{
|
{
|
||||||
Q_ASSERT(q);
|
Q_ASSERT(q);
|
||||||
if (!q) {
|
if (!q) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
q_ptr = q;
|
q_ptr = q;
|
||||||
m_cachedSettings = settings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessQuickHelperPrivate::~FramelessQuickHelperPrivate() = default;
|
FramelessQuickHelperPrivate::~FramelessQuickHelperPrivate() = default;
|
||||||
|
@ -124,9 +130,6 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserSettings settings = m_cachedSettings;
|
|
||||||
m_cachedSettings = {};
|
|
||||||
|
|
||||||
SystemParameters params = {};
|
SystemParameters params = {};
|
||||||
params.getWindowId = [window]() -> WId { return window->winId(); };
|
params.getWindowId = [window]() -> WId { return window->winId(); };
|
||||||
params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); };
|
params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); };
|
||||||
|
@ -163,7 +166,7 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
||||||
data->attached = true;
|
data->attached = true;
|
||||||
g_quickHelper()->mutex.unlock();
|
g_quickHelper()->mutex.unlock();
|
||||||
|
|
||||||
FramelessWindowsManager::instance()->addWindow(settings, params);
|
FramelessWindowsManager::instance()->addWindow(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickHelperPrivate::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
void FramelessQuickHelperPrivate::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
||||||
|
@ -180,20 +183,20 @@ void FramelessQuickHelperPrivate::setSystemButton(QQuickItem *item, const QuickG
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
break;
|
break;
|
||||||
case QuickGlobal::SystemButtonType::WindowIcon:
|
case QuickGlobal::SystemButtonType::WindowIcon:
|
||||||
data->settings.windowIconButton = item;
|
data->windowIconButton = item;
|
||||||
break;
|
break;
|
||||||
case QuickGlobal::SystemButtonType::Help:
|
case QuickGlobal::SystemButtonType::Help:
|
||||||
data->settings.contextHelpButton = item;
|
data->contextHelpButton = item;
|
||||||
break;
|
break;
|
||||||
case QuickGlobal::SystemButtonType::Minimize:
|
case QuickGlobal::SystemButtonType::Minimize:
|
||||||
data->settings.minimizeButton = item;
|
data->minimizeButton = item;
|
||||||
break;
|
break;
|
||||||
case QuickGlobal::SystemButtonType::Maximize:
|
case QuickGlobal::SystemButtonType::Maximize:
|
||||||
case QuickGlobal::SystemButtonType::Restore:
|
case QuickGlobal::SystemButtonType::Restore:
|
||||||
data->settings.maximizeButton = item;
|
data->maximizeButton = item;
|
||||||
break;
|
break;
|
||||||
case QuickGlobal::SystemButtonType::Close:
|
case QuickGlobal::SystemButtonType::Close:
|
||||||
data->settings.closeButton = item;
|
data->closeButton = item;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +229,7 @@ void FramelessQuickHelperPrivate::showSystemMenu(const QPoint &pos)
|
||||||
}
|
}
|
||||||
const QPoint globalPos = window->mapToGlobal(pos);
|
const QPoint globalPos = window->mapToGlobal(pos);
|
||||||
const QPoint nativePos = QPointF(QPointF(globalPos) * window->effectiveDevicePixelRatio()).toPoint();
|
const QPoint nativePos = QPointF(QPointF(globalPos) * window->effectiveDevicePixelRatio()).toPoint();
|
||||||
Utils::showSystemMenu(window->winId(), nativePos, {}, false, {}, [this]() -> bool { return isWindowFixedSize(); });
|
Utils::showSystemMenu(window->winId(), nativePos, false, [this]() -> bool { return isWindowFixedSize(); });
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(pos);
|
Q_UNUSED(pos);
|
||||||
#endif
|
#endif
|
||||||
|
@ -287,10 +290,6 @@ void FramelessQuickHelperPrivate::bringWindowToFront()
|
||||||
|
|
||||||
bool FramelessQuickHelperPrivate::isWindowFixedSize() const
|
bool FramelessQuickHelperPrivate::isWindowFixedSize() const
|
||||||
{
|
{
|
||||||
const QuickHelperData data = getWindowData();
|
|
||||||
if (data.settings.options & Option::DisableResizing) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Q_Q(const FramelessQuickHelper);
|
Q_Q(const FramelessQuickHelper);
|
||||||
const QQuickWindow * const window = q->window();
|
const QQuickWindow * const window = q->window();
|
||||||
if (!window) {
|
if (!window) {
|
||||||
|
@ -307,16 +306,16 @@ bool FramelessQuickHelperPrivate::isWindowFixedSize() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickHelperPrivate::setWindowFixedSize(const bool value, const bool force)
|
void FramelessQuickHelperPrivate::setWindowFixedSize(const bool value)
|
||||||
{
|
{
|
||||||
if ((isWindowFixedSize() == value) && !force) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Q_Q(FramelessQuickHelper);
|
Q_Q(FramelessQuickHelper);
|
||||||
QQuickWindow * const window = q->window();
|
QQuickWindow * const window = q->window();
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isWindowFixedSize() == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
const QSize size = window->size();
|
const QSize size = window->size();
|
||||||
window->setMinimumSize(size);
|
window->setMinimumSize(size);
|
||||||
|
@ -355,37 +354,32 @@ bool FramelessQuickHelperPrivate::isInSystemButtons(const QPoint &pos, QuickGlob
|
||||||
}
|
}
|
||||||
*button = QuickGlobal::SystemButtonType::Unknown;
|
*button = QuickGlobal::SystemButtonType::Unknown;
|
||||||
const QuickHelperData data = getWindowData();
|
const QuickHelperData data = getWindowData();
|
||||||
if (data.settings.windowIconButton && data.settings.windowIconButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
if (data.windowIconButton) {
|
||||||
const auto iconBtn = qobject_cast<QQuickItem *>(data.settings.windowIconButton);
|
if (mapItemGeometryToScene(data.windowIconButton).contains(pos)) {
|
||||||
if (mapItemGeometryToScene(iconBtn).contains(pos)) {
|
|
||||||
*button = QuickGlobal::SystemButtonType::WindowIcon;
|
*button = QuickGlobal::SystemButtonType::WindowIcon;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.settings.contextHelpButton && data.settings.contextHelpButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
if (data.contextHelpButton) {
|
||||||
const auto helpBtn = qobject_cast<QQuickItem *>(data.settings.contextHelpButton);
|
if (mapItemGeometryToScene(data.contextHelpButton).contains(pos)) {
|
||||||
if (mapItemGeometryToScene(helpBtn).contains(pos)) {
|
|
||||||
*button = QuickGlobal::SystemButtonType::Help;
|
*button = QuickGlobal::SystemButtonType::Help;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.settings.minimizeButton && data.settings.minimizeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
if (data.minimizeButton) {
|
||||||
const auto minBtn = qobject_cast<QQuickItem *>(data.settings.minimizeButton);
|
if (mapItemGeometryToScene(data.minimizeButton).contains(pos)) {
|
||||||
if (mapItemGeometryToScene(minBtn).contains(pos)) {
|
|
||||||
*button = QuickGlobal::SystemButtonType::Minimize;
|
*button = QuickGlobal::SystemButtonType::Minimize;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.settings.maximizeButton && data.settings.maximizeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
if (data.maximizeButton) {
|
||||||
const auto maxBtn = qobject_cast<QQuickItem *>(data.settings.maximizeButton);
|
if (mapItemGeometryToScene(data.maximizeButton).contains(pos)) {
|
||||||
if (mapItemGeometryToScene(maxBtn).contains(pos)) {
|
|
||||||
*button = QuickGlobal::SystemButtonType::Maximize;
|
*button = QuickGlobal::SystemButtonType::Maximize;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.settings.closeButton && data.settings.closeButton->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
if (data.closeButton) {
|
||||||
const auto closeBtn = qobject_cast<QQuickItem *>(data.settings.closeButton);
|
if (mapItemGeometryToScene(data.closeButton).contains(pos)) {
|
||||||
if (mapItemGeometryToScene(closeBtn).contains(pos)) {
|
|
||||||
*button = QuickGlobal::SystemButtonType::Close;
|
*button = QuickGlobal::SystemButtonType::Close;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -400,12 +394,11 @@ bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) c
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QRegion region = mapItemGeometryToScene(data.titleBarItem);
|
QRegion region = mapItemGeometryToScene(data.titleBarItem);
|
||||||
const auto systemButtons = {data.settings.windowIconButton, data.settings.contextHelpButton,
|
const auto systemButtons = {data.windowIconButton, data.contextHelpButton,
|
||||||
data.settings.minimizeButton, data.settings.maximizeButton, data.settings.closeButton};
|
data.minimizeButton, data.maximizeButton, data.closeButton};
|
||||||
for (auto &&button : qAsConst(systemButtons)) {
|
for (auto &&button : qAsConst(systemButtons)) {
|
||||||
if (button && button->inherits(QTQUICK_ITEM_CLASS_NAME)) {
|
if (button) {
|
||||||
const auto quickButton = qobject_cast<QQuickItem *>(button);
|
region -= mapItemGeometryToScene(button);
|
||||||
region -= mapItemGeometryToScene(quickButton);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!data.hitTestVisibleItems.isEmpty()) {
|
if (!data.hitTestVisibleItems.isEmpty()) {
|
||||||
|
@ -455,29 +448,29 @@ void FramelessQuickHelperPrivate::setSystemButtonState(const QuickGlobal::System
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
} break;
|
} break;
|
||||||
case QuickGlobal::SystemButtonType::WindowIcon: {
|
case QuickGlobal::SystemButtonType::WindowIcon: {
|
||||||
if (data.settings.windowIconButton && data.settings.windowIconButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
if (data.windowIconButton && data.windowIconButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.windowIconButton);
|
quickButton = qobject_cast<QQuickAbstractButton *>(data.windowIconButton);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case QuickGlobal::SystemButtonType::Help: {
|
case QuickGlobal::SystemButtonType::Help: {
|
||||||
if (data.settings.contextHelpButton && data.settings.contextHelpButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
if (data.contextHelpButton && data.contextHelpButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.contextHelpButton);
|
quickButton = qobject_cast<QQuickAbstractButton *>(data.contextHelpButton);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case QuickGlobal::SystemButtonType::Minimize: {
|
case QuickGlobal::SystemButtonType::Minimize: {
|
||||||
if (data.settings.minimizeButton && data.settings.minimizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
if (data.minimizeButton && data.minimizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.minimizeButton);
|
quickButton = qobject_cast<QQuickAbstractButton *>(data.minimizeButton);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case QuickGlobal::SystemButtonType::Maximize:
|
case QuickGlobal::SystemButtonType::Maximize:
|
||||||
case QuickGlobal::SystemButtonType::Restore: {
|
case QuickGlobal::SystemButtonType::Restore: {
|
||||||
if (data.settings.maximizeButton && data.settings.maximizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
if (data.maximizeButton && data.maximizeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.maximizeButton);
|
quickButton = qobject_cast<QQuickAbstractButton *>(data.maximizeButton);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case QuickGlobal::SystemButtonType::Close: {
|
case QuickGlobal::SystemButtonType::Close: {
|
||||||
if (data.settings.closeButton && data.settings.closeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
if (data.closeButton && data.closeButton->inherits(QTQUICK_BUTTON_CLASS_NAME)) {
|
||||||
quickButton = qobject_cast<QQuickAbstractButton *>(data.settings.closeButton);
|
quickButton = qobject_cast<QQuickAbstractButton *>(data.closeButton);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -546,8 +539,8 @@ QuickHelperData *FramelessQuickHelperPrivate::getWindowDataMutable() const
|
||||||
return &g_quickHelper()->data[windowId];
|
return &g_quickHelper()->data[windowId];
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent, const UserSettings &settings)
|
FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent)
|
||||||
: QQuickItem(parent), d_ptr(new FramelessQuickHelperPrivate(this, settings))
|
: QQuickItem(parent), d_ptr(new FramelessQuickHelperPrivate(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,16 +638,16 @@ void FramelessQuickHelper::bringWindowToFront()
|
||||||
d->bringWindowToFront();
|
d->bringWindowToFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickHelper::setWindowFixedSize(const bool value, const bool force)
|
void FramelessQuickHelper::setWindowFixedSize(const bool value)
|
||||||
{
|
{
|
||||||
Q_D(FramelessQuickHelper);
|
Q_D(FramelessQuickHelper);
|
||||||
d->setWindowFixedSize(value, force);
|
d->setWindowFixedSize(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickHelper::itemChange(const ItemChange change, const ItemChangeData &data)
|
void FramelessQuickHelper::itemChange(const ItemChange change, const ItemChangeData &data)
|
||||||
{
|
{
|
||||||
QQuickItem::itemChange(change, data);
|
QQuickItem::itemChange(change, data);
|
||||||
if ((change == FramelessQuickHelper::ItemSceneChange) && data.window) {
|
if ((change == ItemSceneChange) && data.window) {
|
||||||
Q_D(FramelessQuickHelper);
|
Q_D(FramelessQuickHelper);
|
||||||
d->attachToWindow();
|
d->attachToWindow();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickHelperPrivate : public QObject
|
||||||
Q_DISABLE_COPY_MOVE(FramelessQuickHelperPrivate)
|
Q_DISABLE_COPY_MOVE(FramelessQuickHelperPrivate)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickHelperPrivate(FramelessQuickHelper *q, const Global::UserSettings &settings = {});
|
explicit FramelessQuickHelperPrivate(FramelessQuickHelper *q);
|
||||||
~FramelessQuickHelperPrivate() override;
|
~FramelessQuickHelperPrivate() override;
|
||||||
|
|
||||||
Q_NODISCARD static FramelessQuickHelperPrivate *get(FramelessQuickHelper *pub);
|
Q_NODISCARD static FramelessQuickHelperPrivate *get(FramelessQuickHelper *pub);
|
||||||
|
@ -63,7 +63,7 @@ public:
|
||||||
void bringWindowToFront();
|
void bringWindowToFront();
|
||||||
|
|
||||||
Q_NODISCARD bool isWindowFixedSize() const;
|
Q_NODISCARD bool isWindowFixedSize() const;
|
||||||
void setWindowFixedSize(const bool value, const bool force = false);
|
void setWindowFixedSize(const bool value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const;
|
Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const;
|
||||||
|
@ -76,7 +76,6 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FramelessQuickHelper *q_ptr = nullptr;
|
FramelessQuickHelper *q_ptr = nullptr;
|
||||||
Global::UserSettings m_cachedSettings = {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -58,7 +58,6 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inited = true;
|
inited = true;
|
||||||
qRegisterMetaType<QuickGlobal::Options>();
|
|
||||||
qRegisterMetaType<QuickGlobal::SystemTheme>();
|
qRegisterMetaType<QuickGlobal::SystemTheme>();
|
||||||
qRegisterMetaType<QuickGlobal::SystemButtonType>();
|
qRegisterMetaType<QuickGlobal::SystemButtonType>();
|
||||||
qRegisterMetaType<QuickGlobal::ResourceType>();
|
qRegisterMetaType<QuickGlobal::ResourceType>();
|
||||||
|
|
|
@ -34,14 +34,13 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q, const UserSettings &settings) : QObject(q)
|
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q) : QObject(q)
|
||||||
{
|
{
|
||||||
Q_ASSERT(q);
|
Q_ASSERT(q);
|
||||||
if (!q) {
|
if (!q) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
q_ptr = q;
|
q_ptr = q;
|
||||||
m_settings = settings;
|
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +87,7 @@ bool FramelessQuickWindowPrivate::isZoomed() const
|
||||||
Q_Q(const FramelessQuickWindow);
|
Q_Q(const FramelessQuickWindow);
|
||||||
const FramelessQuickWindow::Visibility visibility = q->visibility();
|
const FramelessQuickWindow::Visibility visibility = q->visibility();
|
||||||
return ((visibility == FramelessQuickWindow::Maximized) ||
|
return ((visibility == FramelessQuickWindow::Maximized) ||
|
||||||
((m_settings.options & Option::DontTreatFullScreenAsZoomed)
|
(visibility == FramelessQuickWindow::FullScreen));
|
||||||
? false : (visibility == FramelessQuickWindow::FullScreen)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessQuickWindowPrivate::isFullScreen() const
|
bool FramelessQuickWindowPrivate::isFullScreen() const
|
||||||
|
@ -228,9 +226,6 @@ void FramelessQuickWindowPrivate::toggleFullScreen()
|
||||||
void FramelessQuickWindowPrivate::initialize()
|
void FramelessQuickWindowPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessQuickWindow);
|
Q_Q(FramelessQuickWindow);
|
||||||
if (m_settings.options & Option::TransparentWindowBackground) {
|
|
||||||
q->setColor(kDefaultTransparentColor);
|
|
||||||
}
|
|
||||||
QQuickItem * const rootItem = q->contentItem();
|
QQuickItem * const rootItem = q->contentItem();
|
||||||
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
||||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||||
|
@ -254,17 +249,13 @@ void FramelessQuickWindowPrivate::initialize()
|
||||||
Q_EMIT q->fullScreenChanged();
|
Q_EMIT q->fullScreenChanged();
|
||||||
});
|
});
|
||||||
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||||
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, [this, q](){
|
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||||
updateTopBorderColor();
|
|
||||||
Q_EMIT q->frameBorderColorChanged();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const
|
bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
return (Utils::isWindowFrameBorderVisible() && !Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)
|
return (Utils::isWindowFrameBorderVisible() && !Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2));
|
||||||
&& !(m_settings.options & Option::DontDrawTopWindowFrameBorder));
|
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -291,8 +282,8 @@ void FramelessQuickWindowPrivate::updateTopBorderHeight()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent, const UserSettings &settings)
|
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent)
|
||||||
: QQuickWindow(parent), d_ptr(new FramelessQuickWindowPrivate(this, settings))
|
: QQuickWindow(parent), d_ptr(new FramelessQuickWindowPrivate(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,12 +319,6 @@ bool FramelessQuickWindow::isFullScreen() const
|
||||||
return d->isFullScreen();
|
return d->isFullScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor FramelessQuickWindow::frameBorderColor() const
|
|
||||||
{
|
|
||||||
Q_D(const FramelessQuickWindow);
|
|
||||||
return d->getFrameBorderColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessQuickWindow::snapToTopBorder(QQuickItem *item, const QuickGlobal::Anchor itemAnchor, const QuickGlobal::Anchor topBorderAnchor)
|
void FramelessQuickWindow::snapToTopBorder(QQuickItem *item, const QuickGlobal::Anchor itemAnchor, const QuickGlobal::Anchor topBorderAnchor)
|
||||||
{
|
{
|
||||||
Q_ASSERT(item);
|
Q_ASSERT(item);
|
||||||
|
|
|
@ -44,7 +44,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickWindowPrivate : public QObject
|
||||||
Q_DISABLE_COPY_MOVE(FramelessQuickWindowPrivate)
|
Q_DISABLE_COPY_MOVE(FramelessQuickWindowPrivate)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q, const Global::UserSettings &settings = {});
|
explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q);
|
||||||
~FramelessQuickWindowPrivate() override;
|
~FramelessQuickWindowPrivate() override;
|
||||||
|
|
||||||
Q_NODISCARD static FramelessQuickWindowPrivate *get(FramelessQuickWindow *pub);
|
Q_NODISCARD static FramelessQuickWindowPrivate *get(FramelessQuickWindow *pub);
|
||||||
|
@ -83,8 +83,6 @@ private:
|
||||||
QScopedPointer<QQuickRectangle> m_topBorderRectangle;
|
QScopedPointer<QQuickRectangle> m_topBorderRectangle;
|
||||||
QScopedPointer<QQuickAnchors> m_topBorderAnchors;
|
QScopedPointer<QQuickAnchors> m_topBorderAnchors;
|
||||||
QQuickWindow::Visibility m_savedVisibility = QQuickWindow::Windowed;
|
QQuickWindow::Visibility m_savedVisibility = QQuickWindow::Windowed;
|
||||||
Global::UserSettings m_settings = {};
|
|
||||||
bool m_windowExposed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -31,12 +31,18 @@ set(SOURCES
|
||||||
${INCLUDE_PREFIX}/framelesswidget.h
|
${INCLUDE_PREFIX}/framelesswidget.h
|
||||||
${INCLUDE_PREFIX}/framelessmainwindow.h
|
${INCLUDE_PREFIX}/framelessmainwindow.h
|
||||||
${INCLUDE_PREFIX}/standardsystembutton.h
|
${INCLUDE_PREFIX}/standardsystembutton.h
|
||||||
|
${INCLUDE_PREFIX}/framelesswidgetshelper.h
|
||||||
|
${INCLUDE_PREFIX}/standardtitlebar.h
|
||||||
framelesswidgetshelper_p.h
|
framelesswidgetshelper_p.h
|
||||||
standardsystembutton_p.h
|
standardsystembutton_p.h
|
||||||
|
standardtitlebar_p.h
|
||||||
framelessmainwindow.cpp
|
framelessmainwindow.cpp
|
||||||
framelesswidgetshelper.cpp
|
framelesswidgetshelper.cpp
|
||||||
framelesswidget.cpp
|
framelesswidget.cpp
|
||||||
standardsystembutton.cpp
|
standardsystembutton.cpp
|
||||||
|
standardtitlebar.cpp
|
||||||
|
widgetssharedhelper_p.h
|
||||||
|
widgetssharedhelper.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
|
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
|
||||||
|
|
|
@ -23,92 +23,50 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "framelessmainwindow.h"
|
#include "framelessmainwindow.h"
|
||||||
#include "framelesswidgetshelper_p.h"
|
#include "framelesswidgetshelper.h"
|
||||||
|
#include "widgetssharedhelper_p.h"
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
FramelessMainWindow::FramelessMainWindow(QWidget *parent, const Qt::WindowFlags flags, const UserSettings &settings) : QMainWindow(parent, flags)
|
FramelessMainWindow::FramelessMainWindow(QWidget *parent, const Qt::WindowFlags flags) : QMainWindow(parent, flags)
|
||||||
{
|
{
|
||||||
d_ptr.reset(new FramelessWidgetsHelper(this, settings));
|
FramelessWidgetsHelper::get(this)->attach();
|
||||||
|
m_helper.reset(new WidgetsSharedHelper(this));
|
||||||
|
m_helper->setup(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessMainWindow::~FramelessMainWindow() = default;
|
FramelessMainWindow::~FramelessMainWindow() = default;
|
||||||
|
|
||||||
bool FramelessMainWindow::isNormal() const
|
bool FramelessMainWindow::isNormal() const
|
||||||
{
|
{
|
||||||
return d_ptr->isNormal();
|
return (Utils::windowStatesToWindowState(windowState()) == Qt::WindowNoState);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessMainWindow::isZoomed() const
|
bool FramelessMainWindow::isZoomed() const
|
||||||
{
|
{
|
||||||
return d_ptr->isZoomed();
|
return (isMaximized() || isFullScreen());
|
||||||
}
|
|
||||||
|
|
||||||
bool FramelessMainWindow::isFixedSize() const
|
|
||||||
{
|
|
||||||
return d_ptr->isFixedSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::setFixedSize(const bool value)
|
|
||||||
{
|
|
||||||
d_ptr->setFixedSize(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::setTitleBarWidget(QWidget *widget)
|
|
||||||
{
|
|
||||||
d_ptr->setTitleBarWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *FramelessMainWindow::titleBarWidget() const
|
|
||||||
{
|
|
||||||
return d_ptr->getTitleBarWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::setHitTestVisible(QWidget *widget)
|
|
||||||
{
|
|
||||||
d_ptr->setHitTestVisible(widget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessMainWindow::toggleMaximized()
|
void FramelessMainWindow::toggleMaximized()
|
||||||
{
|
{
|
||||||
d_ptr->toggleMaximized();
|
if (isMaximized()) {
|
||||||
|
showNormal();
|
||||||
|
} else {
|
||||||
|
showMaximized();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessMainWindow::toggleFullScreen()
|
void FramelessMainWindow::toggleFullScreen()
|
||||||
{
|
{
|
||||||
d_ptr->toggleFullScreen();
|
if (isFullScreen()) {
|
||||||
}
|
setWindowState(m_savedWindowState);
|
||||||
|
} else {
|
||||||
void FramelessMainWindow::moveToDesktopCenter()
|
m_savedWindowState = Utils::windowStatesToWindowState(windowState());
|
||||||
{
|
showFullScreen();
|
||||||
d_ptr->moveToDesktopCenter();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::bringToFront()
|
|
||||||
{
|
|
||||||
d_ptr->bringToFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::showSystemMenu(const QPoint &pos)
|
|
||||||
{
|
|
||||||
d_ptr->showSystemMenu(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::startSystemMove2(const QPoint &pos)
|
|
||||||
{
|
|
||||||
d_ptr->startSystemMove2(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::startSystemResize2(const Qt::Edges edges, const QPoint &pos)
|
|
||||||
{
|
|
||||||
d_ptr->startSystemResize2(edges, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessMainWindow::setSystemButton(QWidget *widget, const SystemButtonType buttonType)
|
|
||||||
{
|
|
||||||
d_ptr->setSystemButton(widget, buttonType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -23,102 +23,50 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "framelesswidget.h"
|
#include "framelesswidget.h"
|
||||||
#include "framelesswidgetshelper_p.h"
|
#include "framelesswidgetshelper.h"
|
||||||
|
#include "widgetssharedhelper_p.h"
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
FramelessWidget::FramelessWidget(QWidget *parent, const UserSettings &settings) : QWidget(parent)
|
FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
d_ptr.reset(new FramelessWidgetsHelper(this, settings));
|
FramelessWidgetsHelper::get(this)->attach();
|
||||||
|
m_helper.reset(new WidgetsSharedHelper(this));
|
||||||
|
m_helper->setup(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessWidget::~FramelessWidget() = default;
|
FramelessWidget::~FramelessWidget() = default;
|
||||||
|
|
||||||
bool FramelessWidget::isNormal() const
|
bool FramelessWidget::isNormal() const
|
||||||
{
|
{
|
||||||
return d_ptr->isNormal();
|
return (Utils::windowStatesToWindowState(windowState()) == Qt::WindowNoState);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessWidget::isZoomed() const
|
bool FramelessWidget::isZoomed() const
|
||||||
{
|
{
|
||||||
return d_ptr->isZoomed();
|
return (isMaximized() || isFullScreen());
|
||||||
}
|
|
||||||
|
|
||||||
bool FramelessWidget::isFixedSize() const
|
|
||||||
{
|
|
||||||
return d_ptr->isFixedSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::setFixedSize(const bool value)
|
|
||||||
{
|
|
||||||
d_ptr->setFixedSize(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::setTitleBarWidget(QWidget *widget)
|
|
||||||
{
|
|
||||||
d_ptr->setTitleBarWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *FramelessWidget::titleBarWidget() const
|
|
||||||
{
|
|
||||||
return d_ptr->getTitleBarWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::setContentWidget(QWidget *widget)
|
|
||||||
{
|
|
||||||
d_ptr->setContentWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *FramelessWidget::contentWidget() const
|
|
||||||
{
|
|
||||||
return d_ptr->getContentWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::setHitTestVisible(QWidget *widget)
|
|
||||||
{
|
|
||||||
d_ptr->setHitTestVisible(widget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidget::toggleMaximized()
|
void FramelessWidget::toggleMaximized()
|
||||||
{
|
{
|
||||||
d_ptr->toggleMaximized();
|
if (isMaximized()) {
|
||||||
|
showNormal();
|
||||||
|
} else {
|
||||||
|
showMaximized();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidget::toggleFullScreen()
|
void FramelessWidget::toggleFullScreen()
|
||||||
{
|
{
|
||||||
d_ptr->toggleFullScreen();
|
if (isFullScreen()) {
|
||||||
}
|
setWindowState(m_savedWindowState);
|
||||||
|
} else {
|
||||||
void FramelessWidget::moveToDesktopCenter()
|
m_savedWindowState = Utils::windowStatesToWindowState(windowState());
|
||||||
{
|
showFullScreen();
|
||||||
d_ptr->moveToDesktopCenter();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::bringToFront()
|
|
||||||
{
|
|
||||||
d_ptr->bringToFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::showSystemMenu(const QPoint &pos)
|
|
||||||
{
|
|
||||||
d_ptr->showSystemMenu(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::startSystemMove2(const QPoint &pos)
|
|
||||||
{
|
|
||||||
d_ptr->startSystemMove2(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::startSystemResize2(const Qt::Edges edges, const QPoint &pos)
|
|
||||||
{
|
|
||||||
d_ptr->startSystemResize2(edges, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessWidget::setSystemButton(QWidget *widget, const SystemButtonType buttonType)
|
|
||||||
{
|
|
||||||
d_ptr->setSystemButton(widget, buttonType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,19 +22,4 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#include "../../include/FramelessHelper/Widgets/framelesswidgetshelper.h"
|
||||||
|
|
||||||
#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);
|
|
||||||
};
|
|
|
@ -26,92 +26,53 @@
|
||||||
|
|
||||||
#include "framelesshelperwidgets_global.h"
|
#include "framelesshelperwidgets_global.h"
|
||||||
#include <QtCore/qobject.h>
|
#include <QtCore/qobject.h>
|
||||||
#include <QtGui/qwindow.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QLabel;
|
|
||||||
class QVBoxLayout;
|
|
||||||
class QShowEvent;
|
|
||||||
class QPaintEvent;
|
|
||||||
class QMouseEvent;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class StandardSystemButton;
|
struct WidgetsHelperData;
|
||||||
|
class FramelessWidgetsHelper;
|
||||||
|
|
||||||
class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelper : public QObject
|
class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelperPrivate : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(FramelessWidgetsHelper)
|
Q_DECLARE_PUBLIC(FramelessWidgetsHelper)
|
||||||
|
Q_DISABLE_COPY_MOVE(FramelessWidgetsHelperPrivate)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessWidgetsHelper(QWidget *q, const Global::UserSettings &settings = {});
|
explicit FramelessWidgetsHelperPrivate(FramelessWidgetsHelper *q);
|
||||||
~FramelessWidgetsHelper() override;
|
~FramelessWidgetsHelperPrivate() override;
|
||||||
|
|
||||||
Q_NODISCARD static FramelessWidgetsHelper *get(QWidget *pub);
|
Q_NODISCARD static FramelessWidgetsHelperPrivate *get(FramelessWidgetsHelper *pub);
|
||||||
Q_NODISCARD static const FramelessWidgetsHelper *get(const QWidget *pub);
|
Q_NODISCARD static const FramelessWidgetsHelperPrivate *get(const FramelessWidgetsHelper *pub);
|
||||||
|
|
||||||
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
|
Q_NODISCARD QWidget *getTitleBarWidget() const;
|
||||||
Q_NODISCARD Q_INVOKABLE bool isZoomed() const;
|
void setTitleBarWidget(QWidget *widget);
|
||||||
Q_NODISCARD Q_INVOKABLE bool isFixedSize() const;
|
|
||||||
Q_INVOKABLE void setFixedSize(const bool value, const bool force = false);
|
|
||||||
|
|
||||||
Q_INVOKABLE void setTitleBarWidget(QWidget *widget);
|
void attachToWindow();
|
||||||
Q_NODISCARD Q_INVOKABLE QWidget *getTitleBarWidget() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void setContentWidget(QWidget *widget);
|
|
||||||
Q_NODISCARD Q_INVOKABLE QWidget *getContentWidget() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void showEventHandler(QShowEvent *event);
|
|
||||||
Q_INVOKABLE void changeEventHandler(QEvent *event);
|
|
||||||
Q_INVOKABLE void paintEventHandler(QPaintEvent *event);
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void setHitTestVisible(QWidget *widget);
|
|
||||||
void toggleMaximized();
|
|
||||||
void toggleFullScreen();
|
|
||||||
void moveToDesktopCenter();
|
|
||||||
void bringToFront();
|
|
||||||
void showSystemMenu(const QPoint &pos);
|
|
||||||
void startSystemMove2(const QPoint &pos);
|
|
||||||
void startSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
|
||||||
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
||||||
|
void setHitTestVisible(QWidget *widget);
|
||||||
|
void showSystemMenu(const QPoint &pos);
|
||||||
|
void windowStartSystemMove2(const QPoint &pos);
|
||||||
|
void windowStartSystemResize2(const Qt::Edges edges, const QPoint &pos);
|
||||||
|
|
||||||
protected:
|
void moveWindowToDesktopCenter();
|
||||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
void bringWindowToFront();
|
||||||
|
|
||||||
|
Q_NODISCARD bool isWindowFixedSize() const;
|
||||||
|
void setWindowFixedSize(const bool value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize();
|
|
||||||
void createSystemTitleBar();
|
|
||||||
void createUserContentContainer();
|
|
||||||
void setupInitialUi();
|
|
||||||
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const;
|
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const;
|
||||||
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const;
|
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const;
|
||||||
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
|
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
|
||||||
Q_NODISCARD bool shouldDrawFrameBorder() const;
|
|
||||||
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
||||||
void setSystemButtonState(const Global::SystemButtonType button, const Global::ButtonState state);
|
void setSystemButtonState(const Global::SystemButtonType button, const Global::ButtonState state);
|
||||||
|
Q_NODISCARD QWidget *getWindow() const;
|
||||||
private Q_SLOTS:
|
Q_NODISCARD WidgetsHelperData getWindowData() const;
|
||||||
void updateContentsMargins();
|
Q_NODISCARD WidgetsHelperData *getWindowDataMutable() const;
|
||||||
void updateSystemTitleBarStyleSheet();
|
|
||||||
void updateSystemMaximizeButton();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<QWidget> q = nullptr;
|
FramelessWidgetsHelper *q_ptr = nullptr;
|
||||||
QScopedPointer<QWidget> m_systemTitleBarWidget;
|
|
||||||
QScopedPointer<QLabel> m_systemWindowTitleLabel;
|
|
||||||
QPointer<QWidget> m_userTitleBarWidget = nullptr;
|
|
||||||
QPointer<QWidget> m_userContentWidget = nullptr;
|
|
||||||
QScopedPointer<QVBoxLayout> m_mainLayout;
|
|
||||||
QWidgetList m_hitTestVisibleWidgets = {};
|
|
||||||
QScopedPointer<QWidget> m_userContentContainerWidget;
|
|
||||||
QScopedPointer<QVBoxLayout> m_userContentContainerLayout;
|
|
||||||
Qt::WindowState m_savedWindowState = {};
|
|
||||||
Global::UserSettings m_settings = {};
|
|
||||||
Global::SystemParameters m_params = {};
|
|
||||||
bool m_windowExposed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -340,7 +340,7 @@ SystemButtonType StandardSystemButton::buttonType()
|
||||||
return d->getButtonType();
|
return d->getButtonType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StandardSystemButton::setButtonType(const Global::SystemButtonType value)
|
void StandardSystemButton::setButtonType(const SystemButtonType value)
|
||||||
{
|
{
|
||||||
Q_D(StandardSystemButton);
|
Q_D(StandardSystemButton);
|
||||||
d->setButtonType(value);
|
d->setButtonType(value);
|
||||||
|
|
|
@ -37,7 +37,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class StandardSystemButton;
|
class StandardSystemButton;
|
||||||
|
|
||||||
class StandardSystemButtonPrivate : public QObject
|
class FRAMELESSHELPER_WIDGETS_API StandardSystemButtonPrivate : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DECLARE_PUBLIC(StandardSystemButton)
|
Q_DECLARE_PUBLIC(StandardSystemButton)
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* 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 "standardtitlebar.h"
|
||||||
|
#include "standardtitlebar_p.h"
|
||||||
|
#include "standardsystembutton.h"
|
||||||
|
#include <QtCore/qcoreevent.h>
|
||||||
|
#include <QtGui/qpainter.h>
|
||||||
|
#include <QtWidgets/qlabel.h>
|
||||||
|
#include <QtWidgets/qboxlayout.h>
|
||||||
|
#include <QtWidgets/qstyle.h>
|
||||||
|
#include <QtWidgets/qstyleoption.h>
|
||||||
|
#include <framelesswindowsmanager.h>
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using namespace Global;
|
||||||
|
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetColorTemplate, "color: %1;")
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetBackgroundColorTemplate, "background-color: %1;")
|
||||||
|
|
||||||
|
StandardTitleBarPrivate::StandardTitleBarPrivate(StandardTitleBar *q) : QObject(q)
|
||||||
|
{
|
||||||
|
Q_ASSERT(q);
|
||||||
|
if (!q) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
q_ptr = q;
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardTitleBarPrivate::~StandardTitleBarPrivate() = default;
|
||||||
|
|
||||||
|
StandardTitleBarPrivate *StandardTitleBarPrivate::get(StandardTitleBar *pub)
|
||||||
|
{
|
||||||
|
Q_ASSERT(pub);
|
||||||
|
if (!pub) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return pub->d_func();
|
||||||
|
}
|
||||||
|
|
||||||
|
const StandardTitleBarPrivate *StandardTitleBarPrivate::get(const StandardTitleBar *pub)
|
||||||
|
{
|
||||||
|
Q_ASSERT(pub);
|
||||||
|
if (!pub) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return pub->d_func();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandardTitleBarPrivate::updateMaximizeButton()
|
||||||
|
{
|
||||||
|
const bool zoomed = (m_window->isMaximized() || m_window->isFullScreen());
|
||||||
|
m_maximizeButton->setToolTip(zoomed ? tr("Restore") : tr("Maximize"));
|
||||||
|
m_maximizeButton->setButtonType(zoomed ? SystemButtonType::Restore : SystemButtonType::Maximize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandardTitleBarPrivate::updateTitleBarStyleSheet()
|
||||||
|
{
|
||||||
|
const bool active = m_window->isActiveWindow();
|
||||||
|
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||||
|
const bool colorizedTitleBar = Utils::isTitleBarColorized();
|
||||||
|
const QColor titleBarBackgroundColor = [active, colorizedTitleBar, dark]() -> QColor {
|
||||||
|
if (active) {
|
||||||
|
if (colorizedTitleBar) {
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
return Utils::getDwmColorizationColor();
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
return Utils::getWmThemeColor();
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
return Utils::getControlsAccentColor();
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (dark) {
|
||||||
|
return kDefaultBlackColor;
|
||||||
|
} else {
|
||||||
|
return kDefaultWhiteColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dark) {
|
||||||
|
return kDefaultSystemDarkColor;
|
||||||
|
} else {
|
||||||
|
return kDefaultWhiteColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
const QColor windowTitleLabelTextColor = (active ? ((dark || colorizedTitleBar) ? kDefaultWhiteColor : kDefaultBlackColor) : kDefaultDarkGrayColor);
|
||||||
|
m_windowTitleLabel->setStyleSheet(kStyleSheetColorTemplate.arg(windowTitleLabelTextColor.name()));
|
||||||
|
Q_Q(StandardTitleBar);
|
||||||
|
q->setStyleSheet(kStyleSheetBackgroundColorTemplate.arg(titleBarBackgroundColor.name()));
|
||||||
|
q->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(object);
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!object || !event) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!object->isWidgetType()) {
|
||||||
|
return QObject::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
const auto widget = qobject_cast<QWidget *>(object);
|
||||||
|
if (!widget->isWindow() || (widget != m_window)) {
|
||||||
|
return QObject::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
switch (event->type()) {
|
||||||
|
case QEvent::WindowStateChange:
|
||||||
|
updateMaximizeButton();
|
||||||
|
break;
|
||||||
|
case QEvent::ActivationChange:
|
||||||
|
updateTitleBarStyleSheet();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QObject::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandardTitleBarPrivate::initialize()
|
||||||
|
{
|
||||||
|
Q_Q(StandardTitleBar);
|
||||||
|
m_window = q->window();
|
||||||
|
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
q->setFixedHeight(kDefaultTitleBarHeight);
|
||||||
|
m_windowTitleLabel.reset(new QLabel(q));
|
||||||
|
m_windowTitleLabel->setFrameShape(QFrame::NoFrame);
|
||||||
|
QFont windowTitleFont = q->font();
|
||||||
|
windowTitleFont.setPointSize(kDefaultTitleBarFontPointSize);
|
||||||
|
m_windowTitleLabel->setFont(windowTitleFont);
|
||||||
|
m_windowTitleLabel->setText(m_window->windowTitle());
|
||||||
|
connect(m_window, &QWidget::windowTitleChanged, m_windowTitleLabel.data(), &QLabel::setText);
|
||||||
|
m_minimizeButton.reset(new StandardSystemButton(SystemButtonType::Minimize, q));
|
||||||
|
m_minimizeButton->setFixedSize(kDefaultSystemButtonSize);
|
||||||
|
m_minimizeButton->setIconSize(kDefaultSystemButtonIconSize);
|
||||||
|
m_minimizeButton->setToolTip(tr("Minimize"));
|
||||||
|
connect(m_minimizeButton.data(), &StandardSystemButton::clicked, m_window, &QWidget::showMinimized);
|
||||||
|
m_maximizeButton.reset(new StandardSystemButton(SystemButtonType::Maximize, q));
|
||||||
|
m_maximizeButton->setFixedSize(kDefaultSystemButtonSize);
|
||||||
|
m_maximizeButton->setIconSize(kDefaultSystemButtonIconSize);
|
||||||
|
updateMaximizeButton();
|
||||||
|
connect(m_maximizeButton.data(), &StandardSystemButton::clicked, this, [this](){
|
||||||
|
if (m_window->isMaximized() || m_window->isFullScreen()) {
|
||||||
|
m_window->showNormal();
|
||||||
|
} else {
|
||||||
|
m_window->showMaximized();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_closeButton.reset(new StandardSystemButton(SystemButtonType::Close, q));
|
||||||
|
m_closeButton->setFixedSize(kDefaultSystemButtonSize);
|
||||||
|
m_closeButton->setIconSize(kDefaultSystemButtonIconSize);
|
||||||
|
m_closeButton->setToolTip(tr("Close"));
|
||||||
|
connect(m_closeButton.data(), &StandardSystemButton::clicked, m_window, &QWidget::close);
|
||||||
|
const auto titleBarLayout = new QHBoxLayout(q);
|
||||||
|
titleBarLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
titleBarLayout->setSpacing(0);
|
||||||
|
titleBarLayout->addSpacerItem(new QSpacerItem(kDefaultTitleBarTitleLabelMargin, kDefaultTitleBarTitleLabelMargin));
|
||||||
|
titleBarLayout->addWidget(m_windowTitleLabel.data());
|
||||||
|
titleBarLayout->addStretch();
|
||||||
|
titleBarLayout->addWidget(m_minimizeButton.data());
|
||||||
|
titleBarLayout->addWidget(m_maximizeButton.data());
|
||||||
|
titleBarLayout->addWidget(m_closeButton.data());
|
||||||
|
q->setLayout(titleBarLayout);
|
||||||
|
updateTitleBarStyleSheet();
|
||||||
|
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged,
|
||||||
|
this, &StandardTitleBarPrivate::updateTitleBarStyleSheet);
|
||||||
|
m_window->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardTitleBar::StandardTitleBar(QWidget *parent)
|
||||||
|
: QWidget(parent), d_ptr(new StandardTitleBarPrivate(this))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardTitleBar::~StandardTitleBar() = default;
|
||||||
|
|
||||||
|
StandardSystemButton *StandardTitleBar::minimizeButton() const
|
||||||
|
{
|
||||||
|
Q_D(const StandardTitleBar);
|
||||||
|
return d->m_minimizeButton.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardSystemButton *StandardTitleBar::maximizeButton() const
|
||||||
|
{
|
||||||
|
Q_D(const StandardTitleBar);
|
||||||
|
return d->m_maximizeButton.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardSystemButton *StandardTitleBar::closeButton() const
|
||||||
|
{
|
||||||
|
Q_D(const StandardTitleBar);
|
||||||
|
return d->m_closeButton.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandardTitleBar::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
// This block of code ensures that our widget applies the stylesheet correctly.
|
||||||
|
// Enabling the "Qt::WA_StyledBackground" attribute can also achieve the same
|
||||||
|
// effect, but since it's documented as only for internal uses, we use the
|
||||||
|
// public way to do that instead.
|
||||||
|
QStyleOption option;
|
||||||
|
option.initFrom(this);
|
||||||
|
QPainter painter(this);
|
||||||
|
style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -22,19 +22,4 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#include "../../include/FramelessHelper/Widgets/standardtitlebar.h"
|
||||||
|
|
||||||
#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);
|
|
||||||
};
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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 "framelesshelperwidgets_global.h"
|
||||||
|
#include <QtCore/qobject.h>
|
||||||
|
#include <QtCore/qpointer.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QLabel;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class StandardTitleBar;
|
||||||
|
class StandardSystemButton;
|
||||||
|
|
||||||
|
class FRAMELESSHELPER_WIDGETS_API StandardTitleBarPrivate : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DECLARE_PUBLIC(StandardTitleBar)
|
||||||
|
Q_DISABLE_COPY_MOVE(StandardTitleBarPrivate)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit StandardTitleBarPrivate(StandardTitleBar *q);
|
||||||
|
~StandardTitleBarPrivate() override;
|
||||||
|
|
||||||
|
Q_NODISCARD static StandardTitleBarPrivate *get(StandardTitleBar *pub);
|
||||||
|
Q_NODISCARD static const StandardTitleBarPrivate *get(const StandardTitleBar *pub);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void updateMaximizeButton();
|
||||||
|
void updateTitleBarStyleSheet();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
StandardTitleBar *q_ptr = nullptr;
|
||||||
|
QScopedPointer<QLabel> m_windowTitleLabel;
|
||||||
|
QScopedPointer<StandardSystemButton> m_minimizeButton;
|
||||||
|
QScopedPointer<StandardSystemButton> m_maximizeButton;
|
||||||
|
QScopedPointer<StandardSystemButton> m_closeButton;
|
||||||
|
QPointer<QWidget> m_window = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* 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 "widgetssharedhelper_p.h"
|
||||||
|
#include <QtCore/qcoreevent.h>
|
||||||
|
#include <QtGui/qevent.h>
|
||||||
|
#include <QtGui/qpainter.h>
|
||||||
|
#include <QtWidgets/qwidget.h>
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using namespace Global;
|
||||||
|
|
||||||
|
WidgetsSharedHelper::WidgetsSharedHelper(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetsSharedHelper::~WidgetsSharedHelper() = default;
|
||||||
|
|
||||||
|
void WidgetsSharedHelper::setup(QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_ASSERT(widget);
|
||||||
|
if (!widget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_targetWidget == widget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_targetWidget = widget;
|
||||||
|
m_targetWidget->installEventFilter(this);
|
||||||
|
updateContentsMargins();
|
||||||
|
m_targetWidget->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WidgetsSharedHelper::eventFilter(QObject *object, QEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(object);
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!object || !event) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!object->isWidgetType()) {
|
||||||
|
return QObject::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
const auto widget = qobject_cast<QWidget *>(object);
|
||||||
|
if (widget != m_targetWidget) {
|
||||||
|
return QObject::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
switch (event->type()) {
|
||||||
|
case QEvent::Paint: {
|
||||||
|
const auto paintEvent = static_cast<QPaintEvent *>(event);
|
||||||
|
paintEventHandler(paintEvent);
|
||||||
|
} break;
|
||||||
|
case QEvent::WindowStateChange: {
|
||||||
|
changeEventHandler(event);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QObject::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetsSharedHelper::changeEventHandler(QEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event->type() != QEvent::WindowStateChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateContentsMargins();
|
||||||
|
QMetaObject::invokeMethod(m_targetWidget, "hiddenChanged");
|
||||||
|
QMetaObject::invokeMethod(m_targetWidget, "normalChanged");
|
||||||
|
QMetaObject::invokeMethod(m_targetWidget, "zoomedChanged");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!shouldDrawFrameBorder()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QPainter painter(m_targetWidget);
|
||||||
|
painter.save();
|
||||||
|
QPen pen = {};
|
||||||
|
pen.setColor(Utils::getFrameBorderColor(m_targetWidget->isActiveWindow()));
|
||||||
|
pen.setWidth(1);
|
||||||
|
painter.setPen(pen);
|
||||||
|
// We should use "m_targetWidget->width() - 1" actually but we can't because
|
||||||
|
// Qt's drawing system have some rounding error internally and
|
||||||
|
// if we minus one here we'll get a one pixel gap, so sad. But
|
||||||
|
// drawing a line with extra pixels won't hurt anyway.
|
||||||
|
painter.drawLine(0, 0, m_targetWidget->width(), 0);
|
||||||
|
painter.restore();
|
||||||
|
#else
|
||||||
|
Q_UNUSED(event);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WidgetsSharedHelper::shouldDrawFrameBorder() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
return (Utils::isWindowFrameBorderVisible() && !Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2)
|
||||||
|
&& (Utils::windowStatesToWindowState(m_targetWidget->windowState()) == Qt::WindowNoState));
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetsSharedHelper::updateContentsMargins()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
m_targetWidget->setContentsMargins(0, (shouldDrawFrameBorder() ? 1 : 0), 0, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -22,22 +22,42 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "systembutton.h"
|
#pragma once
|
||||||
|
|
||||||
SystemButton::SystemButton(QWidget *parent) : QPushButton(parent)
|
#include "framelesshelperwidgets_global.h"
|
||||||
|
#include <QtCore/qobject.h>
|
||||||
|
#include <QtCore/qpointer.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPaintEvent;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class FRAMELESSHELPER_WIDGETS_API WidgetsSharedHelper : public QObject
|
||||||
{
|
{
|
||||||
}
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY_MOVE(WidgetsSharedHelper)
|
||||||
|
|
||||||
SystemButton::~SystemButton() = default;
|
public:
|
||||||
|
explicit WidgetsSharedHelper(QObject *parent = nullptr);
|
||||||
|
~WidgetsSharedHelper() override;
|
||||||
|
|
||||||
void SystemButton::setHovered(const bool value)
|
void setup(QWidget *widget);
|
||||||
{
|
|
||||||
Q_UNUSED(value);
|
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemButton::setPressed(const bool value)
|
protected:
|
||||||
{
|
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
Q_UNUSED(value);
|
|
||||||
Q_UNIMPLEMENTED();
|
private Q_SLOTS:
|
||||||
}
|
void updateContentsMargins();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void changeEventHandler(QEvent *event);
|
||||||
|
void paintEventHandler(QPaintEvent *event);
|
||||||
|
Q_NODISCARD bool shouldDrawFrameBorder() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPointer<QWidget> m_targetWidget = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
FRAMELESSHELPER_END_NAMESPACE
|
Loading…
Reference in New Issue