diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index e63d6d9..bcf4b16 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -58,12 +58,25 @@ static const QString qThemeSettingChangeEventName = QString::fromWCharArray(kThe FRAMELESSHELPER_STRING_CONSTANT(MonitorFromWindow) FRAMELESSHELPER_STRING_CONSTANT(GetMonitorInfoW) FRAMELESSHELPER_STRING_CONSTANT(ScreenToClient) +FRAMELESSHELPER_STRING_CONSTANT(ClientToScreen) FRAMELESSHELPER_STRING_CONSTANT(GetClientRect) -FRAMELESSHELPER_STRING_CONSTANT(GetWindowLongPtrW) -FRAMELESSHELPER_STRING_CONSTANT(SetWindowLongPtrW) +#ifdef Q_PROCESSOR_X86_64 + FRAMELESSHELPER_STRING_CONSTANT(GetWindowLongPtrW) + FRAMELESSHELPER_STRING_CONSTANT(SetWindowLongPtrW) +#else + // WinUser.h defines G/SetClassLongPtr as G/SetClassLong due to the + // "Ptr" suffixed APIs are not available on 32-bit platforms, so we + // have to add the following workaround. Undefine the macros and then + // redefine them is also an option but the following solution is more simple. + FRAMELESSHELPER_STRING_CONSTANT2(GetWindowLongPtrW, "GetWindowLongW") + FRAMELESSHELPER_STRING_CONSTANT2(SetWindowLongPtrW, "SetWindowLongW") +#endif [[nodiscard]] static inline Qt::MouseButtons keyStateToMouseButtons(const WPARAM wParam) { + if (wParam == 0) { + return {}; + } Qt::MouseButtons result = {}; if (wParam & MK_LBUTTON) { result |= Qt::LeftButton; @@ -132,17 +145,23 @@ FRAMELESSHELPER_STRING_CONSTANT(SetWindowLongPtrW) if (isNonClientMouseEvent) { nativeScreenPos = nativePosExtractedFromLParam; nativeWindowPos = nativeScreenPos; - ScreenToClient(hWnd, &nativeWindowPos); + if (ScreenToClient(hWnd, &nativeWindowPos) == FALSE) { + qWarning() << Utils::getSystemErrorMessage(kScreenToClient); + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } } if (isClientMouseEvent) { nativeWindowPos = nativePosExtractedFromLParam; nativeScreenPos = nativeWindowPos; - ClientToScreen(hWnd, &nativeScreenPos); + if (ClientToScreen(hWnd, &nativeScreenPos) == FALSE) { + qWarning() << Utils::getSystemErrorMessage(kClientToScreen); + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } } const qreal devicePixelRatio = data.params.getWindowDevicePixelRatio(); const QPoint qtScenePos = QPointF(QPointF(qreal(nativeWindowPos.x), qreal(nativeWindowPos.y)) / devicePixelRatio).toPoint(); SystemButtonType currentButtonType = SystemButtonType::Unknown; - const ButtonState defaultButtonState = ButtonState::Unspecified; + static constexpr const auto defaultButtonState = ButtonState::Unspecified; data.params.setSystemButtonState(SystemButtonType::WindowIcon, defaultButtonState); data.params.setSystemButtonState(SystemButtonType::Help, defaultButtonState); data.params.setSystemButtonState(SystemButtonType::Minimize, defaultButtonState); @@ -765,7 +784,6 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } return true; } -#if 0 // This block of code is causing some problems in my own Qt Quick applications. Needs some more investigation. case WM_SETICON: case WM_SETTEXT: { // Disable painting while these messages are handled to prevent them @@ -795,7 +813,6 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me *result = ret; return true; } -#endif default: break; } diff --git a/src/quick/framelessquickwindow.cpp b/src/quick/framelessquickwindow.cpp index 125f7fe..09490d0 100644 --- a/src/quick/framelessquickwindow.cpp +++ b/src/quick/framelessquickwindow.cpp @@ -482,28 +482,44 @@ bool FramelessQuickWindowPrivate::isInSystemButtons(const QPoint &pos, SystemBut return false; } *button = SystemButtonType::Unknown; - if (!m_settings.minimizeButton || !m_settings.maximizeButton || !m_settings.closeButton) { + if (!m_settings.windowIconButton && !m_settings.contextHelpButton + && !m_settings.minimizeButton && !m_settings.maximizeButton && !m_settings.closeButton) { return false; } - if (!m_settings.minimizeButton->inherits(QT_QUICKITEM_CLASS_NAME) - || !m_settings.maximizeButton->inherits(QT_QUICKITEM_CLASS_NAME) - || !m_settings.closeButton->inherits(QT_QUICKITEM_CLASS_NAME)) { - return false; + if (m_settings.windowIconButton && m_settings.windowIconButton->inherits(QT_QUICKITEM_CLASS_NAME)) { + const auto iconBtn = qobject_cast(m_settings.windowIconButton); + if (mapItemGeometryToScene(iconBtn).contains(pos)) { + *button = SystemButtonType::WindowIcon; + return true; + } } - const auto minBtn = qobject_cast(m_settings.minimizeButton); - if (mapItemGeometryToScene(minBtn).contains(pos)) { - *button = SystemButtonType::Minimize; - return true; + if (m_settings.contextHelpButton && m_settings.contextHelpButton->inherits(QT_QUICKITEM_CLASS_NAME)) { + const auto helpBtn = qobject_cast(m_settings.contextHelpButton); + if (mapItemGeometryToScene(helpBtn).contains(pos)) { + *button = SystemButtonType::Help; + return true; + } } - const auto maxBtn = qobject_cast(m_settings.maximizeButton); - if (mapItemGeometryToScene(maxBtn).contains(pos)) { - *button = SystemButtonType::Maximize; - return true; + if (m_settings.minimizeButton && m_settings.minimizeButton->inherits(QT_QUICKITEM_CLASS_NAME)) { + const auto minBtn = qobject_cast(m_settings.minimizeButton); + if (mapItemGeometryToScene(minBtn).contains(pos)) { + *button = SystemButtonType::Minimize; + return true; + } } - const auto closeBtn = qobject_cast(m_settings.closeButton); - if (mapItemGeometryToScene(closeBtn).contains(pos)) { - *button = SystemButtonType::Close; - return true; + if (m_settings.maximizeButton && m_settings.maximizeButton->inherits(QT_QUICKITEM_CLASS_NAME)) { + const auto maxBtn = qobject_cast(m_settings.maximizeButton); + if (mapItemGeometryToScene(maxBtn).contains(pos)) { + *button = SystemButtonType::Maximize; + return true; + } + } + if (m_settings.closeButton && m_settings.closeButton->inherits(QT_QUICKITEM_CLASS_NAME)) { + const auto closeBtn = qobject_cast(m_settings.closeButton); + if (mapItemGeometryToScene(closeBtn).contains(pos)) { + *button = SystemButtonType::Close; + return true; + } } return false; } diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 9631ecf..bd35f4a 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -32,6 +32,7 @@ set(SOURCES ${INCLUDE_PREFIX}/framelesswidget.h ${INCLUDE_PREFIX}/framelessmainwindow.h ${INCLUDE_PREFIX}/standardsystembutton.h + standardsystembutton_p.h framelessmainwindow.cpp framelesswidgetshelper.cpp framelesswidget.cpp diff --git a/src/widgets/standardsystembutton.cpp b/src/widgets/standardsystembutton.cpp index dd7c10a..2cec533 100644 --- a/src/widgets/standardsystembutton.cpp +++ b/src/widgets/standardsystembutton.cpp @@ -23,6 +23,7 @@ */ #include "standardsystembutton.h" +#include "standardsystembutton_p.h" #include #include #include @@ -36,54 +37,6 @@ static constexpr const QRect g_buttonRect = {QPoint(0, 0), kDefaultSystemButtonS static constexpr const auto g_buttonIconX = static_cast(qRound(qreal(kDefaultSystemButtonSize.width() - kDefaultSystemButtonIconSize.width()) / 2.0)); static constexpr const auto g_buttonIconY = static_cast(qRound(qreal(kDefaultSystemButtonSize.height() - kDefaultSystemButtonIconSize.height()) / 2.0)); -class StandardSystemButtonPrivate : public QObject -{ - Q_OBJECT - Q_DECLARE_PUBLIC(StandardSystemButton) - Q_DISABLE_COPY_MOVE(StandardSystemButtonPrivate) - -public: - explicit StandardSystemButtonPrivate(StandardSystemButton *q); - ~StandardSystemButtonPrivate() override; - - void refreshButtonTheme(const bool force); - - Q_NODISCARD SystemButtonType getButtonType() const; - void setButtonType(const SystemButtonType type); - - void setIcon(const QIcon &value, const bool reverse); - void setPixmap(const QPixmap &value, const bool reverse); - void setImage(const QImage &value, const bool reverse); - - Q_NODISCARD QSize getRecommendedButtonSize() const; - - Q_NODISCARD bool isHover() const; - Q_NODISCARD QColor getHoverColor() const; - Q_NODISCARD QColor getPressColor() const; - - void setHover(const bool value); - void setHoverColor(const QColor &value); - void setPressColor(const QColor &value); - - void enterEventHandler(QT_ENTER_EVENT_TYPE *event); - void leaveEventHandler(QEvent *event); - void paintEventHandler(QPaintEvent *event); - -private: - void initialize(); - -private: - StandardSystemButton *q_ptr; - SystemTheme m_buttonTheme = SystemTheme::Unknown; - SystemButtonType m_buttonType = SystemButtonType::Unknown; - QPixmap m_icon = {}; - QPixmap m_reversedIcon = {}; - QColor m_hoverColor = {}; - QColor m_pressColor = {}; - bool m_hovered = false; - bool m_pressed = false; -}; - StandardSystemButtonPrivate::StandardSystemButtonPrivate(StandardSystemButton *q) : QObject(q) { Q_ASSERT(q); @@ -321,9 +274,8 @@ void StandardSystemButtonPrivate::initialize() this, [this](){ refreshButtonTheme(false); }); } -StandardSystemButton::StandardSystemButton(QWidget *parent) : QAbstractButton(parent) +StandardSystemButton::StandardSystemButton(QWidget *parent) : QAbstractButton(parent), d_ptr(new StandardSystemButtonPrivate(this)) { - d_ptr.reset(new StandardSystemButtonPrivate(this)); } StandardSystemButton::StandardSystemButton(const SystemButtonType type, QWidget *parent) : StandardSystemButton(parent) @@ -415,5 +367,3 @@ void StandardSystemButton::paintEvent(QPaintEvent *event) } FRAMELESSHELPER_END_NAMESPACE - -#include "standardsystembutton.moc" diff --git a/src/widgets/standardsystembutton_p.h b/src/widgets/standardsystembutton_p.h new file mode 100644 index 0000000..f58a874 --- /dev/null +++ b/src/widgets/standardsystembutton_p.h @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include +#include +#include "framelesshelperwidgets_global.h" + +QT_BEGIN_NAMESPACE +class QEnterEvent; +class QPaintEvent; +QT_END_NAMESPACE + +FRAMELESSHELPER_BEGIN_NAMESPACE + +class StandardSystemButton; + +class StandardSystemButtonPrivate : public QObject +{ + Q_OBJECT + Q_DECLARE_PUBLIC(StandardSystemButton) + Q_DISABLE_COPY_MOVE(StandardSystemButtonPrivate) + +public: + explicit StandardSystemButtonPrivate(StandardSystemButton *q); + ~StandardSystemButtonPrivate() override; + + void refreshButtonTheme(const bool force); + + Q_NODISCARD Global::SystemButtonType getButtonType() const; + void setButtonType(const Global::SystemButtonType type); + + void setIcon(const QIcon &value, const bool reverse); + void setPixmap(const QPixmap &value, const bool reverse); + void setImage(const QImage &value, const bool reverse); + + Q_NODISCARD QSize getRecommendedButtonSize() const; + + Q_NODISCARD bool isHover() const; + Q_NODISCARD QColor getHoverColor() const; + Q_NODISCARD QColor getPressColor() const; + + void setHover(const bool value); + void setHoverColor(const QColor &value); + void setPressColor(const QColor &value); + + void enterEventHandler(QT_ENTER_EVENT_TYPE *event); + void leaveEventHandler(QEvent *event); + void paintEventHandler(QPaintEvent *event); + +private: + void initialize(); + +private: + StandardSystemButton *q_ptr; + Global::SystemTheme m_buttonTheme = Global::SystemTheme::Unknown; + Global::SystemButtonType m_buttonType = Global::SystemButtonType::Unknown; + QPixmap m_icon = {}; + QPixmap m_reversedIcon = {}; + QColor m_hoverColor = {}; + QColor m_pressColor = {}; + bool m_hovered = false; + bool m_pressed = false; +}; + +FRAMELESSHELPER_END_NAMESPACE