backbone of new FramelessHelper
This commit is contained in:
parent
0bfefb25d0
commit
1e2598398d
|
@ -34,177 +34,67 @@
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {}
|
FramelessHelper::FramelessHelper(QWindow *window)
|
||||||
|
: QObject(window)
|
||||||
void FramelessHelper::removeWindowFrame(QWindow *window)
|
, m_window(window)
|
||||||
{
|
{
|
||||||
Q_ASSERT(window);
|
Q_ASSERT(window != nullptr && window->isTopLevel());
|
||||||
if (!window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
window->setFlags(window->flags() | Qt::FramelessWindowHint);
|
|
||||||
window->installEventFilter(this);
|
|
||||||
window->setProperty(Constants::kFramelessModeFlag, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramelessHelper::bringBackWindowFrame(QWindow *window)
|
/*!
|
||||||
|
Setup the window, make it frameless.
|
||||||
|
*/
|
||||||
|
void FramelessHelper::install()
|
||||||
{
|
{
|
||||||
Q_ASSERT(window);
|
QRect origRect = m_window->geometry();
|
||||||
if (!window) {
|
|
||||||
|
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;
|
return;
|
||||||
}
|
|
||||||
window->removeEventFilter(this);
|
setWindowSize(windowSize);
|
||||||
window->setFlags(window->flags() & ~Qt::FramelessWindowHint);
|
}
|
||||||
window->setProperty(Constants::kFramelessModeFlag, false);
|
|
||||||
|
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)
|
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
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -42,14 +42,40 @@ class FRAMELESSHELPER_API FramelessHelper : public QObject
|
||||||
Q_DISABLE_COPY_MOVE(FramelessHelper)
|
Q_DISABLE_COPY_MOVE(FramelessHelper)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessHelper(QObject *parent = nullptr);
|
explicit FramelessHelper(QWindow *window);
|
||||||
~FramelessHelper() override = default;
|
~FramelessHelper() override = default;
|
||||||
|
|
||||||
void removeWindowFrame(QWindow *window);
|
void install();
|
||||||
void bringBackWindowFrame(QWindow *window);
|
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:
|
protected:
|
||||||
bool eventFilter(QObject *object, QEvent *event) override;
|
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
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
Loading…
Reference in New Issue