Zhao Yuhang
2024-05-23 6002cd46a2c5a1c2c4afdbf8e491e76f68b9bfd8
Improve fixed width/height/size hit testing
1个文件已修改
191 ■■■■ 已修改文件
src/core/contexts/win32windowcontext.cpp 191 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/win32windowcontext.cpp
@@ -1583,12 +1583,21 @@
                QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos),
                                                                      m_windowHandle.data());
                int frameSize = getResizeBorderThickness(hWnd);
                bool isFixedWidth = isHostWidthFixed();
                bool isFixedHeight = isHostHeightFixed();
                bool isFixedSize = isHostSizeFixed();
                bool isTitleBar = isInTitleBarDraggableArea(qtScenePos);
                bool isInLeftBorder = nativeLocalPos.x <= frameSize;
                bool isInTopBorder = nativeLocalPos.y <= frameSize;
                bool isInRightBorder = nativeLocalPos.x > clientWidth - frameSize;
                bool isInBottomBorder = nativeLocalPos.y > clientHeight - frameSize;
                bool isInTitleBar = isInTitleBarDraggableArea(qtScenePos);
                WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown;
                bool isInCaptionButtons = isInSystemButtons(qtScenePos, &sysButtonType);
                bool dontOverrideCursor = false; // ### TODO
                WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown;
                if (!isFixedSize && isInSystemButtons(qtScenePos, &sysButtonType)) {
                if (isInCaptionButtons) {
                    // Firstly, we set the hit test result to a default value to be able to detect
                    // whether we have changed it or not afterwards.
                    *result = HTNOWHERE;
@@ -1598,29 +1607,41 @@
                    // window is not maximized/fullscreen/minimized, of course).
                    if (isWindowNoState(hWnd)) {
                        static constexpr const quint8 kBorderSize = 2;
                        bool isTop = (nativeLocalPos.y <= kBorderSize);
                        bool isTop = nativeLocalPos.y <= kBorderSize;
                        bool isLeft = nativeLocalPos.x <= kBorderSize;
                        bool isRight = (nativeLocalPos.x >= (clientWidth - kBorderSize));
                        bool isRight = nativeLocalPos.x > clientWidth - kBorderSize;
                        if (isTop || isLeft || isRight) {
                            if (dontOverrideCursor) {
                            if (isFixedSize || dontOverrideCursor) {
                                // The user doesn't want the window to be resized, so we tell
                                // Windows we are in the client area so that the controls beneath
                                // the mouse cursor can still be hovered or clicked.
                                *result = (isTitleBar ? HTCAPTION : HTCLIENT);
                                *result = isInTitleBar ? HTCAPTION : HTCLIENT;
                            } else {
                                if (isTop) {
                                    if (isLeft) {
                                        *result = HTTOPLEFT;
                                    } else if (isRight) {
                                        *result = HTTOPRIGHT;
                                    } else {
                                        if (isFixedWidth) {
                                        *result = HTTOP;
                                    }
                                } else {
                                    if (isLeft) {
                                        } else if (isFixedHeight) {
                                        *result = HTLEFT;
                                    } else {
                                            *result = HTTOPLEFT;
                                        }
                                    } else if (isRight) {
                                        if (isFixedWidth) {
                                            *result = HTTOP;
                                        } else if (isFixedHeight) {
                                        *result = HTRIGHT;
                                        } else {
                                            *result = HTTOPRIGHT;
                                        }
                                    } else {
                                        *result = isFixedHeight ? HTBORDER : HTTOP;
                                    }
                                } else {
                                    if (isFixedWidth) {
                                        *result = HTBORDER;
                                    } else {
                                        *result = isLeft ? HTLEFT : HTRIGHT;
                                    }
                                }
                            }
@@ -1664,8 +1685,6 @@
                bool max = isMaximized(hWnd);
                bool full = isFullScreen(hWnd);
                int frameSize = getResizeBorderThickness(hWnd);
                bool isTop = (nativeLocalPos.y < frameSize);
                if (isSystemBorderEnabled()) {
                    // This will handle the left, right and bottom parts of the frame
@@ -1677,8 +1696,48 @@
                        // outside the window, that is, the three transparent window resize area.
                        // Returning HTCLIENT will confuse Windows, we can't put our controls there
                        // anyway.
                        *result = ((isFixedSize || dontOverrideCursor) ? HTBORDER
                                                                       : originalHitTestResult);
                        *result = HTNOWHERE; // Make sure we can know we don't set any value explicitly later.
                        if (originalHitTestResult == HTCAPTION) {
                        } else if (isFixedSize || dontOverrideCursor) {
                            *result = HTBORDER;
                        } else if (isFixedWidth || isFixedHeight) {
                            if (originalHitTestResult == HTTOPLEFT) {
                                if (isFixedWidth) {
                                    *result = HTTOP;
                                } else {
                                    *result = HTLEFT;
                                }
                            } else if (originalHitTestResult == HTTOPRIGHT) {
                                if (isFixedWidth) {
                                    *result = HTTOP;
                                } else {
                                    *result = HTRIGHT;
                                }
                            } else if (originalHitTestResult == HTBOTTOMRIGHT) {
                                if (isFixedWidth) {
                                    *result = HTBOTTOM;
                                } else {
                                    *result = HTRIGHT;
                                }
                            } else if (originalHitTestResult == HTBOTTOMLEFT) {
                                if (isFixedWidth) {
                                    *result = HTBOTTOM;
                                } else {
                                    *result = HTLEFT;
                                }
                            } else if (originalHitTestResult == HTLEFT || originalHitTestResult == HTRIGHT) {
                                if (isFixedWidth) {
                                    *result = HTBORDER;
                                }
                            } else if (originalHitTestResult == HTTOP || originalHitTestResult == HTBOTTOM) {
                                if (isFixedHeight) {
                                    *result = HTBORDER;
                                }
                            }
                        }
                        if (*result == HTNOWHERE) {
                            *result = originalHitTestResult;
                        }
                        return true;
                    }
                    if (full) {
@@ -1686,7 +1745,7 @@
                        return true;
                    }
                    if (max) {
                        *result = (isTitleBar ? HTCAPTION : HTCLIENT);
                        *result = isInTitleBar ? HTCAPTION : HTCLIENT;
                        return true;
                    }
                    // At this point, we know that the cursor is inside the client area,
@@ -1694,16 +1753,24 @@
                    // title bar or the drag bar. Apparently, it must be the drag bar or
                    // the little border at the top which the user can use to move or
                    // resize the window.
                    if (isTop) {
                    if (isInTopBorder) {
                        // Return HTCLIENT instead of HTBORDER here, because the mouse is
                        // inside our homemade title bar now, return HTCLIENT to let our
                        // title bar can still capture mouse events.
                        *result = ((isFixedSize || dontOverrideCursor)
                                       ? (isTitleBar ? HTCAPTION : HTCLIENT)
                                       : HTTOP);
                        *result = [&]() {
                            if (isFixedSize || isFixedHeight || dontOverrideCursor || (isFixedWidth && (isInLeftBorder || isInRightBorder))) {
                                if (isInTitleBar) {
                                    return HTCAPTION;
                                } else {
                                    return HTCLIENT;
                                }
                            } else {
                                return HTTOP;
                            }
                        }();
                        return true;
                    }
                    if (isTitleBar) {
                    if (isInTitleBar) {
                        *result = HTCAPTION;
                        return true;
                    }
@@ -1714,58 +1781,86 @@
                        *result = HTCLIENT;
                        return true;
                    }
                    if (max) {
                        *result = (isTitleBar ? HTCAPTION : HTCLIENT);
                    if (max || isFixedSize || dontOverrideCursor) {
                        *result = isInTitleBar ? HTCAPTION : HTCLIENT;
                        return true;
                    }
                    if (!isFixedSize) {
                        const bool isBottom = (nativeLocalPos.y >= (clientHeight - frameSize));
                        // Make the border a little wider to let the user easy to resize on corners.
                        const auto scaleFactor = ((isTop || isBottom) ? qreal(2) : qreal(1));
                        const int scaledFrameSize = std::round(qreal(frameSize) * scaleFactor);
                        const bool isLeft = (nativeLocalPos.x < scaledFrameSize);
                        const bool isRight = (nativeLocalPos.x >= (clientWidth - scaledFrameSize));
                        if (dontOverrideCursor && (isTop || isBottom || isLeft || isRight)) {
                            // Return HTCLIENT instead of HTBORDER here, because the mouse is
                            // inside the window now, return HTCLIENT to let the controls
                            // inside our window can still capture mouse events.
                            *result = (isTitleBar ? HTCAPTION : HTCLIENT);
                            return true;
                    if (isFixedWidth || isFixedHeight) {
                        if (isInLeftBorder && isInTopBorder) {
                            if (isFixedWidth) {
                                *result = HTTOP;
                            } else {
                                *result = HTLEFT;
                        }
                        if (isTop) {
                            if (isLeft) {
                        } else if (isInRightBorder && isInTopBorder) {
                            if (isFixedWidth) {
                                *result = HTTOP;
                            } else {
                                *result = HTRIGHT;
                            }
                        } else if (isInRightBorder && isInBottomBorder) {
                            if (isFixedWidth) {
                                *result = HTBOTTOM;
                            } else {
                                *result = HTRIGHT;
                            }
                        } else if (isInLeftBorder && isInBottomBorder) {
                            if (isFixedWidth) {
                                *result = HTBOTTOM;
                            } else {
                                *result = HTLEFT;
                            }
                        } else if (isInLeftBorder || isInRightBorder) {
                            if (isFixedWidth) {
                                *result = HTCLIENT;
                            } else {
                                *result = isInLeftBorder ? HTLEFT : HTRIGHT;
                            }
                        } else if (isInTopBorder || isInBottomBorder) {
                            if (isFixedHeight) {
                                *result = HTCLIENT;
                            } else {
                                *result = isInTopBorder ? HTTOP : HTBOTTOM;
                            }
                        } else {
                            *result = HTCLIENT;
                        }
                        return true;
                    } else {
                        if (isInTopBorder) {
                            if (isInLeftBorder) {
                                *result = HTTOPLEFT;
                                return true;
                            }
                            if (isRight) {
                            if (isInRightBorder) {
                                *result = HTTOPRIGHT;
                                return true;
                            }
                            *result = HTTOP;
                            return true;
                        }
                        if (isBottom) {
                            if (isLeft) {
                        if (isInBottomBorder) {
                            if (isInLeftBorder) {
                                *result = HTBOTTOMLEFT;
                                return true;
                            }
                            if (isRight) {
                            if (isInRightBorder) {
                                *result = HTBOTTOMRIGHT;
                                return true;
                            }
                            *result = HTBOTTOM;
                            return true;
                        }
                        if (isLeft) {
                        if (isInLeftBorder) {
                            *result = HTLEFT;
                            return true;
                        }
                        if (isRight) {
                        if (isInRightBorder) {
                            *result = HTRIGHT;
                            return true;
                        }
                    }
                    if (isTitleBar) {
                    if (isInTitleBar) {
                        *result = HTCAPTION;
                        return true;
                    }