[PATCH 01/18] text: add pre-edit styling support to protocol

Jan Arne Petersen jpetersen at openismus.com
Wed Jan 16 12:26:38 PST 2013


From: Jan Arne Petersen <jpetersen at openismus.com>

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 at openismus.com>
---
 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 b42b5a1..2198813 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 ff35617..a32cf60 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 36af095..acc7112 100644
--- a/clients/weston-simple-im.c
+++ b/clients/weston-simple-im.c
@@ -363,8 +363,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));
@@ -376,9 +378,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;
@@ -386,8 +390,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 487be0b..20d3667 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.
       </description>
       <arg name="text" type="string"/>
+      <arg name="commit" type="string"/>
+    </request>
+    <request name="preedit_styling">
       <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 name="delete_surrounding_text">
       <arg name="index" type="int"/>
diff --git a/protocol/text.xml b/protocol/text.xml
index 4701f7d..5efeec8 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.
       </description>
-     </request>
+    </request>
     <request name="set_micro_focus">
       <arg name="x" type="int"/>
       <arg name="y" type="int"/>
@@ -101,7 +101,7 @@
         to the start of the composing text.
       </description>
       <arg name="text" type="string"/>
-      <arg name="index" type="uint"/>
+      <arg name="commit" type="string"/>
     </event>
     <event name="delete_surrounding_text">
       <description summary="delete surrounding text">
@@ -112,7 +112,27 @@
       <arg name="index" type="int"/>
       <arg name="length" type="uint"/>
     </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">
       <description summary="modifiers map">
         Transfer an array of 0-terminated modifiers names. The position in
diff --git a/src/text-backend.c b/src/text-backend.c
index d123da9..7f8c16e 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,
-- 
1.8.1



More information about the wayland-devel mailing list