IME: Right align overlay when typing at the edge of the screen

When the cursor is at the right edge of the screen, push the overlay to
the left to display the pre-edit text just entered.
This commit is contained in:
pagedown 2023-03-04 16:11:29 +08:00
parent a2887bb9e0
commit 823db08712
No known key found for this signature in database
GPG Key ID: E921CF18AC8FF6EB
3 changed files with 32 additions and 5 deletions

View File

@ -50,7 +50,7 @@ Detailed list of changes
- When changing the cursor color via escape codes or remote control to a fixed color, do not reset cursor_text_color (:iss:`5994`) - When changing the cursor color via escape codes or remote control to a fixed color, do not reset cursor_text_color (:iss:`5994`)
- Input Method Extensions: Fix incorrect rendering of IME in-progress and committed text in some situations (:pull:`6049`) - Input Method Extensions: Fix incorrect rendering of IME in-progress and committed text in some situations (:pull:`6049`, :pull:`6087`)
- Linux: Reduce minimum required OpenGL version from 3.3 to 3.1 + extensions (:iss:`2790`) - Linux: Reduce minimum required OpenGL version from 3.3 to 3.1 + extensions (:iss:`2790`)

View File

@ -2898,6 +2898,7 @@ screen_update_overlay_text(Screen *self, const char *utf8_text) {
self->overlay_line.is_dirty = true; self->overlay_line.is_dirty = true;
self->overlay_line.xstart = self->cursor->x; self->overlay_line.xstart = self->cursor->x;
self->overlay_line.xnum = !text_len ? 0 : PyLong_AsLong(text_len); self->overlay_line.xnum = !text_len ? 0 : PyLong_AsLong(text_len);
self->overlay_line.text_len = self->overlay_line.xnum;
self->overlay_line.cursor_x = MIN(self->overlay_line.xstart + self->overlay_line.xnum, self->columns); self->overlay_line.cursor_x = MIN(self->overlay_line.xstart + self->overlay_line.xnum, self->columns);
self->overlay_line.ynum = self->cursor->y; self->overlay_line.ynum = self->cursor->y;
cursor_copy_to(self->cursor, &(self->overlay_line.original_line.cursor)); cursor_copy_to(self->cursor, &(self->overlay_line.original_line.cursor));
@ -2913,7 +2914,10 @@ screen_update_overlay_text(Screen *self, const char *utf8_text) {
static void static void
screen_draw_overlay_line(Screen *self) { screen_draw_overlay_line(Screen *self) {
if (!self->overlay_line.overlay_text) return; if (!self->overlay_line.overlay_text) return;
self->overlay_line.xnum = 0; // Right-align the overlay to ensure that the pre-edit text just entered is visible when the cursor is near the end of the line.
index_type xstart = self->overlay_line.text_len <= self->columns ? self->columns - self->overlay_line.text_len : 0;
if (self->overlay_line.xstart < xstart) xstart = self->overlay_line.xstart;
index_type columns_exceeded = self->overlay_line.text_len <= self->columns ? 0 : self->overlay_line.text_len - self->columns;
bool orig_line_wrap_mode = self->modes.mDECAWM; bool orig_line_wrap_mode = self->modes.mDECAWM;
bool orig_cursor_enable_mode = self->modes.mDECTCEM; bool orig_cursor_enable_mode = self->modes.mDECTCEM;
bool orig_insert_replace_mode = self->modes.mIRM; bool orig_insert_replace_mode = self->modes.mIRM;
@ -2923,9 +2927,15 @@ screen_draw_overlay_line(Screen *self) {
Cursor *orig_cursor = self->cursor; Cursor *orig_cursor = self->cursor;
self->cursor = &(self->overlay_line.original_line.cursor); self->cursor = &(self->overlay_line.original_line.cursor);
self->cursor->reverse ^= true; self->cursor->reverse ^= true;
self->cursor->x = self->overlay_line.xstart; self->cursor->x = xstart;
self->cursor->y = self->overlay_line.ynum; self->cursor->y = self->overlay_line.ynum;
self->overlay_line.xnum = 0; self->overlay_line.xnum = 0;
if (xstart > 0) {
// When the cursor is on the second cell of a full-width character for whatever reason,
// make sure the first character in the overlay is visible.
GPUCell *g = self->linebuf->line->gpu_cells + (xstart - 1);
if (g->attrs.width > 1) line_set_char(self->linebuf->line, xstart - 1, 0, 0, NULL, 0);
}
index_type before; index_type before;
const int kind = PyUnicode_KIND(self->overlay_line.overlay_text); const int kind = PyUnicode_KIND(self->overlay_line.overlay_text);
const void *data = PyUnicode_DATA(self->overlay_line.overlay_text); const void *data = PyUnicode_DATA(self->overlay_line.overlay_text);
@ -2933,7 +2943,24 @@ screen_draw_overlay_line(Screen *self) {
for (Py_ssize_t pos = 0; pos < sz; pos++) { for (Py_ssize_t pos = 0; pos < sz; pos++) {
before = self->cursor->x; before = self->cursor->x;
draw_codepoint(self, PyUnicode_READ(kind, data, pos), false); draw_codepoint(self, PyUnicode_READ(kind, data, pos), false);
self->overlay_line.xnum += self->cursor->x - before; index_type len = self->cursor->x - before;
if (columns_exceeded > 0) {
// Reset the cursor to maintain right alignment when the overlay exceeds the screen width.
if (columns_exceeded > len) {
columns_exceeded -= len;
len = 0;
} else {
len = len > columns_exceeded ? len - columns_exceeded : 0;
columns_exceeded = 0;
if (len > 0) {
// When the last character is full width and only half moved out, make sure the next character is visible.
GPUCell *g = self->linebuf->line->gpu_cells + (len - 1);
if (g->attrs.width > 1) line_set_char(self->linebuf->line, len - 1, 0, 0, NULL, 0);
}
}
self->cursor->x = len;
}
self->overlay_line.xnum += len;
} }
self->overlay_line.cursor_x = self->cursor->x; self->overlay_line.cursor_x = self->cursor->x;
self->cursor->reverse ^= true; self->cursor->reverse ^= true;

View File

@ -71,7 +71,7 @@ typedef struct {
PyObject *overlay_text; PyObject *overlay_text;
CPUCell *cpu_cells; CPUCell *cpu_cells;
GPUCell *gpu_cells; GPUCell *gpu_cells;
index_type xstart, ynum, xnum, cursor_x; index_type xstart, ynum, xnum, cursor_x, text_len;
bool is_active; bool is_active;
bool is_dirty; bool is_dirty;
struct { struct {