diff --git a/framelesshelper.cpp b/framelesshelper.cpp index dca059b..e139fa4 100644 --- a/framelesshelper.cpp +++ b/framelesshelper.cpp @@ -34,177 +34,67 @@ FRAMELESSHELPER_BEGIN_NAMESPACE -FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {} - -void FramelessHelper::removeWindowFrame(QWindow *window) +FramelessHelper::FramelessHelper(QWindow *window) + : QObject(window) + , m_window(window) { - Q_ASSERT(window); - if (!window) { - return; - } - window->setFlags(window->flags() | Qt::FramelessWindowHint); - window->installEventFilter(this); - window->setProperty(Constants::kFramelessModeFlag, true); + Q_ASSERT(window != nullptr && window->isTopLevel()); } -void FramelessHelper::bringBackWindowFrame(QWindow *window) +/*! + Setup the window, make it frameless. + */ +void FramelessHelper::install() { - Q_ASSERT(window); - if (!window) { + QRect origRect = m_window->geometry(); + + resizeWindow(origRect.size()); +} + +/*! + Restore the window to its original state + */ +void FramelessHelper::uninstall() +{ + resizeWindow(QSize()); +} + +/*! + Resize non-client area + */ +void FramelessHelper::resizeWindow(const QSize& windowSize) +{ + if (windowSize == this->windowSize()) return; - } - window->removeEventFilter(this); - window->setFlags(window->flags() & ~Qt::FramelessWindowHint); - window->setProperty(Constants::kFramelessModeFlag, false); + + setWindowSize(windowSize); +} + +QRect FramelessHelper::titleBarRect() +{ + return QRect(0, 0, windowSize().width(), titleBarHeight()); +} + +QRect FramelessHelper::clientRect() +{ + QRect rect(0, 0, windowSize().width(), windowSize().height()); + rect = rect.adjusted( + resizeBorderThickness(), titleBarHeight(), + -resizeBorderThickness(), -resizeBorderThickness() + ); + return rect; +} + +QRegion FramelessHelper::nonClientRegion() +{ + QRegion region(QRect(QPoint(0, 0), windowSize())); + region -= clientRect(); + return region; } bool FramelessHelper::eventFilter(QObject *object, QEvent *event) { - Q_ASSERT(object); - Q_ASSERT(event); - if (!object || !event) { - return false; - } - // Only monitor window events. - if (!object->isWindowType()) { - return false; - } - const QEvent::Type type = event->type(); - // We are only interested in mouse events. - if ((type != QEvent::MouseButtonDblClick) && (type != QEvent::MouseButtonPress) - && (type != QEvent::MouseMove)) { - return false; - } - const auto window = qobject_cast(object); - const int resizeBorderThickness = FramelessWindowsManager::getResizeBorderThickness(window); - const int titleBarHeight = FramelessWindowsManager::getTitleBarHeight(window); - const bool resizable = FramelessWindowsManager::getResizable(window); - const int windowWidth = window->width(); - const auto mouseEvent = static_cast(event); -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - const QPoint localMousePosition = mouseEvent->position().toPoint(); -#else - const QPoint localMousePosition = mouseEvent->windowPos().toPoint(); -#endif - const Qt::Edges edges = [window, resizeBorderThickness, windowWidth, &localMousePosition] { - const int windowHeight = window->height(); - if (localMousePosition.y() <= resizeBorderThickness) { - if (localMousePosition.x() <= resizeBorderThickness) { - return Qt::TopEdge | Qt::LeftEdge; - } - if (localMousePosition.x() >= (windowWidth - resizeBorderThickness)) { - return Qt::TopEdge | Qt::RightEdge; - } - return Qt::Edges{Qt::TopEdge}; - } - if (localMousePosition.y() >= (windowHeight - resizeBorderThickness)) { - if (localMousePosition.x() <= resizeBorderThickness) { - return Qt::BottomEdge | Qt::LeftEdge; - } - if (localMousePosition.x() >= (windowWidth - resizeBorderThickness)) { - return Qt::BottomEdge | Qt::RightEdge; - } - return Qt::Edges{Qt::BottomEdge}; - } - if (localMousePosition.x() <= resizeBorderThickness) { - return Qt::Edges{Qt::LeftEdge}; - } - if (localMousePosition.x() >= (windowWidth - resizeBorderThickness)) { - return Qt::Edges{Qt::RightEdge}; - } - return Qt::Edges{}; - } (); - const bool hitTestVisible = Utilities::isHitTestVisibleInChrome(window); - bool isInTitlebarArea = false; - if ((window->windowState() == Qt::WindowMaximized) - || (window->windowState() == Qt::WindowFullScreen)) { - isInTitlebarArea = (localMousePosition.y() >= 0) - && (localMousePosition.y() <= titleBarHeight) - && (localMousePosition.x() >= 0) - && (localMousePosition.x() <= windowWidth) - && !hitTestVisible; - } - if (window->windowState() == Qt::WindowNoState) { - isInTitlebarArea = (localMousePosition.y() > resizeBorderThickness) - && (localMousePosition.y() <= titleBarHeight) - && (localMousePosition.x() > resizeBorderThickness) - && (localMousePosition.x() < (windowWidth - resizeBorderThickness)) - && !hitTestVisible; - } - // Determine if the mouse click occurred in the title bar - static bool titlebarClicked = false; - if (type == QEvent::MouseButtonPress) { - if (isInTitlebarArea) - titlebarClicked = true; - else - titlebarClicked = false; - } - - if (type == QEvent::MouseButtonDblClick) { - if (mouseEvent->button() != Qt::MouseButton::LeftButton) { - return false; - } - if (isInTitlebarArea) { - if (window->windowState() == Qt::WindowState::WindowFullScreen) { - return false; - } - if (window->windowState() == Qt::WindowState::WindowMaximized) { - window->showNormal(); - } else { - window->showMaximized(); - } - window->setCursor(Qt::ArrowCursor); - } - } else if (type == QEvent::MouseMove) { - // Display resize indicators - static bool cursorChanged = false; - if ((window->windowState() == Qt::WindowState::WindowNoState) && resizable) { - if (((edges & Qt::TopEdge) && (edges & Qt::LeftEdge)) - || ((edges & Qt::BottomEdge) && (edges & Qt::RightEdge))) { - window->setCursor(Qt::SizeFDiagCursor); - cursorChanged = true; - } else if (((edges & Qt::TopEdge) && (edges & Qt::RightEdge)) - || ((edges & Qt::BottomEdge) && (edges & Qt::LeftEdge))) { - window->setCursor(Qt::SizeBDiagCursor); - cursorChanged = true; - } else if ((edges & Qt::TopEdge) || (edges & Qt::BottomEdge)) { - window->setCursor(Qt::SizeVerCursor); - cursorChanged = true; - } else if ((edges & Qt::LeftEdge) || (edges & Qt::RightEdge)) { - window->setCursor(Qt::SizeHorCursor); - cursorChanged = true; - } else { - if (cursorChanged) { - window->setCursor(Qt::ArrowCursor); - cursorChanged = false; - } - } - } - - if ((mouseEvent->buttons() & Qt::LeftButton) && titlebarClicked) { - if (edges == Qt::Edges{}) { - if (isInTitlebarArea) { - if (!window->startSystemMove()) { - // ### FIXME: TO BE IMPLEMENTED! - qWarning() << "Current OS doesn't support QWindow::startSystemMove()."; - } - } - } - } - - } else if (type == QEvent::MouseButtonPress) { - if (edges != Qt::Edges{}) { - if ((window->windowState() == Qt::WindowState::WindowNoState) && !hitTestVisible && resizable) { - if (!window->startSystemResize(edges)) { - // ### FIXME: TO BE IMPLEMENTED! - qWarning() << "Current OS doesn't support QWindow::startSystemResize()."; - } - } - } - } - - return false; } FRAMELESSHELPER_END_NAMESPACE diff --git a/framelesshelper.h b/framelesshelper.h index 5b7dd86..b923f56 100644 --- a/framelesshelper.h +++ b/framelesshelper.h @@ -42,14 +42,40 @@ class FRAMELESSHELPER_API FramelessHelper : public QObject Q_DISABLE_COPY_MOVE(FramelessHelper) public: - explicit FramelessHelper(QObject *parent = nullptr); + explicit FramelessHelper(QWindow *window); ~FramelessHelper() override = default; - void removeWindowFrame(QWindow *window); - void bringBackWindowFrame(QWindow *window); + void install(); + void uninstall(); + + QWindow *window() { return m_window; } + + QSize windowSize() { return m_windowSize; } + void setWindowSize(const QSize& size) { m_windowSize = size; } + void resizeWindow(const QSize& windowSize); + + int titleBarHeight() { return m_titleBarHeight; } + int setTitleBarHeight(int height) { m_titleBarHeight = height; } + QRect titleBarRect(); + + int resizeBorderThickness() { return m_resizeBorderThickness; } + void setResizeBorderThickness(int thickness) { m_resizeBorderThickness = thickness; } + + bool resizable() { return m_resizable; } + void setResizable(bool resizable) { m_resizable = resizable; } + + QRect clientRect(); + QRegion nonClientRegion(); protected: bool eventFilter(QObject *object, QEvent *event) override; + +private: + QWindow *m_window; + QSize m_windowSize; + int m_titleBarHeight; + int m_resizeBorderThickness; + bool m_resizable; }; FRAMELESSHELPER_END_NAMESPACE