From 3666805a755b11b8cdc4f973daf034243c225cb7 Mon Sep 17 00:00:00 2001 From: Daijiro Fukuda Date: Thu, 15 Dec 2022 15:24:42 +0900 Subject: [PATCH] Support preedit candidate Support the GLFW preedit candidate feature. This feature supports only Win32 currently. We can use this feature by enabling `FLAG_MANAGE_PREEDIT_CANDIDATE` flag on Win32. --- src/raylib.h | 11 +++++++++++ src/rcore.c | 26 +++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 86710ced3d52..538e86d55acb 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -503,6 +503,7 @@ typedef struct FilePathList { typedef enum { FLAG_VSYNC_HINT = 0x00000040, // Set to try enabling V-Sync on GPU FLAG_FULLSCREEN_MODE = 0x00000002, // Set to run program in fullscreen + FLAG_MANAGE_PREEDIT_CANDIDATE = 0x00020000, // Set to manage the drawing of preedit candidates by the application side FLAG_WINDOW_RESIZABLE = 0x00000004, // Set to allow resizable window FLAG_WINDOW_UNDECORATED = 0x00000008, // Set to disable window decoration (frame and buttons) FLAG_WINDOW_HIDDEN = 0x00000080, // Set to hide window @@ -1092,6 +1093,7 @@ RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ + // Callback for preedit text. // preeditLength: The length of preedit text // preeditString: The preedit text (unicode) @@ -1101,6 +1103,13 @@ RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize // caret: The index of the caret in preeditString typedef void (*PreeditCallback)(int preeditLength, int *preeditString, int blockCount, int *blockSizes, int focusedBlock, int caret); +// Callback for preedit candidate, which is called only when `FLAG_MANAGE_PREEDIT_CANDIDATE` ConfigFlag is enabled on Win32 +// candidatesCount: The number of all preedit candidates +// selectedIndex: The index of the currently selected candidate in the all candidates +// pageStart: The index of the first candidate on the current displaying page +// pageSize: The number of the candidates on the current displaying page +typedef void (*PreeditCandidateCallback)(int candidatesCount, int selectedIndex, int pageStart, int pageSize); + // Input-related functions: keyboard RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once RLAPI bool IsKeyDown(int key); // Check if a key is being pressed @@ -1115,6 +1124,8 @@ RLAPI void GetPreeditCursorRectangle(int *x, int *y, int *w, int *h); // Get the RLAPI bool IsImeOn(void); // Check if IME is ON RLAPI void SetImeStatus(bool on); // Set IME status RLAPI void ResetPreedit(void); // Reset preedit text +RLAPI void SetPreeditCandidateCallback(PreeditCandidateCallback callback); // Set a callback for preedit candidates +RLAPI int *GetPreeditCandidate(int index, int *textCount); // Get the text of the preedie candidate. This can be used only when `FLAG_MANAGE_PREEDIT_CANDIDATE` ConfigFlag is enabled on Win32 // Input-related functions: gamepads RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available diff --git a/src/rcore.c b/src/rcore.c index fad365000a7b..cdd0d6fccb0a 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -438,7 +438,8 @@ typedef struct CoreData { int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode) int charPressedQueueCount; // Input characters queue count - PreeditCallback preeditCallback; // Preedit callback + PreeditCallback preeditCallback; // Preedit callback + PreeditCandidateCallback preeditCandidateCallback; // Preedit candidate callback #if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) int defaultMode; // Default keyboard mode @@ -642,6 +643,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value) static void PreeditCallbackInner(GLFWwindow *window, int preeditLength, unsigned int *preeditString, int blockCount, int *blockSizes, int focusedBlock, int caret); // GLFW3 Preedit Callback +static void PreeditCandidateCallbackInner(GLFWwindow *window, int candidatesCount, int selectedIndex, int pageStart, int pageSize); // GLFW3 Preedit Candidate Callback static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel @@ -3590,6 +3592,18 @@ void ResetPreedit(void) glfwResetPreeditText(CORE.Window.handle); } +// Set a callback for preedit candidate +void SetPreeditCandidateCallback(PreeditCandidateCallback callback) +{ + CORE.Input.Keyboard.preeditCandidateCallback = callback; +} + +// Get the text of the preedie candidate +int *GetPreeditCandidate(int index, int *textCount) +{ + return (int *)glfwGetPreeditCandidate(CORE.Window.handle, index, textCount); +} + // Set a custom key to exit program // NOTE: default exitKey is ESCAPE void SetExitKey(int key) @@ -3956,6 +3970,9 @@ static bool InitGraphicsDevice(int width, int height) glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE); #endif + if ((CORE.Window.flags & FLAG_MANAGE_PREEDIT_CANDIDATE) > 0) glfwInitHint(GLFW_MANAGE_PREEDIT_CANDIDATE, GLFW_TRUE); // Manage the drawing of preedit candidates. + else glfwInitHint(GLFW_MANAGE_PREEDIT_CANDIDATE, GLFW_FALSE); // Leave the drawing of preedit candidates to the IME + if (!glfwInit()) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); @@ -4187,6 +4204,7 @@ static bool InitGraphicsDevice(int width, int height) glfwSetKeyCallback(CORE.Window.handle, KeyCallback); glfwSetCharCallback(CORE.Window.handle, CharCallback); glfwSetPreeditCallback(CORE.Window.handle, PreeditCallbackInner); + glfwSetPreeditCandidateCallback(CORE.Window.handle, PreeditCandidateCallbackInner); glfwSetMouseButtonCallback(CORE.Window.handle, MouseButtonCallback); glfwSetCursorPosCallback(CORE.Window.handle, MouseCursorPosCallback); // Track mouse position changes glfwSetScrollCallback(CORE.Window.handle, MouseScrollCallback); @@ -5433,6 +5451,12 @@ static void PreeditCallbackInner(GLFWwindow *window, int preeditLength, unsigned CORE.Input.Keyboard.preeditCallback(preeditLength, (int *)preeditString, blockCount, blockSizes, focusedBlock, caret); } +// GLFW3 Preedit Candidate Callback +static void PreeditCandidateCallbackInner(GLFWwindow *window, int candidatesCount, int selectedIndex, int pageStart, int pageSize) +{ + if (!CORE.Input.Keyboard.preeditCandidateCallback) return; + CORE.Input.Keyboard.preeditCandidateCallback(candidatesCount, selectedIndex, pageStart, pageSize); +} // GLFW3 Mouse Button Callback, runs on mouse button pressed static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)