Refactor UNIX version

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2021-07-21 17:14:55 +08:00
parent d43d126d3f
commit b44cfb4474
3 changed files with 92 additions and 132 deletions

View File

@ -28,7 +28,6 @@
#include "utilities.h" #include "utilities.h"
#include "framelesswindowsmanager.h" #include "framelesswindowsmanager.h"
#include <QtCore/qdebug.h> #include <QtCore/qdebug.h>
#include <QtCore/qcoreevent.h>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
#include <QtGui/qwindow.h> #include <QtGui/qwindow.h>
@ -63,147 +62,107 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
if (!object || !event) { if (!object || !event) {
return false; return false;
} }
// Only monitor window events.
if (!object->isWindowType()) { if (!object->isWindowType()) {
return false; return false;
} }
const auto currentWindow = qobject_cast<QWindow *>(object); const QEvent::Type type = event->type();
const int m_resizeBorderWidth = FramelessWindowsManager::getResizeBorderWidth(currentWindow); // We are only interested in mouse events.
const int m_resizeBorderHeight = FramelessWindowsManager::getResizeBorderHeight(currentWindow); if ((type != QEvent::MouseButtonDblClick) && (type != QEvent::MouseButtonPress) && (type != QEvent::MouseMove)) {
const int m_titleBarHeight = FramelessWindowsManager::getTitleBarHeight(currentWindow); return false;
const bool m_resizable = FramelessWindowsManager::getResizable(currentWindow); }
const auto getWindowEdges = const auto window = qobject_cast<QWindow *>(object);
[m_resizeBorderWidth, m_resizeBorderHeight](const QPointF &point, const int ww, const int wh) -> Qt::Edges { const int resizeBorderWidth = FramelessWindowsManager::getResizeBorderWidth(window);
if (point.y() <= m_resizeBorderHeight) { const int resizeBorderHeight = FramelessWindowsManager::getResizeBorderHeight(window);
if (point.x() <= m_resizeBorderWidth) { const int titleBarHeight = FramelessWindowsManager::getTitleBarHeight(window);
return Qt::Edge::TopEdge | Qt::Edge::LeftEdge; const bool resizable = FramelessWindowsManager::getResizable(window);
const int windowWidth = window->width();
const QPointF localMousePosition = window->mapFromGlobal(Utilities::getGlobalMousePosition(window));
const Qt::Edges edges = [window, resizeBorderWidth, resizeBorderHeight, windowWidth, &localMousePosition] {
const int windowHeight = window->height();
if (localMousePosition.y() <= resizeBorderHeight) {
if (localMousePosition.x() <= resizeBorderWidth) {
return Qt::TopEdge | Qt::LeftEdge;
} }
if (point.x() >= (ww - m_resizeBorderWidth)) { if (localMousePosition.x() >= (windowWidth - resizeBorderWidth)) {
return Qt::Edge::TopEdge | Qt::Edge::RightEdge; return Qt::TopEdge | Qt::RightEdge;
} }
return Qt::Edge::TopEdge; return Qt::Edges{Qt::TopEdge};
} }
if (point.y() >= (wh - m_resizeBorderHeight)) { if (localMousePosition.y() >= (windowHeight - resizeBorderHeight)) {
if (point.x() <= m_resizeBorderWidth) { if (localMousePosition.x() <= resizeBorderWidth) {
return Qt::Edge::BottomEdge | Qt::Edge::LeftEdge; return Qt::BottomEdge | Qt::LeftEdge;
} }
if (point.x() >= (ww - m_resizeBorderWidth)) { if (localMousePosition.x() >= (windowWidth - resizeBorderWidth)) {
return Qt::Edge::BottomEdge | Qt::Edge::RightEdge; return Qt::BottomEdge | Qt::RightEdge;
} }
return Qt::Edge::BottomEdge; return Qt::Edges{Qt::BottomEdge};
} }
if (point.x() <= m_resizeBorderWidth) { if (localMousePosition.x() <= resizeBorderWidth) {
return Qt::Edge::LeftEdge; return Qt::Edges{Qt::LeftEdge};
} }
if (point.x() >= (ww - m_resizeBorderWidth)) { if (localMousePosition.x() >= (windowWidth - resizeBorderWidth)) {
return Qt::Edge::RightEdge; return Qt::Edges{Qt::RightEdge};
} }
return {}; return Qt::Edges{};
}; } ();
const auto getCursorShape = [](const Qt::Edges edges) -> Qt::CursorShape { const bool hitTestVisible = Utilities::isHitTestVisibleInChrome(window);
if ((edges.testFlag(Qt::Edge::TopEdge) && edges.testFlag(Qt::Edge::LeftEdge)) const bool isInTitlebarArea = (localMousePosition.y() > resizeBorderHeight)
|| (edges.testFlag(Qt::Edge::BottomEdge) && edges.testFlag(Qt::Edge::RightEdge))) { && (localMousePosition.y() <= (titleBarHeight + resizeBorderHeight))
return Qt::CursorShape::SizeFDiagCursor; && (localMousePosition.x() > resizeBorderWidth)
} && (localMousePosition.x() < (windowWidth - resizeBorderWidth))
if ((edges.testFlag(Qt::Edge::TopEdge) && edges.testFlag(Qt::Edge::RightEdge)) && !hitTestVisible;
|| (edges.testFlag(Qt::Edge::BottomEdge) && edges.testFlag(Qt::Edge::LeftEdge))) { const auto mouseEvent = static_cast<QMouseEvent *>(event);
return Qt::CursorShape::SizeBDiagCursor; if (type == QEvent::MouseButtonDblClick) {
} if (mouseEvent->button() != Qt::MouseButton::LeftButton) {
if (edges.testFlag(Qt::Edge::TopEdge) || edges.testFlag(Qt::Edge::BottomEdge)) {
return Qt::CursorShape::SizeVerCursor;
}
if (edges.testFlag(Qt::Edge::LeftEdge) || edges.testFlag(Qt::Edge::RightEdge)) {
return Qt::CursorShape::SizeHorCursor;
}
return Qt::CursorShape::ArrowCursor;
};
const auto isInTitlebarArea = [m_resizeBorderHeight, m_titleBarHeight](const QPointF &point, const QWindow *window) -> bool {
Q_ASSERT(window);
if (!window) {
return false; return false;
} }
return (point.y() > m_resizeBorderHeight) && (point.y() <= (m_titleBarHeight + m_resizeBorderHeight)) if (isInTitlebarArea) {
&& !Utilities::isHitTestVisibleInChrome(window); if (window->windowState() == Qt::WindowState::WindowFullScreen) {
}; return false;
const auto moveOrResize =
[m_resizable, &getWindowEdges, &isInTitlebarArea](const QPointF &point, QWindow *window) {
Q_ASSERT(window);
if (!window) {
return;
} }
const Qt::Edges edges = getWindowEdges(point, window->width(), window->height()); if (window->windowState() == Qt::WindowState::WindowMaximized) {
if (edges == Qt::Edges{}) { window->showNormal();
if (isInTitlebarArea(point, window)) {
if (!window->startSystemMove()) {
// ### FIXME: TO BE IMPLEMENTED!
qWarning() << "Current OS doesn't support QWindow::startSystemMove().";
}
}
} else { } else {
if ((window->windowState() == Qt::WindowState::WindowNoState) window->showMaximized();
&& !Utilities::isHitTestVisibleInChrome(window) && m_resizable) { }
if (!window->startSystemResize(edges)) { window->setCursor(Qt::ArrowCursor);
// ### FIXME: TO BE IMPLEMENTED! }
qWarning() << "Current OS doesn't support QWindow::startSystemResize()."; } else if (type == QEvent::MouseButtonPress) {
} if (mouseEvent->button() != Qt::MouseButton::LeftButton) {
return false;
}
if (edges == Qt::Edges{}) {
if (isInTitlebarArea) {
if (!window->startSystemMove()) {
// ### FIXME: TO BE IMPLEMENTED!
qWarning() << "Current OS doesn't support QWindow::startSystemMove().";
} }
} }
}; } else {
const auto getMousePos = [](const QMouseEvent *e, const bool global) -> QPointF { if ((window->windowState() == Qt::WindowState::WindowNoState) && !hitTestVisible && resizable) {
Q_ASSERT(e); if (!window->startSystemResize(edges)) {
if (!e) { // ### FIXME: TO BE IMPLEMENTED!
return {}; qWarning() << "Current OS doesn't support QWindow::startSystemResize().";
} }
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
return global ? e->globalPosition() : e->scenePosition();
#else
return global ? e->screenPos() : e->windowPos();
#endif
};
switch (event->type()) {
case QEvent::MouseButtonDblClick: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() != Qt::MouseButton::LeftButton) {
break;
}
if (isInTitlebarArea(getMousePos(mouseEvent, false), currentWindow)) {
if (currentWindow->windowState() == Qt::WindowState::WindowFullScreen) {
break;
} }
if (currentWindow->windowState() == Qt::WindowState::WindowMaximized) { }
currentWindow->showNormal(); } else {
if ((window->windowState() == Qt::WindowState::WindowNoState) && resizable) {
if (((edges & Qt::TopEdge) && (edges & Qt::LeftEdge))
|| ((edges & Qt::BottomEdge) && (edges & Qt::RightEdge))) {
window->setCursor(Qt::SizeFDiagCursor);
} else if (((edges & Qt::TopEdge) && (edges & Qt::RightEdge))
|| ((edges & Qt::BottomEdge) && (edges & Qt::LeftEdge))) {
window->setCursor(Qt::SizeBDiagCursor);
} else if ((edges & Qt::TopEdge) || (edges & Qt::BottomEdge)) {
window->setCursor(Qt::SizeVerCursor);
} else if ((edges & Qt::LeftEdge) || (edges & Qt::RightEdge)) {
window->setCursor(Qt::SizeHorCursor);
} else { } else {
currentWindow->showMaximized(); window->setCursor(Qt::ArrowCursor);
} }
currentWindow->setCursor(Qt::CursorShape::ArrowCursor);
} }
} break;
case QEvent::MouseButtonPress: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() != Qt::MouseButton::LeftButton) {
break;
}
moveOrResize(getMousePos(mouseEvent, false), currentWindow);
} break;
case QEvent::MouseMove: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
if ((currentWindow->windowState() == Qt::WindowState::WindowNoState) && m_resizable) {
currentWindow->setCursor(
getCursorShape(getWindowEdges(getMousePos(mouseEvent, false),
currentWindow->width(),
currentWindow->height())));
}
} break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate: {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const auto point = static_cast<QTouchEvent *>(event)->points().first().position();
#else
const auto point = static_cast<QTouchEvent *>(event)->touchPoints().first().pos();
#endif
moveOrResize(point, currentWindow);
} break;
default:
break;
} }
return false; return false;
} }

