2022-06-19 16:17:38 +08:00
|
|
|
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2020-12-29 23:28:17 +08:00
|
|
|
#include "framelesswindow.h"
|
|
|
|
|
2021-01-10 15:23:49 +08:00
|
|
|
#include <QApplication>
|
2020-12-29 23:28:17 +08:00
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
2021-01-10 15:23:49 +08:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#endif // _WIN32
|
|
|
|
|
2020-12-29 23:28:17 +08:00
|
|
|
FramelessWindow::FramelessWindow(QWidget *parent)
|
|
|
|
: QWidget(parent)
|
|
|
|
, m_centralLayout(new QVBoxLayout(this))
|
|
|
|
{
|
2022-06-25 23:52:35 +08:00
|
|
|
// TODO: Remove the comment below when we switch to Qt 6 completely.
|
|
|
|
// There is a bug in Qt 5 that will make pressing Meta+Up cause the app
|
|
|
|
// fullscreen under Windows, see QTBUG-91226 to learn more.
|
|
|
|
// The bug seems no longer exists in Qt 6 (I only tested it under Qt 6.3.0).
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
|
|
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
|
|
|
|
#else
|
2021-02-19 19:22:47 +08:00
|
|
|
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
|
2022-06-25 23:52:35 +08:00
|
|
|
#endif // QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
2020-12-29 23:28:17 +08:00
|
|
|
|
2021-10-02 19:57:42 +08:00
|
|
|
m_centralLayout->setContentsMargins(QMargins());
|
2020-12-29 23:28:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void FramelessWindow::setCentralWidget(QWidget *widget)
|
|
|
|
{
|
|
|
|
if (m_centralWidget) {
|
|
|
|
m_centralLayout->removeWidget(m_centralWidget);
|
|
|
|
m_centralWidget->deleteLater();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_centralLayout->addWidget(widget);
|
|
|
|
m_centralWidget = widget;
|
|
|
|
}
|
2021-01-10 14:57:01 +08:00
|
|
|
|
2021-10-02 19:57:42 +08:00
|
|
|
bool FramelessWindow::nativeEvent(const QByteArray &eventType, void *message, NATIVE_RESULT *result)
|
2021-01-10 14:57:01 +08:00
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
// https://stackoverflow.com/questions/43505580/qt-windows-resizable-frameless-window
|
|
|
|
// Too lazy to do this now.. just stackoverflow it and did a copy and paste..
|
|
|
|
Q_UNUSED(eventType)
|
|
|
|
MSG* msg = static_cast<MSG*>(message);
|
|
|
|
|
|
|
|
if (msg->message == WM_NCHITTEST) {
|
|
|
|
if (isMaximized()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result = 0;
|
|
|
|
const LONG borderWidth = 8;
|
|
|
|
RECT winrect;
|
|
|
|
GetWindowRect(reinterpret_cast<HWND>(winId()), &winrect);
|
|
|
|
|
|
|
|
// must be short to correctly work with multiple monitors (negative coordinates)
|
|
|
|
short x = msg->lParam & 0x0000FFFF;
|
|
|
|
short y = (msg->lParam & 0xFFFF0000) >> 16;
|
|
|
|
|
|
|
|
bool resizeWidth = minimumWidth() != maximumWidth();
|
|
|
|
bool resizeHeight = minimumHeight() != maximumHeight();
|
|
|
|
if (resizeWidth) {
|
|
|
|
//left border
|
|
|
|
if (x >= winrect.left && x < winrect.left + borderWidth) {
|
|
|
|
*result = HTLEFT;
|
|
|
|
}
|
|
|
|
//right border
|
|
|
|
if (x < winrect.right && x >= winrect.right - borderWidth) {
|
|
|
|
*result = HTRIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (resizeHeight) {
|
|
|
|
//bottom border
|
|
|
|
if (y < winrect.bottom && y >= winrect.bottom - borderWidth) {
|
|
|
|
*result = HTBOTTOM;
|
|
|
|
}
|
|
|
|
//top border
|
|
|
|
if (y >= winrect.top && y < winrect.top + borderWidth) {
|
|
|
|
*result = HTTOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (resizeWidth && resizeHeight) {
|
|
|
|
//bottom left corner
|
|
|
|
if (x >= winrect.left && x < winrect.left + borderWidth &&
|
|
|
|
y < winrect.bottom && y >= winrect.bottom - borderWidth)
|
|
|
|
{
|
|
|
|
*result = HTBOTTOMLEFT;
|
|
|
|
}
|
|
|
|
//bottom right corner
|
|
|
|
if (x < winrect.right && x >= winrect.right - borderWidth &&
|
|
|
|
y < winrect.bottom && y >= winrect.bottom - borderWidth)
|
|
|
|
{
|
|
|
|
*result = HTBOTTOMRIGHT;
|
|
|
|
}
|
|
|
|
//top left corner
|
|
|
|
if (x >= winrect.left && x < winrect.left + borderWidth &&
|
|
|
|
y >= winrect.top && y < winrect.top + borderWidth)
|
|
|
|
{
|
|
|
|
*result = HTTOPLEFT;
|
|
|
|
}
|
|
|
|
//top right corner
|
|
|
|
if (x < winrect.right && x >= winrect.right - borderWidth &&
|
|
|
|
y >= winrect.top && y < winrect.top + borderWidth)
|
|
|
|
{
|
|
|
|
*result = HTTOPRIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*result != 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
QWidget *action = QApplication::widgetAt(QCursor::pos());
|
|
|
|
if (action == this) {
|
|
|
|
*result = HTCAPTION;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
#else
|
|
|
|
return QWidget::nativeEvent(eventType, message, result);
|
|
|
|
#endif // _WIN32
|
|
|
|
}
|