KeyRelease = 7, // key released
FocusIn = 8, // keyboard focus received
FocusOut = 9, // keyboard focus lost
+ FocusAboutToChange = 23, // keyboard focus is about to be lost
Enter = 10, // mouse enters widget
Leave = 11, // mouse leaves widget
Paint = 12, // paint widget
void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e)
{
QWindow *previous = QGuiApplicationPrivate::focus_window;
- QGuiApplicationPrivate::focus_window = e->activated.data();
+ QWindow *newFocus = e->activated.data();
- if (previous == QGuiApplicationPrivate::focus_window)
+ if (previous == newFocus)
return;
QObject *previousFocusObject = previous ? previous->focusObject() : 0;
if (previous) {
+ QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
+ QCoreApplication::sendSpontaneousEvent(previous, &focusAboutToChange);
+ }
+
+ QGuiApplicationPrivate::focus_window = newFocus;
+
+ if (previous) {
QFocusEvent focusOut(QEvent::FocusOut);
QCoreApplication::sendSpontaneousEvent(previous, &focusOut);
QObject::disconnect(previous, SIGNAL(focusObjectChanged(QObject*)),
}
QWidget *prev = focus_widget;
focus_widget = focus;
-#ifndef QT_NO_IM
- if (prev && ((reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
- && prev->testAttribute(Qt::WA_InputMethodEnabled))
- // Do reset the input context, in case the new focus widget won't accept keyboard input
- // or it is not created fully yet.
- || (focus_widget && (!focus_widget->testAttribute(Qt::WA_InputMethodEnabled)
- || !focus_widget->testAttribute(Qt::WA_WState_Created))))) {
- qApp->inputMethod()->reset();
- }
-#endif //QT_NO_IM
if(focus_widget)
focus_widget->d_func()->setFocus_sys();
QApplication::sendEvent(that->style(), &in);
}
emit qApp->focusChanged(prev, focus_widget);
- emit qApp->focusObjectChanged(focus_widget);
}
}
}
}
}
+ if (QApplicationPrivate::focus_widget) {
+ if (QApplicationPrivate::focus_widget->testAttribute(Qt::WA_InputMethodEnabled))
+ qApp->inputMethod()->reset();
+
+ QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, Qt::ActiveWindowFocusReason);
+ QApplication::sendEvent(QApplicationPrivate::focus_widget, &focusAboutToChange);
+ }
+
QApplicationPrivate::active_window = window;
if (QApplicationPrivate::active_window) {
If the window is not active, the widget will be given the focus when
the window becomes active.
- First, a focus out event is sent to the focus widget (if any) to
- tell it that it is about to lose the focus. Then a focus in event
- is sent to this widget to tell it that it just received the focus.
+ First, a focus about to change event is sent to the focus widget (if any) to
+ tell it that it is about to lose the focus. Then focus is changed, a
+ focus out event is sent to the previous focus item and a focus in event is sent
+ to the new item to tell it that it just received the focus.
(Nothing happens if the focus in and focus out widgets are the
same.)
}
#endif
- QWidget *w = f;
- if (isHidden()) {
- while (w && w->isHidden()) {
- w->d_func()->focus_child = f;
- w = w->isWindow() ? 0 : w->parentWidget();
- }
- } else {
- while (w) {
- w->d_func()->focus_child = f;
- w = w->isWindow() ? 0 : w->parentWidget();
- }
- }
-
#ifndef QT_NO_GRAPHICSVIEW
// Update proxy state
if (QWExtra *topData = window()->d_func()->extra) {
if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
+ f->d_func()->updateFocusChild();
topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
topData->proxyWidget->setFocus(reason);
topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
#endif
if (f->isActiveWindow()) {
+ QWidget *prev = QApplicationPrivate::focus_widget;
+ if (prev) {
+ if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
+ && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
+ qApp->inputMethod()->reset();
+ }
+
+ if (reason != Qt::NoFocusReason) {
+ QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
+ QApplication::sendEvent(prev, &focusAboutToChange);
+ }
+ }
+
+ f->d_func()->updateFocusChild();
+
QApplicationPrivate::setFocusWidget(f, reason);
#ifndef QT_NO_ACCESSIBILITY
# ifdef Q_OS_WIN
}
}
#endif
+ } else {
+ f->d_func()->updateFocusChild();
+ }
+
+ if (QTLWExtra *extra = f->window()->d_func()->maybeTopData())
+ emit extra->window->focusObjectChanged(f);
+}
+
+// updates focus_child on parent widgets to point into this widget
+void QWidgetPrivate::updateFocusChild()
+{
+ Q_Q(QWidget);
+
+ QWidget *w = q;
+ if (q->isHidden()) {
+ while (w && w->isHidden()) {
+ w->d_func()->focus_child = q;
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ } else {
+ while (w) {
+ w->d_func()->focus_child = q;
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
}
}
Takes keyboard input focus from the widget.
If the widget has active focus, a \link focusOutEvent() focus out
- event\endlink is sent to this widget to tell it that it is about
- to lose the focus.
+ event\endlink is sent to this widget to tell it that it has
+ lost the focus.
This widget must enable focus setting in order to get the keyboard
input focus, i.e. it must call setFocusPolicy().
void QWidget::clearFocus()
{
+ if (hasFocus()) {
+ if (testAttribute(Qt::WA_InputMethodEnabled))
+ qApp->inputMethod()->reset();
+
+ QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
+ QApplication::sendEvent(this, &focusAboutToChange);
+ }
+
QWidget *w = this;
while (w) {
if (w->d_func()->focus_child == this)
void stackUnder_sys(QWidget *);
void setFocus_sys();
+ void updateFocusChild();
void updateFont(const QFont &);
inline void setFont_helper(const QFont &font) {
case QEvent::FocusOut:
return false;
+ case QEvent::FocusAboutToChange:
+ if (QApplicationPrivate::focus_widget) {
+ if (QApplicationPrivate::focus_widget->testAttribute(Qt::WA_InputMethodEnabled))
+ qApp->inputMethod()->commit();
+
+ QGuiApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, event);
+ }
+ return true;
+
case QEvent::KeyPress:
case QEvent::KeyRelease:
handleKeyEvent(static_cast<QKeyEvent *>(event));
void allWindows();
void topLevelWindows();
void abortQuitOnShow();
+ void changeFocusWindow();
};
class DummyWindow : public QWindow
QCOMPARE(app.exec(), 1);
}
+
+class FocusChangeWindow: public QWindow
+{
+protected:
+ virtual bool event(QEvent *ev)
+ {
+ if (ev->type() == QEvent::FocusAboutToChange)
+ windowDuringFocusAboutToChange = qGuiApp->focusWindow();
+ return QWindow::event(ev);
+ }
+
+ virtual void focusOutEvent(QFocusEvent *)
+ {
+ windowDuringFocusOut = qGuiApp->focusWindow();
+ }
+
+public:
+ FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
+
+ QWindow *windowDuringFocusAboutToChange;
+ QWindow *windowDuringFocusOut;
+};
+
+void tst_QGuiApplication::changeFocusWindow()
+{
+ int argc = 0;
+ QGuiApplication app(argc, 0);
+
+ // focus is changed between FocusAboutToChange and FocusChanged
+ FocusChangeWindow window1, window2;
+ window1.show();
+ window2.show();
+ QTest::qWaitForWindowShown(&window1);
+ QTest::qWaitForWindowShown(&window2);
+ window1.requestActivateWindow();
+ QTRY_COMPARE(app.focusWindow(), &window1);
+
+ window2.requestActivateWindow();
+ QTRY_COMPARE(app.focusWindow(), &window2);
+ QCOMPARE(window1.windowDuringFocusAboutToChange, &window1);
+ QCOMPARE(window1.windowDuringFocusOut, &window2);
+}
+
+
QTEST_APPLESS_MAIN(tst_QGuiApplication)
#include "tst_qguiapplication.moc"
QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
}
+class FocusWidget: public QWidget
+{
+protected:
+ virtual bool event(QEvent *ev)
+ {
+ if (ev->type() == QEvent::FocusAboutToChange)
+ widgetDuringFocusAboutToChange = qApp->focusWidget();
+ return QWidget::event(ev);
+ }
+ virtual void focusOutEvent(QFocusEvent *)
+ {
+ widgetDuringFocusOut = qApp->focusWidget();
+ }
+
+public:
+ FocusWidget(QWidget *parent) : QWidget(parent), widgetDuringFocusAboutToChange(0), widgetDuringFocusOut(0) {}
+
+ QWidget *widgetDuringFocusAboutToChange;
+ QWidget *widgetDuringFocusOut;
+};
+
void tst_QWidget::setFocus()
{
{
// window and children show, but window *is* active, children get focus
QWidget window;
- QWidget child1(&window);
+ FocusWidget child1(&window);
child1.setFocusPolicy(Qt::StrongFocus);
QWidget child2(&window);
child2.setFocusPolicy(Qt::StrongFocus);
window.show();
-#ifdef Q_WS_X11
- QApplication::setActiveWindow(&window);
- QTest::qWaitForWindowShown(&window);
-#else
window.activateWindow();
- QApplication::processEvents();
-#endif
+ QTest::qWaitForWindowShown(&window);
+ QTRY_VERIFY(qGuiApp->focusWindow());
child1.setFocus();
QTRY_VERIFY(child1.hasFocus());
QVERIFY(child2.hasFocus());
QCOMPARE(window.focusWidget(), &child2);
QCOMPARE(QApplication::focusWidget(), &child2);
+
+ // focus changed in between the events
+ QCOMPARE(child1.widgetDuringFocusAboutToChange, &child1);
+ QCOMPARE(child1.widgetDuringFocusOut, &child2);
}
{
QWidget window;
window.show();
-#ifdef Q_WS_X11
- QApplication::setActiveWindow(&window);
- QTest::qWaitForWindowShown(&window);
-#else
window.activateWindow();
-#endif
+ QTest::qWaitForWindowShown(&window);
+ QTRY_VERIFY(qGuiApp->focusWindow());
QWidget child1(&window);
child1.setFocusPolicy(Qt::StrongFocus);
QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
child1.show();
-#ifdef Q_WS_X11
- QApplication::setActiveWindow(&child1);
- child1.activateWindow();
-#endif
QApplication::processEvents();
QTRY_VERIFY(child1.hasFocus());
QCOMPARE(window.focusWidget(), &child1);
QWidget window;
window.show();
-#ifdef Q_WS_X11
- QApplication::setActiveWindow(&window);
- QTest::qWaitForWindowShown(&window);
-#else
window.activateWindow();
-#endif
+ QTest::qWaitForWindowShown(&window);
+ QTRY_VERIFY(qGuiApp->focusWindow());
QWidget child1(&window);
child1.setFocusPolicy(Qt::StrongFocus);