parent
059b8d7982
commit
6ffc894213
|
@ -79,10 +79,10 @@ void MainWindow::setupUi()
|
|||
|
||||
setTitleBarWidget(titleBarWidget);
|
||||
|
||||
setHitTestVisible(titleBar->iconButton, true);
|
||||
setHitTestVisible(titleBar->minimizeButton, true);
|
||||
setHitTestVisible(titleBar->maximizeButton, true);
|
||||
setHitTestVisible(titleBar->closeButton, true);
|
||||
setHitTestVisible(titleBar->iconButton);
|
||||
setHitTestVisible(titleBar->minimizeButton);
|
||||
setHitTestVisible(titleBar->maximizeButton);
|
||||
setHitTestVisible(titleBar->closeButton);
|
||||
|
||||
connect(titleBar->minimizeButton, &QPushButton::clicked, this, &MainWindow::showMinimized);
|
||||
connect(titleBar->maximizeButton, &QPushButton::clicked, this, &MainWindow::toggleMaximized);
|
||||
|
|
|
@ -65,21 +65,21 @@ FramelessWindow {
|
|||
title: window.title
|
||||
minimizeButton {
|
||||
id: minimizeButton
|
||||
onClicked: FramelessUtils.showMinimized2(window)
|
||||
onClicked: window.showMinimized2()
|
||||
}
|
||||
maximizeButton {
|
||||
id: maximizeButton
|
||||
onClicked: FramelessUtils.toggleMaximize(window)
|
||||
onClicked: window.toggleMaximize()
|
||||
}
|
||||
closeButton {
|
||||
id: closeButton
|
||||
onClicked: window.close()
|
||||
}
|
||||
Component.onCompleted: {
|
||||
FramelessHelper.setTitleBarItem(window, titleBar);
|
||||
FramelessHelper.setHitTestVisible(window, minimizeButton, true);
|
||||
FramelessHelper.setHitTestVisible(window, maximizeButton, true);
|
||||
FramelessHelper.setHitTestVisible(window, closeButton, true);
|
||||
window.setTitleBarItem(titleBar);
|
||||
window.setHitTestVisible(minimizeButton);
|
||||
window.setHitTestVisible(maximizeButton);
|
||||
window.setHitTestVisible(closeButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,8 @@ enum class Option : int
|
|||
DisableResizing = 0x00002000, // Disable resizing of the window.
|
||||
DisableDragging = 0x00004000, // Disable dragging through the titlebar of the window.
|
||||
DontTouchCursorShape = 0x00008000, // Don't change the cursor shape while the mouse is hovering above the window.
|
||||
DontMoveWindowToDesktopCenter = 0x00010000 // Don't move the window to the desktop center before shown.
|
||||
DontMoveWindowToDesktopCenter = 0x00010000, // Don't move the window to the desktop center before shown.
|
||||
DontTreatFullScreenAsZoomed = 0x00020000 // Don't treat fullscreen as zoomed (maximized).
|
||||
};
|
||||
Q_DECLARE_FLAGS(Options, Option)
|
||||
Q_FLAG_NS(Options)
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
Q_INVOKABLE static void addWindow(QQuickWindow *window);
|
||||
Q_INVOKABLE static void removeWindow(QQuickWindow *window);
|
||||
Q_INVOKABLE static void setTitleBarItem(QQuickWindow *window, QQuickItem *item);
|
||||
Q_INVOKABLE static void setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible);
|
||||
Q_INVOKABLE static void setHitTestVisible(QQuickWindow *window, QQuickItem *item);
|
||||
|
||||
protected:
|
||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
Q_INVOKABLE static void addWindow(QQuickWindow *window);
|
||||
Q_INVOKABLE static void removeWindow(QQuickWindow *window);
|
||||
Q_INVOKABLE static void setTitleBarItem(QQuickWindow *window, QQuickItem *item);
|
||||
Q_INVOKABLE static void setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible);
|
||||
Q_INVOKABLE static void setHitTestVisible(QQuickWindow *window, QQuickItem *item);
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -47,11 +47,9 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickUtils : public QObject
|
|||
Q_PROPERTY(qreal titleBarHeight READ titleBarHeight CONSTANT FINAL)
|
||||
Q_PROPERTY(bool frameBorderVisible READ frameBorderVisible CONSTANT FINAL)
|
||||
Q_PROPERTY(qreal frameBorderThickness READ frameBorderThickness CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor frameBorderActiveColor READ frameBorderActiveColor NOTIFY frameBorderActiveColorChanged FINAL)
|
||||
Q_PROPERTY(QColor frameBorderInactiveColor READ frameBorderInactiveColor NOTIFY frameBorderInactiveColorChanged FINAL)
|
||||
Q_PROPERTY(bool darkModeEnabled READ darkModeEnabled NOTIFY darkModeEnabledChanged FINAL)
|
||||
Q_PROPERTY(QColor systemAccentColor READ systemAccentColor NOTIFY systemAccentColorChanged FINAL)
|
||||
Q_PROPERTY(bool titleBarColorVisible READ titleBarColorVisible NOTIFY titleBarColorVisibleChanged FINAL)
|
||||
Q_PROPERTY(bool titleBarColorized READ titleBarColorized NOTIFY titleBarColorizedChanged FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemLightColor READ defaultSystemLightColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QColor defaultSystemDarkColor READ defaultSystemDarkColor CONSTANT FINAL)
|
||||
Q_PROPERTY(QSizeF defaultSystemButtonSize READ defaultSystemButtonSize CONSTANT FINAL)
|
||||
|
@ -64,28 +62,18 @@ public:
|
|||
Q_NODISCARD static qreal titleBarHeight();
|
||||
Q_NODISCARD static bool frameBorderVisible();
|
||||
Q_NODISCARD static qreal frameBorderThickness();
|
||||
Q_NODISCARD static QColor frameBorderActiveColor();
|
||||
Q_NODISCARD static QColor frameBorderInactiveColor();
|
||||
Q_NODISCARD static bool darkModeEnabled();
|
||||
Q_NODISCARD static QColor systemAccentColor();
|
||||
Q_NODISCARD static bool titleBarColorVisible();
|
||||
Q_NODISCARD static bool titleBarColorized();
|
||||
Q_NODISCARD static QColor defaultSystemLightColor();
|
||||
Q_NODISCARD static QColor defaultSystemDarkColor();
|
||||
Q_NODISCARD static QSizeF defaultSystemButtonSize();
|
||||
Q_NODISCARD static QSizeF defaultSystemButtonIconSize();
|
||||
|
||||
Q_INVOKABLE static void showMinimized2(QQuickWindow *window);
|
||||
Q_INVOKABLE static void toggleMaximize(QQuickWindow *window);
|
||||
Q_INVOKABLE static void showSystemMenu(QQuickWindow *window, const QPoint &pos);
|
||||
Q_INVOKABLE static void startSystemMove2(QQuickWindow *window);
|
||||
Q_INVOKABLE static void startSystemResize2(QQuickWindow *window, const Qt::Edges edges);
|
||||
|
||||
Q_SIGNALS:
|
||||
void frameBorderActiveColorChanged();
|
||||
void frameBorderInactiveColorChanged();
|
||||
void darkModeEnabledChanged();
|
||||
void systemAccentColorChanged();
|
||||
void titleBarColorVisibleChanged();
|
||||
void titleBarColorizedChanged();
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "framelesshelperquick_global.h"
|
||||
#include <QtQuick/qquickitem.h>
|
||||
#include <QtQuick/qquickwindow.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
@ -34,18 +35,34 @@ class FramelessQuickWindowPrivate;
|
|||
class FRAMELESSHELPER_QUICK_API FramelessQuickWindow : public QQuickWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
#ifdef QML_NAMED_ELEMENT
|
||||
QML_NAMED_ELEMENT(FramelessWindow)
|
||||
#endif
|
||||
Q_DECLARE_PRIVATE(FramelessQuickWindow)
|
||||
Q_DISABLE_COPY_MOVE(FramelessQuickWindow)
|
||||
Q_PROPERTY(bool zoomed READ zoomed NOTIFY zoomedChanged FINAL)
|
||||
Q_PROPERTY(QColor frameBorderColor READ frameBorderColor NOTIFY frameBorderColorChanged FINAL)
|
||||
|
||||
public:
|
||||
explicit FramelessQuickWindow(QWindow *parent = nullptr);
|
||||
explicit FramelessQuickWindow(QWindow *parent = nullptr, const Options options = {});
|
||||
~FramelessQuickWindow() override;
|
||||
|
||||
Q_NODISCARD bool zoomed() const;
|
||||
Q_NODISCARD QColor frameBorderColor() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void showMinimized2();
|
||||
void toggleMaximize();
|
||||
void toggleFullScreen();
|
||||
void showSystemMenu(const QPoint &pos);
|
||||
void startSystemMove2();
|
||||
void startSystemResize2(const Qt::Edges edges);
|
||||
void setTitleBarItem(QQuickItem *item);
|
||||
void setHitTestVisible(QQuickItem *item);
|
||||
|
||||
Q_SIGNALS:
|
||||
void zoomedChanged();
|
||||
void frameBorderColorChanged();
|
||||
|
||||
private:
|
||||
QScopedPointer<FramelessQuickWindowPrivate> d_ptr;
|
||||
|
|
|
@ -47,9 +47,10 @@ public:
|
|||
void setTitleBarWidget(QWidget *widget);
|
||||
Q_NODISCARD QWidget *titleBarWidget() const;
|
||||
|
||||
Q_INVOKABLE void setHitTestVisible(QWidget *widget, const bool visible);
|
||||
Q_INVOKABLE void setHitTestVisible(QWidget *widget);
|
||||
|
||||
Q_INVOKABLE void toggleMaximized();
|
||||
Q_INVOKABLE void toggleFullScreen();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *event) override;
|
||||
|
|
|
@ -51,9 +51,10 @@ public:
|
|||
void setContentWidget(QWidget *widget);
|
||||
Q_NODISCARD QWidget *contentWidget() const;
|
||||
|
||||
Q_INVOKABLE void setHitTestVisible(QWidget *widget, const bool visible);
|
||||
Q_INVOKABLE void setHitTestVisible(QWidget *widget);
|
||||
|
||||
Q_INVOKABLE void toggleMaximized();
|
||||
Q_INVOKABLE void toggleFullScreen();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *event) override;
|
||||
|
|
|
@ -57,9 +57,10 @@ public:
|
|||
Q_INVOKABLE void setContentWidget(QWidget *widget);
|
||||
Q_NODISCARD Q_INVOKABLE QWidget *contentWidget() const;
|
||||
|
||||
Q_INVOKABLE void setHitTestVisible(QWidget *widget, const bool visible);
|
||||
Q_INVOKABLE void setHitTestVisible(QWidget *widget);
|
||||
|
||||
Q_INVOKABLE void toggleMaximized();
|
||||
Q_INVOKABLE void toggleFullScreen();
|
||||
|
||||
Q_INVOKABLE void changeEventHandler(QEvent *event);
|
||||
Q_INVOKABLE void paintEventHandler(QPaintEvent *event);
|
||||
|
@ -96,6 +97,8 @@ private:
|
|||
QWidgetList m_hitTestVisibleWidgets = {};
|
||||
QWidget *m_userContentContainerWidget = nullptr;
|
||||
QVBoxLayout *m_userContentContainerLayout = nullptr;
|
||||
Qt::WindowStates m_savedWindowState = {};
|
||||
QWindow *m_window = nullptr;
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -30,11 +30,17 @@
|
|||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
struct QtHelperInternalData
|
||||
{
|
||||
QWindow *window = nullptr;
|
||||
FramelessHelperQt *qtFramelessHelper = nullptr;
|
||||
Options options = {};
|
||||
};
|
||||
|
||||
struct QtHelper
|
||||
{
|
||||
QMutex mutex = {};
|
||||
QHash<QWindow *, FramelessHelperQt *> qtFramelessHelpers = {};
|
||||
QHash<QWindow *, Options> options = {};
|
||||
QHash<QWindow *, QtHelperInternalData> data = {};
|
||||
|
||||
explicit QtHelper() = default;
|
||||
~QtHelper() = default;
|
||||
|
@ -56,18 +62,19 @@ void FramelessHelperQt::addWindow(QWindow *window)
|
|||
return;
|
||||
}
|
||||
g_qtHelper()->mutex.lock();
|
||||
if (g_qtHelper()->qtFramelessHelpers.contains(window)) {
|
||||
if (g_qtHelper()->data.contains(window)) {
|
||||
g_qtHelper()->mutex.unlock();
|
||||
return;
|
||||
}
|
||||
const auto options = qvariant_cast<Options>(window->property(kInternalOptionsFlag));
|
||||
g_qtHelper()->options.insert(window, options);
|
||||
QtHelperInternalData data = {};
|
||||
data.window = window;
|
||||
// Give it a parent so that it can be deleted even if we forget to do so.
|
||||
const auto qtFramelessHelper = new FramelessHelperQt(window);
|
||||
g_qtHelper()->qtFramelessHelpers.insert(window, qtFramelessHelper);
|
||||
data.qtFramelessHelper = new FramelessHelperQt(window);
|
||||
data.options = qvariant_cast<Options>(window->property(kInternalOptionsFlag));
|
||||
g_qtHelper()->data.insert(window, data);
|
||||
g_qtHelper()->mutex.unlock();
|
||||
window->setFlags(window->flags() | Qt::FramelessWindowHint);
|
||||
window->installEventFilter(qtFramelessHelper);
|
||||
window->installEventFilter(data.qtFramelessHelper);
|
||||
}
|
||||
|
||||
void FramelessHelperQt::removeWindow(QWindow *window)
|
||||
|
@ -77,17 +84,15 @@ void FramelessHelperQt::removeWindow(QWindow *window)
|
|||
return;
|
||||
}
|
||||
g_qtHelper()->mutex.lock();
|
||||
if (!g_qtHelper()->qtFramelessHelpers.contains(window)) {
|
||||
if (!g_qtHelper()->data.contains(window)) {
|
||||
g_qtHelper()->mutex.unlock();
|
||||
return;
|
||||
}
|
||||
g_qtHelper()->options.remove(window);
|
||||
FramelessHelperQt *qtFramelessHelper = g_qtHelper()->qtFramelessHelpers.value(window);
|
||||
g_qtHelper()->qtFramelessHelpers.remove(window);
|
||||
const QtHelperInternalData data = g_qtHelper()->data.value(window);
|
||||
g_qtHelper()->data.remove(window);
|
||||
g_qtHelper()->mutex.unlock();
|
||||
window->removeEventFilter(qtFramelessHelper);
|
||||
delete qtFramelessHelper;
|
||||
qtFramelessHelper = nullptr;
|
||||
window->removeEventFilter(data.qtFramelessHelper);
|
||||
delete data.qtFramelessHelper;
|
||||
window->setFlags(window->flags() & ~Qt::FramelessWindowHint);
|
||||
}
|
||||
|
||||
|
@ -109,11 +114,11 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
|||
}
|
||||
const auto window = qobject_cast<QWindow *>(object);
|
||||
g_qtHelper()->mutex.lock();
|
||||
if (!g_qtHelper()->qtFramelessHelpers.contains(window)) {
|
||||
if (!g_qtHelper()->data.contains(window)) {
|
||||
g_qtHelper()->mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
const Options options = g_qtHelper()->options.value(window);
|
||||
const QtHelperInternalData data = g_qtHelper()->data.value(window);
|
||||
g_qtHelper()->mutex.unlock();
|
||||
if (Utils::isWindowFixedSize(window)) {
|
||||
return false;
|
||||
|
@ -126,7 +131,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
|||
#endif
|
||||
switch (type) {
|
||||
case QEvent::MouseMove: {
|
||||
if (options & Option::DontTouchCursorShape) {
|
||||
if (data.options & Option::DontTouchCursorShape) {
|
||||
return false;
|
||||
}
|
||||
const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos);
|
||||
|
|
|
@ -53,11 +53,18 @@ Q_DECLARE_METATYPE(QMargins)
|
|||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
struct Win32UtilsInternalData
|
||||
{
|
||||
HWND hwnd = nullptr;
|
||||
QWindow *window = nullptr;
|
||||
WNDPROC originalWindowProc = nullptr;
|
||||
Options options = {};
|
||||
};
|
||||
|
||||
struct Win32UtilsHelper
|
||||
{
|
||||
QMutex mutex = {};
|
||||
QHash<HWND, WNDPROC> qtWindowProcs = {};
|
||||
QHash<HWND, QWindow *> windowMapping = {};
|
||||
QHash<HWND, Win32UtilsInternalData> data = {};
|
||||
|
||||
explicit Win32UtilsHelper() = default;
|
||||
~Win32UtilsHelper() = default;
|
||||
|
@ -178,28 +185,28 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
|||
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
|
||||
{
|
||||
g_utilsHelper()->mutex.lock();
|
||||
if (!g_utilsHelper()->qtWindowProcs.contains(hWnd)) {
|
||||
g_utilsHelper()->mutex.unlock();
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
const QWindow * const window = g_utilsHelper()->windowMapping.value(hWnd);
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
if (!g_utilsHelper()->data.contains(hWnd)) {
|
||||
g_utilsHelper()->mutex.unlock();
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
const Win32UtilsInternalData data = g_utilsHelper()->data.value(hWnd);
|
||||
g_utilsHelper()->mutex.unlock();
|
||||
Q_ASSERT(data.window);
|
||||
if (!data.window) {
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
const auto winId = reinterpret_cast<WId>(hWnd);
|
||||
const auto getGlobalPosFromMouse = [lParam]() -> QPoint {
|
||||
return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||
};
|
||||
const auto getGlobalPosFromKeyboard = [hWnd, winId]() -> QPoint {
|
||||
const auto getGlobalPosFromKeyboard = [hWnd, winId, &data]() -> QPoint {
|
||||
RECT windowPos = {};
|
||||
if (GetWindowRect(hWnd, &windowPos) == FALSE) {
|
||||
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetWindowRect"));
|
||||
return {};
|
||||
}
|
||||
const bool maxOrFull = (IsMaximized(hWnd) || Utils::isFullScreen(winId));
|
||||
const bool maxOrFull = (IsMaximized(hWnd) ||
|
||||
((data.options & Option::DontTreatFullScreenAsZoomed) ? false : Utils::isFullScreen(winId)));
|
||||
const int frameSizeX = Utils::getResizeBorderThickness(winId, true, true);
|
||||
const bool frameBorderVisible = Utils::isWindowFrameBorderVisible();
|
||||
const int horizontalOffset = ((maxOrFull || !frameBorderVisible) ? 0 : frameSizeX);
|
||||
|
@ -244,21 +251,18 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
|||
}
|
||||
}
|
||||
if (shouldShowSystemMenu) {
|
||||
Utils::showSystemMenu(window, globalPos);
|
||||
Utils::showSystemMenu(data.window, globalPos);
|
||||
// QPA's internal code will handle system menu events separately, and its
|
||||
// behavior is not what we would want to see because it doesn't know our
|
||||
// window doesn't have any window frame now, so return early here to avoid
|
||||
// entering Qt's own handling logic.
|
||||
return 0; // Return 0 means we have handled this event.
|
||||
}
|
||||
g_utilsHelper()->mutex.lock();
|
||||
const WNDPROC originalWindowProc = g_utilsHelper()->qtWindowProcs.value(hWnd);
|
||||
g_utilsHelper()->mutex.unlock();
|
||||
Q_ASSERT(originalWindowProc);
|
||||
if (originalWindowProc) {
|
||||
Q_ASSERT(data.originalWindowProc);
|
||||
if (data.originalWindowProc) {
|
||||
// Hand over to Qt's original window proc function for events we are not
|
||||
// interested in.
|
||||
return CallWindowProcW(originalWindowProc, hWnd, uMsg, wParam, lParam);
|
||||
return CallWindowProcW(data.originalWindowProc, hWnd, uMsg, wParam, lParam);
|
||||
} else {
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
@ -519,9 +523,10 @@ void Utils::showSystemMenu(const QWindow *window, const QPoint &pos)
|
|||
}
|
||||
return true;
|
||||
};
|
||||
const bool maxOrFull = (IsMaximized(hWnd) || isFullScreen(reinterpret_cast<WId>(hWnd)));
|
||||
const bool fixedSize = isWindowFixedSize(window);
|
||||
const auto options = qvariant_cast<Options>(window->property(kInternalOptionsFlag));
|
||||
const bool maxOrFull = (IsMaximized(hWnd) ||
|
||||
((options & Option::DontTreatFullScreenAsZoomed) ? false : isFullScreen(reinterpret_cast<WId>(hWnd))));
|
||||
const bool fixedSize = isWindowFixedSize(window);
|
||||
if (!setState(SC_RESTORE, (maxOrFull && !fixedSize), true)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1027,7 +1032,7 @@ void Utils::installSystemMenuHook(const QWindow *window)
|
|||
}
|
||||
const auto hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
QMutexLocker locker(&g_utilsHelper()->mutex);
|
||||
if (g_utilsHelper()->qtWindowProcs.contains(hwnd)) {
|
||||
if (g_utilsHelper()->data.contains(hwnd)) {
|
||||
return;
|
||||
}
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
|
@ -1043,8 +1048,12 @@ void Utils::installSystemMenuHook(const QWindow *window)
|
|||
return;
|
||||
}
|
||||
//triggerFrameChange(winId);
|
||||
g_utilsHelper()->qtWindowProcs.insert(hwnd, originalWindowProc);
|
||||
g_utilsHelper()->windowMapping.insert(hwnd, const_cast<QWindow *>(window));
|
||||
Win32UtilsInternalData data = {};
|
||||
data.hwnd = hwnd;
|
||||
data.window = const_cast<QWindow *>(window);
|
||||
data.originalWindowProc = originalWindowProc;
|
||||
data.options = qvariant_cast<Options>(window->property(kInternalOptionsFlag));
|
||||
g_utilsHelper()->data.insert(hwnd, data);
|
||||
}
|
||||
|
||||
void Utils::uninstallSystemMenuHook(const WId winId)
|
||||
|
@ -1055,22 +1064,21 @@ void Utils::uninstallSystemMenuHook(const WId winId)
|
|||
}
|
||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
||||
QMutexLocker locker(&g_utilsHelper()->mutex);
|
||||
if (!g_utilsHelper()->qtWindowProcs.contains(hwnd)) {
|
||||
if (!g_utilsHelper()->data.contains(hwnd)) {
|
||||
return;
|
||||
}
|
||||
const WNDPROC originalWindowProc = g_utilsHelper()->qtWindowProcs.value(hwnd);
|
||||
Q_ASSERT(originalWindowProc);
|
||||
if (!originalWindowProc) {
|
||||
const Win32UtilsInternalData data = g_utilsHelper()->data.value(hwnd);
|
||||
Q_ASSERT(data.originalWindowProc);
|
||||
if (!data.originalWindowProc) {
|
||||
return;
|
||||
}
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(originalWindowProc)) == 0) {
|
||||
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(data.originalWindowProc)) == 0) {
|
||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||
return;
|
||||
}
|
||||
//triggerFrameChange(winId);
|
||||
g_utilsHelper()->qtWindowProcs.remove(hwnd);
|
||||
g_utilsHelper()->windowMapping.remove(hwnd);
|
||||
g_utilsHelper()->data.remove(hwnd);
|
||||
}
|
||||
|
||||
void Utils::sendMouseReleaseEvent()
|
||||
|
|
|
@ -58,7 +58,7 @@ if(MSVC)
|
|||
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_CO}
|
||||
)
|
||||
target_compile_options(${SUB_PROJ_NAME} PRIVATE
|
||||
/W4 /WX
|
||||
/utf-8 /W4 /WX
|
||||
)
|
||||
else()
|
||||
target_compile_options(${SUB_PROJ_NAME} PRIVATE
|
||||
|
|
|
@ -147,7 +147,7 @@ void FramelessQuickEventFilter::setTitleBarItem(QQuickWindow *window, QQuickItem
|
|||
g_data()->data[window].titleBarItem = item;
|
||||
}
|
||||
|
||||
void FramelessQuickEventFilter::setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible)
|
||||
void FramelessQuickEventFilter::setHitTestVisible(QQuickWindow *window, QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
Q_ASSERT(item);
|
||||
|
@ -159,11 +159,12 @@ void FramelessQuickEventFilter::setHitTestVisible(QQuickWindow *window, QQuickIt
|
|||
return;
|
||||
}
|
||||
auto &items = g_data()->data[window].hitTestVisibleItems;
|
||||
static constexpr const bool visible = true;
|
||||
const bool exists = items.contains(item);
|
||||
if (visible && !exists) {
|
||||
items.append(item);
|
||||
}
|
||||
if (!visible && exists) {
|
||||
if constexpr (!visible && exists) {
|
||||
items.removeAll(item);
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +247,7 @@ bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
|
|||
return true;
|
||||
}
|
||||
case QEvent::MouseButtonDblClick: {
|
||||
if ((options & Option::NoDoubleClickMaximizeToggle) || (options & Option::DisableResizing)) {
|
||||
if ((options & Option::NoDoubleClickMaximizeToggle) || Utils::isWindowFixedSize(window)) {
|
||||
return false;
|
||||
}
|
||||
if (button != Qt::LeftButton) {
|
||||
|
@ -255,7 +256,8 @@ bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
|
|||
if (!titleBar) {
|
||||
return false;
|
||||
}
|
||||
if ((visibility == QQuickWindow::Maximized) || (visibility == QQuickWindow::FullScreen)) {
|
||||
if ((visibility == QQuickWindow::Maximized) ||
|
||||
((options & Option::DontTreatFullScreenAsZoomed) ? false : (visibility == QQuickWindow::FullScreen))) {
|
||||
window->showNormal();
|
||||
} else {
|
||||
window->showMaximized();
|
||||
|
|
|
@ -63,14 +63,14 @@ void FramelessQuickHelper::setTitleBarItem(QQuickWindow *window, QQuickItem *ite
|
|||
FramelessQuickEventFilter::setTitleBarItem(window, item);
|
||||
}
|
||||
|
||||
void FramelessQuickHelper::setHitTestVisible(QQuickWindow *window, QQuickItem *item, const bool visible)
|
||||
void FramelessQuickHelper::setHitTestVisible(QQuickWindow *window, QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
Q_ASSERT(item);
|
||||
if (!window || !item) {
|
||||
return;
|
||||
}
|
||||
FramelessQuickEventFilter::setHitTestVisible(window, item, visible);
|
||||
FramelessQuickEventFilter::setHitTestVisible(window, item);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -23,27 +23,21 @@
|
|||
*/
|
||||
|
||||
#include "framelessquickutils.h"
|
||||
#include <QtQuick/qquickwindow.h>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))
|
||||
# include <QtGui/qpa/qplatformtheme.h>
|
||||
# include <QtGui/private/qguiapplication_p.h>
|
||||
#endif
|
||||
#include <framelesswindowsmanager.h>
|
||||
#include <utils.h>
|
||||
#ifdef Q_OS_WINDOWS
|
||||
# include <framelesshelper_windows.h>
|
||||
#endif
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
FramelessQuickUtils::FramelessQuickUtils(QObject *parent) : QObject(parent)
|
||||
{
|
||||
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, [this](){
|
||||
Q_EMIT frameBorderActiveColorChanged();
|
||||
Q_EMIT frameBorderInactiveColorChanged();
|
||||
Q_EMIT darkModeEnabledChanged();
|
||||
Q_EMIT systemAccentColorChanged();
|
||||
Q_EMIT titleBarColorVisibleChanged();
|
||||
Q_EMIT titleBarColorizedChanged();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -51,7 +45,7 @@ FramelessQuickUtils::~FramelessQuickUtils() = default;
|
|||
|
||||
qreal FramelessQuickUtils::titleBarHeight()
|
||||
{
|
||||
return 30;
|
||||
return 30.0;
|
||||
}
|
||||
|
||||
bool FramelessQuickUtils::frameBorderVisible()
|
||||
|
@ -65,25 +59,7 @@ bool FramelessQuickUtils::frameBorderVisible()
|
|||
|
||||
qreal FramelessQuickUtils::frameBorderThickness()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::frameBorderActiveColor()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return Utils::getFrameBorderColor(true);
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::frameBorderInactiveColor()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return Utils::getFrameBorderColor(false);
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
bool FramelessQuickUtils::darkModeEnabled()
|
||||
|
@ -111,7 +87,7 @@ QColor FramelessQuickUtils::systemAccentColor()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool FramelessQuickUtils::titleBarColorVisible()
|
||||
bool FramelessQuickUtils::titleBarColorized()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return Utils::isTitleBarColorized();
|
||||
|
@ -140,81 +116,4 @@ QSizeF FramelessQuickUtils::defaultSystemButtonIconSize()
|
|||
return kDefaultSystemButtonIconSize;
|
||||
}
|
||||
|
||||
void FramelessQuickUtils::showMinimized2(QQuickWindow *window)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
// Work-around a QtQuick bug: https://bugreports.qt.io/browse/QTBUG-69711
|
||||
// Don't use "SW_SHOWMINIMIZED" because it will activate the current window
|
||||
// instead of the next window in the Z order, which is not the default behavior
|
||||
// of native Win32 applications.
|
||||
ShowWindow(reinterpret_cast<HWND>(window->winId()), SW_MINIMIZE);
|
||||
#else
|
||||
window->showMinimized();
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickUtils::toggleMaximize(QQuickWindow *window)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
const QQuickWindow::Visibility visibility = window->visibility();
|
||||
if ((visibility == QQuickWindow::Maximized) || (visibility == QQuickWindow::FullScreen)) {
|
||||
window->showNormal();
|
||||
} else {
|
||||
window->showMaximized();
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessQuickUtils::showSystemMenu(QQuickWindow *window, const QPoint &pos)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
const QPoint globalPos = window->mapToGlobal(pos);
|
||||
# else
|
||||
const QPoint globalPos = window->mapToGlobal(pos);
|
||||
# endif
|
||||
const QPoint nativePos = QPointF(QPointF(globalPos) * window->effectiveDevicePixelRatio()).toPoint();
|
||||
Utils::showSystemMenu(window, nativePos);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickUtils::startSystemMove2(QQuickWindow *window)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
window->startSystemMove();
|
||||
#else
|
||||
Utils::startSystemMove(window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickUtils::startSystemResize2(QQuickWindow *window, const Qt::Edges edges)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
if (edges == Qt::Edges{}) {
|
||||
return;
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
window->startSystemResize(edges);
|
||||
#else
|
||||
Utils::startSystemResize(window, edges);
|
||||
#endif
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -29,16 +29,18 @@
|
|||
#include <QtQuick/private/qquickanchors_p.h>
|
||||
#include <framelesswindowsmanager.h>
|
||||
#include <utils.h>
|
||||
#include "framelessquickhelper.h"
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q) : QObject(q)
|
||||
FramelessQuickWindowPrivate::FramelessQuickWindowPrivate(FramelessQuickWindow *q, const Options options) : QObject(q)
|
||||
{
|
||||
Q_ASSERT(q);
|
||||
if (!q) {
|
||||
return;
|
||||
}
|
||||
q_ptr = q;
|
||||
m_options = options;
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
@ -48,45 +50,191 @@ bool FramelessQuickWindowPrivate::isZoomed() const
|
|||
{
|
||||
Q_Q(const FramelessQuickWindow);
|
||||
const FramelessQuickWindow::Visibility visibility = q->visibility();
|
||||
return ((visibility == FramelessQuickWindow::Maximized) || (visibility == FramelessQuickWindow::FullScreen));
|
||||
return ((visibility == FramelessQuickWindow::Maximized) ||
|
||||
((m_options & Option::DontTreatFullScreenAsZoomed) ? false : (visibility == FramelessQuickWindow::FullScreen)));
|
||||
}
|
||||
|
||||
QColor FramelessQuickWindowPrivate::getFrameBorderColor() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Q_Q(const FramelessQuickWindow);
|
||||
return Utils::getFrameBorderColor(q->isActive());
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setTitleBarItem(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
FramelessQuickHelper::setTitleBarItem(q, item);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::setHitTestVisible(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
FramelessQuickHelper::setHitTestVisible(q, item);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::showMinimized2()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
#ifdef Q_OS_WINDOWS
|
||||
// Work-around a QtQuick bug: https://bugreports.qt.io/browse/QTBUG-69711
|
||||
// Don't use "SW_SHOWMINIMIZED" because it will activate the current window
|
||||
// instead of the next window in the Z order, which is not the default behavior
|
||||
// of native Win32 applications.
|
||||
ShowWindow(reinterpret_cast<HWND>(q->winId()), SW_MINIMIZE);
|
||||
#else
|
||||
q->showMinimized();
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::toggleMaximize()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (Utils::isWindowFixedSize(q)) {
|
||||
return;
|
||||
}
|
||||
if (isZoomed()) {
|
||||
q->showNormal();
|
||||
} else {
|
||||
q->showMaximized();
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::toggleFullScreen()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (Utils::isWindowFixedSize(q)) {
|
||||
return;
|
||||
}
|
||||
const QWindow::Visibility visibility = q->visibility();
|
||||
if (visibility == QWindow::FullScreen) {
|
||||
q->setVisibility(m_savedVisibility);
|
||||
} else {
|
||||
m_savedVisibility = visibility;
|
||||
q->showFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::showSystemMenu(const QPoint &pos)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Q_Q(FramelessQuickWindow);
|
||||
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
const QPoint globalPos = q->mapToGlobal(pos);
|
||||
# else
|
||||
const QPoint globalPos = q->mapToGlobal(pos);
|
||||
# endif
|
||||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->effectiveDevicePixelRatio()).toPoint();
|
||||
Utils::showSystemMenu(q, nativePos);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::startSystemMove2()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
q->startSystemMove();
|
||||
#else
|
||||
Utils::startSystemMove(q);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::startSystemResize2(const Qt::Edges edges)
|
||||
{
|
||||
if (edges == Qt::Edges{}) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
if (Utils::isWindowFixedSize(q)) {
|
||||
return;
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
q->startSystemResize(edges);
|
||||
#else
|
||||
Utils::startSystemResize(q, edges);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::initialize()
|
||||
{
|
||||
if (m_initialized) {
|
||||
return;
|
||||
}
|
||||
m_initialized = true;
|
||||
Q_Q(FramelessQuickWindow);
|
||||
FramelessWindowsManager * const manager = FramelessWindowsManager::instance();
|
||||
manager->addWindow(q);
|
||||
QQuickItem * const rootItem = q->contentItem();
|
||||
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||
updateTopBorderHeight();
|
||||
updateTopBorderColor();
|
||||
connect(q, &FramelessQuickWindow::visibilityChanged, this, &FramelessQuickWindowPrivate::updateTopBorderHeight);
|
||||
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||
const auto topBorderAnchors = new QQuickAnchors(m_topBorderRectangle.data(), m_topBorderRectangle.data());
|
||||
topBorderAnchors->setTop(rootItemPrivate->top());
|
||||
topBorderAnchors->setLeft(rootItemPrivate->left());
|
||||
topBorderAnchors->setRight(rootItemPrivate->right());
|
||||
connect(q, &FramelessQuickWindow::visibilityChanged, q, &FramelessQuickWindow::zoomedChanged);
|
||||
q->setProperty(kInternalOptionsFlag, QVariant::fromValue(m_options));
|
||||
FramelessQuickHelper::addWindow(q);
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (isFrameBorderVisible()) {
|
||||
QQuickItem * const rootItem = q->contentItem();
|
||||
const QQuickItemPrivate * const rootItemPrivate = QQuickItemPrivate::get(rootItem);
|
||||
m_topBorderRectangle.reset(new QQuickRectangle(rootItem));
|
||||
updateTopBorderHeight();
|
||||
updateTopBorderColor();
|
||||
connect(q, &FramelessQuickWindow::visibilityChanged, this, [this, q](){
|
||||
updateTopBorderHeight();
|
||||
Q_EMIT q->zoomedChanged();
|
||||
});
|
||||
connect(q, &FramelessQuickWindow::activeChanged, this, &FramelessQuickWindowPrivate::updateTopBorderColor);
|
||||
connect(FramelessWindowsManager::instance(), &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
|
||||
Utils::moveWindowToDesktopCenter([q]() -> QScreen * { return q->screen(); },
|
||||
[q]() -> QSize { return q->size(); },
|
||||
[q](const int x, const int y) -> void {
|
||||
q->setX(x);
|
||||
q->setY(y);
|
||||
}, true);
|
||||
}
|
||||
|
||||
bool FramelessQuickWindowPrivate::isFrameBorderVisible() const
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::updateTopBorderColor()
|
||||
{
|
||||
Q_Q(FramelessQuickWindow);
|
||||
m_topBorderRectangle->setColor(Utils::getFrameBorderColor(q->isActive()));
|
||||
if (!isFrameBorderVisible()) {
|
||||
return;
|
||||
}
|
||||
m_topBorderRectangle->setColor(getFrameBorderColor());
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::updateTopBorderHeight()
|
||||
{
|
||||
if (!isFrameBorderVisible()) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickWindow);
|
||||
const qreal newHeight = ((q->visibility() == FramelessQuickWindow::Windowed) ? 1.0 : 0.0);
|
||||
m_topBorderRectangle->setHeight(newHeight);
|
||||
}
|
||||
|
||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent) : QQuickWindow(parent)
|
||||
FramelessQuickWindow::FramelessQuickWindow(QWindow *parent, const Options options) : QQuickWindow(parent)
|
||||
{
|
||||
d_ptr.reset(new FramelessQuickWindowPrivate(this));
|
||||
d_ptr.reset(new FramelessQuickWindowPrivate(this, options));
|
||||
}
|
||||
|
||||
FramelessQuickWindow::~FramelessQuickWindow() = default;
|
||||
|
@ -97,4 +245,66 @@ bool FramelessQuickWindow::zoomed() const
|
|||
return d->isZoomed();
|
||||
}
|
||||
|
||||
QColor FramelessQuickWindow::frameBorderColor() const
|
||||
{
|
||||
Q_D(const FramelessQuickWindow);
|
||||
return d->getFrameBorderColor();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::setTitleBarItem(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->setTitleBarItem(item);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::setHitTestVisible(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->setHitTestVisible(item);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::showMinimized2()
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->showMinimized2();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::toggleMaximize()
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->toggleMaximize();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::toggleFullScreen()
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->toggleFullScreen();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::showSystemMenu(const QPoint &pos)
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->showSystemMenu(pos);
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::startSystemMove2()
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->startSystemMove2();
|
||||
}
|
||||
|
||||
void FramelessQuickWindow::startSystemResize2(const Qt::Edges edges)
|
||||
{
|
||||
Q_D(FramelessQuickWindow);
|
||||
d->startSystemResize2(edges);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -26,8 +26,10 @@
|
|||
|
||||
#include "framelesshelperquick_global.h"
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QQuickItem;
|
||||
class QQuickRectangle;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -42,10 +44,22 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickWindowPrivate : public QObject
|
|||
Q_DISABLE_COPY_MOVE(FramelessQuickWindowPrivate)
|
||||
|
||||
public:
|
||||
explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q);
|
||||
explicit FramelessQuickWindowPrivate(FramelessQuickWindow *q, const Options options);
|
||||
~FramelessQuickWindowPrivate() override;
|
||||
|
||||
Q_NODISCARD bool isZoomed() const;
|
||||
Q_INVOKABLE Q_NODISCARD bool isZoomed() const;
|
||||
Q_INVOKABLE Q_NODISCARD QColor getFrameBorderColor() const;
|
||||
Q_INVOKABLE Q_NODISCARD bool isFrameBorderVisible() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void showMinimized2();
|
||||
void toggleMaximize();
|
||||
void toggleFullScreen();
|
||||
void showSystemMenu(const QPoint &pos);
|
||||
void startSystemMove2();
|
||||
void startSystemResize2(const Qt::Edges edges);
|
||||
void setTitleBarItem(QQuickItem *item);
|
||||
void setHitTestVisible(QQuickItem *item);
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
@ -56,7 +70,10 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
FramelessQuickWindow *q_ptr = nullptr;
|
||||
bool m_initialized = false;
|
||||
QScopedPointer<QQuickRectangle> m_topBorderRectangle;
|
||||
QWindow::Visibility m_savedVisibility = QWindow::Windowed;
|
||||
Options m_options = {};
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -36,7 +36,7 @@ Button {
|
|||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: (FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible)
|
||||
source: (FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorized)
|
||||
? "image://framelesshelper/dark/close" : "image://framelesshelper/light/close"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,9 +39,9 @@ Button {
|
|||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: button.maximized ?
|
||||
((FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible)
|
||||
((FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorized)
|
||||
? "image://framelesshelper/dark/restore" : "image://framelesshelper/light/restore") :
|
||||
((FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible)
|
||||
((FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorized)
|
||||
? "image://framelesshelper/dark/maximize" : "image://framelesshelper/light/maximize")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ Button {
|
|||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: (FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorVisible)
|
||||
source: (FramelessUtils.darkModeEnabled || FramelessUtils.titleBarColorized)
|
||||
? "image://framelesshelper/dark/minimize" : "image://framelesshelper/light/minimize"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ Rectangle {
|
|||
|
||||
id: titleBar
|
||||
height: FramelessUtils.titleBarHeight
|
||||
color: titleBar.active ? (FramelessUtils.titleBarColorVisible ? FramelessUtils.systemAccentColor
|
||||
color: titleBar.active ? (FramelessUtils.titleBarColorized ? FramelessUtils.systemAccentColor
|
||||
: (FramelessUtils.darkModeEnabled ? "black" : "white"))
|
||||
: (FramelessUtils.darkModeEnabled ? FramelessUtils.defaultSystemDarkColor : "white")
|
||||
|
||||
|
@ -44,7 +44,7 @@ Rectangle {
|
|||
id: windowTitleLabel
|
||||
font.pointSize: 11
|
||||
color: titleBar.active ? ((FramelessUtils.darkModeEnabled
|
||||
|| FramelessUtils.titleBarColorVisible) ? "white" : "black") : "darkGray"
|
||||
|| FramelessUtils.titleBarColorized) ? "white" : "black") : "darkGray"
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: 10
|
||||
|
|
|
@ -41,7 +41,7 @@ target_compile_definitions(${SUB_PROJ_NAME} PRIVATE
|
|||
|
||||
if(MSVC)
|
||||
target_compile_options(${SUB_PROJ_NAME} PRIVATE
|
||||
/W4 /WX
|
||||
/utf-8 /W4 /WX
|
||||
)
|
||||
else()
|
||||
target_compile_options(${SUB_PROJ_NAME} PRIVATE
|
||||
|
|
|
@ -54,9 +54,9 @@ QWidget *FramelessMainWindow::titleBarWidget() const
|
|||
return m_helper->titleBarWidget();
|
||||
}
|
||||
|
||||
void FramelessMainWindow::setHitTestVisible(QWidget *widget, const bool visible)
|
||||
void FramelessMainWindow::setHitTestVisible(QWidget *widget)
|
||||
{
|
||||
m_helper->setHitTestVisible(widget, visible);
|
||||
m_helper->setHitTestVisible(widget);
|
||||
}
|
||||
|
||||
void FramelessMainWindow::toggleMaximized()
|
||||
|
@ -64,6 +64,11 @@ void FramelessMainWindow::toggleMaximized()
|
|||
m_helper->toggleMaximized();
|
||||
}
|
||||
|
||||
void FramelessMainWindow::toggleFullScreen()
|
||||
{
|
||||
m_helper->toggleFullScreen();
|
||||
}
|
||||
|
||||
void FramelessMainWindow::changeEvent(QEvent *event)
|
||||
{
|
||||
QMainWindow::changeEvent(event);
|
||||
|
|
|
@ -64,9 +64,9 @@ QWidget *FramelessWidget::contentWidget() const
|
|||
return m_helper->contentWidget();
|
||||
}
|
||||
|
||||
void FramelessWidget::setHitTestVisible(QWidget *widget, const bool visible)
|
||||
void FramelessWidget::setHitTestVisible(QWidget *widget)
|
||||
{
|
||||
m_helper->setHitTestVisible(widget, visible);
|
||||
m_helper->setHitTestVisible(widget);
|
||||
}
|
||||
|
||||
void FramelessWidget::toggleMaximized()
|
||||
|
@ -74,6 +74,11 @@ void FramelessWidget::toggleMaximized()
|
|||
m_helper->toggleMaximized();
|
||||
}
|
||||
|
||||
void FramelessWidget::toggleFullScreen()
|
||||
{
|
||||
m_helper->toggleFullScreen();
|
||||
}
|
||||
|
||||
void FramelessWidget::changeEvent(QEvent *event)
|
||||
{
|
||||
QWidget::changeEvent(event);
|
||||
|
|
|
@ -73,7 +73,7 @@ bool FramelessWidgetsHelper::isNormal() const
|
|||
|
||||
bool FramelessWidgetsHelper::isZoomed() const
|
||||
{
|
||||
return (q->isMaximized() || q->isFullScreen());
|
||||
return (q->isMaximized() || ((m_options & Option::DontTreatFullScreenAsZoomed) ? false : q->isFullScreen()));
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
|
||||
|
@ -133,17 +133,18 @@ QWidget *FramelessWidgetsHelper::contentWidget() const
|
|||
return m_userContentWidget;
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget, const bool visible)
|
||||
void FramelessWidgetsHelper::setHitTestVisible(QWidget *widget)
|
||||
{
|
||||
Q_ASSERT(widget);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
static constexpr const bool visible = true;
|
||||
const bool exists = m_hitTestVisibleWidgets.contains(widget);
|
||||
if (visible && !exists) {
|
||||
m_hitTestVisibleWidgets.append(widget);
|
||||
}
|
||||
if (!visible && exists) {
|
||||
if constexpr (!visible && exists) {
|
||||
m_hitTestVisibleWidgets.removeAll(widget);
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +219,7 @@ void FramelessWidgetsHelper::mousePressEventHandler(QMouseEvent *event)
|
|||
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||
return;
|
||||
}
|
||||
Utils::startSystemMove(q->windowHandle());
|
||||
Utils::startSystemMove(m_window);
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
|
||||
|
@ -251,7 +252,7 @@ void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
|
|||
const QPoint globalPos = event->globalPos();
|
||||
# endif
|
||||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->devicePixelRatioF()).toPoint();
|
||||
Utils::showSystemMenu(q->windowHandle(), nativePos);
|
||||
Utils::showSystemMenu(m_window, nativePos);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -261,7 +262,7 @@ void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event)
|
|||
if (!event) {
|
||||
return;
|
||||
}
|
||||
if ((m_options & Option::NoDoubleClickMaximizeToggle) || (m_options & Option::DisableResizing)) {
|
||||
if ((m_options & Option::NoDoubleClickMaximizeToggle) || Utils::isWindowFixedSize(m_window)) {
|
||||
return;
|
||||
}
|
||||
if (event->button() != Qt::LeftButton) {
|
||||
|
@ -295,12 +296,12 @@ void FramelessWidgetsHelper::initialize()
|
|||
// Force the widget become a native window now so that we can deal with its
|
||||
// win32 events as soon as possible.
|
||||
q->setAttribute(Qt::WA_NativeWindow);
|
||||
QWindow * const window = q->windowHandle();
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
m_window = q->windowHandle();
|
||||
Q_ASSERT(m_window);
|
||||
if (!m_window) {
|
||||
return;
|
||||
}
|
||||
window->setProperty(kInternalOptionsFlag, QVariant::fromValue(m_options));
|
||||
m_window->setProperty(kInternalOptionsFlag, QVariant::fromValue(m_options));
|
||||
if (m_options & Option::UseStandardWindowLayout) {
|
||||
if (q->inherits(QT_MAINWINDOW_CLASS_NAME)) {
|
||||
m_options &= ~Options(Option::UseStandardWindowLayout);
|
||||
|
@ -315,7 +316,7 @@ void FramelessWidgetsHelper::initialize()
|
|||
true);
|
||||
}
|
||||
FramelessWindowsManager *manager = FramelessWindowsManager::instance();
|
||||
manager->addWindow(window);
|
||||
manager->addWindow(m_window);
|
||||
connect(manager, &FramelessWindowsManager::systemThemeChanged, this, [this](){
|
||||
if (m_options & Option::UseStandardWindowLayout) {
|
||||
updateSystemTitleBarStyleSheet();
|
||||
|
@ -327,12 +328,11 @@ void FramelessWidgetsHelper::initialize()
|
|||
setupInitialUi();
|
||||
if (!(m_options & Option::DontMoveWindowToDesktopCenter)) {
|
||||
Utils::moveWindowToDesktopCenter(
|
||||
[this, window]() -> QScreen * {
|
||||
[this]() -> QScreen * {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
Q_UNUSED(window);
|
||||
return q->screen();
|
||||
#else
|
||||
return window->screen();
|
||||
return m_window->screen();
|
||||
#endif
|
||||
},
|
||||
[this]() -> QSize { return q->size(); },
|
||||
|
@ -525,7 +525,7 @@ void FramelessWidgetsHelper::updateSystemButtonsIcon()
|
|||
|
||||
void FramelessWidgetsHelper::toggleMaximized()
|
||||
{
|
||||
if (m_options & Option::DisableResizing) {
|
||||
if (Utils::isWindowFixedSize(m_window)) {
|
||||
return;
|
||||
}
|
||||
if (isZoomed()) {
|
||||
|
@ -535,4 +535,18 @@ void FramelessWidgetsHelper::toggleMaximized()
|
|||
}
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::toggleFullScreen()
|
||||
{
|
||||
if (Utils::isWindowFixedSize(m_window)) {
|
||||
return;
|
||||
}
|
||||
const Qt::WindowStates windowState = q->windowState();
|
||||
if (windowState & Qt::WindowFullScreen) {
|
||||
q->setWindowState(m_savedWindowState);
|
||||
} else {
|
||||
m_savedWindowState = windowState;
|
||||
q->showFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
Loading…
Reference in New Issue