clutter: Add ClutterPreeditResetMode hint to preedit text

This mode is passed along by the ClutterInputMethod, the
ClutterInputFocus will preserve it and ensure it is honored
whenever the IM is being reset.

This mode is immediate. The ClutterInputFocus commits the
text directly without queueing a CLUTTER_IM_COMMIT event.
This is important so events are serialized in the right order
in the wayland implementations (i.e. commit before wl_pointer.press).

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1940>
This commit is contained in:
Carlos Garnacho 2021-07-30 16:40:17 +02:00 committed by Marge Bot
parent 9c20b4144a
commit 765f41de80
5 changed files with 59 additions and 16 deletions

View File

@ -1638,6 +1638,12 @@ typedef enum
CLUTTER_INPUT_PANEL_STATE_TOGGLE, CLUTTER_INPUT_PANEL_STATE_TOGGLE,
} ClutterInputPanelState; } ClutterInputPanelState;
typedef enum
{
CLUTTER_PREEDIT_RESET_CLEAR,
CLUTTER_PREEDIT_RESET_COMMIT,
} ClutterPreeditResetMode;
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_ENUMS_H__ */ #endif /* __CLUTTER_ENUMS_H__ */

View File

@ -561,6 +561,7 @@ struct _ClutterIMEvent
char *text; char *text;
int32_t offset; int32_t offset;
uint32_t len; uint32_t len;
ClutterPreeditResetMode mode;
}; };
/** /**

View File

@ -30,6 +30,8 @@ typedef struct _ClutterInputFocusPrivate ClutterInputFocusPrivate;
struct _ClutterInputFocusPrivate struct _ClutterInputFocusPrivate
{ {
ClutterInputMethod *im; ClutterInputMethod *im;
char *preedit;
ClutterPreeditResetMode mode;
}; };
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputFocus, clutter_input_focus, G_TYPE_OBJECT) G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputFocus, clutter_input_focus, G_TYPE_OBJECT)
@ -53,9 +55,25 @@ clutter_input_focus_real_focus_out (ClutterInputFocus *focus)
priv->im = NULL; priv->im = NULL;
} }
static void
clutter_input_focus_finalize (GObject *object)
{
ClutterInputFocus *focus = CLUTTER_INPUT_FOCUS (object);
ClutterInputFocusPrivate *priv =
clutter_input_focus_get_instance_private (focus);
g_clear_pointer (&priv->preedit, g_free);
G_OBJECT_CLASS (clutter_input_focus_parent_class)->finalize (object);
}
static void static void
clutter_input_focus_class_init (ClutterInputFocusClass *klass) clutter_input_focus_class_init (ClutterInputFocusClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = clutter_input_focus_finalize;
klass->focus_in = clutter_input_focus_real_focus_in; klass->focus_in = clutter_input_focus_real_focus_in;
klass->focus_out = clutter_input_focus_real_focus_out; klass->focus_out = clutter_input_focus_real_focus_out;
} }
@ -85,6 +103,14 @@ clutter_input_focus_reset (ClutterInputFocus *focus)
priv = clutter_input_focus_get_instance_private (focus); priv = clutter_input_focus_get_instance_private (focus);
if (priv->preedit &&
priv->mode == CLUTTER_PREEDIT_RESET_COMMIT)
clutter_input_focus_commit (focus, priv->preedit);
clutter_input_focus_set_preedit_text (focus, NULL, 0);
g_clear_pointer (&priv->preedit, g_free);
priv->mode = CLUTTER_PREEDIT_RESET_CLEAR;
clutter_input_method_reset (priv->im); clutter_input_method_reset (priv->im);
} }
@ -175,13 +201,16 @@ clutter_input_focus_filter_event (ClutterInputFocus *focus,
} }
else if (event->type == CLUTTER_IM_PREEDIT) else if (event->type == CLUTTER_IM_PREEDIT)
{ {
g_clear_pointer (&priv->preedit, g_free);
priv->preedit = g_strdup (event->im.text);
priv->mode = event->im.mode;
clutter_input_focus_set_preedit_text (focus, event->im.text, clutter_input_focus_set_preedit_text (focus, event->im.text,
event->im.offset); event->im.offset);
return TRUE; return TRUE;
} }
else if (event->type == CLUTTER_TOUCH_BEGIN || else if (event->type == CLUTTER_TOUCH_BEGIN ||
(event->type == CLUTTER_BUTTON_PRESS && (event->type == CLUTTER_BUTTON_PRESS &&
event->button.button == CLUTTER_BUTTON_PRIMARY)) event->button.button == CLUTTER_BUTTON_PRIMARY))
{ {
clutter_input_focus_reset (focus); clutter_input_focus_reset (focus);
/* pointing events are not consumed by IMs */ /* pointing events are not consumed by IMs */

