xcb: fix passing of focus from child to its top level QWindow
With the client message _NET_ACTIVE_WINDOW, not all window managers will pass focus from a child window to its root window, Detect this child-to-root case, and use xcb_set_input_focus() instead. Task-number: QTBUG-39362 Change-Id: Ib32193018e3b725b323f87d7306c9ae9493d78a7 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>bb10
parent
46078f3374
commit
ee22c6505a
|
|
@ -1698,9 +1698,11 @@ void QXcbWindow::requestActivateWindow()
|
|||
m_deferredActivation = false;
|
||||
|
||||
updateNetWmUserTime(connection()->time());
|
||||
QWindow *focusWindow = QGuiApplication::focusWindow();
|
||||
|
||||
if (window()->isTopLevel()
|
||||
&& !(window()->flags() & Qt::X11BypassWindowManagerHint)
|
||||
&& (!focusWindow || !window()->isAncestorOf(focusWindow))
|
||||
&& connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) {
|
||||
xcb_client_message_event_t event;
|
||||
|
||||
|
|
@ -1711,7 +1713,6 @@ void QXcbWindow::requestActivateWindow()
|
|||
event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW);
|
||||
event.data.data32[0] = 1;
|
||||
event.data.data32[1] = connection()->time();
|
||||
QWindow *focusWindow = QGuiApplication::focusWindow();
|
||||
event.data.data32[2] = focusWindow ? focusWindow->winId() : XCB_NONE;
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
|
|
|||
|
|
@ -601,6 +601,24 @@ void tst_QWindow::isActive()
|
|||
// child has focus
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
// test focus back to parent and then back to child (QTBUG-39362)
|
||||
// also verify the cumulative FocusOut and FocusIn counts
|
||||
// activate parent
|
||||
window.requestActivate();
|
||||
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
|
||||
QVERIFY(window.isActive());
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(child.received(QEvent::FocusOut), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 2);
|
||||
|
||||
// activate child again
|
||||
child.requestActivate();
|
||||
QTRY_COMPARE(QGuiApplication::focusWindow(), &child);
|
||||
QVERIFY(child.isActive());
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(window.received(QEvent::FocusOut), 2);
|
||||
QTRY_COMPARE(child.received(QEvent::FocusIn), 2);
|
||||
|
||||
Window dialog;
|
||||
dialog.setTransientParent(&window);
|
||||
dialog.setGeometry(QRect(m_availableTopLeft + QPoint(110, 100), m_testWindowSize));
|
||||
|
|
@ -625,7 +643,7 @@ void tst_QWindow::isActive()
|
|||
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(dialog.received(QEvent::FocusOut), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 2);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 3);
|
||||
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue