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>
This commit is contained in:
committed by
Kristian Høgsberg
parent
18639f8d4a
commit
4653531e7a
+45
-28
@@ -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,10 +361,23 @@ 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
|
||||||
text_model_modifiers_map(void *data,
|
text_model_modifiers_map(void *data,
|
||||||
struct text_model *text_model,
|
struct text_model *text_model,
|
||||||
@@ -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);
|
||||||
|
|||||||
+12
-4
@@ -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"/>
|
||||||
|
|||||||
+23
-3
@@ -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
|
||||||
|
|||||||
+28
-4
@@ -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;
|
struct input_method_context *context = resource->data;
|
||||||
|
|
||||||
text_model_send_preedit_string(&context->model->resource, text, index);
|
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_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,
|
||||||
|
|||||||
Reference in New Issue
Block a user