Drop workaround to turn popups into main windows
On Wayland there are additional requirements when making popups to Qt. In regular cases we can guess what the popup parent should be based on which window last received input, but as it's a heuristic with obscure enough timing events this can sometimes fail. In this situation the current code creates a toplevel instead of a regular popup, having a popup take focus with a window decoration is rarely a good UX. Rather than making an incorrect window, the new approach is to not create a popup over the wire and synthesise an immediate close event. Application code should be able to handle this as it's the same path if the popup was denied server side. Pick-to: 6.9 Task-number: QTBUG-136343 Change-Id: Ia76c36a047e93f2469a8bf0f4b94642f05179124 Reviewed-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
This commit is contained in:
parent
991c83cc96
commit
8c0dd12f4b
@ -314,10 +314,20 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s
|
||||
Qt::WindowType type = window->window()->type();
|
||||
auto *transientParent = window->transientParent();
|
||||
|
||||
if (type == Qt::ToolTip && transientParent) {
|
||||
setPopup(transientParent);
|
||||
} else if (type == Qt::Popup && transientParent && display->lastInputDevice()) {
|
||||
setGrabPopup(transientParent, display->lastInputDevice(), display->lastInputSerial());
|
||||
if (type == Qt::ToolTip) {
|
||||
if (transientParent) {
|
||||
setPopup(transientParent);
|
||||
} else {
|
||||
qCWarning(lcQpaWayland) << "Failed to create popup. Ensure popup " << window->window() << "has a transientParent set.";
|
||||
QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::AsynchronousDelivery>(m_window->window());
|
||||
}
|
||||
} else if (type == Qt::Popup ) {
|
||||
if (transientParent && display->lastInputDevice()) {
|
||||
setGrabPopup(transientParent, display->lastInputDevice(), display->lastInputSerial());
|
||||
} else {
|
||||
qCWarning(lcQpaWayland) << "Failed to create grabbing popup. Ensure popup " << window->window() << "has a transientParent set and that parent window has received input.";
|
||||
QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::AsynchronousDelivery>(m_window->window());
|
||||
}
|
||||
} else {
|
||||
setToplevel();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ private slots:
|
||||
void tooltipAndSiblingPopup();
|
||||
void switchPopups();
|
||||
void hidePopupParent();
|
||||
void popupsWithoutParent();
|
||||
void pongs();
|
||||
void minMaxSize_data();
|
||||
void minMaxSize();
|
||||
@ -608,6 +609,45 @@ void tst_xdgshell::hidePopupParent()
|
||||
QCOMPOSITOR_TRY_VERIFY(!xdgToplevel());
|
||||
}
|
||||
|
||||
void tst_xdgshell::popupsWithoutParent()
|
||||
{
|
||||
QRasterWindow popup;
|
||||
QSignalSpy popupDoneSpy(&popup, &QWindow::visibilityChanged);
|
||||
popup.setFlags(Qt::Popup);
|
||||
popup.resize(100, 100);
|
||||
popup.show();
|
||||
QVERIFY(popup.isVisible());
|
||||
|
||||
// popup cannot be created within the spec, so it gets auto-dismissed
|
||||
QVERIFY(popupDoneSpy.wait());
|
||||
QVERIFY(!popup.isVisible());
|
||||
|
||||
QCOMPOSITOR_VERIFY(!xdgToplevel());
|
||||
|
||||
// now make a normal window with an input event
|
||||
QRasterWindow window;
|
||||
window.setTitle("main window");
|
||||
window.resize(200, 200);
|
||||
window.show();
|
||||
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
|
||||
exec([&] { xdgToplevel()->sendCompleteConfigure(); });
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial);
|
||||
exec([&] {
|
||||
keyboard()->sendEnter(xdgToplevel()->surface());
|
||||
keyboard()->sendKey(client(), 72, Keyboard::key_state_pressed); // related with native scan code
|
||||
keyboard()->sendKey(client(), 72, Keyboard::key_state_released); // related with native scan code
|
||||
});
|
||||
QTRY_COMPARE(qGuiApp->focusWindow(), &window);
|
||||
|
||||
// now re-show our popup, it should be able to guess a transient this time
|
||||
// and correctly show as a popup
|
||||
popup.show();
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgPopup());
|
||||
exec([&] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial);
|
||||
}
|
||||
|
||||
void tst_xdgshell::pongs()
|
||||
{
|
||||
// Create and show a window to trigger shell integration initialzation,
|
||||
|
Loading…
x
Reference in New Issue
Block a user