summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowsinputcontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsinputcontext.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp78
1 files changed, 40 insertions, 38 deletions
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 2429e8a4fa..2284c47ed6 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -44,6 +44,7 @@
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
#include "qwindowsmousehandler.h"
+#include "qwindowsscaling.h"
#include <QtCore/QDebug>
#include <QtCore/QObject>
@@ -83,23 +84,15 @@ 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);
}
-// Query a QObject for an InputMethod-related value
-// by sending a QInputMethodQueryEvent.
-template <class T>
- bool inputMethodQuery(QObject *fo, Qt::InputMethodQuery query, T *result)
-{
- QInputMethodQueryEvent queryEvent(query);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return false;
- *result = qvariant_cast<T>(queryEvent.value(query));
- return true;
-}
-
/*!
\class QWindowsInputContext
\brief Windows Input context implementation
@@ -170,7 +163,7 @@ QWindowsInputContext::QWindowsInputContext() :
m_WM_MSIME_MOUSE(RegisterWindowMessage(L"MSIMEMouseOperation")),
m_endCompositionRecursionGuard(false)
{
- connect(qApp->inputMethod(), SIGNAL(cursorRectangleChanged()),
+ connect(QGuiApplication::inputMethod(), SIGNAL(cursorRectangleChanged()),
this, SLOT(cursorRectChanged()));
}
@@ -187,21 +180,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.
*/
@@ -215,10 +214,11 @@ void QWindowsInputContext::cursorRectChanged()
{
if (!m_compositionContext.hwnd)
return;
- const QInputMethod *inputMethod = qApp->inputMethod();
- QRect cursorRectangle = inputMethod->cursorRectangle().toRect();
- if (!cursorRectangle.isValid())
+ const QInputMethod *inputMethod = QGuiApplication::inputMethod();
+ const QRect cursorRectangleDip = inputMethod->cursorRectangle().toRect();
+ if (!cursorRectangleDip.isValid())
return;
+ const QRect cursorRectangle = QWindowsScaling::mapToNative(cursorRectangleDip);
qCDebug(lcQpaInputMethods) << __FUNCTION__<< cursorRectangle;
@@ -329,7 +329,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.
@@ -339,7 +339,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;
}
@@ -353,6 +353,7 @@ void QWindowsInputContext::startContextComposition()
m_compositionContext.isComposing = true;
m_compositionContext.composition.clear();
m_compositionContext.position = 0;
+ cursorRectChanged(); // position cursor initially.
update(Qt::ImQueryAll);
}
@@ -396,11 +397,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)
@@ -437,10 +437,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;
@@ -454,8 +454,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;
@@ -463,7 +462,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();
@@ -471,11 +470,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.
@@ -496,6 +496,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,
@@ -536,9 +537,10 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
if (!fo)
return false;
- QString surroundingText;
- if (!inputMethodQuery(fo, Qt::ImSurroundingText, &surroundingText))
+ const QVariant surroundingTextV = QInputMethod::queryFocusObject(Qt::ImSurroundingText, QVariant());
+ if (!surroundingTextV.isValid())
return -1;
+ const QString surroundingText = surroundingTextV.toString();
const DWORD memSize = sizeof(RECONVERTSTRING)
+ (surroundingText.length() + 1) * sizeof(ushort);
qCDebug(lcQpaInputMethods) << __FUNCTION__ << " reconv=" << reconv
@@ -547,8 +549,8 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
if (!reconv)
return surroundingText.isEmpty() ? -1 : int(memSize);
- int pos = 0;
- inputMethodQuery(fo, Qt::ImCursorPosition, &pos);
+ const QVariant posV = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant());
+ const int pos = posV.isValid() ? posV.toInt() : 0;
// Find the word in the surrounding text.
QTextBoundaryFinder bounds(QTextBoundaryFinder::Word, surroundingText);
bounds.setPosition(pos);