Skip to content

Commit 735f0cc

Browse files
committed
wayland: Handle text input per-seat
When changing the text input mode on a window, only update the seats that currently hold keyboard focus on that window, otherwise, text input might be inadvertently enabled or disabled on a seat focused on another window.
1 parent 8bd29f7 commit 735f0cc

File tree

4 files changed

+73
-66
lines changed

4 files changed

+73
-66
lines changed

src/video/wayland/SDL_waylandevents.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "SDL_waylandwindow.h"
3636
#include "SDL_waylandmouse.h"
3737
#include "SDL_waylandclipboard.h"
38+
#include "SDL_waylandkeyboard.h"
3839

3940
#include "pointer-constraints-unstable-v1-client-protocol.h"
4041
#include "relative-pointer-unstable-v1-client-protocol.h"
@@ -1897,7 +1898,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
18971898
Wayland_DisplayUpdatePointerGrabs(seat->display, window);
18981899

18991900
// Update text input and IME focus.
1900-
Wayland_UpdateTextInput(seat->display);
1901+
Wayland_SeatUpdateTextInput(seat);
19011902

19021903
#ifdef SDL_USE_IME
19031904
if (!seat->text_input.zwp_text_input) {
@@ -1979,7 +1980,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
19791980
seat->keyboard.pressed_modifiers = SDL_KMOD_NONE;
19801981

19811982
// Update text input and IME focus.
1982-
Wayland_UpdateTextInput(seat->display);
1983+
Wayland_SeatUpdateTextInput(seat);
19831984

19841985
#ifdef SDL_USE_IME
19851986
if (!seat->text_input.zwp_text_input && !window->keyboard_focus_count) {

src/video/wayland/SDL_waylandevents_c.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include "SDL_waylandvideo.h"
3232
#include "SDL_waylandwindow.h"
3333
#include "SDL_waylanddatamanager.h"
34-
#include "SDL_waylandkeyboard.h"
3534

3635
enum SDL_WaylandAxisEvent
3736
{

src/video/wayland/SDL_waylandkeyboard.c

Lines changed: 69 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -51,65 +51,59 @@ void Wayland_QuitKeyboard(SDL_VideoDevice *_this)
5151
#endif
5252
}
5353

54-
void Wayland_UpdateTextInput(SDL_VideoData *display)
54+
void Wayland_SeatUpdateTextInput(SDL_WaylandSeat *seat)
5555
{
56-
SDL_WaylandSeat *seat = NULL;
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);
5777

58-
if (display->text_input_manager) {
59-
wl_list_for_each(seat, &display->seat_list, link) {
60-
SDL_WindowData *focus = seat->keyboard.focus;
61-
62-
if (seat->text_input.zwp_text_input) {
63-
if (focus && focus->text_input_props.active) {
64-
SDL_Window *window = focus->sdlwindow;
65-
66-
// Enabling will reset all state, so don't do it redundantly.
67-
if (!seat->text_input.enabled) {
68-
seat->text_input.enabled = true;
69-
zwp_text_input_v3_enable(seat->text_input.zwp_text_input);
70-
71-
// Now that it's enabled, set the input properties
72-
zwp_text_input_v3_set_content_type(seat->text_input.zwp_text_input, focus->text_input_props.hint, focus->text_input_props.purpose);
73-
if (!SDL_RectEmpty(&window->text_input_rect)) {
74-
const SDL_Rect scaled_rect = {
75-
(int)SDL_floor(window->text_input_rect.x / focus->pointer_scale.x),
76-
(int)SDL_floor(window->text_input_rect.y / focus->pointer_scale.y),
77-
(int)SDL_ceil(window->text_input_rect.w / focus->pointer_scale.x),
78-
(int)SDL_ceil(window->text_input_rect.h / focus->pointer_scale.y)
79-
};
80-
const int scaled_cursor = (int)SDL_floor(window->text_input_cursor / focus->pointer_scale.x);
81-
82-
SDL_copyp(&seat->text_input.text_input_rect, &scaled_rect);
83-
seat->text_input.text_input_cursor = scaled_cursor;
84-
85-
// Clamp the x value so it doesn't run too far past the end of the text input area.
86-
zwp_text_input_v3_set_cursor_rectangle(seat->text_input.zwp_text_input,
87-
SDL_min(scaled_rect.x + scaled_cursor, scaled_rect.x + scaled_rect.w),
88-
scaled_rect.y,
89-
1,
90-
scaled_rect.h);
91-
}
92-
zwp_text_input_v3_commit(seat->text_input.zwp_text_input);
93-
94-
if (seat->keyboard.xkb.compose_state) {
95-
// Reset compose state so composite and dead keys don't carry over
96-
WAYLAND_xkb_compose_state_reset(seat->keyboard.xkb.compose_state);
97-
}
98-
}
99-
} else {
100-
if (seat->text_input.enabled) {
101-
seat->text_input.enabled = false;
102-
SDL_zero(seat->text_input.text_input_rect);
103-
seat->text_input.text_input_cursor = 0;
104-
zwp_text_input_v3_disable(seat->text_input.zwp_text_input);
105-
zwp_text_input_v3_commit(seat->text_input.zwp_text_input);
106-
}
107-
108-
if (seat->keyboard.xkb.compose_state) {
109-
// Reset compose state so composite and dead keys don't carry over
110-
WAYLAND_xkb_compose_state_reset(seat->keyboard.xkb.compose_state);
111-
}
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);
11287
}
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);
113107
}
114108
}
115109
}
@@ -182,21 +176,34 @@ bool Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_Prop
182176
}
183177

