Page MenuHome

Cleanup: Check for IME key events using window messages
Needs ReviewPublic

Authored by Yuki Hashimoto (hzuika) on Mar 17 2022, 12:22 PM.

Details

Summary

Instead of checking the key events processed by the IME for each character in each language, it checks whether a WM_CHAR message or a WM_IME_COMPOSITION message is sent.

Previously, each character was checked to distinguish between characters that are processed by IME and those that are not. However, it may be difficult to respond to changes (Each time a similar problem occurs, the code must be rewritten. D11929 D13771 D14354).

After the WM_INPUT message is sent, if the character is to be processed by the IME, WM_IME_STARTCOMPOSITION, WM_IME_COMPOSITION or WM_IME_ENDCOMPOSITION message is sent. However, if the character is not processed by the IME, WM_CHAR message is sent.
Since it is difficult to distinguish between the two cases in the WM_INPUT message, the event is temporarily stored when WM_INPUT message is sent, and then processed when the WM_CHAR message is sent, or deleted when the WM_IME_*COMPOSITION message is sent.
However, some control characters do not send either message, so functions are needed to check for them.


Test

  • Japanese (Alphabet, Numbers(keyboards, numpads), Symbols(keyboards, numpads), Arrow, Home/End, Delete, Tab, Space, Backspace, Enter)

Diff Detail

Repository
rB Blender
Branch
win_ime_wm_char (branched from master)
Build Status
Buildable 21084
Build 21084: arc lint + arc unit

Event Timeline

Yuki Hashimoto (hzuika) requested review of this revision.Mar 17 2022, 12:22 PM
Yuki Hashimoto (hzuika) created this revision.

I need to test if this works for all patterns (each characters, each CJK languages).

Yuki Hashimoto (hzuika) removed rB Blender as the repository for this revision.

When the arrow keys, Home/End key, Delete key, etc. are pressed, the WM_CHAR message is not posted, so the event created by the WM_INPUT message is used.

Characters to be ignored are as follows

GHOST_kKeyLeftArrow,
GHOST_kKeyRightArrow,
GHOST_kKeyUpArrow,
GHOST_kKeyDownArrow,

GHOST_kKeyPrintScreen,
GHOST_kKeyPause,

GHOST_kKeyInsert,
GHOST_kKeyDelete,
GHOST_kKeyHome,
GHOST_kKeyEnd,
GHOST_kKeyUpPage,
GHOST_kKeyDownPage,

Updated to the current state of master.

Yuki Hashimoto (hzuika) updated this revision to Diff 49509.EditedMar 22 2022, 3:38 AM
  • Cleanup code
    • Create function
    • Rename variable
    • Edit comment
  • Add delete statement
  • Fix selection (Shift + arrow key)

Characters for checks ime key event are

GHOST_kKeyLeftShift = 0x100,
GHOST_kKeyRightShift,
GHOST_kKeyLeftControl,
GHOST_kKeyRightControl,
GHOST_kKeyLeftAlt,
GHOST_kKeyRightAlt,
GHOST_kKeyOS,     /* Command key on Apple, Windows key(s) on Windows. */
GHOST_kKeyGrLess, /* German PC only! */
GHOST_kKeyApp,    /* Also known as menu key. */

GHOST_kKeyCapsLock,
GHOST_kKeyNumLock,
GHOST_kKeyScrollLock,

GHOST_kKeyLeftArrow,
GHOST_kKeyRightArrow,
GHOST_kKeyUpArrow,
GHOST_kKeyDownArrow,

GHOST_kKeyPrintScreen,
GHOST_kKeyPause,

GHOST_kKeyInsert,
GHOST_kKeyDelete,
GHOST_kKeyHome,
GHOST_kKeyEnd,
GHOST_kKeyUpPage,
GHOST_kKeyDownPage,
Yuki Hashimoto (hzuika) edited the summary of this revision. (Show Details)Mar 22 2022, 4:12 AM
Yuki Hashimoto (hzuika) edited the summary of this revision. (Show Details)Mar 22 2022, 4:14 AM
Yuki Hashimoto (hzuika) edited the summary of this revision. (Show Details)Mar 22 2022, 4:37 AM
Yuki Hashimoto (hzuika) edited the summary of this revision. (Show Details)Mar 22 2022, 4:40 AM
Yuki Hashimoto (hzuika) retitled this revision from WIP: Cleanup: IME handling on Windows. to Cleanup: Check for IME key events using window messages.Mar 22 2022, 6:33 AM
Yuki Hashimoto (hzuika) edited the summary of this revision. (Show Details)Mar 22 2022, 6:55 AM

