[Completer] Minimum size popup, fall back to compact design if not possible. (#7111)
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions

* [Completer] Minimum size popup, fall back to compact design if not possible.

Took 15 minutes

Took 6 seconds


Took 5 minutes

* [Completer] Fix popup going offscreen by clamping in screen coordinates

The position clamping in applyPopupWidth() was comparing popup->pos()
(parent coordinates) against screen->availableGeometry() (screen
coordinates).  When the parent widget is not at the screen origin the
clamping computed a position in the wrong coordinate space, placing the
popup offscreen.  Convert to global coordinates first, clamp, then map
back to parent coordinates.

* [Completer] Clamp popup from geometry() in screen coordinates

setMinimumWidth() already widens the popup synchronously, so the old
width() < minWidth guard never ran and the popup grew past the right
screen edge. The popup is also a top-level Qt::Popup window, so move()
takes global coordinates and the mapFromGlobal round-trip moved it to
the top-left of the screen. Clamp x from geometry() after
setMinimumWidth() and move(QPoint(clampedX, popup->y())) directly.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-10-15 18:10:07 +02:00 • committed by GitHub
parent 96b0888a73
commit 213ce691dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 89 additions and 14 deletions

View file

@ -20,6 +20,7 @@
#include <QPropertyAnimation>
#include <QRect>
#include <QScreen>
#include <QScrollBar>
#include <QSharedPointer>
#include <QSize>
#include <QString>
@ -103,6 +104,7 @@ bool CardCompleterStyler::eventFilter(QObject *obj, QEvent *ev)
case QEvent::Show:
case QEvent::Move:
case QEvent::Resize:
applyPopupWidth();
updateOrientation();
reposition();
break;
@ -159,6 +161,42 @@ bool CardCompleterStyler::handlePopupKeyPress(QKeyEvent *event)
// ---------------------------------------------------------------------------
void CardCompleterStyler::applyPopupWidth()
{
auto *popup = completer->popup();
// QCompleter sizes its popup to the line edit, so a narrow search field
// would crush the rows. Ask for the width the rows are designed for (plus
// the frame and scrollbar) and let QWidget's geometry clamping keep the
// popup that wide, clamped to the screen it is shown on.
int contentWidth = CardCompleterDelegate::PopupRowWidth + popup->frameWidth() * 2;
if (auto *vbar = popup->verticalScrollBar(); vbar != nullptr) {
contentWidth += vbar->sizeHint().width();
}
const QScreen *screen = popup->screen();
const QRect available = screen ? screen->availableGeometry() : QRect();
const int minWidth = available.isEmpty() ? contentWidth : qMin(contentWidth, available.width());
popup->setMinimumWidth(minWidth);
// setMinimumWidth() already widened the popup if it was narrower, but
// QCompleter positioned it for the line-edit width, so the widened popup
// can now extend past the right screen edge. The popup is a top-level
// Qt::Popup window, so geometry()/move() are already in screen
// coordinates: clamp the x from geometry() and move directly.
if (!available.isEmpty()) {
const QRect geom = popup->geometry();
const int clampedX =
qBound(available.left(), geom.x(), qMax(available.left(), available.right() - geom.width() + 1));
if (clampedX != geom.x()) {
popup->move(QPoint(clampedX, popup->y()));
}
}
}
// ---------------------------------------------------------------------------
void CardCompleterStyler::updateOrientation()
{
above = isPopupAboveWidget();