184178
wind->text_input_props.active = true;
185-
Wayland_UpdateTextInput(display);
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+
}
186186

187187
return true;
188188
}
189189

190-
return false;
190+
return SDL_SetError("wayland: cannot enable text input; compositor lacks support for the required zwp_text_input_v3 protocol");
191191
}
192192

193193
bool Wayland_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
194194
{
195195
SDL_VideoData *display = _this->internal;
196196

197197
if (display->text_input_manager) {
198-
window->internal->text_input_props.active = false;
199-
Wayland_UpdateTextInput(display);
198+
SDL_WaylandSeat *seat;
199+
SDL_WindowData *wind = window->internal;
200+
wind->text_input_props.active = false;
201+
202+
wl_list_for_each (seat, &display->seat_list, link) {
203+
if (seat->keyboard.focus == wind) {
204+
Wayland_SeatUpdateTextInput(seat);
205+
}
206+
}
200207
}
201208
#ifdef SDL_USE_IME
202209
else {
@@ -212,10 +219,10 @@ bool Wayland_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
212219
SDL_VideoData *internal = _this->internal;
213220
if (internal->text_input_manager) {
214221
SDL_WaylandSeat *seat;
222+
SDL_WindowData *wind = window->internal;
215223

216224
wl_list_for_each (seat, &internal->seat_list, link) {
217-
if (seat->text_input.zwp_text_input && seat->keyboard.focus == window->internal) {
218-
SDL_WindowData *wind = window->internal;
225+
if (seat->text_input.zwp_text_input && seat->keyboard.focus == wind) {
219226
const SDL_Rect scaled_rect = {
220227
(int)SDL_floor(window->text_input_rect.x / wind->pointer_scale.x),
221228
(int)SDL_floor(window->text_input_rect.y / wind->pointer_scale.y),

src/video/wayland/SDL_waylandkeyboard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ extern void Wayland_QuitKeyboard(SDL_VideoDevice *_this);
2828
extern bool Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props);
2929
extern bool Wayland_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window);
3030
extern bool Wayland_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window);
31-
extern void Wayland_UpdateTextInput(SDL_VideoData *display);
31+
extern void Wayland_SeatUpdateTextInput(SDL_WaylandSeat *seat);
3232
extern bool Wayland_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
3333

3434
#endif // SDL_waylandkeyboard_h_

0 commit comments

Comments
 (0)