From b6d576922b07ff2125f6070ea7a009477c684d73 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Fri, 23 Feb 2024 03:50:55 +0900 Subject: [PATCH 1/2] IME: support IME popup --- include/input/ime.h | 7 +++ include/node.h | 1 + src/debug.c | 5 ++ src/desktop.c | 4 ++ src/input/ime.c | 150 ++++++++++++++++++++++++++++++++++++++++++++ src/layers.c | 7 +++ src/xdg.c | 2 +- 7 files changed, 175 insertions(+), 1 deletion(-) diff --git a/include/input/ime.h b/include/input/ime.h index 54ac22be..06dd16ff 100644 --- a/include/input/ime.h +++ b/include/input/ime.h @@ -29,12 +29,19 @@ struct input_method_relay { */ struct text_input *active_text_input; + struct wlr_input_popup_surface_v2 *popup_surface; + struct wlr_scene_tree *popup_tree; + 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; + 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; diff --git a/include/node.h b/include/node.h index 419aa996..d0a41c71 100644 --- a/include/node.h +++ b/include/node.h @@ -15,6 +15,7 @@ enum node_descriptor_type { LAB_NODE_DESC_XDG_POPUP, LAB_NODE_DESC_LAYER_SURFACE, LAB_NODE_DESC_LAYER_POPUP, + LAB_NODE_DESC_IME_POPUP, LAB_NODE_DESC_MENUITEM, LAB_NODE_DESC_TREE, LAB_NODE_DESC_SSD_BUTTON, diff --git a/src/debug.c b/src/debug.c index af722f3e..d8b9c179 100644 --- a/src/debug.c +++ b/src/debug.c @@ -141,6 +141,11 @@ get_special(struct server *server, struct wlr_scene_node *node) /* Created on-demand */ return "seat->region_overlay"; } + if (server->seat.input_method_relay->popup_tree + && node == &server->seat.input_method_relay->popup_tree->node) { + /* Created on-demand */ + return "seat->im_relay->popup_tree"; + } if (server->osd_state.preview_outline && node == &server->osd_state.preview_outline->tree->node) { /* Created on-demand */ diff --git a/src/desktop.c b/src/desktop.c index 4aca14b8..4141e974 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -326,6 +326,10 @@ get_cursor_context(struct server *server) ret.type = LAB_SSD_CLIENT; ret.surface = get_surface_from_layer_node(node); return ret; + case LAB_NODE_DESC_IME_POPUP: + ret.type = LAB_SSD_CLIENT; + ret.surface = lab_wlr_surface_from_node(ret.node); + return ret; case LAB_NODE_DESC_MENUITEM: /* Always return the top scene node for menu items */ ret.node = node; diff --git a/src/input/ime.c b/src/input/ime.c index 18d54207..bb08f6d5 100644 --- a/src/input/ime.c +++ b/src/input/ime.c @@ -152,6 +152,94 @@ update_text_inputs_focused_surface(struct input_method_relay *relay) } } +static void +update_popup_position(struct input_method_relay *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) { + return; + } + + struct wlr_box cursor_rect; + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_try_from_wlr_surface(relay->focused_surface); + struct wlr_layer_surface_v1 *layer_surface = + wlr_layer_surface_v1_try_from_wlr_surface(relay->focused_surface); + + if ((text_input->input->current.features + & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE) + && (xdg_surface || layer_surface)) { + cursor_rect = text_input->input->current.cursor_rectangle; + + /* + * wlr_surface->data is: + * - for XDG surfaces: view->scene_node + * - for layer surfaces: lab_layer_surface->scene_layer_surface->tree + * - for layer popups: lab_layer_popup->scene_tree + */ + struct wlr_scene_tree *tree = relay->focused_surface->data; + int lx, ly; + wlr_scene_node_coords(&tree->node, &lx, &ly); + cursor_rect.x += lx; + cursor_rect.y += ly; + + if (xdg_surface) { + /* Take into account invisible xdg-shell CSD borders */ + struct wlr_box geo; + wlr_xdg_surface_get_geometry(xdg_surface, &geo); + cursor_rect.x -= geo.x; + cursor_rect.y -= geo.y; + } + } else { + cursor_rect = (struct wlr_box){0}; + } + + struct output *output = + output_nearest_to(server, cursor_rect.x, cursor_rect.y); + if (!output_is_usable(output)) { + wlr_log(WLR_ERROR, + "Cannot position IME popup (unusable output)"); + return; + } + struct wlr_box output_box; + wlr_output_layout_get_box( + server->output_layout, output->wlr_output, &output_box); + + /* Use xdg-positioner utilities to position popup */ + struct wlr_xdg_positioner_rules rules = { + .anchor_rect = cursor_rect, + .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, + }, + .constraint_adjustment = + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y + | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X, + }; + + struct wlr_box popup_box; + wlr_xdg_positioner_rules_get_geometry(&rules, &popup_box); + 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 */ + 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){ + .x = cursor_rect.x - popup_box.x, + .y = cursor_rect.y - popup_box.y, + .width = cursor_rect.width, + .height = cursor_rect.height, + }); +} + static void handle_input_method_commit(struct wl_listener *listener, void *data) { @@ -236,6 +324,59 @@ handle_input_method_destroy(struct wl_listener *listener, void *data) update_active_text_input(relay); } +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; +} + +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); +} + +static void +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; + } + + relay->popup_surface = data; + + 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); + + 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); +} + static void handle_new_input_method(struct wl_listener *listener, void *data) { @@ -268,6 +409,11 @@ handle_new_input_method(struct wl_listener *listener, void *data) wl_signal_add(&relay->input_method->events.destroy, &relay->input_method_destroy); + relay->input_method_new_popup_surface.notify = + handle_input_method_new_popup_surface; + wl_signal_add(&relay->input_method->events.new_popup_surface, + &relay->input_method_new_popup_surface); + update_text_inputs_focused_surface(relay); update_active_text_input(relay); } @@ -308,6 +454,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); send_state_to_input_method(relay); } } @@ -333,6 +480,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); send_state_to_input_method(relay); } } @@ -412,6 +560,8 @@ 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; } diff --git a/src/layers.c b/src/layers.c index 20e9e683..efb5462f 100644 --- a/src/layers.c +++ b/src/layers.c @@ -298,6 +298,10 @@ create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent) free(popup); return NULL; } + + /* In support of IME popup */ + wlr_popup->base->surface->data = popup->scene_tree; + node_descriptor_create(&popup->scene_tree->node, LAB_NODE_DESC_LAYER_POPUP, popup); @@ -424,6 +428,9 @@ handle_new_layer_surface(struct wl_listener *listener, void *data) return; } + /* In support of IME popup */ + layer_surface->surface->data = surface->scene_layer_surface->tree; + node_descriptor_create(&surface->scene_layer_surface->tree->node, LAB_NODE_DESC_LAYER_SURFACE, surface); diff --git a/src/xdg.c b/src/xdg.c index 73c9ef68..1ad53554 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -773,7 +773,7 @@ xdg_surface_new(struct wl_listener *listener, void *data) */ kde_server_decoration_set_view(view, xdg_surface->surface); - /* In support of xdg popups */ + /* In support of xdg popups and IME popup */ xdg_surface->surface->data = tree; view_connect_map(view, xdg_surface->surface); From 1597d683ca37e3c6e9f0ad7a058c00d362088569 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 12 Mar 2024 22:48:48 +0100 Subject: [PATCH 2/2] Translation updates from weblate Co-authored-by: Abdullah Albaroty Co-authored-by: Hiroaki Yamamoto Co-authored-by: Weblate Co-authored-by: alwanasary Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ar/ Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/id/ Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ja/ Translation: Labwc/labwc --- po/ar.po | 4 ++-- po/id.po | 16 ++++++++-------- po/ja.po | 29 +++++++++++++++-------------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/po/ar.po b/po/ar.po index 681bdeb7..a6f10f34 100644 --- a/po/ar.po +++ b/po/ar.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: labwc\n" "Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n" "POT-Creation-Date: 2024-01-15 16:00-0500\n" -"PO-Revision-Date: 2024-03-06 09:23+0000\n" +"PO-Revision-Date: 2024-03-11 10:23+0000\n" "Last-Translator: Abdullah Albaroty \n" "Language-Team: Arabic \n" @@ -46,7 +46,7 @@ msgstr "طي/إلغاء طي" #: src/menu/menu.c:723 msgid "Decorations" -msgstr "إلغاء الحواف" +msgstr "إخف الإطار" #: src/menu/menu.c:725 msgid "Always on Top" diff --git a/po/id.po b/po/id.po index 59f75d7f..79907257 100644 --- a/po/id.po +++ b/po/id.po @@ -3,19 +3,21 @@ # This file is distributed under the same license as the labwc package. # May Mantari , 2023. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: labwc\n" "Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n" "POT-Creation-Date: 2024-01-15 16:00-0500\n" -"PO-Revision-Date: 2023-04-14 20:40+0700\n" -"Last-Translator: May Mantari \n" +"PO-Revision-Date: 2024-03-12 21:48+0000\n" +"Last-Translator: alwanasary \n" +"Language-Team: Indonesian \n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.2.1\n" #: src/menu/menu.c:697 msgid "Reconfigure" @@ -39,15 +41,13 @@ msgstr "Tampil Menyeluruh" #: src/menu/menu.c:721 msgid "Roll up/down" -msgstr "" +msgstr "Gulir atas/bawah" #: src/menu/menu.c:723 msgid "Decorations" msgstr "Dekorasi" #: src/menu/menu.c:725 -#, fuzzy -#| msgid "Always On Top" msgid "Always on Top" msgstr "Selalu di Muka" @@ -61,7 +61,7 @@ msgstr "Geser ke Kanan" #: src/menu/menu.c:742 msgid "Always on Visible Workspace" -msgstr "" +msgstr "Selalu pada Ruang Kerja yang Terlihat" #: src/menu/menu.c:745 msgid "Workspace" diff --git a/po/ja.po b/po/ja.po index 51352e34..dd8b9cbd 100644 --- a/po/ja.po +++ b/po/ja.po @@ -8,9 +8,10 @@ msgstr "" "Project-Id-Version: labwc\n" "Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n" "POT-Creation-Date: 2024-01-15 16:00-0500\n" -"PO-Revision-Date: 2024-01-02 15:23+0000\n" -"Last-Translator: Masamichi Ito \n" -"Language-Team: Japanese \n" +"PO-Revision-Date: 2024-03-12 21:48+0000\n" +"Last-Translator: Hiroaki Yamamoto \n" +"Language-Team: Japanese \n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -20,7 +21,7 @@ msgstr "" #: src/menu/menu.c:697 msgid "Reconfigure" -msgstr "" +msgstr "再設定" #: src/menu/menu.c:699 msgid "Exit" @@ -28,43 +29,43 @@ msgstr "終了" #: src/menu/menu.c:715 msgid "Minimize" -msgstr "" +msgstr "最小化" #: src/menu/menu.c:717 msgid "Maximize" -msgstr "" +msgstr "最大化" #: src/menu/menu.c:719 msgid "Fullscreen" -msgstr "" +msgstr "フルスクリーン" #: src/menu/menu.c:721 msgid "Roll up/down" -msgstr "" +msgstr "折りたたむ/広げる" #: src/menu/menu.c:723 msgid "Decorations" -msgstr "" +msgstr "デコレーション" #: src/menu/menu.c:725 msgid "Always on Top" -msgstr "" +msgstr "常に最全面に表示" #: src/menu/menu.c:730 msgid "Move left" -msgstr "" +msgstr "左に移動" #: src/menu/menu.c:737 msgid "Move right" -msgstr "" +msgstr "右に移動" #: src/menu/menu.c:742 msgid "Always on Visible Workspace" -msgstr "" +msgstr "現在のワークスペースに常に表示" #: src/menu/menu.c:745 msgid "Workspace" -msgstr "" +msgstr "ワークスペース" #: src/menu/menu.c:748 msgid "Close"