Atlas - SDL_waylandkeyboard.c

Home / ext / SDL / src / video / wayland Lines: 1 | Size: 11695 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 Sam Lantinga <[email protected]> 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#if SDL_VIDEO_DRIVER_WAYLAND 24 25#include "../SDL_sysvideo.h" 26#include "SDL_waylandvideo.h" 27#include "SDL_waylandevents_c.h" 28#include "../../events/SDL_keyboard_c.h" 29#include "text-input-unstable-v3-client-protocol.h" 30 31bool Wayland_InitKeyboard(SDL_VideoDevice *_this) 32{ 33#ifdef SDL_USE_IME 34 SDL_VideoData *internal = _this->internal; 35 if (!internal->text_input_manager) { 36 SDL_IME_Init(); 37 } 38#endif 39 SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); 40 41 return true; 42} 43 44void Wayland_QuitKeyboard(SDL_VideoDevice *_this) 45{ 46#ifdef SDL_USE_IME 47 SDL_VideoData *internal = _this->internal; 48 if (!internal->text_input_manager) { 49 SDL_IME_Quit(); 50 } 51#endif 52} 53 54void Wayland_SeatUpdateTextInput(SDL_WaylandSeat *seat) 55{ 56 if (seat->text_input.zwp_text_input) { 57 SDL_WindowData *focus = seat->keyboard.focus; 58 59 if (focus && focus->text_input_props.active) { 60 SDL_Window *window = focus->sdlwindow; 61 62 // Enabling will reset all state, so don't do it redundantly. 63 if (!seat->text_input.enabled) { 64 seat->text_input.enabled = true; 65 zwp_text_input_v3_enable(seat->text_input.zwp_text_input); 66 67 // Now that it's enabled, set the input properties 68 zwp_text_input_v3_set_content_type(seat->text_input.zwp_text_input, focus->text_input_props.hint, focus->text_input_props.purpose); 69 if (!SDL_RectEmpty(&window->text_input_rect)) { 70 const SDL_Rect scaled_rect = { 71 (int)SDL_floor(window->text_input_rect.x / focus->pointer_scale.x), 72 (int)SDL_floor(window->text_input_rect.y / focus->pointer_scale.y), 73 (int)SDL_ceil(window->text_input_rect.w / focus->pointer_scale.x), 74 (int)SDL_ceil(window->text_input_rect.h / focus->pointer_scale.y) 75 }; 76 const int scaled_cursor = (int)SDL_floor(window->text_input_cursor / focus->pointer_scale.x); 77 78 SDL_copyp(&seat->text_input.text_input_rect, &scaled_rect); 79 seat->text_input.text_input_cursor = scaled_cursor; 80 81 // Clamp the x value so it doesn't run too far past the end of the text input area. 82 zwp_text_input_v3_set_cursor_rectangle(seat->text_input.zwp_text_input, 83 SDL_min(scaled_rect.x + scaled_cursor, scaled_rect.x + scaled_rect.w), 84 scaled_rect.y, 85 1, 86 scaled_rect.h); 87 } 88 zwp_text_input_v3_commit(seat->text_input.zwp_text_input); 89 90 if (seat->keyboard.xkb.compose_state) { 91 // Reset compose state so composite and dead keys don't carry over 92 WAYLAND_xkb_compose_state_reset(seat->keyboard.xkb.compose_state); 93 } 94 } 95 } else { 96 if (seat->text_input.enabled) { 97 seat->text_input.enabled = false; 98 SDL_zero(seat->text_input.text_input_rect); 99 seat->text_input.text_input_cursor = 0; 100 zwp_text_input_v3_disable(seat->text_input.zwp_text_input); 101 zwp_text_input_v3_commit(seat->text_input.zwp_text_input); 102 } 103 104 if (seat->keyboard.xkb.compose_state) { 105 // Reset compose state so composite and dead keys don't carry over 106 WAYLAND_xkb_compose_state_reset(seat->keyboard.xkb.compose_state); 107 } 108 } 109 } 110} 111 112bool Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) 113{ 114 SDL_VideoData *display = _this->internal; 115 116 if (display->text_input_manager) { 117 SDL_WindowData *wind = window->internal; 118 wind->text_input_props.hint = ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE; 119 120 switch (SDL_GetTextInputType(props)) { 121 default: 122 case SDL_TEXTINPUT_TYPE_TEXT: 123 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL; 124 break; 125 case SDL_TEXTINPUT_TYPE_TEXT_NAME: 126 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NAME; 127 break; 128 case SDL_TEXTINPUT_TYPE_TEXT_EMAIL: 129 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL; 130 break; 131 case SDL_TEXTINPUT_TYPE_TEXT_USERNAME: 132 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL; 133 wind->text_input_props.hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA; 134 break; 135 case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN: 136 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD; 137 wind->text_input_props.hint |= (ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT | ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA); 138 break; 139 case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE: 140 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD; 141 wind->text_input_props.hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA; 142 break; 143 case SDL_TEXTINPUT_TYPE_NUMBER: 144 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER; 145 break; 146 case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN: 147 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PIN; 148 wind->text_input_props.hint |= (ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT | ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA); 149 break; 150 case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE: 151 wind->text_input_props.purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PIN; 152 wind->text_input_props.hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA; 153 break; 154 } 155 156 switch (SDL_GetTextInputCapitalization(props)) { 157 default: 158 case SDL_CAPITALIZE_NONE: 159 break; 160 case SDL_CAPITALIZE_LETTERS: 161 wind->text_input_props.hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE; 162 break; 163 case SDL_CAPITALIZE_WORDS: 164 wind->text_input_props.hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_TITLECASE; 165 break; 166 case SDL_CAPITALIZE_SENTENCES: 167 wind->text_input_props.hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_AUTO_CAPITALIZATION; 168 break; 169 } 170 171 if (SDL_GetTextInputAutocorrect(props)) { 172 wind->text_input_props.hint |= (ZWP_TEXT_INPUT_V3_CONTENT_HINT_COMPLETION | ZWP_TEXT_INPUT_V3_CONTENT_HINT_SPELLCHECK); 173 } 174 if (SDL_GetTextInputMultiline(props)) { 175 wind->text_input_props.hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE; 176 } 177 178 wind->text_input_props.active = true; 179 180 SDL_WaylandSeat *seat; 181 wl_list_for_each (seat, &display->seat_list, link) { 182 if (seat->keyboard.focus == wind) { 183 Wayland_SeatUpdateTextInput(seat); 184 } 185 } 186 } 187 188 /* Always return true, even if the text input protocol isn't supported, as basic 189 * text can still be obtained from keysyms and the composition system. 190 */ 191 return true; 192} 193 194bool Wayland_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) 195{ 196 SDL_VideoData *display = _this->internal; 197 198 if (display->text_input_manager) { 199 SDL_WaylandSeat *seat; 200 SDL_WindowData *wind = window->internal; 201 wind->text_input_props.active = false; 202 203 wl_list_for_each (seat, &display->seat_list, link) { 204 if (seat->keyboard.focus == wind) { 205 Wayland_SeatUpdateTextInput(seat); 206 } 207 } 208 } 209#ifdef SDL_USE_IME 210 else { 211 SDL_IME_Reset(); 212 } 213#endif 214 215 return true; 216} 217 218bool Wayland_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window) 219{ 220 SDL_VideoData *internal = _this->internal; 221 if (internal->text_input_manager) { 222 SDL_WaylandSeat *seat; 223 SDL_WindowData *wind = window->internal; 224 225 wl_list_for_each (seat, &internal->seat_list, link) { 226 if (seat->text_input.zwp_text_input && seat->keyboard.focus == wind) { 227 const SDL_Rect scaled_rect = { 228 (int)SDL_floor(window->text_input_rect.x / wind->pointer_scale.x), 229 (int)SDL_floor(window->text_input_rect.y / wind->pointer_scale.y), 230 (int)SDL_ceil(window->text_input_rect.w / wind->pointer_scale.x), 231 (int)SDL_ceil(window->text_input_rect.h / wind->pointer_scale.y) 232 }; 233 const int scaled_cursor = (int)SDL_floor(window->text_input_cursor / wind->pointer_scale.x); 234 235 if (!SDL_RectsEqual(&scaled_rect, &seat->text_input.text_input_rect) || scaled_cursor != seat->text_input.text_input_cursor) { 236 SDL_copyp(&seat->text_input.text_input_rect, &scaled_rect); 237 seat->text_input.text_input_cursor = scaled_cursor; 238 239 // Clamp the x value so it doesn't run too far past the end of the text input area. 240 zwp_text_input_v3_set_cursor_rectangle(seat->text_input.zwp_text_input, 241 SDL_min(scaled_rect.x + scaled_cursor, scaled_rect.x + scaled_rect.w), 242 scaled_rect.y, 243 1, 244 scaled_rect.h); 245 zwp_text_input_v3_commit(seat->text_input.zwp_text_input); 246 } 247 } 248 } 249 } 250#ifdef SDL_USE_IME 251 else { 252 SDL_IME_UpdateTextInputArea(window); 253 } 254#endif 255 return true; 256} 257 258bool Wayland_HasScreenKeyboardSupport(SDL_VideoDevice *_this) 259{ 260 /* In reality, we just want to return true when the screen keyboard is the 261 * _only_ way to get text input. So, in addition to checking for the text 262 * input protocol, make sure we don't have any physical keyboards either. 263 */ 264 SDL_VideoData *internal = _this->internal; 265 SDL_WaylandSeat *seat; 266 bool hastextmanager = (internal->text_input_manager != NULL); 267 bool haskeyboard = false; 268 269 // Check for at least one keyboard object on one seat. 270 wl_list_for_each (seat, &internal->seat_list, link) { 271 if (seat->keyboard.wl_keyboard) { 272 haskeyboard = true; 273 break; 274 } 275 } 276 277 return !haskeyboard && hastextmanager; 278} 279 280#endif // SDL_VIDEO_DRIVER_WAYLAND 281
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.