[PATCH v2 09/17] editor: Add support for selection

Jan Arne Petersen jpetersen at openismus.com
Sun Sep 9 14:08:38 PDT 2012


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

Make it possible to select text and render the selection to the editor
example.

Signed-off-by: Jan Arne Petersen <jpetersen at openismus.com>
---
 clients/editor.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/clients/editor.c b/clients/editor.c
index 295018a..3056bdc 100644
--- a/clients/editor.c
+++ b/clients/editor.c
@@ -50,6 +50,7 @@ struct text_entry {
 	char *text;
 	int active;
 	uint32_t cursor;
+	uint32_t anchor;
 	struct text_model *model;
 	struct text_layout *layout;
 };
@@ -309,6 +310,7 @@ text_entry_create(struct editor *editor, const char *text)
 	entry->text = strdup(text);
 	entry->active = 0;
 	entry->cursor = strlen(text);
+	entry->anchor = entry->cursor;
 	entry->model = text_model_factory_create_text_model(editor->text_model_factory);
 	text_model_add_listener(entry->model, &text_model_listener, entry);
 
@@ -418,6 +420,7 @@ 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);
 
 	text_layout_set_text(entry->layout, entry->text);
 }
@@ -432,6 +435,50 @@ text_entry_set_cursor_position(struct text_entry *entry,
 }
 
 static void
+text_entry_set_anchor_position(struct text_entry *entry,
+			       int32_t x, int32_t y)
+{
+	entry->anchor = text_layout_xy_to_index(entry->layout, x, y);
+
+	widget_schedule_redraw(entry->widget);
+}
+
+static void
+text_entry_draw_selection(struct text_entry *entry, cairo_t *cr)
+{
+	cairo_text_extents_t extents;
+	uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
+	uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
+	cairo_rectangle_t start;
+	cairo_rectangle_t end;
+
+	if (entry->anchor == entry->cursor)
+		return;
+
+	text_layout_extents(entry->layout, &extents);
+
+	text_layout_index_to_pos(entry->layout, start_index, &start);
+	text_layout_index_to_pos(entry->layout, end_index, &end);
+
+	cairo_save (cr);
+
+	cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
+	cairo_rectangle(cr,
+			start.x, extents.y_bearing + extents.height + 2,
+			end.x - start.x, -extents.height - 4);
+	cairo_fill(cr);
+
+	cairo_rectangle(cr,
+			start.x, extents.y_bearing + extents.height,
+			end.x - start.x, -extents.height);
+	cairo_clip(cr);
+	cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
+	text_layout_draw(entry->layout, cr);
+
+	cairo_restore (cr);
+}
+
+static void
 text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
 {
 	cairo_text_extents_t extents;
@@ -484,6 +531,8 @@ text_entry_redraw_handler(struct widget *widget, void *data)
 	cairo_translate(cr, 10, allocation.height / 2);
 	text_layout_draw(entry->layout, cr);
 
+	text_entry_draw_selection(entry, cr);
+
 	text_entry_draw_cursor(entry, cr);
 
 	cairo_pop_group_to_source(cr);
@@ -493,6 +542,23 @@ text_entry_redraw_handler(struct widget *widget, void *data)
 	cairo_surface_destroy(surface);
 }
 
+static int
+text_entry_motion_handler(struct widget *widget,
+			  struct input *input, uint32_t time,
+			  float x, float y, void *data)
+{
+	struct text_entry *entry = data;
+	struct rectangle allocation;
+
+	widget_get_allocation(entry->widget, &allocation);
+
+	text_entry_set_cursor_position(entry,
+				       x - allocation.x,
+				       y - allocation.y);
+
+	return CURSOR_IBEAM;
+}
+
 static void
 text_entry_button_handler(struct widget *widget,
 			  struct input *input, uint32_t time,
@@ -510,7 +576,7 @@ text_entry_button_handler(struct widget *widget,
 		return;
 	}
 
-	text_entry_set_cursor_position(entry, 
+	text_entry_set_cursor_position(entry,
 				       x - allocation.x,
 				       y - allocation.y);
 
@@ -518,6 +584,14 @@ text_entry_button_handler(struct widget *widget,
 		struct wl_seat *seat = input_get_seat(input);
 
 		text_entry_activate(entry, seat);
+
+		text_entry_set_anchor_position(entry,
+					       x - allocation.x,
+					       y - allocation.y);
+
+		widget_set_motion_handler(entry->widget, text_entry_motion_handler);
+	} else {
+		widget_set_motion_handler(entry->widget, NULL);
 	}
 }
 
-- 
1.7.11.4



More information about the wayland-devel mailing list