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,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