Wayland: Gate text-input routing on focus

Map explicit text input focus to text-input-v3 enable/disable and
text-input-v1 activate/deactivate.

When text input focus is inactive, avoid auto-enabling text input on
protocol enter and ignore stale text-input callbacks.  Applications
that never call glfwSetTextInputFocus keep the previous enter-time
activation behavior.

On focus out, reset local preedit state and send the available protocol
reset/disable requests.
This commit is contained in:
Takuro Ashie 2026-06-21 16:31:10 +09:00
parent 148ff80572
commit 377cab5616

View file

@ -737,6 +737,11 @@ static void deactivateTextInputV1(_GLFWwindow* window)
zwp_text_input_v1_deactivate(window->wl.textInputV1, _glfw.wl.seat);
}
static GLFWbool textInputFocusDisabled(_GLFWwindow* window)
{
return window->textInputFocusInitialized && !window->textInputFocus;
}
static void xdgToplevelHandleConfigure(void* userData,
struct xdg_toplevel* toplevel,
int32_t width,
@ -764,7 +769,8 @@ static void xdgToplevelHandleConfigure(void* userData,
break;
case XDG_TOPLEVEL_STATE_ACTIVATED:
window->wl.pending.activated = GLFW_TRUE;
activateTextInputV1(window);
if (!textInputFocusDisabled(window))
activateTextInputV1(window);
break;
}
}
@ -1717,7 +1723,8 @@ static void pointerHandleButton(void* userData,
// On weston, pressing the title bar will cause leave event and never emit
// enter event even though back to content area by pressing mouse button
// just after it. So activate it here explicitly.
activateTextInputV1(window);
if (!textInputFocusDisabled(window))
activateTextInputV1(window);
_glfw.wl.serial = serial;
@ -2410,8 +2417,13 @@ static void textInputV3Enter(void* data,
struct zwp_text_input_v3* textInputV3,
struct wl_surface* surface)
{
zwp_text_input_v3_enable(textInputV3);
zwp_text_input_v3_commit(textInputV3);
_GLFWwindow* window = (_GLFWwindow*) data;
if (!textInputFocusDisabled(window))
{
zwp_text_input_v3_enable(textInputV3);
zwp_text_input_v3_commit(textInputV3);
}
}
static void textInputV3Reset(_GLFWwindow* window)
@ -2451,6 +2463,9 @@ static void textInputV3PreeditString(void* data,
const char* cur = text;
unsigned int cursorLength = 0;
if (textInputFocusDisabled(window))
return;
preedit->textCount = 0;
preedit->blockSizesCount = 0;
preedit->focusedBlockIndex = 0;
@ -2524,6 +2539,9 @@ static void textInputV3CommitString(void* data,
_GLFWwindow* window = (_GLFWwindow*) data;
const char* cur = text;
if (textInputFocusDisabled(window))
return;
if (!window->callbacks.character)
return;
@ -2546,6 +2564,9 @@ static void textInputV3Done(void* data,
uint32_t serial)
{
_GLFWwindow* window = (_GLFWwindow*) data;
if (textInputFocusDisabled(window))
return;
_glfwUpdatePreeditCursorRectangleWayland(window);
_glfwInputPreedit(window);
}
@ -2571,7 +2592,9 @@ static void textInputV1Enter(void* data,
struct wl_surface* surface)
{
_GLFWwindow* window = (_GLFWwindow*) data;
activateTextInputV1(window);
if (!textInputFocusDisabled(window))
activateTextInputV1(window);
}
static void textInputV1Reset(_GLFWwindow* window)
@ -2597,6 +2620,13 @@ static void textInputV1Leave(void* data,
_GLFWwindow* window = (_GLFWwindow*) data;
char* commitText = window->wl.textInputV1Context.commitTextOnReset;
if (textInputFocusDisabled(window))
{
textInputV1Reset(window);
deactivateTextInputV1(window);
return;
}
textInputV3CommitString(data, NULL, commitText);
textInputV1Reset(window);
deactivateTextInputV1(window);
@ -2622,6 +2652,9 @@ static void textInputV1PreeditString(void* data,
{
_GLFWwindow* window = (_GLFWwindow*) data;
if (textInputFocusDisabled(window))
return;
_glfw_free(window->wl.textInputV1Context.preeditText);
_glfw_free(window->wl.textInputV1Context.commitTextOnReset);
window->wl.textInputV1Context.preeditText = strdup(text);
@ -2648,6 +2681,9 @@ static void textInputV1PreeditCursor(void* data,
const char* text = window->wl.textInputV1Context.preeditText;
const char* cur = text;
if (textInputFocusDisabled(window))
return;
preedit->caretIndex = 0;
if (index <= 0 || preedit->textCount == 0)
return;
@ -2670,6 +2706,9 @@ static void textInputV1CommitString(void* data,
{
_GLFWwindow* window = (_GLFWwindow*) data;
if (textInputFocusDisabled(window))
return;
textInputV1Reset(window);
textInputV3CommitString(data, NULL, text);
}
@ -2697,6 +2736,10 @@ static void textInputV1Keysym(void* data,
uint32_t state,
uint32_t modifiers)
{
_GLFWwindow* window = (_GLFWwindow*) data;
if (textInputFocusDisabled(window))
return;
uint32_t scancode;
// This code supports only weston-keyboard because we aren't aware
@ -3945,7 +3988,29 @@ void _glfwResetPreeditTextWayland(_GLFWwindow* window)
void _glfwSetTextInputFocusWayland(_GLFWwindow* window, GLFWbool focused)
{
// TODO: Wire this to text-input-v3 enable/disable or focus integration.
if (window->wl.textInputV3)
{
if (focused)
zwp_text_input_v3_enable(window->wl.textInputV3);
else
{
zwp_text_input_v3_disable(window->wl.textInputV3);
textInputV3Reset(window);
}
zwp_text_input_v3_commit(window->wl.textInputV3);
}
else if (window->wl.textInputV1)
{
if (focused)
activateTextInputV1(window);
else
{
zwp_text_input_v1_reset(window->wl.textInputV1);
textInputV1Reset(window);
deactivateTextInputV1(window);
}
}
}
void _glfwSetIMEStatusWayland(_GLFWwindow* window, int active)