summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2014-07-30 15:13:41 +0200
committerFriedemann Kleint <Friedemann.Kleint@digia.com>2014-08-04 17:13:36 +0200
commit501fe9f9395eedc8294f5098466a322b32d13ea4 (patch)
treed37af1da079c7507012f3cdeb125ff93e9b89d41 /src/plugins/platforms/windows
parent219c2eb4e28dd1c806cbc2115ff40454d6d3f9c5 (diff)
Implement focus change for Windows Input context.
Keep track of the focus object in the input context ensuring that events on canceling are sent to the right object. Task-number: QTBUG-40402 Change-Id: I79820db94d97e21b47abc8fe2bae6fa012d31236 Reviewed-by: Liang Qi <liang.qi@digia.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp47
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h5
2 files changed, 33 insertions, 19 deletions
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index bc7ffc9afd..f8676c30f7 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -83,6 +83,10 @@ static inline QByteArray debugComposition(int lParam)
// Cancel current IME composition.
static inline void imeNotifyCancelComposition(HWND hwnd)
{
+ if (!hwnd) {
+ qWarning() << __FUNCTION__ << "called with" << hwnd;
+ return;
+ }
const HIMC himc = ImmGetContext(hwnd);
ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
ImmReleaseContext(hwnd, himc);
@@ -175,21 +179,27 @@ void QWindowsInputContext::reset()
QPlatformInputContext::reset();
if (!m_compositionContext.hwnd)
return;
- QObject *fo = qApp->focusObject();
- qCDebug(lcQpaInputMethods) << __FUNCTION__<< fo;
- if (!fo)
- return;
- if (m_compositionContext.isComposing) {
+ qCDebug(lcQpaInputMethods) << __FUNCTION__;
+ if (m_compositionContext.isComposing && m_compositionContext.focusObject.isNull()) {
QInputMethodEvent event;
if (!m_compositionContext.composition.isEmpty())
event.setCommitString(m_compositionContext.composition);
- QCoreApplication::sendEvent(fo, &event);
+ QCoreApplication::sendEvent(m_compositionContext.focusObject, &event);
endContextComposition();
}
imeNotifyCancelComposition(m_compositionContext.hwnd);
doneContext();
}
+void QWindowsInputContext::setFocusObject(QObject *)
+{
+ // ### fixme: On Windows 8.1, it has been observed that the Input context
+ // remains active when this happens resulting in a lock-up. Consecutive
+ // key events still have VK_PROCESSKEY set and are thus ignored.
+ if (m_compositionContext.isComposing)
+ imeNotifyCancelComposition(m_compositionContext.hwnd);
+}
+
/*!
\brief Moves the candidate window along with microfocus of the focus object.
*/
@@ -317,7 +327,7 @@ static inline QTextFormat standardFormat(StandardFormat format)
bool QWindowsInputContext::startComposition(HWND hwnd)
{
- const QObject *fo = qApp->focusObject();
+ QObject *fo = QGuiApplication::focusObject();
if (!fo)
return false;
// This should always match the object.
@@ -327,7 +337,7 @@ bool QWindowsInputContext::startComposition(HWND hwnd)
qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo << window;
if (!fo || QWindowsWindow::handleOf(window) != hwnd)
return false;
- initContext(hwnd);
+ initContext(hwnd, fo);
startContextComposition();
return true;
}
@@ -341,6 +351,7 @@ void QWindowsInputContext::startContextComposition()
m_compositionContext.isComposing = true;
m_compositionContext.composition.clear();
m_compositionContext.position = 0;
+ cursorRectChanged(); // position cursor initially.
update(Qt::ImQueryAll);
}
@@ -384,11 +395,10 @@ static inline QList<QInputMethodEvent::Attribute>
bool QWindowsInputContext::composition(HWND hwnd, LPARAM lParamIn)
{
- QObject *fo = qApp->focusObject();
const int lParam = int(lParamIn);
- qCDebug(lcQpaInputMethods) << '>' << __FUNCTION__ << fo << debugComposition(lParam)
- << " composing=" << m_compositionContext.isComposing;
- if (!fo || m_compositionContext.hwnd != hwnd || !lParam)
+ qCDebug(lcQpaInputMethods) << '>' << __FUNCTION__ << m_compositionContext.focusObject
+ << debugComposition(lParam) << " composing=" << m_compositionContext.isComposing;
+ if (m_compositionContext.focusObject.isNull() || m_compositionContext.hwnd != hwnd || !lParam)
return false;
const HIMC himc = ImmGetContext(m_compositionContext.hwnd);
if (!himc)
@@ -425,10 +435,10 @@ bool QWindowsInputContext::composition(HWND hwnd, LPARAM lParamIn)
event->setCommitString(getCompositionString(himc, GCS_RESULTSTR));
endContextComposition();
}
- const bool result = QCoreApplication::sendEvent(fo, event.data());
+ const bool result = QCoreApplication::sendEvent(m_compositionContext.focusObject, event.data());
qCDebug(lcQpaInputMethods) << '<' << __FUNCTION__ << "sending markup="
<< event->attributes().size() << " commit=" << event->commitString()
- << " to " << fo << " returns " << result;
+ << " to " << m_compositionContext.focusObject << " returns " << result;
update(Qt::ImQueryAll);
ImmReleaseContext(m_compositionContext.hwnd, himc);
return result;
@@ -442,8 +452,7 @@ bool QWindowsInputContext::endComposition(HWND hwnd)
// against that.
if (m_endCompositionRecursionGuard || m_compositionContext.hwnd != hwnd)
return false;
- QObject *fo = qApp->focusObject();
- if (!fo)
+ if (m_compositionContext.focusObject.isNull())
return false;
m_endCompositionRecursionGuard = true;
@@ -451,7 +460,7 @@ bool QWindowsInputContext::endComposition(HWND hwnd)
imeNotifyCancelComposition(m_compositionContext.hwnd);
if (m_compositionContext.isComposing) {
QInputMethodEvent event;
- QCoreApplication::sendEvent(fo, &event);
+ QCoreApplication::sendEvent(m_compositionContext.focusObject, &event);
}
doneContext();
@@ -459,11 +468,12 @@ bool QWindowsInputContext::endComposition(HWND hwnd)
return true;
}
-void QWindowsInputContext::initContext(HWND hwnd)
+void QWindowsInputContext::initContext(HWND hwnd, QObject *focusObject)
{
if (m_compositionContext.hwnd)
doneContext();
m_compositionContext.hwnd = hwnd;
+ m_compositionContext.focusObject = focusObject;
// Create a hidden caret which is kept at the microfocus
// position in update(). This is important for some
// Chinese input methods.
@@ -484,6 +494,7 @@ void QWindowsInputContext::doneContext()
m_compositionContext.composition.clear();
m_compositionContext.position = 0;
m_compositionContext.isComposing = m_compositionContext.haveCaret = false;
+ m_compositionContext.focusObject = 0;
}
bool QWindowsInputContext::handleIME_Request(WPARAM wParam,
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 51ea8adf1e..8ab684b837 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -44,6 +44,7 @@
#include "qtwindows_additional.h"
+#include <QtCore/QPointer>
#include <qpa/qplatforminputcontext.h>
QT_BEGIN_NAMESPACE
@@ -63,6 +64,7 @@ class QWindowsInputContext : public QPlatformInputContext
QString composition;
int position;
bool isComposing;
+ QPointer<QObject> focusObject;
};
public:
explicit QWindowsInputContext();
@@ -71,6 +73,7 @@ public:
void reset() Q_DECL_OVERRIDE;
void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
+ void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
static QWindowsInputContext *instance();
@@ -86,7 +89,7 @@ private slots:
void cursorRectChanged();
private:
- void initContext(HWND hwnd);
+ void initContext(HWND hwnd, QObject *focusObject);
void doneContext();
void startContextComposition();
void endContextComposition();