backbone of new FramelessHelper
This commit is contained in:
parent
0bfefb25d0
commit
1e2598398d
|
@ -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<QWindow *>(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<QMouseEvent *>(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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue