add better calc to fix zoneviewwidget behavior on windows

This commit is contained in:
Alex Okonechnikov 2026-01-01 08:38:55 -05:00
parent df9a8b2272
commit 7ef37998e8

View file

@ -272,31 +272,38 @@ void ZoneViewWidget::startWindowDrag(QGraphicsSceneMouseEvent *event)
QRectF ZoneViewWidget::closeButtonRect(QWidget *styleWidget) const QRectF ZoneViewWidget::closeButtonRect(QWidget *styleWidget) const
{ {
const QRectF frameRectF = windowFrameRect(); const QRectF frameRectF = windowFrameRect();
const QRect titleBarRect(frameRectF.toRect().x(), frameRectF.toRect().y(), frameRectF.toRect().width(), const QRectF contentRect = rect();
static_cast<int>(kTitleBarHeight));
// query the style for the close button position (handles macOS top-left placement) // Compute actual frame margins from frameRect vs contentRect
const qreal actualTopMargin = contentRect.top() - frameRectF.top();
const qreal actualLeftMargin = contentRect.left() - frameRectF.left();
// The visual titlebar spans the full frame width, not just content width
const qreal frameWidth = frameRectF.width();
// Query the platform style for close button position (handles macOS top-left placement)
if (styleWidget) { if (styleWidget) {
QStyleOptionTitleBar opt; QStyleOptionTitleBar opt;
opt.initFrom(styleWidget); opt.initFrom(styleWidget);
opt.rect = titleBarRect; // Use frame width since the titlebar visually spans the entire frame
opt.text = windowTitle(); opt.rect = QRect(0, 0, qRound(frameWidth), static_cast<int>(actualTopMargin));
opt.icon = styleWidget->windowIcon();
opt.titleBarFlags = Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint; opt.titleBarFlags = Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
opt.subControls = QStyle::SC_TitleBarCloseButton; opt.subControls = QStyle::SC_TitleBarCloseButton;
opt.activeSubControls = QStyle::SC_TitleBarCloseButton; opt.activeSubControls = QStyle::SC_TitleBarCloseButton;
opt.titleBarState = styleWidget->isActiveWindow() ? Qt::WindowActive : Qt::WindowNoState;
if (styleWidget->isActiveWindow())
opt.state |= QStyle::State_Active;
const QRect r = styleWidget->style()->subControlRect(QStyle::CC_TitleBar, &opt, QStyle::SC_TitleBarCloseButton, const QRect r = styleWidget->style()->subControlRect(QStyle::CC_TitleBar, &opt, QStyle::SC_TitleBarCloseButton,
styleWidget); styleWidget);
if (r.isValid() && !r.isEmpty()) { if (r.isValid() && !r.isEmpty()) {
return QRectF(r); // Style returns coords relative to titlebar at (0,0), but our frame's
// titlebar starts at x=-leftMargin and y=-topMargin relative to content origin.
return QRectF(r).translated(-actualLeftMargin, -actualTopMargin);
} }
} }
// fallback: square at right end of titlebar (Windows/Linux style) // Fallback: square at right end of titlebar (Windows/Linux style)
return QRectF(frameRectF.right() - kTitleBarHeight, frameRectF.top(), kTitleBarHeight, kTitleBarHeight); const qreal fallbackX = frameWidth - actualLeftMargin - actualTopMargin;
return QRectF(fallbackX, -actualTopMargin, actualTopMargin, actualTopMargin);
} }
QGraphicsView *ZoneViewWidget::findDragView(QWidget *eventWidget) const QGraphicsView *ZoneViewWidget::findDragView(QWidget *eventWidget) const
@ -342,16 +349,21 @@ bool ZoneViewWidget::windowFrameEvent(QEvent *event)
switch (event->type()) { switch (event->type()) {
case QEvent::GraphicsSceneMousePress: case QEvent::GraphicsSceneMousePress:
if (me->button() == Qt::LeftButton && windowFrameSectionAt(me->pos()) == Qt::TitleBarArea) { if (me->button() == Qt::LeftButton) {
// avoid drag on close button const QRectF closeRect = closeButtonRect(me->widget());
if (closeButtonRect(me->widget()).contains(me->pos())) {
// Close button takes priority over drag handling
if (closeRect.contains(me->pos())) {
me->accept(); me->accept();
close(); close();
return true; return true;
} }
startWindowDrag(me);
me->accept(); if (windowFrameSectionAt(me->pos()) == Qt::TitleBarArea) {
return true; startWindowDrag(me);
me->accept();
return true;
}
} }
break; break;