summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qcoreevent.h1
-rw-r--r--src/gui/kernel/qguiapplication.cpp11
-rw-r--r--src/widgets/kernel/qapplication.cpp19
-rw-r--r--src/widgets/kernel/qwidget.cpp72
-rw-r--r--src/widgets/kernel/qwidget_p.h1
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa.cpp9
6 files changed, 82 insertions, 31 deletions
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 1d54b32dfa..bfd99208cc 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -75,6 +75,7 @@ public:
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
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 5611296385..e12183869a 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1155,14 +1155,21 @@ void QGuiApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::Le
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*)),
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 7441d55865..ce57e2868d 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1760,16 +1760,6 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
}
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();
@@ -1798,7 +1788,6 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
QApplication::sendEvent(that->style(), &in);
}
emit qApp->focusChanged(prev, focus_widget);
- emit qApp->focusObjectChanged(focus_widget);
}
}
}
@@ -2051,6 +2040,14 @@ void QApplication::setActiveWindow(QWidget* act)
}
}
+ 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) {
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 6418ba63e1..63eb2540ff 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -5875,9 +5875,10 @@ bool QWidget::hasFocus() const
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.)
@@ -5930,23 +5931,11 @@ void QWidget::setFocus(Qt::FocusReason reason)
}
#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;
@@ -5955,6 +5944,21 @@ void QWidget::setFocus(Qt::FocusReason reason)
#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
@@ -5999,6 +6003,30 @@ void QWidget::setFocus(Qt::FocusReason reason)
}
}
#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();
+ }
}
}
@@ -6015,8 +6043,8 @@ void QWidget::setFocus(Qt::FocusReason reason)
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().
@@ -6027,6 +6055,14 @@ void QWidget::setFocus(Qt::FocusReason reason)
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)
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 38314c234b..8107b6ca74 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -336,6 +336,7 @@ public:
void stackUnder_sys(QWidget *);
void setFocus_sys();
+ void updateFocusChild();
void updateFont(const QFont &);
inline void setFont_helper(const QFont &font) {
diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp
index f58dddb70f..7a13e2032e 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa.cpp
+++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp
@@ -99,6 +99,15 @@ bool QWidgetWindow::event(QEvent *event)
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));