From f3645b3e5e46e5389f6bcf2adefb4d055abd7a0b Mon Sep 17 00:00:00 2001 From: rpm-build Date: Dec 09 2020 17:12:07 +0000 Subject: ibus-1713606-hangul-with-mouse.patch patch_name: ibus-1713606-hangul-with-mouse.patch present_in_specfile: true location_in_specfile: 8 --- diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c index 80f3acf..bbbb577 100644 --- a/bus/ibusimpl.c +++ b/bus/ibusimpl.c @@ -815,6 +815,17 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus, engine = bus_input_context_get_engine (ibus->focused_context); if (engine) { g_object_ref (engine); + /* _ic_focus_in() can be called before _ic_focus_out() is + * called under the async processes of two ibus clients. + * E.g. gedit is a little slower v.s. a simple GtkTextView + * application is the fastest when you click a Hangul + * preedit text between the applications. + * preedit will be committed with focus-out in the ibus client + * likes ibus-im.so + * so do not commit preedit here in focus-in event. + */ + bus_input_context_clear_preedit_text (ibus->focused_context, + FALSE); bus_input_context_set_engine (ibus->focused_context, NULL); bus_input_context_set_emoji_extension (ibus->focused_context, NULL); diff --git a/bus/inputcontext.c b/bus/inputcontext.c index 4f98b84..1b8e7ad 100644 --- a/bus/inputcontext.c +++ b/bus/inputcontext.c @@ -73,6 +73,7 @@ struct _BusInputContext { guint preedit_cursor_pos; gboolean preedit_visible; guint preedit_mode; + gboolean client_commit_preedit; /* auxiliary text */ IBusText *auxiliary_text; @@ -212,6 +213,9 @@ static IBusPropList *props_empty = NULL; static const gchar introspection_xml[] = "" " " + /* properties */ + " " + " \n" /* methods */ " " " " @@ -273,6 +277,12 @@ static const gchar introspection_xml[] = " " " " " " + " " + " " + " " + " " + " " + " " " " " " " " @@ -297,9 +307,6 @@ static const gchar introspection_xml[] = " " " " " " - - /* properties */ - " " " " ""; @@ -1069,6 +1076,12 @@ _ic_reset (BusInputContext *context, GDBusMethodInvocation *invocation) { if (context->engine) { + if (context->preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) { + if (context->client_commit_preedit) + bus_input_context_clear_preedit_text (context, FALSE); + else + bus_input_context_clear_preedit_text (context, TRUE); + } bus_engine_proxy_reset (context->engine); } g_dbus_method_invocation_return_value (invocation, NULL); @@ -1354,6 +1367,13 @@ _ic_set_content_type (BusInputContext *context, } } +static void +_ic_set_client_commit_preedit (BusInputContext *context, + GVariant *value) +{ + g_variant_get (value, "(b)", &context->client_commit_preedit); +} + static gboolean bus_input_context_service_set_property (IBusService *service, GDBusConnection *connection, @@ -1379,9 +1399,14 @@ bus_input_context_service_set_property (IBusService *service, if (!bus_input_context_service_authorized_method (service, connection)) return FALSE; + g_return_val_if_fail (BUS_IS_INPUT_CONTEXT (service), FALSE); + if (g_strcmp0 (property_name, "ContentType") == 0) { - BusInputContext *context = (BusInputContext *) service; - _ic_set_content_type (context, value); + _ic_set_content_type (BUS_INPUT_CONTEXT (service), value); + return TRUE; + } + if (g_strcmp0 (property_name, "ClientCommitPreedit") == 0) { + _ic_set_client_commit_preedit (BUS_INPUT_CONTEXT (service), value); return TRUE; } @@ -1453,22 +1478,44 @@ bus_input_context_focus_in (BusInputContext *context) /** * bus_input_context_clear_preedit_text: + * @context: A #BusInputContext + * @with_signal: %FALSE if the preedit is already updated in ibus clients + * likes ibus-im.so. Otherwise %TRUE. * - * Clear context->preedit_text. If the preedit mode is IBUS_ENGINE_PREEDIT_COMMIT, commit it before clearing. + * Clear context->preedit_text. If the preedit mode is + * IBUS_ENGINE_PREEDIT_COMMIT, commit it before clearing. */ -static void -bus_input_context_clear_preedit_text (BusInputContext *context) +void +bus_input_context_clear_preedit_text (BusInputContext *context, + gboolean with_signal) { + IBusText *preedit_text; + guint preedit_mode; + gboolean preedit_visible; + g_assert (BUS_IS_INPUT_CONTEXT (context)); - if (context->preedit_visible && - context->preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) { - bus_input_context_commit_text (context, context->preedit_text); + if (!with_signal) { + g_object_unref (context->preedit_text); + context->preedit_mode = IBUS_ENGINE_PREEDIT_CLEAR; + context->preedit_text = (IBusText *) g_object_ref_sink (text_empty); + context->preedit_cursor_pos = 0; + context->preedit_visible = FALSE; + return; } - /* always clear preedit text */ + /* always clear preedit text to reset the cursor position in the + * client application before commit the preeit text. */ + preedit_text = g_object_ref (context->preedit_text); + preedit_mode = context->preedit_mode; + preedit_visible = context->preedit_visible; bus_input_context_update_preedit_text (context, text_empty, 0, FALSE, IBUS_ENGINE_PREEDIT_CLEAR, TRUE); + + if (preedit_visible && preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) { + bus_input_context_commit_text (context, preedit_text); + } + g_object_unref (preedit_text); } void @@ -1479,7 +1526,10 @@ bus_input_context_focus_out (BusInputContext *context) if (!context->has_focus) return; - bus_input_context_clear_preedit_text (context); + if (context->client_commit_preedit) + bus_input_context_clear_preedit_text (context, FALSE); + else + bus_input_context_clear_preedit_text (context, TRUE); bus_input_context_update_auxiliary_text (context, text_empty, FALSE); bus_input_context_update_lookup_table (context, lookup_table_empty, @@ -2338,7 +2388,7 @@ bus_input_context_disable (BusInputContext *context) { g_assert (BUS_IS_INPUT_CONTEXT (context)); - bus_input_context_clear_preedit_text (context); + bus_input_context_clear_preedit_text (context, TRUE); bus_input_context_update_auxiliary_text (context, text_empty, FALSE); bus_input_context_update_lookup_table (context, lookup_table_empty, @@ -2385,7 +2435,7 @@ bus_input_context_unset_engine (BusInputContext *context) { g_assert (BUS_IS_INPUT_CONTEXT (context)); - bus_input_context_clear_preedit_text (context); + bus_input_context_clear_preedit_text (context, TRUE); bus_input_context_update_auxiliary_text (context, text_empty, FALSE); bus_input_context_update_lookup_table (context, lookup_table_empty, @@ -2807,14 +2857,26 @@ bus_input_context_update_preedit_text (BusInputContext *context, } else if (PREEDIT_CONDITION) { GVariant *variant = ibus_serializable_serialize ( (IBusSerializable *)context->preedit_text); - bus_input_context_emit_signal (context, - "UpdatePreeditText", - g_variant_new ( - "(vub)", - variant, - context->preedit_cursor_pos, - extension_visible), - NULL); + if (context->client_commit_preedit) { + bus_input_context_emit_signal ( + context, + "UpdatePreeditTextWithMode", + g_variant_new ("(vubu)", + variant, + context->preedit_cursor_pos, + extension_visible, + context->preedit_mode), + NULL); + } else { + bus_input_context_emit_signal ( + context, + "UpdatePreeditText", + g_variant_new ("(vub)", + variant, + context->preedit_cursor_pos, + extension_visible), + NULL); + } } else { g_signal_emit (context, context_signals[UPDATE_PREEDIT_TEXT], diff --git a/bus/inputcontext.h b/bus/inputcontext.h index a46d5c0..7105fff 100644 --- a/bus/inputcontext.h +++ b/bus/inputcontext.h @@ -2,8 +2,8 @@ /* vim:set et sts=4: */ /* ibus - The Input Bus * Copyright (C) 2008-2014 Peng Huang - * Copyright (C) 2017 Takao Fujiwara - * Copyright (C) 2008-2014 Red Hat, Inc. + * Copyright (C) 2017-2018 Takao Fujiwara + * Copyright (C) 2008-2018 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -377,5 +377,20 @@ void bus_input_context_update_lookup_table void bus_input_context_panel_extension_received (BusInputContext *context, IBusExtensionEvent *event); + +/** + * bus_input_context_clear_preedit_text: + * + * Clear context->preedit_text. If the preedit mode is + * IBUS_ENGINE_PREEDIT_COMMIT and with_signal is %TRUE, commit it before + * clearing. + * If with_signal is %FALSE, this just clears the preedit coditions + * and the actual preedit is handled in ibus clients. + */ +void bus_input_context_clear_preedit_text + (BusInputContext *context, + gboolean + with_signal); + G_END_DECLS #endif diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c index e4de52d..50290c5 100644 --- a/client/gtk2/ibusimcontext.c +++ b/client/gtk2/ibusimcontext.c @@ -2,8 +2,8 @@ /* vim:set et sts=4: */ /* ibus - The Input Bus * Copyright (C) 2008-2013 Peng Huang - * Copyright (C) 2015-2017 Takao Fujiwara - * Copyright (C) 2008-2017 Red Hat, Inc. + * Copyright (C) 2015-2019 Takao Fujiwara + * Copyright (C) 2008-2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -61,6 +61,7 @@ struct _IBusIMContext { PangoAttrList *preedit_attrs; gint preedit_cursor_pos; gboolean preedit_visible; + guint preedit_mode; GdkRectangle cursor_area; gboolean has_focus; @@ -71,6 +72,10 @@ struct _IBusIMContext { /* cancellable */ GCancellable *cancellable; GQueue *events_queue; + +#if !GTK_CHECK_VERSION (3, 93, 0) + gboolean use_button_press_event; +#endif }; struct _IBusIMContextClass { @@ -132,8 +137,14 @@ static void ibus_im_context_set_surrounding gint len, gint cursor_index); - /* static methods*/ +static void _ibus_context_update_preedit_text_cb + (IBusInputContext *ibuscontext, + IBusText *text, + gint cursor_pos, + gboolean visible, + guint mode, + IBusIMContext *ibusimcontext); static void _create_input_context (IBusIMContext *context); static gboolean _set_cursor_location_internal (IBusIMContext *context); @@ -163,7 +174,6 @@ static void _create_fake_input_context (void); static gboolean _set_content_type (IBusIMContext *context); - static GType _ibus_type_im_context = 0; static GtkIMContextClass *parent_class = NULL; @@ -291,6 +301,7 @@ ibus_im_context_commit_event (IBusIMContext *ibusimcontext, IBusText *text = ibus_text_new_from_unichar (ch); g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text); g_object_unref (text); + _request_surrounding_text (ibusimcontext); return TRUE; } return FALSE; @@ -303,7 +314,6 @@ _process_key_event_done (GObject *object, { IBusInputContext *context = (IBusInputContext *)object; GdkEventKey *event = (GdkEventKey *) user_data; - GError *error = NULL; gboolean retval = ibus_input_context_process_key_event_async_finish ( context, @@ -352,12 +362,10 @@ _process_key_event (IBusInputContext *context, retval = TRUE; } - if (retval) { + if (retval) event->state |= IBUS_HANDLED_MASK; - } - else { + else event->state |= IBUS_IGNORED_MASK; - } return retval; } @@ -379,9 +387,12 @@ _request_surrounding_text (IBusIMContext *context) g_signal_emit (context, _signal_retrieve_surrounding_id, 0, &return_value); if (!return_value) { - context->caps &= ~IBUS_CAP_SURROUNDING_TEXT; - ibus_input_context_set_capabilities (context->ibuscontext, - context->caps); + /* #2054 firefox::IMContextWrapper::GetCurrentParagraph() could + * fail with the first typing on firefox but it succeeds with + * the second typing. + */ + g_warning ("%s has no capability of surrounding-text feature", + g_get_prgname ()); } } } @@ -552,6 +563,10 @@ daemon_name_appeared (GDBusConnection *connection, const gchar *owner, gpointer data) { + if (!g_strcmp0 (ibus_bus_get_service_name (_bus), IBUS_SERVICE_PORTAL)) { + _daemon_is_running = TRUE; + return; + } /* If ibus-daemon is running and run ssh -X localhost, * daemon_name_appeared() is called but ibus_get_address() == NULL * because the hostname and display number are different between @@ -744,6 +759,7 @@ ibus_im_context_init (GObject *obj) ibusimcontext->preedit_attrs = NULL; ibusimcontext->preedit_cursor_pos = 0; ibusimcontext->preedit_visible = FALSE; + ibusimcontext->preedit_mode = IBUS_ENGINE_PREEDIT_CLEAR; // Init cursor area ibusimcontext->cursor_area.x = -1; @@ -854,6 +870,36 @@ ibus_im_context_finalize (GObject *obj) G_OBJECT_CLASS(parent_class)->finalize (obj); } +static void +ibus_im_context_clear_preedit_text (IBusIMContext *ibusimcontext) +{ + gchar *preedit_string = NULL; + g_assert (ibusimcontext->ibuscontext); + if (ibusimcontext->preedit_visible && + ibusimcontext->preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) { + preedit_string = g_strdup (ibusimcontext->preedit_string); + } + + /* Clear the preedit_string but keep the preedit_cursor_pos and + * preedit_visible because a time lag could happen, firefox commit + * the preedit text before the preedit text is cleared and it cause + * a double commits of the Hangul preedit in firefox if the preedit + * would be located on the URL bar and click on anywhere of firefox + * out of the URL bar. + */ + _ibus_context_update_preedit_text_cb (ibusimcontext->ibuscontext, + ibus_text_new_from_string (""), + ibusimcontext->preedit_cursor_pos, + ibusimcontext->preedit_visible, + IBUS_ENGINE_PREEDIT_CLEAR, + ibusimcontext); + if (preedit_string) { + g_signal_emit (ibusimcontext, _signal_commit_id, 0, preedit_string); + g_free (preedit_string); + _request_surrounding_text (ibusimcontext); + } +} + static gboolean ibus_im_context_filter_keypress (GtkIMContext *context, GdkEventKey *event) @@ -1003,6 +1049,7 @@ ibus_im_context_focus_out (GtkIMContext *context) ibusimcontext->has_focus = FALSE; if (ibusimcontext->ibuscontext) { + ibus_im_context_clear_preedit_text (ibusimcontext); ibus_input_context_focus_out (ibusimcontext->ibuscontext); } @@ -1022,6 +1069,13 @@ ibus_im_context_reset (GtkIMContext *context) IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context); if (ibusimcontext->ibuscontext) { + /* Commented out ibus_im_context_clear_preedit_text(). + * Hangul needs to receive the reset callback with button press + * but other IMEs should avoid to receive the reset callback + * by themselves. + * IBus uses button-press-event instead until GTK is fixed. + * https://gitlab.gnome.org/GNOME/gtk/issues/1534 + */ ibus_input_context_reset (ibusimcontext->ibuscontext); } gtk_im_context_reset (ibusimcontext->slave); @@ -1068,21 +1122,80 @@ ibus_im_context_get_preedit_string (GtkIMContext *context, } +#if !GTK_CHECK_VERSION (3, 93, 0) +/* Use the button-press-event signal until GtkIMContext always emits the reset + * signal. + * https://gitlab.gnome.org/GNOME/gtk/merge_requests/460 + */ +static gboolean +ibus_im_context_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + IBusIMContext *ibusimcontext) +{ + if (event->button != 1) + return FALSE; + + if (ibusimcontext->ibuscontext) { + ibus_im_context_clear_preedit_text (ibusimcontext); + ibus_input_context_reset (ibusimcontext->ibuscontext); + } + return FALSE; +} + +static void +_connect_button_press_event (IBusIMContext *ibusimcontext, + gboolean do_connect) +{ + GtkWidget *widget = NULL; + + g_assert (ibusimcontext->client_window); + gdk_window_get_user_data (ibusimcontext->client_window, + (gpointer *)&widget); + /* firefox needs GtkWidget instead of GtkWindow */ + if (GTK_IS_WIDGET (widget)) { + if (do_connect) { + g_signal_connect ( + widget, + "button-press-event", + G_CALLBACK (ibus_im_context_button_press_event_cb), + ibusimcontext); + ibusimcontext->use_button_press_event = TRUE; + } else { + g_signal_handlers_disconnect_by_func ( + widget, + G_CALLBACK (ibus_im_context_button_press_event_cb), + ibusimcontext); + ibusimcontext->use_button_press_event = FALSE; + } + } +} +#endif + static void ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) { + IBusIMContext *ibusimcontext; + IDEBUG ("%s", __FUNCTION__); - IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context); + ibusimcontext = IBUS_IM_CONTEXT (context); if (ibusimcontext->client_window) { +#if !GTK_CHECK_VERSION (3, 93, 0) + if (ibusimcontext->use_button_press_event) + _connect_button_press_event (ibusimcontext, FALSE); +#endif g_object_unref (ibusimcontext->client_window); ibusimcontext->client_window = NULL; } - if (client != NULL) + if (client != NULL) { ibusimcontext->client_window = g_object_ref (client); - +#if !GTK_CHECK_VERSION (3, 93, 0) + if (!ibusimcontext->use_button_press_event) + _connect_button_press_event (ibusimcontext, TRUE); +#endif + } if (ibusimcontext->slave) gtk_im_context_set_client_window (ibusimcontext->slave, client); } @@ -1393,6 +1506,7 @@ _key_is_modifier (guint keyval) return FALSE; } } + /* Copy from gdk */ static GdkEventKey * _create_gdk_event (IBusIMContext *ibusimcontext, @@ -1530,6 +1644,7 @@ _ibus_context_update_preedit_text_cb (IBusInputContext *ibuscontext, IBusText *text, gint cursor_pos, gboolean visible, + guint mode, IBusIMContext *ibusimcontext) { IDEBUG ("%s", __FUNCTION__); @@ -1545,6 +1660,15 @@ _ibus_context_update_preedit_text_cb (IBusInputContext *ibuscontext, ibusimcontext->preedit_attrs = NULL; } +#if !GTK_CHECK_VERSION (3, 93, 0) + if (!ibusimcontext->use_button_press_event && + mode == IBUS_ENGINE_PREEDIT_COMMIT) { + if (ibusimcontext->client_window) { + _connect_button_press_event (ibusimcontext, TRUE); + } + } +#endif + str = text->text; ibusimcontext->preedit_string = g_strdup (str); if (text->attrs) { @@ -1586,6 +1710,7 @@ _ibus_context_update_preedit_text_cb (IBusInputContext *ibuscontext, flag = ibusimcontext->preedit_visible != visible; ibusimcontext->preedit_visible = visible; + ibusimcontext->preedit_mode = mode; if (ibusimcontext->preedit_visible) { if (flag) { @@ -1676,7 +1801,7 @@ _create_input_context_done (IBusBus *bus, g_error_free (error); } else { - + ibus_input_context_set_client_commit_preedit (context, TRUE); ibusimcontext->ibuscontext = context; g_signal_connect (ibusimcontext->ibuscontext, @@ -1692,7 +1817,7 @@ _create_input_context_done (IBusBus *bus, G_CALLBACK (_ibus_context_delete_surrounding_text_cb), ibusimcontext); g_signal_connect (ibusimcontext->ibuscontext, - "update-preedit-text", + "update-preedit-text-with-mode", G_CALLBACK (_ibus_context_update_preedit_text_cb), ibusimcontext); g_signal_connect (ibusimcontext->ibuscontext, diff --git a/portal/org.freedesktop.IBus.Portal.xml b/portal/org.freedesktop.IBus.Portal.xml index afce4da..376ad42 100644 --- a/portal/org.freedesktop.IBus.Portal.xml +++ b/portal/org.freedesktop.IBus.Portal.xml @@ -1,6 +1,6 @@