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); HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
case XCB_CONFIGURE_NOTIFY: case XCB_CONFIGURE_NOTIFY:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); 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: case XCB_CLIENT_MESSAGE:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent);
case XCB_ENTER_NOTIFY: case XCB_ENTER_NOTIFY:

View File

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

View File

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

View File

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