static void text_input_commit_string(void *data, struct wl_text_input *text_input, uint32_t serial, const char *text) { struct text_entry *entry = data; if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n", serial, entry->serial, entry->reset_serial); return; } text_entry_reset_preedit(entry); text_entry_delete_selected_text(entry); if (entry->pending_commit.delete_length) { text_entry_delete_text(entry, entry->pending_commit.delete_index, entry->pending_commit.delete_length); } 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); }
static void text_model_delete_surrounding_text(void *data, struct text_model *text_model, int32_t index, uint32_t length) { struct text_entry *entry = data; uint32_t cursor_index = index + entry->cursor; const char *start, *end; if (cursor_index > strlen(entry->text)) { fprintf(stderr, "Invalid cursor index %d\n", index); return; } if (cursor_index + length > strlen(entry->text)) { fprintf(stderr, "Invalid length %d\n", length); return; } if (length == 0) return; start = utf8_start_char(entry->text, entry->text + cursor_index); end = utf8_end_char(entry->text + cursor_index + length); text_entry_delete_text(entry, start - entry->text, end - start); }
static void text_entry_delete_selected_text(struct text_entry *entry) { uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor; uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor; if (entry->anchor == entry->cursor) return; text_entry_delete_text(entry, start_index, end_index - start_index); entry->anchor = entry->cursor; }
static void text_input_preedit_string(void *data, struct wl_text_input *text_input, uint32_t serial, const char *text, const char *commit) { struct text_entry *entry = data; if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { fprintf(stderr, "Ignore preedit_string. Serial: %u, Current: %u, Reset: %u\n", serial, entry->serial, entry->reset_serial); clear_pending_preedit(entry); return; } if (entry->pending_commit.invalid_delete) { fprintf(stderr, "Ignore preedit_string. Invalid previous delete_surrounding event.\n"); clear_pending_preedit(entry); return; } if (entry->pending_commit.delete_length) { text_entry_delete_text(entry, entry->pending_commit.delete_index, entry->pending_commit.delete_length); } else { text_entry_delete_selected_text(entry); } text_entry_set_preedit(entry, text, entry->preedit_info.cursor); entry->preedit.commit = strdup(commit); entry->preedit.attr_list = pango_attr_list_ref(entry->preedit_info.attr_list); clear_pending_preedit(entry); text_entry_update(entry); widget_schedule_redraw(entry->widget); }
static void text_input_keysym(void *data, struct wl_text_input *text_input, uint32_t serial, uint32_t time, uint32_t key, uint32_t state, uint32_t modifiers) { struct text_entry *entry = data; const char *state_label = "release"; const char *key_label = "Unknown"; const char *new_char; if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { state_label = "pressed"; } if (key == XKB_KEY_Left || key == XKB_KEY_Right) { if (state != WL_KEYBOARD_KEY_STATE_RELEASED) return; if (key == XKB_KEY_Left) new_char = utf8_prev_char(entry->text, entry->text + entry->cursor); else new_char = utf8_next_char(entry->text + entry->cursor); if (new_char != NULL) { entry->cursor = new_char - entry->text; } if (!(modifiers & entry->keysym.shift_mask)) entry->anchor = entry->cursor; widget_schedule_redraw(entry->widget); return; } if (key == XKB_KEY_BackSpace) { const char *start, *end; if (state != WL_KEYBOARD_KEY_STATE_RELEASED) return; text_entry_commit_and_reset(entry); start = utf8_prev_char(entry->text, entry->text + entry->cursor); end = utf8_next_char(start); if (start == NULL) return; text_entry_delete_text(entry, start - entry->text, end - start); return; } switch (key) { case XKB_KEY_Tab: key_label = "Tab"; break; case XKB_KEY_KP_Enter: case XKB_KEY_Return: key_label = "Enter"; break; } fprintf(stderr, "%s key was %s.\n", key_label, state_label); }
static void key_handler(struct window *window, struct input *input, uint32_t time, uint32_t key, uint32_t sym, enum wl_keyboard_key_state state, void *data) { struct editor *editor = data; struct text_entry *entry; const char *new_char; char text[16]; if (!editor->active_entry) return; entry = editor->active_entry; if (state != WL_KEYBOARD_KEY_STATE_PRESSED) return; switch (sym) { case XKB_KEY_BackSpace: text_entry_commit_and_reset(entry); new_char = utf8_prev_char(entry->text, entry->text + entry->cursor); if (new_char != NULL) text_entry_delete_text(entry, new_char - entry->text, (entry->text + entry->cursor) - new_char); break; case XKB_KEY_Delete: text_entry_commit_and_reset(entry); new_char = utf8_next_char(entry->text + entry->cursor); if (new_char != NULL) text_entry_delete_text(entry, entry->cursor, new_char - (entry->text + entry->cursor)); break; case XKB_KEY_Left: text_entry_commit_and_reset(entry); new_char = utf8_prev_char(entry->text, entry->text + entry->cursor); if (new_char != NULL) { entry->cursor = new_char - entry->text; entry->anchor = entry->cursor; widget_schedule_redraw(entry->widget); } break; case XKB_KEY_Right: text_entry_commit_and_reset(entry); new_char = utf8_next_char(entry->text + entry->cursor); if (new_char != NULL) { entry->cursor = new_char - entry->text; entry->anchor = entry->cursor; widget_schedule_redraw(entry->widget); } break; default: if (xkb_keysym_to_utf8(sym, text, sizeof(text)) <= 0) break; text_entry_commit_and_reset(entry); text_entry_insert_at_cursor(entry, text, 0, 0); break; } widget_schedule_redraw(entry->widget); }