diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 57509c557861..e7d23353bd48 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -638,6 +638,12 @@ void ResetPreedit(void) TRACELOG(LOG_WARNING, "ResetPreedit() not implemented on target platform"); } +// Get the text of the preedie candidate +int *GetPreeditCandidate(int index, int *textCount) +{ + TRACELOG(LOG_WARNING, "GetPreeditCandidate() not implemented on target platform"); +} + // Set internal gamepad mappings int SetGamepadMappings(const char *mappings) { diff --git a/src/platforms/rcore_desktop.c b/src/platforms/rcore_desktop.c index cd7b5f34ab2a..6950abc72c10 100644 --- a/src/platforms/rcore_desktop.c +++ b/src/platforms/rcore_desktop.c @@ -129,6 +129,7 @@ static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float s 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 codepoint); // GLFW3 Char Callback, runs on key pressed (get codepoint 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 Scrolling Callback, runs on mouse wheel @@ -1078,6 +1079,12 @@ void ResetPreedit(void) glfwResetPreeditText(platform.handle); } +// Get the text of the preedie candidate +int *GetPreeditCandidate(int index, int *textCount) +{ + return (int *)glfwGetPreeditCandidate(platform.handle, index, textCount); +} + // Set internal gamepad mappings int SetGamepadMappings(const char *mappings) { @@ -1277,6 +1284,10 @@ int InitPlatform(void) #if defined(__APPLE__) 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 + // Initialize GLFW internal global state int result = glfwInit(); if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; } @@ -1580,6 +1591,7 @@ int InitPlatform(void) glfwSetKeyCallback(platform.handle, KeyCallback); glfwSetCharCallback(platform.handle, CharCallback); glfwSetPreeditCallback(platform.handle, PreeditCallbackInner); + glfwSetPreeditCandidateCallback(platform.handle, PreeditCandidateCallbackInner); glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback); glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes glfwSetScrollCallback(platform.handle, MouseScrollCallback); @@ -1769,6 +1781,13 @@ 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) { diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index be758a965f8d..805e203eacfb 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -964,6 +964,12 @@ void ResetPreedit(void) TRACELOG(LOG_WARNING, "ResetPreedit() not implemented on target platform"); } +// Get the text of the preedie candidate +int *GetPreeditCandidate(int index, int *textCount) +{ + TRACELOG(LOG_WARNING, "GetPreeditCandidate() not implemented on target platform"); +} + // Set internal gamepad mappings int SetGamepadMappings(const char *mappings) { diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 9167f2722972..0382f57f6e18 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -544,6 +544,12 @@ void ResetPreedit(void) TRACELOG(LOG_WARNING, "ResetPreedit() not implemented on target platform"); } +// Get the text of the preedie candidate +int *GetPreeditCandidate(int index, int *textCount) +{ + TRACELOG(LOG_WARNING, "GetPreeditCandidate() not implemented on target platform"); +} + // Set internal gamepad mappings int SetGamepadMappings(const char *mappings) { diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c index 83f4dc4b8ef6..74a41d95eaf8 100644 --- a/src/platforms/rcore_template.c +++ b/src/platforms/rcore_template.c @@ -396,6 +396,12 @@ void ResetPreedit(void) TRACELOG(LOG_WARNING, "ResetPreedit() not implemented on target platform"); } +// Get the text of the preedie candidate +int *GetPreeditCandidate(int index, int *textCount) +{ + TRACELOG(LOG_WARNING, "GetPreeditCandidate() not implemented on target platform"); +} + // Set internal gamepad mappings int SetGamepadMappings(const char *mappings) { diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index a3ee3ad19564..63ac67938a5b 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -121,6 +121,7 @@ static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float s 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 @@ -876,6 +877,12 @@ void ResetPreedit(void) glfwResetPreeditText(platform.handle); } +// Get the text of the preedie candidate +int *GetPreeditCandidate(int index, int *textCount) +{ + return (int *)glfwGetPreeditCandidate(platform.handle, index, textCount); +} + // Set internal gamepad mappings int SetGamepadMappings(const char *mappings) { @@ -1040,6 +1047,9 @@ int InitPlatform(void) { glfwSetErrorCallback(ErrorCallback); + 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 + // Initialize GLFW internal global state int result = glfwInit(); if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; } @@ -1240,6 +1250,7 @@ int InitPlatform(void) glfwSetKeyCallback(platform.handle, KeyCallback); glfwSetCharCallback(platform.handle, CharCallback); glfwSetPreeditCallback(platform.handle, PreeditCallbackInner); + glfwSetPreeditCandidateCallback(platform.handle, PreeditCandidateCallbackInner); glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback); glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes glfwSetScrollCallback(platform.handle, MouseScrollCallback); @@ -1478,6 +1489,13 @@ static void PreeditCallbackInner(GLFWwindow *window, int preeditLength, unsigned CORE.Input.Keyboard.preeditCallback(preeditLength, (int *)preeditString, blockCount, blockSizes, focusedBlock, caret); } +// GLFW3 Preedit Callback +static void PreeditCallbackInner(GLFWwindow *window, int preeditLength, unsigned int *preeditString, int blockCount, int *blockSizes, int focusedBlock, int caret) +{ + if (!CORE.Input.Keyboard.preeditCallback) return; + CORE.Input.Keyboard.preeditCallback(preeditLength, (int *)preeditString, blockCount, blockSizes, focusedBlock, caret); +} + // GLFW3 Mouse Button Callback, runs on mouse button pressed static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { diff --git a/src/raylib.h b/src/raylib.h index 1a1d08badfef..aaf282f784e3 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -533,6 +533,7 @@ typedef struct AutomationEventList { 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 @@ -1150,6 +1151,7 @@ RLAPI void PlayAutomationEvent(AutomationEvent event); //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ + // Callback for preedit text. // preeditLength: The length of preedit text // preeditString: The preedit text (unicode) @@ -1159,6 +1161,13 @@ RLAPI void PlayAutomationEvent(AutomationEvent event); // 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 IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP) @@ -1174,6 +1183,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 9f9da46aeeb2..a6f95c2b04bb 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -305,6 +305,7 @@ typedef struct CoreData { int charPressedQueueCount; // Input characters queue count PreeditCallback preeditCallback; // Preedit callback + PreeditCandidateCallback preeditCandidateCallback; // Preedit candidate callback } Keyboard; struct { @@ -2787,6 +2788,12 @@ void SetPreeditCallback(PreeditCallback callback) CORE.Input.Keyboard.preeditCallback = callback; } +// Set a callback for preedit candidate +void SetPreeditCandidateCallback(PreeditCandidateCallback callback) +{ + CORE.Input.Keyboard.preeditCandidateCallback = callback; +} + // Set a custom key to exit program // NOTE: default exitKey is set to ESCAPE void SetExitKey(int key)