Windows: Disable Windows input context when another context is used.

Remove QWindowsContext::instance() method and use
QPlatformIntegration::inputContext() with proper check instead.
Extract static method to disable Windows IME on a window
by associating a null context from QWindowsInputContext
and use that to disable the IME if another context is
in use.

Amends change b46fe39d94.

Change-Id: Icaad99d390cea5559167602ffbf994660d4717a5
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
bb10
Friedemann Kleint 2015-09-22 10:57:51 +02:00
parent d417f81f28
commit 47ff3dcd08
4 changed files with 48 additions and 31 deletions

View File

@ -33,6 +33,7 @@
****************************************************************************/
#include "qwindowscontext.h"
#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowskeymapper.h"
#include "qwindowsguieventdispatcher.h"
@ -907,16 +908,30 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
}
}
if (et & QtWindows::InputMethodEventFlag) {
QWindowsInputContext *windowsInputContext =
qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
// Disable IME assuming this is a special implementation hooking into keyboard input.
// "Real" IME implementations should use a native event filter intercepting IME events.
if (!windowsInputContext) {
QWindowsInputContext::setWindowsImeEnabled(platformWindow, false);
return false;
}
switch (et) {
case QtWindows::InputMethodStartCompositionEvent:
return windowsInputContext->startComposition(hwnd);
case QtWindows::InputMethodCompositionEvent:
return windowsInputContext->composition(hwnd, lParam);
case QtWindows::InputMethodEndCompositionEvent:
return windowsInputContext->endComposition(hwnd);
case QtWindows::InputMethodRequest:
return windowsInputContext->handleIME_Request(wParam, lParam, result);
default:
break;
}
} // InputMethodEventFlag
switch (et) {
case QtWindows::InputMethodStartCompositionEvent:
return QWindowsInputContext::instance()->startComposition(hwnd);
case QtWindows::InputMethodCompositionEvent:
return QWindowsInputContext::instance()->composition(hwnd, lParam);
case QtWindows::InputMethodEndCompositionEvent:
return QWindowsInputContext::instance()->endComposition(hwnd);
case QtWindows::InputMethodRequest:
return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result);
case QtWindows::GestureEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);

View File

@ -219,21 +219,24 @@ void QWindowsInputContext::updateEnabled()
const bool accepted = inputMethodAccepted();
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted;
if (accepted) {
// Re-enable IME by associating default context saved on first disabling.
if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
}
} else {
// Disable IME by associating 0 context. Store context first time.
if (!platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
if (!QWindowsInputContext::m_defaultContext && oldImC)
QWindowsInputContext::m_defaultContext = oldImC;
}
}
QWindowsInputContext::setWindowsImeEnabled(platformWindow, accepted);
}
}
void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled)
{
if (!platformWindow || platformWindow->testFlag(QWindowsWindow::InputMethodDisabled) == !enabled)
return;
if (enabled) {
// Re-enable Windows IME by associating default context saved on first disabling.
ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
} else {
// Disable Windows IME by associating 0 context. Store context first time.
const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
if (!QWindowsInputContext::m_defaultContext && oldImC)
QWindowsInputContext::m_defaultContext = oldImC;
}
}
@ -306,11 +309,6 @@ void QWindowsInputContext::invokeAction(QInputMethod::Action action, int cursorP
ImmReleaseContext(m_compositionContext.hwnd, himc);
}
QWindowsInputContext *QWindowsInputContext::instance()
{
return static_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
}
static inline QString getCompositionString(HIMC himc, DWORD dwIndex)
{
enum { bufferSize = 256 };

View File

@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE
class QInputMethodEvent;
class QWindowsWindow;
class QWindowsInputContext : public QPlatformInputContext
{
@ -62,14 +63,14 @@ public:
explicit QWindowsInputContext();
~QWindowsInputContext();
static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled);
bool hasCapability(Capability capability) const Q_DECL_OVERRIDE;
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();
bool startComposition(HWND hwnd);
bool composition(HWND hwnd, LPARAM lParam);
bool endComposition(HWND hwnd);

View File

@ -33,6 +33,7 @@
#include "qwindowskeymapper.h"
#include "qwindowscontext.h"
#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowsguieventdispatcher.h"
#include "qwindowsinputcontext.h"
@ -1074,7 +1075,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
// results, if we map this virtual key-code directly (for eg '?' US layouts). So try
// to find the correct key using the current message parameters & keyboard state.
if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
if (!QWindowsInputContext::instance()->isComposing())
const QWindowsInputContext *windowsInputContext =
qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
if (!(windowsInputContext && windowsInputContext->isComposing()))
vk_key = ImmGetVirtualKey((HWND)window->winId());
BYTE keyState[256];
wchar_t newKey[3] = {0};