Prevent XSetInputFocus BadMatch errors.

The BadMatch errors are generated if XSetInputFocus is called before the
window has been mapped, so we need to set a flag when we get the map
notify event.
This commit is contained in:
Samuel Rødal 2011-06-01 13:02:57 +02:00
parent ead7c1c33c
commit f05236a40d
4 changed files with 27 additions and 2 deletions

View File

@ -442,6 +442,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
case XCB_CONFIGURE_NOTIFY:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
case XCB_MAP_NOTIFY:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent);
case XCB_CLIENT_MESSAGE:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent);
case XCB_ENTER_NOTIFY:

View File

@ -94,6 +94,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
, m_window(0)
, m_context(0)
, m_syncCounter(0)
, m_mapped(false)
{
m_screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens().at(0));
@ -278,6 +279,7 @@ void QXcbWindow::destroy()
connection()->removeWindow(m_window);
Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
}
m_mapped = false;
}
void QXcbWindow::setGeometry(const QRect &rect)
@ -367,6 +369,8 @@ void QXcbWindow::hide()
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
xcb_flush(xcb_connection());
m_mapped = false;
}
struct QtMotifWmHints {
@ -877,8 +881,10 @@ void QXcbWindow::propagateSizeHints()
void QXcbWindow::requestActivateWindow()
{
Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, XCB_TIME_CURRENT_TIME));
connection()->sync();
if (m_mapped){
Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, XCB_TIME_CURRENT_TIME));
connection()->sync();
}
}
QPlatformGLContext *QXcbWindow::glContext() const
@ -968,6 +974,12 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
#endif
}
void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
{
if (event->window == m_window)
m_mapped = true;
}
static Qt::MouseButtons translateMouseButtons(int s)
{
Qt::MouseButtons ret = 0;

View File

@ -83,6 +83,7 @@ public:
void handleExposeEvent(const xcb_expose_event_t *event);
void handleClientMessageEvent(const xcb_client_message_event_t *event);
void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event);
void handleMapNotifyEvent(const xcb_map_notify_event_t *event);
void handleButtonPressEvent(const xcb_button_press_event_t *event);
void handleButtonReleaseEvent(const xcb_button_release_event_t *event);
void handleMotionNotifyEvent(const xcb_motion_notify_event_t *event);
@ -127,6 +128,8 @@ private:
bool m_hasReceivedSyncRequest;
Qt::WindowState m_windowState;
bool m_mapped;
};
#endif

View File

@ -10226,18 +10226,26 @@ void tst_QWidget::nativeChildFocus()
QLineEdit *p2 = new QLineEdit;
layout->addWidget(p1);
layout->addWidget(p2);
#if 1
p1->setObjectName("p1");
p2->setObjectName("p2");
#endif
w.show();
#if 1
w.activateWindow();
p1->setFocus();
p1->setAttribute(Qt::WA_NativeWindow);
p2->setAttribute(Qt::WA_NativeWindow);
QApplication::processEvents();
QTest::qWaitForWindowShown(&w);
QTest::qWait(10);
qDebug() << "checking active window:" << QApplication::activeWindow();
QCOMPARE(QApplication::activeWindow(), &w);
QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
#endif
QTest::qWait(1000);
}
QTEST_MAIN(tst_QWidget)