[PATCH 5/5] text: Split out cursor_position

Jan Arne Petersen jpetersen at openismus.com
Thu Jan 31 06:52:23 PST 2013


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

Add an extra cursor_position, which also allows to change the anchor
(for slections). Change the index type to int to allow setting it before
the beginning of a commited string.

The cursor should not be moved as a direct repsonse to this event but
atomically on the next commit_string event.

Signed-off-by: Jan Arne Petersen <jpetersen at openismus.com>
---
 clients/editor.c           | 50 +++++++++++++++++++++++++++++++++++-----------
 clients/keyboard.c         |  6 ++++--
 clients/weston-simple-im.c | 18 +++++++++++------
 protocol/input-method.xml  |  6 +++++-
 protocol/text.xml          | 10 +++++++++-
 src/text-backend.c         | 18 ++++++++++++++---
 6 files changed, 83 insertions(+), 25 deletions(-)

diff --git a/clients/editor.c b/clients/editor.c
index a830ead..32c3f9b 100644
--- a/clients/editor.c
+++ b/clients/editor.c
@@ -53,6 +53,10 @@ struct text_entry {
 		PangoAttrList *attr_list;
 		int32_t cursor;
 	} preedit_info;
+	struct {
+		int32_t cursor;
+		int32_t anchor;
+	} pending_commit;
 	struct text_model *model;
 	PangoLayout *layout;
 	struct {
@@ -112,7 +116,8 @@ static void text_entry_button_handler(struct widget *widget,
 				      struct input *input, uint32_t time,
 				      uint32_t button,
 				      enum wl_pointer_button_state state, void *data);
-static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text);
+static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
+					int32_t cursor, int32_t anchor);
 static void text_entry_set_preedit(struct text_entry *entry,
 				   const char *preedit_text,
 				   int preedit_cursor);
@@ -126,18 +131,18 @@ static void
 text_model_commit_string(void *data,
 			 struct text_model *text_model,
 			 uint32_t serial,
-			 const char *text,
-			 uint32_t index)
+			 const char *text)
 {
 	struct text_entry *entry = data;
 
-	if (index > strlen(text))
-		fprintf(stderr, "Invalid cursor index %d\n", index);
-
 	text_entry_reset_preedit(entry);
 
 	text_entry_delete_selected_text(entry);
-	text_entry_insert_at_cursor(entry, text);
+	text_entry_insert_at_cursor(entry, text,
+				    entry->pending_commit.cursor,
+				    entry->pending_commit.anchor);
+
+	memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
 
 	widget_schedule_redraw(entry->widget);
 }
@@ -195,6 +200,19 @@ text_model_delete_surrounding_text(void *data,
 }
 
 static void
+text_model_cursor_position(void *data,
+			   struct text_model *text_model,
+			   uint32_t serial,
+			   int32_t index,
+			   int32_t anchor)
+{
+	struct text_entry *entry = data;
+
+	entry->pending_commit.cursor = index;
+	entry->pending_commit.anchor = anchor;
+}
+
+static void
 text_model_preedit_styling(void *data,
 			   struct text_model *text_model,
 			   uint32_t serial,
@@ -377,6 +395,7 @@ static const struct text_model_listener text_model_listener = {
 	text_model_commit_string,
 	text_model_preedit_string,
 	text_model_delete_surrounding_text,
+	text_model_cursor_position,
 	text_model_preedit_styling,
 	text_model_preedit_cursor,
 	text_model_modifiers_map,
@@ -583,7 +602,8 @@ text_entry_update(struct text_entry *entry)
 }
 
 static void
-text_entry_insert_at_cursor(struct text_entry *entry, const char *text)
+text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
+			    int32_t cursor, int32_t anchor)
 {
 	char *new_text = malloc(strlen(entry->text) + strlen(text) + 1);
 
@@ -594,8 +614,14 @@ text_entry_insert_at_cursor(struct text_entry *entry, const char *text)
 
 	free(entry->text);
 	entry->text = new_text;
-	entry->cursor += strlen(text);
-	entry->anchor += strlen(text);
+	if (anchor >= 0)
+		entry->anchor = entry->cursor + strlen(text) + anchor;
+	else
+		entry->anchor = entry->cursor + 1 + anchor;
+	if (cursor >= 0)
+		entry->cursor += strlen(text) + cursor;
+	else
+		entry->cursor += 1 + cursor;
 
 	text_entry_update_layout(entry);
 
@@ -629,7 +655,7 @@ text_entry_commit_and_reset(struct text_entry *entry)
 
 	text_entry_reset_preedit(entry);
 	if (commit) {
-		text_entry_insert_at_cursor(entry, commit);
+		text_entry_insert_at_cursor(entry, commit, 0, 0);
 		free(commit);
 	}
 }
