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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3645>
This commit is contained in:
Jonas Dreßler 2024-03-06 21:51:52 +01:00
parent a775241efd
commit 64a1da9363

View File

@ -61,57 +61,26 @@ static GParamSpec *pspecs[N_PROPS] = { 0 };
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputMethod, clutter_input_method, G_TYPE_OBJECT) 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 static void
clutter_input_method_set_property (GObject *object, clutter_input_method_set_property (GObject *object,
guint prop_id, guint prop_id,
const GValue *value, const GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterInputMethod *im = CLUTTER_INPUT_METHOD (object);
switch (prop_id) switch (prop_id)
{ {
case PROP_CONTENT_HINTS: case PROP_CONTENT_HINTS:
set_content_hints (CLUTTER_INPUT_METHOD (object), clutter_input_method_set_content_hints (im,
g_value_get_flags (value)); g_value_get_flags (value));
break; break;
case PROP_CONTENT_PURPOSE: case PROP_CONTENT_PURPOSE:
set_content_purpose (CLUTTER_INPUT_METHOD (object), clutter_input_method_set_content_purpose (im,
g_value_get_enum (value)); g_value_get_enum (value));
break; break;
case PROP_CAN_SHOW_PREEDIT: case PROP_CAN_SHOW_PREEDIT:
set_can_show_preedit (CLUTTER_INPUT_METHOD (object), clutter_input_method_set_can_show_preedit (im,
g_value_get_boolean (value)); g_value_get_boolean (value));
break; break;
default: default:
@ -193,17 +162,20 @@ clutter_input_method_class_init (ClutterInputMethodClass *klass)
g_param_spec_flags ("content-hints", NULL, NULL, g_param_spec_flags ("content-hints", NULL, NULL,
CLUTTER_TYPE_INPUT_CONTENT_HINT_FLAGS, 0, CLUTTER_TYPE_INPUT_CONTENT_HINT_FLAGS, 0,
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS); G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
pspecs[PROP_CONTENT_PURPOSE] = pspecs[PROP_CONTENT_PURPOSE] =
g_param_spec_enum ("content-purpose", NULL, NULL, g_param_spec_enum ("content-purpose", NULL, NULL,
CLUTTER_TYPE_INPUT_CONTENT_PURPOSE, 0, CLUTTER_TYPE_INPUT_CONTENT_PURPOSE, 0,
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS); G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
pspecs[PROP_CAN_SHOW_PREEDIT] = pspecs[PROP_CAN_SHOW_PREEDIT] =
g_param_spec_boolean ("can-show-preedit", NULL, NULL, g_param_spec_boolean ("can-show-preedit", NULL, NULL,
FALSE, FALSE,
G_PARAM_READWRITE | 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); g_object_class_install_properties (object_class, N_PROPS, pspecs);
} }
@ -423,27 +395,56 @@ void
clutter_input_method_set_content_hints (ClutterInputMethod *im, clutter_input_method_set_content_hints (ClutterInputMethod *im,
ClutterInputContentHintFlags hints) ClutterInputContentHintFlags hints)
{ {
ClutterInputMethodPrivate *priv;
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); 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 void
clutter_input_method_set_content_purpose (ClutterInputMethod *im, clutter_input_method_set_content_purpose (ClutterInputMethod *im,
ClutterInputContentPurpose purpose) ClutterInputContentPurpose purpose)
{ {
ClutterInputMethodPrivate *priv;
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); 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 void
clutter_input_method_set_can_show_preedit (ClutterInputMethod *im, clutter_input_method_set_can_show_preedit (ClutterInputMethod *im,
gboolean can_show_preedit) gboolean can_show_preedit)
{ {
ClutterInputMethodPrivate *priv;
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); 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 gboolean