diff options
author | Gunnar Sletta <gunnar.sletta@digia.com> | 2013-01-22 10:19:49 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-01-24 09:08:59 +0100 |
commit | fc663b5f9aae16fe6a03160e3eb148a5f742ac58 (patch) | |
tree | cdc95023da9a6f7c5068e31f07cdf0dbfb47fa13 | |
parent | a5fa0cf98cdedd6dc3488b590499b0b4387747dc (diff) |
Fix focus handling of native child widgets in xcb.
Change-Id: If4d596195624011142bff6853849a23064e478df
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
-rw-r--r-- | src/gui/kernel/qwindow_p.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 8 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 14 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 18 |
5 files changed, 44 insertions, 3 deletions
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index e02b87e921..dd526cb505 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -122,6 +122,8 @@ public: return offset; } + virtual QWindow *eventReceiver() { Q_Q(QWindow); return q; } + QWindow::SurfaceType surfaceType; Qt::WindowFlags windowFlags; QWindow *parentWindow; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index c477c3a1a5..44c730d375 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -258,6 +258,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char , has_randr_extension(false) , has_input_shape(false) , m_buttons(0) + , m_focusWindow(0) { #ifdef XCB_USE_XLIB Display *dpy = XOpenDisplay(m_displayName.constData()); @@ -418,7 +419,7 @@ break; if (QXcbWindow *platformWindow = platformWindowFromId(e->event)) { \ handled = QWindowSystemInterface::handleNativeEvent(platformWindow->window(), m_nativeInterface->genericEventFilterType(), event, &result); \ if (!handled) \ - m_keyboard->handler(platformWindow, e); \ + m_keyboard->handler(m_focusWindow, e); \ } \ } \ break; @@ -942,6 +943,11 @@ void QXcbEventReader::unlock() m_mutex.unlock(); } +void QXcbConnection::setFocusWindow(QXcbWindow *w) +{ + m_focusWindow = w; +} + void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) { xcb_client_message_event_t event; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 68d2b85f78..b499f75b78 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -385,6 +385,9 @@ public: Qt::MouseButtons buttons() const { return m_buttons; } + QXcbWindow *focusWindow() const { return m_focusWindow; } + void setFocusWindow(QXcbWindow *); + private slots: void processXcbEvents(); @@ -511,6 +514,8 @@ private: bool has_input_shape; Qt::MouseButtons m_buttons; + + QXcbWindow *m_focusWindow; }; #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 60cc547979..a8957d5810 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -403,6 +403,9 @@ QXcbWindow::~QXcbWindow() void QXcbWindow::destroy() { + if (connection()->focusWindow() == this) + connection()->setFocusWindow(0); + if (m_syncCounter && m_screen->syncRequestSupported()) Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); if (m_window) { @@ -1483,6 +1486,11 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) { + if (window() != QGuiApplication::focusWindow()) { + QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver(); + w->requestActivate(); + } + updateNetWmUserTime(event->time); QPoint local(event->event_x, event->event_y); @@ -1645,7 +1653,10 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *) { - QWindowSystemInterface::handleWindowActivated(window()); + QWindow *w = window(); + w = static_cast<QWindowPrivate *>(QObjectPrivate::get(w))->eventReceiver(); + connection()->setFocusWindow(static_cast<QXcbWindow *>(w->handle())); + QWindowSystemInterface::handleWindowActivated(w); } static bool focusInPeeker(xcb_generic_event_t *event) @@ -1661,6 +1672,7 @@ static bool focusInPeeker(xcb_generic_event_t *event) void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) { + connection()->setFocusWindow(0); // Do not set the active window to 0 if there is a FocusIn coming. // There is however no equivalent for XPutBackEvent so register a // callback for QXcbConnection instead. diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 462ebc605b..50b61beb05 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "private/qwindow_p.h" #include "qwidgetwindow_qpa_p.h" #include "private/qwidget_p.h" @@ -60,8 +61,23 @@ extern int openPopupCount; bool qt_replay_popup_mouse_event = false; extern bool qt_try_modal(QWidget *widget, QEvent::Type type); +class QWidgetWindowPrivate : public QWindowPrivate +{ + Q_DECLARE_PUBLIC(QWidgetWindow) +public: + QWindow *eventReceiver() { + Q_Q(QWidgetWindow); + QWindow *w = q; + while (w->parent() && qobject_cast<QWidgetWindow *>(w) && qobject_cast<QWidgetWindow *>(w->parent())) { + w = w->parent(); + } + return w; + } +}; + QWidgetWindow::QWidgetWindow(QWidget *widget) - : m_widget(widget) + : QWindow(*new QWidgetWindowPrivate(), 0) + , m_widget(widget) { updateObjectName(); connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); |