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_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)); if (!entry->preedit_text) { text_layout_set_text(entry->layout, entry->text); return; } 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), entry->text + entry->cursor); text_layout_set_text(entry->layout, text); free(text); widget_schedule_redraw(entry->widget); text_model_set_surrounding_text(entry->model, entry->text, entry->cursor, entry->anchor); }
static void 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); strncpy(new_text, entry->text, entry->cursor); strcpy(new_text + entry->cursor, text); strcpy(new_text + entry->cursor + strlen(text), entry->text + entry->cursor); free(entry->text); entry->text = new_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); widget_schedule_redraw(entry->widget); text_entry_update(entry); }
static int motion_handler(struct widget *widget, struct input *input, uint32_t time, float x, float y, void *data) { struct cliptest *cliptest = data; struct ui_state *ui = &cliptest->ui; struct geometry *ref = &ui->geometry; struct geometry *geom = &cliptest->geometry; float dx, dy; if (!ui->down) return CURSOR_LEFT_PTR; dx = (x - ui->down_pos[0]) * 0.25; dy = (y - ui->down_pos[1]) * 0.25; switch (ui->button) { case BTN_LEFT: geom->clip.x1 = ref->clip.x1 + dx; geom->clip.y1 = ref->clip.y1 + dy; /* fall through */ case BTN_RIGHT: geom->clip.x2 = ref->clip.x2 + dx; geom->clip.y2 = ref->clip.y2 + dy; break; default: return CURSOR_LEFT_PTR; } widget_schedule_redraw(cliptest->widget); return CURSOR_BLANK; }
static void text_entry_delete_text(struct text_entry *entry, uint32_t index, uint32_t length) { uint32_t l; assert(index <= strlen(entry->text)); assert(index + length <= strlen(entry->text)); assert(index + length >= length); l = strlen(entry->text + index + length); memmove(entry->text + index, entry->text + index + length, l + 1); if (entry->cursor > (index + length)) entry->cursor -= length; else if (entry->cursor > index) entry->cursor = index; entry->anchor = entry->cursor; text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); text_entry_update(entry); }
static void button_handler(struct widget *widget, struct input *input, uint32_t time, uint32_t button, enum wl_pointer_button_state state, void *data) { struct keyboard *keyboard = data; struct rectangle allocation; int32_t x, y; int row, col; unsigned int i; if (state != WL_POINTER_BUTTON_STATE_PRESSED || button != BTN_LEFT) { return; } input_get_position(input, &x, &y); widget_get_allocation(keyboard->widget, &allocation); x -= allocation.x; y -= allocation.y; row = y / key_height; col = x / key_width + row * columns; for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) { col -= keys[i].width; if (col < 0) { keyboard_handle_key(keyboard, &keys[i]); break; } } widget_schedule_redraw(widget); }
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_model_deactivated(void *data, struct text_model *text_model) { struct text_entry *entry = data; entry->active = 0; widget_schedule_redraw(entry->widget); }
static void text_model_commit_string(void *data, struct text_model *text_model, const char *text, uint32_t index) { struct text_entry *entry = data; text_entry_append(entry, text); widget_schedule_redraw(entry->widget); }
static void button_handler(struct widget *widget, struct input *input, uint32_t time, uint32_t button, enum wl_pointer_button_state state, void *data) { struct clickdot *clickdot = data; if (state == WL_POINTER_BUTTON_STATE_PRESSED && button == BTN_LEFT) input_get_position(input, &clickdot->dot.x, &clickdot->dot.y); widget_schedule_redraw(widget); }
static void input_method_activate(void *data, struct wl_input_method *input_method, struct wl_input_method_context *context) { struct virtual_keyboard *keyboard = data; struct wl_array modifiers_map; const struct layout *layout; keyboard->keyboard->state = keyboardstate_default; if (keyboard->context) wl_input_method_context_destroy(keyboard->context); if (keyboard->preedit_string) free(keyboard->preedit_string); keyboard->preedit_string = strdup(""); keyboard->content_hint = 0; keyboard->content_purpose = 0; free(keyboard->preferred_language); keyboard->preferred_language = NULL; free(keyboard->surrounding_text); keyboard->surrounding_text = NULL; keyboard->serial = 0; keyboard->context = context; wl_input_method_context_add_listener(context, &input_method_context_listener, keyboard); wl_array_init(&modifiers_map); keysym_modifiers_add(&modifiers_map, "Shift"); keysym_modifiers_add(&modifiers_map, "Control"); keysym_modifiers_add(&modifiers_map, "Mod1"); wl_input_method_context_modifiers_map(context, &modifiers_map); keyboard->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift"); wl_array_release(&modifiers_map); layout = get_current_layout(keyboard); window_schedule_resize(keyboard->keyboard->window, layout->columns * key_width, layout->rows * key_height); wl_input_method_context_language(context, keyboard->serial, layout->language); wl_input_method_context_text_direction(context, keyboard->serial, layout->text_direction); widget_schedule_redraw(keyboard->keyboard->widget); }
static void text_model_enter(void *data, struct text_model *text_model, struct wl_surface *surface) { struct text_entry *entry = data; if (surface != window_get_wl_surface(entry->window)) return; entry->active = 1; widget_schedule_redraw(entry->widget); }
static void text_input_leave(void *data, struct wl_text_input *text_input) { struct text_entry *entry = data; text_entry_commit_and_reset(entry); entry->active = 0; wl_text_input_hide_input_panel(text_input); widget_schedule_redraw(entry->widget); }
static void text_model_keysym(void *data, struct text_model *text_model, 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; } 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 int enter_handler(struct widget *widget, struct input *input, float x, float y, void *data) { struct fullscreen *fullscreen = data; fullscreen->pointer_x = x; fullscreen->pointer_y = y; widget_schedule_redraw(widget); return fullscreen->draw_cursor ? CURSOR_BLANK : CURSOR_LEFT_PTR; }
static void text_entry_set_cursor_position(struct text_entry *entry, int32_t x, int32_t y) { entry->cursor = text_layout_xy_to_index(entry->layout, x, y); text_model_reset(entry->model); if (entry->cursor >= entry->preedit_cursor) { entry->cursor -= entry->preedit_cursor; } text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); }
static void text_model_commit_string(void *data, struct text_model *text_model, const char *text, uint32_t index) { struct text_entry *entry = data; if (index > strlen(text)) fprintf(stderr, "Invalid cursor index %d\n", index); text_entry_delete_selected_text(entry); text_entry_insert_at_cursor(entry, text); widget_schedule_redraw(entry->widget); }
static void axis_handler(struct widget *widget, struct input *input, uint32_t time, uint32_t axis, wl_fixed_t value, void *data) { struct cliptest *cliptest = data; struct geometry *geom = &cliptest->geometry; if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; geometry_set_phi(geom, geom->phi + (M_PI / 12.0) * wl_fixed_to_double(value)); cliptest->view.transform.enabled = 1; widget_schedule_redraw(cliptest->widget); }
static void text_entry_delete_text(struct text_entry *entry, uint32_t index, uint32_t length) { if (entry->cursor > index) entry->cursor -= length; entry->anchor = entry->cursor; entry->text[index] = '\0'; strcat(entry->text, entry->text + index + length); text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); }
static void text_entry_set_preedit(struct text_entry *entry, const char *preedit_text, int preedit_cursor) { text_entry_reset_preedit(entry); if (!preedit_text) return; entry->preedit.text = strdup(preedit_text); entry->preedit.cursor = preedit_cursor; text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); }
static void text_input_enter(void *data, struct wl_text_input *text_input, struct wl_surface *surface) { struct text_entry *entry = data; if (surface != window_get_wl_surface(entry->window)) return; entry->active = 1; text_entry_update(entry); entry->reset_serial = entry->serial; widget_schedule_redraw(entry->widget); }
static void text_entry_set_anchor_position(struct text_entry *entry, int32_t x, int32_t y) { int index, trailing; const char *text; pango_layout_xy_to_index(entry->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); text = pango_layout_get_text(entry->layout); entry->anchor = g_utf8_offset_to_pointer(text + index, trailing) - text; text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); text_entry_update(entry); }
static void button_handler(struct widget *widget, struct input *input, uint32_t time, uint32_t button, enum wl_pointer_button_state state, void *data) { struct calibrator *calibrator = data; int32_t x, y; if (state == WL_POINTER_BUTTON_STATE_PRESSED && button == BTN_LEFT) { input_get_position(input, &x, &y); calibrator->tests[calibrator->current_test].clicked_x = x; calibrator->tests[calibrator->current_test].clicked_y = y; calibrator->current_test--; if (calibrator->current_test < 0) finish_calibration(calibrator); } widget_schedule_redraw(widget); }
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; 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 = entry->preedit_info.attr_list; entry->preedit_info.cursor = 0; entry->preedit_info.attr_list = NULL; text_entry_update(entry); widget_schedule_redraw(entry->widget); }
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 sub_redraw_handler(struct widget *widget, void *data) { struct demoapp *app = data; cairo_t *cr; struct rectangle allocation; uint32_t time; widget_get_allocation(app->subsurface, &allocation); cr = widget_cairo_create(widget); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); /* debug: paint whole surface magenta; no magenta should show */ cairo_set_source_rgba(cr, 0.9, 0.0, 0.9, 1.0); cairo_paint(cr); cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height); cairo_clip(cr); cairo_set_source_rgba(cr, 0.8, 0, 0, 0.8); cairo_paint(cr); time = widget_get_last_time(widget); cairo_set_source_rgba(cr, 1.0, 0.5, 0.5, 1.0); draw_spinner(cr, &allocation, time); cairo_destroy(cr); if (app->animate) widget_schedule_redraw(app->subsurface); DBG("%dx%d @ %d,%d, last time %u\n", allocation.width, allocation.height, allocation.x, allocation.y, time); }
static void button_handler(struct widget *widget, struct input *input, uint32_t time, uint32_t button, enum wl_pointer_button_state state, void *data) { struct editor *editor = data; struct rectangle allocation; int32_t x, y; struct wl_seat *seat; if (state != WL_POINTER_BUTTON_STATE_PRESSED || button != BTN_LEFT) { return; } input_get_position(input, &x, &y); widget_get_allocation(editor->widget, &allocation); x -= allocation.x; y -= allocation.y; int32_t activate_entry = rectangle_contains(&editor->entry->allocation, x, y); int32_t activate_editor = rectangle_contains(&editor->editor->allocation, x, y); assert(!(activate_entry && activate_editor)); seat = input_get_seat(input); if (activate_entry) { text_entry_activate(editor->entry, seat); } else if (activate_editor) { text_entry_activate(editor->editor, seat); } else { text_entry_deactivate(editor->entry, seat); text_entry_deactivate(editor->editor, seat); } widget_schedule_redraw(widget); }
static void button_handler(struct widget *widget, struct input *input, uint32_t time, uint32_t button, enum wl_pointer_button_state state, void *data) { struct flower *flower = data; switch (button) { case BTN_LEFT: if (state == WL_POINTER_BUTTON_STATE_PRESSED) window_move(flower->window, input, display_get_serial(flower->display)); break; case BTN_MIDDLE: if (state == WL_POINTER_BUTTON_STATE_PRESSED) widget_schedule_redraw(widget); break; case BTN_RIGHT: if (state == WL_POINTER_BUTTON_STATE_PRESSED) window_show_frame_menu(flower->window, input, time); break; } }
static void button_handler(struct widget *widget, struct input *input, uint32_t time, uint32_t button, enum wl_pointer_button_state state, void *data) { struct keyboard *keyboard = data; struct rectangle allocation; int32_t x, y; int row, col; unsigned int i; const struct layout *layout; layout = get_current_layout(keyboard->keyboard); if (button != BTN_LEFT) { return; } input_get_position(input, &x, &y); widget_get_allocation(keyboard->widget, &allocation); x -= allocation.x; y -= allocation.y; row = y / key_height; col = x / key_width + row * layout->columns; for (i = 0; i < layout->count; ++i) { col -= layout->keys[i].width; if (col < 0) { keyboard_handle_key(keyboard, time, &layout->keys[i], input, state); break; } } widget_schedule_redraw(widget); }
static void text_entry_set_cursor_position(struct text_entry *entry, int32_t x, int32_t y, bool move_anchor) { int index, trailing; const char *text; uint32_t cursor; pango_layout_xy_to_index(entry->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); text = pango_layout_get_text(entry->layout); cursor = g_utf8_offset_to_pointer(text + index, trailing) - text; if (move_anchor) entry->anchor = cursor; if (text_entry_has_preedit(entry)) { text_entry_commit_and_reset(entry); assert(!text_entry_has_preedit(entry)); } if (entry->cursor == cursor) return; entry->cursor = cursor; text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); text_entry_update(entry); }