1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | #include "SDL_internal.h" |
22 | |
23 | #include "SDL_ime.h" |
24 | #include "SDL_ibus.h" |
25 | #include "SDL_fcitx.h" |
26 | |
27 | typedef bool (*SDL_IME_Init_t)(void); |
28 | typedef void (*SDL_IME_Quit_t)(void); |
29 | typedef void (*SDL_IME_SetFocus_t)(bool); |
30 | typedef void (*SDL_IME_Reset_t)(void); |
31 | typedef bool (*SDL_IME_ProcessKeyEvent_t)(Uint32, Uint32, bool down); |
32 | typedef void (*SDL_IME_UpdateTextInputArea_t)(SDL_Window *window); |
33 | typedef void (*SDL_IME_PumpEvents_t)(void); |
34 | |
35 | static SDL_IME_Init_t SDL_IME_Init_Real = NULL; |
36 | static SDL_IME_Quit_t SDL_IME_Quit_Real = NULL; |
37 | static SDL_IME_SetFocus_t SDL_IME_SetFocus_Real = NULL; |
38 | static SDL_IME_Reset_t SDL_IME_Reset_Real = NULL; |
39 | static SDL_IME_ProcessKeyEvent_t SDL_IME_ProcessKeyEvent_Real = NULL; |
40 | static SDL_IME_UpdateTextInputArea_t SDL_IME_UpdateTextInputArea_Real = NULL; |
41 | static SDL_IME_PumpEvents_t SDL_IME_PumpEvents_Real = NULL; |
42 | |
43 | static void InitIME(void) |
44 | { |
45 | static bool inited = false; |
46 | #ifdef HAVE_FCITX |
47 | const char *im_module = SDL_getenv("SDL_IM_MODULE" ); |
48 | const char *xmodifiers = SDL_getenv("XMODIFIERS" ); |
49 | #endif |
50 | |
51 | if (inited == true) { |
52 | return; |
53 | } |
54 | |
55 | inited = true; |
56 | |
57 | // See if fcitx IME support is being requested |
58 | #ifdef HAVE_FCITX |
59 | if (!SDL_IME_Init_Real && |
60 | ((im_module && SDL_strcmp(im_module, "fcitx" ) == 0) || |
61 | (!im_module && xmodifiers && SDL_strstr(xmodifiers, "@im=fcitx" ) != NULL))) { |
62 | SDL_IME_Init_Real = SDL_Fcitx_Init; |
63 | SDL_IME_Quit_Real = SDL_Fcitx_Quit; |
64 | SDL_IME_SetFocus_Real = SDL_Fcitx_SetFocus; |
65 | SDL_IME_Reset_Real = SDL_Fcitx_Reset; |
66 | SDL_IME_ProcessKeyEvent_Real = SDL_Fcitx_ProcessKeyEvent; |
67 | SDL_IME_UpdateTextInputArea_Real = SDL_Fcitx_UpdateTextInputArea; |
68 | SDL_IME_PumpEvents_Real = SDL_Fcitx_PumpEvents; |
69 | } |
70 | #endif // HAVE_FCITX |
71 | |
72 | // default to IBus |
73 | #ifdef HAVE_IBUS_IBUS_H |
74 | if (!SDL_IME_Init_Real) { |
75 | SDL_IME_Init_Real = SDL_IBus_Init; |
76 | SDL_IME_Quit_Real = SDL_IBus_Quit; |
77 | SDL_IME_SetFocus_Real = SDL_IBus_SetFocus; |
78 | SDL_IME_Reset_Real = SDL_IBus_Reset; |
79 | SDL_IME_ProcessKeyEvent_Real = SDL_IBus_ProcessKeyEvent; |
80 | SDL_IME_UpdateTextInputArea_Real = SDL_IBus_UpdateTextInputArea; |
81 | SDL_IME_PumpEvents_Real = SDL_IBus_PumpEvents; |
82 | } |
83 | #endif // HAVE_IBUS_IBUS_H |
84 | } |
85 | |
86 | bool SDL_IME_Init(void) |
87 | { |
88 | InitIME(); |
89 | |
90 | if (SDL_IME_Init_Real) { |
91 | if (SDL_IME_Init_Real()) { |
92 | return true; |
93 | } |
94 | |
95 | // uhoh, the IME implementation's init failed! Disable IME support. |
96 | SDL_IME_Init_Real = NULL; |
97 | SDL_IME_Quit_Real = NULL; |
98 | SDL_IME_SetFocus_Real = NULL; |
99 | SDL_IME_Reset_Real = NULL; |
100 | SDL_IME_ProcessKeyEvent_Real = NULL; |
101 | SDL_IME_UpdateTextInputArea_Real = NULL; |
102 | SDL_IME_PumpEvents_Real = NULL; |
103 | } |
104 | |
105 | return false; |
106 | } |
107 | |
108 | void SDL_IME_Quit(void) |
109 | { |
110 | if (SDL_IME_Quit_Real) { |
111 | SDL_IME_Quit_Real(); |
112 | } |
113 | } |
114 | |
115 | void SDL_IME_SetFocus(bool focused) |
116 | { |
117 | if (SDL_IME_SetFocus_Real) { |
118 | SDL_IME_SetFocus_Real(focused); |
119 | } |
120 | } |
121 | |
122 | void SDL_IME_Reset(void) |
123 | { |
124 | if (SDL_IME_Reset_Real) { |
125 | SDL_IME_Reset_Real(); |
126 | } |
127 | } |
128 | |
129 | bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down) |
130 | { |
131 | if (SDL_IME_ProcessKeyEvent_Real) { |
132 | return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, down); |
133 | } |
134 | |
135 | return false; |
136 | } |
137 | |
138 | void SDL_IME_UpdateTextInputArea(SDL_Window *window) |
139 | { |
140 | if (SDL_IME_UpdateTextInputArea_Real) { |
141 | SDL_IME_UpdateTextInputArea_Real(window); |
142 | } |
143 | } |
144 | |
145 | void SDL_IME_PumpEvents(void) |
146 | { |
147 | if (SDL_IME_PumpEvents_Real) { |
148 | SDL_IME_PumpEvents_Real(); |
149 | } |
150 | } |
151 | |