View File

@ -278,11 +278,12 @@ clutter_input_method_get_focus (ClutterInputMethod *im)
} }
static void static void
clutter_input_method_put_im_event (ClutterInputMethod *im, clutter_input_method_put_im_event (ClutterInputMethod *im,
ClutterEventType event_type, ClutterEventType event_type,
const char *text, const char *text,
int32_t offset, int32_t offset,
uint32_t len) uint32_t len,
ClutterPreeditResetMode mode)
{ {
ClutterInputDevice *keyboard; ClutterInputDevice *keyboard;
ClutterSeat *seat; ClutterSeat *seat;
@ -299,6 +300,7 @@ clutter_input_method_put_im_event (ClutterInputMethod *im,
event->im.text = g_strdup (text); event->im.text = g_strdup (text);
event->im.offset = offset; event->im.offset = offset;
event->im.len = len; event->im.len = len;
event->im.mode = mode;
clutter_event_set_device (event, keyboard); clutter_event_set_device (event, keyboard);
clutter_event_set_source_device (event, keyboard); clutter_event_set_source_device (event, keyboard);
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_INPUT_METHOD); clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_INPUT_METHOD);
@ -315,7 +317,8 @@ clutter_input_method_commit (ClutterInputMethod *im,
{ {
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
clutter_input_method_put_im_event (im, CLUTTER_IM_COMMIT, text, 0, 0); clutter_input_method_put_im_event (im, CLUTTER_IM_COMMIT, text, 0, 0,
CLUTTER_PREEDIT_RESET_CLEAR);
} }
void void
@ -325,7 +328,8 @@ clutter_input_method_delete_surrounding (ClutterInputMethod *im,
{ {
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
clutter_input_method_put_im_event (im, CLUTTER_IM_DELETE, NULL, offset, len); clutter_input_method_put_im_event (im, CLUTTER_IM_DELETE, NULL, offset, len,
CLUTTER_PREEDIT_RESET_CLEAR);
} }
void void
@ -349,13 +353,15 @@ clutter_input_method_request_surrounding (ClutterInputMethod *im)
* Sets the preedit text on the current input focus. * Sets the preedit text on the current input focus.
**/ **/
void void
clutter_input_method_set_preedit_text (ClutterInputMethod *im, clutter_input_method_set_preedit_text (ClutterInputMethod *im,
const gchar *preedit, const gchar *preedit,
guint cursor) unsigned int cursor,
ClutterPreeditResetMode mode)
{ {
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
clutter_input_method_put_im_event (im, CLUTTER_IM_PREEDIT, preedit, cursor, 0); clutter_input_method_put_im_event (im, CLUTTER_IM_PREEDIT, preedit,
cursor, 0, mode);
} }
void void

View File

@ -74,9 +74,10 @@ CLUTTER_EXPORT
void clutter_input_method_request_surrounding (ClutterInputMethod *im); void clutter_input_method_request_surrounding (ClutterInputMethod *im);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_input_method_set_preedit_text (ClutterInputMethod *im, void clutter_input_method_set_preedit_text (ClutterInputMethod *im,
const gchar *preedit, const gchar *preedit,
guint cursor); unsigned int cursor,
ClutterPreeditResetMode mode);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_input_method_notify_key_event (ClutterInputMethod *im, void clutter_input_method_notify_key_event (ClutterInputMethod *im,