Fix focus handling of native child widgets in xcb.

Change-Id: If4d596195624011142bff6853849a23064e478df
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
(cherry picked from commit fc663b5f9a)
This commit is contained in:
Gunnar Sletta 2013-01-22 10:19:49 +01:00 committed by The Qt Project
parent 18f9eb797b
commit 3f99983e76
5 changed files with 44 additions and 3 deletions

View File

@ -120,6 +120,8 @@ public:
return offset;
}
virtual QWindow *eventReceiver() { Q_Q(QWindow); return q; }
QWindow::SurfaceType surfaceType;
Qt::WindowFlags windowFlags;
QWindow *parentWindow;

View File

@ -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;
@ -943,6 +944,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;

View File

@ -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()))

View File

@ -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) {
@ -1473,6 +1476,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);
@ -1635,7 +1643,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)
@ -1651,6 +1662,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.

View File

@ -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);