Comments (9)
If it renders these rectangles then it means that the characters aren't part of the font. TGUI uses DejaVuSans by default, which indeed doesn't support CJK.
You will need to call tgui::Font::setGlobalFont("filename.ttf")
at the beginning of the program (after creating the Gui) with a font file that can display Chinese characters.
from tgui.
Thanks very much.
Is it necessary to set the default font to one that supports CJK?
If not, I'll close the Issue.
from tgui.
By the way.
The input method prompt box of the CJK does not follow the input cursor.
This is the key code:
if (HIMC himc = ImmGetContext(win->hwnd))
{
COMPOSITIONFORM comp = {};
comp.ptCurrentPos.x = x;
comp.ptCurrentPos.y = y;
comp.dwStyle = CFS_FORCE_POSITION;
ImmSetCompositionWindow(himc, &comp);
CANDIDATEFORM cand = {};
cand.dwStyle = CFS_CANDIDATEPOS;
cand.ptCurrentPos.x = x;
cand.ptCurrentPos.y = y;
ImmSetCandidateWindow(himc, &cand);
ImmReleaseContext(win->hwnd, himc);
}
from tgui.
Is it necessary to set the default font to one that supports CJK?
The font used by the edit box needs to support CJK to display the characters. I assumed you wanted to use Chinese characters in the entire application so I suggested changing the global font so that all widgets would use that font, but you can also change the font of only the edit box like this:
tgui::Font font("path/to/simhei.ttf");
editBox->getRenderer()->setFont(font);
The input method prompt box of the CJK does not follow the input cursor.
I've never used an IMM/IME so I'm not familiar with how it should work. TGUI doesn't do anything special with IME, it doesn't even know it exists. So unless you tell the IME yourself, it has no idea where on the screen the TGUI edit box is located.
I know that SDL has a SDL_SetTextInputRect function that probably positions the IME next to the edit box, but TGUI currently only calls that function on Android and iOS to get a virtual keyboard. Maybe I could call that on desktops as well when using the SDL backend. SFML on the other hand has no such function available to my knowledge, so there isn't much that I can do to improve the default behavior in the SFML_GRAPHICS backend.
Is the code you showed with ImmGetContext
something that you have in your own code? If so, can't you position the IME window yourself so that it appears below the edit box? Getting the exact location of the cursor would be a bit more complex, but it could be done if you really need it and aren't satisfied with just having the IME window at a fixed location next to the edit box.
from tgui.
I looked into this a little bit further, I guess you want the ImmSetCompositionWindow and ImmSetCandidateWindow functions to be called by TGUI when the caret of the edit box moves?
One question I still have is who is in charge of showing and hiding the IME window? If I don't show or hide the window and only move it around, then the window might be in the way of other content when you are done typing. So should the gui also be responsible for hiding the window when the edit box is unfocused (and showing the window when it gains focus again)? Or do you want control over when the IME window is shown in your own code?
from tgui.
Thanks for reply.
I guess you want the ImmSetCompositionWindow and ImmSetCandidateWindow functions to be called by TGUI when the caret of the edit box moves?
Yes.
Who is in charge of showing and hiding the IME window?
I think the operating system does the job.
Here's some of the code I found:
Here's how GTK solves this problem:
https://gitlab.gnome.org/GNOME/gtk/-/blob/main/gtk/gtkimcontextime.c
case WM_IME_STARTCOMPOSITION:
context_ime->preediting = TRUE;
gtk_im_context_ime_set_cursor_location (context, NULL);
g_signal_emit_by_name (context, "preedit-start");
if (context_ime->use_preedit)
retval = GDK_WIN32_MESSAGE_FILTER_REMOVE;
break;
case WM_IME_ENDCOMPOSITION:
context_ime->preediting = FALSE;
g_signal_emit_by_name (context, "preedit-changed");
g_signal_emit_by_name (context, "preedit-end");
if (context_ime->use_preedit)
retval = GDK_WIN32_MESSAGE_FILTER_REMOVE;
break;
case WM_IME_NOTIFY:
switch (msg->wParam)
{
case IMN_SETOPENSTATUS:
context_ime->opened = ImmGetOpenStatus (himc);
gtk_im_context_ime_set_preedit_font (context);
break;
default:
break;
}
break;
And FLTK did this:
https://github.com/fltk/fltk/blob/5f189aa2139da497de03b2dfc157dbffd176a27c/src/Fl_win32.cxx
static void get_imm_module() {
s_imm_module = LoadLibrary("IMM32.DLL");
if (!s_imm_module)
Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
"Please check your input method manager library accessibility.");
flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx");
flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
}
void Fl_WinAPI_Screen_Driver::set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win)
{
if (!win) return;
Fl_Window* tw = win->top_window();
if (!tw->shown())
return;
HIMC himc = flImmGetContext(fl_xid(tw));
if (himc) {
COMPOSITIONFORM cfs;
float s = Fl_Graphics_Driver::default_driver().scale();
cfs.dwStyle = CFS_POINT;
cfs.ptCurrentPos.x = int(X * s);
cfs.ptCurrentPos.y = int(Y * s) - int(tw->labelsize() * s);
// Attempt to have temporary text entered by input method use scaled font.
// Does good, but still not always effective.
Fl_GDI_Font_Descriptor *desc = (Fl_GDI_Font_Descriptor*)Fl_Graphics_Driver::default_driver().font_descriptor();
if (desc) SelectObject((HDC)Fl_Graphics_Driver::default_driver().gc(), desc->fid);
MapWindowPoints(fl_xid(win), fl_xid(tw), &cfs.ptCurrentPos, 1);
flImmSetCompositionWindow(himc, &cfs);
flImmReleaseContext(fl_xid(tw), himc);
}
}
And RmlUi did this:(I'm involved in this PR)
mikke89/RmlUi@89a357b
#ifdef _MSC_VER
#pragma comment(lib, "imm32")
#endif
void SystemInterface_Win32::ActivateKeyboard(Rml::Vector2f caret_position, float /*line_height*/)
{
// Adjust the position of the input method editor (IME) to the caret.
if (HIMC himc = ImmGetContext(window_handle))
{
COMPOSITIONFORM comp = {};
comp.ptCurrentPos.x = (LONG)caret_position.x;
comp.ptCurrentPos.y = (LONG)caret_position.y;
comp.dwStyle = CFS_FORCE_POSITION;
ImmSetCompositionWindow(himc, &comp);
CANDIDATEFORM cand = {};
cand.dwStyle = CFS_CANDIDATEPOS;
cand.ptCurrentPos.x = (LONG)caret_position.x;
cand.ptCurrentPos.y = (LONG)caret_position.y;
ImmSetCandidateWindow(himc, &cand);
ImmReleaseContext(window_handle, himc);
}
}
void WidgetTextInput::SetKeyboardActive(bool active)
{
if (SystemInterface* system = GetSystemInterface())
{
if (active)
{
// Activate the keyboard and submit the cursor position and line height to enable clients to adjust the input method editor (IME). Note
// that the cursor is extended by one pixel along the top and bottom, we reverse this extension here.
const Vector2f element_offset = parent->GetAbsoluteOffset() - scroll_offset;
const Vector2f absolute_cursor_position = element_offset + cursor_position + Vector2f(0, 1);
const float line_height = cursor_size.y - 2.f;
system->ActivateKeyboard(absolute_cursor_position, line_height);
}
else
{
system->DeactivateKeyboard();
}
}
}
Here are some of the information provided by Microsoft.
(I'm not familiar with Mac OS and Linux)
Using an Input Method Editor in a Game
Input Method Editor (IME) requirements
Example: Getting WMI Data from the Local Computer
from tgui.
Thanks for the information. I will look into this more in the next few days, I expect to have something working this weekend.
I'm still a bit confused about what to do on focus and unfocus. GTK and RmlUi don't seem to do anything special, but FLTK calls ImmAssociateContextEx and SDL calls ImmAssociateContext. Do you know what the effect would be of calling ImmAssociateContextEx(hwnd, 0, IACE_DEFAULT);
when the edit box is focused and ImmAssociateContextEx(hwnd, 0, 0);
on unfocus, like FLTK is doing? Would that be a good thing to do or should TGUI only call ImmSetCompositionWindow and ImmSetCandidateWindow?
I'm probably going to call the SDL functions when TGUI is built with the SDL backend (as SDL also has implementations for macOS and Linux), and fall back to calling ImmSetCompositionWindow and ImmSetCandidateWindow myself and only supporting Windows when SFML is used.
from tgui.
The IME candidate list will now follow the text cursor on Windows.
I won't bother with implementing this for Linux or macOS until there is someone that actually needs it there.
I saw no effect from calling ImmSetCandidateWindow in any of my tests, so I'm only using ImmSetCompositionWindow.
from tgui.
Sorry for late reply.
I'm on a vacation and can't focus on this issue.
from tgui.
Related Issues (20)
- Autocomplete support for EditBox HOT 2
- Black background shown when changing window size HOT 4
- How to customize the window's title bar and frame HOT 2
- How to implement a polygon window HOT 2
- Hover style does not disappear when mouse moves out of the window HOT 6
- Add a 2d chart or rendering 3d data for TGUI? HOT 1
- Chinese support? HOT 5
- Focus Issues HOT 1
- [ANNOUNCE] The TGUI now distributed via MSYS2 on Windows HOT 1
- CMake fails to install pkg-config files HOT 2
- On macOS, Input Method Editors(IME) behavior seems incorrect. HOT 6
- How to use SDL2/3 backend with cmake `FetchContent` HOT 2
- [Question] How to compile my first example of TGUI ? HOT 13
- [Bug] Dead radio button text HOT 3
- [Bug] Tabs state after disabled tab click HOT 2
- FileDialog documentation needs clarification and maybe working examples HOT 4
- Is there a C binding? HOT 12
- Raylib backend? HOT 15
- Cannot delete widgets inside of the gui-builder HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tgui.