improve windowborder element

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-10-10 22:12:01 +08:00
parent 1fc23e1c6a
commit 1e43ba2e81
14 changed files with 175 additions and 146 deletions

View File

@ -0,0 +1 @@
#include <framelessquickwindow.h>

View File

@ -0,0 +1,85 @@
/*
* 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 <QtQml/qqmlparserstatus.h>
#include <QtQuick/qquickwindow.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
class FramelessQuickWindowPrivate;
class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow, public QQmlParserStatus
{
Q_OBJECT
#ifdef QML_NAMED_ELEMENT
QML_NAMED_ELEMENT(FramelessWindow)
#endif
Q_DECLARE_PRIVATE(FramelessQuickWindow)
Q_DISABLE_COPY_MOVE(FramelessQuickWindow)
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL)
Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL)
Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL)
Q_PROPERTY(bool maximized READ isMaximized NOTIFY maximizedChanged FINAL)
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL)
public:
explicit FramelessQuickWindow(QWindow *parent = nullptr);
~FramelessQuickWindow() override;
Q_NODISCARD bool isHidden() const;
Q_NODISCARD bool isNormal() const;
Q_NODISCARD bool isMinimized() const;
Q_NODISCARD bool isMaximized() const;
Q_NODISCARD bool isZoomed() const;
Q_NODISCARD bool isFullScreen() const;
public Q_SLOTS:
void showMinimized2();
void toggleMaximized();
void toggleFullScreen();
protected:
void classBegin() override;
void componentComplete() override;
Q_SIGNALS:
void hiddenChanged();
void normalChanged();
void minimizedChanged();
void maximizedChanged();
void zoomedChanged();
void fullScreenChanged();
private:
QScopedPointer<FramelessQuickWindowPrivate> d_ptr;
};
FRAMELESSHELPER_END_NAMESPACE
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow))
QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow))

View File

@ -25,61 +25,46 @@
#pragma once
#include "framelesshelperquick_global.h"
#include <QtQml/qqmlparserstatus.h>
#include <QtQuick/qquickwindow.h>
#include "framelessquickwindow.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
class FramelessQuickWindowPrivate;
class QuickWindowBorder;
class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow, public QQmlParserStatus
class FRAMELESSHELPER_QUICK_API FramelessQuickWindowPrivate : public QObject
{
Q_OBJECT
#ifdef QML_NAMED_ELEMENT
QML_NAMED_ELEMENT(FramelessWindow)
#endif
Q_DECLARE_PRIVATE(FramelessQuickWindow)
Q_DISABLE_COPY_MOVE(FramelessQuickWindow)
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged FINAL)
Q_PROPERTY(bool normal READ isNormal NOTIFY normalChanged FINAL)
Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged FINAL)
Q_PROPERTY(bool maximized READ isMaximized NOTIFY maximizedChanged FINAL)
Q_PROPERTY(bool zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL)
Q_DECLARE_PUBLIC(FramelessQuickWindow)
Q_DISABLE_COPY_MOVE(FramelessQuickWindowPrivate)
public:
explicit FramelessQuickWindow(QWindow *parent = nullptr);
~FramelessQuickWindow() override;
explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q);
~FramelessQuickWindowPrivate() override;
Q_NODISCARD bool isHidden() const;
Q_NODISCARD bool isNormal() const;
Q_NODISCARD bool isMinimized() const;
Q_NODISCARD bool isMaximized() const;
Q_NODISCARD bool isZoomed() const;
Q_NODISCARD bool isFullScreen() const;
Q_NODISCARD static FramelessQuickWindowPrivate *get(FramelessQuickWindow *pub);
Q_NODISCARD static const FramelessQuickWindowPrivate *get(const FramelessQuickWindow *pub);
Q_INVOKABLE Q_NODISCARD bool isHidden() const;
Q_INVOKABLE Q_NODISCARD bool isNormal() const;
Q_INVOKABLE Q_NODISCARD bool isMinimized() const;
Q_INVOKABLE Q_NODISCARD bool isMaximized() const;
Q_INVOKABLE Q_NODISCARD bool isZoomed() const;
Q_INVOKABLE Q_NODISCARD bool isFullScreen() const;
public Q_SLOTS:
void showMinimized2();
void toggleMaximized();
void toggleFullScreen();
protected:
void classBegin() override;
void componentComplete() override;
Q_SIGNALS:
void hiddenChanged();
void normalChanged();
void minimizedChanged();
void maximizedChanged();
void zoomedChanged();
void fullScreenChanged();
private:
void initialize();
private:
QScopedPointer<FramelessQuickWindowPrivate> d_ptr;
QPointer<FramelessQuickWindow> q_ptr = nullptr;
QScopedPointer<QuickWindowBorder> m_windowBorder;
QQuickWindow::Visibility m_savedVisibility = QQuickWindow::Windowed;
};
FRAMELESSHELPER_END_NAMESPACE
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow))
QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow))
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindowPrivate))

View File

@ -1,74 +0,0 @@
/*
* 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 "framelessquickwindow_p.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
class QuickWindowBorder;
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 static FramelessQuickWindowPrivate *get(FramelessQuickWindow *pub);
Q_NODISCARD static const FramelessQuickWindowPrivate *get(const FramelessQuickWindow *pub);
Q_INVOKABLE Q_NODISCARD bool isHidden() const;
Q_INVOKABLE Q_NODISCARD bool isNormal() const;
Q_INVOKABLE Q_NODISCARD bool isMinimized() const;
Q_INVOKABLE Q_NODISCARD bool isMaximized() const;
Q_INVOKABLE Q_NODISCARD bool isZoomed() const;
Q_INVOKABLE Q_NODISCARD bool isFullScreen() const;
public Q_SLOTS:
void showMinimized2();
void toggleMaximized();
void toggleFullScreen();
private:
void initialize();
Q_NODISCARD bool shouldDrawFrameBorder() const;
private Q_SLOTS:
void updateWindowBorderVisibility();
private:
QPointer<FramelessQuickWindow> q_ptr = nullptr;
QScopedPointer<QuickWindowBorder> m_windowBorder;
QQuickWindow::Visibility m_savedVisibility = QQuickWindow::Windowed;
};
FRAMELESSHELPER_END_NAMESPACE
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindowPrivate))

View File

@ -46,12 +46,18 @@ public:
void paint(QPainter *painter) const;
public Q_SLOTS:
void update();
private:
void initialize();
void rebindWindow();
private:
QPointer<QuickWindowBorder> q_ptr = nullptr;
QScopedPointer<WindowBorderPainter> m_borderPainter;
QMetaObject::Connection m_activeChangeConnection = {};
QMetaObject::Connection m_visibilityChangeConnection = {};
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -75,6 +75,7 @@ public Q_SLOTS:
void setInactiveColor(const QColor &value);
protected:
void itemChange(const ItemChange change, const ItemChangeData &value) override;
void classBegin() override;
void componentComplete() override;

View File

@ -27,11 +27,11 @@ HEADERS += \
$$QUICK_PUB_INC_DIR/quickmicamaterial.h \
$$QUICK_PUB_INC_DIR/quickimageitem.h \
$$QUICK_PUB_INC_DIR/quickwindowborder.h \
$$QUICK_PUB_INC_DIR/framelessquickwindow.h \
$$QUICK_PRIV_INC_DIR/quickstandardsystembutton_p.h \
$$QUICK_PRIV_INC_DIR/quickstandardtitlebar_p.h \
$$QUICK_PRIV_INC_DIR/framelessquickhelper_p.h \
$$QUICK_PRIV_INC_DIR/framelessquickwindow_p.h \
$$QUICK_PRIV_INC_DIR/framelessquickwindow_p_p.h \
$$QUICK_PRIV_INC_DIR/quickmicamaterial_p.h \
$$QUICK_PRIV_INC_DIR/quickimageitem_p.h \
$$QUICK_PRIV_INC_DIR/quickwindowborder_p.h

View File

@ -963,8 +963,15 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
const bool isFixedSize = data.params.isWindowFixedSize();
const bool dontOverrideCursor = data.params.getProperty(kDontOverrideCursorVar, false).toBool();
const bool dontToggleMaximize = data.params.getProperty(kDontToggleMaximizeVar, false).toBool();
// To disable window maximization, you should remove the WS_MAXIMIZEBOX style from the window instead.
Q_UNUSED(dontToggleMaximize);
if (dontToggleMaximize) {
static bool once = false;
if (!once) {
once = true;
DEBUG << "To disable window maximization, you should remove the "
"WS_MAXIMIZEBOX style from the window instead. FramelessHelper "
"won't do that for you, so you'll have to do it manually yourself.";
}
}
if (frameBorderVisible) {
// This will handle the left, right and bottom parts of the frame
// because we didn't change them.

View File

@ -40,6 +40,7 @@ set(PUBLIC_HEADERS
${INCLUDE_PREFIX}/quickmicamaterial.h
${INCLUDE_PREFIX}/quickimageitem.h
${INCLUDE_PREFIX}/quickwindowborder.h
${INCLUDE_PREFIX}/framelessquickwindow.h
)
set(PUBLIC_HEADERS_ALIAS
@ -51,6 +52,7 @@ set(PUBLIC_HEADERS_ALIAS
${INCLUDE_PREFIX}/QuickMicaMaterial
${INCLUDE_PREFIX}/QuickImageItem
${INCLUDE_PREFIX}/QuickWindowBorder
${INCLUDE_PREFIX}/FramelessQuickWindow
)
set(PRIVATE_HEADERS
@ -58,7 +60,6 @@ set(PRIVATE_HEADERS
${INCLUDE_PREFIX}/private/quickstandardtitlebar_p.h
${INCLUDE_PREFIX}/private/framelessquickhelper_p.h
${INCLUDE_PREFIX}/private/framelessquickwindow_p.h
${INCLUDE_PREFIX}/private/framelessquickwindow_p_p.h
${INCLUDE_PREFIX}/private/quickmicamaterial_p.h
${INCLUDE_PREFIX}/private/quickimageitem_p.h
${INCLUDE_PREFIX}/private/quickwindowborder_p.h

View File

@ -30,8 +30,8 @@
# include "quickchromepalette.h"
# include "quickstandardsystembutton_p.h"
# include "quickstandardtitlebar_p.h"
# include "framelessquickwindow.h"
# include "framelessquickwindow_p.h"
# include "framelessquickwindow_p_p.h"
# include "quickmicamaterial.h"
# include "quickmicamaterial_p.h"
# include "quickimageitem.h"

View File

@ -29,7 +29,7 @@
#include "quickmicamaterial.h"
#include "quickimageitem.h"
#include "quickwindowborder.h"
#include "framelessquickwindow_p.h"
#include "framelessquickwindow.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
# include "quickstandardsystembutton_p.h"
# include "quickstandardtitlebar_p.h"

View File

@ -22,16 +22,12 @@
* SOFTWARE.
*/
#include "framelessquickwindow.h"
#include "framelessquickwindow_p.h"
#include "framelessquickwindow_p_p.h"
#include "framelessquickhelper.h"
#include "quickwindowborder.h"
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickanchors_p.h>
#include <utils.h>
#ifdef Q_OS_WINDOWS
# include <winverhelper_p.h>
#endif
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -154,8 +150,7 @@ void FramelessQuickWindowPrivate::initialize()
m_windowBorder->setParentItem(rootItem);
m_windowBorder->setZ(999); // Make sure it always stays on the top.
QQuickItemPrivate::get(m_windowBorder.data())->anchors()->setFill(rootItem);
connect(q, &FramelessQuickWindow::visibilityChanged, this, [this, q](){
updateWindowBorderVisibility();
connect(q, &FramelessQuickWindow::visibilityChanged, q, [q](){
Q_EMIT q->hiddenChanged();
Q_EMIT q->normalChanged();
Q_EMIT q->minimizedChanged();
@ -163,27 +158,6 @@ void FramelessQuickWindowPrivate::initialize()
Q_EMIT q->zoomedChanged();
Q_EMIT q->fullScreenChanged();
});
connect(q, &FramelessQuickWindow::activeChanged,
m_windowBorder.data(), [this](){ m_windowBorder->update(); });
updateWindowBorderVisibility();
}
bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const
{
#ifdef Q_OS_WINDOWS
return (Utils::isWindowFrameBorderVisible()
&& !WindowsVersionHelper::isWin11OrGreater() && isNormal());
#else
return false;
#endif
}
void FramelessQuickWindowPrivate::updateWindowBorderVisibility()
{
if (m_windowBorder.isNull()) {
return;
}
m_windowBorder->setVisible(shouldDrawFrameBorder());
}
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent)

