From 64a1da93633fd746cc1a83327654edadc3045747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Wed, 6 Mar 2024 21:51:52 +0100 Subject: [PATCH] clutter/input-method: Check for equality before notifying properties ClutterInputMethods content hint or purpose will be set again (even to the same values) whenever a wayland client sends us a new content type/purpose. Gtk appears to always set a content purpose on wl_text_input changes, so we currently set and notify the "content-purpose" property on every change in a gtk text field. Since the OSK is gnome-shell listens to this property and re-generates its entire layout when the content-purpose prop gets notified, this is currently causing lag/freezes on every keypress in the OSK in gnome-shell. So ensure to not notify these properties in case they're equal and set the properties in the same way as we usually set them instead of going via GObject. Part-of: --- clutter/clutter/clutter-input-method.c | 91 +++++++++++++------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/clutter/clutter/clutter-input-method.c b/clutter/clutter/clutter-input-method.c index 2d5213ef0..b693b6177 100644 --- a/clutter/clutter/clutter-input-method.c +++ b/clutter/clutter/clutter-input-method.c @@ -61,58 +61,27 @@ static GParamSpec *pspecs[N_PROPS] = { 0 }; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputMethod, clutter_input_method, G_TYPE_OBJECT) -static void -set_content_hints (ClutterInputMethod *im, - ClutterInputContentHintFlags content_hints) -{ - ClutterInputMethodPrivate *priv; - - priv = clutter_input_method_get_instance_private (im); - priv->content_hints = content_hints; - CLUTTER_INPUT_METHOD_GET_CLASS (im)->update_content_hints (im, content_hints); -} - -static void -set_content_purpose (ClutterInputMethod *im, - ClutterInputContentPurpose content_purpose) -{ - ClutterInputMethodPrivate *priv; - - priv = clutter_input_method_get_instance_private (im); - priv->content_purpose = content_purpose; - CLUTTER_INPUT_METHOD_GET_CLASS (im)->update_content_purpose (im, - content_purpose); -} - -static void -set_can_show_preedit (ClutterInputMethod *im, - gboolean can_show_preedit) -{ - ClutterInputMethodPrivate *priv; - - priv = clutter_input_method_get_instance_private (im); - priv->can_show_preedit = can_show_preedit; -} - static void clutter_input_method_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + ClutterInputMethod *im = CLUTTER_INPUT_METHOD (object); + switch (prop_id) { case PROP_CONTENT_HINTS: - set_content_hints (CLUTTER_INPUT_METHOD (object), - g_value_get_flags (value)); + clutter_input_method_set_content_hints (im, + g_value_get_flags (value)); break; case PROP_CONTENT_PURPOSE: - set_content_purpose (CLUTTER_INPUT_METHOD (object), - g_value_get_enum (value)); + clutter_input_method_set_content_purpose (im, + g_value_get_enum (value)); break; case PROP_CAN_SHOW_PREEDIT: - set_can_show_preedit (CLUTTER_INPUT_METHOD (object), - g_value_get_boolean (value)); + clutter_input_method_set_can_show_preedit (im, + g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -193,17 +162,20 @@ clutter_input_method_class_init (ClutterInputMethodClass *klass) g_param_spec_flags ("content-hints", NULL, NULL, CLUTTER_TYPE_INPUT_CONTENT_HINT_FLAGS, 0, G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); pspecs[PROP_CONTENT_PURPOSE] = g_param_spec_enum ("content-purpose", NULL, NULL, CLUTTER_TYPE_INPUT_CONTENT_PURPOSE, 0, G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); pspecs[PROP_CAN_SHOW_PREEDIT] = g_param_spec_boolean ("can-show-preedit", NULL, NULL, FALSE, G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, N_PROPS, pspecs); } @@ -423,27 +395,56 @@ void clutter_input_method_set_content_hints (ClutterInputMethod *im, ClutterInputContentHintFlags hints) { + ClutterInputMethodPrivate *priv; + g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); - g_object_set (G_OBJECT (im), "content-hints", hints, NULL); + priv = clutter_input_method_get_instance_private (im); + + if (priv->content_hints == hints) + return; + + priv->content_hints = hints; + CLUTTER_INPUT_METHOD_GET_CLASS (im)->update_content_hints (im, hints); + + g_object_notify_by_pspec (G_OBJECT (im), pspecs[PROP_CONTENT_HINTS]); } void clutter_input_method_set_content_purpose (ClutterInputMethod *im, ClutterInputContentPurpose purpose) { + ClutterInputMethodPrivate *priv; + g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); - g_object_set (G_OBJECT (im), "content-purpose", purpose, NULL); + priv = clutter_input_method_get_instance_private (im); + + if (priv->content_purpose == purpose) + return; + + priv->content_purpose = purpose; + CLUTTER_INPUT_METHOD_GET_CLASS (im)->update_content_purpose (im, purpose); + + g_object_notify_by_pspec (G_OBJECT (im), pspecs[PROP_CONTENT_PURPOSE]); } void clutter_input_method_set_can_show_preedit (ClutterInputMethod *im, gboolean can_show_preedit) { + ClutterInputMethodPrivate *priv; + g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); - g_object_set (G_OBJECT (im), "can-show-preedit", can_show_preedit, NULL); + priv = clutter_input_method_get_instance_private (im); + + if (priv->can_show_preedit == can_show_preedit) + return; + + priv->can_show_preedit = can_show_preedit; + + g_object_notify_by_pspec (G_OBJECT (im), pspecs[PROP_CAN_SHOW_PREEDIT]); } gboolean