mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-06 01:40:22 -05:00
Send text_input_rectangle requests for text-input
This commit is contained in:
parent
c1675af103
commit
95c0c89cac
7 changed files with 143 additions and 2 deletions
|
|
@ -43,7 +43,8 @@
|
||||||
copied to. The default is `primary`, which corresponds to the
|
copied to. The default is `primary`, which corresponds to the
|
||||||
behavior in older foot releases
|
behavior in older foot releases
|
||||||
(https://codeberg.org/dnkl/foot/issues/288).
|
(https://codeberg.org/dnkl/foot/issues/288).
|
||||||
|
* IME popup location support: foot now sends the location of the cursor
|
||||||
|
so any popup can be displayed near the text that is being typed.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
@ -114,6 +115,7 @@
|
||||||
* [pc](https://codeberg.org/pc)
|
* [pc](https://codeberg.org/pc)
|
||||||
* [FollieHiyuki](https://codeberg.org/FollieHiyuki)
|
* [FollieHiyuki](https://codeberg.org/FollieHiyuki)
|
||||||
* jbeich
|
* jbeich
|
||||||
|
* [tdeo](https://codeberg.org/tdeo)
|
||||||
|
|
||||||
|
|
||||||
## 1.6.2
|
## 1.6.2
|
||||||
|
|
|
||||||
77
ime.c
77
ime.c
|
|
@ -327,6 +327,36 @@ ime_reset(struct seat *seat)
|
||||||
ime_reset_commit(seat);
|
ime_reset_commit(seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ime_send_cursor_rect(struct seat *seat, struct terminal *term)
|
||||||
|
{
|
||||||
|
if (unlikely(seat->wayl->text_input_manager == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!term->ime.enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (seat->ime.cursor_rect.pending.x == seat->ime.cursor_rect.sent.x &&
|
||||||
|
seat->ime.cursor_rect.pending.y == seat->ime.cursor_rect.sent.y &&
|
||||||
|
seat->ime.cursor_rect.pending.width == seat->ime.cursor_rect.sent.width &&
|
||||||
|
seat->ime.cursor_rect.pending.height == seat->ime.cursor_rect.sent.height)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
zwp_text_input_v3_set_cursor_rectangle(
|
||||||
|
seat->wl_text_input,
|
||||||
|
seat->ime.cursor_rect.pending.x / term->scale,
|
||||||
|
seat->ime.cursor_rect.pending.y / term->scale,
|
||||||
|
seat->ime.cursor_rect.pending.width / term->scale,
|
||||||
|
seat->ime.cursor_rect.pending.height / term->scale);
|
||||||
|
|
||||||
|
zwp_text_input_v3_commit(seat->wl_text_input);
|
||||||
|
seat->ime.serial++;
|
||||||
|
|
||||||
|
seat->ime.cursor_rect.sent = seat->ime.cursor_rect.pending;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ime_enable(struct seat *seat)
|
ime_enable(struct seat *seat)
|
||||||
{
|
{
|
||||||
|
|
@ -347,6 +377,15 @@ ime_enable(struct seat *seat)
|
||||||
ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
|
ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
|
||||||
ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL);
|
ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL);
|
||||||
|
|
||||||
|
zwp_text_input_v3_set_cursor_rectangle(
|
||||||
|
seat->wl_text_input,
|
||||||
|
seat->ime.cursor_rect.pending.x / term->scale,
|
||||||
|
seat->ime.cursor_rect.pending.y / term->scale,
|
||||||
|
seat->ime.cursor_rect.pending.width / term->scale,
|
||||||
|
seat->ime.cursor_rect.pending.height / term->scale);
|
||||||
|
|
||||||
|
seat->ime.cursor_rect.sent = seat->ime.cursor_rect.pending;
|
||||||
|
|
||||||
zwp_text_input_v3_commit(seat->wl_text_input);
|
zwp_text_input_v3_commit(seat->wl_text_input);
|
||||||
seat->ime.serial++;
|
seat->ime.serial++;
|
||||||
}
|
}
|
||||||
|
|
@ -364,6 +403,42 @@ ime_disable(struct seat *seat)
|
||||||
seat->ime.serial++;
|
seat->ime.serial++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ime_update_cursor_rect(struct seat *seat, struct terminal *term)
|
||||||
|
{
|
||||||
|
/* Set in render_ime_preedit() */
|
||||||
|
if (term->ime.preedit.cells != NULL)
|
||||||
|
goto update;
|
||||||
|
|
||||||
|
/* Set in render_search_box() */
|
||||||
|
if (term->is_searching)
|
||||||
|
goto update;
|
||||||
|
|
||||||
|
int x, y, width, height;
|
||||||
|
int col = term->grid->cursor.point.col;
|
||||||
|
int row = term->grid->cursor.point.row;
|
||||||
|
row += term->grid->offset;
|
||||||
|
row -= term->grid->view;
|
||||||
|
row &= term->grid->num_rows - 1;
|
||||||
|
x = term->margins.left + col * term->cell_width;
|
||||||
|
y = term->margins.top + row * term->cell_height;
|
||||||
|
|
||||||
|
if (term->cursor_style == CURSOR_BAR)
|
||||||
|
width = 1;
|
||||||
|
else
|
||||||
|
width = term->cell_width;
|
||||||
|
|
||||||
|
height = term->cell_height;
|
||||||
|
|
||||||
|
seat->ime.cursor_rect.pending.x = x;
|
||||||
|
seat->ime.cursor_rect.pending.y = y;
|
||||||
|
seat->ime.cursor_rect.pending.width = width;
|
||||||
|
seat->ime.cursor_rect.pending.height = height;
|
||||||
|
|
||||||
|
update:
|
||||||
|
ime_send_cursor_rect(seat, term);
|
||||||
|
}
|
||||||
|
|
||||||
const struct zwp_text_input_v3_listener text_input_listener = {
|
const struct zwp_text_input_v3_listener text_input_listener = {
|
||||||
.enter = &enter,
|
.enter = &enter,
|
||||||
.leave = &leave,
|
.leave = &leave,
|
||||||
|
|
@ -377,9 +452,11 @@ const struct zwp_text_input_v3_listener text_input_listener = {
|
||||||
|
|
||||||
void ime_enable(struct seat *seat) {}
|
void ime_enable(struct seat *seat) {}
|
||||||
void ime_disable(struct seat *seat) {}
|
void ime_disable(struct seat *seat) {}
|
||||||
|
void ime_update_cursor_rect(struct seat *seat, struct terminal *term) {}
|
||||||
|
|
||||||
void ime_reset_preedit(struct seat *seat) {}
|
void ime_reset_preedit(struct seat *seat) {}
|
||||||
void ime_reset_commit(struct seat *seat) {}
|
void ime_reset_commit(struct seat *seat) {}
|
||||||
void ime_reset(struct seat *seat) {}
|
void ime_reset(struct seat *seat) {}
|
||||||
|
void ime_send_cursor_rect(struct seat *seat, struct terminal *term) {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
3
ime.h
3
ime.h
|
|
@ -9,10 +9,13 @@ extern const struct zwp_text_input_v3_listener text_input_listener;
|
||||||
#endif /* FOOT_IME_ENABLED */
|
#endif /* FOOT_IME_ENABLED */
|
||||||
|
|
||||||
struct seat;
|
struct seat;
|
||||||
|
struct terminal;
|
||||||
|
|
||||||
void ime_enable(struct seat *seat);
|
void ime_enable(struct seat *seat);
|
||||||
void ime_disable(struct seat *seat);
|
void ime_disable(struct seat *seat);
|
||||||
|
void ime_update_cursor_rect(struct seat *seat, struct terminal *term);
|
||||||
|
|
||||||
void ime_reset_preedit(struct seat *seat);
|
void ime_reset_preedit(struct seat *seat);
|
||||||
void ime_reset_commit(struct seat *seat);
|
void ime_reset_commit(struct seat *seat);
|
||||||
void ime_reset(struct seat *seat);
|
void ime_reset(struct seat *seat);
|
||||||
|
void ime_send_cursor_rect(struct seat *seat, struct terminal *term);
|
||||||
|
|
|
||||||
31
render.c
31
render.c
|
|
@ -34,6 +34,7 @@
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
#include "ime.h"
|
||||||
|
|
||||||
#define TIME_SCROLL_DAMAGE 0
|
#define TIME_SCROLL_DAMAGE 0
|
||||||
|
|
||||||
|
|
@ -1206,6 +1207,7 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
||||||
struct fcft_font *font = attrs_to_font(term, &start_cell->attrs);
|
struct fcft_font *font = attrs_to_font(term, &start_cell->attrs);
|
||||||
draw_bar(term, buf->pix[0], font, &cursor_color, x, y);
|
draw_bar(term, buf->pix[0], font, &cursor_color, x, y);
|
||||||
}
|
}
|
||||||
|
term_ime_set_cursor_rect(term, x, y, 1, term->cell_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (end > start) {
|
else if (end > start) {
|
||||||
|
|
@ -1214,6 +1216,9 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
||||||
int cols = end - start;
|
int cols = end - start;
|
||||||
draw_unfocused_block(term, buf->pix[0], &cursor_color, x, y, cols);
|
draw_unfocused_block(term, buf->pix[0], &cursor_color, x, y, cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
term_ime_set_cursor_rect(
|
||||||
|
term, x, y, (end - start) * term->cell_width, term->cell_height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2275,6 +2280,9 @@ render_search_box(struct terminal *term)
|
||||||
unsigned long cookie = shm_cookie_search(term);
|
unsigned long cookie = shm_cookie_search(term);
|
||||||
struct buffer *buf = shm_get_buffer(term->wl->shm, width, height, cookie, false, 1);
|
struct buffer *buf = shm_get_buffer(term->wl->shm, width, height, cookie, false, 1);
|
||||||
|
|
||||||
|
#define WINDOW_X(x) (margin + x)
|
||||||
|
#define WINDOW_Y(y) (term->height - margin - height + y)
|
||||||
|
|
||||||
/* Background - yellow on empty/match, red on mismatch */
|
/* Background - yellow on empty/match, red on mismatch */
|
||||||
pixman_color_t color = color_hex_to_pixman(
|
pixman_color_t color = color_hex_to_pixman(
|
||||||
term->search.match_len == text_len
|
term->search.match_len == text_len
|
||||||
|
|
@ -2362,6 +2370,7 @@ render_search_box(struct terminal *term)
|
||||||
width = widths[i],
|
width = widths[i],
|
||||||
next_cell_idx += width)
|
next_cell_idx += width)
|
||||||
{
|
{
|
||||||
|
/* Convert subsurface coordinates to window coordinates*/
|
||||||
/* Render cursor */
|
/* Render cursor */
|
||||||
if (i == term->search.cursor) {
|
if (i == term->search.cursor) {
|
||||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||||
|
|
@ -2390,6 +2399,9 @@ render_search_box(struct terminal *term)
|
||||||
/* Bar-styled cursor, if in the visible area */
|
/* Bar-styled cursor, if in the visible area */
|
||||||
if (start >= 0 && start <= visible_cells)
|
if (start >= 0 && start <= visible_cells)
|
||||||
draw_bar(term, buf->pix[0], font, &fg, x + start * term->cell_width, y);
|
draw_bar(term, buf->pix[0], font, &fg, x + start * term->cell_width, y);
|
||||||
|
term_ime_set_cursor_rect(term,
|
||||||
|
WINDOW_X(x + start * term->cell_width), WINDOW_Y(y),
|
||||||
|
1, term->cell_height);
|
||||||
} else {
|
} else {
|
||||||
/* Underline everything before and after the cursor */
|
/* Underline everything before and after the cursor */
|
||||||
int count1 = min(start, cells_left);
|
int count1 = min(start, cells_left);
|
||||||
|
|
@ -2405,6 +2417,9 @@ render_search_box(struct terminal *term)
|
||||||
draw_unfocused_block(
|
draw_unfocused_block(
|
||||||
term, buf->pix[0], &fg, x + start * term->cell_width, y, end - start);
|
term, buf->pix[0], &fg, x + start * term->cell_width, y, end - start);
|
||||||
}
|
}
|
||||||
|
term_ime_set_cursor_rect(term,
|
||||||
|
WINDOW_X(x + start * term->cell_width), WINDOW_Y(y),
|
||||||
|
term->cell_width * (end - start), term->cell_height);
|
||||||
}
|
}
|
||||||
} else if (!have_preedit)
|
} else if (!have_preedit)
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2413,6 +2428,8 @@ render_search_box(struct terminal *term)
|
||||||
xassert(cell_idx >= glyph_offset);
|
xassert(cell_idx >= glyph_offset);
|
||||||
xassert(cell_idx <= glyph_offset + visible_cells);
|
xassert(cell_idx <= glyph_offset + visible_cells);
|
||||||
draw_bar(term, buf->pix[0], font, &fg, x, y);
|
draw_bar(term, buf->pix[0], font, &fg, x, y);
|
||||||
|
term_ime_set_cursor_rect(
|
||||||
|
term, WINDOW_X(x), WINDOW_Y(y), 1, term->cell_height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2465,8 +2482,11 @@ render_search_box(struct terminal *term)
|
||||||
/* Already rendered */;
|
/* Already rendered */;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (term->search.cursor >= term->search.len)
|
if (term->search.cursor >= term->search.len) {
|
||||||
draw_bar(term, buf->pix[0], font, &fg, x, y);
|
draw_bar(term, buf->pix[0], font, &fg, x, y);
|
||||||
|
term_ime_set_cursor_rect(
|
||||||
|
term, WINDOW_X(x), WINDOW_Y(y), 1, term->cell_height);
|
||||||
|
}
|
||||||
|
|
||||||
quirk_weston_subsurface_desync_on(term->window->search_sub_surface);
|
quirk_weston_subsurface_desync_on(term->window->search_sub_surface);
|
||||||
|
|
||||||
|
|
@ -2493,6 +2513,8 @@ render_search_box(struct terminal *term)
|
||||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||||
free(text);
|
free(text);
|
||||||
#endif
|
#endif
|
||||||
|
#undef WINDOW_X
|
||||||
|
#undef WINDOW_Y
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2543,6 +2565,10 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da
|
||||||
if (search && term->is_searching)
|
if (search && term->is_searching)
|
||||||
render_search_box(term);
|
render_search_box(term);
|
||||||
|
|
||||||
|
tll_foreach(term->wl->seats, it)
|
||||||
|
if (it->item.kbd_focus == term)
|
||||||
|
ime_update_cursor_rect(&it->item, term);
|
||||||
|
|
||||||
if (grid && (!term->delayed_render_timer.is_armed || csd || search))
|
if (grid && (!term->delayed_render_timer.is_armed || csd || search))
|
||||||
grid_render(term);
|
grid_render(term);
|
||||||
}
|
}
|
||||||
|
|
@ -2987,6 +3013,9 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data)
|
||||||
render_update_title(term);
|
render_update_title(term);
|
||||||
if (search)
|
if (search)
|
||||||
render_search_box(term);
|
render_search_box(term);
|
||||||
|
tll_foreach(term->wl->seats, it)
|
||||||
|
if (it->item.kbd_focus == term)
|
||||||
|
ime_update_cursor_rect(&it->item, term);
|
||||||
if (grid)
|
if (grid)
|
||||||
grid_render(term);
|
grid_render(term);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
16
terminal.c
16
terminal.c
|
|
@ -2943,3 +2943,19 @@ term_ime_reset(struct terminal *term)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
term_ime_set_cursor_rect(struct terminal *term, int x, int y, int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||||
|
tll_foreach(term->wl->seats, it) {
|
||||||
|
if (it->item.kbd_focus == term) {
|
||||||
|
it->item.ime.cursor_rect.pending.x = x;
|
||||||
|
it->item.ime.cursor_rect.pending.y = y;
|
||||||
|
it->item.ime.cursor_rect.pending.width = width;
|
||||||
|
it->item.ime.cursor_rect.pending.height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -644,3 +644,5 @@ bool term_ime_is_enabled(const struct terminal *term);
|
||||||
void term_ime_enable(struct terminal *term);
|
void term_ime_enable(struct terminal *term);
|
||||||
void term_ime_disable(struct terminal *term);
|
void term_ime_disable(struct terminal *term);
|
||||||
void term_ime_reset(struct terminal *term);
|
void term_ime_reset(struct terminal *term);
|
||||||
|
void term_ime_set_cursor_rect(
|
||||||
|
struct terminal *term, int x, int y, int width, int height);
|
||||||
|
|
|
||||||
12
wayland.h
12
wayland.h
|
|
@ -139,6 +139,13 @@ struct button_tracker {
|
||||||
bool send_to_client; /* Only valid when surface is the main grid surface */
|
bool send_to_client; /* Only valid when surface is the main grid surface */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rect {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
|
||||||
struct seat {
|
struct seat {
|
||||||
struct wayland *wayl;
|
struct wayland *wayl;
|
||||||
struct wl_seat *wl_seat;
|
struct wl_seat *wl_seat;
|
||||||
|
|
@ -236,6 +243,11 @@ struct seat {
|
||||||
/* Input Method Editor */
|
/* Input Method Editor */
|
||||||
struct zwp_text_input_v3 *wl_text_input;
|
struct zwp_text_input_v3 *wl_text_input;
|
||||||
struct {
|
struct {
|
||||||
|
struct {
|
||||||
|
struct rect pending;
|
||||||
|
struct rect sent;
|
||||||
|
} cursor_rect;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
char *text;
|
char *text;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue