From 4653531e7a846abc5fee89a74f5edf3e1835fc5e Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Wed, 16 Jan 2013 21:26:38 +0100 Subject: [PATCH] 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 --- clients/editor.c | 73 +++++++++++++++++++++++--------------- clients/keyboard.c | 16 ++++++--- clients/weston-simple-im.c | 12 +++++-- protocol/input-method.xml | 12 +++++++ protocol/text.xml | 26 ++++++++++++-- src/text-backend.c | 32 ++++++++++++++--- 6 files changed, 129 insertions(+), 42 deletions(-) diff --git a/clients/editor.c b/clients/editor.c index b42b5a10..2198813a 100644 --- a/clients/editor.c +++ b/clients/editor.c @@ -51,8 +51,14 @@ struct text_entry { int active; uint32_t cursor; uint32_t anchor; - char *preedit_text; - uint32_t preedit_cursor; + struct { + char *text; + int32_t cursor; + char *commit; + } preedit; + struct { + int32_t cursor; + } preedit_info; struct text_model *model; struct text_layout *layout; struct { @@ -312,17 +318,12 @@ static void text_model_preedit_string(void *data, struct text_model *text_model, const char *text, - uint32_t index) + const char *commit) { 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_set_preedit(entry, text, index); + text_entry_set_preedit(entry, text, entry->preedit_info.cursor); widget_schedule_redraw(entry->widget); } @@ -360,8 +361,21 @@ text_model_delete_surrounding_text(void *data, static void 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 @@ -474,6 +488,7 @@ static const struct text_model_listener text_model_listener = { text_model_preedit_string, text_model_delete_surrounding_text, text_model_preedit_styling, + text_model_preedit_cursor, text_model_modifiers_map, text_model_keysym, text_model_selection_replacement, @@ -496,8 +511,6 @@ text_entry_create(struct editor *editor, const char *text) entry->active = 0; entry->cursor = strlen(text); entry->anchor = entry->cursor; - entry->preedit_text = NULL; - entry->preedit_cursor = 0; entry->model = text_model_factory_create_text_model(editor->text_model_factory); text_model_add_listener(entry->model, &text_model_listener, entry); @@ -600,17 +613,17 @@ text_entry_update_layout(struct text_entry *entry) char *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); 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); - strcpy(text + entry->cursor, entry->preedit_text); - strcpy(text + entry->cursor + strlen(entry->preedit_text), + strcpy(text + entry->cursor, entry->preedit.text); + strcpy(text + entry->cursor + strlen(entry->preedit.text), entry->text + entry->cursor); text_layout_set_text(entry->layout, text); @@ -647,17 +660,17 @@ text_entry_set_preedit(struct text_entry *entry, const char *preedit_text, int preedit_cursor) { - if (entry->preedit_text) { - free(entry->preedit_text); - entry->preedit_text = NULL; - entry->preedit_cursor = 0; + if (entry->preedit.text) { + free(entry->preedit.text); + entry->preedit.text = NULL; + entry->preedit.cursor = 0; } if (!preedit_text) return; - entry->preedit_text = strdup(preedit_text); - entry->preedit_cursor = preedit_cursor; + entry->preedit.text = strdup(preedit_text); + entry->preedit.cursor = preedit_cursor; text_entry_update_layout(entry); } @@ -670,8 +683,9 @@ text_entry_set_cursor_position(struct text_entry *entry, text_model_reset(entry->model); - if (entry->cursor >= entry->preedit_cursor) { - entry->cursor -= entry->preedit_cursor; + if (entry->preedit.cursor > 0 && + entry->cursor >= (uint32_t)entry->preedit.cursor) { + entry->cursor -= entry->preedit.cursor; } 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_rectangle_t cursor_pos; + if (entry->preedit.text && entry->preedit.cursor < 0) + return; + text_layout_extents(entry->layout, &extents); text_layout_get_cursor_pos(entry->layout, - entry->cursor + entry->preedit_cursor, + entry->cursor + entry->preedit.cursor, &cursor_pos); 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 end; - if (!entry->preedit_text) + if (!entry->preedit.text) return; 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 + strlen(entry->preedit_text), + entry->cursor + strlen(entry->preedit.text), &end); cairo_save (cr); diff --git a/clients/keyboard.c b/clients/keyboard.c index ff356171..a32cf60a 100644 --- a/clients/keyboard.c +++ b/clients/keyboard.c @@ -226,9 +226,11 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard) strlen(keyboard->preedit_string) == 0) return; + input_method_context_preedit_cursor(keyboard->context, + 0); input_method_context_preedit_string(keyboard->context, "", - 0); + ""); input_method_context_commit_string(keyboard->context, 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, label); + input_method_context_preedit_cursor(keyboard->keyboard->context, + strlen(keyboard->keyboard->preedit_string)); input_method_context_preedit_string(keyboard->keyboard->context, keyboard->keyboard->preedit_string, - strlen(keyboard->keyboard->preedit_string)); + keyboard->keyboard->preedit_string); break; case keytype_backspace: 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); } else { 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, keyboard->keyboard->preedit_string, - strlen(keyboard->keyboard->preedit_string)); + keyboard->keyboard->preedit_string); } break; case keytype_enter: @@ -386,9 +392,11 @@ input_method_context_reset(void *data, fprintf(stderr, "Reset pre-edit buffer\n"); if (strlen(keyboard->preedit_string)) { + input_method_context_preedit_cursor(context, + 0); input_method_context_preedit_string(context, "", - 0); + ""); free(keyboard->preedit_string); keyboard->preedit_string = strdup(""); } diff --git a/clients/weston-simple-im.c b/clients/weston-simple-im.c index 46887e81..1b6a3fd0 100644 --- a/clients/weston-simple-im.c +++ b/clients/weston-simple-im.c @@ -370,8 +370,10 @@ simple_im_key_handler(struct simple_im *keyboard, if (cs) { if (cs->keys[i + 1] == 0) { + input_method_context_preedit_cursor(keyboard->context, + 0); input_method_context_preedit_string(keyboard->context, - "", 0); + "", ""); input_method_context_commit_string(keyboard->context, 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); } + input_method_context_preedit_cursor(keyboard->context, + strlen(text)); input_method_context_preedit_string(keyboard->context, text, - strlen(text)); + text); } } else { uint32_t j = 0, idx = 0; @@ -393,8 +397,10 @@ simple_im_key_handler(struct simple_im *keyboard, for (; j <= i; j++) { 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, - "", 0); + "", ""); input_method_context_commit_string(keyboard->context, text, strlen(text)); diff --git a/protocol/input-method.xml b/protocol/input-method.xml index 487be0b7..20d36679 100644 --- a/protocol/input-method.xml +++ b/protocol/input-method.xml @@ -47,7 +47,19 @@ Send the pre-edit string text to the applications text model. + + + + + + + + + Sets the cursor position inside the composing text (as byte index) + relative to the start of the composing text. + + diff --git a/protocol/text.xml b/protocol/text.xml index 4701f7d0..5efeec8f 100644 --- a/protocol/text.xml +++ b/protocol/text.xml @@ -73,7 +73,7 @@ be reseted, for example after the text was changed outside of the normal input method flow. - + @@ -101,7 +101,7 @@ to the start of the composing text. - + @@ -112,7 +112,27 @@ - + + + + + + + + + + + + + + + + + Sets the cursor position inside the composing text (as byte index) + relative to the start of the composing text. + + + Transfer an array of 0-terminated modifiers names. The position in diff --git a/src/text-backend.c b/src/text-backend.c index d123da9c..7f8c16e0 100644 --- a/src/text-backend.c +++ b/src/text-backend.c @@ -338,13 +338,35 @@ input_method_context_commit_string(struct wl_client *client, static void input_method_context_preedit_string(struct wl_client *client, - struct wl_resource *resource, - const char *text, - uint32_t index) + struct wl_resource *resource, + const char *text, + 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; - text_model_send_preedit_string(&context->model->resource, text, index); + text_model_send_preedit_cursor(&context->model->resource, cursor); } static void @@ -495,6 +517,8 @@ static const struct input_method_context_interface input_method_context_implemen input_method_context_destroy, input_method_context_commit_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_modifiers_map, input_method_context_keysym,