text: Fix serial handling

Signed-off-by: Jan Arne Petersen <jpetersen@openismus.com>
This commit is contained in:
Jan Arne Petersen 2013-04-18 16:47:33 +02:00 committed by Kristian Høgsberg
parent b41531a88e
commit 00191c7c4a
7 changed files with 73 additions and 86 deletions

View file

@ -63,6 +63,7 @@ struct text_entry {
xkb_mod_mask_t shift_mask;
} keysym;
uint32_t serial;
uint32_t reset_serial;
uint32_t content_purpose;
uint32_t click_to_show;
char *preferred_language;
@ -138,6 +139,12 @@ text_input_commit_string(void *data,
{
struct text_entry *entry = data;
if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) {
fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n",
serial, entry->serial, entry->reset_serial);
return;
}
text_entry_reset_preedit(entry);
text_entry_delete_selected_text(entry);
@ -175,7 +182,6 @@ text_input_preedit_string(void *data,
static void
text_input_delete_surrounding_text(void *data,
struct text_input *text_input,
uint32_t serial,
int32_t index,
uint32_t length)
{
@ -207,7 +213,6 @@ text_input_delete_surrounding_text(void *data,
static void
text_input_cursor_position(void *data,
struct text_input *text_input,
uint32_t serial,
int32_t index,
int32_t anchor)
{
@ -220,7 +225,6 @@ text_input_cursor_position(void *data,
static void
text_input_preedit_styling(void *data,
struct text_input *text_input,
uint32_t serial,
uint32_t index,
uint32_t length,
uint32_t style)
@ -272,7 +276,6 @@ text_input_preedit_styling(void *data,
static void
text_input_preedit_cursor(void *data,
struct text_input *text_input,
uint32_t serial,
int32_t index)
{
struct text_entry *entry = data;
@ -374,6 +377,9 @@ text_input_enter(void *data,
entry->active = 1;
text_entry_update(entry);
entry->reset_serial = entry->serial;
widget_schedule_redraw(entry->widget);
}
@ -552,10 +558,7 @@ text_entry_activate(struct text_entry *entry,
if (!entry->click_to_show)
text_input_show_input_panel(entry->text_input);
entry->serial++;
text_input_activate(entry->text_input,
entry->serial,
seat,
surface);
}
@ -653,7 +656,7 @@ text_entry_update(struct text_entry *entry)
text_input_set_cursor_rectangle(entry->text_input, cursor_rectangle.x, cursor_rectangle.y,
cursor_rectangle.width, cursor_rectangle.height);
text_input_commit_state(entry->text_input);
text_input_commit_state(entry->text_input, ++entry->serial);
}
static void
@ -714,8 +717,9 @@ text_entry_commit_and_reset(struct text_entry *entry)
free(commit);
}
entry->serial++;
text_input_reset(entry->text_input, entry->serial);
text_input_reset(entry->text_input);
text_entry_update(entry);
entry->reset_serial = entry->serial;
}
static void

View file

@ -395,7 +395,6 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
"",
"");
input_method_context_cursor_position(keyboard->context,
keyboard->serial,
0, 0);
input_method_context_commit_string(keyboard->context,
keyboard->serial,
@ -412,14 +411,12 @@ virtual_keyboard_send_preedit(struct virtual_keyboard *keyboard,
if (keyboard->preedit_style)
input_method_context_preedit_styling(keyboard->context,
keyboard->serial,
0,
strlen(keyboard->preedit_string),
keyboard->preedit_style);
if (cursor > 0)
index = cursor;
input_method_context_preedit_cursor(keyboard->context,
keyboard->serial,
index);
input_method_context_preedit_string(keyboard->context,
keyboard->serial,
@ -449,7 +446,6 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
if (strlen(keyboard->keyboard->preedit_string) == 0) {
input_method_context_delete_surrounding_text(keyboard->keyboard->context,
keyboard->keyboard->serial,
-1, 1);
} else {
keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0';
@ -579,8 +575,7 @@ handle_surrounding_text(void *data,
static void
handle_reset(void *data,
struct input_method_context *context,
uint32_t serial)
struct input_method_context *context)
{
struct virtual_keyboard *keyboard = data;
@ -597,8 +592,6 @@ handle_reset(void *data,
free(keyboard->preedit_string);
keyboard->preedit_string = strdup("");
}
keyboard->serial = serial;
}
static void
@ -628,12 +621,15 @@ handle_invoke_action(void *data,
}
static void
handle_commit(void *data,
struct input_method_context *context)
handle_commit_state(void *data,
struct input_method_context *context,
uint32_t serial)
{
struct virtual_keyboard *keyboard = data;
const struct layout *layout;
keyboard->serial = serial;
layout = get_current_layout(keyboard);
if (keyboard->surrounding_text)
@ -670,15 +666,14 @@ static const struct input_method_context_listener input_method_context_listener
handle_reset,
handle_content_type,
handle_invoke_action,
handle_commit,
handle_commit_state,
handle_preferred_language
};
static void
input_method_activate(void *data,
struct input_method *input_method,
struct input_method_context *context,
uint32_t serial)
struct input_method_context *context)
{
struct virtual_keyboard *keyboard = data;
struct wl_array modifiers_map;
@ -700,7 +695,7 @@ input_method_activate(void *data,
free(keyboard->surrounding_text);
keyboard->surrounding_text = NULL;
keyboard->serial = serial;
keyboard->serial = 0;
keyboard->context = context;
input_method_context_add_listener(context,

View file

@ -112,16 +112,13 @@ handle_surrounding_text(void *data,
static void
handle_reset(void *data,
struct input_method_context *context,
uint32_t serial)
struct input_method_context *context)
{
struct simple_im *keyboard = data;
fprintf(stderr, "Reset pre-edit buffer\n");
keyboard->compose_state = state_normal;
keyboard->serial = serial;
}
static void
@ -141,9 +138,13 @@ handle_invoke_action(void *data,
}
static void
handle_commit(void *data,
struct input_method_context *context)
handle_commit_state(void *data,
struct input_method_context *context,
uint32_t serial)
{
struct simple_im *keyboard = data;
keyboard->serial = serial;
}
static void
@ -158,7 +159,7 @@ static const struct input_method_context_listener input_method_context_listener
handle_reset,
handle_content_type,
handle_invoke_action,
handle_commit,
handle_commit_state,
handle_preferred_language
};
@ -285,8 +286,7 @@ static const struct wl_keyboard_listener input_method_keyboard_listener = {
static void
input_method_activate(void *data,
struct input_method *input_method,
struct input_method_context *context,
uint32_t serial)
struct input_method_context *context)
{
struct simple_im *keyboard = data;
@ -295,7 +295,7 @@ input_method_activate(void *data,
keyboard->compose_state = state_normal;
keyboard->serial = serial;
keyboard->serial = 0;
keyboard->context = context;
input_method_context_add_listener(context,
@ -396,7 +396,7 @@ simple_im_key_handler(struct simple_im *keyboard,
for (i = 0; i < sizeof(ignore_keys_on_compose) / sizeof(ignore_keys_on_compose[0]); i++) {
if (sym == ignore_keys_on_compose[i]) {
input_method_context_key(context, serial, time, key, state);
input_method_context_key(context, keyboard->serial, time, key, state);
return;
}
}
@ -412,13 +412,11 @@ simple_im_key_handler(struct simple_im *keyboard,
if (cs) {
if (cs->keys[i + 1] == 0) {
input_method_context_preedit_cursor(keyboard->context,
keyboard->serial,
0);
input_method_context_preedit_string(keyboard->context,
keyboard->serial,
"", "");
input_method_context_cursor_position(keyboard->context,
keyboard->serial,
0, 0);
input_method_context_commit_string(keyboard->context,
keyboard->serial,
@ -432,7 +430,6 @@ simple_im_key_handler(struct simple_im *keyboard,
}
input_method_context_preedit_cursor(keyboard->context,
keyboard->serial,
strlen(text));
input_method_context_preedit_string(keyboard->context,
keyboard->serial,
@ -446,13 +443,11 @@ simple_im_key_handler(struct simple_im *keyboard,
idx += xkb_keysym_to_utf8(keyboard->compose_seq.keys[j], text + idx, sizeof(text) - idx);
}
input_method_context_preedit_cursor(keyboard->context,
keyboard->serial,
0);
input_method_context_preedit_string(keyboard->context,
keyboard->serial,
"", "");
input_method_context_cursor_position(keyboard->context,
keyboard->serial,
0, 0);
input_method_context_commit_string(keyboard->context,
keyboard->serial,
@ -471,7 +466,6 @@ simple_im_key_handler(struct simple_im *keyboard,
return;
input_method_context_cursor_position(keyboard->context,
keyboard->serial,
0, 0);
input_method_context_commit_string(keyboard->context,
keyboard->serial,

View file

@ -33,6 +33,13 @@
receive information about the text model from the application via events.
Input method contexts do not keep state after deactivation and should be
destroyed after deactivation is handled.
Serials are used to synchronize the state between the text input and
an input method. New serials are sent by the text input in the
commit_state request and are used by the input method to indicate
the known text input state in events like preedit_string, commit_string,
and keysym. The text input can then ignore events from the input method
which are based on an outdated state (for example after a reset).
</description>
<request name="destroy" type="destructor"/>
<request name="commit_string">
@ -63,7 +70,6 @@
This request should be sent before sending preedit_string request.
</description>
<arg name="serial" type="uint"/>
<arg name="index" type="uint"/>
<arg name="length" type="uint"/>
<arg name="style" type="uint"/>
@ -75,16 +81,13 @@
This request should be sent before sending preedit_string request.
</description>
<arg name="serial" type="uint"/>
<arg name="index" type="int"/>
</request>
<request name="delete_surrounding_text">
<arg name="serial" type="uint"/>
<arg name="index" type="int"/>
<arg name="length" type="uint"/>
</request>
<request name="cursor_position">
<arg name="serial" type="uint"/>
<arg name="index" type="int"/>
<arg name="anchor" type="int"/>
</request>
@ -147,7 +150,6 @@
<arg name="anchor" type="uint"/>
</event>
<event name="reset">
<arg name="serial" type="uint"/>
</event>
<event name="content_type">
<arg name="hint" type="uint"/>
@ -157,7 +159,9 @@
<arg name="button" type="uint"/>
<arg name="index" type="uint"/>
</event>
<event name="commit"/>
<event name="commit_state">
<arg name="serial" type="uint"/>
</event>
<event name="preferred_language">
<arg name="language" type="string"/>
</event>
@ -176,7 +180,6 @@
which allows communication with the text model.
</description>
<arg name="id" type="new_id" interface="input_method_context"/>
<arg name="serial" type="uint"/>
</event>
<event name="deactivate">
<description summary="activate event">

View file

@ -2,7 +2,7 @@
<protocol name="text">
<copyright>
Copyright © 2012 Intel Corporation
Copyright © 2012, 2013 Intel Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
@ -38,6 +38,13 @@
the pre-edit and commit events. Using this interface removes the need
for applications to directly process hardware key events and compose text
out of them.
Serials are used to synchronize the state between the text input and
an input method. New serials are sent by the text input in the
commit_state request and are used by the input method to indicate
the known text input state in events like preedit_string, commit_string,
and keysym. The text input can then ignore events from the input method
which are based on an outdated state (for example after a reset).
</description>
<request name="activate">
<description summary="request activation">
@ -48,7 +55,6 @@
text-input object and tracked for focus lost. The enter event
is emitted on successful activation.
</description>
<arg name="serial" type="uint"/>
<arg name="seat" type="object" interface="wl_seat"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
@ -76,7 +82,6 @@
reset, for example after the text was changed outside of the normal
input method flow.
</description>
<arg name="serial" type="uint"/>
</request>
<request name="set_surrounding_text">
<description summary="sets the surrounding text">
@ -162,6 +167,7 @@
<arg name="language" type="string"/>
</request>
<request name="commit_state">
<arg name="serial" type="uint" summary="used to identify the known state"/>
</request>
<request name="invoke_action">
<arg name="button" type="uint"/>
@ -204,7 +210,7 @@
The commit text can be used to replace the preedit text on reset
(for example on unfocus).
</description>
<arg name="serial" type="uint"/>
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
<arg name="text" type="string"/>
<arg name="commit" type="string"/>
</event>
@ -228,7 +234,6 @@
This event should be handled as part of a following preedit_string
event.
</description>
<arg name="serial" type="uint"/>
<arg name="index" type="uint"/>
<arg name="length" type="uint"/>
<arg name="style" type="uint"/>
@ -241,7 +246,6 @@
This event should be handled as part of a following preedit_string
event.
</description>
<arg name="serial" type="uint"/>
<arg name="index" type="int"/>
</event>
<event name="commit_string">
@ -253,7 +257,7 @@
Any previously set composing text should be removed.
</description>
<arg name="serial" type="uint"/>
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
<arg name="text" type="string"/>
</event>
<event name="cursor_position">
@ -261,7 +265,6 @@
Notify when the cursor or anchor position should be modified. It
should take effect after the next commit_string event.
</description>
<arg name="serial" type="uint"/>
<arg name="index" type="int"/>
<arg name="anchor" type="int"/>
</event>
@ -271,7 +274,6 @@
deleted. Index is relative to the current cursor (as byte index).
Length is the length of deleted text (in bytes).
</description>
<arg name="serial" type="uint"/>
<arg name="index" type="int"/>
<arg name="length" type="uint"/>
</event>
@ -284,7 +286,7 @@
wl_keyboard key_state. Modifiers are a mask for effective modifiers
(where the modifier indices are set by the modifiers_map event)
</description>
<arg name="serial" type="uint"/>
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
<arg name="time" type="uint"/>
<arg name="sym" type="uint"/>
<arg name="state" type="uint"/>
@ -295,7 +297,7 @@
Sets the language of the input text. The "language" argument is a RFC-3066
format language tag.
</description>
<arg name="serial" type="uint"/>
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
<arg name="language" type="string"/>
</event>
<enum name="text_direction">
@ -311,7 +313,7 @@
editor when there is no input yet done and making sure neutral
direction text is laid out properly.
</description>
<arg name="serial" type="uint"/>
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
<arg name="direction" type="uint"/>
</event>
</interface>

View file

@ -98,8 +98,7 @@ struct text_backend {
};
static void input_method_context_create(struct text_input *model,
struct input_method *input_method,
uint32_t serial);
struct input_method *input_method);
static void input_method_context_end_keyboard_grab(struct input_method_context *context);
static void input_method_init_seat(struct weston_seat *seat);
@ -161,7 +160,6 @@ text_input_set_surrounding_text(struct wl_client *client,
static void
text_input_activate(struct wl_client *client,
struct wl_resource *resource,
uint32_t serial,
struct wl_resource *seat,
struct wl_resource *surface)
{
@ -185,7 +183,7 @@ text_input_activate(struct wl_client *client,
text_input->surface = surface->data;
input_method_context_create(text_input, input_method, serial);
input_method_context_create(text_input, input_method);
if (text_input->input_panel_visible) {
wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
@ -209,8 +207,7 @@ text_input_deactivate(struct wl_client *client,
static void
text_input_reset(struct wl_client *client,
struct wl_resource *resource,
uint32_t serial)
struct wl_resource *resource)
{
struct text_input *text_input = resource->data;
struct input_method *input_method, *next;
@ -218,7 +215,7 @@ text_input_reset(struct wl_client *client,
wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
if (!input_method->context)
continue;
input_method_context_send_reset(&input_method->context->resource, serial);
input_method_context_send_reset(&input_method->context->resource);
}
}
@ -275,7 +272,8 @@ text_input_invoke_action(struct wl_client *client,
static void
text_input_commit_state(struct wl_client *client,
struct wl_resource *resource)
struct wl_resource *resource,
uint32_t serial)
{
struct text_input *text_input = resource->data;
struct input_method *input_method, *next;
@ -283,7 +281,7 @@ text_input_commit_state(struct wl_client *client,
wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
if (!input_method->context)
continue;
input_method_context_send_commit(&input_method->context->resource);
input_method_context_send_commit_state(&input_method->context->resource, serial);
}
}
@ -451,49 +449,45 @@ input_method_context_preedit_string(struct wl_client *client,
static void
input_method_context_preedit_styling(struct wl_client *client,
struct wl_resource *resource,
uint32_t serial,
uint32_t index,
uint32_t length,
uint32_t style)
{
struct input_method_context *context = resource->data;
text_input_send_preedit_styling(&context->model->resource, serial, index, length, style);
text_input_send_preedit_styling(&context->model->resource, index, length, style);
}
static void
input_method_context_preedit_cursor(struct wl_client *client,
struct wl_resource *resource,
uint32_t serial,
int32_t cursor)
{
struct input_method_context *context = resource->data;
text_input_send_preedit_cursor(&context->model->resource, serial, cursor);
text_input_send_preedit_cursor(&context->model->resource, cursor);
}
static void
input_method_context_delete_surrounding_text(struct wl_client *client,
struct wl_resource *resource,
uint32_t serial,
int32_t index,
uint32_t length)
{
struct input_method_context *context = resource->data;
text_input_send_delete_surrounding_text(&context->model->resource, serial, index, length);
text_input_send_delete_surrounding_text(&context->model->resource, index, length);
}
static void
input_method_context_cursor_position(struct wl_client *client,
struct wl_resource *resource,
uint32_t serial,
int32_t index,
int32_t anchor)
{
struct input_method_context *context = resource->data;
text_input_send_cursor_position(&context->model->resource, serial, index, anchor);
text_input_send_cursor_position(&context->model->resource, index, anchor);
}
static void
@ -687,8 +681,7 @@ destroy_input_method_context(struct wl_resource *resource)
static void
input_method_context_create(struct text_input *model,
struct input_method *input_method,
uint32_t serial)
struct input_method *input_method)
{
struct input_method_context *context;
@ -713,7 +706,7 @@ input_method_context_create(struct text_input *model,
wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
input_method_send_activate(input_method->input_method_binding, &context->resource, serial);
input_method_send_activate(input_method->input_method_binding, &context->resource);
}
static void

View file

@ -51,7 +51,6 @@ text_input_preedit_string(void *data,
static void
text_input_delete_surrounding_text(void *data,
struct text_input *text_input,
uint32_t serial,
int32_t index,
uint32_t length)
{
@ -60,7 +59,6 @@ text_input_delete_surrounding_text(void *data,
static void
text_input_cursor_position(void *data,
struct text_input *text_input,
uint32_t serial,
int32_t index,
int32_t anchor)
{
@ -69,7 +67,6 @@ text_input_cursor_position(void *data,
static void
text_input_preedit_styling(void *data,
struct text_input *text_input,
uint32_t serial,
uint32_t index,
uint32_t length,
uint32_t style)
@ -79,7 +76,6 @@ text_input_preedit_styling(void *data,
static void
text_input_preedit_cursor(void *data,
struct text_input *text_input,
uint32_t serial,
int32_t index)
{
}
@ -195,7 +191,7 @@ TEST(text_test)
assert(client->input->keyboard->focus == client->surface);
/* Activate test model and make sure we get enter event. */
text_input_activate(text_input, 0, client->input->wl_seat,
text_input_activate(text_input, client->input->wl_seat,
client->surface->wl_surface);
client_roundtrip(client);
assert(state.activated == 1 && state.deactivated == 0);
@ -206,7 +202,7 @@ TEST(text_test)
assert(state.activated == 1 && state.deactivated == 1);
/* Activate test model again. */
text_input_activate(text_input, 0, client->input->wl_seat,
text_input_activate(text_input, client->input->wl_seat,
client->surface->wl_surface);
client_roundtrip(client);
assert(state.activated == 2 && state.deactivated == 1);