Forward IME messages to ScintillaWX and handle them
The handling code is copied from ScintillaWin Closes #18759
This commit is contained in:
@@ -5493,6 +5493,10 @@ protected:
|
|||||||
void NotifyChange();
|
void NotifyChange();
|
||||||
void NotifyParent(SCNotification* scn);
|
void NotifyParent(SCNotification* scn);
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxOVERRIDE;
|
||||||
|
#endif // __WXMSW__
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
wxDECLARE_DYNAMIC_CLASS(wxStyledTextCtrl);
|
wxDECLARE_DYNAMIC_CLASS(wxStyledTextCtrl);
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#include "ScintillaWX.h"
|
#include "ScintillaWX.h"
|
||||||
#include "ExternalLexer.h"
|
#include "ExternalLexer.h"
|
||||||
|
#include "UniConversion.h"
|
||||||
#include "wx/stc/stc.h"
|
#include "wx/stc/stc.h"
|
||||||
#include "wx/stc/private.h"
|
#include "wx/stc/private.h"
|
||||||
#include "PlatWX.h"
|
#include "PlatWX.h"
|
||||||
@@ -844,6 +845,31 @@ sptr_t ScintillaWX::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam)
|
|||||||
case SCI_GETDIRECTPOINTER:
|
case SCI_GETDIRECTPOINTER:
|
||||||
return reinterpret_cast<sptr_t>(this);
|
return reinterpret_cast<sptr_t>(this);
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
// ScintillaWin
|
||||||
|
case WM_IME_STARTCOMPOSITION: // dbcs
|
||||||
|
// TODO: We haven't ported WM_IME_COMPOSITION yet, so always use windowed IME to make it at least work
|
||||||
|
//if (KoreanIME() || imeInteraction == imeInline) {
|
||||||
|
if (false) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImeStartComposition();
|
||||||
|
return stc->wxControl::MSWWindowProc(iMessage, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_IME_ENDCOMPOSITION: // dbcs
|
||||||
|
ImeEndComposition();
|
||||||
|
return stc->wxControl::MSWWindowProc(iMessage, wParam, lParam);
|
||||||
|
|
||||||
|
case WM_IME_KEYDOWN:
|
||||||
|
case WM_IME_REQUEST:
|
||||||
|
case WM_IME_COMPOSITION:
|
||||||
|
case WM_IME_SETCONTEXT:
|
||||||
|
// TODO: Port event handling from ScintillaWin
|
||||||
|
return stc->wxControl::MSWWindowProc(iMessage, wParam, lParam);
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ScintillaBase::WndProc(iMessage, wParam, lParam);
|
return ScintillaBase::WndProc(iMessage, wParam, lParam);
|
||||||
}
|
}
|
||||||
@@ -1407,6 +1433,114 @@ sptr_t ScintillaWX::DirectFunction(
|
|||||||
return swx->WndProc(iMessage, wParam, lParam);
|
return swx->WndProc(iMessage, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// ScintillaWin
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
POINT POINTFromPoint(Point pt) wxNOEXCEPT {
|
||||||
|
POINT ret;
|
||||||
|
ret.x = static_cast<LONG>(pt.x);
|
||||||
|
ret.y = static_cast<LONG>(pt.y);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
class IMContext {
|
||||||
|
HWND hwnd;
|
||||||
|
public:
|
||||||
|
HIMC hIMC;
|
||||||
|
IMContext(HWND hwnd_) wxNOEXCEPT :
|
||||||
|
hwnd(hwnd_), hIMC(::ImmGetContext(hwnd_)) {
|
||||||
|
}
|
||||||
|
~IMContext() {
|
||||||
|
if (hIMC)
|
||||||
|
::ImmReleaseContext(hwnd, hIMC);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int GetImeCaretPos() const wxNOEXCEPT {
|
||||||
|
return ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, wxNullPtr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BYTE> GetImeAttributes() {
|
||||||
|
const int attrLen = ::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, wxNullPtr, 0);
|
||||||
|
std::vector<BYTE> attr(attrLen, 0);
|
||||||
|
::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, &attr[0], static_cast<DWORD>(attr.size()));
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring GetCompositionString(DWORD dwIndex) {
|
||||||
|
const LONG byteLen = ::ImmGetCompositionStringW(hIMC, dwIndex, wxNullPtr, 0);
|
||||||
|
std::wstring wcs(byteLen / 2, 0);
|
||||||
|
::ImmGetCompositionStringW(hIMC, dwIndex, &wcs[0], byteLen);
|
||||||
|
return wcs;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
// Private so IMContext objects can not be copied.
|
||||||
|
IMContext(const IMContext&);
|
||||||
|
IMContext& operator=(const IMContext&);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND ScintillaWX::MainHWND() const wxNOEXCEPT {
|
||||||
|
return static_cast<HWND>(wMain.GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DBCS: support Input Method Editor (IME).
|
||||||
|
* Called when IME Window opened.
|
||||||
|
*/
|
||||||
|
void ScintillaWX::ImeStartComposition() {
|
||||||
|
if (caret.active) {
|
||||||
|
// Move IME Window to current caret position
|
||||||
|
IMContext imc(stc->GetHandle());
|
||||||
|
const Point pos = PointMainCaret();
|
||||||
|
COMPOSITIONFORM CompForm;
|
||||||
|
CompForm.dwStyle = CFS_POINT;
|
||||||
|
CompForm.ptCurrentPos = POINTFromPoint(pos);
|
||||||
|
|
||||||
|
::ImmSetCompositionWindow(imc.hIMC, &CompForm);
|
||||||
|
|
||||||
|
// Set font of IME window to same as surrounded text.
|
||||||
|
if (stylesValid) {
|
||||||
|
// Since the style creation code has been made platform independent,
|
||||||
|
// The logfont for the IME is recreated here.
|
||||||
|
const int styleHere = pdoc->StyleIndexAt(sel.MainCaret());
|
||||||
|
LOGFONTW lf = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"" };
|
||||||
|
int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER;
|
||||||
|
if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
|
||||||
|
sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
|
||||||
|
AutoSurface surface(this);
|
||||||
|
int deviceHeight = sizeZoomed;
|
||||||
|
if (surface) {
|
||||||
|
deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72;
|
||||||
|
}
|
||||||
|
// The negative is to allow for leading
|
||||||
|
lf.lfHeight = -(std::abs(deviceHeight / SC_FONT_SIZE_MULTIPLIER));
|
||||||
|
lf.lfWeight = vs.styles[styleHere].weight;
|
||||||
|
lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0);
|
||||||
|
lf.lfCharSet = DEFAULT_CHARSET;
|
||||||
|
lf.lfFaceName[0] = L'\0';
|
||||||
|
if (vs.styles[styleHere].fontName) {
|
||||||
|
const char* fontName = vs.styles[styleHere].fontName;
|
||||||
|
UTF16FromUTF8(fontName, strlen(fontName)+1, lf.lfFaceName, LF_FACESIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
::ImmSetCompositionFontW(imc.hIMC, &lf);
|
||||||
|
}
|
||||||
|
// Caret is displayed in IME window. So, caret in Scintilla is useless.
|
||||||
|
DropCaret();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when IME Window closed. */
|
||||||
|
void ScintillaWX::ImeEndComposition() {
|
||||||
|
ShowCaretAtCurrentPosition();
|
||||||
|
}
|
||||||
|
#endif // __WXMSW__
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -238,6 +238,15 @@ private:
|
|||||||
wxDataFormat m_clipRectTextFormat;
|
wxDataFormat m_clipRectTextFormat;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
// ScintillaWin
|
||||||
|
HWND MainHWND() const wxNOEXCEPT;
|
||||||
|
|
||||||
|
// DBCS
|
||||||
|
void ImeStartComposition();
|
||||||
|
void ImeEndComposition();
|
||||||
|
#endif
|
||||||
|
|
||||||
friend class wxSTCCallTip;
|
friend class wxSTCCallTip;
|
||||||
friend class wxSTCTimer; // To get access to TickReason declaration
|
friend class wxSTCTimer; // To get access to TickReason declaration
|
||||||
};
|
};
|
||||||
|
@@ -5674,6 +5674,26 @@ void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
|
|||||||
GetEventHandler()->ProcessEvent(evt);
|
GetEventHandler()->ProcessEvent(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
WXLRESULT wxStyledTextCtrl::MSWWindowProc(WXUINT nMsg,
|
||||||
|
WXWPARAM wParam,
|
||||||
|
WXLPARAM lParam)
|
||||||
|
{
|
||||||
|
switch(nMsg) {
|
||||||
|
// Forward IME messages to ScintillaWX
|
||||||
|
case WM_IME_KEYDOWN:
|
||||||
|
case WM_IME_REQUEST:
|
||||||
|
case WM_IME_STARTCOMPOSITION:
|
||||||
|
case WM_IME_ENDCOMPOSITION:
|
||||||
|
case WM_IME_COMPOSITION:
|
||||||
|
case WM_IME_SETCONTEXT:
|
||||||
|
return SendMsg(nMsg, wParam, lParam);
|
||||||
|
default:
|
||||||
|
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
@@ -1201,6 +1201,26 @@ void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
|
|||||||
GetEventHandler()->ProcessEvent(evt);
|
GetEventHandler()->ProcessEvent(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
WXLRESULT wxStyledTextCtrl::MSWWindowProc(WXUINT nMsg,
|
||||||
|
WXWPARAM wParam,
|
||||||
|
WXLPARAM lParam)
|
||||||
|
{
|
||||||
|
switch(nMsg) {
|
||||||
|
// Forward IME messages to ScintillaWX
|
||||||
|
case WM_IME_KEYDOWN:
|
||||||
|
case WM_IME_REQUEST:
|
||||||
|
case WM_IME_STARTCOMPOSITION:
|
||||||
|
case WM_IME_ENDCOMPOSITION:
|
||||||
|
case WM_IME_COMPOSITION:
|
||||||
|
case WM_IME_SETCONTEXT:
|
||||||
|
return SendMsg(nMsg, wParam, lParam);
|
||||||
|
default:
|
||||||
|
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
@@ -611,6 +611,10 @@ protected:
|
|||||||
void NotifyChange();
|
void NotifyChange();
|
||||||
void NotifyParent(SCNotification* scn);
|
void NotifyParent(SCNotification* scn);
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxOVERRIDE;
|
||||||
|
#endif // __WXMSW__
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
wxDECLARE_DYNAMIC_CLASS(wxStyledTextCtrl);
|
wxDECLARE_DYNAMIC_CLASS(wxStyledTextCtrl);
|
||||||
|
Reference in New Issue
Block a user