Hi @Yuki Hashimoto (hzuika).

I need some explain.
Would you explain below, please?

  1. Is it your patch's summary below, ok? (It is my understanding.)
/* When the IME is enabled, input events are superseded by WM_IME_STARTCOMPOSITION or
         * WM_IME_COMPOSITION messages. Therefore, NULL is returned here. However, some keys are
         * not handled by IME, so they are temporarily stored (ImeNotHandledEventCandidate) and
         * used when WM_CHAR message is posted.
*/


- ImeNotHandledEventCandidate (GHOST doesn't not need to pass these keys to IME. i.e. not character keys.)
  - GHOST_kKeyLeftShift = 0x100,
  - GHOST_kKeyRightShift,
  - GHOST_kKeyLeftControl,
  - GHOST_kKeyRightControl,
  - GHOST_kKeyLeftAlt,
  - GHOST_kKeyRightAlt,
  - GHOST_kKeyOS,     /* Command key on Apple, Windows key(s) on Windows. */
  - GHOST_kKeyGrLess, /* German PC only! */
  - GHOST_kKeyApp,    /* Also known as menu key. */

  - GHOST_kKeyCapsLock,
  - GHOST_kKeyNumLock,
  - GHOST_kKeyScrollLock,

  - GHOST_kKeyLeftArrow,
  - GHOST_kKeyRightArrow,
  - GHOST_kKeyUpArrow,
  - GHOST_kKeyDownArrow,

  - GHOST_kKeyPrintScreen,
  - GHOST_kKeyPause,

  - GHOST_kKeyInsert,
  - GHOST_kKeyDelete,
  - GHOST_kKeyHome,
  - GHOST_kKeyEnd,
  - GHOST_kKeyUpPage,
  - GHOST_kKeyDownPage,
  1. About the timing of input event flow and new IME's event behavior.

In past, you explain about the flow of processing input and new IME's event flow. (https://developer.blender.org/D11929#308878).
This patch uses WM_IME_STARTCOMPOSITION, but isn't it problem about the timing in this case of this patch?

Function to return true for keys that send WM_CHAR or WM_IME_*COMPOSITION messages.

@Takahiro Shizuki (sntulix)

Thank you for your comment.
I apologize for the lack of explanation.
I try to write a detailed explanation.

Hi @Takahiro Shizuki (sntulix) . If the explanation below is difficult to understand, please ask.

1

ImeNotHandledEventCandidate (GHOST doesn't not need to pass these keys to IME. i.e. not character keys.)

Sorry, the name of ImeNotHandledEventCandidate() may be misleading.
ImeNotHandledEventCandidate() returns true when the key is all drawable characters(alphabet, symbols, numbers) and some control keys(Enter, Backspace, Tab, Etc)
These keys sent WM_CHAR message or WM_IME_*COMPOSITION messages.
ImeNotHandledEventCandidate() returns false when the key is a control key(Ex: F1, Arrow, Delete, Home, End, Shift, Control) without above.
These keys do not sent WM_CHAR message and WM_IME_*COMPOSITION messages (only WM_INPUT messages).


2

I explained like this, but this has mistakes.

Press any key when IME turns on

WM_INPUT
The character is processed by IME? →No Add GHOST_kEventKeyDown Event
↓Yes
WM_IME_STARTCOMPOSITION
(Remove GHOST_kEventKeyDown Event)

WM_IME_COMPOSITION
Add GHOST_kEventImeComposition Event

Process GHOST_kEventImeComposition Event


Current approach

Press any key when IME turns on

WM_INPUT
The character is processed by IME? →No (Return GHOST_kEventKeyDown Event)
↓Yes (Return NULL)
WM_IME_STARTCOMPOSITION
(Return GHOST_kEventImeCompositionStart Event)

WM_IME_COMPOSITION
(Return GHOST_kEventImeComposition Event)


This patch suggest the following approach.

Press any key when IME turns on

WM_INPUT
The character is control key (= does not sent messages bellow)? → Yes (Return GHOST_kEventKeyDown Event).
↓No (Return NULL)
1 WM_CHAR (Return original GHOST_kEventKeyDown Event)
2 WM_IME_STARTCOMPOSITION (Return GHOST_kEventImeCompositionStart Event)

WM_IME_COMPOSITION (Return GHOST_kEventImeComposition Event)

This patch is an attempt to improve IsImeKeyEvent, which is becoming more complicated, by using WM_CHAR.

These are simple reference figures.

Current approach.

This patch.
The number of steps is increased, and the complexity of IsImeKeyEvent () is reduced.

Hi, @Yuki Hashimoto (hzuika)
Thank you for your detail writing for my easy understanding.
Excuse me, I appended in your image.

Note:

  • WM_INPUT message
    • Sent to the window that is getting raw input.
  • WM_CHAR message
    • Posted to the window with the keyboard focus when a WM_KEYDOWN message is translated by the TranslateMessage function. The WM_CHAR message contains the character code of the key that was pressed.
  • WM_IME_STARTCOMPOSITION message
    • Sent immediately before the IME generates the composition string as a result of a keystroke. A window receives this message through its WindowProc function.
  • IsImeKeyEventCandidate()
    • GHOST_ImeWin32::IsImeKeyEventCandidate()
  • ImeNotHandledEventCandidate
    • GHOST_Event *ImeNotHandledEventCandidate;

For me, if "ImeNotHandledEventCandidate" rename to "evt_ImeNotHandledEventCandidate", I understand more easily.

Rename ImeNotHandledEventCandidate to evt_ImeNotHandledEventCandidate
Thank you @Takahiro Shizuki (sntulix).

Hi. @Harley Acheson (harley) @Yuki Hashimoto (hzuika)

I think this will make refine to avoid sensitive with a pattern of the languages.
Though, by GHOST_ImeWin32::IsImeKeyEventCandidate()'s code got simple, I can't see it what do from the code.

bool GHOST_ImeWin32::IsImeKeyEventCandidate(bool keyDown, GHOST_TKey key)
{
  if (!(IsEnglishMode()) && !(GHOST_kKeyLeftShift <= key && key <= GHOST_kKeyDownPage) && keyDown) {
    return true;
  }
  return false;
}

How about renaming IsImeKeyEventCandidate() to IsImeKeyEventCandidateToForward() for finding easily that it is a check method whether it is forward to ime?

bool GHOST_ImeWin32:: IsImeKeyEventCandidateToForward(bool keyDown, GHOST_TKey key)
{
  if (!(IsEnglishMode()) && !(GHOST_kKeyLeftShift <= key && key <= GHOST_kKeyDownPage) && keyDown) {
    return true;
  }
  return false;
}

Or, How about write the comment below at declaration of the method ( GHOST_ImeWin32.h:146 ) at the define ( GHOST_ImeWin32.cpp:82 ) too?

/* Checks a key whether IME has to do handling. */
bool IsImeKeyEventCandidate(bool keyDown, GHOST_TKey key);
/* Checks a key whether IME has to do handling. */
bool GHOST_ImeWin32::IsImeKeyEventCandidate(bool keyDown, GHOST_TKey key)
{
  if (!(IsEnglishMode()) && !(GHOST_kKeyLeftShift <= key && key <= GHOST_kKeyDownPage) && keyDown) {
    return true;
  }
  return false;
}

Rename IsImeKeyEventCandidate to IsImeKeyEventCandidateToForward
IsImeKeyEventCandidateToForward method returns true for all characters transferred to IME for the sake of clarity.

Yuki Hashimoto (hzuika) planned changes to this revision.Mar 29 2022, 12:43 PM

If you press and hold BackSpace while IME is enabled, Unhandled exception thrown: read access violation. occur in Debug Build.

Fix access violation.