text: add pre-edit styling support to protocol

Also add a separate preedit-cursor event and add a commit argument to
preedit-string to allow to support commit on reset. Fix editor and
keyboard example to adapt to the protocol changes.

Signed-off-by: Jan Arne Petersen <jpetersen@openismus.com>
Jan Arne Petersen 12 years ago committed by Kristian Høgsberg
parent 18639f8d4a
commit 4653531e7a
  1. 73
      clients/editor.c
  2. 16
      clients/keyboard.c
  3. 12
      clients/weston-simple-im.c
  4. 12
      protocol/input-method.xml
  5. 26
      protocol/text.xml
  6. 32
      src/text-backend.c

@ -51,8 +51,14 @@ struct text_entry {
int active; int active;
uint32_t cursor; uint32_t cursor;
uint32_t anchor; uint32_t anchor;
char *preedit_text; struct {
uint32_t preedit_cursor; char *text;
int32_t cursor;
char *commit;
} preedit;
struct {
int32_t cursor;
} preedit_info;
struct text_model *model; struct text_model *model;
struct text_layout *layout; struct text_layout *layout;
struct { struct {
@ -312,17 +318,12 @@ static void
text_model_preedit_string(void *data, text_model_preedit_string(void *data,
struct text_model *text_model, struct text_model *text_model,
const char *text, const char *text,
uint32_t index) const char *commit)
{ {
struct text_entry *entry = data; struct text_entry *entry = data;
if (index > strlen(text)) {
fprintf(stderr, "Invalid cursor index %d\n", index);
index = strlen(text);
}
text_entry_delete_selected_text(entry); text_entry_delete_selected_text(entry);
text_entry_set_preedit(entry, text, index); text_entry_set_preedit(entry, text, entry->preedit_info.cursor);
widget_schedule_redraw(entry->widget); widget_schedule_redraw(entry->widget);
} }
@ -360,8 +361,21 @@ text_model_delete_surrounding_text(void *data,
static void static void
text_model_preedit_styling(void *data, text_model_preedit_styling(void *data,
struct text_model *text_model) struct text_model *text_model,
uint32_t index,
uint32_t length,
uint32_t style)
{
}
static void
text_model_preedit_cursor(void *data,
struct text_model *text_model,
int32_t index)
{ {
struct text_entry *entry = data;
entry->preedit_info.cursor = index;
} }
static void static void
@ -474,6 +488,7 @@ static const struct text_model_listener text_model_listener = {
text_model_preedit_string, text_model_preedit_string,
text_model_delete_surrounding_text, text_model_delete_surrounding_text,
text_model_preedit_styling, text_model_preedit_styling,
text_model_preedit_cursor,
text_model_modifiers_map, text_model_modifiers_map,
text_model_keysym, text_model_keysym,
text_model_selection_replacement, text_model_selection_replacement,
@ -496,8 +511,6 @@ text_entry_create(struct editor *editor, const char *text)
entry->active = 0; entry->active = 0;
entry->cursor = strlen(text); entry->cursor = strlen(text);
entry->anchor = entry->cursor; entry->anchor = entry->cursor;
entry->preedit_text = NULL;
entry->preedit_cursor = 0;
entry->model = text_model_factory_create_text_model(editor->text_model_factory); entry->model = text_model_factory_create_text_model(editor->text_model_factory);
text_model_add_listener(entry->model, &text_model_listener, entry); text_model_add_listener(entry->model, &text_model_listener, entry);
@ -600,17 +613,17 @@ text_entry_update_layout(struct text_entry *entry)
char *text; char *text;
assert(((unsigned int)entry->cursor) <= strlen(entry->text) + assert(((unsigned int)entry->cursor) <= strlen(entry->text) +
(entry->preedit_text ? strlen(entry->preedit_text) : 0)); (entry->preedit.text ? strlen(entry->preedit.text) : 0));
if (!entry->preedit_text) { if (!entry->preedit.text) {
text_layout_set_text(entry->layout, entry->text); text_layout_set_text(entry->layout, entry->text);
return; return;
} }
text = malloc(strlen(entry->text) + strlen(entry->preedit_text) + 1); text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1);
strncpy(text, entry->text, entry->cursor); strncpy(text, entry->text, entry->cursor);
strcpy(text + entry->cursor, entry->preedit_text); strcpy(text + entry->cursor, entry->preedit.text);
strcpy(text + entry->cursor + strlen(entry->preedit_text), strcpy(text + entry->cursor + strlen(entry->preedit.text),
entry->text + entry->cursor); entry->text + entry->cursor);
text_layout_set_text(entry->layout, text); text_layout_set_text(entry->layout, text);
@ -647,17 +660,17 @@ text_entry_set_preedit(struct text_entry *entry,
const char *preedit_text, const char *preedit_text,
int preedit_cursor) int preedit_cursor)
{ {
if (entry->preedit_text) { if (entry->preedit.text) {
free(entry->preedit_text); free(entry->preedit.text);
entry->preedit_text = NULL; entry->preedit.text = NULL;
entry->preedit_cursor = 0; entry->preedit.cursor = 0;
} }
if (!preedit_text) if (!preedit_text)
return; return;
entry->preedit_text = strdup(preedit_text); entry->preedit.text = strdup(preedit_text);
entry->preedit_cursor = preedit_cursor; entry->preedit.cursor = preedit_cursor;
text_entry_update_layout(entry); text_entry_update_layout(entry);
} }
@ -670,8 +683,9 @@ text_entry_set_cursor_position(struct text_entry *entry,
text_model_reset(entry->model); text_model_reset(entry->model);
if (entry->cursor >= entry->preedit_cursor) { if (entry->preedit.cursor > 0 &&
entry->cursor -= entry->preedit_cursor; entry->cursor >= (uint32_t)entry->preedit.cursor) {
entry->cursor -= entry->preedit.cursor;
} }
text_entry_update_layout(entry); text_entry_update_layout(entry);
@ -760,9 +774,12 @@ text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
cairo_text_extents_t extents; cairo_text_extents_t extents;
cairo_rectangle_t cursor_pos; cairo_rectangle_t cursor_pos;
if (entry->preedit.text && entry->preedit.cursor < 0)
return;
text_layout_extents(entry->layout, &extents); text_layout_extents(entry->layout, &extents);
text_layout_get_cursor_pos(entry->layout, text_layout_get_cursor_pos(entry->layout,
entry->cursor + entry->preedit_cursor, entry->cursor + entry->preedit.cursor,
&cursor_pos); &cursor_pos);
cairo_set_line_width(cr, 1.0); cairo_set_line_width(cr, 1.0);
@ -778,14 +795,14 @@ text_entry_draw_preedit(struct text_entry *entry, cairo_t *cr)
cairo_rectangle_t start; cairo_rectangle_t start;
cairo_rectangle_t end; cairo_rectangle_t end;
if (!entry->preedit_text) if (!entry->preedit.text)
return; return;
text_layout_extents(entry->layout, &extents); text_layout_extents(entry->layout, &extents);
text_layout_index_to_pos(entry->layout, entry->cursor, &start); text_layout_index_to_pos(entry->layout, entry->cursor, &start);
text_layout_index_to_pos(entry->layout, text_layout_index_to_pos(entry->layout,
entry->cursor + strlen(entry->preedit_text), entry->cursor + strlen(entry->preedit.text),
&end); &end);
cairo_save (cr); cairo_save (cr);

@ -226,9 +226,11 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
strlen(keyboard->preedit_string) == 0) strlen(keyboard->preedit_string) == 0)
return; return;
input_method_context_preedit_cursor(keyboard->context,
0);
input_method_context_preedit_string(keyboard->context, input_method_context_preedit_string(keyboard->context,
"", "",
0); "");
input_method_context_commit_string(keyboard->context, input_method_context_commit_string(keyboard->context,
keyboard->preedit_string, keyboard->preedit_string,
strlen(keyboard->preedit_string)); strlen(keyboard->preedit_string));
@ -250,9 +252,11 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string, keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string,
label); label);
input_method_context_preedit_cursor(keyboard->keyboard->context,
strlen(keyboard->keyboard->preedit_string));
input_method_context_preedit_string(keyboard->keyboard->context, input_method_context_preedit_string(keyboard->keyboard->context,
keyboard->keyboard->preedit_string, keyboard->keyboard->preedit_string,
strlen(keyboard->keyboard->preedit_string)); keyboard->keyboard->preedit_string);
break; break;
case keytype_backspace: case keytype_backspace:
if (state != WL_POINTER_BUTTON_STATE_PRESSED) if (state != WL_POINTER_BUTTON_STATE_PRESSED)
@ -263,9 +267,11 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
-1, 1); -1, 1);
} else { } else {
keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0'; keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0';
input_method_context_preedit_cursor(keyboard->keyboard->context,
strlen(keyboard->keyboard->preedit_string));
input_method_context_preedit_string(keyboard->keyboard->context, input_method_context_preedit_string(keyboard->keyboard->context,
keyboard->keyboard->preedit_string, keyboard->keyboard->preedit_string,
strlen(keyboard->keyboard->preedit_string)); keyboard->keyboard->preedit_string);
} }
break; break;
case keytype_enter: case keytype_enter:
@ -386,9 +392,11 @@ input_method_context_reset(void *data,
fprintf(stderr, "Reset pre-edit buffer\n"); fprintf(stderr, "Reset pre-edit buffer\n");
if (strlen(keyboard->preedit_string)) { if (strlen(keyboard->preedit_string)) {
input_method_context_preedit_cursor(context,
0);
input_method_context_preedit_string(context, input_method_context_preedit_string(context,
"", "",
0); "");
free(keyboard->preedit_string); free(keyboard->preedit_string);
keyboard->preedit_string = strdup(""); keyboard->preedit_string = strdup("");
} }

@ -370,8 +370,10 @@ simple_im_key_handler(struct simple_im *keyboard,
if (cs) { if (cs) {
if (cs->keys[i + 1] == 0) { if (cs->keys[i + 1] == 0) {
input_method_context_preedit_cursor(keyboard->context,
0);
input_method_context_preedit_string(keyboard->context, input_method_context_preedit_string(keyboard->context,
"", 0); "", "");
input_method_context_commit_string(keyboard->context, input_method_context_commit_string(keyboard->context,
cs->text, cs->text,
strlen(cs->text)); strlen(cs->text));
@ -383,9 +385,11 @@ simple_im_key_handler(struct simple_im *keyboard,
idx += xkb_keysym_to_utf8(cs->keys[j], text + idx, sizeof(text) - idx); idx += xkb_keysym_to_utf8(cs->keys[j], text + idx, sizeof(text) - idx);
} }
input_method_context_preedit_cursor(keyboard->context,
strlen(text));
input_method_context_preedit_string(keyboard->context, input_method_context_preedit_string(keyboard->context,
text, text,
strlen(text)); text);
} }
} else { } else {
uint32_t j = 0, idx = 0; uint32_t j = 0, idx = 0;
@ -393,8 +397,10 @@ simple_im_key_handler(struct simple_im *keyboard,
for (; j <= i; j++) { for (; j <= i; j++) {
idx += xkb_keysym_to_utf8(keyboard->compose_seq.keys[j], text + idx, sizeof(text) - idx); idx += xkb_keysym_to_utf8(keyboard->compose_seq.keys[j], text + idx, sizeof(text) - idx);
} }
input_method_context_preedit_cursor(keyboard->context,
0);
input_method_context_preedit_string(keyboard->context, input_method_context_preedit_string(keyboard->context,
"", 0); "", "");
input_method_context_commit_string(keyboard->context, input_method_context_commit_string(keyboard->context,
text, text,
strlen(text)); strlen(text));

@ -47,7 +47,19 @@
Send the pre-edit string text to the applications text model. Send the pre-edit string text to the applications text model.
</description> </description>
<arg name="text" type="string"/> <arg name="text" type="string"/>
<arg name="commit" type="string"/>
</request>
<request name="preedit_styling">
<arg name="index" type="uint"/> <arg name="index" type="uint"/>
<arg name="length" type="uint"/>
<arg name="style" type="uint"/>
</request>
<request name="preedit_cursor">
<description summary="pre-edit cursor">
Sets the cursor position inside the composing text (as byte index)
relative to the start of the composing text.
</description>
<arg name="index" type="int"/>
</request> </request>
<request name="delete_surrounding_text"> <request name="delete_surrounding_text">
<arg name="index" type="int"/> <arg name="index" type="int"/>

@ -73,7 +73,7 @@
be reseted, for example after the text was changed outside of the be reseted, for example after the text was changed outside of the
normal input method flow. normal input method flow.
</description> </description>
</request> </request>
<request name="set_micro_focus"> <request name="set_micro_focus">
<arg name="x" type="int"/> <arg name="x" type="int"/>
<arg name="y" type="int"/> <arg name="y" type="int"/>
@ -101,7 +101,7 @@
to the start of the composing text. to the start of the composing text.
</description> </description>
<arg name="text" type="string"/> <arg name="text" type="string"/>
<arg name="index" type="uint"/> <arg name="commit" type="string"/>
</event> </event>
<event name="delete_surrounding_text"> <event name="delete_surrounding_text">
<description summary="delete surrounding text"> <description summary="delete surrounding text">
@ -112,7 +112,27 @@
<arg name="index" type="int"/> <arg name="index" type="int"/>
<arg name="length" type="uint"/> <arg name="length" type="uint"/>
</event> </event>
<event name="preedit_styling"/> <enum name="preedit_style">
<entry name="default" value="1"/>
<entry name="active" value="2"/>
<entry name="inactive" value="3"/>
<entry name="highlight" value="4"/>
<entry name="underline" value="5"/>
<entry name="selection" value="6"/>
<entry name="incorrect" value="7"/>
</enum>
<event name="preedit_styling">
<arg name="index" type="uint"/>
<arg name="length" type="uint"/>
<arg name="style" type="uint"/>
</event>
<event name="preedit_cursor">
<description summary="pre-edit cursor">
Sets the cursor position inside the composing text (as byte index)
relative to the start of the composing text.
</description>
<arg name="index" type="int"/>
</event>
<event name="modifiers_map"> <event name="modifiers_map">
<description summary="modifiers map"> <description summary="modifiers map">
Transfer an array of 0-terminated modifiers names. The position in Transfer an array of 0-terminated modifiers names. The position in

@ -338,13 +338,35 @@ input_method_context_commit_string(struct wl_client *client,
static void static void
input_method_context_preedit_string(struct wl_client *client, input_method_context_preedit_string(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
const char *text, const char *text,
uint32_t index) const char *commit)
{
struct input_method_context *context = resource->data;
text_model_send_preedit_string(&context->model->resource, text, commit);
}
static void
input_method_context_preedit_styling(struct wl_client *client,
struct wl_resource *resource,
uint32_t index,
uint32_t length,
uint32_t style)
{
struct input_method_context *context = resource->data;
text_model_send_preedit_styling(&context->model->resource, index, length, style);
}
static void
input_method_context_preedit_cursor(struct wl_client *client,
struct wl_resource *resource,
int32_t cursor)
{ {
struct input_method_context *context = resource->data; struct input_method_context *context = resource->data;
text_model_send_preedit_string(&context->model->resource, text, index); text_model_send_preedit_cursor(&context->model->resource, cursor);
} }
static void static void
@ -495,6 +517,8 @@ static const struct input_method_context_interface input_method_context_implemen
input_method_context_destroy, input_method_context_destroy,
input_method_context_commit_string, input_method_context_commit_string,
input_method_context_preedit_string, input_method_context_preedit_string,
input_method_context_preedit_styling,
input_method_context_preedit_cursor,
input_method_context_delete_surrounding_text, input_method_context_delete_surrounding_text,
input_method_context_modifiers_map, input_method_context_modifiers_map,
input_method_context_keysym, input_method_context_keysym,

Loading…
Cancel
Save