mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
IME: support multiple IME popups
We didn't support multiple IME popups since input-method-v2 protocol has no way to position them individually, but we should support it to provide IME developers with more programming flexibility.
This commit is contained in:
parent
1c334cc918
commit
2f1fcb4468
2 changed files with 55 additions and 48 deletions
|
|
@ -29,7 +29,7 @@ struct input_method_relay {
|
|||
*/
|
||||
struct text_input *active_text_input;
|
||||
|
||||
struct wlr_input_popup_surface_v2 *popup_surface;
|
||||
struct wl_list popups; /* input_method_popup.link */
|
||||
struct wlr_scene_tree *popup_tree;
|
||||
|
||||
struct wl_listener new_text_input;
|
||||
|
|
@ -40,13 +40,20 @@ struct input_method_relay {
|
|||
struct wl_listener input_method_destroy;
|
||||
struct wl_listener input_method_new_popup_surface;
|
||||
|
||||
struct wl_listener popup_surface_destroy;
|
||||
struct wl_listener popup_surface_commit;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct text_input {
|
||||
struct input_method_relay *relay;
|
||||
struct wlr_text_input_v3 *input;
|
||||
|
|
|
|||
|
|
@ -164,13 +164,14 @@ update_text_inputs_focused_surface(struct input_method_relay *relay)
|
|||
}
|
||||
|
||||
static void
|
||||
update_popup_position(struct input_method_relay *relay)
|
||||
update_popup_position(struct input_method_popup *popup)
|
||||
{
|
||||
struct input_method_relay *relay = popup->relay;
|
||||
struct server *server = relay->seat->server;
|
||||
struct text_input *text_input = relay->active_text_input;
|
||||
|
||||
if (!text_input || !relay->focused_surface || !relay->popup_surface
|
||||
|| !relay->popup_surface->surface->mapped) {
|
||||
if (!text_input || !relay->focused_surface
|
||||
|| !popup->popup_surface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -225,8 +226,8 @@ update_popup_position(struct input_method_relay *relay)
|
|||
.anchor = XDG_POSITIONER_ANCHOR_BOTTOM_LEFT,
|
||||
.gravity = XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT,
|
||||
.size = {
|
||||
.width = relay->popup_surface->surface->current.width,
|
||||
.height = relay->popup_surface->surface->current.height,
|
||||
.width = popup->popup_surface->surface->current.width,
|
||||
.height = popup->popup_surface->surface->current.height,
|
||||
},
|
||||
.constraint_adjustment =
|
||||
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y
|
||||
|
|
@ -238,12 +239,12 @@ update_popup_position(struct input_method_relay *relay)
|
|||
wlr_xdg_positioner_rules_unconstrain_box(&rules, &output_box, &popup_box);
|
||||
|
||||
wlr_scene_node_set_position(
|
||||
&relay->popup_tree->node, popup_box.x, popup_box.y);
|
||||
/* Make sure IME popup is always on top, above layer-shell surfaces */
|
||||
&popup->tree->node, popup_box.x, popup_box.y);
|
||||
/* Make sure IME popups are always on top, above layer-shell surfaces */
|
||||
wlr_scene_node_raise_to_top(&relay->popup_tree->node);
|
||||
|
||||
wlr_input_popup_surface_v2_send_text_input_rectangle(
|
||||
relay->popup_surface, &(struct wlr_box){
|
||||
popup->popup_surface, &(struct wlr_box){
|
||||
.x = cursor_rect.x - popup_box.x,
|
||||
.y = cursor_rect.y - popup_box.y,
|
||||
.width = cursor_rect.width,
|
||||
|
|
@ -251,6 +252,15 @@ update_popup_position(struct input_method_relay *relay)
|
|||
});
|
||||
}
|
||||
|
||||
static void
|
||||
update_popups_position(struct input_method_relay *relay)
|
||||
{
|
||||
struct input_method_popup *popup;
|
||||
wl_list_for_each(popup, &relay->popups, link) {
|
||||
update_popup_position(popup);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_input_method_commit(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
@ -342,20 +352,20 @@ handle_input_method_destroy(struct wl_listener *listener, void *data)
|
|||
static void
|
||||
handle_popup_surface_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct input_method_relay *relay =
|
||||
wl_container_of(listener, relay, popup_surface_destroy);
|
||||
wl_list_remove(&relay->popup_surface_destroy.link);
|
||||
wl_list_remove(&relay->popup_surface_commit.link);
|
||||
relay->popup_surface = NULL;
|
||||
relay->popup_tree = NULL;
|
||||
struct input_method_popup *popup =
|
||||
wl_container_of(listener, popup, destroy);
|
||||
wl_list_remove(&popup->destroy.link);
|
||||
wl_list_remove(&popup->commit.link);
|
||||
wl_list_remove(&popup->link);
|
||||
free(popup);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_popup_surface_commit(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct input_method_relay *relay =
|
||||
wl_container_of(listener, relay, popup_surface_commit);
|
||||
update_popup_position(relay);
|
||||
struct input_method_popup *popup =
|
||||
wl_container_of(listener, popup, commit);
|
||||
update_popup_position(popup);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -364,32 +374,22 @@ handle_input_method_new_popup_surface(struct wl_listener *listener, void *data)
|
|||
struct input_method_relay *relay = wl_container_of(listener, relay,
|
||||
input_method_new_popup_surface);
|
||||
|
||||
if (relay->popup_surface) {
|
||||
/*
|
||||
* With current input-method-v2 protocol, creating multiple IME
|
||||
* popups is not useful because they just stack up at the same
|
||||
* position.
|
||||
*
|
||||
* Discussed here:
|
||||
* https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/40#note_847039
|
||||
*/
|
||||
wlr_log(WLR_INFO,
|
||||
"Creating multiple IME popups is not supported");
|
||||
return;
|
||||
}
|
||||
struct input_method_popup *popup = znew(*popup);
|
||||
popup->popup_surface = data;
|
||||
popup->relay = relay;
|
||||
|
||||
relay->popup_surface = data;
|
||||
popup->destroy.notify = handle_popup_surface_destroy;
|
||||
wl_signal_add(&popup->popup_surface->events.destroy, &popup->destroy);
|
||||
|
||||
wl_signal_add(&relay->popup_surface->events.destroy,
|
||||
&relay->popup_surface_destroy);
|
||||
wl_signal_add(&relay->popup_surface->surface->events.commit,
|
||||
&relay->popup_surface_commit);
|
||||
popup->commit.notify = handle_popup_surface_commit;
|
||||
wl_signal_add(&popup->popup_surface->surface->events.commit,
|
||||
&popup->commit);
|
||||
|
||||
relay->popup_tree = wlr_scene_subsurface_tree_create(
|
||||
&relay->seat->server->scene->tree,
|
||||
relay->popup_surface->surface);
|
||||
node_descriptor_create(
|
||||
&relay->popup_tree->node, LAB_NODE_DESC_IME_POPUP, NULL);
|
||||
popup->tree = wlr_scene_subsurface_tree_create(
|
||||
relay->popup_tree, popup->popup_surface->surface);
|
||||
node_descriptor_create(&popup->tree->node, LAB_NODE_DESC_IME_POPUP, NULL);
|
||||
|
||||
wl_list_insert(&relay->popups, &popup->link);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -469,7 +469,7 @@ handle_text_input_enable(struct wl_listener *listener, void *data)
|
|||
|
||||
update_active_text_input(relay);
|
||||
if (relay->active_text_input == text_input) {
|
||||
update_popup_position(relay);
|
||||
update_popups_position(relay);
|
||||
send_state_to_input_method(relay);
|
||||
}
|
||||
}
|
||||
|
|
@ -495,7 +495,7 @@ handle_text_input_commit(struct wl_listener *listener, void *data)
|
|||
struct input_method_relay *relay = text_input->relay;
|
||||
|
||||
if (relay->active_text_input == text_input) {
|
||||
update_popup_position(relay);
|
||||
update_popups_position(relay);
|
||||
send_state_to_input_method(relay);
|
||||
}
|
||||
}
|
||||
|
|
@ -565,6 +565,8 @@ input_method_relay_create(struct seat *seat)
|
|||
struct input_method_relay *relay = znew(*relay);
|
||||
relay->seat = seat;
|
||||
wl_list_init(&relay->text_inputs);
|
||||
wl_list_init(&relay->popups);
|
||||
relay->popup_tree = wlr_scene_tree_create(&seat->server->scene->tree);
|
||||
|
||||
relay->new_text_input.notify = handle_new_text_input;
|
||||
wl_signal_add(&seat->server->text_input_manager->events.text_input,
|
||||
|
|
@ -575,8 +577,6 @@ input_method_relay_create(struct seat *seat)
|
|||
&relay->new_input_method);
|
||||
|
||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||
relay->popup_surface_destroy.notify = handle_popup_surface_destroy;
|
||||
relay->popup_surface_commit.notify = handle_popup_surface_commit;
|
||||
|
||||
return relay;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue