labwc/include/input/ime.h

92 lines
2.7 KiB
C
Raw Normal View History

2024-02-09 16:52:37 +09:00
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_IME_H
#define LABWC_IME_H
#include <wayland-server-core.h>
2024-02-09 16:52:37 +09:00
struct keyboard;
struct wlr_keyboard_key_event;
2024-02-09 16:52:37 +09:00
/*
* The relay structure manages the relationship between text-inputs and
* input-method on a given seat. Multiple text-inputs may be bound to a relay,
2024-03-08 21:59:20 +09:00
* but at most one will be "active" (communicating with input-method) at a time.
2024-02-09 16:52:37 +09:00
* At most one input-method may be bound to the seat. When an input-method and
* an active text-input is present, the relay passes messages between them.
*/
struct input_method_relay {
struct seat *seat;
struct wl_list text_inputs; /* struct text_input.link */
struct wlr_input_method_v2 *input_method;
struct wlr_surface *focused_surface;
IME: fix stuck Ctrl when pressed Ctrl+F in Firefox with Fcitx5 683f67b7 introduced another regression that the modifier state (Ctrl) is stuck when Ctrl+F is pressed in some applications like Firefox while Fcitx5 is running. This caused mouse scrolls to zoom in/out the UI. Let me explain the cause in detail. When Ctrl+F is pressed, an input box is opened in the application and Fcitx5 creates a new virtual keyboard (VK), whose initial modifiers is empty. Then prior to 683f67b7, the key/modifiers events flowed like this: - The compositor detects F key-release - Modifiers (Ctrl pressed) are notified via _set_keyboard() - F key-release is forwarded to IM - IM sends modifiers (Ctrl) back to the compositor via VK - **The modifiers on VK is updated (empty->Ctrl)** - **Modifers (Ctrl) are notified to the app** - IM sends F key-release back to the compositor via VK - F key-release is notified to the app - The compositor detects Ctrl key-release - Ctrl key-release is forwarded to IM - Modifiers (empty) are forwarded to IM - IM sends Ctrl key-release back to the compsitor via VK - Ctrl key-release is notified to IM - IM sends modifiers (empty) back to the compositor via VK - **The modifiers on VK is updated again (Ctrl->empty)** - **Modifiers (empty) are notified to the app** Thus, the final modifiers (empty) is notified to the application as expected. However, after 683f67b7, the key/modifiers events flowed like this: - The compositor detects F key-release - F key-release is directly notified to the app - The modifiers (Ctrl) is also notified to the app - The compositor detects Ctrl key-release - Ctrl key-release is directly notified to the app - Modifiers (empty) are forwarded to IM - IM sends modifiers (empty) back to the compositor via VK - **Modifier on VK is not updated (empty->empty)** - **The compositor ignores it** So the final modifier (empty) is never notified to the application, which causes stuck Ctrl modifier. This commit fixes this by not forwarding the modifiers when it hasn't been updated since it was forwarded previously. So after this commit, the key/modifiers events flow like this: - The compositor detects F key-release - F key-release is directly notified to the app - The modifiers (Ctrl) is also notified to the app - The compositor detects Ctrl key-release - Ctrl key-release is directly notified to the app - The modifiers are directly notified to the app because the modifiers (empty) are the same as the last forwarded modifier (empty).
2025-01-06 16:30:54 +09:00
2024-02-09 16:52:37 +09:00
/*
* Text-input which is enabled by the client and communicating with
* input-method.
* This must be NULL if input-method is not present.
* Its client must be the same as that of focused_surface.
*/
struct text_input *active_text_input;
struct wl_list popups; /* input_method_popup.link */
2024-02-23 03:50:55 +09:00
struct wlr_scene_tree *popup_tree;
2024-02-09 16:52:37 +09:00
struct wl_listener new_text_input;
struct wl_listener new_input_method;
struct wl_listener input_method_commit;
struct wl_listener input_method_grab_keyboard;
struct wl_listener input_method_destroy;
2024-02-23 03:50:55 +09:00
struct wl_listener input_method_new_popup_surface;
2024-02-09 16:52:37 +09:00
struct wl_listener keyboard_grab_destroy;
struct wl_listener focused_surface_destroy;
};
struct input_method_popup {
struct wlr_input_popup_surface_v2 *popup_surface;
struct wlr_scene_tree *tree;
struct input_method_relay *relay;
struct wl_list link; /* input_method_relay.popups */
struct wl_listener destroy;
struct wl_listener commit;
};
2024-02-09 16:52:37 +09:00
struct text_input {
struct input_method_relay *relay;
struct wlr_text_input_v3 *input;
struct wl_list link;
struct wl_listener enable;
struct wl_listener commit;
struct wl_listener disable;
struct wl_listener destroy;
};
/*
* Forward key event to keyboard grab of the seat from the keyboard
* if the keyboard grab exists.
* Returns true if the key event was forwarded.
*/
bool input_method_keyboard_grab_forward_key(struct keyboard *keyboard,
struct wlr_keyboard_key_event *event);
/*
* Forward modifier state to keyboard grab of the seat from the keyboard
* if the keyboard grab exists.
* Returns true if the modifier state was forwarded.
*/
bool input_method_keyboard_grab_forward_modifiers(struct keyboard *keyboard);
struct input_method_relay *input_method_relay_create(struct seat *seat);
void input_method_relay_finish(struct input_method_relay *relay);
/* Updates currently focused surface. Surface must belong to the same seat. */
void input_method_relay_set_focus(struct input_method_relay *relay,
struct wlr_surface *surface);
#endif