From f05236a40d7ee9299c5855d70e542143a2d342c8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Samuel=20R=C3=B8dal?= Date: Wed, 1 Jun 2011 13:02:57 +0200 Subject: [PATCH] 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. --- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 ++ src/plugins/platforms/xcb/qxcbwindow.cpp | 16 ++++++++++++++-- src/plugins/platforms/xcb/qxcbwindow.h | 3 +++ tests/auto/qwidget/tst_qwidget.cpp | 8 ++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 89b5072..5b0d9d8 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -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: diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index d46e140..e4f4fd7 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -94,6 +94,7 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_window(0) , m_context(0) , m_syncCounter(0) + , m_mapped(false) { m_screen = static_cast(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; diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 2260832..40d21f4 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -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 diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 7c0042a..1d3591d 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -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(p1)); +#endif + + QTest::qWait(1000); } QTEST_MAIN(tst_QWidget) -- 2.7.4