View File

@ -109,8 +109,9 @@ static inline void installHelper(QWindow *window, const bool enable)
return; return;
} }
Utilities::updateQtFrameMargins(window, enable); Utilities::updateQtFrameMargins(window, enable);
Utilities::updateFrameMargins(window->winId(), !enable); const WId winId = window->winId();
Utilities::triggerFrameChange(window->winId()); Utilities::updateFrameMargins(winId, !enable);
Utilities::triggerFrameChange(winId);
window->setProperty(_flh_global::_flh_framelessEnabled_flag, enable); window->setProperty(_flh_global::_flh_framelessEnabled_flag, enable);
} }
@ -518,9 +519,14 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())}; POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())};
ScreenToClient(msg->hwnd, &winLocalMouse); ScreenToClient(msg->hwnd, &winLocalMouse);
const QPointF localMouse = {static_cast<qreal>(winLocalMouse.x), static_cast<qreal>(winLocalMouse.y)}; const QPointF localMouse = {static_cast<qreal>(winLocalMouse.x), static_cast<qreal>(winLocalMouse.y)};
RECT clientRect = {0, 0, 0, 0};
GetClientRect(msg->hwnd, &clientRect);
const LONG ww = clientRect.right;
const int rbw = getSystemMetric(window, Utilities::SystemMetric::ResizeBorderWidth, true);
const int rbh = getSystemMetric(window, Utilities::SystemMetric::ResizeBorderHeight, true); const int rbh = getSystemMetric(window, Utilities::SystemMetric::ResizeBorderHeight, true);
const int tbh = getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, true); const int tbh = getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, true);
const bool isTitleBar = (localMouse.y() > rbh) && (localMouse.y() <= (rbh + tbh)) const bool isTitleBar = (localMouse.y() > rbh) && (localMouse.y() <= (rbh + tbh))
&& (localMouse.x() > rbw) && (localMouse.y() < (ww - rbw))
&& !Utilities::isHitTestVisibleInChrome(window); && !Utilities::isHitTestVisibleInChrome(window);
const bool isTop = localMouse.y() <= rbh; const bool isTop = localMouse.y() <= rbh;
if (shouldHaveWindowFrame()) { if (shouldHaveWindowFrame()) {
@ -547,13 +553,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
*result = HTCLIENT; *result = HTCLIENT;
return true; return true;
} else { } else {
const auto getHitTestResult = const LRESULT hitTestResult = [clientRect, msg, isTitleBar, &localMouse, rbw, rbh, ww, isTop, window] {
[msg, isTitleBar, &localMouse, rbh, isTop, window]() -> LRESULT {
RECT clientRect = {0, 0, 0, 0};
GetClientRect(msg->hwnd, &clientRect);
const LONG ww = clientRect.right;
const LONG wh = clientRect.bottom; const LONG wh = clientRect.bottom;
const int rbw = getSystemMetric(window, Utilities::SystemMetric::ResizeBorderWidth, true);
if (IsMaximized(msg->hwnd)) { if (IsMaximized(msg->hwnd)) {
if (isTitleBar) { if (isTitleBar) {
return HTCAPTION; return HTCAPTION;
@ -597,8 +598,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return HTCAPTION; return HTCAPTION;
} }
return HTCLIENT; return HTCLIENT;
}; } ();
*result = getHitTestResult(); *result = hitTestResult;
return true; return true;
} }
} }

View File

@ -57,7 +57,7 @@ bool Utilities::isWindowFixedSize(const QWindow *window)
return false; return false;
} }
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
if (window->flags().testFlag(Qt::MSWindowsFixedSizeDialogHint)) { if (window->flags() & Qt::MSWindowsFixedSizeDialogHint) {
return true; return true;
} }
#endif #endif