@@ -993,7 +1019,7 @@ key_handler(struct window *window,
 
 			text_entry_commit_and_reset(entry);
 
-			text_entry_insert_at_cursor(entry, text);
+			text_entry_insert_at_cursor(entry, text, 0, 0);
 			break;
 	}
 
diff --git a/clients/keyboard.c b/clients/keyboard.c
index 8d94870..3760ff7 100644
--- a/clients/keyboard.c
+++ b/clients/keyboard.c
@@ -321,10 +321,12 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
 					    keyboard->serial,
 					    "",
 					    "");
+	input_method_context_cursor_position(keyboard->context,
+					     keyboard->serial,
+					     0, 0);
 	input_method_context_commit_string(keyboard->context,
 					   keyboard->serial,
-					   keyboard->preedit_string,
-					   strlen(keyboard->preedit_string));
+					   keyboard->preedit_string);
 	free(keyboard->preedit_string);
 	keyboard->preedit_string = strdup("");
 }
diff --git a/clients/weston-simple-im.c b/clients/weston-simple-im.c
index fab7fc5..e955d3c 100644
--- a/clients/weston-simple-im.c
+++ b/clients/weston-simple-im.c
@@ -409,10 +409,12 @@ simple_im_key_handler(struct simple_im *keyboard,
 				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,
-								   cs->text,
-								   strlen(cs->text));
+								   cs->text);
 				keyboard->compose_state = state_normal;
 			} else {
 				uint32_t j = 0, idx = 0;
@@ -441,10 +443,12 @@ simple_im_key_handler(struct simple_im *keyboard,
 			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,
-							   text,
-							   strlen(text));
+							   text);
 			keyboard->compose_state = state_normal;
 		}
 		return;
@@ -458,10 +462,12 @@ simple_im_key_handler(struct simple_im *keyboard,
 	if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
 		return;
 
+	input_method_context_cursor_position(keyboard->context,
+					     keyboard->serial,
+					     0, 0);
 	input_method_context_commit_string(keyboard->context,
 					   keyboard->serial,
-					   text,
-					   strlen(text));
+					   text);
 }
 
 int
diff --git a/protocol/input-method.xml b/protocol/input-method.xml
index 690aee1..a59201b 100644
--- a/protocol/input-method.xml
+++ b/protocol/input-method.xml
@@ -41,7 +41,6 @@
       </description>
       <arg name="serial" type="uint"/>
       <arg name="text" type="string"/>
-      <arg name="index" type="uint"/>
     </request>
     <request name="preedit_string">
       <description summary="pre-edit string">
@@ -70,6 +69,11 @@
       <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>
     <request name="modifiers_map">
       <arg name="map" type="array"/>
     </request>
diff --git a/protocol/text.xml b/protocol/text.xml
index 749c8c2..28d12ed 100644
--- a/protocol/text.xml
+++ b/protocol/text.xml
@@ -161,7 +161,6 @@
       </description>
       <arg name="serial" type="uint"/>
       <arg name="text" type="string"/>
-      <arg name="index" type="uint"/>
     </event>
     <event name="preedit_string">
       <description summary="pre-edit">
@@ -186,6 +185,15 @@
       <arg name="index" type="int"/>
       <arg name="length" type="uint"/>
     </event>
+    <event name="cursor_position">
+      <description summary="set cursor to new position">
+        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>
     <enum name="preedit_style">
       <entry name="default" value="1"/>
       <entry name="active" value="2"/>
diff --git a/src/text-backend.c b/src/text-backend.c
index 00ca46e..a92aebe 100644
--- a/src/text-backend.c
+++ b/src/text-backend.c
@@ -397,12 +397,11 @@ static void
 input_method_context_commit_string(struct wl_client *client,
 				   struct wl_resource *resource,
 				   uint32_t serial,
-				   const char *text,
-				   uint32_t index)
+				   const char *text)
 {
 	struct input_method_context *context = resource->data;
 
-	text_model_send_commit_string(&context->model->resource, serial, text, index);
+	text_model_send_commit_string(&context->model->resource, serial, text);
 }
 
 static void
@@ -454,6 +453,18 @@ input_method_context_delete_surrounding_text(struct wl_client *client,
 }
 
 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_model_send_cursor_position(&context->model->resource, serial, index, anchor);
+}
+
+static void
 input_method_context_modifiers_map(struct wl_client *client,
 				   struct wl_resource *resource,
 				   struct wl_array *map)
@@ -597,6 +608,7 @@ static const struct input_method_context_interface input_method_context_implemen
 	input_method_context_preedit_styling,
 	input_method_context_preedit_cursor,
 	input_method_context_delete_surrounding_text,
+	input_method_context_cursor_position,
 	input_method_context_modifiers_map,
 	input_method_context_keysym,
 	input_method_context_grab_keyboard,
-- 
1.8.1



More information about the wayland-devel mailing list