10#include <QtCore/qdebug.h>
11#include <QtCore/qobject.h>
12#include <QtCore/qrect.h>
13#include <QtCore/qtextboundaryfinder.h>
15#include <QtGui/qevent.h>
16#include <QtGui/qtextformat.h>
17#include <QtGui/qpalette.h>
18#include <QtGui/qguiapplication.h>
20#include <private/qhighdpiscaling_p.h>
29 if (lParam & GCS_RESULTSTR)
31 if (lParam & GCS_COMPSTR)
33 if (lParam & GCS_COMPATTR)
35 if (lParam & GCS_CURSORPOS)
37 if (lParam & GCS_COMPCLAUSE)
39 if (lParam & CS_INSERTCHAR)
41 if (lParam & CS_NOMOVECARET)
42 str +=
"NOMOVECARET ";
50 qWarning() << __FUNCTION__ <<
"called with" << hwnd;
53 const HIMC himc = ImmGetContext(hwnd);
54 ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
55 ImmReleaseContext(hwnd, himc);
60 return localeId & 0xFFFF;
130 m_WM_MSIME_MOUSE(RegisterWindowMessage(L
"MSIMEMouseOperation")),
135 m_transparentBitmap = CreateBitmap(2, 2, 1, 1, &bmpData);
138 this, &QWindowsInputContext::cursorRectChanged);
143 if (m_transparentBitmap)
144 DeleteObject(m_transparentBitmap);
149 switch (capability) {
164 if (!m_compositionContext.hwnd)
166 qCDebug(lcQpaInputMethods) << __FUNCTION__;
167 if (m_compositionContext.isComposing && !m_compositionContext.focusObject.isNull()) {
169 if (!m_compositionContext.composition.isEmpty())
170 event.setCommitString(m_compositionContext.composition);
172 endContextComposition();
183 if (m_compositionContext.isComposing)
188HWND QWindowsInputContext::getVirtualKeyboardWindowHandle()
const
190 return ::FindWindowA(
"IPTip_Main_Window",
nullptr);
195 if (HWND hwnd = getVirtualKeyboardWindowHandle()) {
197 if (::GetWindowRect(hwnd, &
rect)) {
206 HWND hwnd = getVirtualKeyboardWindowHandle();
207 if (hwnd && ::IsWindowEnabled(hwnd) && ::IsWindowVisible(hwnd))
213 if (HIMC himc = ImmGetContext(platformWindow->handle()))
214 return ImmGetOpenStatus(himc);
237 if (!m_caretCreated && m_transparentBitmap)
238 m_caretCreated = CreateCaret(platformWindow->
handle(), m_transparentBitmap, 0, 0);
240 if (m_caretCreated) {
242 ShowCaret(platformWindow->
handle());
248 if (m_caretCreated) {
250 m_caretCreated =
false;
254void QWindowsInputContext::updateEnabled()
261 qCDebug(lcQpaInputMethods) << __FUNCTION__ << platformWindow->window() <<
"accepted=" << accepted;
272 ImmAssociateContextEx(platformWindow->
handle(),
nullptr, IACE_DEFAULT);
275 ImmAssociateContext(platformWindow->
handle(),
nullptr);
289void QWindowsInputContext::cursorRectChanged()
299 if (!cursorRectangleF.
isValid())
308 if (!m_compositionContext.hwnd)
313 const HIMC himc = ImmGetContext(m_compositionContext.hwnd);
319 cf.dwStyle = CFS_FORCE_POSITION;
325 candf.dwStyle = CFS_EXCLUDE;
333 ImmSetCompositionWindow(himc, &cf);
334 ImmSetCandidateWindow(himc, &candf);
335 ImmReleaseContext(m_compositionContext.hwnd, himc);
345 qCDebug(lcQpaInputMethods) << __FUNCTION__ << cursorPosition << action;
346 if (cursorPosition < 0 || cursorPosition > m_compositionContext.composition.size())
351 const HIMC himc = ImmGetContext(m_compositionContext.hwnd);
352 const HWND imeWindow = ImmGetDefaultIMEWnd(m_compositionContext.hwnd);
353 const WPARAM mouseOperationCode =
354 MAKELONG(MAKEWORD(MK_LBUTTON, cursorPosition == 0 ? 2 : 1), cursorPosition);
355 SendMessage(imeWindow, m_WM_MSIME_MOUSE, mouseOperationCode, LPARAM(himc));
356 ImmReleaseContext(m_compositionContext.hwnd, himc);
361 enum { bufferSize = 256 };
362 wchar_t buffer[bufferSize];
363 const int length = ImmGetCompositionString(himc, dwIndex,
buffer, bufferSize *
sizeof(
wchar_t));
370 enum { bufferSize = 256 };
372 char attrBuffer[bufferSize];
373 *selStart = *selLength = 0;
374 if (
const int attrLength = ImmGetCompositionString(himc, GCS_COMPATTR, attrBuffer, bufferSize)) {
376 while (
start < attrLength && !(attrBuffer[
start] & ATTR_TARGET_CONVERTED))
378 if (
start < attrLength) {
380 while (
end < attrLength && (attrBuffer[
end] & ATTR_TARGET_CONVERTED))
421 qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo <<
window <<
"language=" << m_languageId;
424 initContext(hwnd, fo);
425 startContextComposition();
429void QWindowsInputContext::startContextComposition()
431 if (m_compositionContext.isComposing) {
432 qWarning(
"%s: Called out of sequence.", __FUNCTION__);
435 m_compositionContext.isComposing =
true;
436 m_compositionContext.composition.clear();
437 m_compositionContext.position = 0;
442void QWindowsInputContext::endContextComposition()
444 if (!m_compositionContext.isComposing) {
445 qWarning(
"%s: Called out of sequence.", __FUNCTION__);
448 m_compositionContext.composition.clear();
449 m_compositionContext.position = 0;
450 m_compositionContext.isComposing =
false;
458 int selStart,
int selLength)
467 if (selStart + selLength < compositionLength)
469 compositionLength - selStart - selLength,
482 const int lParam = int(lParamIn);
483 qCDebug(lcQpaInputMethods) <<
'>' << __FUNCTION__ << m_compositionContext.focusObject
484 <<
debugComposition(lParam) <<
" composing=" << m_compositionContext.isComposing;
485 if (m_compositionContext.focusObject.isNull() || m_compositionContext.hwnd != hwnd || !lParam)
487 const HIMC himc = ImmGetContext(m_compositionContext.hwnd);
492 if (lParam & (GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS)) {
493 if (!m_compositionContext.isComposing)
494 startContextComposition();
497 int selStart, selLength;
499 m_compositionContext.position = ImmGetCompositionString(himc, GCS_CURSORPOS,
nullptr, 0);
501 if ((lParam & CS_INSERTCHAR) && (lParam & CS_NOMOVECARET)) {
504 selLength = m_compositionContext.composition.size();
511 m_compositionContext.composition.size(),
512 selStart, selLength)));
517 if (lParam & GCS_RESULTSTR) {
520 if (!(lParam & GCS_DELTASTART))
521 endContextComposition();
524 qCDebug(lcQpaInputMethods) <<
'<' << __FUNCTION__ <<
"sending markup="
525 <<
event->attributes().size() <<
" commit=" <<
event->commitString()
526 <<
" to " << m_compositionContext.focusObject <<
" returns " <<
result;
528 ImmReleaseContext(m_compositionContext.hwnd, himc);
534 qCDebug(lcQpaInputMethods) << __FUNCTION__ << m_endCompositionRecursionGuard << hwnd;
538 if (m_endCompositionRecursionGuard || m_compositionContext.hwnd != hwnd)
540 if (m_compositionContext.focusObject.isNull())
551 m_endCompositionRecursionGuard =
true;
554 if (m_compositionContext.isComposing) {
560 m_endCompositionRecursionGuard =
false;
564void QWindowsInputContext::initContext(HWND hwnd,
QObject *focusObject)
566 if (m_compositionContext.hwnd)
568 m_compositionContext.hwnd = hwnd;
569 m_compositionContext.focusObject = focusObject;
572 m_compositionContext.isComposing =
false;
573 m_compositionContext.position = 0;
576void QWindowsInputContext::doneContext()
578 if (!m_compositionContext.hwnd)
580 m_compositionContext.hwnd =
nullptr;
581 m_compositionContext.composition.clear();
582 m_compositionContext.position = 0;
583 m_compositionContext.isComposing =
false;
584 m_compositionContext.focusObject =
nullptr;
591 switch (
int(wParam)) {
592 case IMR_RECONVERTSTRING: {
599 case IMR_CONFIRMRECONVERTSTRING:
610 if (newLanguageId == m_languageId)
612 const LCID oldLanguageId = m_languageId;
613 m_languageId = newLanguageId;
618 << oldLanguageId <<
"->" << newLanguageId <<
"Character set:"
640 if (!surroundingTextV.
isValid())
643 const int memSize = int(
sizeof(RECONVERTSTRING))
645 qCDebug(lcQpaInputMethods) << __FUNCTION__ <<
" reconv=" << reconv
646 <<
" surroundingText=" << surroundingText <<
" size=" << memSize;
649 return surroundingText.
isEmpty() ? -1 : memSize;
658 const int startPos = bounds.
position();
660 const int endPos = bounds.
position();
661 qCDebug(lcQpaInputMethods) << __FUNCTION__ <<
" boundary=" << startPos << endPos;
668 reconv->dwSize = DWORD(memSize);
669 reconv->dwVersion = 0;
671 reconv->dwStrLen = DWORD(surroundingText.
size());
672 reconv->dwStrOffset =
sizeof(RECONVERTSTRING);
673 reconv->dwCompStrLen = DWORD(endPos - startPos);
674 reconv->dwCompStrOffset = DWORD(startPos) *
sizeof(
ushort);
675 reconv->dwTargetStrLen = reconv->dwCompStrLen;
676 reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
677 auto *pastReconv =
reinterpret_cast<ushort *
>(reconv + 1);
678 std::copy(surroundingText.
utf16(), surroundingText.
utf16() + surroundingText.
size(),
The QColor class provides colors based on RGB, HSV or CMYK values.
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QPalette palette()
Returns the current application palette.
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
static QInputMethod * inputMethod()
returns the input method.
static Qt::KeyboardModifiers queryKeyboardModifiers()
Queries and returns the state of the modifier keys on the keyboard.
static qreal factor(C *context)
Language language() const
Returns the language of this locale.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
The QPalette class contains color groups for each widget state.
bool inputMethodAccepted() const
Returns true if current focus object supports input method events.
virtual void invokeAction(QInputMethod::Action, int cursorPosition)
Called when the word currently being composed in the input item is tapped by the user.
static QRectF cursorRectangle()
QPlatformInputContext::cursorRectangle.
\inmodule QtCore\reentrant
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr qreal height() const noexcept
Returns the height of the rectangle.
constexpr qreal width() const noexcept
Returns the width of the rectangle.
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
\inmodule QtCore\reentrant
\macro QT_RESTRICTED_CAST_FROM_ASCII
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
qsizetype size() const
Returns the number of characters in this string.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
qsizetype length() const
Returns the number of characters in this string.
BoundaryReasons boundaryReasons() const
Returns the reasons for the boundary finder to have chosen the current position as a boundary.
void setPosition(qsizetype position)
Sets the current position of the QTextBoundaryFinder to position.
qsizetype toNextBoundary()
Moves the QTextBoundaryFinder to the next boundary position and returns that position.
qsizetype toPreviousBoundary()
Moves the QTextBoundaryFinder to the previous boundary position and returns that position.
qsizetype position() const
Returns the current position of the QTextBoundaryFinder.
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
static HWND handleOf(const QWindow *w)
~QWindowsInputContext() override
QRectF keyboardRect() const override
This function can be reimplemented to return virtual keyboard rectangle in currently active window co...
void update(Qt::InputMethodQueries) override
Moves the candidate window along with microfocus of the focus object.
bool composition(HWND hwnd, LPARAM lParam)
Notify focus object about markup or final text.
bool hasCapability(Capability capability) const override
Returns whether the implementation supports capability.
bool startComposition(HWND hwnd)
void invokeAction(QInputMethod::Action, int cursorPosition) override
Called when the word currently being composed in the input item is tapped by the user.
void handleInputLanguageChanged(WPARAM wparam, LPARAM lparam)
void showInputPanel() override
Request to show input panel.
static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled)
bool isInputPanelVisible() const override
Returns input panel visibility status.
void setFocusObject(QObject *object) override
This virtual method gets called to notify updated focus to object.
bool handleIME_Request(WPARAM wparam, LPARAM lparam, LRESULT *result)
int reconvertString(RECONVERTSTRING *reconv)
Determines the string for reconversion with selection.
bool endComposition(HWND hwnd)
void hideInputPanel() override
Request to hide input panel.
void reset() override
Cancels a composition.
static QWindowsWindow * windowsWindowOf(const QWindow *w)
HWND handle() const override
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
QTextStream & showbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ShowBase) on stream and r...
QTextStream & noshowbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ShowBase) on stream and ...
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
#define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x)
Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id)
#define qCDebug(category,...)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei GLsizei GLenum format
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QList< QInputMethodEvent::Attribute > intermediateMarkup(int position, int compositionLength, int selStart, int selLength)
static void imeNotifyCancelComposition(HWND hwnd)
static void getCompositionStringConvertedRange(HIMC himc, int *selStart, int *selLength)
static QString getCompositionString(HIMC himc, DWORD dwIndex)
static LCID currentInputLanguageId()
static QT_BEGIN_NAMESPACE QByteArray debugComposition(int lParam)
Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id)
static QTextFormat standardFormat(StandardFormat format)
static LCID languageIdFromLocaleId(LCID localeId)