forked from github_mirror/framelesshelper
parent
6a43ef39f8
commit
5ecc06df2f
|
@ -34,12 +34,6 @@ FramelessWindow {
|
|||
height: 600
|
||||
title: qsTr("Hello, World! - Qt Quick")
|
||||
color: FramelessUtils.darkModeEnabled ? FramelessUtils.defaultSystemDarkColor : FramelessUtils.defaultSystemLightColor
|
||||
Component.onCompleted: {
|
||||
FramelessHelper.setTitleBarItem(window, titleBar);
|
||||
FramelessHelper.setHitTestVisible(window, minimizeButton, true);
|
||||
FramelessHelper.setHitTestVisible(window, maximizeButton, true);
|
||||
FramelessHelper.setHitTestVisible(window, closeButton, true);
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 500
|
||||
|
@ -62,12 +56,12 @@ FramelessWindow {
|
|||
id: titleBar
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: window.windowTopBorder.height
|
||||
topMargin: 1
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
active: window.active
|
||||
maximized: (window.visibility === Window.Maximized) || (window.visibility === Window.FullScreen)
|
||||
maximized: window.zoomed
|
||||
title: window.title
|
||||
minimizeButton {
|
||||
id: minimizeButton
|
||||
|
@ -81,5 +75,11 @@ FramelessWindow {
|
|||
id: closeButton
|
||||
onClicked: window.close()
|
||||
}
|
||||
Component.onCompleted: {
|
||||
FramelessHelper.setTitleBarItem(window, titleBar);
|
||||
FramelessHelper.setHitTestVisible(window, minimizeButton, true);
|
||||
FramelessHelper.setHitTestVisible(window, maximizeButton, true);
|
||||
FramelessHelper.setHitTestVisible(window, closeButton, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,6 +118,8 @@ Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API)
|
|||
[[maybe_unused]] static const QString kForceHideFrameBorderKeyPath = QStringLiteral("Options/ForceHideFrameBorder");
|
||||
[[maybe_unused]] static const QString kForceShowFrameBorderKeyPath = QStringLiteral("Options/ForceShowFrameBorder");
|
||||
|
||||
[[maybe_unused]] static constexpr const QSize kInvalidWindowSize = {160, 160};
|
||||
|
||||
enum class Option : int
|
||||
{
|
||||
Default = 0x00000000, // Default placeholder, have no effect.
|
||||
|
@ -136,7 +138,8 @@ enum class Option : int
|
|||
NoDoubleClickMaximizeToggle = 0x00001000, // Don't toggle the maximize state when 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.
|
||||
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 shown.
|
||||
};
|
||||
Q_DECLARE_FLAGS(Options, Option)
|
||||
Q_FLAG_NS(Options)
|
||||
|
|
|
@ -79,6 +79,7 @@ FRAMELESSHELPER_CORE_API void startSystemResize(QWindow *window, const Qt::Edges
|
|||
(const SystemButtonType button, const SystemTheme theme, const ResourceType type);
|
||||
FRAMELESSHELPER_CORE_API void sendMouseReleaseEvent();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QWindow *findWindow(const WId winId);
|
||||
FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(QWindow *window, const bool considerTaskBar);
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin8OrGreater();
|
||||
|
|
|
@ -29,14 +29,26 @@
|
|||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
class FramelessQuickWindowPrivate;
|
||||
|
||||
class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(FramelessQuickWindow)
|
||||
Q_DISABLE_COPY_MOVE(FramelessQuickWindow)
|
||||
Q_PROPERTY(bool zoomed READ zoomed NOTIFY zoomedChanged FINAL)
|
||||
|
||||
public:
|
||||
explicit FramelessQuickWindow(QWindow *parent = nullptr);
|
||||
~FramelessQuickWindow() override;
|
||||
|
||||
Q_NODISCARD bool zoomed() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void zoomedChanged();
|
||||
|
||||
private:
|
||||
QScopedPointer<FramelessQuickWindowPrivate> d_ptr;
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -58,6 +58,15 @@ FramelessWindowsManagerPrivate *FramelessWindowsManagerPrivate::get(FramelessWin
|
|||
return manager->d_func();
|
||||
}
|
||||
|
||||
const FramelessWindowsManagerPrivate *FramelessWindowsManagerPrivate::get(const FramelessWindowsManager *manager)
|
||||
{
|
||||
Q_ASSERT(manager);
|
||||
if (!manager) {
|
||||
return nullptr;
|
||||
}
|
||||
return manager->d_func();
|
||||
}
|
||||
|
||||
bool FramelessWindowsManagerPrivate::usePureQtImplementation() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
@ -188,6 +197,7 @@ void FramelessWindowsManager::addWindow(QWindow *window)
|
|||
}
|
||||
#endif
|
||||
d->mutex.unlock();
|
||||
const auto options = qvariant_cast<Options>(window->property(kInternalOptionsFlag));
|
||||
if (pureQt) {
|
||||
FramelessHelperQt::addWindow(window);
|
||||
}
|
||||
|
@ -195,11 +205,13 @@ void FramelessWindowsManager::addWindow(QWindow *window)
|
|||
if (!pureQt) {
|
||||
FramelessHelperWin::addWindow(window);
|
||||
}
|
||||
const auto options = qvariant_cast<Options>(window->property(kInternalOptionsFlag));
|
||||
if (!(options & Option::DontInstallSystemMenuHook)) {
|
||||
Utils::installSystemMenuHook(window);
|
||||
}
|
||||
#endif
|
||||
if (!(options & Option::DontMoveWindowToDesktopCenter)) {
|
||||
Utils::moveWindowToDesktopCenter(window, true);
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessWindowsManager::removeWindow(QWindow *window)
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
~FramelessWindowsManagerPrivate();
|
||||
|
||||
[[nodiscard]] static FramelessWindowsManagerPrivate *get(FramelessWindowsManager *manager);
|
||||
[[nodiscard]] static const FramelessWindowsManagerPrivate *get(const FramelessWindowsManager *manager);
|
||||
|
||||
[[nodiscard]] bool usePureQtImplementation() const;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <QtCore/qvariant.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qscreen.h>
|
||||
|
||||
// The "Q_INIT_RESOURCE()" macro can't be used within a namespace,
|
||||
// so we wrap it into a separate function outside of the namespace and
|
||||
|
@ -171,4 +172,30 @@ QWindow *Utils::findWindow(const WId winId)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void Utils::moveWindowToDesktopCenter(QWindow *window, const bool considerTaskBar)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
const QSize windowSize = window->size();
|
||||
if (windowSize.isEmpty() || (windowSize == kInvalidWindowSize)) {
|
||||
return;
|
||||
}
|
||||
const QScreen * const screen = [window]() -> const QScreen * {
|
||||
const QScreen * const s = window->screen();
|
||||
return (s ? s : QGuiApplication::primaryScreen());
|
||||
}();
|
||||
Q_ASSERT(screen);
|
||||
if (!screen) {
|
||||
return;
|
||||
}
|
||||
const QSize screenSize = (considerTaskBar ? screen->availableSize() : screen->size());
|
||||
const QPoint offset = (considerTaskBar ? screen->availableGeometry().topLeft() : QPoint(0, 0));
|
||||
const auto newX = static_cast<int>(qRound(qreal(screenSize.width() - windowSize.width()) / 2.0));
|
||||
const auto newY = static_cast<int>(qRound(qreal(screenSize.height() - windowSize.height()) / 2.0));
|
||||
window->setX(newX + offset.x());
|
||||
window->setY(newY + offset.y());
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -10,6 +10,7 @@ set(SOURCES
|
|||
${INCLUDE_PREFIX}/framelessquickeventfilter.h
|
||||
${INCLUDE_PREFIX}/framelesshelper_quick.h
|
||||
${INCLUDE_PREFIX}/framelessquickwindow.h
|
||||
framelessquickwindow_p.h
|
||||
framelesshelperquick.qrc
|
||||
framelesshelper_quick.cpp
|
||||
framelessquickhelper.cpp
|
||||
|
|
|
@ -23,11 +23,78 @@
|
|||
*/
|
||||
|
||||
#include "framelessquickwindow.h"
|
||||
#include "framelessquickwindow_p.h"
|
||||
#include <QtQuick/private/qquickitem_p.h>
|
||||
#include <QtQuick/private/qquickrectangle_p.h>
|
||||
#include <QtQuick/private/qquickanchors_p.h>
|
||||
#include <framelesswindowsmanager.h>
|
||||
#include <utils.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent) : QQuickWindow(parent) {}
|
||||
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q) : QObject(q)
|
||||
{
|
||||
Q_ASSERT(q);
|
||||
if (!q) {
|
||||
return;
|
||||
}
|
||||
q_ptr = q;
|
||||
initialize();
|
||||
}
|
||||
|
||||
FramelessQuickWindowPrivate::~FramelessQuickWindowPrivate() = default;
|
||||
|
||||
bool FramelessQuickWindowPrivate::isZoomed() const
|
||||
{
|
||||
Q_Q(const FramelessQuickWindow);
|
||||
const FramelessQuickWindow::Visibility visibility = q->visibility();
|
||||
return ((visibility == FramelessQuickWindow::Maximized) || (visibility == FramelessQuickWindow::FullScreen));
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::initialize()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
FramelessWindowsManager * const manager = FramelessWindowsManager::instance();
|
||||
manager->addWindow(q);
|
||||
QQuickItem * const rootItem = q->contentItem();
|
||||
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||
updateTopBorderHeight();
|
||||
updateTopBorderColor();
|
||||
connect(q, &FramelessQuickWindow::visibilityChanged, this, &FramelessQuickWindowPrivate::updateTopBorderHeight);
|
||||
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||
const auto topBorderAnchors = new QQuickAnchors(m_topBorderRectangle.data(), m_topBorderRectangle.data());
|
||||
topBorderAnchors->setTop(rootItemPrivate->top());
|
||||
topBorderAnchors->setLeft(rootItemPrivate->left());
|
||||
topBorderAnchors->setRight(rootItemPrivate->right());
|
||||
connect(q, &FramelessQuickWindow::visibilityChanged, q, &FramelessQuickWindow::zoomedChanged);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::updateTopBorderColor()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
m_topBorderRectangle->setColor(Utils::getFrameBorderColor(q->isActive()));
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::updateTopBorderHeight()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
const qreal newHeight = ((q->visibility() == FramelessQuickWindow::Windowed) ? 1.0 : 0.0);
|
||||
m_topBorderRectangle->setHeight(newHeight);
|
||||
}
|
||||
|
||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent) : QQuickWindow(parent)
|
||||
{
|
||||
d_ptr.reset(new FramelessQuickWindowPrivate(this));
|
||||
}
|
||||
|
||||
FramelessQuickWindow::~FramelessQuickWindow() = default;
|
||||
|
||||
bool FramelessQuickWindow::zoomed() const
|
||||
{
|
||||
Q_D(const FramelessQuickWindow);
|
||||
return d->isZoomed();
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framelesshelperquick_global.h"
|
||||
#include <QtCore/qobject.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QQuickRectangle;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
class FramelessQuickWindow;
|
||||
|
||||
class FRAMELESSHELPER_QUICK_API FramelessQuickWindowPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PUBLIC(FramelessQuickWindow)
|
||||
Q_DISABLE_COPY_MOVE(FramelessQuickWindowPrivate)
|
||||
|
||||
public:
|
||||
explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q);
|
||||
~FramelessQuickWindowPrivate() override;
|
||||
|
||||
Q_NODISCARD bool isZoomed() const;
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateTopBorderColor();
|
||||
void updateTopBorderHeight();
|
||||
|
||||
private:
|
||||
FramelessQuickWindow *q_ptr = nullptr;
|
||||
QScopedPointer<QQuickRectangle> m_topBorderRectangle;
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
static constexpr const char QT_MAINWINDOW_CLASS_NAME[] = "QMainWindow";
|
||||
|
||||
static const QString kSystemButtonStyleSheet = QStringLiteral(R"(
|
||||
QPushButton {
|
||||
border-style: none;
|
||||
|
@ -54,11 +56,12 @@ QPushButton:pressed {
|
|||
FramelessWidgetsHelper::FramelessWidgetsHelper(QWidget *q, const Options options) : QObject(q)
|
||||
{
|
||||
Q_ASSERT(q);
|
||||
if (q) {
|
||||
if (!q) {
|
||||
return;
|
||||
}
|
||||
this->q = q;
|
||||
m_options = options;
|
||||
initialize();
|
||||
}
|
||||
}
|
||||
|
||||
FramelessWidgetsHelper::~FramelessWidgetsHelper() = default;
|
||||
|
@ -299,7 +302,7 @@ void FramelessWidgetsHelper::initialize()
|
|||
}
|
||||
window->setProperty(kInternalOptionsFlag, QVariant::fromValue(m_options));
|
||||
if (m_options & Option::UseStandardWindowLayout) {
|
||||
if (q->inherits("QMainWindow")) {
|
||||
if (q->inherits(QT_MAINWINDOW_CLASS_NAME)) {
|
||||
m_options &= ~Options(Option::UseStandardWindowLayout);
|
||||
qWarning() << "\"Option::UseStandardWindowLayout\" is not compatible with QMainWindow and it's subclasses."
|
||||
" Enabling this option will mess up with your main window's layout.";
|
||||
|
@ -310,7 +313,7 @@ void FramelessWidgetsHelper::initialize()
|
|||
Q_ASSERT(window->flags() & Qt::FramelessWindowHint);
|
||||
}
|
||||
FramelessWindowsManager *manager = FramelessWindowsManager::instance();
|
||||
manager->addWindow(q->windowHandle());
|
||||
manager->addWindow(window);
|
||||
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this](){
|
||||
if (m_options & Option::UseStandardWindowLayout) {
|
||||
updateSystemTitleBarStyleSheet();
|
||||
|
|
Loading…
Reference in New Issue