forked from github_mirror/framelesshelper
win implementation is mostly settled now
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
389a342a81
commit
d4e711d679
|
@ -45,7 +45,6 @@ int main(int argc, char *argv[])
|
||||||
QApplication application(argc, argv);
|
QApplication application(argc, argv);
|
||||||
|
|
||||||
MainWindow mainWindow;
|
MainWindow mainWindow;
|
||||||
mainWindow.moveToDesktopCenter();
|
|
||||||
mainWindow.show();
|
mainWindow.show();
|
||||||
|
|
||||||
return QCoreApplication::exec();
|
return QCoreApplication::exec();
|
||||||
|
|
|
@ -29,14 +29,11 @@ import org.wangwenx190.FramelessHelper 1.0
|
||||||
|
|
||||||
FramelessWindow {
|
FramelessWindow {
|
||||||
id: window
|
id: window
|
||||||
|
visible: true
|
||||||
width: 800
|
width: 800
|
||||||
height: 600
|
height: 600
|
||||||
title: qsTr("Hello, World! - Qt Quick")
|
title: qsTr("Hello, World! - Qt Quick")
|
||||||
color: FramelessUtils.darkModeEnabled ? FramelessUtils.defaultSystemDarkColor : FramelessUtils.defaultSystemLightColor
|
color: FramelessUtils.darkModeEnabled ? FramelessUtils.defaultSystemDarkColor : FramelessUtils.defaultSystemLightColor
|
||||||
Component.onCompleted: {
|
|
||||||
window.moveToDesktopCenter();
|
|
||||||
window.visible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
interval: 500
|
interval: 500
|
||||||
|
|
|
@ -45,7 +45,6 @@ int main(int argc, char *argv[])
|
||||||
QApplication application(argc, argv);
|
QApplication application(argc, argv);
|
||||||
|
|
||||||
Widget widget;
|
Widget widget;
|
||||||
widget.moveToDesktopCenter();
|
|
||||||
widget.show();
|
widget.show();
|
||||||
|
|
||||||
return QCoreApplication::exec();
|
return QCoreApplication::exec();
|
||||||
|
|
|
@ -32,7 +32,19 @@ FRAMELESSHELPER_USE_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
Widget::Widget(QWidget *parent) : FramelessWidget(parent, {Option::UseStandardWindowLayout})
|
static const UserSettings settings =
|
||||||
|
{
|
||||||
|
/* startupPosition */ QPoint(),
|
||||||
|
/* startupSize */ QSize(),
|
||||||
|
/* startupState */ Qt::WindowNoState,
|
||||||
|
/* options */ { Option::UseStandardWindowLayout },
|
||||||
|
/* systemMenuOffset */ QPoint(),
|
||||||
|
/* minimizeButton */ nullptr,
|
||||||
|
/* maximizeButton */ nullptr,
|
||||||
|
/* closeButton */ nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
Widget::Widget(QWidget *parent) : FramelessWidget(parent, settings)
|
||||||
{
|
{
|
||||||
setupUi();
|
setupUi();
|
||||||
startTimer(500);
|
startTimer(500);
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
explicit FramelessHelperQt(QObject *parent = nullptr);
|
explicit FramelessHelperQt(QObject *parent = nullptr);
|
||||||
~FramelessHelperQt() override;
|
~FramelessHelperQt() override;
|
||||||
|
|
||||||
static void addWindow(const Global::FramelessHelperParams ¶ms);
|
static void addWindow(const Global::UserSettings &settings, 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::FramelessHelperParams ¶ms);
|
static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms);
|
||||||
|
|
||||||
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, NATIVE_EVENT_RESULT_TYPE *result) override;
|
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <QtCore/qobject.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 <QtGui/qcolor.h>
|
#include <QtGui/qcolor.h>
|
||||||
#include <QtGui/qwindowdefs.h>
|
#include <QtGui/qwindowdefs.h>
|
||||||
|
|
||||||
|
@ -181,10 +182,11 @@ enum class SystemButtonType : int
|
||||||
{
|
{
|
||||||
Unknown = -1,
|
Unknown = -1,
|
||||||
WindowIcon = 0,
|
WindowIcon = 0,
|
||||||
Minimize = 1,
|
Help = 1,
|
||||||
Maximize = 2,
|
Minimize = 2,
|
||||||
Restore = 3,
|
Maximize = 3,
|
||||||
Close = 4
|
Restore = 4,
|
||||||
|
Close = 5
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(SystemButtonType)
|
Q_ENUM_NS(SystemButtonType)
|
||||||
|
|
||||||
|
@ -224,30 +226,65 @@ using SetWindowStateCallback = std::function<void(const Qt::WindowState)>;
|
||||||
|
|
||||||
using GetWindowHandleCallback = std::function<QWindow *()>;
|
using GetWindowHandleCallback = std::function<QWindow *()>;
|
||||||
|
|
||||||
struct FramelessHelperParams
|
using WindowToScreenCallback = std::function<QPoint(const QPoint &)>;
|
||||||
|
using ScreenToWindowCallback = std::function<QPoint(const QPoint &)>;
|
||||||
|
|
||||||
|
using IsInsideSystemButtonsCallback = std::function<bool(const QPoint &, SystemButtonType *)>;
|
||||||
|
using IsInsideTitleBarDraggableAreaCallback = std::function<bool(const QPoint &)>;
|
||||||
|
|
||||||
|
using GetWindowDevicePixelRatioCallback = std::function<qreal()>;
|
||||||
|
|
||||||
|
struct UserSettings
|
||||||
{
|
{
|
||||||
WId windowId = 0;
|
QPoint startupPosition = {};
|
||||||
|
QSize startupSize = {};
|
||||||
|
Qt::WindowState startupState = Qt::WindowNoState;
|
||||||
Options options = {};
|
Options options = {};
|
||||||
QPoint systemMenuOffset = {};
|
QPoint systemMenuOffset = {};
|
||||||
|
QPointer<QObject> minimizeButton = nullptr;
|
||||||
|
QPointer<QObject> maximizeButton = nullptr;
|
||||||
|
QPointer<QObject> closeButton = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SystemParameters
|
||||||
|
{
|
||||||
|
WId windowId = 0;
|
||||||
|
|
||||||
GetWindowFlagsCallback getWindowFlags = nullptr;
|
GetWindowFlagsCallback getWindowFlags = nullptr;
|
||||||
SetWindowFlagsCallback setWindowFlags = nullptr;
|
SetWindowFlagsCallback setWindowFlags = nullptr;
|
||||||
|
|
||||||
GetWindowSizeCallback getWindowSize = nullptr;
|
GetWindowSizeCallback getWindowSize = nullptr;
|
||||||
SetWindowSizeCallback setWindowSize = nullptr;
|
SetWindowSizeCallback setWindowSize = nullptr;
|
||||||
|
|
||||||
GetWindowPositionCallback getWindowPosition = nullptr;
|
GetWindowPositionCallback getWindowPosition = nullptr;
|
||||||
SetWindowPositionCallback setWindowPosition = nullptr;
|
SetWindowPositionCallback setWindowPosition = nullptr;
|
||||||
|
|
||||||
GetWindowScreenCallback getWindowScreen = nullptr;
|
GetWindowScreenCallback getWindowScreen = nullptr;
|
||||||
|
|
||||||
IsWindowFixedSizeCallback isWindowFixedSize = nullptr;
|
IsWindowFixedSizeCallback isWindowFixedSize = nullptr;
|
||||||
SetWindowFixedSizeCallback setWindowFixedSize = nullptr;
|
SetWindowFixedSizeCallback setWindowFixedSize = nullptr;
|
||||||
|
|
||||||
GetWindowStateCallback getWindowState = nullptr;
|
GetWindowStateCallback getWindowState = nullptr;
|
||||||
SetWindowStateCallback setWindowState = nullptr;
|
SetWindowStateCallback setWindowState = nullptr;
|
||||||
|
|
||||||
GetWindowHandleCallback getWindowHandle = nullptr;
|
GetWindowHandleCallback getWindowHandle = nullptr;
|
||||||
|
|
||||||
|
WindowToScreenCallback windowToScreen = nullptr;
|
||||||
|
ScreenToWindowCallback screenToWindow = nullptr;
|
||||||
|
|
||||||
|
IsInsideSystemButtonsCallback isInsideSystemButtons = nullptr;
|
||||||
|
IsInsideTitleBarDraggableAreaCallback isInsideTitleBarDraggableArea = nullptr;
|
||||||
|
|
||||||
|
GetWindowDevicePixelRatioCallback getWindowDevicePixelRatio = nullptr;
|
||||||
|
|
||||||
[[nodiscard]] inline bool isValid() const
|
[[nodiscard]] inline bool isValid() const
|
||||||
{
|
{
|
||||||
return (windowId && getWindowFlags && setWindowFlags && getWindowSize
|
return (windowId && getWindowFlags && setWindowFlags && getWindowSize
|
||||||
&& setWindowSize && getWindowPosition && setWindowPosition
|
&& setWindowSize && getWindowPosition && setWindowPosition
|
||||||
&& isWindowFixedSize && setWindowFixedSize && getWindowState
|
&& isWindowFixedSize && setWindowFixedSize && getWindowState
|
||||||
&& setWindowState && getWindowHandle);
|
&& setWindowState && getWindowHandle && windowToScreen && screenToWindow
|
||||||
|
&& isInsideSystemButtons && isInsideTitleBarDraggableArea
|
||||||
|
&& getWindowDevicePixelRatio);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,4 +292,5 @@ struct FramelessHelperParams
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global::FramelessHelperParams))
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global::UserSettings))
|
||||||
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global::SystemParameters))
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
Q_NODISCARD static Global::SystemTheme systemTheme();
|
Q_NODISCARD static Global::SystemTheme systemTheme();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
static void addWindow(const Global::FramelessHelperParams ¶ms);
|
static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters ¶ms);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void systemThemeChanged();
|
void systemThemeChanged();
|
||||||
|
|
|
@ -43,7 +43,7 @@ getSystemButtonIconResource(const Global::SystemButtonType button,
|
||||||
const Global::SystemTheme theme,
|
const Global::SystemTheme theme,
|
||||||
const Global::ResourceType type);
|
const Global::ResourceType type);
|
||||||
FRAMELESSHELPER_CORE_API void sendMouseReleaseEvent();
|
FRAMELESSHELPER_CORE_API void sendMouseReleaseEvent();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QWindow *findWindow(const WId winId);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QWindow *findWindow(const WId windowId);
|
||||||
FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(
|
FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(
|
||||||
const Global::GetWindowScreenCallback &getWindowScreen,
|
const Global::GetWindowScreenCallback &getWindowScreen,
|
||||||
const Global::GetWindowSizeCallback &getWindowSize,
|
const Global::GetWindowSizeCallback &getWindowSize,
|
||||||
|
@ -60,15 +60,15 @@ FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin101809OrGreater();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin101809OrGreater();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin11OrGreater();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin11OrGreater();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isDwmCompositionEnabled();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isDwmCompositionEnabled();
|
||||||
FRAMELESSHELPER_CORE_API void triggerFrameChange(const WId winId);
|
FRAMELESSHELPER_CORE_API void triggerFrameChange(const WId windowId);
|
||||||
FRAMELESSHELPER_CORE_API void updateWindowFrameMargins(const WId winId, const bool reset);
|
FRAMELESSHELPER_CORE_API void updateWindowFrameMargins(const WId windowId, const bool reset);
|
||||||
FRAMELESSHELPER_CORE_API void updateInternalWindowFrameMargins(QWindow *window, const bool enable);
|
FRAMELESSHELPER_CORE_API void updateInternalWindowFrameMargins(QWindow *window, const bool enable);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QString getSystemErrorMessage(const QString &function);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QString getSystemErrorMessage(const QString &function);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFullScreen(const WId winId);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFullScreen(const WId windowId);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowNoState(const WId winId);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowNoState(const WId windowId);
|
||||||
FRAMELESSHELPER_CORE_API void syncWmPaintWithDwm();
|
FRAMELESSHELPER_CORE_API void syncWmPaintWithDwm();
|
||||||
FRAMELESSHELPER_CORE_API void showSystemMenu(
|
FRAMELESSHELPER_CORE_API void showSystemMenu(
|
||||||
const WId winId,
|
const WId windowId,
|
||||||
const QPoint &pos,
|
const QPoint &pos,
|
||||||
const Global::Options options,
|
const Global::Options options,
|
||||||
const QPoint &offset,
|
const QPoint &offset,
|
||||||
|
@ -78,32 +78,32 @@ FRAMELESSHELPER_CORE_API void showSystemMenu(
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::DwmColorizationArea getDwmColorizationArea();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::DwmColorizationArea getDwmColorizationArea();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isHighContrastModeEnabled();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isHighContrastModeEnabled();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getPrimaryScreenDpi(const bool horizontal);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getPrimaryScreenDpi(const bool horizontal);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getWindowDpi(const WId winId, const bool horizontal);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getWindowDpi(const WId windowId, const bool horizontal);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThickness(const WId winId,
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThickness(const WId windowId,
|
||||||
const bool horizontal,
|
const bool horizontal,
|
||||||
const bool scaled);
|
const bool scaled);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionHeight(const WId winId, const bool scaled);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionHeight(const WId windowId, const bool scaled);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeight(const WId winId, const bool scaled);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeight(const WId windowId, const bool scaled);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId winId,
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId windowId,
|
||||||
const bool scaled);
|
const bool scaled);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getFrameBorderColor(const bool active);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getFrameBorderColor(const bool active);
|
||||||
FRAMELESSHELPER_CORE_API void updateWindowFrameBorderColor(const WId winId, const bool dark);
|
FRAMELESSHELPER_CORE_API void updateWindowFrameBorderColor(const WId windowId, const bool dark);
|
||||||
FRAMELESSHELPER_CORE_API void fixupQtInternals(const WId winId);
|
FRAMELESSHELPER_CORE_API void fixupQtInternals(const WId windowId);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized();
|
||||||
FRAMELESSHELPER_CORE_API void installSystemMenuHook(
|
FRAMELESSHELPER_CORE_API void installSystemMenuHook(
|
||||||
const WId winId,
|
const WId windowId,
|
||||||
const Global::Options options,
|
const Global::Options options,
|
||||||
const QPoint &offset,
|
const QPoint &offset,
|
||||||
const Global::IsWindowFixedSizeCallback &isWindowFixedSize);
|
const Global::IsWindowFixedSizeCallback &isWindowFixedSize);
|
||||||
FRAMELESSHELPER_CORE_API void uninstallSystemMenuHook(const WId winId);
|
FRAMELESSHELPER_CORE_API void uninstallSystemMenuHook(const WId windowId);
|
||||||
FRAMELESSHELPER_CORE_API void tryToBeCompatibleWithQtFramelessWindowHint(
|
FRAMELESSHELPER_CORE_API void tryToBeCompatibleWithQtFramelessWindowHint(
|
||||||
const WId winId,
|
const WId windowId,
|
||||||
const Global::GetWindowFlagsCallback &getWindowFlags,
|
const Global::GetWindowFlagsCallback &getWindowFlags,
|
||||||
const Global::SetWindowFlagsCallback &setWindowFlags,
|
const Global::SetWindowFlagsCallback &setWindowFlags,
|
||||||
const bool enable);
|
const bool enable);
|
||||||
FRAMELESSHELPER_CORE_API void setAeroSnappingEnabled(const WId winId, const bool enable);
|
FRAMELESSHELPER_CORE_API void setAeroSnappingEnabled(const WId windowId, const bool enable);
|
||||||
FRAMELESSHELPER_CORE_API void tryToEnableHighestDpiAwarenessLevel();
|
FRAMELESSHELPER_CORE_API void tryToEnableHighestDpiAwarenessLevel();
|
||||||
#endif // Q_OS_WINDOWS
|
#endif // Q_OS_WINDOWS
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <framelessquickeventfilter.h>
|
|
|
@ -1,54 +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 <QtCore/qobject.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QQuickWindow;
|
|
||||||
class QQuickItem;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class FRAMELESSHELPER_QUICK_API FramelessQuickEventFilter : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_DISABLE_COPY_MOVE(FramelessQuickEventFilter)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FramelessQuickEventFilter(QObject *parent = nullptr);
|
|
||||||
~FramelessQuickEventFilter() override;
|
|
||||||
|
|
||||||
static void addWindow(const Global::FramelessHelperParams ¶ms);
|
|
||||||
static void setTitleBarItem(QQuickWindow *window, QQuickItem *item);
|
|
||||||
static void setHitTestVisible(QQuickWindow *window, QQuickItem *item);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
|
|
@ -40,15 +40,23 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow
|
||||||
#endif
|
#endif
|
||||||
Q_DECLARE_PRIVATE(FramelessQuickWindow)
|
Q_DECLARE_PRIVATE(FramelessQuickWindow)
|
||||||
Q_DISABLE_COPY_MOVE(FramelessQuickWindow)
|
Q_DISABLE_COPY_MOVE(FramelessQuickWindow)
|
||||||
Q_PROPERTY(bool zoomed READ zoomed NOTIFY zoomedChanged FINAL)
|
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 zoomed READ isZoomed NOTIFY zoomedChanged FINAL)
|
||||||
|
Q_PROPERTY(bool fullScreen READ isFullScreen NOTIFY fullScreenChanged FINAL)
|
||||||
Q_PROPERTY(bool fixedSize READ fixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL)
|
Q_PROPERTY(bool fixedSize READ fixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL)
|
||||||
Q_PROPERTY(QColor frameBorderColor READ frameBorderColor NOTIFY frameBorderColorChanged FINAL)
|
Q_PROPERTY(QColor frameBorderColor READ frameBorderColor NOTIFY frameBorderColorChanged FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickWindow(QWindow *parent = nullptr, const Global::Options options = {});
|
explicit FramelessQuickWindow(QWindow *parent = nullptr, const Global::UserSettings &settings = {});
|
||||||
~FramelessQuickWindow() override;
|
~FramelessQuickWindow() override;
|
||||||
|
|
||||||
Q_NODISCARD bool zoomed() const;
|
Q_NODISCARD bool isHidden() const;
|
||||||
|
Q_NODISCARD bool isNormal() const;
|
||||||
|
Q_NODISCARD bool isMinimized() const;
|
||||||
|
Q_NODISCARD bool isZoomed() const;
|
||||||
|
Q_NODISCARD bool isFullScreen() const;
|
||||||
|
|
||||||
Q_NODISCARD bool fixedSize() const;
|
Q_NODISCARD bool fixedSize() const;
|
||||||
void setFixedSize(const bool value);
|
void setFixedSize(const bool value);
|
||||||
|
@ -65,9 +73,20 @@ public Q_SLOTS:
|
||||||
void setTitleBarItem(QQuickItem *item);
|
void setTitleBarItem(QQuickItem *item);
|
||||||
void setHitTestVisible(QQuickItem *item);
|
void setHitTestVisible(QQuickItem *item);
|
||||||
void moveToDesktopCenter();
|
void moveToDesktopCenter();
|
||||||
|
void bringToFront();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent *event) override;
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void hiddenChanged();
|
||||||
|
void normalChanged();
|
||||||
|
void minimizedChanged();
|
||||||
void zoomedChanged();
|
void zoomedChanged();
|
||||||
|
void fullScreenChanged();
|
||||||
void fixedSizeChanged();
|
void fixedSizeChanged();
|
||||||
void frameBorderColorChanged();
|
void frameBorderColorChanged();
|
||||||
|
|
||||||
|
|
|
@ -35,16 +35,17 @@ class FRAMELESSHELPER_WIDGETS_API FramelessMainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(FramelessMainWindow)
|
Q_DISABLE_COPY_MOVE(FramelessMainWindow)
|
||||||
|
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged 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(bool fixedSize READ isFixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL)
|
||||||
Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged 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::Options options = {});
|
explicit FramelessMainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {}, const Global::UserSettings &settings = {});
|
||||||
~FramelessMainWindow() override;
|
~FramelessMainWindow() override;
|
||||||
|
|
||||||
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
|
Q_NODISCARD bool isNormal() const;
|
||||||
|
|
||||||
Q_NODISCARD bool isZoomed() const;
|
Q_NODISCARD bool isZoomed() const;
|
||||||
|
|
||||||
Q_NODISCARD bool isFixedSize() const;
|
Q_NODISCARD bool isFixedSize() const;
|
||||||
|
@ -58,8 +59,13 @@ public Q_SLOTS:
|
||||||
void toggleMaximized();
|
void toggleMaximized();
|
||||||
void toggleFullScreen();
|
void toggleFullScreen();
|
||||||
void moveToDesktopCenter();
|
void moveToDesktopCenter();
|
||||||
|
void bringToFront();
|
||||||
|
void showSystemMenu(const QPoint &pos);
|
||||||
|
void startSystemMove2();
|
||||||
|
void startSystemResize2(const Qt::Edges edges);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void showEvent(QShowEvent *event) override;
|
||||||
void changeEvent(QEvent *event) override;
|
void changeEvent(QEvent *event) override;
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
@ -67,6 +73,8 @@ protected:
|
||||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void hiddenChanged();
|
||||||
|
void normalChanged();
|
||||||
void zoomedChanged();
|
void zoomedChanged();
|
||||||
void fixedSizeChanged();
|
void fixedSizeChanged();
|
||||||
void titleBarWidgetChanged();
|
void titleBarWidgetChanged();
|
||||||
|
|
|
@ -35,17 +35,18 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(FramelessWidget)
|
Q_DISABLE_COPY_MOVE(FramelessWidget)
|
||||||
|
Q_PROPERTY(bool hidden READ isHidden NOTIFY hiddenChanged 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(bool fixedSize READ isFixedSize WRITE setFixedSize NOTIFY fixedSizeChanged FINAL)
|
||||||
Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL)
|
Q_PROPERTY(QWidget* titleBarWidget READ titleBarWidget WRITE setTitleBarWidget NOTIFY titleBarWidgetChanged FINAL)
|
||||||
Q_PROPERTY(QWidget* contentWidget READ contentWidget WRITE setContentWidget NOTIFY contentWidgetChanged FINAL)
|
Q_PROPERTY(QWidget* contentWidget READ contentWidget WRITE setContentWidget NOTIFY contentWidgetChanged FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessWidget(QWidget *parent = nullptr, const Global::Options options = {});
|
explicit FramelessWidget(QWidget *parent = nullptr, const Global::UserSettings &settings = {});
|
||||||
~FramelessWidget() override;
|
~FramelessWidget() override;
|
||||||
|
|
||||||
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
|
Q_NODISCARD bool isNormal() const;
|
||||||
|
|
||||||
Q_NODISCARD bool isZoomed() const;
|
Q_NODISCARD bool isZoomed() const;
|
||||||
|
|
||||||
Q_NODISCARD bool isFixedSize() const;
|
Q_NODISCARD bool isFixedSize() const;
|
||||||
|
@ -62,8 +63,13 @@ public Q_SLOTS:
|
||||||
void toggleMaximized();
|
void toggleMaximized();
|
||||||
void toggleFullScreen();
|
void toggleFullScreen();
|
||||||
void moveToDesktopCenter();
|
void moveToDesktopCenter();
|
||||||
|
void bringToFront();
|
||||||
|
void showSystemMenu(const QPoint &pos);
|
||||||
|
void startSystemMove2();
|
||||||
|
void startSystemResize2(const Qt::Edges edges);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void showEvent(QShowEvent *event) override;
|
||||||
void changeEvent(QEvent *event) override;
|
void changeEvent(QEvent *event) override;
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
@ -71,6 +77,8 @@ protected:
|
||||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void hiddenChanged();
|
||||||
|
void normalChanged();
|
||||||
void zoomedChanged();
|
void zoomedChanged();
|
||||||
void fixedSizeChanged();
|
void fixedSizeChanged();
|
||||||
void titleBarWidgetChanged();
|
void titleBarWidgetChanged();
|
||||||
|
|
|
@ -32,6 +32,7 @@ QT_BEGIN_NAMESPACE
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QVBoxLayout;
|
class QVBoxLayout;
|
||||||
|
class QShowEvent;
|
||||||
class QPaintEvent;
|
class QPaintEvent;
|
||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -44,7 +45,7 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelper : public QObject
|
||||||
Q_DISABLE_COPY_MOVE(FramelessWidgetsHelper)
|
Q_DISABLE_COPY_MOVE(FramelessWidgetsHelper)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessWidgetsHelper(QWidget *q, const Global::Options options = {});
|
explicit FramelessWidgetsHelper(QWidget *q, const Global::UserSettings &settings = {});
|
||||||
~FramelessWidgetsHelper() override;
|
~FramelessWidgetsHelper() override;
|
||||||
|
|
||||||
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
|
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
|
||||||
|
@ -58,6 +59,7 @@ public:
|
||||||
Q_INVOKABLE void setContentWidget(QWidget *widget);
|
Q_INVOKABLE void setContentWidget(QWidget *widget);
|
||||||
Q_NODISCARD Q_INVOKABLE QWidget *getContentWidget() const;
|
Q_NODISCARD Q_INVOKABLE QWidget *getContentWidget() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void showEventHandler(QShowEvent *event);
|
||||||
Q_INVOKABLE void changeEventHandler(QEvent *event);
|
Q_INVOKABLE void changeEventHandler(QEvent *event);
|
||||||
Q_INVOKABLE void paintEventHandler(QPaintEvent *event);
|
Q_INVOKABLE void paintEventHandler(QPaintEvent *event);
|
||||||
Q_INVOKABLE void mousePressEventHandler(QMouseEvent *event);
|
Q_INVOKABLE void mousePressEventHandler(QMouseEvent *event);
|
||||||
|
@ -69,12 +71,18 @@ public Q_SLOTS:
|
||||||
void toggleMaximized();
|
void toggleMaximized();
|
||||||
void toggleFullScreen();
|
void toggleFullScreen();
|
||||||
void moveToDesktopCenter();
|
void moveToDesktopCenter();
|
||||||
|
void bringToFront();
|
||||||
|
void showSystemMenu(const QPoint &pos);
|
||||||
|
void startSystemMove2();
|
||||||
|
void startSystemResize2(const Qt::Edges edges);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize();
|
void initialize();
|
||||||
void createSystemTitleBar();
|
void createSystemTitleBar();
|
||||||
void createUserContentContainer();
|
void createUserContentContainer();
|
||||||
void setupInitialUi();
|
void setupInitialUi();
|
||||||
|
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) 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 shouldDrawFrameBorder() const;
|
||||||
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
||||||
|
@ -100,7 +108,9 @@ private:
|
||||||
QVBoxLayout *m_userContentContainerLayout = nullptr;
|
QVBoxLayout *m_userContentContainerLayout = nullptr;
|
||||||
Qt::WindowState m_savedWindowState = {};
|
Qt::WindowState m_savedWindowState = {};
|
||||||
QWindow *m_window = nullptr;
|
QWindow *m_window = nullptr;
|
||||||
Global::FramelessHelperParams m_params = {};
|
Global::UserSettings m_settings = {};
|
||||||
|
Global::SystemParameters m_params = {};
|
||||||
|
bool m_windowExposed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -32,16 +32,17 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
struct QtHelperInternalData
|
struct QtHelperData
|
||||||
{
|
{
|
||||||
FramelessHelperParams params = {};
|
UserSettings settings = {};
|
||||||
FramelessHelperQt *framelessHelper = nullptr;
|
SystemParameters params = {};
|
||||||
|
FramelessHelperQt *eventFilter = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QtHelper
|
struct QtHelper
|
||||||
{
|
{
|
||||||
QMutex mutex = {};
|
QMutex mutex = {};
|
||||||
QHash<WId, QtHelperInternalData> data = {};
|
QHash<WId, QtHelperData> data = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(QtHelper, g_qtHelper)
|
Q_GLOBAL_STATIC(QtHelper, g_qtHelper)
|
||||||
|
@ -50,7 +51,7 @@ FramelessHelperQt::FramelessHelperQt(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
FramelessHelperQt::~FramelessHelperQt() = default;
|
FramelessHelperQt::~FramelessHelperQt() = default;
|
||||||
|
|
||||||
void FramelessHelperQt::addWindow(const FramelessHelperParams ¶ms)
|
void FramelessHelperQt::addWindow(const UserSettings &settings, const SystemParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_ASSERT(params.isValid());
|
Q_ASSERT(params.isValid());
|
||||||
if (!params.isValid()) {
|
if (!params.isValid()) {
|
||||||
|
@ -61,15 +62,16 @@ void FramelessHelperQt::addWindow(const FramelessHelperParams ¶ms)
|
||||||
g_qtHelper()->mutex.unlock();
|
g_qtHelper()->mutex.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QtHelperInternalData 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.
|
||||||
data.framelessHelper = new FramelessHelperQt(window);
|
data.eventFilter = new FramelessHelperQt(window);
|
||||||
g_qtHelper()->data.insert(params.windowId, data);
|
g_qtHelper()->data.insert(params.windowId, data);
|
||||||
g_qtHelper()->mutex.unlock();
|
g_qtHelper()->mutex.unlock();
|
||||||
window->setFlags(window->flags() | Qt::FramelessWindowHint);
|
params.setWindowFlags(params.getWindowFlags() | Qt::FramelessWindowHint);
|
||||||
window->installEventFilter(data.framelessHelper);
|
window->installEventFilter(data.eventFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
|
@ -95,7 +97,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
g_qtHelper()->mutex.unlock();
|
g_qtHelper()->mutex.unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const QtHelperInternalData data = g_qtHelper()->data.value(windowId);
|
const QtHelperData data = g_qtHelper()->data.value(windowId);
|
||||||
g_qtHelper()->mutex.unlock();
|
g_qtHelper()->mutex.unlock();
|
||||||
if (data.params.isWindowFixedSize()) {
|
if (data.params.isWindowFixedSize()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -108,7 +110,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
#endif
|
#endif
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case QEvent::MouseMove: {
|
case QEvent::MouseMove: {
|
||||||
if (data.params.options & Option::DontTouchCursorShape) {
|
if (data.settings.options & Option::DontTouchCursorShape) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos);
|
const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos);
|
||||||
|
|
|
@ -37,11 +37,17 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
|
struct Win32HelperData
|
||||||
|
{
|
||||||
|
UserSettings settings = {};
|
||||||
|
SystemParameters params = {};
|
||||||
|
};
|
||||||
|
|
||||||
struct Win32Helper
|
struct Win32Helper
|
||||||
{
|
{
|
||||||
QMutex mutex = {};
|
QMutex mutex = {};
|
||||||
QScopedPointer<FramelessHelperWin> nativeEventFilter;
|
QScopedPointer<FramelessHelperWin> nativeEventFilter;
|
||||||
QHash<WId, FramelessHelperParams> data = {};
|
QHash<WId, Win32HelperData> data = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
||||||
|
@ -50,7 +56,7 @@ FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {}
|
||||||
|
|
||||||
FramelessHelperWin::~FramelessHelperWin() = default;
|
FramelessHelperWin::~FramelessHelperWin() = default;
|
||||||
|
|
||||||
void FramelessHelperWin::addWindow(const FramelessHelperParams ¶ms)
|
void FramelessHelperWin::addWindow(const UserSettings &settings, const SystemParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_ASSERT(params.isValid());
|
Q_ASSERT(params.isValid());
|
||||||
if (!params.isValid()) {
|
if (!params.isValid()) {
|
||||||
|
@ -61,27 +67,29 @@ void FramelessHelperWin::addWindow(const FramelessHelperParams ¶ms)
|
||||||
g_win32Helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FramelessHelperParams localParams = params;
|
Win32HelperData data = {};
|
||||||
if ((localParams.options & Option::ForceHideWindowFrameBorder)
|
data.settings = settings;
|
||||||
&& (localParams.options & Option::ForceShowWindowFrameBorder)) {
|
data.params = params;
|
||||||
localParams.options &= ~(Option::ForceHideWindowFrameBorder | Option::ForceShowWindowFrameBorder);
|
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 "
|
qWarning() << "You can't use both \"Option::ForceHideWindowFrameBorder\" and "
|
||||||
"\"Option::ForceShowWindowFrameBorder\" at the same time.";
|
"\"Option::ForceShowWindowFrameBorder\" at the same time.";
|
||||||
}
|
}
|
||||||
g_win32Helper()->data.insert(localParams.windowId, localParams);
|
g_win32Helper()->data.insert(params.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 (!(localParams.options & Option::DontTouchQtInternals)) {
|
if (!(settings.options & Option::DontTouchQtInternals)) {
|
||||||
Utils::fixupQtInternals(localParams.windowId);
|
Utils::fixupQtInternals(params.windowId);
|
||||||
}
|
}
|
||||||
Utils::updateInternalWindowFrameMargins(localParams.getWindowHandle(), true);
|
Utils::updateInternalWindowFrameMargins(params.getWindowHandle(), true);
|
||||||
Utils::updateWindowFrameMargins(localParams.windowId, false);
|
Utils::updateWindowFrameMargins(params.windowId, false);
|
||||||
if (!(localParams.options & Option::DontTouchWindowFrameBorderColor)) {
|
if (!(settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
||||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||||
Utils::updateWindowFrameBorderColor(localParams.windowId, dark);
|
Utils::updateWindowFrameBorderColor(params.windowId, dark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,30 +104,33 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
#else
|
#else
|
||||||
const auto msg = static_cast<LPMSG>(message);
|
const auto msg = static_cast<LPMSG>(message);
|
||||||
#endif
|
#endif
|
||||||
if (!msg->hwnd) {
|
const HWND hWnd = msg->hwnd;
|
||||||
|
if (!hWnd) {
|
||||||
// Why sometimes the window handle is null? Is it designed to be like this?
|
// Why sometimes the window handle is null? Is it designed to be like this?
|
||||||
// Anyway, we should skip the entire processing in this case.
|
// Anyway, we should skip the entire processing in this case.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto winId = reinterpret_cast<WId>(msg->hwnd);
|
const auto windowId = reinterpret_cast<WId>(hWnd);
|
||||||
g_win32Helper()->mutex.lock();
|
g_win32Helper()->mutex.lock();
|
||||||
if (!g_win32Helper()->data.contains(winId)) {
|
if (!g_win32Helper()->data.contains(windowId)) {
|
||||||
g_win32Helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const FramelessHelperParams params = g_win32Helper()->data.value(winId);
|
const Win32HelperData data = g_win32Helper()->data.value(windowId);
|
||||||
g_win32Helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
const bool frameBorderVisible = [¶ms]() -> bool {
|
const bool frameBorderVisible = [&data]() -> bool {
|
||||||
if (params.options & Option::ForceShowWindowFrameBorder) {
|
if (data.settings.options & Option::ForceShowWindowFrameBorder) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (params.options & Option::ForceHideWindowFrameBorder) {
|
if (data.settings.options & Option::ForceHideWindowFrameBorder) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Utils::isWindowFrameBorderVisible();
|
return Utils::isWindowFrameBorderVisible();
|
||||||
}();
|
}();
|
||||||
const bool fixedSize = params.isWindowFixedSize();
|
const UINT uMsg = msg->message;
|
||||||
switch (msg->message) {
|
const WPARAM wParam = msg->wParam;
|
||||||
|
const LPARAM lParam = msg->lParam;
|
||||||
|
switch (uMsg) {
|
||||||
case WM_NCCALCSIZE: {
|
case WM_NCCALCSIZE: {
|
||||||
// Windows是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容)
|
// Windows是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容)
|
||||||
// 和非客户区(标题栏、窗口边框、菜单栏和状态栏等Windows系统自行提供的部分
|
// 和非客户区(标题栏、窗口边框、菜单栏和状态栏等Windows系统自行提供的部分
|
||||||
|
@ -208,14 +219,14 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// implement an elaborate client-area preservation technique, and
|
// implement an elaborate client-area preservation technique, and
|
||||||
// simply return 0, which means "preserve the entire old client area
|
// simply return 0, which means "preserve the entire old client area
|
||||||
// and align it with the upper-left corner of our new client area".
|
// and align it with the upper-left corner of our new client area".
|
||||||
const auto clientRect = ((static_cast<BOOL>(msg->wParam) == FALSE)
|
const auto clientRect = ((static_cast<BOOL>(wParam) == FALSE)
|
||||||
? reinterpret_cast<LPRECT>(msg->lParam)
|
? reinterpret_cast<LPRECT>(lParam)
|
||||||
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam))->rgrc[0]);
|
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
||||||
if (frameBorderVisible) {
|
if (frameBorderVisible) {
|
||||||
// Store the original top before the default window proc applies the default frame.
|
// Store the original top before the default window proc applies the default frame.
|
||||||
const LONG originalTop = clientRect->top;
|
const LONG originalTop = clientRect->top;
|
||||||
// Apply the default frame.
|
// Apply the default frame.
|
||||||
const LRESULT ret = DefWindowProcW(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam);
|
const LRESULT ret = DefWindowProcW(hWnd, WM_NCCALCSIZE, wParam, lParam);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
*result = ret;
|
*result = ret;
|
||||||
return true;
|
return true;
|
||||||
|
@ -223,8 +234,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// Re-apply the original top from before the size of the default frame was applied.
|
// Re-apply the original top from before the size of the default frame was applied.
|
||||||
clientRect->top = originalTop;
|
clientRect->top = originalTop;
|
||||||
}
|
}
|
||||||
const bool max = IsMaximized(msg->hwnd);
|
const bool max = IsMaximized(hWnd);
|
||||||
const bool full = Utils::isFullScreen(winId);
|
const bool full = Utils::isFullScreen(windowId);
|
||||||
// We don't need this correction when we're fullscreen. We will
|
// We don't need this correction when we're fullscreen. We will
|
||||||
// have the WS_POPUP size, so we don't have to worry about
|
// have the WS_POPUP size, so we don't have to worry about
|
||||||
// borders, and the default frame will be fine.
|
// borders, and the default frame will be fine.
|
||||||
|
@ -235,11 +246,11 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// then the window is clipped to the monitor so that the resize handle
|
// then the window is clipped to the monitor so that the resize handle
|
||||||
// do not appear because you don't need them (because you can't resize
|
// do not appear because you don't need them (because you can't resize
|
||||||
// a window when it's maximized unless you restore it).
|
// a window when it's maximized unless you restore it).
|
||||||
const int frameSizeY = Utils::getResizeBorderThickness(winId, false, true);
|
const int frameSizeY = Utils::getResizeBorderThickness(windowId, false, true);
|
||||||
clientRect->top += frameSizeY;
|
clientRect->top += frameSizeY;
|
||||||
if (!frameBorderVisible) {
|
if (!frameBorderVisible) {
|
||||||
clientRect->bottom -= frameSizeY;
|
clientRect->bottom -= frameSizeY;
|
||||||
const int frameSizeX = Utils::getResizeBorderThickness(winId, true, true);
|
const int frameSizeX = Utils::getResizeBorderThickness(windowId, true, true);
|
||||||
clientRect->left += frameSizeX;
|
clientRect->left += frameSizeX;
|
||||||
clientRect->right -= frameSizeX;
|
clientRect->right -= frameSizeX;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +276,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
MONITORINFO monitorInfo;
|
MONITORINFO monitorInfo;
|
||||||
SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
|
SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
|
||||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||||
const HMONITOR monitor = MonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONEAREST);
|
const HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
||||||
if (!monitor) {
|
if (!monitor) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("MonitorFromWindow"));
|
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("MonitorFromWindow"));
|
||||||
break;
|
break;
|
||||||
|
@ -297,7 +308,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
_abd.cbSize = sizeof(_abd);
|
_abd.cbSize = sizeof(_abd);
|
||||||
_abd.hWnd = FindWindowW(L"Shell_TrayWnd", nullptr);
|
_abd.hWnd = FindWindowW(L"Shell_TrayWnd", nullptr);
|
||||||
if (_abd.hWnd) {
|
if (_abd.hWnd) {
|
||||||
const HMONITOR windowMonitor = MonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONEAREST);
|
const HMONITOR windowMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
||||||
if (!windowMonitor) {
|
if (!windowMonitor) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("MonitorFromWindow"));
|
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("MonitorFromWindow"));
|
||||||
break;
|
break;
|
||||||
|
@ -367,7 +378,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// of the upper-left non-client area. It's confirmed that this issue exists
|
// of the upper-left non-client area. It's confirmed that this issue exists
|
||||||
// from Windows 7 to Windows 10. Not tested on Windows 11 yet. Don't know
|
// from Windows 7 to Windows 10. Not tested on Windows 11 yet. Don't know
|
||||||
// whether it exists on Windows XP to Windows Vista or not.
|
// whether it exists on Windows XP to Windows Vista or not.
|
||||||
*result = ((static_cast<BOOL>(msg->wParam) == FALSE) ? 0 : WVR_REDRAW);
|
*result = ((static_cast<BOOL>(wParam) == FALSE) ? 0 : WVR_REDRAW);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case WM_NCHITTEST: {
|
case WM_NCHITTEST: {
|
||||||
|
@ -436,25 +447,51 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// another branch, if you are interested in it, you can give it a
|
// another branch, if you are interested in it, you can give it a
|
||||||
// try.
|
// try.
|
||||||
|
|
||||||
if (fixedSize) {
|
if (data.params.isWindowFixedSize()) {
|
||||||
*result = HTCLIENT;
|
*result = HTCLIENT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const POINT globalPos = {GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam)};
|
const POINT globalPos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||||
POINT localPos = globalPos;
|
POINT localPos = globalPos;
|
||||||
if (ScreenToClient(msg->hwnd, &localPos) == FALSE) {
|
if (ScreenToClient(hWnd, &localPos) == FALSE) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("ScreenToClient"));
|
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("ScreenToClient"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const bool max = IsMaximized(msg->hwnd);
|
if (data.settings.options & Option::MaximizeButtonDocking) {
|
||||||
const bool full = Utils::isFullScreen(winId);
|
const QPoint scenePos = QPointF(QPointF(qreal(localPos.x), qreal(localPos.y))
|
||||||
const int frameSizeY = Utils::getResizeBorderThickness(winId, false, true);
|
/ data.params.getWindowDevicePixelRatio()).toPoint();
|
||||||
|
SystemButtonType systemButton = SystemButtonType::Unknown;
|
||||||
|
if (data.params.isInsideSystemButtons(scenePos, &systemButton)) {
|
||||||
|
switch (systemButton) {
|
||||||
|
case SystemButtonType::Help:
|
||||||
|
*result = HTHELP;
|
||||||
|
break;
|
||||||
|
case SystemButtonType::Minimize:
|
||||||
|
*result = HTREDUCE;
|
||||||
|
break;
|
||||||
|
case SystemButtonType::Maximize:
|
||||||
|
case SystemButtonType::Restore:
|
||||||
|
*result = HTZOOM;
|
||||||
|
break;
|
||||||
|
case SystemButtonType::Close:
|
||||||
|
*result = HTCLOSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*result = HTCAPTION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const bool max = IsMaximized(hWnd);
|
||||||
|
const bool full = Utils::isFullScreen(windowId);
|
||||||
|
const int frameSizeY = Utils::getResizeBorderThickness(windowId, false, true);
|
||||||
const bool isTop = (localPos.y < frameSizeY);
|
const bool isTop = (localPos.y < frameSizeY);
|
||||||
const bool isTitleBar = (false && !(params.options & Option::DisableDragging));
|
const bool isTitleBar = (false && !(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.
|
||||||
const LRESULT originalRet = DefWindowProcW(msg->hwnd, WM_NCHITTEST, 0, msg->lParam);
|
const LRESULT originalRet = DefWindowProcW(hWnd, WM_NCHITTEST, 0, lParam);
|
||||||
if (originalRet != HTCLIENT) {
|
if (originalRet != HTCLIENT) {
|
||||||
*result = originalRet;
|
*result = originalRet;
|
||||||
return true;
|
return true;
|
||||||
|
@ -492,7 +529,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
RECT clientRect = {0, 0, 0, 0};
|
RECT clientRect = {0, 0, 0, 0};
|
||||||
if (GetClientRect(msg->hwnd, &clientRect) == FALSE) {
|
if (GetClientRect(hWnd, &clientRect) == FALSE) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetClientRect"));
|
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetClientRect"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +538,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
const bool isBottom = (localPos.y >= (height - frameSizeY));
|
const bool isBottom = (localPos.y >= (height - frameSizeY));
|
||||||
// Make the border a little wider to let the user easy to resize on corners.
|
// Make the border a little wider to let the user easy to resize on corners.
|
||||||
const qreal scaleFactor = ((isTop || isBottom) ? 2.0 : 1.0);
|
const qreal scaleFactor = ((isTop || isBottom) ? 2.0 : 1.0);
|
||||||
const int frameSizeX = Utils::getResizeBorderThickness(winId, true, true);
|
const int frameSizeX = Utils::getResizeBorderThickness(windowId, true, true);
|
||||||
const auto scaledFrameSizeX = static_cast<int>(qRound(qreal(frameSizeX) * scaleFactor));
|
const auto scaledFrameSizeX = static_cast<int>(qRound(qreal(frameSizeX) * scaleFactor));
|
||||||
const bool isLeft = (localPos.x < scaledFrameSizeX);
|
const bool isLeft = (localPos.x < scaledFrameSizeX);
|
||||||
const bool isRight = (localPos.x >= (width - scaledFrameSizeX));
|
const bool isRight = (localPos.x >= (width - scaledFrameSizeX));
|
||||||
|
@ -549,23 +586,23 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
case WM_WINDOWPOSCHANGING: {
|
case WM_WINDOWPOSCHANGING: {
|
||||||
// Tell Windows to discard the entire contents of the client area, as re-using
|
// Tell Windows to discard the entire contents of the client area, as re-using
|
||||||
// parts of the client area would lead to jitter during resize.
|
// parts of the client area would lead to jitter during resize.
|
||||||
const auto windowPos = reinterpret_cast<LPWINDOWPOS>(msg->lParam);
|
const auto windowPos = reinterpret_cast<LPWINDOWPOS>(lParam);
|
||||||
windowPos->flags |= SWP_NOCOPYBITS;
|
windowPos->flags |= SWP_NOCOPYBITS;
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
case WM_DPICHANGED: {
|
case WM_DPICHANGED: {
|
||||||
// Sync the internal window frame margins with the latest DPI.
|
// Sync the internal window frame margins with the latest DPI.
|
||||||
Utils::updateInternalWindowFrameMargins(params.getWindowHandle(), true);
|
Utils::updateInternalWindowFrameMargins(data.params.getWindowHandle(), true);
|
||||||
} break;
|
} break;
|
||||||
case WM_DWMCOMPOSITIONCHANGED: {
|
case WM_DWMCOMPOSITIONCHANGED: {
|
||||||
// Re-apply the custom window frame if recovered from the basic theme.
|
// Re-apply the custom window frame if recovered from the basic theme.
|
||||||
Utils::updateWindowFrameMargins(winId, false);
|
Utils::updateWindowFrameMargins(windowId, false);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!frameBorderVisible) {
|
if (!frameBorderVisible) {
|
||||||
switch (msg->message) {
|
switch (uMsg) {
|
||||||
case WM_NCUAHDRAWCAPTION:
|
case WM_NCUAHDRAWCAPTION:
|
||||||
case WM_NCUAHDRAWFRAME: {
|
case WM_NCUAHDRAWFRAME: {
|
||||||
// These undocumented messages are sent to draw themed window
|
// These undocumented messages are sent to draw themed window
|
||||||
|
@ -594,9 +631,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate
|
// https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate
|
||||||
// Don't use "*result = 0" here, otherwise the window won't respond to the
|
// Don't use "*result = 0" here, otherwise the window won't respond to the
|
||||||
// window activation state change.
|
// window activation state change.
|
||||||
*result = DefWindowProcW(msg->hwnd, WM_NCACTIVATE, msg->wParam, -1);
|
*result = DefWindowProcW(hWnd, WM_NCACTIVATE, wParam, -1);
|
||||||
} else {
|
} else {
|
||||||
if (static_cast<BOOL>(msg->wParam) == FALSE) {
|
if (static_cast<BOOL>(wParam) == FALSE) {
|
||||||
*result = TRUE;
|
*result = TRUE;
|
||||||
} else {
|
} else {
|
||||||
*result = FALSE;
|
*result = FALSE;
|
||||||
|
@ -610,26 +647,27 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// Disable painting while these messages are handled to prevent them
|
// Disable painting while these messages are handled to prevent them
|
||||||
// from drawing a window caption over the client area.
|
// from drawing a window caption over the client area.
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
const LONG_PTR oldStyle = GetWindowLongPtrW(msg->hwnd, GWL_STYLE);
|
const auto oldStyle = static_cast<DWORD>(GetWindowLongPtrW(hWnd, GWL_STYLE));
|
||||||
if (oldStyle == 0) {
|
if (oldStyle == 0) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetWindowLongPtrW"));
|
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetWindowLongPtrW"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Prevent Windows from drawing the default title bar by temporarily
|
// Prevent Windows from drawing the default title bar by temporarily
|
||||||
// toggling the WS_VISIBLE style.
|
// toggling the WS_VISIBLE style.
|
||||||
|
const DWORD newStyle = (oldStyle & ~WS_VISIBLE);
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
if (SetWindowLongPtrW(msg->hwnd, GWL_STYLE, static_cast<LONG_PTR>(oldStyle & ~WS_VISIBLE)) == 0) {
|
if (SetWindowLongPtrW(hWnd, GWL_STYLE, static_cast<LONG_PTR>(newStyle)) == 0) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Utils::triggerFrameChange(winId);
|
Utils::triggerFrameChange(windowId);
|
||||||
const LRESULT ret = DefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
const LRESULT ret = DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
if (SetWindowLongPtrW(msg->hwnd, GWL_STYLE, oldStyle) == 0) {
|
if (SetWindowLongPtrW(hWnd, GWL_STYLE, static_cast<LONG_PTR>(oldStyle)) == 0) {
|
||||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Utils::triggerFrameChange(winId);
|
Utils::triggerFrameChange(windowId);
|
||||||
*result = ret;
|
*result = ret;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -638,10 +676,10 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const bool themeSettingChanged = [&msg]() -> bool {
|
const bool themeSettingChanged = [uMsg, wParam, lParam]() -> bool {
|
||||||
if (Utils::isWin10OrGreater()) {
|
if (Utils::isWin10OrGreater()) {
|
||||||
if (msg->message == WM_SETTINGCHANGE) {
|
if (uMsg == WM_SETTINGCHANGE) {
|
||||||
if ((msg->wParam == 0) && (QString::fromWCharArray(reinterpret_cast<LPCWSTR>(msg->lParam))
|
if ((wParam == 0) && (QString::fromWCharArray(reinterpret_cast<LPCWSTR>(lParam))
|
||||||
.compare(QU8Str(kThemeSettingChangeEventName), Qt::CaseInsensitive) == 0)) {
|
.compare(QU8Str(kThemeSettingChangeEventName), Qt::CaseInsensitive) == 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -650,13 +688,13 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
return false;
|
return false;
|
||||||
}();
|
}();
|
||||||
if (themeSettingChanged) {
|
if (themeSettingChanged) {
|
||||||
if (!(params.options & Option::DontTouchWindowFrameBorderColor)) {
|
if (!(data.settings.options & Option::DontTouchWindowFrameBorderColor)) {
|
||||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||||
Utils::updateWindowFrameBorderColor(winId, dark);
|
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (themeSettingChanged || (msg->message == WM_THEMECHANGED)
|
if (themeSettingChanged || (uMsg == WM_THEMECHANGED)
|
||||||
|| (msg->message == WM_DWMCOLORIZATIONCOLORCHANGED)) {
|
|| (uMsg == WM_DWMCOLORIZATIONCOLORCHANGED)) {
|
||||||
Q_EMIT FramelessWindowsManager::instance()->systemThemeChanged();
|
Q_EMIT FramelessWindowsManager::instance()->systemThemeChanged();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -39,13 +39,13 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
struct FramelessWindowsManagerData
|
struct FramelessWindowsManagerHelper
|
||||||
{
|
{
|
||||||
QMutex mutex = {};
|
QMutex mutex = {};
|
||||||
QList<WId> windowIds = {};
|
QList<WId> windowIds = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(FramelessWindowsManagerData, g_data)
|
Q_GLOBAL_STATIC(FramelessWindowsManagerHelper, g_helper)
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(FramelessWindowsManager, g_manager)
|
Q_GLOBAL_STATIC(FramelessWindowsManager, g_manager)
|
||||||
|
|
||||||
|
@ -54,6 +54,8 @@ FramelessWindowsManager::FramelessWindowsManager(QObject *parent) : QObject(pare
|
||||||
if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings)) {
|
if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings)) {
|
||||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||||
}
|
}
|
||||||
|
qRegisterMetaType<UserSettings>();
|
||||||
|
qRegisterMetaType<SystemParameters>();
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessWindowsManager::~FramelessWindowsManager() = default;
|
FramelessWindowsManager::~FramelessWindowsManager() = default;
|
||||||
|
@ -89,19 +91,19 @@ SystemTheme FramelessWindowsManager::systemTheme()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWindowsManager::addWindow(const FramelessHelperParams ¶ms)
|
void FramelessWindowsManager::addWindow(const UserSettings &settings, const SystemParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_ASSERT(params.isValid());
|
Q_ASSERT(params.isValid());
|
||||||
if (!params.isValid()) {
|
if (!params.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_data()->mutex.lock();
|
g_helper()->mutex.lock();
|
||||||
if (g_data()->windowIds.contains(params.windowId)) {
|
if (g_helper()->windowIds.contains(params.windowId)) {
|
||||||
g_data()->mutex.unlock();
|
g_helper()->mutex.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_data()->windowIds.append(params.windowId);
|
g_helper()->windowIds.append(params.windowId);
|
||||||
g_data()->mutex.unlock();
|
g_helper()->mutex.unlock();
|
||||||
static const bool pureQt = usePureQtImplementation();
|
static const bool pureQt = usePureQtImplementation();
|
||||||
QWindow *window = params.getWindowHandle();
|
QWindow *window = params.getWindowHandle();
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
|
@ -121,15 +123,15 @@ void FramelessWindowsManager::addWindow(const FramelessHelperParams ¶ms)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (pureQt) {
|
if (pureQt) {
|
||||||
FramelessHelperQt::addWindow(params);
|
FramelessHelperQt::addWindow(settings, params);
|
||||||
}
|
}
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (!pureQt) {
|
if (!pureQt) {
|
||||||
FramelessHelperWin::addWindow(params);
|
FramelessHelperWin::addWindow(settings, params);
|
||||||
}
|
}
|
||||||
if (!(params.options & Option::DontInstallSystemMenuHook)) {
|
if (!(settings.options & Option::DontInstallSystemMenuHook)) {
|
||||||
Utils::installSystemMenuHook(params.windowId, params.options,
|
Utils::installSystemMenuHook(params.windowId, settings.options,
|
||||||
params.systemMenuOffset, params.isWindowFixedSize);
|
settings.systemMenuOffset, params.isWindowFixedSize);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,9 @@ QVariant Utils::getSystemButtonIconResource
|
||||||
case SystemButtonType::Unknown:
|
case SystemButtonType::Unknown:
|
||||||
return {};
|
return {};
|
||||||
case SystemButtonType::WindowIcon:
|
case SystemButtonType::WindowIcon:
|
||||||
return QStringLiteral("windowIcon");
|
return QStringLiteral("windowicon");
|
||||||
|
case SystemButtonType::Help:
|
||||||
|
return QStringLiteral("help");
|
||||||
case SystemButtonType::Minimize:
|
case SystemButtonType::Minimize:
|
||||||
return QStringLiteral("minimize");
|
return QStringLiteral("minimize");
|
||||||
case SystemButtonType::Maximize:
|
case SystemButtonType::Maximize:
|
||||||
|
@ -142,10 +144,10 @@ QVariant Utils::getSystemButtonIconResource
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindow *Utils::findWindow(const WId winId)
|
QWindow *Utils::findWindow(const WId windowId)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const QWindowList windows = QGuiApplication::topLevelWindows();
|
const QWindowList windows = QGuiApplication::topLevelWindows();
|
||||||
|
@ -154,7 +156,7 @@ QWindow *Utils::findWindow(const WId winId)
|
||||||
}
|
}
|
||||||
for (auto &&window : qAsConst(windows)) {
|
for (auto &&window : qAsConst(windows)) {
|
||||||
if (window && window->handle()) {
|
if (window && window->handle()) {
|
||||||
if (window->winId() == winId) {
|
if (window->winId() == windowId) {
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
struct Win32UtilsInternalData
|
struct Win32UtilsHelperData
|
||||||
{
|
{
|
||||||
WNDPROC originalWindowProc = nullptr;
|
WNDPROC originalWindowProc = nullptr;
|
||||||
Options options = {};
|
Options options = {};
|
||||||
|
@ -65,7 +65,7 @@ struct Win32UtilsInternalData
|
||||||
struct Win32UtilsHelper
|
struct Win32UtilsHelper
|
||||||
{
|
{
|
||||||
QMutex mutex = {};
|
QMutex mutex = {};
|
||||||
QHash<WId, Win32UtilsInternalData> data = {};
|
QHash<WId, Win32UtilsHelperData> data = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(Win32UtilsHelper, g_utilsHelper)
|
Q_GLOBAL_STATIC(Win32UtilsHelper, g_utilsHelper)
|
||||||
|
@ -127,14 +127,14 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
||||||
return __getSystemErrorMessage(function, dwError);
|
return __getSystemErrorMessage(function, dwError);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static inline int getSystemMetrics2(const WId winId, const int index,
|
[[nodiscard]] static inline int getSystemMetrics2(const WId windowId, const int index,
|
||||||
const bool horizontal, const bool scaled)
|
const bool horizontal, const bool scaled)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const UINT windowDpi = Utils::getWindowDpi(winId, horizontal);
|
const UINT windowDpi = Utils::getWindowDpi(windowId, horizontal);
|
||||||
static const auto pGetSystemMetricsForDpi =
|
static const auto pGetSystemMetricsForDpi =
|
||||||
reinterpret_cast<decltype(&GetSystemMetricsForDpi)>(
|
reinterpret_cast<decltype(&GetSystemMetricsForDpi)>(
|
||||||
QSystemLibrary::resolve(QStringLiteral("user32"), "GetSystemMetricsForDpi"));
|
QSystemLibrary::resolve(QStringLiteral("user32"), "GetSystemMetricsForDpi"));
|
||||||
|
@ -189,7 +189,7 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
||||||
g_utilsHelper()->mutex.unlock();
|
g_utilsHelper()->mutex.unlock();
|
||||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
const Win32UtilsInternalData data = g_utilsHelper()->data.value(windowId);
|
const Win32UtilsHelperData data = g_utilsHelper()->data.value(windowId);
|
||||||
g_utilsHelper()->mutex.unlock();
|
g_utilsHelper()->mutex.unlock();
|
||||||
const auto getGlobalPosFromMouse = [lParam]() -> QPoint {
|
const auto getGlobalPosFromMouse = [lParam]() -> QPoint {
|
||||||
return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||||
|
@ -331,23 +331,23 @@ bool Utils::isDwmCompositionEnabled()
|
||||||
return (enabled != FALSE);
|
return (enabled != FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::triggerFrameChange(const WId winId)
|
void Utils::triggerFrameChange(const WId windowId)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
static constexpr const UINT flags = (SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
static constexpr const UINT flags = (SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||||
if (SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, flags) == FALSE) {
|
if (SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, flags) == FALSE) {
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowPos"));
|
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowPos"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::updateWindowFrameMargins(const WId winId, const bool reset)
|
void Utils::updateWindowFrameMargins(const WId windowId, const bool reset)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We can't extend the window frame when DWM composition is disabled.
|
// We can't extend the window frame when DWM composition is disabled.
|
||||||
|
@ -368,13 +368,13 @@ void Utils::updateWindowFrameMargins(const WId winId, const bool reset)
|
||||||
return {1, 1, 1, 1};
|
return {1, 1, 1, 1};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
const HRESULT hr = pDwmExtendFrameIntoClientArea(hwnd, &margins);
|
const HRESULT hr = pDwmExtendFrameIntoClientArea(hwnd, &margins);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
qWarning() << __getSystemErrorMessage(QStringLiteral("DwmExtendFrameIntoClientArea"), hr);
|
qWarning() << __getSystemErrorMessage(QStringLiteral("DwmExtendFrameIntoClientArea"), hr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
triggerFrameChange(winId);
|
triggerFrameChange(windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::updateInternalWindowFrameMargins(QWindow *window, const bool enable)
|
void Utils::updateInternalWindowFrameMargins(QWindow *window, const bool enable)
|
||||||
|
@ -383,17 +383,17 @@ void Utils::updateInternalWindowFrameMargins(QWindow *window, const bool enable)
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const WId winId = window->winId();
|
const WId windowId = window->winId();
|
||||||
const QMargins margins = [enable, winId]() -> QMargins {
|
const QMargins margins = [enable, windowId]() -> QMargins {
|
||||||
if (!enable) {
|
if (!enable) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const int titleBarHeight = getTitleBarHeight(winId, true);
|
const int titleBarHeight = getTitleBarHeight(windowId, true);
|
||||||
if (isWindowFrameBorderVisible()) {
|
if (isWindowFrameBorderVisible()) {
|
||||||
return {0, -titleBarHeight, 0, 0};
|
return {0, -titleBarHeight, 0, 0};
|
||||||
} else {
|
} else {
|
||||||
const int frameSizeX = getResizeBorderThickness(winId, true, true);
|
const int frameSizeX = getResizeBorderThickness(windowId, true, true);
|
||||||
const int frameSizeY = getResizeBorderThickness(winId, false, true);
|
const int frameSizeY = getResizeBorderThickness(windowId, false, true);
|
||||||
return {-frameSizeX, -titleBarHeight, -frameSizeX, -frameSizeY};
|
return {-frameSizeX, -titleBarHeight, -frameSizeX, -frameSizeY};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
@ -414,7 +414,7 @@ void Utils::updateInternalWindowFrameMargins(QWindow *window, const bool enable)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
triggerFrameChange(winId);
|
triggerFrameChange(windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Utils::getSystemErrorMessage(const QString &function)
|
QString Utils::getSystemErrorMessage(const QString &function)
|
||||||
|
@ -493,15 +493,15 @@ DwmColorizationArea Utils::getDwmColorizationArea()
|
||||||
return DwmColorizationArea::None;
|
return DwmColorizationArea::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::showSystemMenu(const WId winId, const QPoint &pos, const Options options,
|
void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const Options options,
|
||||||
const QPoint &offset, const IsWindowFixedSizeCallback &isWindowFixedSize)
|
const QPoint &offset, const IsWindowFixedSizeCallback &isWindowFixedSize)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
Q_ASSERT(isWindowFixedSize);
|
Q_ASSERT(isWindowFixedSize);
|
||||||
if (!winId || !isWindowFixedSize) {
|
if (!windowId || !isWindowFixedSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hWnd = reinterpret_cast<HWND>(winId);
|
const auto hWnd = reinterpret_cast<HWND>(windowId);
|
||||||
const HMENU menu = GetSystemMenu(hWnd, FALSE);
|
const HMENU menu = GetSystemMenu(hWnd, FALSE);
|
||||||
if (!menu) {
|
if (!menu) {
|
||||||
// The corresponding window doesn't have a menu, this isn't an error,
|
// The corresponding window doesn't have a menu, this isn't an error,
|
||||||
|
@ -522,7 +522,7 @@ void Utils::showSystemMenu(const WId winId, const QPoint &pos, const Options opt
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
const bool maxOrFull = (IsMaximized(hWnd) ||
|
const bool maxOrFull = (IsMaximized(hWnd) ||
|
||||||
((options & Option::DontTreatFullScreenAsZoomed) ? false : isFullScreen(winId)));
|
((options & Option::DontTreatFullScreenAsZoomed) ? false : isFullScreen(windowId)));
|
||||||
const bool fixedSize = isWindowFixedSize();
|
const bool fixedSize = isWindowFixedSize();
|
||||||
if (!setState(SC_RESTORE, (maxOrFull && !fixedSize), true)) {
|
if (!setState(SC_RESTORE, (maxOrFull && !fixedSize), true)) {
|
||||||
return;
|
return;
|
||||||
|
@ -558,13 +558,13 @@ void Utils::showSystemMenu(const WId winId, const QPoint &pos, const Options opt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::isFullScreen(const WId winId)
|
bool Utils::isFullScreen(const WId windowId)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
RECT wndRect = {};
|
RECT wndRect = {};
|
||||||
if (GetWindowRect(hwnd, &wndRect) == FALSE) {
|
if (GetWindowRect(hwnd, &wndRect) == FALSE) {
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("GetWindowRect"));
|
qWarning() << getSystemErrorMessage(QStringLiteral("GetWindowRect"));
|
||||||
|
@ -590,13 +590,13 @@ bool Utils::isFullScreen(const WId winId)
|
||||||
&& (wndRect.right == scrRect.right) && (wndRect.bottom == scrRect.bottom));
|
&& (wndRect.right == scrRect.right) && (wndRect.bottom == scrRect.bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::isWindowNoState(const WId winId)
|
bool Utils::isWindowNoState(const WId windowId)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
WINDOWPLACEMENT wp;
|
WINDOWPLACEMENT wp;
|
||||||
SecureZeroMemory(&wp, sizeof(wp));
|
SecureZeroMemory(&wp, sizeof(wp));
|
||||||
wp.length = sizeof(wp); // This line is important! Don't miss it!
|
wp.length = sizeof(wp); // This line is important! Don't miss it!
|
||||||
|
@ -755,13 +755,13 @@ QT_WARNING_POP
|
||||||
return USER_DEFAULT_SCREEN_DPI;
|
return USER_DEFAULT_SCREEN_DPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 Utils::getWindowDpi(const WId winId, const bool horizontal)
|
quint32 Utils::getWindowDpi(const WId windowId, const bool horizontal)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return USER_DEFAULT_SCREEN_DPI;
|
return USER_DEFAULT_SCREEN_DPI;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
QSystemLibrary user32Lib(QStringLiteral("user32"));
|
QSystemLibrary user32Lib(QStringLiteral("user32"));
|
||||||
static const auto pGetDpiForWindow =
|
static const auto pGetDpiForWindow =
|
||||||
reinterpret_cast<decltype(&GetDpiForWindow)>(user32Lib.resolve("GetDpiForWindow"));
|
reinterpret_cast<decltype(&GetDpiForWindow)>(user32Lib.resolve("GetDpiForWindow"));
|
||||||
|
@ -793,43 +793,43 @@ quint32 Utils::getWindowDpi(const WId winId, const bool horizontal)
|
||||||
return getPrimaryScreenDpi(horizontal);
|
return getPrimaryScreenDpi(horizontal);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 Utils::getResizeBorderThickness(const WId winId, const bool horizontal, const bool scaled)
|
quint32 Utils::getResizeBorderThickness(const WId windowId, const bool horizontal, const bool scaled)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (horizontal) {
|
if (horizontal) {
|
||||||
return (getSystemMetrics2(winId, SM_CXSIZEFRAME, true, scaled)
|
return (getSystemMetrics2(windowId, SM_CXSIZEFRAME, true, scaled)
|
||||||
+ getSystemMetrics2(winId, SM_CXPADDEDBORDER, true, scaled));
|
+ getSystemMetrics2(windowId, SM_CXPADDEDBORDER, true, scaled));
|
||||||
} else {
|
} else {
|
||||||
return (getSystemMetrics2(winId, SM_CYSIZEFRAME, false, scaled)
|
return (getSystemMetrics2(windowId, SM_CYSIZEFRAME, false, scaled)
|
||||||
+ getSystemMetrics2(winId, SM_CYPADDEDBORDER, false, scaled));
|
+ getSystemMetrics2(windowId, SM_CYPADDEDBORDER, false, scaled));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 Utils::getCaptionHeight(const WId winId, const bool scaled)
|
quint32 Utils::getCaptionHeight(const WId windowId, const bool scaled)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return getSystemMetrics2(winId, SM_CYCAPTION, false, scaled);
|
return getSystemMetrics2(windowId, SM_CYCAPTION, false, scaled);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 Utils::getTitleBarHeight(const WId winId, const bool scaled)
|
quint32 Utils::getTitleBarHeight(const WId windowId, const bool scaled)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (getCaptionHeight(winId, scaled) + getResizeBorderThickness(winId, false, scaled));
|
return (getCaptionHeight(windowId, scaled) + getResizeBorderThickness(windowId, false, scaled));
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 Utils::getFrameBorderThickness(const WId winId, const bool scaled)
|
quint32 Utils::getFrameBorderThickness(const WId windowId, const bool scaled)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// There's no window frame border before Windows 10.
|
// There's no window frame border before Windows 10.
|
||||||
|
@ -842,9 +842,9 @@ quint32 Utils::getFrameBorderThickness(const WId winId, const bool scaled)
|
||||||
if (!pDwmGetWindowAttribute) {
|
if (!pDwmGetWindowAttribute) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const UINT dpi = getWindowDpi(winId, true);
|
const UINT dpi = getWindowDpi(windowId, true);
|
||||||
const qreal scaleFactor = (qreal(dpi) / qreal(USER_DEFAULT_SCREEN_DPI));
|
const qreal scaleFactor = (qreal(dpi) / qreal(USER_DEFAULT_SCREEN_DPI));
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
UINT value = 0;
|
UINT value = 0;
|
||||||
if (SUCCEEDED(pDwmGetWindowAttribute(hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &value, sizeof(value)))) {
|
if (SUCCEEDED(pDwmGetWindowAttribute(hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &value, sizeof(value)))) {
|
||||||
const qreal dpr = (scaled ? 1.0 : scaleFactor);
|
const qreal dpr = (scaled ? 1.0 : scaleFactor);
|
||||||
|
@ -874,10 +874,10 @@ QColor Utils::getFrameBorderColor(const bool active)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::updateWindowFrameBorderColor(const WId winId, const bool dark)
|
void Utils::updateWindowFrameBorderColor(const WId windowId, const bool dark)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// There's no global dark theme before Win10 1809.
|
// There's no global dark theme before Win10 1809.
|
||||||
|
@ -890,7 +890,7 @@ void Utils::updateWindowFrameBorderColor(const WId winId, const bool dark)
|
||||||
if (!pDwmSetWindowAttribute) {
|
if (!pDwmSetWindowAttribute) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
const BOOL value = (dark ? TRUE : FALSE);
|
const BOOL value = (dark ? TRUE : FALSE);
|
||||||
// Whether dark window frame is available or not depends on the runtime system version,
|
// Whether dark window frame is available or not depends on the runtime system version,
|
||||||
// it's totally OK if it's not available, so just ignore the errors.
|
// it's totally OK if it's not available, so just ignore the errors.
|
||||||
|
@ -898,13 +898,13 @@ void Utils::updateWindowFrameBorderColor(const WId winId, const bool dark)
|
||||||
pDwmSetWindowAttribute(hwnd, _DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
pDwmSetWindowAttribute(hwnd, _DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::fixupQtInternals(const WId winId)
|
void Utils::fixupQtInternals(const WId windowId)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
const auto oldClassStyle = static_cast<DWORD>(GetClassLongPtrW(hwnd, GCL_STYLE));
|
const auto oldClassStyle = static_cast<DWORD>(GetClassLongPtrW(hwnd, GCL_STYLE));
|
||||||
if (oldClassStyle == 0) {
|
if (oldClassStyle == 0) {
|
||||||
|
@ -929,7 +929,7 @@ void Utils::fixupQtInternals(const WId winId)
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
triggerFrameChange(winId);
|
triggerFrameChange(windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::startSystemMove(QWindow *window)
|
void Utils::startSystemMove(QWindow *window)
|
||||||
|
@ -1013,19 +1013,19 @@ bool Utils::isFrameBorderColorized()
|
||||||
return isTitleBarColorized();
|
return isTitleBarColorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::installSystemMenuHook(const WId winId, const Options options, const QPoint &offset,
|
void Utils::installSystemMenuHook(const WId windowId, const Options options, const QPoint &offset,
|
||||||
const IsWindowFixedSizeCallback &isWindowFixedSize)
|
const IsWindowFixedSizeCallback &isWindowFixedSize)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
Q_ASSERT(isWindowFixedSize);
|
Q_ASSERT(isWindowFixedSize);
|
||||||
if (!winId || !isWindowFixedSize) {
|
if (!windowId || !isWindowFixedSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QMutexLocker locker(&g_utilsHelper()->mutex);
|
QMutexLocker locker(&g_utilsHelper()->mutex);
|
||||||
if (g_utilsHelper()->data.contains(winId)) {
|
if (g_utilsHelper()->data.contains(windowId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
const auto originalWindowProc = reinterpret_cast<WNDPROC>(GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
|
const auto originalWindowProc = reinterpret_cast<WNDPROC>(GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
|
||||||
Q_ASSERT(originalWindowProc);
|
Q_ASSERT(originalWindowProc);
|
||||||
|
@ -1038,38 +1038,38 @@ void Utils::installSystemMenuHook(const WId winId, const Options options, const
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//triggerFrameChange(winId);
|
//triggerFrameChange(windowId);
|
||||||
Win32UtilsInternalData data = {};
|
Win32UtilsHelperData data = {};
|
||||||
data.originalWindowProc = originalWindowProc;
|
data.originalWindowProc = originalWindowProc;
|
||||||
data.options = options;
|
data.options = options;
|
||||||
data.offset = offset;
|
data.offset = offset;
|
||||||
data.isWindowFixedSize = isWindowFixedSize;
|
data.isWindowFixedSize = isWindowFixedSize;
|
||||||
g_utilsHelper()->data.insert(winId, data);
|
g_utilsHelper()->data.insert(windowId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::uninstallSystemMenuHook(const WId winId)
|
void Utils::uninstallSystemMenuHook(const WId windowId)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QMutexLocker locker(&g_utilsHelper()->mutex);
|
QMutexLocker locker(&g_utilsHelper()->mutex);
|
||||||
if (!g_utilsHelper()->data.contains(winId)) {
|
if (!g_utilsHelper()->data.contains(windowId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const Win32UtilsInternalData data = g_utilsHelper()->data.value(winId);
|
const Win32UtilsHelperData data = g_utilsHelper()->data.value(windowId);
|
||||||
Q_ASSERT(data.originalWindowProc);
|
Q_ASSERT(data.originalWindowProc);
|
||||||
if (!data.originalWindowProc) {
|
if (!data.originalWindowProc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(data.originalWindowProc)) == 0) {
|
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(data.originalWindowProc)) == 0) {
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//triggerFrameChange(winId);
|
//triggerFrameChange(windowId);
|
||||||
g_utilsHelper()->data.remove(winId);
|
g_utilsHelper()->data.remove(windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::sendMouseReleaseEvent()
|
void Utils::sendMouseReleaseEvent()
|
||||||
|
@ -1079,18 +1079,18 @@ void Utils::sendMouseReleaseEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::tryToBeCompatibleWithQtFramelessWindowHint(const WId winId,
|
void Utils::tryToBeCompatibleWithQtFramelessWindowHint(const WId windowId,
|
||||||
const GetWindowFlagsCallback &getWindowFlags,
|
const GetWindowFlagsCallback &getWindowFlags,
|
||||||
const SetWindowFlagsCallback &setWindowFlags,
|
const SetWindowFlagsCallback &setWindowFlags,
|
||||||
const bool enable)
|
const bool enable)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
Q_ASSERT(getWindowFlags);
|
Q_ASSERT(getWindowFlags);
|
||||||
Q_ASSERT(setWindowFlags);
|
Q_ASSERT(setWindowFlags);
|
||||||
if (!winId || !getWindowFlags || !setWindowFlags) {
|
if (!windowId || !getWindowFlags || !setWindowFlags) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
const LONG_PTR originalWindowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
|
const LONG_PTR originalWindowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
|
||||||
if (originalWindowStyle == 0) {
|
if (originalWindowStyle == 0) {
|
||||||
|
@ -1106,16 +1106,16 @@ void Utils::tryToBeCompatibleWithQtFramelessWindowHint(const WId winId,
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
triggerFrameChange(winId);
|
triggerFrameChange(windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::setAeroSnappingEnabled(const WId winId, const bool enable)
|
void Utils::setAeroSnappingEnabled(const WId windowId, const bool enable)
|
||||||
{
|
{
|
||||||
Q_ASSERT(winId);
|
Q_ASSERT(windowId);
|
||||||
if (!winId) {
|
if (!windowId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
const auto oldWindowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
|
const auto oldWindowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
|
||||||
if (oldWindowStyle == 0) {
|
if (oldWindowStyle == 0) {
|
||||||
|
@ -1134,7 +1134,7 @@ void Utils::setAeroSnappingEnabled(const WId winId, const bool enable)
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
triggerFrameChange(winId);
|
triggerFrameChange(windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::tryToEnableHighestDpiAwarenessLevel()
|
void Utils::tryToEnableHighestDpiAwarenessLevel()
|
||||||
|
|
|
@ -6,7 +6,6 @@ set(SOURCES
|
||||||
${INCLUDE_PREFIX}/framelesshelperquick_global.h
|
${INCLUDE_PREFIX}/framelesshelperquick_global.h
|
||||||
${INCLUDE_PREFIX}/framelessquickutils.h
|
${INCLUDE_PREFIX}/framelessquickutils.h
|
||||||
${INCLUDE_PREFIX}/framelesshelperimageprovider.h
|
${INCLUDE_PREFIX}/framelesshelperimageprovider.h
|
||||||
${INCLUDE_PREFIX}/framelessquickeventfilter.h
|
|
||||||
${INCLUDE_PREFIX}/framelesshelper_quick.h
|
${INCLUDE_PREFIX}/framelesshelper_quick.h
|
||||||
${INCLUDE_PREFIX}/framelessquickwindow.h
|
${INCLUDE_PREFIX}/framelessquickwindow.h
|
||||||
framelessquickwindow_p.h
|
framelessquickwindow_p.h
|
||||||
|
@ -14,7 +13,6 @@ set(SOURCES
|
||||||
framelesshelper_quick.cpp
|
framelesshelper_quick.cpp
|
||||||
framelessquickutils.cpp
|
framelessquickutils.cpp
|
||||||
framelesshelperimageprovider.cpp
|
framelesshelperimageprovider.cpp
|
||||||
framelessquickeventfilter.cpp
|
|
||||||
framelessquickwindow.cpp
|
framelessquickwindow.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include "framelessquickutils.h"
|
#include "framelessquickutils.h"
|
||||||
#include "framelessquickwindow.h"
|
#include "framelessquickwindow.h"
|
||||||
|
|
||||||
|
#ifndef QML_URL_EXPAND
|
||||||
|
# define QML_URL_EXPAND(fileName) \
|
||||||
|
QUrl(QStringLiteral("qrc:///org.wangwenx190.FramelessHelper/qml/%1.qml").arg(fileName))
|
||||||
|
#endif
|
||||||
|
|
||||||
// The "Q_INIT_RESOURCE()" macro can't be used inside a namespace,
|
// The "Q_INIT_RESOURCE()" macro can't be used inside a namespace,
|
||||||
// the official workaround is to wrap it into a global function
|
// the official workaround is to wrap it into a global function
|
||||||
// and call the wrapper function inside the namespace.
|
// and call the wrapper function inside the namespace.
|
||||||
|
@ -38,15 +43,6 @@ static inline void initResource()
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
[[nodiscard]] static inline QUrl getQmlFileUrl(const QString &qml)
|
|
||||||
{
|
|
||||||
Q_ASSERT(!qml.isEmpty());
|
|
||||||
if (qml.isEmpty()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return QUrl(QStringLiteral("qrc:///org.wangwenx190.FramelessHelper/qml/%1.qml").arg(qml));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
|
void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
|
||||||
{
|
{
|
||||||
Q_ASSERT(engine);
|
Q_ASSERT(engine);
|
||||||
|
@ -66,10 +62,10 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
|
||||||
qmlRegisterAnonymousType<QWindow>(FRAMELESSHELPER_QUICK_URI, 1);
|
qmlRegisterAnonymousType<QWindow>(FRAMELESSHELPER_QUICK_URI, 1);
|
||||||
#endif
|
#endif
|
||||||
initResource();
|
initResource();
|
||||||
qmlRegisterType(getQmlFileUrl(QStringLiteral("MinimizeButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "MinimizeButton");
|
qmlRegisterType(QML_URL_EXPAND(QStringLiteral("MinimizeButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "MinimizeButton");
|
||||||
qmlRegisterType(getQmlFileUrl(QStringLiteral("MaximizeButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "MaximizeButton");
|
qmlRegisterType(QML_URL_EXPAND(QStringLiteral("MaximizeButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "MaximizeButton");
|
||||||
qmlRegisterType(getQmlFileUrl(QStringLiteral("CloseButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "CloseButton");
|
qmlRegisterType(QML_URL_EXPAND(QStringLiteral("CloseButton")), FRAMELESSHELPER_QUICK_URI, 1, 0, "CloseButton");
|
||||||
qmlRegisterType(getQmlFileUrl(QStringLiteral("StandardTitleBar")), FRAMELESSHELPER_QUICK_URI, 1, 0, "StandardTitleBar");
|
qmlRegisterType(QML_URL_EXPAND(QStringLiteral("StandardTitleBar")), FRAMELESSHELPER_QUICK_URI, 1, 0, "StandardTitleBar");
|
||||||
}
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -56,6 +56,9 @@ using namespace Global;
|
||||||
if (str.compare(QStringLiteral("windowicon"), Qt::CaseInsensitive) == 0) {
|
if (str.compare(QStringLiteral("windowicon"), Qt::CaseInsensitive) == 0) {
|
||||||
return SystemButtonType::WindowIcon;
|
return SystemButtonType::WindowIcon;
|
||||||
}
|
}
|
||||||
|
if (str.compare(QStringLiteral("help"), Qt::CaseInsensitive) == 0) {
|
||||||
|
return SystemButtonType::Help;
|
||||||
|
}
|
||||||
if (str.compare(QStringLiteral("minimize"), Qt::CaseInsensitive) == 0) {
|
if (str.compare(QStringLiteral("minimize"), Qt::CaseInsensitive) == 0) {
|
||||||
return SystemButtonType::Minimize;
|
return SystemButtonType::Minimize;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,257 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "framelessquickeventfilter.h"
|
|
||||||
#include <QtCore/qmutex.h>
|
|
||||||
#include <QtCore/qhash.h>
|
|
||||||
#include <QtCore/qlist.h>
|
|
||||||
#include <QtQuick/qquickwindow.h>
|
|
||||||
#include <QtQuick/qquickitem.h>
|
|
||||||
#include <utils.h>
|
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
using namespace Global;
|
|
||||||
|
|
||||||
struct EventFilterDataInternal
|
|
||||||
{
|
|
||||||
FramelessQuickEventFilter *eventFilter = nullptr;
|
|
||||||
QQuickItem *titleBarItem = nullptr;
|
|
||||||
QList<QQuickItem *> hitTestVisibleItems = {};
|
|
||||||
FramelessHelperParams params = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EventFilterData
|
|
||||||
{
|
|
||||||
QMutex mutex = {};
|
|
||||||
QHash<WId, EventFilterDataInternal> data = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(EventFilterData, g_data)
|
|
||||||
|
|
||||||
[[nodiscard]] static inline bool isInTitleBarDraggableArea(QQuickWindow *window, const QPoint &pos)
|
|
||||||
{
|
|
||||||
Q_ASSERT(window);
|
|
||||||
if (!window) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const WId windowId = window->winId();
|
|
||||||
g_data()->mutex.lock();
|
|
||||||
if (!g_data()->data.contains(windowId)) {
|
|
||||||
g_data()->mutex.unlock();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const EventFilterDataInternal data = g_data()->data.value(windowId);
|
|
||||||
g_data()->mutex.unlock();
|
|
||||||
if (!data.titleBarItem) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto mapGeometryToScene = [](const QQuickItem * const item) -> QRect {
|
|
||||||
Q_ASSERT(item);
|
|
||||||
if (!item) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return QRect(item->mapToScene(QPointF(0.0, 0.0)).toPoint(), item->size().toSize());
|
|
||||||
};
|
|
||||||
QRegion region = mapGeometryToScene(data.titleBarItem);
|
|
||||||
if (!data.hitTestVisibleItems.isEmpty()) {
|
|
||||||
for (auto &&item : qAsConst(data.hitTestVisibleItems)) {
|
|
||||||
Q_ASSERT(item);
|
|
||||||
if (item) {
|
|
||||||
region -= mapGeometryToScene(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return region.contains(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
FramelessQuickEventFilter::FramelessQuickEventFilter(QObject *parent) : QObject(parent) {}
|
|
||||||
|
|
||||||
FramelessQuickEventFilter::~FramelessQuickEventFilter() = default;
|
|
||||||
|
|
||||||
void FramelessQuickEventFilter::addWindow(const FramelessHelperParams ¶ms)
|
|
||||||
{
|
|
||||||
Q_ASSERT(params.isValid());
|
|
||||||
if (!params.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_data()->mutex.lock();
|
|
||||||
if (g_data()->data.contains(params.windowId)) {
|
|
||||||
g_data()->mutex.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto data = EventFilterDataInternal{};
|
|
||||||
data.params = params;
|
|
||||||
const auto window = qobject_cast<QQuickWindow *>(params.getWindowHandle());
|
|
||||||
// Give it a parent so that it can be deleted even if we forget to do so.
|
|
||||||
data.eventFilter = new FramelessQuickEventFilter(window);
|
|
||||||
g_data()->data.insert(params.windowId, data);
|
|
||||||
g_data()->mutex.unlock();
|
|
||||||
window->installEventFilter(data.eventFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessQuickEventFilter::setTitleBarItem(QQuickWindow *window, QQuickItem *item)
|
|
||||||
{
|
|
||||||
Q_ASSERT(window);
|
|
||||||
Q_ASSERT(item);
|
|
||||||
if (!window || !item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const WId windowId = window->winId();
|
|
||||||
QMutexLocker locker(&g_data()->mutex);
|
|
||||||
if (!g_data()->data.contains(windowId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_data()->data[windowId].titleBarItem = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramelessQuickEventFilter::setHitTestVisible(QQuickWindow *window, QQuickItem *item)
|
|
||||||
{
|
|
||||||
Q_ASSERT(window);
|
|
||||||
Q_ASSERT(item);
|
|
||||||
if (!window || !item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const WId windowId = window->winId();
|
|
||||||
QMutexLocker locker(&g_data()->mutex);
|
|
||||||
if (!g_data()->data.contains(windowId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto &items = g_data()->data[windowId].hitTestVisibleItems;
|
|
||||||
static constexpr const bool visible = true;
|
|
||||||
const bool exists = items.contains(item);
|
|
||||||
if (visible && !exists) {
|
|
||||||
items.append(item);
|
|
||||||
}
|
|
||||||
if constexpr (!visible && exists) {
|
|
||||||
items.removeAll(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
|
|
||||||
{
|
|
||||||
Q_ASSERT(object);
|
|
||||||
Q_ASSERT(event);
|
|
||||||
if (!object || !event) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!object->isWindowType()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto window = qobject_cast<QQuickWindow *>(object);
|
|
||||||
if (!window) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const WId windowId = window->winId();
|
|
||||||
g_data()->mutex.lock();
|
|
||||||
if (!g_data()->data.contains(windowId)) {
|
|
||||||
g_data()->mutex.unlock();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const EventFilterDataInternal data = g_data()->data.value(windowId);
|
|
||||||
g_data()->mutex.unlock();
|
|
||||||
const QEvent::Type eventType = event->type();
|
|
||||||
if ((eventType != QEvent::MouseButtonPress) && (eventType != QEvent::MouseButtonRelease)
|
|
||||||
&& (eventType != QEvent::MouseButtonDblClick)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto mouseEvent = static_cast<QMouseEvent *>(event);
|
|
||||||
const Qt::MouseButton button = mouseEvent->button();
|
|
||||||
if ((button != Qt::LeftButton) && (button != Qt::RightButton)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
const QPoint scenePos = mouseEvent->scenePosition().toPoint();
|
|
||||||
#else
|
|
||||||
const QPoint scenePos = mouseEvent->windowPos().toPoint();
|
|
||||||
#endif
|
|
||||||
const QQuickWindow::Visibility visibility = window->visibility();
|
|
||||||
if ((visibility == QQuickWindow::Windowed)
|
|
||||||
&& ((scenePos.x() < kDefaultResizeBorderThickness)
|
|
||||||
|| (scenePos.x() >= (window->width() - kDefaultResizeBorderThickness))
|
|
||||||
|| (scenePos.y() < kDefaultResizeBorderThickness))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const bool titleBar = isInTitleBarDraggableArea(window, scenePos);
|
|
||||||
const bool isFixedSize = data.params.isWindowFixedSize();
|
|
||||||
switch (eventType) {
|
|
||||||
case QEvent::MouseButtonPress: {
|
|
||||||
if (data.params.options & Option::DisableDragging) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (button != Qt::LeftButton) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!titleBar) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Utils::startSystemMove(window);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case QEvent::MouseButtonRelease: {
|
|
||||||
if (data.params.options & Option::DisableSystemMenu) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (button != Qt::RightButton) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!titleBar) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
const QPoint globalPos = mouseEvent->globalPosition().toPoint();
|
|
||||||
#else
|
|
||||||
const QPoint globalPos = mouseEvent->globalPos();
|
|
||||||
#endif
|
|
||||||
const QPoint nativePos = QPointF(QPointF(globalPos) * window->effectiveDevicePixelRatio()).toPoint();
|
|
||||||
Utils::showSystemMenu(windowId, nativePos, data.params.options,
|
|
||||||
data.params.systemMenuOffset, data.params.isWindowFixedSize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case QEvent::MouseButtonDblClick: {
|
|
||||||
if ((data.params.options & Option::NoDoubleClickMaximizeToggle) || isFixedSize) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (button != Qt::LeftButton) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!titleBar) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((visibility == QQuickWindow::Maximized)
|
|
||||||
|| ((data.params.options & Option::DontTreatFullScreenAsZoomed)
|
|
||||||
? false : (visibility == QQuickWindow::FullScreen))) {
|
|
||||||
window->showNormal();
|
|
||||||
} else {
|
|
||||||
window->showMaximized();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
|
|
@ -1,25 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../include/FramelessHelper/Quick/framelessquickeventfilter.h"
|
|
|
@ -29,37 +29,62 @@
|
||||||
#include <QtQuick/private/qquickanchors_p.h>
|
#include <QtQuick/private/qquickanchors_p.h>
|
||||||
#include <framelesswindowsmanager.h>
|
#include <framelesswindowsmanager.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
#include "framelessquickeventfilter.h"
|
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q, const Options options) : QObject(q)
|
static constexpr const char QT_QUICKITEM_CLASS_NAME[] = "QQuickItem";
|
||||||
|
|
||||||
|
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q, const UserSettings &settings) : QObject(q)
|
||||||
{
|
{
|
||||||
Q_ASSERT(q);
|
Q_ASSERT(q);
|
||||||
if (!q) {
|
if (!q) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
q_ptr = q;
|
q_ptr = q;
|
||||||
m_params.options = options;
|
m_settings = settings;
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessQuickWindowPrivate::~FramelessQuickWindowPrivate() = default;
|
FramelessQuickWindowPrivate::~FramelessQuickWindowPrivate() = default;
|
||||||
|
|
||||||
|
bool FramelessQuickWindowPrivate::isHidden() const
|
||||||
|
{
|
||||||
|
Q_Q(const FramelessQuickWindow);
|
||||||
|
return (q->visibility() == FramelessQuickWindow::Hidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindowPrivate::isNormal() const
|
||||||
|
{
|
||||||
|
Q_Q(const FramelessQuickWindow);
|
||||||
|
return (q->visibility() == FramelessQuickWindow::Windowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindowPrivate::isMinimized() const
|
||||||
|
{
|
||||||
|
Q_Q(const FramelessQuickWindow);
|
||||||
|
return (q->visibility() == FramelessQuickWindow::Minimized);
|
||||||
|
}
|
||||||
|
|
||||||
bool FramelessQuickWindowPrivate::isZoomed() const
|
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_params.options & Option::DontTreatFullScreenAsZoomed)
|
((m_settings.options & Option::DontTreatFullScreenAsZoomed)
|
||||||
? false : (visibility == FramelessQuickWindow::FullScreen)));
|
? false : (visibility == FramelessQuickWindow::FullScreen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindowPrivate::isFullScreen() const
|
||||||
|
{
|
||||||
|
Q_Q(const FramelessQuickWindow);
|
||||||
|
return (q->visibility() == FramelessQuickWindow::FullScreen);
|
||||||
|
}
|
||||||
|
|
||||||
bool FramelessQuickWindowPrivate::isFixedSize() const
|
bool FramelessQuickWindowPrivate::isFixedSize() const
|
||||||
{
|
{
|
||||||
if (m_params.options & Option::DisableResizing) {
|
if (m_settings.options & Option::DisableResizing) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Q_Q(const FramelessQuickWindow);
|
Q_Q(const FramelessQuickWindow);
|
||||||
|
@ -90,8 +115,10 @@ void FramelessQuickWindowPrivate::setTitleBarItem(QQuickItem *item)
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Q_Q(FramelessQuickWindow);
|
if (m_titleBarItem == item) {
|
||||||
FramelessQuickEventFilter::setTitleBarItem(q, item);
|
return;
|
||||||
|
}
|
||||||
|
m_titleBarItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickWindowPrivate::setHitTestVisible(QQuickItem *item)
|
void FramelessQuickWindowPrivate::setHitTestVisible(QQuickItem *item)
|
||||||
|
@ -100,8 +127,14 @@ void FramelessQuickWindowPrivate::setHitTestVisible(QQuickItem *item)
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Q_Q(FramelessQuickWindow);
|
static constexpr const bool visible = true;
|
||||||
FramelessQuickEventFilter::setHitTestVisible(q, item);
|
const bool exists = m_hitTestVisibleItems.contains(item);
|
||||||
|
if (visible && !exists) {
|
||||||
|
m_hitTestVisibleItems.append(item);
|
||||||
|
}
|
||||||
|
if constexpr (!visible && exists) {
|
||||||
|
m_hitTestVisibleItems.removeAll(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickWindowPrivate::moveToDesktopCenter()
|
void FramelessQuickWindowPrivate::moveToDesktopCenter()
|
||||||
|
@ -132,6 +165,19 @@ void FramelessQuickWindowPrivate::setFixedSize(const bool value, const bool forc
|
||||||
Q_EMIT q->fixedSizeChanged();
|
Q_EMIT q->fixedSizeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindowPrivate::bringToFront()
|
||||||
|
{
|
||||||
|
Q_Q(FramelessQuickWindow);
|
||||||
|
if (isHidden()) {
|
||||||
|
q->show();
|
||||||
|
}
|
||||||
|
if (isMinimized()) {
|
||||||
|
q->showNormal(); // ### FIXME !!!
|
||||||
|
}
|
||||||
|
q->raise();
|
||||||
|
q->requestActivate();
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessQuickWindowPrivate::showMinimized2()
|
void FramelessQuickWindowPrivate::showMinimized2()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
|
@ -165,11 +211,10 @@ void FramelessQuickWindowPrivate::toggleFullScreen()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Q_Q(FramelessQuickWindow);
|
Q_Q(FramelessQuickWindow);
|
||||||
const QWindow::Visibility visibility = q->visibility();
|
if (isFullScreen()) {
|
||||||
if (visibility == QWindow::FullScreen) {
|
|
||||||
q->setVisibility(m_savedVisibility);
|
q->setVisibility(m_savedVisibility);
|
||||||
} else {
|
} else {
|
||||||
m_savedVisibility = visibility;
|
m_savedVisibility = q->visibility();
|
||||||
q->showFullScreen();
|
q->showFullScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,14 +223,10 @@ void FramelessQuickWindowPrivate::showSystemMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
Q_Q(FramelessQuickWindow);
|
Q_Q(FramelessQuickWindow);
|
||||||
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
const QPoint globalPos = q->mapToGlobal(pos);
|
const QPoint globalPos = q->mapToGlobal(pos);
|
||||||
# else
|
|
||||||
const QPoint globalPos = q->mapToGlobal(pos);
|
|
||||||
# endif
|
|
||||||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->effectiveDevicePixelRatio()).toPoint();
|
const QPoint nativePos = QPointF(QPointF(globalPos) * q->effectiveDevicePixelRatio()).toPoint();
|
||||||
Utils::showSystemMenu(m_params.windowId, nativePos, m_params.options,
|
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.options,
|
||||||
m_params.systemMenuOffset, m_params.isWindowFixedSize);
|
m_settings.systemMenuOffset, m_params.isWindowFixedSize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,76 +281,285 @@ void FramelessQuickWindowPrivate::initialize()
|
||||||
m_params.getWindowState = [q]() -> Qt::WindowState { return q->windowState(); };
|
m_params.getWindowState = [q]() -> Qt::WindowState { return q->windowState(); };
|
||||||
m_params.setWindowState = [q](const Qt::WindowState state) -> void { q->setWindowState(state); };
|
m_params.setWindowState = [q](const Qt::WindowState state) -> void { q->setWindowState(state); };
|
||||||
m_params.getWindowHandle = [q]() -> QWindow * { return q; };
|
m_params.getWindowHandle = [q]() -> QWindow * { return q; };
|
||||||
|
m_params.windowToScreen = [q](const QPoint &pos) -> QPoint { return q->mapToGlobal(pos); };
|
||||||
|
m_params.screenToWindow = [q](const QPoint &pos) -> QPoint { return q->mapFromGlobal(pos); };
|
||||||
|
m_params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { return isInSystemButtons(pos, button); };
|
||||||
|
m_params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); };
|
||||||
|
m_params.getWindowDevicePixelRatio = [q]() -> qreal { return q->effectiveDevicePixelRatio(); };
|
||||||
FramelessWindowsManager * const manager = FramelessWindowsManager::instance();
|
FramelessWindowsManager * const manager = FramelessWindowsManager::instance();
|
||||||
manager->addWindow(m_params);
|
manager->addWindow(m_settings, m_params);
|
||||||
FramelessQuickEventFilter::addWindow(m_params);
|
QQuickItem * const rootItem = q->contentItem();
|
||||||
#ifdef Q_OS_WINDOWS
|
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
||||||
if (isFrameBorderVisible()) {
|
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||||
QQuickItem * const rootItem = q->contentItem();
|
const bool frameBorderVisible = shouldDrawFrameBorder();
|
||||||
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
if (frameBorderVisible) {
|
||||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
|
||||||
updateTopBorderHeight();
|
updateTopBorderHeight();
|
||||||
updateTopBorderColor();
|
updateTopBorderColor();
|
||||||
connect(q, &FramelessQuickWindow::visibilityChanged, this, [this, q](){
|
|
||||||
updateTopBorderHeight();
|
|
||||||
Q_EMIT q->zoomedChanged();
|
|
||||||
});
|
|
||||||
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
|
||||||
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this, q](){
|
|
||||||
updateTopBorderColor();
|
|
||||||
Q_EMIT q->frameBorderColorChanged();
|
|
||||||
});
|
|
||||||
const auto topBorderAnchors = new QQuickAnchors(m_topBorderRectangle.data(), m_topBorderRectangle.data());
|
|
||||||
topBorderAnchors->setTop(rootItemPrivate->top());
|
|
||||||
topBorderAnchors->setLeft(rootItemPrivate->left());
|
|
||||||
topBorderAnchors->setRight(rootItemPrivate->right());
|
|
||||||
}
|
}
|
||||||
#endif
|
connect(q, &FramelessQuickWindow::visibilityChanged, this, [this, q, frameBorderVisible](){
|
||||||
if (m_params.options & Option::DisableResizing) {
|
if (frameBorderVisible) {
|
||||||
|
updateTopBorderHeight();
|
||||||
|
}
|
||||||
|
Q_EMIT q->hiddenChanged();
|
||||||
|
Q_EMIT q->normalChanged();
|
||||||
|
Q_EMIT q->minimizedChanged();
|
||||||
|
Q_EMIT q->zoomedChanged();
|
||||||
|
Q_EMIT q->fullScreenChanged();
|
||||||
|
});
|
||||||
|
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||||
|
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this, q, frameBorderVisible](){
|
||||||
|
if (frameBorderVisible) {
|
||||||
|
updateTopBorderColor();
|
||||||
|
}
|
||||||
|
Q_EMIT q->frameBorderColorChanged();
|
||||||
|
});
|
||||||
|
m_topBorderAnchors.reset(new QQuickAnchors(m_topBorderRectangle.data(), m_topBorderRectangle.data()));
|
||||||
|
m_topBorderAnchors->setTop(rootItemPrivate->top());
|
||||||
|
m_topBorderAnchors->setLeft(rootItemPrivate->left());
|
||||||
|
m_topBorderAnchors->setRight(rootItemPrivate->right());
|
||||||
|
if (m_settings.options & Option::DisableResizing) {
|
||||||
setFixedSize(true, true);
|
setFixedSize(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessQuickWindowPrivate::isFrameBorderVisible() const
|
QRect FramelessQuickWindowPrivate::mapItemGeometryToScene(const QQuickItem * const item) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(item);
|
||||||
|
if (!item) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const QPointF originPoint = item->mapToScene(QPointF(0.0, 0.0));
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||||
|
const QSizeF size = item->size();
|
||||||
|
#else
|
||||||
|
const QSizeF size = {item->width(), item->height()};
|
||||||
|
#endif
|
||||||
|
return QRectF(originPoint, size).toRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindowPrivate::isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(button);
|
||||||
|
if (!button) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*button = SystemButtonType::Unknown;
|
||||||
|
if (!m_settings.minimizeButton || !m_settings.maximizeButton || !m_settings.closeButton) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_settings.minimizeButton->inherits(QT_QUICKITEM_CLASS_NAME)
|
||||||
|
|| !m_settings.maximizeButton->inherits(QT_QUICKITEM_CLASS_NAME)
|
||||||
|
|| !m_settings.closeButton->inherits(QT_QUICKITEM_CLASS_NAME)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto minBtn = qobject_cast<QQuickItem *>(m_settings.minimizeButton);
|
||||||
|
if (mapItemGeometryToScene(minBtn).contains(pos)) {
|
||||||
|
*button = SystemButtonType::Minimize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto maxBtn = qobject_cast<QQuickItem *>(m_settings.maximizeButton);
|
||||||
|
if (mapItemGeometryToScene(maxBtn).contains(pos)) {
|
||||||
|
*button = SystemButtonType::Maximize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto closeBtn = qobject_cast<QQuickItem *>(m_settings.closeButton);
|
||||||
|
if (mapItemGeometryToScene(closeBtn).contains(pos)) {
|
||||||
|
*button = SystemButtonType::Close;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindowPrivate::isInTitleBarDraggableArea(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
if (!m_titleBarItem) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QRegion region = mapItemGeometryToScene(m_titleBarItem);
|
||||||
|
if (!m_hitTestVisibleItems.isEmpty()) {
|
||||||
|
for (auto &&item : qAsConst(m_hitTestVisibleItems)) {
|
||||||
|
Q_ASSERT(item);
|
||||||
|
if (item) {
|
||||||
|
region -= mapItemGeometryToScene(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return region.contains(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindowPrivate::shouldDrawFrameBorder() const
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater());
|
return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater()
|
||||||
|
&& isNormal() && !(m_settings.options & Option::DontDrawTopWindowFrameBorder));
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickWindowPrivate::updateTopBorderColor()
|
bool FramelessQuickWindowPrivate::shouldIgnoreMouseEvents(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
if (!isFrameBorderVisible()) {
|
Q_Q(const FramelessQuickWindow);
|
||||||
|
return (isNormal() && ((pos.x() < kDefaultResizeBorderThickness)
|
||||||
|
|| (pos.x() >= (q->width() - kDefaultResizeBorderThickness))
|
||||||
|
|| (pos.y() < kDefaultResizeBorderThickness)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindowPrivate::showEventHandler(QShowEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (m_windowExposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_windowExposed = true;
|
||||||
|
if (m_settings.options & Option::DontMoveWindowToDesktopCenter) {
|
||||||
|
if (!m_settings.startupPosition.isNull()) {
|
||||||
|
m_params.setWindowPosition(m_settings.startupPosition);
|
||||||
|
}
|
||||||
|
if (!m_settings.startupSize.isEmpty()) {
|
||||||
|
m_params.setWindowSize(m_settings.startupSize);
|
||||||
|
}
|
||||||
|
if (m_settings.startupState != Qt::WindowNoState) {
|
||||||
|
m_params.setWindowState(m_settings.startupState);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
moveToDesktopCenter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindowPrivate::mousePressEventHandler(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_settings.options & Option::DisableDragging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event->button() != Qt::LeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
const QPoint scenePos = event->scenePosition().toPoint();
|
||||||
|
#else
|
||||||
|
const QPoint scenePos = event->windowPos().toPoint();
|
||||||
|
#endif
|
||||||
|
if (shouldIgnoreMouseEvents(scenePos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startSystemMove2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindowPrivate::mouseReleaseEventHandler(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_settings.options & Option::DisableSystemMenu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event->button() != Qt::RightButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
const QPoint scenePos = event->scenePosition().toPoint();
|
||||||
|
#else
|
||||||
|
const QPoint scenePos = event->windowPos().toPoint();
|
||||||
|
#endif
|
||||||
|
if (shouldIgnoreMouseEvents(scenePos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showSystemMenu(scenePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindowPrivate::mouseDoubleClickEventHandler(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((m_settings.options & Option::NoDoubleClickMaximizeToggle) || isFixedSize()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event->button() != Qt::LeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
const QPoint scenePos = event->scenePosition().toPoint();
|
||||||
|
#else
|
||||||
|
const QPoint scenePos = event->windowPos().toPoint();
|
||||||
|
#endif
|
||||||
|
if (shouldIgnoreMouseEvents(scenePos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toggleMaximize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindowPrivate::updateTopBorderColor()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
m_topBorderRectangle->setColor(getFrameBorderColor());
|
m_topBorderRectangle->setColor(getFrameBorderColor());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickWindowPrivate::updateTopBorderHeight()
|
void FramelessQuickWindowPrivate::updateTopBorderHeight()
|
||||||
{
|
{
|
||||||
if (!isFrameBorderVisible()) {
|
#ifdef Q_OS_WINDOWS
|
||||||
return;
|
const qreal newHeight = (isNormal() ? 1.0 : 0.0);
|
||||||
}
|
|
||||||
Q_Q(FramelessQuickWindow);
|
|
||||||
const qreal newHeight = ((q->visibility() == FramelessQuickWindow::Windowed) ? 1.0 : 0.0);
|
|
||||||
m_topBorderRectangle->setHeight(newHeight);
|
m_topBorderRectangle->setHeight(newHeight);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent, const Options options) : QQuickWindow(parent)
|
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent, const UserSettings &settings) : QQuickWindow(parent)
|
||||||
{
|
{
|
||||||
d_ptr.reset(new FramelessQuickWindowPrivate(this, options));
|
d_ptr.reset(new FramelessQuickWindowPrivate(this, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessQuickWindow::~FramelessQuickWindow() = default;
|
FramelessQuickWindow::~FramelessQuickWindow() = default;
|
||||||
|
|
||||||
bool FramelessQuickWindow::zoomed() const
|
bool FramelessQuickWindow::isHidden() const
|
||||||
|
{
|
||||||
|
Q_D(const FramelessQuickWindow);
|
||||||
|
return d->isHidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindow::isNormal() const
|
||||||
|
{
|
||||||
|
Q_D(const FramelessQuickWindow);
|
||||||
|
return d->isNormal();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindow::isMinimized() const
|
||||||
|
{
|
||||||
|
Q_D(const FramelessQuickWindow);
|
||||||
|
return d->isMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindow::isZoomed() const
|
||||||
{
|
{
|
||||||
Q_D(const FramelessQuickWindow);
|
Q_D(const FramelessQuickWindow);
|
||||||
return d->isZoomed();
|
return d->isZoomed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickWindow::isFullScreen() const
|
||||||
|
{
|
||||||
|
Q_D(const FramelessQuickWindow);
|
||||||
|
return d->isFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
bool FramelessQuickWindow::fixedSize() const
|
bool FramelessQuickWindow::fixedSize() const
|
||||||
{
|
{
|
||||||
Q_D(const FramelessQuickWindow);
|
Q_D(const FramelessQuickWindow);
|
||||||
|
@ -354,6 +604,40 @@ void FramelessQuickWindow::moveToDesktopCenter()
|
||||||
d->moveToDesktopCenter();
|
d->moveToDesktopCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindow::bringToFront()
|
||||||
|
{
|
||||||
|
Q_D(FramelessQuickWindow);
|
||||||
|
d->bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindow::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
QQuickWindow::showEvent(event);
|
||||||
|
Q_D(FramelessQuickWindow);
|
||||||
|
d->showEventHandler(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindow::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QQuickWindow::mousePressEvent(event);
|
||||||
|
Q_D(FramelessQuickWindow);
|
||||||
|
d->mousePressEventHandler(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindow::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QQuickWindow::mouseReleaseEvent(event);
|
||||||
|
Q_D(FramelessQuickWindow);
|
||||||
|
d->mouseReleaseEventHandler(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QQuickWindow::mouseDoubleClickEvent(event);
|
||||||
|
Q_D(FramelessQuickWindow);
|
||||||
|
d->mouseDoubleClickEventHandler(event);
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessQuickWindow::showMinimized2()
|
void FramelessQuickWindow::showMinimized2()
|
||||||
{
|
{
|
||||||
Q_D(FramelessQuickWindow);
|
Q_D(FramelessQuickWindow);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
class QQuickRectangle;
|
class QQuickRectangle;
|
||||||
|
class QQuickAnchors;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
@ -44,13 +45,22 @@ 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::Options options);
|
explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q, const Global::UserSettings &settings = {});
|
||||||
~FramelessQuickWindowPrivate() override;
|
~FramelessQuickWindowPrivate() override;
|
||||||
|
|
||||||
|
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 isZoomed() const;
|
Q_INVOKABLE Q_NODISCARD bool isZoomed() const;
|
||||||
|
Q_INVOKABLE Q_NODISCARD bool isFullScreen() const;
|
||||||
Q_INVOKABLE Q_NODISCARD bool isFixedSize() const;
|
Q_INVOKABLE Q_NODISCARD bool isFixedSize() const;
|
||||||
|
|
||||||
Q_INVOKABLE Q_NODISCARD QColor getFrameBorderColor() const;
|
Q_INVOKABLE Q_NODISCARD QColor getFrameBorderColor() const;
|
||||||
Q_INVOKABLE Q_NODISCARD bool isFrameBorderVisible() const;
|
|
||||||
|
Q_INVOKABLE void showEventHandler(QShowEvent *event);
|
||||||
|
Q_INVOKABLE void mousePressEventHandler(QMouseEvent *event);
|
||||||
|
Q_INVOKABLE void mouseReleaseEventHandler(QMouseEvent *event);
|
||||||
|
Q_INVOKABLE void mouseDoubleClickEventHandler(QMouseEvent *event);
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void showMinimized2();
|
void showMinimized2();
|
||||||
|
@ -63,9 +73,15 @@ public Q_SLOTS:
|
||||||
void setHitTestVisible(QQuickItem *item);
|
void setHitTestVisible(QQuickItem *item);
|
||||||
void moveToDesktopCenter();
|
void moveToDesktopCenter();
|
||||||
void setFixedSize(const bool value, const bool force = false);
|
void setFixedSize(const bool value, const bool force = false);
|
||||||
|
void bringToFront();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize();
|
void initialize();
|
||||||
|
Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const;
|
||||||
|
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const;
|
||||||
|
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
|
||||||
|
Q_NODISCARD bool shouldDrawFrameBorder() const;
|
||||||
|
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void updateTopBorderColor();
|
void updateTopBorderColor();
|
||||||
|
@ -75,8 +91,13 @@ private:
|
||||||
FramelessQuickWindow *q_ptr = nullptr;
|
FramelessQuickWindow *q_ptr = nullptr;
|
||||||
bool m_initialized = false;
|
bool m_initialized = false;
|
||||||
QScopedPointer<QQuickRectangle> m_topBorderRectangle;
|
QScopedPointer<QQuickRectangle> m_topBorderRectangle;
|
||||||
|
QScopedPointer<QQuickAnchors> m_topBorderAnchors;
|
||||||
QWindow::Visibility m_savedVisibility = QWindow::Windowed;
|
QWindow::Visibility m_savedVisibility = QWindow::Windowed;
|
||||||
Global::FramelessHelperParams m_params = {};
|
Global::UserSettings m_settings = {};
|
||||||
|
Global::SystemParameters m_params = {};
|
||||||
|
bool m_windowExposed = false;
|
||||||
|
QQuickItem *m_titleBarItem = nullptr;
|
||||||
|
QList<QQuickItem *> m_hitTestVisibleItems = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -29,9 +29,9 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
FramelessMainWindow::FramelessMainWindow(QWidget *parent, const Qt::WindowFlags flags, const Options options) : QMainWindow(parent, flags)
|
FramelessMainWindow::FramelessMainWindow(QWidget *parent, const Qt::WindowFlags flags, const UserSettings &settings) : QMainWindow(parent, flags)
|
||||||
{
|
{
|
||||||
m_helper.reset(new FramelessWidgetsHelper(this, options));
|
m_helper.reset(new FramelessWidgetsHelper(this, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessMainWindow::~FramelessMainWindow() = default;
|
FramelessMainWindow::~FramelessMainWindow() = default;
|
||||||
|
@ -86,6 +86,32 @@ void FramelessMainWindow::moveToDesktopCenter()
|
||||||
m_helper->moveToDesktopCenter();
|
m_helper->moveToDesktopCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::bringToFront()
|
||||||
|
{
|
||||||
|
m_helper->bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::showSystemMenu(const QPoint &pos)
|
||||||
|
{
|
||||||
|
m_helper->showSystemMenu(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::startSystemMove2()
|
||||||
|
{
|
||||||
|
m_helper->startSystemMove2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::startSystemResize2(const Qt::Edges edges)
|
||||||
|
{
|
||||||
|
m_helper->startSystemResize2(edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
QMainWindow::showEvent(event);
|
||||||
|
m_helper->showEventHandler(event);
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessMainWindow::changeEvent(QEvent *event)
|
void FramelessMainWindow::changeEvent(QEvent *event)
|
||||||
{
|
{
|
||||||
QMainWindow::changeEvent(event);
|
QMainWindow::changeEvent(event);
|
||||||
|
|
|
@ -29,9 +29,9 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
FramelessWidget::FramelessWidget(QWidget *parent, const Options options) : QWidget(parent)
|
FramelessWidget::FramelessWidget(QWidget *parent, const UserSettings &settings) : QWidget(parent)
|
||||||
{
|
{
|
||||||
m_helper.reset(new FramelessWidgetsHelper(this, options));
|
m_helper.reset(new FramelessWidgetsHelper(this, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessWidget::~FramelessWidget() = default;
|
FramelessWidget::~FramelessWidget() = default;
|
||||||
|
@ -96,6 +96,32 @@ void FramelessWidget::moveToDesktopCenter()
|
||||||
m_helper->moveToDesktopCenter();
|
m_helper->moveToDesktopCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::bringToFront()
|
||||||
|
{
|
||||||
|
m_helper->bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::showSystemMenu(const QPoint &pos)
|
||||||
|
{
|
||||||
|
m_helper->showSystemMenu(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::startSystemMove2()
|
||||||
|
{
|
||||||
|
m_helper->startSystemMove2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::startSystemResize2(const Qt::Edges edges)
|
||||||
|
{
|
||||||
|
m_helper->startSystemResize2(edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
QWidget::showEvent(event);
|
||||||
|
m_helper->showEventHandler(event);
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessWidget::changeEvent(QEvent *event)
|
void FramelessWidget::changeEvent(QEvent *event)
|
||||||
{
|
{
|
||||||
QWidget::changeEvent(event);
|
QWidget::changeEvent(event);
|
||||||
|
|
|
@ -54,14 +54,14 @@ QPushButton:pressed {
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
|
||||||
FramelessWidgetsHelper::FramelessWidgetsHelper(QWidget *q, const Options options) : QObject(q)
|
FramelessWidgetsHelper::FramelessWidgetsHelper(QWidget *q, const UserSettings &settings) : QObject(q)
|
||||||
{
|
{
|
||||||
Q_ASSERT(q);
|
Q_ASSERT(q);
|
||||||
if (!q) {
|
if (!q) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->q = q;
|
this->q = q;
|
||||||
m_params.options = options;
|
m_settings = settings;
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@ bool FramelessWidgetsHelper::isNormal() const
|
||||||
|
|
||||||
bool FramelessWidgetsHelper::isZoomed() const
|
bool FramelessWidgetsHelper::isZoomed() const
|
||||||
{
|
{
|
||||||
return (q->isMaximized() || ((m_params.options & Option::DontTreatFullScreenAsZoomed) ? false : q->isFullScreen()));
|
return (q->isMaximized() || ((m_settings.options & Option::DontTreatFullScreenAsZoomed) ? false : q->isFullScreen()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessWidgetsHelper::isFixedSize() const
|
bool FramelessWidgetsHelper::isFixedSize() const
|
||||||
{
|
{
|
||||||
if (m_params.options & Option::DisableResizing) {
|
if (m_settings.options & Option::DisableResizing) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (q->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) {
|
if (q->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) {
|
||||||
|
@ -124,7 +124,7 @@ void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
|
||||||
if (m_userTitleBarWidget == widget) {
|
if (m_userTitleBarWidget == widget) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_params.options & Option::UseStandardWindowLayout) {
|
if (m_settings.options & Option::UseStandardWindowLayout) {
|
||||||
if (m_systemTitleBarWidget && m_systemTitleBarWidget->isVisible()) {
|
if (m_systemTitleBarWidget && m_systemTitleBarWidget->isVisible()) {
|
||||||
m_mainLayout->removeWidget(m_systemTitleBarWidget);
|
m_mainLayout->removeWidget(m_systemTitleBarWidget);
|
||||||
m_systemTitleBarWidget->hide();
|
m_systemTitleBarWidget->hide();
|
||||||
|
@ -152,7 +152,7 @@ void FramelessWidgetsHelper::setContentWidget(QWidget *widget)
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(m_params.options & Option::UseStandardWindowLayout)) {
|
if (!(m_settings.options & Option::UseStandardWindowLayout)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_userContentWidget == widget) {
|
if (m_userContentWidget == widget) {
|
||||||
|
@ -188,6 +188,31 @@ void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelper::showEventHandler(QShowEvent *event)
|
||||||
|
{
|
||||||
|
Q_ASSERT(event);
|
||||||
|
if (!event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_windowExposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_windowExposed = true;
|
||||||
|
if (m_settings.options & Option::DontMoveWindowToDesktopCenter) {
|
||||||
|
if (!m_settings.startupPosition.isNull()) {
|
||||||
|
m_params.setWindowPosition(m_settings.startupPosition);
|
||||||
|
}
|
||||||
|
if (!m_settings.startupSize.isEmpty()) {
|
||||||
|
m_params.setWindowSize(m_settings.startupSize);
|
||||||
|
}
|
||||||
|
if (m_settings.startupState != Qt::WindowNoState) {
|
||||||
|
m_params.setWindowState(m_settings.startupState);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
moveToDesktopCenter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelper::changeEventHandler(QEvent *event)
|
void FramelessWidgetsHelper::changeEventHandler(QEvent *event)
|
||||||
{
|
{
|
||||||
Q_ASSERT(event);
|
Q_ASSERT(event);
|
||||||
|
@ -198,7 +223,7 @@ void FramelessWidgetsHelper::changeEventHandler(QEvent *event)
|
||||||
if ((type != QEvent::WindowStateChange) && (type != QEvent::ActivationChange)) {
|
if ((type != QEvent::WindowStateChange) && (type != QEvent::ActivationChange)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bool standardLayout = (m_params.options & Option::UseStandardWindowLayout);
|
const bool standardLayout = (m_settings.options & Option::UseStandardWindowLayout);
|
||||||
if (type == QEvent::WindowStateChange) {
|
if (type == QEvent::WindowStateChange) {
|
||||||
if (standardLayout) {
|
if (standardLayout) {
|
||||||
if (isZoomed()) {
|
if (isZoomed()) {
|
||||||
|
@ -241,7 +266,7 @@ void FramelessWidgetsHelper::mousePressEventHandler(QMouseEvent *event)
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_params.options & Option::DisableDragging) {
|
if (m_settings.options & Option::DisableDragging) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event->button() != Qt::LeftButton) {
|
if (event->button() != Qt::LeftButton) {
|
||||||
|
@ -258,7 +283,7 @@ void FramelessWidgetsHelper::mousePressEventHandler(QMouseEvent *event)
|
||||||
if (!isInTitleBarDraggableArea(scenePos)) {
|
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Utils::startSystemMove(m_window);
|
startSystemMove2();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
|
void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
|
||||||
|
@ -267,7 +292,7 @@ void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_params.options & Option::DisableSystemMenu) {
|
if (m_settings.options & Option::DisableSystemMenu) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event->button() != Qt::RightButton) {
|
if (event->button() != Qt::RightButton) {
|
||||||
|
@ -284,16 +309,7 @@ void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
|
||||||
if (!isInTitleBarDraggableArea(scenePos)) {
|
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef Q_OS_WINDOWS
|
showSystemMenu(scenePos);
|
||||||
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
const QPoint globalPos = event->globalPosition().toPoint();
|
|
||||||
# else
|
|
||||||
const QPoint globalPos = event->globalPos();
|
|
||||||
# endif
|
|
||||||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->devicePixelRatioF()).toPoint();
|
|
||||||
Utils::showSystemMenu(m_params.windowId, nativePos, m_params.options,
|
|
||||||
m_params.systemMenuOffset, m_params.isWindowFixedSize);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event)
|
void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event)
|
||||||
|
@ -302,7 +318,7 @@ void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event)
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((m_params.options & Option::NoDoubleClickMaximizeToggle) || isFixedSize()) {
|
if ((m_settings.options & Option::NoDoubleClickMaximizeToggle) || isFixedSize()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event->button() != Qt::LeftButton) {
|
if (event->button() != Qt::LeftButton) {
|
||||||
|
@ -365,39 +381,54 @@ void FramelessWidgetsHelper::initialize()
|
||||||
m_params.getWindowState = [this]() -> Qt::WindowState { return Utils::windowStatesToWindowState(q->windowState()); };
|
m_params.getWindowState = [this]() -> Qt::WindowState { return Utils::windowStatesToWindowState(q->windowState()); };
|
||||||
m_params.setWindowState = [this](const Qt::WindowState state) -> void { q->setWindowState(state); };
|
m_params.setWindowState = [this](const Qt::WindowState state) -> void { q->setWindowState(state); };
|
||||||
m_params.getWindowHandle = [this]() -> QWindow * { return m_window; };
|
m_params.getWindowHandle = [this]() -> QWindow * { return m_window; };
|
||||||
if (m_params.options & Option::UseStandardWindowLayout) {
|
m_params.windowToScreen = [this](const QPoint &pos) -> QPoint { return q->mapToGlobal(pos); };
|
||||||
|
m_params.screenToWindow = [this](const QPoint &pos) -> QPoint { return q->mapFromGlobal(pos); };
|
||||||
|
m_params.isInsideSystemButtons = [this](const QPoint &pos, SystemButtonType *button) -> bool { return isInSystemButtons(pos, button); };
|
||||||
|
m_params.isInsideTitleBarDraggableArea = [this](const QPoint &pos) -> bool { return isInTitleBarDraggableArea(pos); };
|
||||||
|
m_params.getWindowDevicePixelRatio = [this]() -> qreal { return q->devicePixelRatioF(); };
|
||||||
|
if (m_settings.options & Option::UseStandardWindowLayout) {
|
||||||
if (q->inherits(QT_MAINWINDOW_CLASS_NAME)) {
|
if (q->inherits(QT_MAINWINDOW_CLASS_NAME)) {
|
||||||
m_params.options &= ~Options(Option::UseStandardWindowLayout);
|
m_settings.options &= ~Options(Option::UseStandardWindowLayout);
|
||||||
qWarning() << "\"Option::UseStandardWindowLayout\" is not compatible with QMainWindow and it's subclasses."
|
qWarning() << "\"Option::UseStandardWindowLayout\" is not compatible with QMainWindow and it's subclasses."
|
||||||
" Enabling this option will mess up with your main window's layout.";
|
" Enabling this option will mess up with your main window's layout.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_params.options & Option::BeCompatibleWithQtFramelessWindowHint) {
|
if (m_settings.options & Option::BeCompatibleWithQtFramelessWindowHint) {
|
||||||
Utils::tryToBeCompatibleWithQtFramelessWindowHint(windowId, m_params.getWindowFlags,
|
Utils::tryToBeCompatibleWithQtFramelessWindowHint(windowId, m_params.getWindowFlags,
|
||||||
m_params.setWindowFlags, true);
|
m_params.setWindowFlags, true);
|
||||||
}
|
}
|
||||||
FramelessWindowsManager * const manager = FramelessWindowsManager::instance();
|
FramelessWindowsManager * const manager = FramelessWindowsManager::instance();
|
||||||
manager->addWindow(m_params);
|
manager->addWindow(m_settings, m_params);
|
||||||
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this](){
|
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this](){
|
||||||
if (m_params.options & Option::UseStandardWindowLayout) {
|
if (m_settings.options & Option::UseStandardWindowLayout) {
|
||||||
updateSystemTitleBarStyleSheet();
|
updateSystemTitleBarStyleSheet();
|
||||||
updateSystemButtonsIcon();
|
updateSystemButtonsIcon();
|
||||||
q->update();
|
q->update();
|
||||||
}
|
}
|
||||||
QMetaObject::invokeMethod(q, "systemThemeChanged");
|
QMetaObject::invokeMethod(q, "systemThemeChanged");
|
||||||
});
|
});
|
||||||
connect(m_window, &QWindow::windowStateChanged, this, [this](){
|
connect(m_window, &QWindow::visibilityChanged, this, [this](){
|
||||||
|
QMetaObject::invokeMethod(q, "hiddenChanged");
|
||||||
|
QMetaObject::invokeMethod(q, "normalChanged");
|
||||||
QMetaObject::invokeMethod(q, "zoomedChanged");
|
QMetaObject::invokeMethod(q, "zoomedChanged");
|
||||||
});
|
});
|
||||||
setupInitialUi();
|
setupInitialUi();
|
||||||
if (m_params.options & Option::DisableResizing) {
|
if (m_settings.options & Option::UseStandardWindowLayout) {
|
||||||
|
Q_ASSERT(m_systemMinimizeButton);
|
||||||
|
Q_ASSERT(m_systemMaximizeButton);
|
||||||
|
Q_ASSERT(m_systemCloseButton);
|
||||||
|
m_settings.minimizeButton = m_systemMinimizeButton;
|
||||||
|
m_settings.maximizeButton = m_systemMaximizeButton;
|
||||||
|
m_settings.closeButton = m_systemCloseButton;
|
||||||
|
}
|
||||||
|
if (m_settings.options & Option::DisableResizing) {
|
||||||
setFixedSize(true, true);
|
setFixedSize(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelper::createSystemTitleBar()
|
void FramelessWidgetsHelper::createSystemTitleBar()
|
||||||
{
|
{
|
||||||
if (!(m_params.options & Option::UseStandardWindowLayout)) {
|
if (!(m_settings.options & Option::UseStandardWindowLayout)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_systemTitleBarWidget = new QWidget(q);
|
m_systemTitleBarWidget = new QWidget(q);
|
||||||
|
@ -440,7 +471,7 @@ void FramelessWidgetsHelper::createSystemTitleBar()
|
||||||
|
|
||||||
void FramelessWidgetsHelper::createUserContentContainer()
|
void FramelessWidgetsHelper::createUserContentContainer()
|
||||||
{
|
{
|
||||||
if (!(m_params.options & Option::UseStandardWindowLayout)) {
|
if (!(m_settings.options & Option::UseStandardWindowLayout)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_userContentContainerWidget = new QWidget(q);
|
m_userContentContainerWidget = new QWidget(q);
|
||||||
|
@ -453,7 +484,7 @@ void FramelessWidgetsHelper::createUserContentContainer()
|
||||||
|
|
||||||
void FramelessWidgetsHelper::setupInitialUi()
|
void FramelessWidgetsHelper::setupInitialUi()
|
||||||
{
|
{
|
||||||
if (m_params.options & Option::UseStandardWindowLayout) {
|
if (m_settings.options & Option::UseStandardWindowLayout) {
|
||||||
createSystemTitleBar();
|
createSystemTitleBar();
|
||||||
createUserContentContainer();
|
createUserContentContainer();
|
||||||
m_mainLayout = new QVBoxLayout(q);
|
m_mainLayout = new QVBoxLayout(q);
|
||||||
|
@ -468,33 +499,69 @@ void FramelessWidgetsHelper::setupInitialUi()
|
||||||
updateContentsMargins();
|
updateContentsMargins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect FramelessWidgetsHelper::mapWidgetGeometryToScene(const QWidget * const widget) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(widget);
|
||||||
|
if (!widget) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const QPoint originPoint = widget->mapTo(q, QPoint(0, 0));
|
||||||
|
const QSize size = widget->size();
|
||||||
|
return QRect(originPoint, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessWidgetsHelper::isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(button);
|
||||||
|
if (!button) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*button = SystemButtonType::Unknown;
|
||||||
|
if (!m_settings.minimizeButton || !m_settings.maximizeButton || !m_settings.closeButton) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_settings.minimizeButton->isWidgetType() || !m_settings.maximizeButton->isWidgetType()
|
||||||
|
|| !m_settings.closeButton->isWidgetType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto minBtn = qobject_cast<QWidget *>(m_settings.minimizeButton);
|
||||||
|
if (minBtn->geometry().contains(pos)) {
|
||||||
|
*button = SystemButtonType::Minimize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto maxBtn = qobject_cast<QWidget *>(m_settings.maximizeButton);
|
||||||
|
if (maxBtn->geometry().contains(pos)) {
|
||||||
|
*button = SystemButtonType::Maximize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto closeBtn = qobject_cast<QWidget *>(m_settings.closeButton);
|
||||||
|
if (closeBtn->geometry().contains(pos)) {
|
||||||
|
*button = SystemButtonType::Close;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool FramelessWidgetsHelper::isInTitleBarDraggableArea(const QPoint &pos) const
|
bool FramelessWidgetsHelper::isInTitleBarDraggableArea(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
const QRegion draggableRegion = [this]() -> QRegion {
|
const QRegion draggableRegion = [this]() -> QRegion {
|
||||||
const auto mapGeometryToScene = [this](const QWidget * const widget) -> QRect {
|
|
||||||
Q_ASSERT(widget);
|
|
||||||
if (!widget) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return QRect(widget->mapTo(q, QPoint(0, 0)), widget->size());
|
|
||||||
};
|
|
||||||
if (m_userTitleBarWidget) {
|
if (m_userTitleBarWidget) {
|
||||||
QRegion region = mapGeometryToScene(m_userTitleBarWidget);
|
QRegion region = mapWidgetGeometryToScene(m_userTitleBarWidget);
|
||||||
if (!m_hitTestVisibleWidgets.isEmpty()) {
|
if (!m_hitTestVisibleWidgets.isEmpty()) {
|
||||||
for (auto &&widget : qAsConst(m_hitTestVisibleWidgets)) {
|
for (auto &&widget : qAsConst(m_hitTestVisibleWidgets)) {
|
||||||
Q_ASSERT(widget);
|
Q_ASSERT(widget);
|
||||||
if (widget) {
|
if (widget) {
|
||||||
region -= mapGeometryToScene(widget);
|
region -= mapWidgetGeometryToScene(widget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
if (m_params.options & Option::UseStandardWindowLayout) {
|
if (m_settings.options & Option::UseStandardWindowLayout) {
|
||||||
QRegion region = mapGeometryToScene(m_systemTitleBarWidget);
|
QRegion region = mapWidgetGeometryToScene(m_systemTitleBarWidget);
|
||||||
region -= mapGeometryToScene(m_systemMinimizeButton);
|
region -= mapWidgetGeometryToScene(m_systemMinimizeButton);
|
||||||
region -= mapGeometryToScene(m_systemMaximizeButton);
|
region -= mapWidgetGeometryToScene(m_systemMaximizeButton);
|
||||||
region -= mapGeometryToScene(m_systemCloseButton);
|
region -= mapWidgetGeometryToScene(m_systemCloseButton);
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
@ -506,7 +573,7 @@ bool FramelessWidgetsHelper::shouldDrawFrameBorder() const
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater()
|
return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater()
|
||||||
&& isNormal() && !(m_params.options & Option::DontDrawTopWindowFrameBorder));
|
&& isNormal() && !(m_settings.options & Option::DontDrawTopWindowFrameBorder));
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -528,7 +595,7 @@ void FramelessWidgetsHelper::updateContentsMargins()
|
||||||
|
|
||||||
void FramelessWidgetsHelper::updateSystemTitleBarStyleSheet()
|
void FramelessWidgetsHelper::updateSystemTitleBarStyleSheet()
|
||||||
{
|
{
|
||||||
if (!(m_params.options & Option::UseStandardWindowLayout)) {
|
if (!(m_settings.options & Option::UseStandardWindowLayout)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bool active = q->isActiveWindow();
|
const bool active = q->isActiveWindow();
|
||||||
|
@ -563,7 +630,7 @@ void FramelessWidgetsHelper::updateSystemTitleBarStyleSheet()
|
||||||
|
|
||||||
void FramelessWidgetsHelper::updateSystemButtonsIcon()
|
void FramelessWidgetsHelper::updateSystemButtonsIcon()
|
||||||
{
|
{
|
||||||
if (!(m_params.options & Option::UseStandardWindowLayout)) {
|
if (!(m_settings.options & Option::UseStandardWindowLayout)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const SystemTheme theme = ((Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()) ? SystemTheme::Dark : SystemTheme::Light);
|
const SystemTheme theme = ((Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized()) ? SystemTheme::Dark : SystemTheme::Light);
|
||||||
|
@ -609,4 +676,44 @@ void FramelessWidgetsHelper::moveToDesktopCenter()
|
||||||
m_params.getWindowSize, m_params.setWindowPosition, true);
|
m_params.getWindowSize, m_params.setWindowPosition, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelper::bringToFront()
|
||||||
|
{
|
||||||
|
if (q->isHidden()) {
|
||||||
|
q->show();
|
||||||
|
}
|
||||||
|
if (q->isMinimized()) {
|
||||||
|
q->setWindowState(q->windowState() & ~Qt::WindowMinimized);
|
||||||
|
}
|
||||||
|
q->raise();
|
||||||
|
q->activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
const QPoint globalPos = q->mapToGlobal(pos);
|
||||||
|
const QPoint nativePos = QPointF(QPointF(globalPos) * q->devicePixelRatioF()).toPoint();
|
||||||
|
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.options,
|
||||||
|
m_settings.systemMenuOffset, m_params.isWindowFixedSize);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelper::startSystemMove2()
|
||||||
|
{
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||||
|
m_window->startSystemMove();
|
||||||
|
#else
|
||||||
|
Utils::startSystemMove(m_window);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelper::startSystemResize2(const Qt::Edges edges)
|
||||||
|
{
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||||
|
m_window->startSystemResize(edges);
|
||||||
|
#else
|
||||||
|
Utils::startSystemResize(m_window, edges);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
Loading…
Reference in New Issue