summaryrefslogtreecommitdiff
path: root/clients
diff options
context:
space:
mode:
authorManuel Bachmann <manuel.bachmann@open.eurogiciel.org>2015-03-30 01:57:44 +0200
committerBryce Harrington <bryce@osg.samsung.com>2015-05-07 16:27:30 -0700
commit22f343017560764e82d63535fbf5617d999a4038 (patch)
tree0a1327072139599e27ed970a67eb113602ba2c4c /clients
parent71c9ac6c7f546f2a11d3c1ec60356a641a2781c9 (diff)
downloadweston-22f343017560764e82d63535fbf5617d999a4038.tar.gz
editor: implement Cut,Copy,Paste
weston-editor is the only stock client spawning the virtual keyboard ; which means it may be the only client able to obtain some special characters (depending on the user's keyboard layout). If we implement Cut, Copy and Paste, the user has now a way to copy such characters to other useful clients (such as weston-terminal). Plus, it demonstrates text data exchange between two clients of different nature. Functionality is implemented in a right-click menu and the Ctrl+Shift+X/C/V bindings, just as in weston-terminal. Signed-off-by: Manuel Bachmann <manuel.bachmann@open.eurogiciel.org> Reviewed-by: Bryce Harrington <bryce@osg.samsung.com> Tested-by: Bryce Harrington <bryce@osg.samsung.com>
Diffstat (limited to 'clients')
-rw-r--r--clients/editor.c169
1 files changed, 166 insertions, 3 deletions
diff --git a/clients/editor.c b/clients/editor.c
index 9299a050..29cab34a 100644
--- a/clients/editor.c
+++ b/clients/editor.c
@@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include <unistd.h>
#include <linux/input.h>
#include <cairo.h>
@@ -76,6 +77,8 @@ struct text_entry {
struct editor {
struct wl_text_input_manager *text_input_manager;
+ struct wl_data_source *selection;
+ char *selected_text;
struct display *display;
struct window *window;
struct widget *widget;
@@ -554,6 +557,128 @@ static const struct wl_text_input_listener text_input_listener = {
text_input_text_direction
};
+static void
+data_source_target(void *data,
+ struct wl_data_source *source, const char *mime_type)
+{
+}
+
+static void
+data_source_send(void *data,
+ struct wl_data_source *source,
+ const char *mime_type, int32_t fd)
+{
+ struct editor *editor = data;
+
+ write(fd, editor->selected_text, strlen(editor->selected_text) + 1);
+}
+
+static void
+data_source_cancelled(void *data, struct wl_data_source *source)
+{
+ wl_data_source_destroy(source);
+}
+
+static const struct wl_data_source_listener data_source_listener = {
+ data_source_target,
+ data_source_send,
+ data_source_cancelled
+};
+
+static void
+paste_func(void *buffer, size_t len,
+ int32_t x, int32_t y, void *data)
+{
+ struct editor *editor = data;
+ struct text_entry *entry = editor->active_entry;
+ char *pasted_text;
+
+ if (!entry)
+ return;
+
+ pasted_text = malloc(len + 1);
+ strncpy(pasted_text, buffer, len);
+ pasted_text[len] = '\0';
+
+ text_entry_insert_at_cursor(entry, pasted_text, 0, 0);
+
+ free(pasted_text);
+}
+
+static void
+editor_copy_cut(struct editor *editor, struct input *input, bool cut)
+{
+ struct text_entry *entry = editor->active_entry;
+
+ if (!entry)
+ return;
+
+ if (entry->cursor != entry->anchor) {
+ int start_index = MIN(entry->cursor, entry->anchor);
+ int end_index = MAX(entry->cursor, entry->anchor);
+ int len = end_index - start_index;
+
+ editor->selected_text = realloc(editor->selected_text, len + 1);
+ strncpy(editor->selected_text, &entry->text[start_index], len);
+ editor->selected_text[len] = '\0';
+
+ if (cut)
+ text_entry_delete_text(entry, start_index, len);
+
+ editor->selection =
+ display_create_data_source(editor->display);
+ wl_data_source_offer(editor->selection,
+ "text/plain;charset=utf-8");
+ wl_data_source_add_listener(editor->selection,
+ &data_source_listener, editor);
+ input_set_selection(input, editor->selection,
+ display_get_serial(editor->display));
+ }
+}
+
+static void
+editor_paste(struct editor *editor, struct input *input)
+{
+ input_receive_selection_data(input,
+ "text/plain;charset=utf-8",
+ paste_func, editor);
+}
+
+static void
+menu_func(void *data, struct input *input, int index)
+{
+ struct window *window = data;
+ struct editor *editor = window_get_user_data(window);
+
+ fprintf(stderr, "picked entry %d\n", index);
+
+ switch (index) {
+ case 0:
+ editor_copy_cut(editor, input, true);
+ break;
+ case 1:
+ editor_copy_cut(editor, input, false);
+ break;
+ case 2:
+ editor_paste(editor, input);
+ break;
+ }
+}
+
+static void
+show_menu(struct editor *editor, struct input *input, uint32_t time)
+{
+ int32_t x, y;
+ static const char *entries[] = {
+ "Cut", "Copy", "Paste"
+ };
+
+ input_get_position(input, &x, &y);
+ window_show_menu(editor->display, input, time, editor->window,
+ x + 10, y + 20, menu_func,
+ entries, ARRAY_LENGTH(entries));
+}
+
static struct text_entry*
text_entry_create(struct editor *editor, const char *text)
{
@@ -1123,13 +1248,18 @@ text_entry_button_handler(struct widget *widget,
editor = window_get_user_data(entry->window);
- if (button == BTN_LEFT) {
+ switch (button) {
+ case BTN_LEFT:
entry->button_pressed = (state == WL_POINTER_BUTTON_STATE_PRESSED);
-
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
input_grab(input, entry->widget, button);
else
input_ungrab(input);
+ break;
+ case BTN_RIGHT:
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED)
+ show_menu(editor, input, time);
+ break;
}
if (text_entry_has_preedit(entry)) {
@@ -1139,7 +1269,8 @@ text_entry_button_handler(struct widget *widget,
return;
}
- if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ button == BTN_LEFT) {
struct wl_seat *seat = input_get_seat(input);
text_entry_activate(entry, seat);
@@ -1216,6 +1347,25 @@ keyboard_focus_handler(struct window *window,
window_schedule_redraw(editor->window);
}
+static int
+handle_bound_key(struct editor *editor,
+ struct input *input, uint32_t sym, uint32_t time)
+{
+ switch (sym) {
+ case XKB_KEY_X:
+ editor_copy_cut(editor, input, true);
+ return 1;
+ case XKB_KEY_C:
+ editor_copy_cut(editor, input, false);
+ return 1;
+ case XKB_KEY_V:
+ editor_paste(editor, input);
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static void
key_handler(struct window *window,
struct input *input, uint32_t time,
@@ -1226,6 +1376,7 @@ key_handler(struct window *window,
struct text_entry *entry;
const char *new_char;
char text[16];
+ uint32_t modifiers;
if (!editor->active_entry)
return;
@@ -1235,6 +1386,12 @@ key_handler(struct window *window,
if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
return;
+ modifiers = input_get_modifiers(input);
+ if ((modifiers & MOD_CONTROL_MASK) &&
+ (modifiers & MOD_SHIFT_MASK) &&
+ handle_bound_key(editor, input, sym, time))
+ return;
+
switch (sym) {
case XKB_KEY_BackSpace:
text_entry_commit_and_reset(entry);
@@ -1374,6 +1531,8 @@ main(int argc, char *argv[])
editor.editor = text_entry_create(&editor, "Numeric");
editor.editor->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
editor.editor->click_to_show = click_to_show;
+ editor.selection = NULL;
+ editor.selected_text = NULL;
window_set_title(editor.window, "Text Editor");
window_set_key_handler(editor.window, key_handler);
@@ -1390,6 +1549,10 @@ main(int argc, char *argv[])
display_run(editor.display);
+ if (editor.selected_text)
+ free(editor.selected_text);
+ if (editor.selection)
+ wl_data_source_destroy(editor.selection);
text_entry_destroy(editor.entry);
text_entry_destroy(editor.editor);
widget_destroy(editor.widget);