View File

@ -181,10 +181,11 @@ void QuickMicaMaterialPrivate::initialize()
void QuickMicaMaterialPrivate::rebindWindow()
{
Q_Q(QuickMicaMaterial);
QQuickWindow * const window = q->window();
const QQuickWindow * const window = q->window();
if (!window) {
return;
}
q->setZ(-999); // Make sure we always stays on the bottom most place.
if (m_rootWindowXChangedConnection) {
disconnect(m_rootWindowXChangedConnection);
m_rootWindowXChangedConnection = {};

View File

@ -118,6 +118,17 @@ void QuickWindowBorderPrivate::paint(QPainter *painter) const
m_borderPainter->paint(painter, size, (q->window() && q->window()->isActive()));
}
void QuickWindowBorderPrivate::update()
{
Q_Q(QuickWindowBorder);
const QQuickWindow * const window = q->window();
if (!window) {
return;
}
q->update();
q->setVisible(window->visibility() == QQuickWindow::Windowed);
}
void QuickWindowBorderPrivate::initialize()
{
Q_Q(QuickWindowBorder);
@ -141,6 +152,28 @@ void QuickWindowBorderPrivate::initialize()
connect(m_borderPainter.data(), &WindowBorderPainter::shouldRepaint, q, [q](){ q->update(); });
}
void QuickWindowBorderPrivate::rebindWindow()
{
Q_Q(QuickWindowBorder);
const QQuickWindow * const window = q->window();
if (!window) {
return;
}
q->setZ(999); // Make sure we always stays on the top most place.
if (m_activeChangeConnection) {
disconnect(m_activeChangeConnection);
m_activeChangeConnection = {};
}
if (m_visibilityChangeConnection) {
disconnect(m_visibilityChangeConnection);
m_visibilityChangeConnection = {};
}
m_activeChangeConnection = connect(window, &QQuickWindow::activeChanged,
this, &QuickWindowBorderPrivate::update);
m_visibilityChangeConnection = connect(window, &QQuickWindow::visibilityChanged,
this, &QuickWindowBorderPrivate::update);
}
QuickWindowBorder::QuickWindowBorder(QQuickItem *parent)
: QQuickPaintedItem(parent), d_ptr(new QuickWindowBorderPrivate(this))
{
@ -252,6 +285,15 @@ void QuickWindowBorder::setInactiveColor(const QColor &value)
d->m_borderPainter->setInactiveColor(value);
}
void QuickWindowBorder::itemChange(const ItemChange change, const ItemChangeData &value)
{
QQuickPaintedItem::itemChange(change, value);
if ((change == ItemSceneChange) && value.window) {
Q_D(QuickWindowBorder);
d->rebindWindow();
}
}
void QuickWindowBorder::classBegin()
{
QQuickPaintedItem::classBegin();