Skip to content

[win] Support CJK input method manager (IMM)#147

Merged
dacap merged 3 commits into
aseprite:mainfrom
Cerallin:feat/CJK-input-support
Jul 9, 2025
Merged

[win] Support CJK input method manager (IMM)#147
dacap merged 3 commits into
aseprite:mainfrom
Cerallin:feat/CJK-input-support

Conversation

@Cerallin

@Cerallin Cerallin commented Jun 12, 2025

Copy link
Copy Markdown
Contributor
  • Add CMake option LAF_WITH_IME, default off, for Windows only
  • Call translateMessage() when WM_KEYDOWN and if it is a virtual key
  • Refactored setTranslateDeadKey() to setTextInput() for IME form positioning

The code about TranslateMessage() still needs discussion. Am I doing right?
And I would like to know if there is a good way to get the caret position, which is used for IME positioning.

I agree that my contributions are licensed under the MIT License.
You can find a copy of this license at https://opensource.org/licenses/MIT

Ref: aseprite/aseprite#1767

@Cerallin Cerallin force-pushed the feat/CJK-input-support branch 3 times, most recently from b174bd8 to 3c666dd Compare June 12, 2025 09:06
@Cerallin Cerallin changed the title [win] Add IMM support [win] Support CJK input method manager (IMM) Jun 12, 2025
@dacap dacap self-assigned this Jun 13, 2025

@dacap dacap left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good first draft, but we need to work in the API. I'll make another comment about this later.

Comment thread CMakeLists.txt Outdated
Comment thread os/win/event_queue.cpp Outdated
Comment thread os/win/window.cpp Outdated
@dacap

dacap commented Jun 13, 2025

Copy link
Copy Markdown
Member

The os::System::setTranslateDeadKeys() function is used by Aseprite to indicate when we are inside a input field. For example, if we are outside a input field, setTranslateDeadKeys(false) is called, so dead keys are not received, we need only keyboard shortcuts as they are. When we focus a text input field, then setTranslateDeadKeys(true) is called to start receiving dead keys/special unicode chars.

There is a comment in this member function:

laf/os/system.h

Lines 196 to 202 in e04e7c5

// Indicates if you want to use dead keys or not. By default it's
// false, which behaves as regular shortcuts. You should set this
// to true when you're inside a text field in your app.
//
// TODO Improve this API using different input modes,
// e.g. GameLike, TextInput, TextInputWithDeadKeys
virtual void setTranslateDeadKeys(bool state) = 0;

Probably we could just refactor setTranslateDeadKeys() to something like:

class System {
...
  virtual void setTextInput(bool state, const gfx::Point& screenCaretPos = {}) = 0;
...
};

@Cerallin Cerallin force-pushed the feat/CJK-input-support branch 3 times, most recently from 72f71ad to 88dd3d9 Compare June 13, 2025 13:34
@Cerallin

Copy link
Copy Markdown
Contributor Author

@dacap It seems much easier than I thought to check if user is inputting with IME. Please have a look:
https://learn.microsoft.com/en-us/windows/win32/learnwin32/keyboard-input
https://learn.microsoft.com/en-us/windows/win32/api/imm/nf-imm-immgetvirtualkey

The key point is to handle messages with virtual key value of VK_PROCESSKEY. Should I still work on exposing an API to indicate if we are inside an input field or not?

@dacap

dacap commented Jun 13, 2025

Copy link
Copy Markdown
Member

Should I still work on exposing an API to indicate if we are inside an input field or not?

I think the main thing is that the app (not laf) is the only one that can tell us if we are inside a text field or not, which means what we should do with this VK_PROCESSKEY. For example, if we are not in a text field, we should ignore VK_PROCESSKEY.

@Cerallin Cerallin force-pushed the feat/CJK-input-support branch 2 times, most recently from 51ad3c5 to 1af03b2 Compare June 14, 2025 03:19
@Cerallin Cerallin requested a review from dacap June 14, 2025 03:57
@Cerallin Cerallin force-pushed the feat/CJK-input-support branch from 1af03b2 to 44b9ed9 Compare June 14, 2025 04:52
Cerallin added 2 commits June 14, 2025 14:20
* Rename setTranslateDeadKeys() to setTextInput().
* Add a param screenCaretPos for further use in CJK input support.

This function now is to indicate when we are inside a input field, and
set caret position for IME positioning.
This option is default off and now for Windows only. Also adds
m_isTextInputMode field to os::EventQueueWin. It will also be set in
WindowWin::setTextInput().
@Cerallin Cerallin force-pushed the feat/CJK-input-support branch 2 times, most recently from b08c253 to 9eabe2e Compare June 14, 2025 12:44
It handles IME state (in a text field or not) and composition form
positioning.
@Cerallin

Cerallin commented Jul 3, 2025

Copy link
Copy Markdown
Contributor Author

@dacap I’ve finished making the requested changes. Please take a look whenever it’s convenient.

@dacap

dacap commented Jul 9, 2025

Copy link
Copy Markdown
Member

Thanks a lot for this PR @Cerallin, so far it's a good starting point to integrate in laf. I'll merge as it is and make some minor adjustments and more testing in a near future. I think we could start compiling some beta version of Aseprite with LAF_WITH_IME=ON in a near future.

@dacap dacap merged commit 1ce7fc5 into aseprite:main Jul 9, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants