Add minimum composition text support in IME
This commit is contained in:
parent
7184119409
commit
1620cbdbd8
@ -8,6 +8,8 @@
|
|||||||
#include "IGUIElement.h"
|
#include "IGUIElement.h"
|
||||||
#include "SColor.h"
|
#include "SColor.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace gui
|
namespace gui
|
||||||
@ -125,6 +127,9 @@ namespace gui
|
|||||||
|
|
||||||
//! Returns maximum amount of characters, previously set by setMax();
|
//! Returns maximum amount of characters, previously set by setMax();
|
||||||
virtual u32 getMax() const = 0;
|
virtual u32 getMax() const = 0;
|
||||||
|
virtual void setComposingText(const std::u32string& ct) = 0;
|
||||||
|
virtual void clearComposingText() = 0;
|
||||||
|
virtual const core::position2di& getICPos() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,7 +124,13 @@ namespace gui
|
|||||||
|
|
||||||
//! Reads attributes of the element
|
//! Reads attributes of the element
|
||||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||||
|
virtual void setComposingText(const std::u32string& ct) {}
|
||||||
|
virtual void clearComposingText() {}
|
||||||
|
virtual const core::position2di& getICPos() const
|
||||||
|
{
|
||||||
|
static core::position2di unused;
|
||||||
|
return unused;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
//! Breaks the single text line.
|
//! Breaks the single text line.
|
||||||
void breakText();
|
void breakText();
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
|
#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
|
||||||
|
|
||||||
#include "CIrrDeviceWin32.h"
|
#include "CIrrDeviceWin32.h"
|
||||||
|
#include "IGUIEditBox.h"
|
||||||
|
#include "IGUIEnvironment.h"
|
||||||
|
#include "IGUIFont.h"
|
||||||
|
#include "IGUISkin.h"
|
||||||
#include "IEventReceiver.h"
|
#include "IEventReceiver.h"
|
||||||
#include "irrList.h"
|
#include "irrList.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@ -952,6 +956,15 @@ irr::CIrrDeviceWin32* getDeviceFromHWnd(HWND hWnd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateIMECompositonPosition(irr::core::position2di pos, HWND hwnd, HIMC himc)
|
||||||
|
{
|
||||||
|
COMPOSITIONFORM cf;
|
||||||
|
cf.dwStyle = CFS_POINT;
|
||||||
|
cf.ptCurrentPos.x = pos.X;
|
||||||
|
cf.ptCurrentPos.y = pos.Y;
|
||||||
|
ImmSetCompositionWindow(himc, &cf);
|
||||||
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
#ifndef WM_MOUSEWHEEL
|
#ifndef WM_MOUSEWHEEL
|
||||||
@ -1043,7 +1056,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev = getDeviceFromHWnd(hWnd);
|
dev = getDeviceFromHWnd(hWnd);
|
||||||
if (dev)
|
if (dev && !dev->isIMEComposingStarted())
|
||||||
{
|
{
|
||||||
dev->postEventFromUser(event);
|
dev->postEventFromUser(event);
|
||||||
|
|
||||||
@ -1078,22 +1091,116 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
|
|
||||||
case WM_ERASEBKGND:
|
case WM_ERASEBKGND:
|
||||||
return 0;
|
return 0;
|
||||||
|
case WM_SETFOCUS:
|
||||||
case WM_IME_CHAR:
|
case WM_KILLFOCUS:
|
||||||
|
{
|
||||||
|
dev = getDeviceFromHWnd(hWnd);
|
||||||
|
if (dev)
|
||||||
|
dev->setIMEComposingStarted(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_IME_SETCONTEXT:
|
||||||
|
{
|
||||||
|
// application wants to draw composition text by itself.
|
||||||
|
lParam &= ~(ISC_SHOWUICOMPOSITIONWINDOW);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_IME_STARTCOMPOSITION:
|
||||||
|
case WM_IME_ENDCOMPOSITION:
|
||||||
{
|
{
|
||||||
dev = getDeviceFromHWnd(hWnd);
|
dev = getDeviceFromHWnd(hWnd);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return 0;
|
return 0;
|
||||||
event.EventType = irr::EET_KEY_INPUT_EVENT;
|
|
||||||
event.KeyInput.PressedDown = true;
|
irr::gui::IGUIEnvironment* env = dev->getGUIEnvironment();
|
||||||
event.KeyInput.Char = (char32_t)wParam;
|
if (!env)
|
||||||
event.KeyInput.Key = irr::IRR_KEY_UNKNOWN;
|
return 0;
|
||||||
event.KeyInput.Shift = false;
|
|
||||||
event.KeyInput.Control = false;
|
irr::gui::IGUISkin* skin = env->getSkin();
|
||||||
dev->postEventFromUser(event);
|
if (!skin)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
irr::gui::IGUIFont* font = skin->getFont();
|
||||||
|
if (!font)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
irr::gui::IGUIEditBox* box = dynamic_cast<irr::gui::IGUIEditBox*>(env->getFocus());
|
||||||
|
if (!box)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
box->clearComposingText();
|
||||||
|
dev->setIMEComposingStarted(message == WM_IME_STARTCOMPOSITION);
|
||||||
|
HIMC imc = ImmGetContext(hWnd);
|
||||||
|
if (!imc)
|
||||||
|
return 0;
|
||||||
|
if (message == WM_IME_STARTCOMPOSITION)
|
||||||
|
{
|
||||||
|
updateIMECompositonPosition(box->getICPos(), hWnd, imc);
|
||||||
|
// Same height as system font so the composition window is
|
||||||
|
// positioned correctly vertically
|
||||||
|
LOGFONT lFont = {0};
|
||||||
|
lFont.lfHeight = font->getHeightPerLine();
|
||||||
|
lFont.lfCharSet = OEM_CHARSET;
|
||||||
|
ImmSetCompositionFont(imc, &lFont);
|
||||||
|
}
|
||||||
|
ImmReleaseContext(hWnd, imc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case WM_IME_COMPOSITION:
|
||||||
|
{
|
||||||
|
dev = getDeviceFromHWnd(hWnd);
|
||||||
|
if (!dev)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
irr::gui::IGUIEnvironment* env = dev->getGUIEnvironment();
|
||||||
|
if (!env)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
irr::gui::IGUIEditBox* box = dynamic_cast<irr::gui::IGUIEditBox*>(env->getFocus());
|
||||||
|
if (!box)
|
||||||
|
return 0;
|
||||||
|
bool get_comp_str = (lParam & GCS_COMPSTR) != 0;
|
||||||
|
bool get_result_str = (lParam & GCS_RESULTSTR) != 0;
|
||||||
|
if (get_comp_str || get_result_str)
|
||||||
|
{
|
||||||
|
HIMC imc = ImmGetContext(hWnd);
|
||||||
|
if (!imc)
|
||||||
|
return 0;
|
||||||
|
LONG vec_size = ImmGetCompositionString(imc, get_comp_str ? GCS_COMPSTR : GCS_RESULTSTR, (void*)NULL, 0);
|
||||||
|
if ((vec_size == IMM_ERROR_NODATA) ||
|
||||||
|
(vec_size == IMM_ERROR_GENERAL))
|
||||||
|
{
|
||||||
|
ImmReleaseContext(hWnd, imc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::vector<wchar_t> ct;
|
||||||
|
// NULL terminator
|
||||||
|
ct.resize(vec_size / sizeof(wchar_t) + 1, 0);
|
||||||
|
ImmGetCompositionString(imc, get_comp_str ? GCS_COMPSTR : GCS_RESULTSTR, ct.data(), vec_size);
|
||||||
|
std::u32string result = StringUtils::wideToUtf32(ct.data());
|
||||||
|
if (get_comp_str)
|
||||||
|
{
|
||||||
|
box->setComposingText(result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (char32_t c : result)
|
||||||
|
{
|
||||||
|
event.EventType = irr::EET_KEY_INPUT_EVENT;
|
||||||
|
event.KeyInput.PressedDown = true;
|
||||||
|
event.KeyInput.Char = (char32_t)c;
|
||||||
|
event.KeyInput.Key = irr::IRR_KEY_UNKNOWN;
|
||||||
|
event.KeyInput.Shift = false;
|
||||||
|
event.KeyInput.Control = false;
|
||||||
|
dev->postEventFromUser(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_result_str)
|
||||||
|
updateIMECompositonPosition(box->getICPos(), hWnd, imc);
|
||||||
|
ImmReleaseContext(hWnd, imc);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case WM_SYSKEYDOWN:
|
case WM_SYSKEYDOWN:
|
||||||
case WM_SYSKEYUP:
|
case WM_SYSKEYUP:
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
@ -1139,7 +1246,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
event.KeyInput.Control = 0;
|
event.KeyInput.Control = 0;
|
||||||
|
|
||||||
dev = getDeviceFromHWnd(hWnd);
|
dev = getDeviceFromHWnd(hWnd);
|
||||||
if (dev)
|
if (dev && !dev->isIMEComposingStarted())
|
||||||
{
|
{
|
||||||
if (conversionResult >= 1)
|
if (conversionResult >= 1)
|
||||||
{
|
{
|
||||||
@ -1248,6 +1355,7 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params)
|
|||||||
setDebugName("CIrrDeviceWin32");
|
setDebugName("CIrrDeviceWin32");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_ime_composing_started = false;
|
||||||
// get windows version and create OS operator
|
// get windows version and create OS operator
|
||||||
core::stringc winversion;
|
core::stringc winversion;
|
||||||
getWindowsVersion(winversion);
|
getWindowsVersion(winversion);
|
||||||
|
@ -388,6 +388,10 @@ namespace irr
|
|||||||
|
|
||||||
HWND getHandle() const { return HWnd; }
|
HWND getHandle() const { return HWnd; }
|
||||||
|
|
||||||
|
bool isIMEComposingStarted() const { return m_ime_composing_started; }
|
||||||
|
|
||||||
|
void setIMEComposingStarted(bool started) { m_ime_composing_started = started; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//! create the driver
|
//! create the driver
|
||||||
@ -400,6 +404,7 @@ namespace irr
|
|||||||
|
|
||||||
void resizeIfNecessary();
|
void resizeIfNecessary();
|
||||||
|
|
||||||
|
bool m_ime_composing_started;
|
||||||
HWND HWnd;
|
HWND HWnd;
|
||||||
|
|
||||||
bool ChangedToFullScreen;
|
bool ChangedToFullScreen;
|
||||||
|
@ -223,7 +223,7 @@ CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border,
|
|||||||
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateScrollPos();
|
m_scroll_pos = m_cursor_distance = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -242,6 +242,8 @@ CGUIEditBox::~CGUIEditBox()
|
|||||||
irr_driver->getDevice());
|
irr_driver->getDevice());
|
||||||
dl->setIMEEnable(false);
|
dl->setIMEEnable(false);
|
||||||
}
|
}
|
||||||
|
#elif defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
||||||
|
DestroyCaret();
|
||||||
#endif
|
#endif
|
||||||
if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard() &&
|
if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard() &&
|
||||||
irr_driver->getDevice()->hasOnScreenKeyboard())
|
irr_driver->getDevice()->hasOnScreenKeyboard())
|
||||||
@ -350,31 +352,33 @@ bool CGUIEditBox::OnEvent(const SEvent& event)
|
|||||||
MouseMarking = false;
|
MouseMarking = false;
|
||||||
setTextMarkers(0,0);
|
setTextMarkers(0,0);
|
||||||
}
|
}
|
||||||
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
#if defined(_IRR_COMPILE_WITH_X11_DEVICE_)
|
||||||
if (irr_driver->getDevice()->getType() == irr::EIDT_X11)
|
if (irr_driver->getDevice()->getType() == irr::EIDT_X11)
|
||||||
{
|
{
|
||||||
CIrrDeviceLinux* dl = dynamic_cast<CIrrDeviceLinux*>(
|
CIrrDeviceLinux* dl = dynamic_cast<CIrrDeviceLinux*>(
|
||||||
irr_driver->getDevice());
|
irr_driver->getDevice());
|
||||||
dl->setIMEEnable(false);
|
dl->setIMEEnable(false);
|
||||||
}
|
}
|
||||||
|
#elif defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
||||||
|
DestroyCaret();
|
||||||
#endif
|
#endif
|
||||||
m_from_android_edittext = false;
|
m_from_android_edittext = false;
|
||||||
m_composing_start = 0;
|
m_composing_start = 0;
|
||||||
m_composing_end = 0;
|
m_composing_end = 0;
|
||||||
|
m_composing_text.clear();
|
||||||
}
|
}
|
||||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
|
else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
|
||||||
{
|
{
|
||||||
m_mark_begin = m_mark_end = m_cursor_pos = getTextCount();
|
m_mark_begin = m_mark_end = m_cursor_pos = getTextCount();
|
||||||
updateCursorDistance();
|
|
||||||
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
||||||
if (irr_driver->getDevice()->getType() == irr::EIDT_X11)
|
if (irr_driver->getDevice()->getType() == irr::EIDT_X11)
|
||||||
{
|
{
|
||||||
CIrrDeviceLinux* dl = dynamic_cast<CIrrDeviceLinux*>(
|
CIrrDeviceLinux* dl = dynamic_cast<CIrrDeviceLinux*>(
|
||||||
irr_driver->getDevice());
|
irr_driver->getDevice());
|
||||||
dl->setIMEEnable(true);
|
dl->setIMEEnable(true);
|
||||||
dl->setIMELocation(calculateICPos());
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
calculateScrollPos();
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard() &&
|
if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard() &&
|
||||||
irr_driver->getDevice()->hasOnScreenKeyboard() &&
|
irr_driver->getDevice()->hasOnScreenKeyboard() &&
|
||||||
@ -392,6 +396,7 @@ bool CGUIEditBox::OnEvent(const SEvent& event)
|
|||||||
{
|
{
|
||||||
m_from_android_edittext = false;
|
m_from_android_edittext = false;
|
||||||
}
|
}
|
||||||
|
m_composing_text.clear();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EET_KEY_INPUT_EVENT:
|
case EET_KEY_INPUT_EVENT:
|
||||||
@ -862,17 +867,6 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! calculate the position of input composition window
|
|
||||||
core::position2di CGUIEditBox::calculateICPos()
|
|
||||||
{
|
|
||||||
core::position2di pos;
|
|
||||||
pos.X = CurrentTextRect.UpperLeftCorner.X + m_cursor_distance;
|
|
||||||
//bug? The text is always drawn in the height of the center. SetTextAlignment() doesn't influence.
|
|
||||||
pos.Y = AbsoluteRect.getCenter().Y + (Border ? 3 : 0);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! draws the element and its children
|
//! draws the element and its children
|
||||||
void CGUIEditBox::draw()
|
void CGUIEditBox::draw()
|
||||||
{
|
{
|
||||||
@ -880,7 +874,8 @@ void CGUIEditBox::draw()
|
|||||||
if (!IsVisible)
|
if (!IsVisible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
updateSurrogatePairText();
|
if (Environment->hasFocus(this))
|
||||||
|
updateSurrogatePairText();
|
||||||
GUIEngine::ScreenKeyboard* screen_kbd = GUIEngine::ScreenKeyboard::getCurrent();
|
GUIEngine::ScreenKeyboard* screen_kbd = GUIEngine::ScreenKeyboard::getCurrent();
|
||||||
bool has_screen_kbd = (screen_kbd && screen_kbd->getEditBox() == this);
|
bool has_screen_kbd = (screen_kbd && screen_kbd->getEditBox() == this);
|
||||||
|
|
||||||
@ -933,31 +928,60 @@ void CGUIEditBox::draw()
|
|||||||
const s32 realcbgn = m_composing_start < m_composing_end ? m_composing_start : m_composing_end;
|
const s32 realcbgn = m_composing_start < m_composing_end ? m_composing_start : m_composing_end;
|
||||||
const s32 realcend = m_composing_start < m_composing_end ? m_composing_end : m_composing_start;
|
const s32 realcend = m_composing_start < m_composing_end ? m_composing_end : m_composing_start;
|
||||||
|
|
||||||
for (unsigned i = 0; i < m_glyph_layouts.size(); i++)
|
|
||||||
{
|
|
||||||
GlyphLayout& glyph = m_glyph_layouts[i];
|
|
||||||
auto& cluster = glyph.cluster;
|
|
||||||
for (unsigned c = 0; c < glyph.cluster.size(); c++)
|
|
||||||
{
|
|
||||||
if (realmbgn != realmend)
|
|
||||||
{
|
|
||||||
if (cluster[c] >= realmbgn && cluster[c] < realmend)
|
|
||||||
glyph.draw_flags.at(c) = GLD_MARKED;
|
|
||||||
}
|
|
||||||
else if (!PasswordBox && realcbgn != realcend)
|
|
||||||
{
|
|
||||||
if (cluster[c] >= realcbgn && cluster[c] < realcend)
|
|
||||||
glyph.draw_flags.at(c) = GLD_COMPOSING;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
glyph.draw_flags.at(c) = GLD_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw the text layout
|
// draw the text layout
|
||||||
font->draw(m_glyph_layouts, CurrentTextRect,
|
if (!m_composing_text.empty())
|
||||||
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
|
{
|
||||||
false, true, &localClipRect);
|
std::vector<gui::GlyphLayout> ct;
|
||||||
|
std::u32string total = m_edit_text;
|
||||||
|
const s32 realcbgn = m_cursor_pos;
|
||||||
|
const s32 realcend = m_cursor_pos + (s32)m_composing_text.size();
|
||||||
|
total.insert(m_cursor_pos, m_composing_text);
|
||||||
|
font_manager->shape(total, ct);
|
||||||
|
for (unsigned i = 0; i < ct.size(); i++)
|
||||||
|
{
|
||||||
|
GlyphLayout& glyph = ct[i];
|
||||||
|
auto& cluster = glyph.cluster;
|
||||||
|
for (unsigned c = 0; c < glyph.cluster.size(); c++)
|
||||||
|
{
|
||||||
|
if (realcbgn != realcend)
|
||||||
|
{
|
||||||
|
if (cluster[c] >= realcbgn && cluster[c] < realcend)
|
||||||
|
glyph.draw_flags.at(c) = GLD_COMPOSING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glyph.draw_flags.at(c) = GLD_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
font->draw(ct, CurrentTextRect,
|
||||||
|
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
|
||||||
|
false, true, &localClipRect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < m_glyph_layouts.size(); i++)
|
||||||
|
{
|
||||||
|
GlyphLayout& glyph = m_glyph_layouts[i];
|
||||||
|
auto& cluster = glyph.cluster;
|
||||||
|
for (unsigned c = 0; c < glyph.cluster.size(); c++)
|
||||||
|
{
|
||||||
|
if (realmbgn != realmend)
|
||||||
|
{
|
||||||
|
if (cluster[c] >= realmbgn && cluster[c] < realmend)
|
||||||
|
glyph.draw_flags.at(c) = GLD_MARKED;
|
||||||
|
}
|
||||||
|
else if (!PasswordBox && realcbgn != realcend)
|
||||||
|
{
|
||||||
|
if (cluster[c] >= realcbgn && cluster[c] < realcend)
|
||||||
|
glyph.draw_flags.at(c) = GLD_COMPOSING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glyph.draw_flags.at(c) = GLD_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
font->draw(m_glyph_layouts, CurrentTextRect,
|
||||||
|
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
|
||||||
|
false, true, &localClipRect);
|
||||||
|
}
|
||||||
|
|
||||||
// Reset draw flags
|
// Reset draw flags
|
||||||
for (unsigned i = 0; i < m_glyph_layouts.size(); i++)
|
for (unsigned i = 0; i < m_glyph_layouts.size(); i++)
|
||||||
@ -1338,35 +1362,36 @@ void CGUIEditBox::calculateScrollPos()
|
|||||||
m_scroll_pos = 0;
|
m_scroll_pos = 0;
|
||||||
|
|
||||||
// todo: adjust scrollbar
|
// todo: adjust scrollbar
|
||||||
core::position2di pos = calculateICPos();
|
// calculate the position of input composition window
|
||||||
#if defined(_IRR_COMPILE_WITH_X11_DEVICE_)
|
#if defined(_IRR_COMPILE_WITH_X11_DEVICE_)
|
||||||
|
m_ic_pos.X = CurrentTextRect.UpperLeftCorner.X + m_cursor_distance;
|
||||||
|
// bug? The text is always drawn in the height of the center. SetTextAlignment() doesn't influence.
|
||||||
|
m_ic_pos.Y = AbsoluteRect.getCenter().Y + (Border ? 3 : 0);
|
||||||
if (irr_driver->getDevice()->getType() == irr::EIDT_X11)
|
if (irr_driver->getDevice()->getType() == irr::EIDT_X11)
|
||||||
{
|
{
|
||||||
CIrrDeviceLinux* dl = dynamic_cast<CIrrDeviceLinux*>(
|
CIrrDeviceLinux* dl = dynamic_cast<CIrrDeviceLinux*>(
|
||||||
irr_driver->getDevice());
|
irr_driver->getDevice());
|
||||||
if (dl)
|
if (dl)
|
||||||
{
|
{
|
||||||
dl->setIMELocation(pos);
|
dl->setIMELocation(m_ic_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
#elif defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
||||||
|
m_ic_pos.X = CurrentTextRect.UpperLeftCorner.X + m_cursor_distance;
|
||||||
|
m_ic_pos.Y = CurrentTextRect.UpperLeftCorner.Y;
|
||||||
|
|
||||||
|
// We need a native windows api caret for ime language chooser
|
||||||
|
// positioning, we always hide it though and draw with our own
|
||||||
|
// opengl caret later
|
||||||
CIrrDeviceWin32* win = NULL;
|
CIrrDeviceWin32* win = NULL;
|
||||||
if (irr_driver->getDevice()->getType() == irr::EIDT_WIN32)
|
if (irr_driver->getDevice()->getType() == irr::EIDT_WIN32)
|
||||||
win = dynamic_cast<CIrrDeviceWin32*>(irr_driver->getDevice());
|
win = dynamic_cast<CIrrDeviceWin32*>(irr_driver->getDevice());
|
||||||
if (!win)
|
if (!isVisible() || !win)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
COMPOSITIONFORM cf;
|
CreateCaret(win->getHandle(), NULL, 1, GUIEngine::getFontHeight());
|
||||||
HIMC hIMC = ImmGetContext(win->getHandle());
|
SetCaretPos(m_ic_pos.X, m_ic_pos.Y);
|
||||||
|
HideCaret(win->getHandle());
|
||||||
if (hIMC)
|
|
||||||
{
|
|
||||||
cf.dwStyle = CFS_POINT;
|
|
||||||
cf.ptCurrentPos.x = pos.X;
|
|
||||||
cf.ptCurrentPos.y = pos.Y - font->getHeightPerLine();
|
|
||||||
ImmSetCompositionWindow(hIMC, &cf);
|
|
||||||
ImmReleaseContext(win->getHandle(), hIMC);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SERVER_ONLY
|
#endif // SERVER_ONLY
|
||||||
|
@ -133,6 +133,9 @@ namespace GUIEngine
|
|||||||
s32 getCursorPosInBox() const { return m_cursor_pos; }
|
s32 getCursorPosInBox() const { return m_cursor_pos; }
|
||||||
s32 getTextCount() const { return (s32)m_edit_text.size(); }
|
s32 getTextCount() const { return (s32)m_edit_text.size(); }
|
||||||
void setTextBoxType(GUIEngine::TextBoxType t) { m_type = t; }
|
void setTextBoxType(GUIEngine::TextBoxType t) { m_type = t; }
|
||||||
|
virtual void setComposingText(const std::u32string& ct) { m_composing_text = ct; }
|
||||||
|
virtual void clearComposingText() { m_composing_text.clear(); }
|
||||||
|
virtual const core::position2di& getICPos() const { return m_ic_pos; }
|
||||||
protected:
|
protected:
|
||||||
//! sets the area of the given line
|
//! sets the area of the given line
|
||||||
void setTextRect(s32 line);
|
void setTextRect(s32 line);
|
||||||
@ -147,8 +150,6 @@ namespace GUIEngine
|
|||||||
void updateCursorDistance();
|
void updateCursorDistance();
|
||||||
bool processKey(const SEvent& event);
|
bool processKey(const SEvent& event);
|
||||||
bool processMouse(const SEvent& event);
|
bool processMouse(const SEvent& event);
|
||||||
//! calculates the input composition position
|
|
||||||
core::position2di calculateICPos();
|
|
||||||
s32 getCursorPos(s32 x, s32 y);
|
s32 getCursorPos(s32 x, s32 y);
|
||||||
void updateGlyphLayouts();
|
void updateGlyphLayouts();
|
||||||
|
|
||||||
@ -186,9 +187,13 @@ namespace GUIEngine
|
|||||||
/* UTF32 string for shaping and editing to avoid wchar_t issue in
|
/* UTF32 string for shaping and editing to avoid wchar_t issue in
|
||||||
* windows */
|
* windows */
|
||||||
std::u32string m_edit_text;
|
std::u32string m_edit_text;
|
||||||
|
/* Used in windows api for native composing text handling. */
|
||||||
|
std::u32string m_composing_text;
|
||||||
std::vector<GlyphLayout> m_glyph_layouts;
|
std::vector<GlyphLayout> m_glyph_layouts;
|
||||||
// Pre-edit surrogate chars
|
// Pre-edit surrogate chars
|
||||||
std::vector<wchar_t> m_surrogate_chars;
|
std::vector<wchar_t> m_surrogate_chars;
|
||||||
|
// Position to show composition box in native window (linux / windows)
|
||||||
|
core::position2di m_ic_pos;
|
||||||
void correctCursor(s32& cursor_pos, bool left);
|
void correctCursor(s32& cursor_pos, bool left);
|
||||||
void updateSurrogatePairText();
|
void updateSurrogatePairText();
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user