From f606ac3b92ecf7bd39a350f37284f5ab97db5d31 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 1 Jun 2026 11:45:28 +0200 Subject: [PATCH] UI/Qt: Show autocomplete above native web content Make the address autocomplete popup a non-activating top-level window. The Linux Vulkan web view is a native child window, so ordinary widgets that overlap it can be obscured by native stacking. Keeping the popup as a top-level tooltip-style window lets it appear above web content while preserving keyboard focus in the location edit. --- UI/Qt/Autocomplete.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/UI/Qt/Autocomplete.cpp b/UI/Qt/Autocomplete.cpp index aaa38cad1f..f510a67fe0 100644 --- a/UI/Qt/Autocomplete.cpp +++ b/UI/Qt/Autocomplete.cpp @@ -355,16 +355,20 @@ Autocomplete::Autocomplete(QLineEdit* anchor) , m_anchor(anchor) , m_autocomplete(make()) { - // The popup is parented to the anchor's top-level window in - // position_popup() rather than made its own window, so that showing - // it never causes the address bar to lose keyboard focus. - m_popup = new QFrame(); + // Use a non-activating top-level window so it can stack above native web + // content windows without moving keyboard focus away from the address bar. + m_popup = new QFrame(m_anchor->window(), Qt::ToolTip | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); + connect(m_popup, &QObject::destroyed, this, [this] { + m_popup = nullptr; + }); m_popup->setObjectName("LadybirdAutocompletePopup"); #if defined(AK_OS_MACOS) // The web content view is a native QRhiWidget on macOS, so the popup must // also be native to receive mouse events while overlapping it. m_popup->setAttribute(Qt::WA_NativeWindow); #endif + m_popup->setAttribute(Qt::WA_ShowWithoutActivating); + m_popup->setAttribute(Qt::WA_X11DoNotAcceptFocus); m_popup->setFocusPolicy(Qt::NoFocus); m_popup->setFrameShape(QFrame::StyledPanel); m_popup->setFrameShadow(QFrame::Raised); @@ -416,7 +420,8 @@ Autocomplete::Autocomplete(QLineEdit* anchor) Autocomplete::~Autocomplete() { qApp->removeEventFilter(this); - delete m_popup; + if (m_popup) + delete m_popup; } void Autocomplete::query_autocomplete_engine(String query) @@ -598,8 +603,11 @@ void Autocomplete::position_popup() auto* top_window = m_anchor->window(); if (!top_window) return; - if (m_popup->parentWidget() != top_window) - m_popup->setParent(top_window); + if (m_popup->parentWidget() != top_window) { + m_popup->setParent(top_window, Qt::ToolTip | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); + m_popup->setAttribute(Qt::WA_ShowWithoutActivating); + m_popup->setAttribute(Qt::WA_X11DoNotAcceptFocus); + } int width = std::max(m_anchor->width(), MINIMUM_POPUP_WIDTH); int frame_overhead = m_popup->frameWidth() * 2; @@ -608,8 +616,8 @@ void Autocomplete::position_popup() m_list_view->setFixedHeight(total_height); m_popup->setFixedSize(width, popup_height); - auto pos_in_window = m_anchor->mapTo(top_window, QPoint(0, m_anchor->height())); - m_popup->move(pos_in_window); + auto popup_position = m_anchor->mapToGlobal(QPoint(0, m_anchor->height())); + m_popup->move(popup_position); m_popup->raise(); }