diff --git a/ime.c b/ime.c index ec38be18..4137a949 100644 --- a/ime.c +++ b/ime.c @@ -37,10 +37,6 @@ leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct seat *seat = data; LOG_DBG("leave: seat=%s", seat->name); - struct terminal *term = seat->kbd_focus; - if (term != NULL) - term_ime_reset(term); - ime_disable(seat); seat->ime.focused = false; } @@ -53,7 +49,7 @@ preedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct seat *seat = data; - ime_reset_preedit(seat); + ime_reset_pending_preedit(seat); if (text != NULL) { seat->ime.preedit.pending.text = xstrdup(text); @@ -70,7 +66,7 @@ commit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct seat *seat = data; - ime_reset_commit(seat); + ime_reset_pending_commit(seat); if (text != NULL) seat->ime.commit.pending.text = xstrdup(text); @@ -107,6 +103,7 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, LOG_DBG("done: serial=%u", serial); struct seat *seat = data; + struct terminal *term = seat->kbd_focus; if (seat->ime.serial != serial) { LOG_DBG("IME serial mismatch: expected=0x%08x, got 0x%08x", @@ -114,16 +111,16 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, return; } - xassert(seat->kbd_focus); - struct terminal *term = seat->kbd_focus; - /* 1. Delete existing pre-edit text */ - if (term->ime.preedit.cells != NULL) { - term_ime_reset(term); - if (term->is_searching) - render_refresh_search(term); - else - render_refresh(term); + if (seat->ime.preedit.cells != NULL) { + ime_reset_preedit(seat); + + if (term != NULL) { + if (term->is_searching) + render_refresh_search(term); + else + render_refresh(term); + } } /* @@ -139,12 +136,14 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, const char *text = seat->ime.commit.pending.text; size_t len = strlen(text); - if (term->is_searching) { - search_add_chars(term, text, len); - render_refresh_search(term); - } else - term_to_slave(term, text, len); - ime_reset_commit(seat); + if (term != NULL) { + if (term->is_searching) { + search_add_chars(term, text, len); + render_refresh_search(term); + } else + term_to_slave(term, text, len); + } + ime_reset_pending_commit(seat); } /* 4. Calculate surrounding text to send - not supported */ @@ -155,41 +154,41 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, : 0; if (wchars == 0 || wchars == (size_t)-1) { - ime_reset_preedit(seat); + ime_reset_pending_preedit(seat); return; } /* First, convert to unicode */ - term->ime.preedit.text = xmalloc((wchars + 1) * sizeof(wchar_t)); - mbstowcs(term->ime.preedit.text, seat->ime.preedit.pending.text, wchars); - term->ime.preedit.text[wchars] = L'\0'; + seat->ime.preedit.text = xmalloc((wchars + 1) * sizeof(wchar_t)); + mbstowcs(seat->ime.preedit.text, seat->ime.preedit.pending.text, wchars); + seat->ime.preedit.text[wchars] = L'\0'; /* Next, count number of cells needed */ size_t cell_count = 0; size_t widths[wchars + 1]; for (size_t i = 0; i < wchars; i++) { - int width = max(wcwidth(term->ime.preedit.text[i]), 1); + int width = max(wcwidth(seat->ime.preedit.text[i]), 1); widths[i] = width; cell_count += width; } /* Allocate cells */ - term->ime.preedit.cells = xmalloc( - cell_count * sizeof(term->ime.preedit.cells[0])); - term->ime.preedit.count = cell_count; + seat->ime.preedit.cells = xmalloc( + cell_count * sizeof(seat->ime.preedit.cells[0])); + seat->ime.preedit.count = cell_count; /* Populate cells */ for (size_t i = 0, cell_idx = 0; i < wchars; i++) { - struct cell *cell = &term->ime.preedit.cells[cell_idx]; + struct cell *cell = &seat->ime.preedit.cells[cell_idx]; int width = widths[i]; - cell->wc = term->ime.preedit.text[i]; + cell->wc = seat->ime.preedit.text[i]; cell->attrs = (struct attributes){.clean = 0}; for (int j = 1; j < width; j++) { - cell = &term->ime.preedit.cells[cell_idx + j]; + cell = &seat->ime.preedit.cells[cell_idx + j]; cell->wc = CELL_MULT_COL_SPACER; cell->attrs = (struct attributes){.clean = 1}; } @@ -206,18 +205,18 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, /* Note: docs says *both* begin and end should be -1, * but what else can we do if only one is -1? */ LOG_DBG("pre-edit cursor is hidden"); - term->ime.preedit.cursor.hidden = true; - term->ime.preedit.cursor.start = -1; - term->ime.preedit.cursor.end = -1; + seat->ime.preedit.cursor.hidden = true; + seat->ime.preedit.cursor.start = -1; + seat->ime.preedit.cursor.end = -1; } else if (seat->ime.preedit.pending.cursor_begin == byte_len && seat->ime.preedit.pending.cursor_end == byte_len) { /* Cursor is *after* the entire pre-edit string */ - term->ime.preedit.cursor.hidden = false; - term->ime.preedit.cursor.start = cell_count; - term->ime.preedit.cursor.end = cell_count; + seat->ime.preedit.cursor.hidden = false; + seat->ime.preedit.cursor.start = cell_count; + seat->ime.preedit.cursor.end = cell_count; } else { @@ -271,7 +270,7 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, /* Expand cursor end to end of glyph */ while (cell_end > cell_begin && cell_end < cell_count && - term->ime.preedit.cells[cell_end].wc == CELL_MULT_COL_SPACER) + seat->ime.preedit.cells[cell_end].wc == CELL_MULT_COL_SPACER) { cell_end++; } @@ -284,50 +283,65 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, xassert(cell_end >= 0); xassert(cell_end <= cell_count); - term->ime.preedit.cursor.hidden = false; - term->ime.preedit.cursor.start = cell_begin; - term->ime.preedit.cursor.end = cell_end; + seat->ime.preedit.cursor.hidden = false; + seat->ime.preedit.cursor.start = cell_begin; + seat->ime.preedit.cursor.end = cell_end; } /* Underline pre-edit string that is *not* covered by the cursor */ - bool hidden = term->ime.preedit.cursor.hidden; - int start = term->ime.preedit.cursor.start; - int end = term->ime.preedit.cursor.end; + bool hidden = seat->ime.preedit.cursor.hidden; + int start = seat->ime.preedit.cursor.start; + int end = seat->ime.preedit.cursor.end; for (size_t i = 0, cell_idx = 0; i < wchars; cell_idx += widths[i], i++) { if (hidden || start == end || cell_idx < start || cell_idx >= end) { - struct cell *cell = &term->ime.preedit.cells[cell_idx]; + struct cell *cell = &seat->ime.preedit.cells[cell_idx]; cell->attrs.underline = true; } } - ime_reset_preedit(seat); + ime_reset_pending_preedit(seat); - if (term->is_searching) - render_refresh_search(term); - else - render_refresh(term); + if (term != NULL) { + if (term->is_searching) + render_refresh_search(term); + else + render_refresh(term); + } } void -ime_reset_preedit(struct seat *seat) +ime_reset_pending_preedit(struct seat *seat) { free(seat->ime.preedit.pending.text); seat->ime.preedit.pending.text = NULL; } void -ime_reset_commit(struct seat *seat) +ime_reset_pending_commit(struct seat *seat) { free(seat->ime.commit.pending.text); seat->ime.commit.pending.text = NULL; } void -ime_reset(struct seat *seat) +ime_reset_pending(struct seat *seat) { - ime_reset_preedit(seat); - ime_reset_commit(seat); + ime_reset_pending_preedit(seat); + ime_reset_pending_commit(seat); +} + +void +ime_reset_preedit(struct seat *seat) +{ + if (seat->ime.preedit.cells == NULL) + return; + + free(seat->ime.preedit.text); + free(seat->ime.preedit.cells); + seat->ime.preedit.text = NULL; + seat->ime.preedit.cells = NULL; + seat->ime.preedit.count = 0; } void @@ -339,7 +353,7 @@ ime_send_cursor_rect(struct seat *seat, struct terminal *term) if (!seat->ime.focused) return; - if (!term->ime.enabled) + if (!term->ime_enabled) return; if (seat->ime.cursor_rect.pending.x == seat->ime.cursor_rect.sent.x && @@ -370,15 +384,21 @@ ime_enable(struct seat *seat) return; struct terminal *term = seat->kbd_focus; + + /* TODO: we’ve actaully seen text-input::enter without first + * seeing keyboard::enter... so perhaps we should check for this, + * and... do what? Ignore IME completely, or do we need to call + * ime_enable() from keyboard::enter too? */ xassert(term != NULL); if (!seat->ime.focused) return; - if (!term->ime.enabled) + if (!term->ime_enabled) return; - ime_reset(seat); + ime_reset_pending(seat); + ime_reset_preedit(seat); zwp_text_input_v3_enable(seat->wl_text_input); zwp_text_input_v3_set_content_type( @@ -408,7 +428,8 @@ ime_disable(struct seat *seat) if (!seat->ime.focused) return; - ime_reset(seat); + ime_reset_pending(seat); + ime_reset_preedit(seat); zwp_text_input_v3_disable(seat->wl_text_input); zwp_text_input_v3_commit(seat->wl_text_input); @@ -419,7 +440,7 @@ void ime_update_cursor_rect(struct seat *seat, struct terminal *term) { /* Set in render_ime_preedit() */ - if (term->ime.preedit.cells != NULL) + if (seat->ime.preedit.cells != NULL) goto update; /* Set in render_search_box() */ @@ -466,9 +487,10 @@ void ime_enable(struct seat *seat) {} void ime_disable(struct seat *seat) {} void ime_update_cursor_rect(struct seat *seat, struct terminal *term) {} +void ime_reset_pending_preedit(struct seat *seat) {} +void ime_reset_pending_commit(struct seat *seat) {} +void ime_reset_pending(struct seat *seat) {} void ime_reset_preedit(struct seat *seat) {} -void ime_reset_commit(struct seat *seat) {} -void ime_reset(struct seat *seat) {} void ime_send_cursor_rect(struct seat *seat, struct terminal *term) {} #endif diff --git a/ime.h b/ime.h index ed2fe507..01438a5a 100644 --- a/ime.h +++ b/ime.h @@ -15,7 +15,8 @@ void ime_enable(struct seat *seat); void ime_disable(struct seat *seat); void ime_update_cursor_rect(struct seat *seat, struct terminal *term); +void ime_reset_pending_preedit(struct seat *seat); +void ime_reset_pending_commit(struct seat *seat); +void ime_reset_pending(struct seat *seat); void ime_reset_preedit(struct seat *seat); -void ime_reset_commit(struct seat *seat); -void ime_reset(struct seat *seat); void ime_send_cursor_rect(struct seat *seat, struct terminal *term); diff --git a/pgo/pgo.c b/pgo/pgo.c index 933d100c..ec8a7883 100644 --- a/pgo/pgo.c +++ b/pgo/pgo.c @@ -129,6 +129,7 @@ void cmd_scrollback_down(struct terminal *term, int rows) {} void ime_enable(struct seat *seat) {} void ime_disable(struct seat *seat) {} +void ime_reset_preedit(struct seat *seat) {} void notify_notify(const struct terminal *term, const char *title, const char *body) diff --git a/render.c b/render.c index fcd07f56..79f90cc7 100644 --- a/render.c +++ b/render.c @@ -1114,12 +1114,12 @@ render_sixel_images(struct terminal *term, pixman_image_t *pix, } } -static void -render_ime_preedit(struct terminal *term, struct buffer *buf) -{ #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - - if (likely(term->ime.preedit.cells == NULL)) +static void +render_ime_preedit_for_seat(struct terminal *term, struct seat *seat, + struct buffer *buf) +{ + if (likely(seat->ime.preedit.cells == NULL)) return; if (unlikely(term->is_searching)) @@ -1135,10 +1135,10 @@ render_ime_preedit(struct terminal *term, struct buffer *buf) if (cursor.row < 0 || cursor.row >= term->rows) return; - int cells_needed = term->ime.preedit.count; + int cells_needed = seat->ime.preedit.count; - if (term->ime.preedit.cursor.start == cells_needed && - term->ime.preedit.cursor.end == cells_needed) + if (seat->ime.preedit.cursor.start == cells_needed && + seat->ime.preedit.cursor.end == cells_needed) { /* Cursor will be drawn *after* the pre-edit string, i.e. in * the cell *after*. This means we need to copy, and dirty, @@ -1160,8 +1160,8 @@ render_ime_preedit(struct terminal *term, struct buffer *buf) col_idx -= cells_used - cells_left; if (cells_needed > cells_used) { - int start = term->ime.preedit.cursor.start; - int end = term->ime.preedit.cursor.end; + int start = seat->ime.preedit.cursor.start; + int end = seat->ime.preedit.cursor.end; if (start == end) { /* Ensure *end* of pre-edit string is visible */ @@ -1177,7 +1177,7 @@ render_ime_preedit(struct terminal *term, struct buffer *buf) /* Make sure we don't start in the middle of a character */ while (ime_ofs < cells_needed && - term->ime.preedit.cells[ime_ofs].wc == CELL_MULT_COL_SPACER) + seat->ime.preedit.cells[ime_ofs].wc == CELL_MULT_COL_SPACER) { ime_ofs++; } @@ -1208,9 +1208,9 @@ render_ime_preedit(struct terminal *term, struct buffer *buf) row->dirty = true; /* Render pre-edit text */ - xassert(term->ime.preedit.cells[ime_ofs].wc != CELL_MULT_COL_SPACER); - for (int i = 0, idx = ime_ofs; idx < term->ime.preedit.count; i++, idx++) { - const struct cell *cell = &term->ime.preedit.cells[idx]; + xassert(seat->ime.preedit.cells[ime_ofs].wc != CELL_MULT_COL_SPACER); + for (int i = 0, idx = ime_ofs; idx < seat->ime.preedit.count; i++, idx++) { + const struct cell *cell = &seat->ime.preedit.cells[idx]; if (cell->wc == CELL_MULT_COL_SPACER) continue; @@ -1223,11 +1223,11 @@ render_ime_preedit(struct terminal *term, struct buffer *buf) render_cell(term, buf->pix[0], row, col_idx + i, row_idx, false); } - int start = term->ime.preedit.cursor.start - ime_ofs; - int end = term->ime.preedit.cursor.end - ime_ofs; + int start = seat->ime.preedit.cursor.start - ime_ofs; + int end = seat->ime.preedit.cursor.end - ime_ofs; - if (!term->ime.preedit.cursor.hidden) { - const struct cell *start_cell = &term->ime.preedit.cells[0]; + if (!seat->ime.preedit.cursor.hidden) { + const struct cell *start_cell = &seat->ime.preedit.cells[0]; pixman_color_t fg = color_hex_to_pixman(term->colors.fg); pixman_color_t bg = color_hex_to_pixman(term->colors.bg); @@ -1271,6 +1271,17 @@ render_ime_preedit(struct terminal *term, struct buffer *buf) term->margins.top + row_idx * term->cell_height, term->width - term->margins.left - term->margins.right, 1 * term->cell_height); +} +#endif + +static void +render_ime_preedit(struct terminal *term, struct buffer *buf) +{ +#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED + tll_foreach(term->wl->seats, it) { + if (it->item.kbd_focus == term) + render_ime_preedit_for_seat(term, &it->item, buf); + } #endif } @@ -2238,9 +2249,18 @@ render_search_box(struct terminal *term) */ #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED + /* TODO: do we want to/need to handle multi-seat? */ + struct seat *ime_seat = NULL; + tll_foreach(term->wl->seats, it) { + if (it->item.kbd_focus == term) { + ime_seat = &it->item; + break; + } + } + size_t text_len = term->search.len; - if (term->ime.preedit.text != NULL) - text_len += wcslen(term->ime.preedit.text); + if (ime_seat != NULL && ime_seat->ime.preedit.text != NULL) + text_len += wcslen(ime_seat->ime.preedit.text); wchar_t *text = xmalloc((text_len + 1) * sizeof(wchar_t)); text[0] = L'\0'; @@ -2250,8 +2270,8 @@ render_search_box(struct terminal *term) text[term->search.cursor] = L'\0'; /* Insert pre-edit text at cursor */ - if (term->ime.preedit.text != NULL) - wcscat(text, term->ime.preedit.text); + if (ime_seat != NULL && ime_seat->ime.preedit.text != NULL) + wcscat(text, ime_seat->ime.preedit.text); /* And finally everything after the cursor */ wcsncat(text, &term->search.buf[term->search.cursor], @@ -2319,18 +2339,18 @@ render_search_box(struct terminal *term) continue; #if (FOOT_IME_ENABLED) && FOOT_IME_ENABLED - if (term->ime.preedit.cells != NULL) { - if (term->ime.preedit.cursor.start == term->ime.preedit.cursor.end) { + if (ime_seat != NULL && ime_seat->ime.preedit.cells != NULL) { + if (ime_seat->ime.preedit.cursor.start == ime_seat->ime.preedit.cursor.end) { /* All IME's I've seen so far keeps the cursor at * index 0, so ensure the *end* of the pre-edit string * is visible */ - cell_idx += term->ime.preedit.count; + cell_idx += ime_seat->ime.preedit.count; } else { /* Try to predict in which direction we'll shift the text */ - if (cell_idx + term->ime.preedit.cursor.start > glyph_offset) - cell_idx += term->ime.preedit.cursor.end; + if (cell_idx + ime_seat->ime.preedit.cursor.start > glyph_offset) + cell_idx += ime_seat->ime.preedit.cursor.end; else - cell_idx += term->ime.preedit.cursor.start; + cell_idx += ime_seat->ime.preedit.cursor.start; } } #endif @@ -2383,8 +2403,10 @@ render_search_box(struct terminal *term) /* Render cursor */ if (i == term->search.cursor) { #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - bool have_preedit = term->ime.preedit.cells != NULL; - bool hidden = term->ime.preedit.cursor.hidden; + bool have_preedit = + ime_seat != NULL && ime_seat->ime.preedit.cells != NULL; + bool hidden = + ime_seat != NULL && ime_seat->ime.preedit.cursor.hidden; if (have_preedit && !hidden) { /* Cursor may be outside the visible area: @@ -2394,13 +2416,13 @@ render_search_box(struct terminal *term) /* If cursor is outside the visible area, we need to * adjust our rectangle's position */ - int start = term->ime.preedit.cursor.start + int start = ime_seat->ime.preedit.cursor.start + min((ssize_t)(cell_idx - glyph_offset), 0); - int end = term->ime.preedit.cursor.end + int end = ime_seat->ime.preedit.cursor.end + min((ssize_t)(cell_idx - glyph_offset), 0); if (start == end) { - int count = min(term->ime.preedit.count, cells_left); + int count = min(ime_seat->ime.preedit.count, cells_left); /* Underline the entire (visible part of) pre-edit text */ draw_underline(term, buf->pix[0], font, &fg, x, y, count); @@ -2415,7 +2437,7 @@ render_search_box(struct terminal *term) /* Underline everything before and after the cursor */ int count1 = min(start, cells_left); int count2 = max( - min(term->ime.preedit.count - term->ime.preedit.cursor.end, + min(ime_seat->ime.preedit.count - ime_seat->ime.preedit.cursor.end, cells_left - end), 0); draw_underline(term, buf->pix[0], font, &fg, x, y, count1); @@ -2487,7 +2509,7 @@ render_search_box(struct terminal *term) } #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - if (term->ime.preedit.cells != NULL) + if (ime_seat != NULL && ime_seat->ime.preedit.cells != NULL) /* Already rendered */; else #endif diff --git a/terminal.c b/terminal.c index cc423395..1984562f 100644 --- a/terminal.c +++ b/terminal.c @@ -1182,9 +1182,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .foot_exe = xstrdup(foot_exe), .cwd = xstrdup(cwd), #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - .ime = { - .enabled = true, - }, + .ime_enabled = true, #endif }; @@ -2405,10 +2403,8 @@ term_kbd_focus_out(struct terminal *term) return; #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - if (term->ime.preedit.cells != NULL) { - term_ime_reset(term); + if (term_ime_reset(term)) render_refresh(term); - } #endif term->kbd_focus = false; @@ -3039,7 +3035,7 @@ bool term_ime_is_enabled(const struct terminal *term) { #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - return term->ime.enabled; + return term->ime_enabled; #else return false; #endif @@ -3049,13 +3045,12 @@ void term_ime_enable(struct terminal *term) { #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - if (term->ime.enabled) + if (term->ime_enabled) return; LOG_DBG("IME enabled"); - term->ime.enabled = true; - term_ime_reset(term); + term->ime_enabled = true; /* IME is per seat - enable on all seat currently focusing us */ tll_foreach(term->wl->seats, it) { @@ -3069,13 +3064,12 @@ void term_ime_disable(struct terminal *term) { #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - if (!term->ime.enabled) + if (!term->ime_enabled) return; LOG_DBG("IME disabled"); - term->ime.enabled = false; - term_ime_reset(term); + term->ime_enabled = false; /* IME is per seat - disable on all seat currently focusing us */ tll_foreach(term->wl->seats, it) { @@ -3085,18 +3079,24 @@ term_ime_disable(struct terminal *term) #endif } -void +bool term_ime_reset(struct terminal *term) { + bool at_least_one_seat_was_reset = false; + #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - if (term->ime.preedit.cells != NULL) { - free(term->ime.preedit.text); - free(term->ime.preedit.cells); - term->ime.preedit.text = NULL; - term->ime.preedit.cells = NULL; - term->ime.preedit.count = 0; + tll_foreach(term->wl->seats, it) { + struct seat *seat = &it->item; + + if (seat->kbd_focus != term) + continue; + + ime_reset_preedit(seat); + at_least_one_seat_was_reset = true; } #endif + + return at_least_one_seat_was_reset; } void diff --git a/terminal.h b/terminal.h index 6cf52522..ce808ce8 100644 --- a/terminal.h +++ b/terminal.h @@ -567,20 +567,7 @@ struct terminal { struct grid *url_grid_snapshot; #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED - struct { - bool enabled; - struct { - wchar_t *text; - struct cell *cells; - int count; - - struct { - bool hidden; - int start; /* Cell index, inclusive */ - int end; /* Cell index, exclusive */ - } cursor; - } preedit; - } ime; + bool ime_enabled; #endif bool is_shutting_down; @@ -713,7 +700,7 @@ bool term_view_to_text( bool term_ime_is_enabled(const struct terminal *term); void term_ime_enable(struct terminal *term); void term_ime_disable(struct terminal *term); -void term_ime_reset(struct terminal *term); +bool term_ime_reset(struct terminal *term); void term_ime_set_cursor_rect( struct terminal *term, int x, int y, int width, int height); diff --git a/wayland.c b/wayland.c index a092e054..edc9b482 100644 --- a/wayland.c +++ b/wayland.c @@ -189,7 +189,7 @@ seat_destroy(struct seat *seat) if (seat->wl_seat != NULL) wl_seat_release(seat->wl_seat); - ime_reset(seat); + ime_reset_pending(seat); free(seat->clipboard.text); free(seat->primary.text); free(seat->name); diff --git a/wayland.h b/wayland.h index 34314414..0b916ccc 100644 --- a/wayland.h +++ b/wayland.h @@ -256,6 +256,15 @@ struct seat { int32_t cursor_begin; int32_t cursor_end; } pending; + + wchar_t *text; + struct cell *cells; + int count; + struct { + bool hidden; + int start; /* Cell index, inclusive */ + int end; /* Cell index, exclusive */ + } cursor; } preedit; struct {