allow user to remove a window from the frameless window list
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
3d3607af7b
commit
47bf4da5ae
|
@ -42,6 +42,7 @@ public:
|
||||||
~FramelessHelperQt() override;
|
~FramelessHelperQt() override;
|
||||||
|
|
||||||
static void addWindow(const Global::SystemParameters ¶ms);
|
static void addWindow(const Global::SystemParameters ¶ms);
|
||||||
|
static void removeWindow(const WId windowId);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
|
|
|
@ -41,6 +41,7 @@ public:
|
||||||
~FramelessHelperWin() override;
|
~FramelessHelperWin() override;
|
||||||
|
|
||||||
static void addWindow(const Global::SystemParameters ¶ms);
|
static void addWindow(const Global::SystemParameters ¶ms);
|
||||||
|
static void removeWindow(const WId windowId);
|
||||||
|
|
||||||
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void addWindow(const Global::SystemParameters ¶ms);
|
void addWindow(const Global::SystemParameters ¶ms);
|
||||||
|
void removeWindow(const WId windowId);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void systemThemeChanged();
|
void systemThemeChanged();
|
||||||
|
|
|
@ -53,10 +53,13 @@ public:
|
||||||
Q_NODISCARD Global::WallpaperAspectStyle wallpaperAspectStyle() const;
|
Q_NODISCARD Global::WallpaperAspectStyle wallpaperAspectStyle() const;
|
||||||
|
|
||||||
static void addWindow(const Global::SystemParameters ¶ms);
|
static void addWindow(const Global::SystemParameters ¶ms);
|
||||||
|
static void removeWindow(const WId windowId);
|
||||||
|
|
||||||
Q_INVOKABLE void notifySystemThemeHasChangedOrNot();
|
Q_INVOKABLE void notifySystemThemeHasChangedOrNot();
|
||||||
Q_INVOKABLE void notifyWallpaperHasChangedOrNot();
|
Q_INVOKABLE void notifyWallpaperHasChangedOrNot();
|
||||||
|
|
||||||
|
Q_NODISCARD static bool usePureQtImplementation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
|
|
|
@ -42,10 +42,10 @@ Q_DECLARE_LOGGING_CATEGORY(lcUtilsCommon)
|
||||||
namespace Utils
|
namespace Utils
|
||||||
{
|
{
|
||||||
|
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::CursorShape calculateCursorShape(const QWindow *window,
|
[[nodiscard]] FRAMELESSHELPER_CORE_API
|
||||||
const QPoint &pos);
|
Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::Edges calculateWindowEdges(const QWindow *window,
|
[[nodiscard]] FRAMELESSHELPER_CORE_API
|
||||||
const QPoint &pos);
|
Qt::Edges calculateWindowEdges(const QWindow *window, const QPoint &pos);
|
||||||
FRAMELESSHELPER_CORE_API void startSystemMove(QWindow *window, const QPoint &globalPos);
|
FRAMELESSHELPER_CORE_API void startSystemMove(QWindow *window, const QPoint &globalPos);
|
||||||
FRAMELESSHELPER_CORE_API void startSystemResize(QWindow *window, const Qt::Edges edges, const QPoint &globalPos);
|
FRAMELESSHELPER_CORE_API void startSystemResize(QWindow *window, const Qt::Edges edges, const QPoint &globalPos);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QString getSystemButtonIconCode(const Global::SystemButtonType button);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QString getSystemButtonIconCode(const Global::SystemButtonType button);
|
||||||
|
|
|
@ -50,7 +50,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickHelper : public QQuickItem
|
||||||
Q_PROPERTY(bool windowFixedSize READ isWindowFixedSize WRITE setWindowFixedSize NOTIFY windowFixedSizeChanged FINAL)
|
Q_PROPERTY(bool windowFixedSize READ isWindowFixedSize WRITE setWindowFixedSize NOTIFY windowFixedSizeChanged FINAL)
|
||||||
Q_PROPERTY(bool blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged FINAL)
|
Q_PROPERTY(bool blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged FINAL)
|
||||||
Q_PROPERTY(QQuickWindow* window READ window NOTIFY windowChanged2 FINAL)
|
Q_PROPERTY(QQuickWindow* window READ window NOTIFY windowChanged2 FINAL)
|
||||||
Q_PROPERTY(bool attached READ isAttached NOTIFY attachedChanged FINAL)
|
Q_PROPERTY(bool extendsContentIntoTitleBar READ isContentExtendedIntoTitleBar WRITE setContentExtendedIntoTitleBar NOTIFY extendsContentIntoTitleBarChanged FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickHelper(QQuickItem *parent = nullptr);
|
explicit FramelessQuickHelper(QQuickItem *parent = nullptr);
|
||||||
|
@ -62,10 +62,11 @@ public:
|
||||||
Q_NODISCARD QQuickItem *titleBarItem() const;
|
Q_NODISCARD QQuickItem *titleBarItem() const;
|
||||||
Q_NODISCARD bool isWindowFixedSize() const;
|
Q_NODISCARD bool isWindowFixedSize() const;
|
||||||
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
||||||
Q_NODISCARD bool isAttached() const;
|
Q_NODISCARD bool isContentExtendedIntoTitleBar() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void extendsContentIntoTitleBar();
|
[[deprecated("Use the extendsContentIntoTitleBar property instead.")]] void extendsContentIntoTitleBar();
|
||||||
|
void setContentExtendedIntoTitleBar(const bool value);
|
||||||
|
|
||||||
void setTitleBarItem(QQuickItem *value);
|
void setTitleBarItem(QQuickItem *value);
|
||||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||||
|
@ -85,11 +86,11 @@ protected:
|
||||||
void itemChange(const ItemChange change, const ItemChangeData &value) override;
|
void itemChange(const ItemChange change, const ItemChangeData &value) override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void extendsContentIntoTitleBarChanged();
|
||||||
void titleBarItemChanged();
|
void titleBarItemChanged();
|
||||||
void windowFixedSizeChanged();
|
void windowFixedSizeChanged();
|
||||||
void blurBehindWindowEnabledChanged();
|
void blurBehindWindowEnabledChanged();
|
||||||
void windowChanged2();
|
void windowChanged2();
|
||||||
void attachedChanged();
|
|
||||||
void ready();
|
void ready();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -50,10 +50,14 @@ public:
|
||||||
Q_NODISCARD static FramelessQuickHelperPrivate *get(FramelessQuickHelper *pub);
|
Q_NODISCARD static FramelessQuickHelperPrivate *get(FramelessQuickHelper *pub);
|
||||||
Q_NODISCARD static const FramelessQuickHelperPrivate *get(const FramelessQuickHelper *pub);
|
Q_NODISCARD static const FramelessQuickHelperPrivate *get(const FramelessQuickHelper *pub);
|
||||||
|
|
||||||
|
Q_NODISCARD bool isContentExtendedIntoTitleBar() const;
|
||||||
|
void setContentExtendedIntoTitleBar(const bool value);
|
||||||
|
|
||||||
Q_NODISCARD QQuickItem *getTitleBarItem() const;
|
Q_NODISCARD QQuickItem *getTitleBarItem() const;
|
||||||
void setTitleBarItem(QQuickItem *value);
|
void setTitleBarItem(QQuickItem *value);
|
||||||
|
|
||||||
void attachToWindow();
|
void attach();
|
||||||
|
void detach();
|
||||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||||
void setHitTestVisible(QQuickItem *item, const bool visible = true);
|
void setHitTestVisible(QQuickItem *item, const bool visible = true);
|
||||||
void setHitTestVisible(const QRect &rect, const bool visible = true);
|
void setHitTestVisible(const QRect &rect, const bool visible = true);
|
||||||
|
@ -75,8 +79,6 @@ public:
|
||||||
void setProperty(const QByteArray &name, const QVariant &value);
|
void setProperty(const QByteArray &name, const QVariant &value);
|
||||||
Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {});
|
Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {});
|
||||||
|
|
||||||
Q_NODISCARD bool isAttached() const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelper : public QObject
|
||||||
Q_PROPERTY(bool windowFixedSize READ isWindowFixedSize WRITE setWindowFixedSize NOTIFY windowFixedSizeChanged FINAL)
|
Q_PROPERTY(bool windowFixedSize READ isWindowFixedSize WRITE setWindowFixedSize NOTIFY windowFixedSizeChanged FINAL)
|
||||||
Q_PROPERTY(bool blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged FINAL)
|
Q_PROPERTY(bool blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged FINAL)
|
||||||
Q_PROPERTY(QWidget* window READ window NOTIFY windowChanged FINAL)
|
Q_PROPERTY(QWidget* window READ window NOTIFY windowChanged FINAL)
|
||||||
Q_PROPERTY(bool attached READ isAttached NOTIFY attachedChanged FINAL)
|
Q_PROPERTY(bool extendsContentIntoTitleBar READ isContentExtendedIntoTitleBar WRITE setContentExtendedIntoTitleBar NOTIFY extendsContentIntoTitleBarChanged FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessWidgetsHelper(QObject *parent = nullptr);
|
explicit FramelessWidgetsHelper(QObject *parent = nullptr);
|
||||||
|
@ -56,10 +56,11 @@ public:
|
||||||
Q_NODISCARD bool isWindowFixedSize() const;
|
Q_NODISCARD bool isWindowFixedSize() const;
|
||||||
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
||||||
Q_NODISCARD QWidget *window() const;
|
Q_NODISCARD QWidget *window() const;
|
||||||
Q_NODISCARD bool isAttached() const;
|
Q_NODISCARD bool isContentExtendedIntoTitleBar() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void extendsContentIntoTitleBar();
|
[[deprecated("Use the extendsContentIntoTitleBar property instead.")]] void extendsContentIntoTitleBar();
|
||||||
|
void setContentExtendedIntoTitleBar(const bool value);
|
||||||
|
|
||||||
void setTitleBarWidget(QWidget *widget);
|
void setTitleBarWidget(QWidget *widget);
|
||||||
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
||||||
|
@ -76,11 +77,11 @@ public Q_SLOTS:
|
||||||
void setBlurBehindWindowEnabled(const bool value);
|
void setBlurBehindWindowEnabled(const bool value);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void extendsContentIntoTitleBarChanged();
|
||||||
void titleBarWidgetChanged();
|
void titleBarWidgetChanged();
|
||||||
void windowFixedSizeChanged();
|
void windowFixedSizeChanged();
|
||||||
void blurBehindWindowEnabledChanged();
|
void blurBehindWindowEnabledChanged();
|
||||||
void windowChanged();
|
void windowChanged();
|
||||||
void attachedChanged();
|
|
||||||
void ready();
|
void ready();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -46,10 +46,14 @@ public:
|
||||||
Q_NODISCARD static FramelessWidgetsHelperPrivate *get(FramelessWidgetsHelper *pub);
|
Q_NODISCARD static FramelessWidgetsHelperPrivate *get(FramelessWidgetsHelper *pub);
|
||||||
Q_NODISCARD static const FramelessWidgetsHelperPrivate *get(const FramelessWidgetsHelper *pub);
|
Q_NODISCARD static const FramelessWidgetsHelperPrivate *get(const FramelessWidgetsHelper *pub);
|
||||||
|
|
||||||
|
Q_NODISCARD bool isContentExtendedIntoTitleBar() const;
|
||||||
|
void setContentExtendedIntoTitleBar(const bool value);
|
||||||
|
|
||||||
Q_NODISCARD QWidget *getTitleBarWidget() const;
|
Q_NODISCARD QWidget *getTitleBarWidget() const;
|
||||||
void setTitleBarWidget(QWidget *widget);
|
void setTitleBarWidget(QWidget *widget);
|
||||||
|
|
||||||
void attachToWindow();
|
void attach();
|
||||||
|
void detach();
|
||||||
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
||||||
void setHitTestVisible(QWidget *widget, const bool visible = true);
|
void setHitTestVisible(QWidget *widget, const bool visible = true);
|
||||||
void setHitTestVisible(const QRect &rect, const bool visible = true);
|
void setHitTestVisible(const QRect &rect, const bool visible = true);
|
||||||
|
@ -72,7 +76,6 @@ public:
|
||||||
Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {});
|
Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {});
|
||||||
|
|
||||||
Q_NODISCARD QWidget *window() const;
|
Q_NODISCARD QWidget *window() const;
|
||||||
Q_NODISCARD bool isAttached() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const;
|
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const;
|
||||||
|
|
|
@ -106,6 +106,24 @@ void FramelessHelperQt::addWindow(const SystemParameters ¶ms)
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware();
|
FramelessHelper::Core::setApplicationOSThemeAware();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessHelperQt::removeWindow(const WId windowId)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QMutexLocker locker(&g_qtHelper()->mutex);
|
||||||
|
if (!g_qtHelper()->data.contains(windowId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QtHelperData data = g_qtHelper()->data.value(windowId);
|
||||||
|
g_qtHelper()->data.remove(windowId);
|
||||||
|
if (QWindow * const window = Utils::findWindow(windowId)) {
|
||||||
|
window->removeEventFilter(data.eventFilter);
|
||||||
|
}
|
||||||
|
delete data.eventFilter;
|
||||||
|
}
|
||||||
|
|
||||||
bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
||||||
{
|
{
|
||||||
Q_ASSERT(object);
|
Q_ASSERT(object);
|
||||||
|
|
|
@ -552,6 +552,41 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessHelperWin::removeWindow(const WId windowId)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_win32Helper()->mutex.lock();
|
||||||
|
if (!g_win32Helper()->data.contains(windowId)) {
|
||||||
|
g_win32Helper()->mutex.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_win32Helper()->data.remove(windowId);
|
||||||
|
if (g_win32Helper()->data.isEmpty()) {
|
||||||
|
if (!g_win32Helper()->nativeEventFilter.isNull()) {
|
||||||
|
qApp->removeNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
|
||||||
|
g_win32Helper()->nativeEventFilter.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HWND hwnd = nullptr;
|
||||||
|
auto it = g_win32Helper()->fallbackTitleBarToParentWindowMapping.constBegin();
|
||||||
|
while (it != g_win32Helper()->fallbackTitleBarToParentWindowMapping.constEnd()) {
|
||||||
|
if (it.value() == windowId) {
|
||||||
|
const WId key = it.key();
|
||||||
|
hwnd = reinterpret_cast<HWND>(key);
|
||||||
|
g_win32Helper()->fallbackTitleBarToParentWindowMapping.remove(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
g_win32Helper()->mutex.unlock();
|
||||||
|
if (DestroyWindow(reinterpret_cast<HWND>(hwnd)) == FALSE) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kDestroyWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result)
|
bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result)
|
||||||
{
|
{
|
||||||
if ((eventType != kWin32MessageTypeName) || !message || !result) {
|
if ((eventType != kWin32MessageTypeName) || !message || !result) {
|
||||||
|
|
|
@ -54,10 +54,15 @@ Q_LOGGING_CATEGORY(lcFramelessManager, "wangwenx190.framelesshelper.core.framele
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
|
struct FramelessManagerHelperData
|
||||||
|
{
|
||||||
|
QMetaObject::Connection screenChangeConnection = {};
|
||||||
|
};
|
||||||
|
|
||||||
struct FramelessManagerHelper
|
struct FramelessManagerHelper
|
||||||
{
|
{
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
QList<WId> windowIds = {};
|
QHash<WId, FramelessManagerHelperData> data = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(FramelessManagerHelper, g_helper)
|
Q_GLOBAL_STATIC(FramelessManagerHelper, g_helper)
|
||||||
|
@ -182,35 +187,35 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms)
|
||||||
}
|
}
|
||||||
const WId windowId = params.getWindowId();
|
const WId windowId = params.getWindowId();
|
||||||
g_helper()->mutex.lock();
|
g_helper()->mutex.lock();
|
||||||
if (g_helper()->windowIds.contains(windowId)) {
|
if (g_helper()->data.contains(windowId)) {
|
||||||
g_helper()->mutex.unlock();
|
g_helper()->mutex.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_helper()->windowIds.append(windowId);
|
g_helper()->data.insert(windowId, {});
|
||||||
g_helper()->mutex.unlock();
|
g_helper()->mutex.unlock();
|
||||||
static const bool pureQt = []() -> bool {
|
QMetaObject::Connection screenChangeConnection = {};
|
||||||
#ifdef Q_OS_WINDOWS
|
static const bool pureQt = usePureQtImplementation();
|
||||||
return FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation);
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}();
|
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (!pureQt) {
|
if (!pureQt) {
|
||||||
// Work-around Win32 multi-monitor artifacts.
|
// Work-around Win32 multi-monitor artifacts.
|
||||||
QWindow * const window = params.getWindowHandle();
|
QWindow * const window = params.getWindowHandle();
|
||||||
Q_ASSERT(window);
|
Q_ASSERT(window);
|
||||||
connect(window, &QWindow::screenChanged, window, [windowId, window](QScreen *screen){
|
if (window) {
|
||||||
Q_UNUSED(screen);
|
g_helper()->mutex.lock();
|
||||||
// Force a WM_NCCALCSIZE event to inform Windows about our custom window frame,
|
g_helper()->data[windowId].screenChangeConnection =
|
||||||
// this is only necessary when the window is being moved cross monitors.
|
connect(window, &QWindow::screenChanged, window, [windowId, window](QScreen *screen){
|
||||||
Utils::triggerFrameChange(windowId);
|
Q_UNUSED(screen);
|
||||||
// For some reason the window is not repainted correctly when moving cross monitors,
|
// Force a WM_NCCALCSIZE event to inform Windows about our custom window frame,
|
||||||
// we workaround this issue by force a re-paint and re-layout of the window by triggering
|
// this is only necessary when the window is being moved cross monitors.
|
||||||
// a resize event manually. Although the actual size does not change, the issue we
|
Utils::triggerFrameChange(windowId);
|
||||||
// observed disappeared indeed, amazingly.
|
// For some reason the window is not repainted correctly when moving cross monitors,
|
||||||
window->resize(window->size());
|
// we workaround this issue by force a re-paint and re-layout of the window by triggering
|
||||||
});
|
// a resize event manually. Although the actual size does not change, the issue we
|
||||||
|
// observed disappeared indeed, amazingly.
|
||||||
|
window->resize(window->size());
|
||||||
|
});
|
||||||
|
g_helper()->mutex.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (pureQt) {
|
if (pureQt) {
|
||||||
|
@ -225,6 +230,37 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessManagerPrivate::removeWindow(const WId windowId)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_helper()->mutex.lock();
|
||||||
|
if (!g_helper()->data.contains(windowId)) {
|
||||||
|
g_helper()->mutex.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const FramelessManagerHelperData data = g_helper()->data.value(windowId);
|
||||||
|
g_helper()->data.remove(windowId);
|
||||||
|
g_helper()->mutex.unlock();
|
||||||
|
static const bool pureQt = usePureQtImplementation();
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
if (!pureQt && data.screenChangeConnection) {
|
||||||
|
disconnect(data.screenChangeConnection);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (pureQt) {
|
||||||
|
FramelessHelperQt::removeWindow(windowId);
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
if (!pureQt) {
|
||||||
|
FramelessHelperWin::removeWindow(windowId);
|
||||||
|
}
|
||||||
|
Utils::uninstallSystemMenuHook(windowId);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessManagerPrivate::notifySystemThemeHasChangedOrNot()
|
void FramelessManagerPrivate::notifySystemThemeHasChangedOrNot()
|
||||||
{
|
{
|
||||||
const QMutexLocker locker(&g_helper()->mutex);
|
const QMutexLocker locker(&g_helper()->mutex);
|
||||||
|
@ -282,6 +318,18 @@ void FramelessManagerPrivate::notifyWallpaperHasChangedOrNot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FramelessManagerPrivate::usePureQtImplementation()
|
||||||
|
{
|
||||||
|
static const bool result = []() -> bool {
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
return FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation);
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessManagerPrivate::initialize()
|
void FramelessManagerPrivate::initialize()
|
||||||
{
|
{
|
||||||
const QMutexLocker locker(&g_helper()->mutex);
|
const QMutexLocker locker(&g_helper()->mutex);
|
||||||
|
@ -342,4 +390,10 @@ void FramelessManager::addWindow(const SystemParameters ¶ms)
|
||||||
d->addWindow(params);
|
d->addWindow(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessManager::removeWindow(const WId windowId)
|
||||||
|
{
|
||||||
|
Q_D(FramelessManager);
|
||||||
|
d->removeWindow(windowId);
|
||||||
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -1154,46 +1154,56 @@ void Utils::fixupQtInternals(const WId windowId)
|
||||||
if (qEnvironmentVariableIntValue(kNoFixQtInternalEnvVar)) {
|
if (qEnvironmentVariableIntValue(kNoFixQtInternalEnvVar)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bool shouldUpdateFrame = false;
|
||||||
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
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 classStyle = static_cast<DWORD>(GetClassLongPtrW(hwnd, GCL_STYLE));
|
||||||
if (oldClassStyle == 0) {
|
if (classStyle != 0) {
|
||||||
|
// CS_HREDRAW/CS_VREDRAW will trigger a repaint event when the window size changes
|
||||||
|
// horizontally/vertically, which will cause flicker and jitter during window resizing,
|
||||||
|
// mostly for the applications which do all the painting by themselves (eg: Qt).
|
||||||
|
// So we remove these flags from the window class here. Qt by default won't add them
|
||||||
|
// but let's make it extra safe in case the user may add them by accident.
|
||||||
|
static constexpr const DWORD badClassStyle = (CS_HREDRAW | CS_VREDRAW);
|
||||||
|
if (classStyle & badClassStyle) {
|
||||||
|
SetLastError(ERROR_SUCCESS);
|
||||||
|
if (SetClassLongPtrW(hwnd, GCL_STYLE,
|
||||||
|
static_cast<LONG_PTR>(classStyle & ~badClassStyle)) == 0) {
|
||||||
|
WARNING << getSystemErrorMessage(kSetClassLongPtrW);
|
||||||
|
} else {
|
||||||
|
shouldUpdateFrame = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
WARNING << getSystemErrorMessage(kGetClassLongPtrW);
|
WARNING << getSystemErrorMessage(kGetClassLongPtrW);
|
||||||
return;
|
|
||||||
}
|
|
||||||
// CS_HREDRAW/CS_VREDRAW will trigger a repaint event when the window size changes
|
|
||||||
// horizontally/vertically, which will cause flicker and jitter during window
|
|
||||||
// resizing, mostly for the applications which do all the painting by themselves.
|
|
||||||
// So we remove these flags from the window class here, Qt by default won't add them
|
|
||||||
// but let's make it extra safe.
|
|
||||||
const DWORD newClassStyle = (oldClassStyle & ~(CS_HREDRAW | CS_VREDRAW));
|
|
||||||
SetLastError(ERROR_SUCCESS);
|
|
||||||
if (SetClassLongPtrW(hwnd, GCL_STYLE, static_cast<LONG_PTR>(newClassStyle)) == 0) {
|
|
||||||
WARNING << getSystemErrorMessage(kSetClassLongPtrW);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
const auto oldWindowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
|
const auto windowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
|
||||||
if (oldWindowStyle == 0) {
|
if (windowStyle != 0) {
|
||||||
|
// Qt by default adds the "WS_POPUP" flag to all Win32 windows it created and maintained,
|
||||||
|
// which is not a good thing (although it won't cause any obvious issues in most cases
|
||||||
|
// either), because popup windows have some different behavior with normal overlapped
|
||||||
|
// windows, for example, it will affect DWM's default policy. And Qt will also lack some
|
||||||
|
// necessary window styles in some cases (caused by misconfigured setWindowFlag(s) calls)
|
||||||
|
// and this will also break the normal functionalities for our windows, so we do the
|
||||||
|
// correction here unconditionally.
|
||||||
|
static constexpr const DWORD goodWindowStyle =
|
||||||
|
(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
|
||||||
|
if (!(windowStyle & goodWindowStyle)) {
|
||||||
|
SetLastError(ERROR_SUCCESS);
|
||||||
|
if (SetWindowLongPtrW(hwnd, GWL_STYLE,
|
||||||
|
static_cast<LONG_PTR>((windowStyle & ~WS_POPUP) | goodWindowStyle)) == 0) {
|
||||||
|
WARNING << getSystemErrorMessage(kSetWindowLongPtrW);
|
||||||
|
} else {
|
||||||
|
shouldUpdateFrame = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
WARNING << getSystemErrorMessage(kGetWindowLongPtrW);
|
WARNING << getSystemErrorMessage(kGetWindowLongPtrW);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// Qt by default adds the "WS_POPUP" flag to all Win32 windows it created and maintained,
|
if (shouldUpdateFrame) {
|
||||||
// which is not a good thing (although it won't cause any obvious issues in most cases
|
triggerFrameChange(windowId);
|
||||||
// either), because popup windows have some different behavior with normal overlapped
|
|
||||||
// windows, for example, it will affect DWM's default policy. And Qt will also lack some
|
|
||||||
// necessary window styles in some cases (caused by misconfigured setWindowFlag(s) calls)
|
|
||||||
// and this will also break the normal functionalities for our windows, so we do the
|
|
||||||
// correction here unconditionally.
|
|
||||||
static constexpr const DWORD normalWindowStyle =
|
|
||||||
(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
|
|
||||||
const DWORD newWindowStyle = ((oldWindowStyle & ~WS_POPUP) | normalWindowStyle);
|
|
||||||
SetLastError(ERROR_SUCCESS);
|
|
||||||
if (SetWindowLongPtrW(hwnd, GWL_STYLE, static_cast<LONG_PTR>(newWindowStyle)) == 0) {
|
|
||||||
WARNING << getSystemErrorMessage(kSetWindowLongPtrW);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
triggerFrameChange(windowId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
|
void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
|
||||||
|
|
|
@ -52,7 +52,7 @@ using namespace Global;
|
||||||
|
|
||||||
struct QuickHelperData
|
struct QuickHelperData
|
||||||
{
|
{
|
||||||
bool attached = false;
|
bool ready = false;
|
||||||
SystemParameters params = {};
|
SystemParameters params = {};
|
||||||
QPointer<QQuickItem> titleBarItem = nullptr;
|
QPointer<QQuickItem> titleBarItem = nullptr;
|
||||||
QList<QPointer<QQuickItem>> hitTestVisibleItems = {};
|
QList<QPointer<QQuickItem>> hitTestVisibleItems = {};
|
||||||
|
@ -97,11 +97,14 @@ FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
q_ptr = q;
|
q_ptr = q;
|
||||||
// Workaround a moc limitation.
|
// Workaround a MOC limitation: we can't emit a signal from the parent class.
|
||||||
connect(q_ptr, &FramelessQuickHelper::windowChanged, q_ptr, &FramelessQuickHelper::windowChanged2);
|
connect(q_ptr, &FramelessQuickHelper::windowChanged, q_ptr, &FramelessQuickHelper::windowChanged2);
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessQuickHelperPrivate::~FramelessQuickHelperPrivate() = default;
|
FramelessQuickHelperPrivate::~FramelessQuickHelperPrivate()
|
||||||
|
{
|
||||||
|
detach();
|
||||||
|
}
|
||||||
|
|
||||||
FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(FramelessQuickHelper *pub)
|
FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(FramelessQuickHelper *pub)
|
||||||
{
|
{
|
||||||
|
@ -121,6 +124,24 @@ const FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(const Framel
|
||||||
return pub->d_func();
|
return pub->d_func();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickHelperPrivate::isContentExtendedIntoTitleBar() const
|
||||||
|
{
|
||||||
|
return getWindowData().ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickHelperPrivate::setContentExtendedIntoTitleBar(const bool value)
|
||||||
|
{
|
||||||
|
if (isContentExtendedIntoTitleBar() == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
attach();
|
||||||
|
} else {
|
||||||
|
detach();
|
||||||
|
}
|
||||||
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("extendsContentIntoTitleBarChanged"));
|
||||||
|
}
|
||||||
|
|
||||||
QQuickItem *FramelessQuickHelperPrivate::getTitleBarItem() const
|
QQuickItem *FramelessQuickHelperPrivate::getTitleBarItem() const
|
||||||
{
|
{
|
||||||
return getWindowData().titleBarItem;
|
return getWindowData().titleBarItem;
|
||||||
|
@ -144,7 +165,7 @@ void FramelessQuickHelperPrivate::setTitleBarItem(QQuickItem *value)
|
||||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("titleBarItemChanged"));
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("titleBarItemChanged"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickHelperPrivate::attachToWindow()
|
void FramelessQuickHelperPrivate::attach()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessQuickHelper);
|
Q_Q(FramelessQuickHelper);
|
||||||
QQuickWindow * const window = q->window();
|
QQuickWindow * const window = q->window();
|
||||||
|
@ -154,18 +175,13 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
g_quickHelper()->mutex.lock();
|
g_quickHelper()->mutex.lock();
|
||||||
QuickHelperData *data = getWindowDataMutable();
|
QuickHelperData * const data = getWindowDataMutable();
|
||||||
if (!data) {
|
if (!data || data->ready) {
|
||||||
g_quickHelper()->mutex.unlock();
|
g_quickHelper()->mutex.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bool attached = data->attached;
|
|
||||||
g_quickHelper()->mutex.unlock();
|
g_quickHelper()->mutex.unlock();
|
||||||
|
|
||||||
if (attached) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->installEventFilter(this);
|
window->installEventFilter(this);
|
||||||
|
|
||||||
SystemParameters params = {};
|
SystemParameters params = {};
|
||||||
|
@ -208,7 +224,7 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
||||||
|
|
||||||
g_quickHelper()->mutex.lock();
|
g_quickHelper()->mutex.lock();
|
||||||
data->params = params;
|
data->params = params;
|
||||||
data->attached = true;
|
data->ready = true;
|
||||||
g_quickHelper()->mutex.unlock();
|
g_quickHelper()->mutex.unlock();
|
||||||
|
|
||||||
// We have to wait for a little time before moving the top level window
|
// We have to wait for a little time before moving the top level window
|
||||||
|
@ -223,11 +239,27 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
||||||
if (FramelessConfig::instance()->isSet(Option::EnableBlurBehindWindow)) {
|
if (FramelessConfig::instance()->isSet(Option::EnableBlurBehindWindow)) {
|
||||||
setBlurBehindWindowEnabled(true, {});
|
setBlurBehindWindowEnabled(true, {});
|
||||||
}
|
}
|
||||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("attachedChanged"));
|
|
||||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("ready"));
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("ready"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessQuickHelperPrivate::detach()
|
||||||
|
{
|
||||||
|
Q_Q(FramelessQuickHelper);
|
||||||
|
QQuickWindow * const w = q->window();
|
||||||
|
if (!w) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const WId windowId = w->winId();
|
||||||
|
const QMutexLocker locker(&g_quickHelper()->mutex);
|
||||||
|
if (!g_quickHelper()->data.contains(windowId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_quickHelper()->data.remove(windowId);
|
||||||
|
w->removeEventFilter(this);
|
||||||
|
FramelessManager::instance()->removeWindow(windowId);
|
||||||
|
}
|
||||||
|
|
||||||
void FramelessQuickHelperPrivate::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
void FramelessQuickHelperPrivate::setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType)
|
||||||
{
|
{
|
||||||
Q_ASSERT(item);
|
Q_ASSERT(item);
|
||||||
|
@ -512,12 +544,6 @@ QVariant FramelessQuickHelperPrivate::getProperty(const QByteArray &name, const
|
||||||
return (value.isValid() ? value : defaultValue);
|
return (value.isValid() ? value : defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessQuickHelperPrivate::isAttached() const
|
|
||||||
{
|
|
||||||
const QMutexLocker locker(&g_quickHelper()->mutex);
|
|
||||||
return getWindowData().attached;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event)
|
bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event)
|
||||||
{
|
{
|
||||||
Q_ASSERT(object);
|
Q_ASSERT(object);
|
||||||
|
@ -838,7 +864,7 @@ FramelessQuickHelper *FramelessQuickHelper::get(QObject *object)
|
||||||
instance->setParentItem(parentItem);
|
instance->setParentItem(parentItem);
|
||||||
instance->setParent(parent);
|
instance->setParent(parent);
|
||||||
// No need to do this here, we'll do it once the item has been assigned to a specific window.
|
// No need to do this here, we'll do it once the item has been assigned to a specific window.
|
||||||
//instance->d_func()->attachToWindow();
|
//instance->d_func()->attach();
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -870,15 +896,21 @@ bool FramelessQuickHelper::isBlurBehindWindowEnabled() const
|
||||||
return d->isBlurBehindWindowEnabled();
|
return d->isBlurBehindWindowEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessQuickHelper::isAttached() const
|
bool FramelessQuickHelper::isContentExtendedIntoTitleBar() const
|
||||||
{
|
{
|
||||||
Q_D(const FramelessQuickHelper);
|
Q_D(const FramelessQuickHelper);
|
||||||
return d->isAttached();
|
return d->isContentExtendedIntoTitleBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickHelper::extendsContentIntoTitleBar()
|
void FramelessQuickHelper::extendsContentIntoTitleBar()
|
||||||
{
|
{
|
||||||
// Intentionally not doing anything here.
|
setContentExtendedIntoTitleBar(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickHelper::setContentExtendedIntoTitleBar(const bool value)
|
||||||
|
{
|
||||||
|
Q_D(FramelessQuickHelper);
|
||||||
|
d->setContentExtendedIntoTitleBar(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessQuickHelper::setTitleBarItem(QQuickItem *value)
|
void FramelessQuickHelper::setTitleBarItem(QQuickItem *value)
|
||||||
|
@ -988,7 +1020,7 @@ void FramelessQuickHelper::itemChange(const ItemChange change, const ItemChangeD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Q_D(FramelessQuickHelper);
|
Q_D(FramelessQuickHelper);
|
||||||
d->attachToWindow();
|
d->attach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ void FramelessQuickWindowPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessQuickWindow);
|
Q_Q(FramelessQuickWindow);
|
||||||
QQuickItem * const rootItem = q->contentItem();
|
QQuickItem * const rootItem = q->contentItem();
|
||||||
FramelessQuickHelper::get(rootItem)->extendsContentIntoTitleBar();
|
FramelessQuickHelper::get(rootItem)->setContentExtendedIntoTitleBar(true);
|
||||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||||
m_topBorderRectangle->setZ(999); // Make sure the frame border stays on top of eveything.
|
m_topBorderRectangle->setZ(999); // Make sure the frame border stays on top of eveything.
|
||||||
m_topBorderRectangle->setColor(kDefaultTransparentColor);
|
m_topBorderRectangle->setColor(kDefaultTransparentColor);
|
||||||
|
|
|
@ -71,7 +71,7 @@ const FramelessDialogPrivate *FramelessDialogPrivate::get(const FramelessDialog
|
||||||
void FramelessDialogPrivate::initialize()
|
void FramelessDialogPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessDialog);
|
Q_Q(FramelessDialog);
|
||||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
FramelessWidgetsHelper::get(q)->setContentExtendedIntoTitleBar(true);
|
||||||
m_helper.reset(new WidgetsSharedHelper(this));
|
m_helper.reset(new WidgetsSharedHelper(this));
|
||||||
m_helper->setup(q);
|
m_helper->setup(q);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ const FramelessMainWindowPrivate *FramelessMainWindowPrivate::get(const Frameles
|
||||||
void FramelessMainWindowPrivate::initialize()
|
void FramelessMainWindowPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessMainWindow);
|
Q_Q(FramelessMainWindow);
|
||||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
FramelessWidgetsHelper::get(q)->setContentExtendedIntoTitleBar(true);
|
||||||
m_helper.reset(new WidgetsSharedHelper(this));
|
m_helper.reset(new WidgetsSharedHelper(this));
|
||||||
m_helper->setup(q);
|
m_helper->setup(q);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ const FramelessWidgetPrivate *FramelessWidgetPrivate::get(const FramelessWidget
|
||||||
void FramelessWidgetPrivate::initialize()
|
void FramelessWidgetPrivate::initialize()
|
||||||
{
|
{
|
||||||
Q_Q(FramelessWidget);
|
Q_Q(FramelessWidget);
|
||||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
FramelessWidgetsHelper::get(q)->setContentExtendedIntoTitleBar(true);
|
||||||
m_helper.reset(new WidgetsSharedHelper(this));
|
m_helper.reset(new WidgetsSharedHelper(this));
|
||||||
m_helper->setup(q);
|
m_helper->setup(q);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ using namespace Global;
|
||||||
|
|
||||||
struct WidgetsHelperData
|
struct WidgetsHelperData
|
||||||
{
|
{
|
||||||
bool attached = false;
|
bool ready = false;
|
||||||
SystemParameters params = {};
|
SystemParameters params = {};
|
||||||
QPointer<QWidget> titleBarWidget = nullptr;
|
QPointer<QWidget> titleBarWidget = nullptr;
|
||||||
QList<QPointer<QWidget>> hitTestVisibleWidgets = {};
|
QList<QPointer<QWidget>> hitTestVisibleWidgets = {};
|
||||||
|
@ -107,7 +107,10 @@ FramelessWidgetsHelperPrivate::FramelessWidgetsHelperPrivate(FramelessWidgetsHel
|
||||||
q_ptr = q;
|
q_ptr = q;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate() = default;
|
FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate()
|
||||||
|
{
|
||||||
|
detach();
|
||||||
|
}
|
||||||
|
|
||||||
FramelessWidgetsHelperPrivate *FramelessWidgetsHelperPrivate::get(FramelessWidgetsHelper *pub)
|
FramelessWidgetsHelperPrivate *FramelessWidgetsHelperPrivate::get(FramelessWidgetsHelper *pub)
|
||||||
{
|
{
|
||||||
|
@ -264,10 +267,9 @@ QWidget *FramelessWidgetsHelperPrivate::window() const
|
||||||
return m_window;
|
return m_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessWidgetsHelperPrivate::isAttached() const
|
bool FramelessWidgetsHelperPrivate::isContentExtendedIntoTitleBar() const
|
||||||
{
|
{
|
||||||
const QMutexLocker locker(&g_widgetsHelper()->mutex);
|
return getWindowData().ready;
|
||||||
return getWindowData().attached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelperPrivate::setTitleBarWidget(QWidget *widget)
|
void FramelessWidgetsHelperPrivate::setTitleBarWidget(QWidget *widget)
|
||||||
|
@ -333,7 +335,7 @@ void FramelessWidgetsHelperPrivate::setHitTestVisible(const QRect &rect, const b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelperPrivate::attachToWindow()
|
void FramelessWidgetsHelperPrivate::attach()
|
||||||
{
|
{
|
||||||
QWidget * const window = findTopLevelWindow();
|
QWidget * const window = findTopLevelWindow();
|
||||||
Q_ASSERT(window);
|
Q_ASSERT(window);
|
||||||
|
@ -346,18 +348,13 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
|
||||||
m_window = window;
|
m_window = window;
|
||||||
|
|
||||||
g_widgetsHelper()->mutex.lock();
|
g_widgetsHelper()->mutex.lock();
|
||||||
WidgetsHelperData *data = getWindowDataMutable();
|
WidgetsHelperData * const data = getWindowDataMutable();
|
||||||
if (!data) {
|
if (!data || data->ready) {
|
||||||
g_widgetsHelper()->mutex.unlock();
|
g_widgetsHelper()->mutex.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bool attached = data->attached;
|
|
||||||
g_widgetsHelper()->mutex.unlock();
|
g_widgetsHelper()->mutex.unlock();
|
||||||
|
|
||||||
if (attached) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Without this flag, Qt will always create an invisible native parent window
|
// Without this flag, Qt will always create an invisible native parent window
|
||||||
// for any native widgets which will intercept some win32 messages and confuse
|
// for any native widgets which will intercept some win32 messages and confuse
|
||||||
// our own native event filter, so to prevent some weired bugs from happening,
|
// our own native event filter, so to prevent some weired bugs from happening,
|
||||||
|
@ -405,7 +402,7 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
|
||||||
|
|
||||||
g_widgetsHelper()->mutex.lock();
|
g_widgetsHelper()->mutex.lock();
|
||||||
data->params = params;
|
data->params = params;
|
||||||
data->attached = true;
|
data->ready = true;
|
||||||
g_widgetsHelper()->mutex.unlock();
|
g_widgetsHelper()->mutex.unlock();
|
||||||
|
|
||||||
// We have to wait for a little time before moving the top level window
|
// We have to wait for a little time before moving the top level window
|
||||||
|
@ -421,11 +418,39 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
|
||||||
setBlurBehindWindowEnabled(true, {});
|
setBlurBehindWindowEnabled(true, {});
|
||||||
}
|
}
|
||||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("windowChanged"));
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("windowChanged"));
|
||||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("attachedChanged"));
|
|
||||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("ready"));
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("ready"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelperPrivate::detach()
|
||||||
|
{
|
||||||
|
if (!m_window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const WId windowId = m_window->winId();
|
||||||
|
const QMutexLocker locker(&g_widgetsHelper()->mutex);
|
||||||
|
if (!g_widgetsHelper()->data.contains(windowId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_widgetsHelper()->data.remove(windowId);
|
||||||
|
FramelessManager::instance()->removeWindow(windowId);
|
||||||
|
m_window = nullptr;
|
||||||
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("windowChanged"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelperPrivate::setContentExtendedIntoTitleBar(const bool value)
|
||||||
|
{
|
||||||
|
if (isContentExtendedIntoTitleBar() == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
attach();
|
||||||
|
} else {
|
||||||
|
detach();
|
||||||
|
}
|
||||||
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("extendsContentIntoTitleBarChanged"));
|
||||||
|
}
|
||||||
|
|
||||||
QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const
|
QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const
|
||||||
{
|
{
|
||||||
Q_Q(const FramelessWidgetsHelper);
|
Q_Q(const FramelessWidgetsHelper);
|
||||||
|
@ -796,7 +821,7 @@ FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *object)
|
||||||
FramelessWidgetsHelper *instance = parent->findChild<FramelessWidgetsHelper *>();
|
FramelessWidgetsHelper *instance = parent->findChild<FramelessWidgetsHelper *>();
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = new FramelessWidgetsHelper(parent);
|
instance = new FramelessWidgetsHelper(parent);
|
||||||
instance->d_func()->attachToWindow();
|
instance->d_func()->attach();
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -825,15 +850,21 @@ QWidget *FramelessWidgetsHelper::window() const
|
||||||
return d->window();
|
return d->window();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramelessWidgetsHelper::isAttached() const
|
bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const
|
||||||
{
|
{
|
||||||
Q_D(const FramelessWidgetsHelper);
|
Q_D(const FramelessWidgetsHelper);
|
||||||
return d->isAttached();
|
return d->isContentExtendedIntoTitleBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelper::extendsContentIntoTitleBar()
|
void FramelessWidgetsHelper::extendsContentIntoTitleBar()
|
||||||
{
|
{
|
||||||
// Intentionally not doing anything here.
|
setContentExtendedIntoTitleBar(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidgetsHelper::setContentExtendedIntoTitleBar(const bool value)
|
||||||
|
{
|
||||||
|
Q_D(FramelessWidgetsHelper);
|
||||||
|
d->setContentExtendedIntoTitleBar(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
|
void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
|
||||||
|
|
Loading…
Reference in New Issue