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;
|
||||
|
||||
static void addWindow(const Global::SystemParameters ¶ms);
|
||||
static void removeWindow(const WId windowId);
|
||||
|
||||
protected:
|
||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
~FramelessHelperWin() override;
|
||||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
|
||||
public Q_SLOTS:
|
||||
void addWindow(const Global::SystemParameters ¶ms);
|
||||
void removeWindow(const WId windowId);
|
||||
|
||||
Q_SIGNALS:
|
||||
void systemThemeChanged();
|
||||
|
|
|
@ -53,10 +53,13 @@ public:
|
|||
Q_NODISCARD Global::WallpaperAspectStyle wallpaperAspectStyle() const;
|
||||
|
||||
static void addWindow(const Global::SystemParameters ¶ms);
|
||||
static void removeWindow(const WId windowId);
|
||||
|
||||
Q_INVOKABLE void notifySystemThemeHasChangedOrNot();
|
||||
Q_INVOKABLE void notifyWallpaperHasChangedOrNot();
|
||||
|
||||
Q_NODISCARD static bool usePureQtImplementation();
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@ Q_DECLARE_LOGGING_CATEGORY(lcUtilsCommon)
|
|||
namespace Utils
|
||||
{
|
||||
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::CursorShape calculateCursorShape(const QWindow *window,
|
||||
const QPoint &pos);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Qt::Edges calculateWindowEdges(const QWindow *window,
|
||||
const QPoint &pos);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API
|
||||
Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API
|
||||
Qt::Edges calculateWindowEdges(const QWindow *window, const QPoint &pos);
|
||||
FRAMELESSHELPER_CORE_API void startSystemMove(QWindow *window, 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);
|
||||
|
|
|
@ -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 blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged 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:
|
||||
explicit FramelessQuickHelper(QQuickItem *parent = nullptr);
|
||||
|
@ -62,10 +62,11 @@ public:
|
|||
Q_NODISCARD QQuickItem *titleBarItem() const;
|
||||
Q_NODISCARD bool isWindowFixedSize() const;
|
||||
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
||||
Q_NODISCARD bool isAttached() const;
|
||||
Q_NODISCARD bool isContentExtendedIntoTitleBar() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void extendsContentIntoTitleBar();
|
||||
[[deprecated("Use the extendsContentIntoTitleBar property instead.")]] void extendsContentIntoTitleBar();
|
||||
void setContentExtendedIntoTitleBar(const bool value);
|
||||
|
||||
void setTitleBarItem(QQuickItem *value);
|
||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||
|
@ -85,11 +86,11 @@ protected:
|
|||
void itemChange(const ItemChange change, const ItemChangeData &value) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void extendsContentIntoTitleBarChanged();
|
||||
void titleBarItemChanged();
|
||||
void windowFixedSizeChanged();
|
||||
void blurBehindWindowEnabledChanged();
|
||||
void windowChanged2();
|
||||
void attachedChanged();
|
||||
void ready();
|
||||
|
||||
private:
|
||||
|
|
|
@ -50,10 +50,14 @@ public:
|
|||
Q_NODISCARD static FramelessQuickHelperPrivate *get(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;
|
||||
void setTitleBarItem(QQuickItem *value);
|
||||
|
||||
void attachToWindow();
|
||||
void attach();
|
||||
void detach();
|
||||
void setSystemButton(QQuickItem *item, const QuickGlobal::SystemButtonType buttonType);
|
||||
void setHitTestVisible(QQuickItem *item, 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);
|
||||
Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {});
|
||||
|
||||
Q_NODISCARD bool isAttached() const;
|
||||
|
||||
protected:
|
||||
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 blurBehindWindowEnabled READ isBlurBehindWindowEnabled WRITE setBlurBehindWindowEnabled NOTIFY blurBehindWindowEnabledChanged 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:
|
||||
explicit FramelessWidgetsHelper(QObject *parent = nullptr);
|
||||
|
@ -56,10 +56,11 @@ public:
|
|||
Q_NODISCARD bool isWindowFixedSize() const;
|
||||
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
||||
Q_NODISCARD QWidget *window() const;
|
||||
Q_NODISCARD bool isAttached() const;
|
||||
Q_NODISCARD bool isContentExtendedIntoTitleBar() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void extendsContentIntoTitleBar();
|
||||
[[deprecated("Use the extendsContentIntoTitleBar property instead.")]] void extendsContentIntoTitleBar();
|
||||
void setContentExtendedIntoTitleBar(const bool value);
|
||||
|
||||
void setTitleBarWidget(QWidget *widget);
|
||||
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
||||
|
@ -76,11 +77,11 @@ public Q_SLOTS:
|
|||
void setBlurBehindWindowEnabled(const bool value);
|
||||
|
||||
Q_SIGNALS:
|
||||
void extendsContentIntoTitleBarChanged();
|
||||
void titleBarWidgetChanged();
|
||||
void windowFixedSizeChanged();
|
||||
void blurBehindWindowEnabledChanged();
|
||||
void windowChanged();
|
||||
void attachedChanged();
|
||||
void ready();
|
||||
|
||||
private:
|
||||
|
|
|
@ -46,10 +46,14 @@ public:
|
|||
Q_NODISCARD static FramelessWidgetsHelperPrivate *get(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;
|
||||
void setTitleBarWidget(QWidget *widget);
|
||||
|
||||
void attachToWindow();
|
||||
void attach();
|
||||
void detach();
|
||||
void setSystemButton(QWidget *widget, const Global::SystemButtonType buttonType);
|
||||
void setHitTestVisible(QWidget *widget, 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 QWidget *window() const;
|
||||
Q_NODISCARD bool isAttached() const;
|
||||
|
||||
private:
|
||||
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const;
|
||||
|
|
|
@ -106,6 +106,24 @@ void FramelessHelperQt::addWindow(const SystemParameters ¶ms)
|
|||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if ((eventType != kWin32MessageTypeName) || !message || !result) {
|
||||
|
|
|
@ -54,10 +54,15 @@ Q_LOGGING_CATEGORY(lcFramelessManager, "wangwenx190.framelesshelper.core.framele
|
|||
|
||||
using namespace Global;
|
||||
|
||||
struct FramelessManagerHelperData
|
||||
{
|
||||
QMetaObject::Connection screenChangeConnection = {};
|
||||
};
|
||||
|
||||
struct FramelessManagerHelper
|
||||
{
|
||||
QMutex mutex;
|
||||
QList<WId> windowIds = {};
|
||||
QHash<WId, FramelessManagerHelperData> data = {};
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(FramelessManagerHelper, g_helper)
|
||||
|
@ -182,24 +187,22 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms)
|
|||
}
|
||||
const WId windowId = params.getWindowId();
|
||||
g_helper()->mutex.lock();
|
||||
if (g_helper()->windowIds.contains(windowId)) {
|
||||
if (g_helper()->data.contains(windowId)) {
|
||||
g_helper()->mutex.unlock();
|
||||
return;
|
||||
}
|
||||
g_helper()->windowIds.append(windowId);
|
||||
g_helper()->data.insert(windowId, {});
|
||||
g_helper()->mutex.unlock();
|
||||
static const bool pureQt = []() -> bool {
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}();
|
||||
QMetaObject::Connection screenChangeConnection = {};
|
||||
static const bool pureQt = usePureQtImplementation();
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (!pureQt) {
|
||||
// Work-around Win32 multi-monitor artifacts.
|
||||
QWindow * const window = params.getWindowHandle();
|
||||
Q_ASSERT(window);
|
||||
if (window) {
|
||||
g_helper()->mutex.lock();
|
||||
g_helper()->data[windowId].screenChangeConnection =
|
||||
connect(window, &QWindow::screenChanged, window, [windowId, window](QScreen *screen){
|
||||
Q_UNUSED(screen);
|
||||
// Force a WM_NCCALCSIZE event to inform Windows about our custom window frame,
|
||||
|
@ -211,6 +214,8 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms)
|
|||
// observed disappeared indeed, amazingly.
|
||||
window->resize(window->size());
|
||||
});
|
||||
g_helper()->mutex.unlock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (pureQt) {
|
||||
|
@ -225,6 +230,37 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms)
|
|||
#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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
const QMutexLocker locker(&g_helper()->mutex);
|
||||
|
@ -342,4 +390,10 @@ void FramelessManager::addWindow(const SystemParameters ¶ms)
|
|||
d->addWindow(params);
|
||||
}
|
||||
|
||||
void FramelessManager::removeWindow(const WId windowId)
|
||||
{
|
||||
Q_D(FramelessManager);
|
||||
d->removeWindow(windowId);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -1154,30 +1154,32 @@ void Utils::fixupQtInternals(const WId windowId)
|
|||
if (qEnvironmentVariableIntValue(kNoFixQtInternalEnvVar)) {
|
||||
return;
|
||||
}
|
||||
bool shouldUpdateFrame = false;
|
||||
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
const auto oldClassStyle = static_cast<DWORD>(GetClassLongPtrW(hwnd, GCL_STYLE));
|
||||
if (oldClassStyle == 0) {
|
||||
WARNING << getSystemErrorMessage(kGetClassLongPtrW);
|
||||
return;
|
||||
}
|
||||
const auto classStyle = static_cast<DWORD>(GetClassLongPtrW(hwnd, GCL_STYLE));
|
||||
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.
|
||||
// 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));
|
||||
// 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>(newClassStyle)) == 0) {
|
||||
if (SetClassLongPtrW(hwnd, GCL_STYLE,
|
||||
static_cast<LONG_PTR>(classStyle & ~badClassStyle)) == 0) {
|
||||
WARNING << getSystemErrorMessage(kSetClassLongPtrW);
|
||||
return;
|
||||
} else {
|
||||
shouldUpdateFrame = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
WARNING << getSystemErrorMessage(kGetClassLongPtrW);
|
||||
}
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
const auto oldWindowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
|
||||
if (oldWindowStyle == 0) {
|
||||
WARNING << getSystemErrorMessage(kGetWindowLongPtrW);
|
||||
return;
|
||||
}
|
||||
const auto windowStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_STYLE));
|
||||
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
|
||||
|
@ -1185,16 +1187,24 @@ void Utils::fixupQtInternals(const WId windowId)
|
|||
// 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 =
|
||||
static constexpr const DWORD goodWindowStyle =
|
||||
(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
|
||||
const DWORD newWindowStyle = ((oldWindowStyle & ~WS_POPUP) | normalWindowStyle);
|
||||
if (!(windowStyle & goodWindowStyle)) {
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
if (SetWindowLongPtrW(hwnd, GWL_STYLE, static_cast<LONG_PTR>(newWindowStyle)) == 0) {
|
||||
if (SetWindowLongPtrW(hwnd, GWL_STYLE,
|
||||
static_cast<LONG_PTR>((windowStyle & ~WS_POPUP) | goodWindowStyle)) == 0) {
|
||||
WARNING << getSystemErrorMessage(kSetWindowLongPtrW);
|
||||
return;
|
||||
} else {
|
||||
shouldUpdateFrame = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
WARNING << getSystemErrorMessage(kGetWindowLongPtrW);
|
||||
}
|
||||
if (shouldUpdateFrame) {
|
||||
triggerFrameChange(windowId);
|
||||
}
|
||||
}
|
||||
|
||||
void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ using namespace Global;
|
|||
|
||||
struct QuickHelperData
|
||||
{
|
||||
bool attached = false;
|
||||
bool ready = false;
|
||||
SystemParameters params = {};
|
||||
QPointer<QQuickItem> titleBarItem = nullptr;
|
||||
QList<QPointer<QQuickItem>> hitTestVisibleItems = {};
|
||||
|
@ -97,11 +97,14 @@ FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q
|
|||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
FramelessQuickHelperPrivate::~FramelessQuickHelperPrivate() = default;
|
||||
FramelessQuickHelperPrivate::~FramelessQuickHelperPrivate()
|
||||
{
|
||||
detach();
|
||||
}
|
||||
|
||||
FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(FramelessQuickHelper *pub)
|
||||
{
|
||||
|
@ -121,6 +124,24 @@ const FramelessQuickHelperPrivate *FramelessQuickHelperPrivate::get(const Framel
|
|||
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
|
||||
{
|
||||
return getWindowData().titleBarItem;
|
||||
|
@ -144,7 +165,7 @@ void FramelessQuickHelperPrivate::setTitleBarItem(QQuickItem *value)
|
|||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("titleBarItemChanged"));
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::attachToWindow()
|
||||
void FramelessQuickHelperPrivate::attach()
|
||||
{
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
|
@ -154,18 +175,13 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
|||
}
|
||||
|
||||
g_quickHelper()->mutex.lock();
|
||||
QuickHelperData *data = getWindowDataMutable();
|
||||
if (!data) {
|
||||
QuickHelperData * const data = getWindowDataMutable();
|
||||
if (!data || data->ready) {
|
||||
g_quickHelper()->mutex.unlock();
|
||||
return;
|
||||
}
|
||||
const bool attached = data->attached;
|
||||
g_quickHelper()->mutex.unlock();
|
||||
|
||||
if (attached) {
|
||||
return;
|
||||
}
|
||||
|
||||
window->installEventFilter(this);
|
||||
|
||||
SystemParameters params = {};
|
||||
|
@ -208,7 +224,7 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
|||
|
||||
g_quickHelper()->mutex.lock();
|
||||
data->params = params;
|
||||
data->attached = true;
|
||||
data->ready = true;
|
||||
g_quickHelper()->mutex.unlock();
|
||||
|
||||
// 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)) {
|
||||
setBlurBehindWindowEnabled(true, {});
|
||||
}
|
||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("attachedChanged"));
|
||||
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)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
|
@ -512,12 +544,6 @@ QVariant FramelessQuickHelperPrivate::getProperty(const QByteArray &name, const
|
|||
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)
|
||||
{
|
||||
Q_ASSERT(object);
|
||||
|
@ -838,7 +864,7 @@ FramelessQuickHelper *FramelessQuickHelper::get(QObject *object)
|
|||
instance->setParentItem(parentItem);
|
||||
instance->setParent(parent);
|
||||
// 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;
|
||||
}
|
||||
|
@ -870,15 +896,21 @@ bool FramelessQuickHelper::isBlurBehindWindowEnabled() const
|
|||
return d->isBlurBehindWindowEnabled();
|
||||
}
|
||||
|
||||
bool FramelessQuickHelper::isAttached() const
|
||||
bool FramelessQuickHelper::isContentExtendedIntoTitleBar() const
|
||||
{
|
||||
Q_D(const FramelessQuickHelper);
|
||||
return d->isAttached();
|
||||
return d->isContentExtendedIntoTitleBar();
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -988,7 +1020,7 @@ void FramelessQuickHelper::itemChange(const ItemChange change, const ItemChangeD
|
|||
}
|
||||
}
|
||||
Q_D(FramelessQuickHelper);
|
||||
d->attachToWindow();
|
||||
d->attach();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ void FramelessQuickWindowPrivate::initialize()
|
|||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
QQuickItem * const rootItem = q->contentItem();
|
||||
FramelessQuickHelper::get(rootItem)->extendsContentIntoTitleBar();
|
||||
FramelessQuickHelper::get(rootItem)->setContentExtendedIntoTitleBar(true);
|
||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||
m_topBorderRectangle->setZ(999); // Make sure the frame border stays on top of eveything.
|
||||
m_topBorderRectangle->setColor(kDefaultTransparentColor);
|
||||
|
|
|
@ -71,7 +71,7 @@ const FramelessDialogPrivate *FramelessDialogPrivate::get(const FramelessDialog
|
|||
void FramelessDialogPrivate::initialize()
|
||||
{
|
||||
Q_Q(FramelessDialog);
|
||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
||||
FramelessWidgetsHelper::get(q)->setContentExtendedIntoTitleBar(true);
|
||||
m_helper.reset(new WidgetsSharedHelper(this));
|
||||
m_helper->setup(q);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ const FramelessMainWindowPrivate *FramelessMainWindowPrivate::get(const Frameles
|
|||
void FramelessMainWindowPrivate::initialize()
|
||||
{
|
||||
Q_Q(FramelessMainWindow);
|
||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
||||
FramelessWidgetsHelper::get(q)->setContentExtendedIntoTitleBar(true);
|
||||
m_helper.reset(new WidgetsSharedHelper(this));
|
||||
m_helper->setup(q);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ const FramelessWidgetPrivate *FramelessWidgetPrivate::get(const FramelessWidget
|
|||
void FramelessWidgetPrivate::initialize()
|
||||
{
|
||||
Q_Q(FramelessWidget);
|
||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
||||
FramelessWidgetsHelper::get(q)->setContentExtendedIntoTitleBar(true);
|
||||
m_helper.reset(new WidgetsSharedHelper(this));
|
||||
m_helper->setup(q);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ using namespace Global;
|
|||
|
||||
struct WidgetsHelperData
|
||||
{
|
||||
bool attached = false;
|
||||
bool ready = false;
|
||||
SystemParameters params = {};
|
||||
QPointer<QWidget> titleBarWidget = nullptr;
|
||||
QList<QPointer<QWidget>> hitTestVisibleWidgets = {};
|
||||
|
@ -107,7 +107,10 @@ FramelessWidgetsHelperPrivate::FramelessWidgetsHelperPrivate(FramelessWidgetsHel
|
|||
q_ptr = q;
|
||||
}
|
||||
|
||||
FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate() = default;
|
||||
FramelessWidgetsHelperPrivate::~FramelessWidgetsHelperPrivate()
|
||||
{
|
||||
detach();
|
||||
}
|
||||
|
||||
FramelessWidgetsHelperPrivate *FramelessWidgetsHelperPrivate::get(FramelessWidgetsHelper *pub)
|
||||
{
|
||||
|
@ -264,10 +267,9 @@ QWidget *FramelessWidgetsHelperPrivate::window() const
|
|||
return m_window;
|
||||
}
|
||||
|
||||
bool FramelessWidgetsHelperPrivate::isAttached() const
|
||||
bool FramelessWidgetsHelperPrivate::isContentExtendedIntoTitleBar() const
|
||||
{
|
||||
const QMutexLocker locker(&g_widgetsHelper()->mutex);
|
||||
return getWindowData().attached;
|
||||
return getWindowData().ready;
|
||||
}
|
||||
|
||||
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();
|
||||
Q_ASSERT(window);
|
||||
|
@ -346,18 +348,13 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
|
|||
m_window = window;
|
||||
|
||||
g_widgetsHelper()->mutex.lock();
|
||||
WidgetsHelperData *data = getWindowDataMutable();
|
||||
if (!data) {
|
||||
WidgetsHelperData * const data = getWindowDataMutable();
|
||||
if (!data || data->ready) {
|
||||
g_widgetsHelper()->mutex.unlock();
|
||||
return;
|
||||
}
|
||||
const bool attached = data->attached;
|
||||
g_widgetsHelper()->mutex.unlock();
|
||||
|
||||
if (attached) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Without this flag, Qt will always create an invisible native parent window
|
||||
// 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,
|
||||
|
@ -405,7 +402,7 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
|
|||
|
||||
g_widgetsHelper()->mutex.lock();
|
||||
data->params = params;
|
||||
data->attached = true;
|
||||
data->ready = true;
|
||||
g_widgetsHelper()->mutex.unlock();
|
||||
|
||||
// We have to wait for a little time before moving the top level window
|
||||
|
@ -421,11 +418,39 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
|
|||
setBlurBehindWindowEnabled(true, {});
|
||||
}
|
||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("windowChanged"));
|
||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("attachedChanged"));
|
||||
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
|
||||
{
|
||||
Q_Q(const FramelessWidgetsHelper);
|
||||
|
@ -796,7 +821,7 @@ FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *object)
|
|||
FramelessWidgetsHelper *instance = parent->findChild<FramelessWidgetsHelper *>();
|
||||
if (!instance) {
|
||||
instance = new FramelessWidgetsHelper(parent);
|
||||
instance->d_func()->attachToWindow();
|
||||
instance->d_func()->attach();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
@ -825,15 +850,21 @@ QWidget *FramelessWidgetsHelper::window() const
|
|||
return d->window();
|
||||
}
|
||||
|
||||
bool FramelessWidgetsHelper::isAttached() const
|
||||
bool FramelessWidgetsHelper::isContentExtendedIntoTitleBar() const
|
||||
{
|
||||
Q_D(const FramelessWidgetsHelper);
|
||||
return d->isAttached();
|
||||
return d->isContentExtendedIntoTitleBar();
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue