fix: avoid promoting child widgets to child windows (#5161)

This commit is contained in:
nerix
2024-02-10 12:43:59 +01:00
committed by GitHub
parent f34a371576
commit 10aabd39e7
4 changed files with 94 additions and 30 deletions
+66 -30
View File
@@ -201,7 +201,7 @@ void BaseWindow::init()
}
// DPI
// auto dpi = getWindowDpi(this->winId());
// auto dpi = getWindowDpi(this->safeHWND());
// if (dpi) {
// this->scale = dpi.value() / 96.f;
@@ -232,12 +232,13 @@ void BaseWindow::setTopMost(bool topMost)
{
return;
}
this->isTopMost_ = topMost;
#ifdef USEWINSDK
::SetWindowPos(reinterpret_cast<HWND>(this->winId()),
topMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
if (!this->waitingForTopMost_)
{
this->tryApplyTopMost();
}
#else
auto isVisible = this->isVisible();
this->setWindowFlag(Qt::WindowStaysOnTopHint, topMost);
@@ -247,10 +248,26 @@ void BaseWindow::setTopMost(bool topMost)
}
#endif
this->isTopMost_ = topMost;
this->topMostChanged(this->isTopMost_);
}
#ifdef USEWINSDK
void BaseWindow::tryApplyTopMost()
{
auto hwnd = this->safeHWND();
if (!hwnd)
{
this->waitingForTopMost_ = true;
QTimer::singleShot(50, this, &BaseWindow::tryApplyTopMost);
return;
}
this->waitingForTopMost_ = false;
::SetWindowPos(*hwnd, this->isTopMost_ ? HWND_TOPMOST : HWND_NOTOPMOST, 0,
0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
#endif
bool BaseWindow::isTopMost() const
{
return this->isTopMost_ || this->flags_.has(TopMost);
@@ -491,12 +508,15 @@ void BaseWindow::changeEvent(QEvent *)
if (this->isVisible() && this->hasCustomWindowFrame())
{
auto palette = this->palette();
palette.setColor(QPalette::Window,
GetForegroundWindow() == HWND(this->winId())
? QColor(90, 90, 90)
: QColor(50, 50, 50));
this->setPalette(palette);
auto hwnd = this->safeHWND();
if (hwnd)
{
auto palette = this->palette();
palette.setColor(QPalette::Window, GetForegroundWindow() == *hwnd
? QColor(90, 90, 90)
: QColor(50, 50, 50));
this->setPalette(palette);
}
}
#endif
@@ -532,14 +552,18 @@ void BaseWindow::resizeEvent(QResizeEvent *)
{
this->isResizeFixing_ = true;
QTimer::singleShot(50, this, [this] {
auto hwnd = this->safeHWND();
if (!hwnd)
{
this->isResizeFixing_ = false;
return;
}
RECT rect;
::GetWindowRect((HWND)this->winId(), &rect);
::SetWindowPos((HWND)this->winId(), nullptr, 0, 0,
rect.right - rect.left + 1, rect.bottom - rect.top,
SWP_NOMOVE | SWP_NOZORDER);
::SetWindowPos((HWND)this->winId(), nullptr, 0, 0,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOMOVE | SWP_NOZORDER);
::GetWindowRect(*hwnd, &rect);
::SetWindowPos(*hwnd, nullptr, 0, 0, rect.right - rect.left + 1,
rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
::SetWindowPos(*hwnd, nullptr, 0, 0, rect.right - rect.left,
rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
QTimer::singleShot(10, this, [this] {
this->isResizeFixing_ = false;
});
@@ -579,9 +603,10 @@ void BaseWindow::showEvent(QShowEvent *)
if (!this->flags_.has(TopMost))
{
QTimer::singleShot(1, this, [this] {
::SetWindowPos(reinterpret_cast<HWND>(this->winId()),
this->isTopMost_ ? HWND_TOPMOST : HWND_NOTOPMOST, 0,
0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
if (!this->waitingForTopMost_)
{
this->tryApplyTopMost();
}
});
}
#endif
@@ -653,7 +678,7 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message,
long y = GET_Y_LPARAM(msg->lParam);
RECT winrect;
GetWindowRect(HWND(winId()), &winrect);
GetWindowRect(msg->hwnd, &winrect);
QPoint globalPos(x, y);
this->ui_.titlebarButtons->hover(msg->wParam, globalPos);
this->lastEventWasNcMouseMove_ = true;
@@ -704,7 +729,7 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message,
long y = GET_Y_LPARAM(msg->lParam);
RECT winrect;
GetWindowRect(HWND(winId()), &winrect);
GetWindowRect(msg->hwnd, &winrect);
QPoint globalPos(x, y);
if (msg->message == WM_NCLBUTTONDOWN)
{
@@ -852,7 +877,7 @@ bool BaseWindow::handleSHOWWINDOW(MSG *msg)
{
// disable OS window border
const MARGINS margins = {-1};
DwmExtendFrameIntoClientArea(HWND(this->winId()), &margins);
DwmExtendFrameIntoClientArea(msg->hwnd, &margins);
}
if (!this->initalBounds_.isNull())
@@ -888,8 +913,8 @@ bool BaseWindow::handleNCCALCSIZE(MSG *msg, long *result)
auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg->lParam);
if (ncp)
{
ncp->lppos->flags |= SWP_NOREDRAW;
ncp->rgrc[0].top -= 1;
// ncp->lppos->flags |= SWP_NOREDRAW;
// ncp->rgrc[0].top -= 1;
}
}
@@ -915,8 +940,8 @@ bool BaseWindow::handleSIZE(MSG *msg)
{
if (msg->wParam == SIZE_MAXIMIZED)
{
auto offset = int(
getWindowDpi(HWND(this->winId())).value_or(96) * 8 / 96);
auto offset =
int(getWindowDpi(msg->hwnd).value_or(96) * 8 / 96);
this->ui_.windowLayout->setContentsMargins(offset, offset,
offset, offset);
@@ -970,7 +995,7 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result)
#ifdef USEWINSDK
const LONG border_width = 8; // in pixels
RECT winrect;
GetWindowRect(HWND(winId()), &winrect);
GetWindowRect(msg->hwnd, &winrect);
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
@@ -1149,4 +1174,15 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result)
#endif
}
#ifdef USEWINSDK
std::optional<HWND> BaseWindow::safeHWND() const
{
if (!this->testAttribute(Qt::WA_WState_Created))
{
return std::nullopt;
}
return reinterpret_cast<HWND>(this->winId());
}
#endif
} // namespace chatterino