apprt/gtk: commit buffer before preeditchanged resets

When gtkInputPreeditChanged is called after gtkInputCommit, character
that should be committed is cleared. Check if there's buffered character
and send the characters directly when preedit changed.

Fix #1563
This commit is contained in:
Kyungrok Chung
2024-03-10 15:05:53 +09:00
committed by rok
parent 5dc7384d57
commit 612d98d8f8

View File

@ -251,6 +251,7 @@ inspector: ?*inspector.Inspector = null,
in_keypress: bool = false, in_keypress: bool = false,
im_context: *c.GtkIMContext, im_context: *c.GtkIMContext,
im_composing: bool = false, im_composing: bool = false,
im_commit_buffered: bool = false,
im_buf: [128]u8 = undefined, im_buf: [128]u8 = undefined,
im_len: u7 = 0, im_len: u7 = 0,
@ -1521,6 +1522,25 @@ fn gtkInputPreeditChanged(
ud: ?*anyopaque, ud: ?*anyopaque,
) callconv(.C) void { ) callconv(.C) void {
const self = userdataSelf(ud.?); const self = userdataSelf(ud.?);
// If there's buffered character, send the characters directly to the surface.
if (self.im_composing and self.im_commit_buffered) {
defer self.im_commit_buffered = false;
defer self.im_len = 0;
_ = self.core_surface.keyCallback(.{
.action = .press,
.key = .invalid,
.physical_key = .invalid,
.mods = .{},
.consumed_mods = .{},
.composing = false,
.utf8 = self.im_buf[0..self.im_len],
}) catch |err| {
log.err("error in key callback err={}", .{err});
return;
};
}
if (!self.in_keypress) return; if (!self.in_keypress) return;
// Get our pre-edit string that we'll use to show the user. // Get our pre-edit string that we'll use to show the user.
@ -1567,6 +1587,12 @@ fn gtkInputCommit(
@memcpy(self.im_buf[0..str.len], str); @memcpy(self.im_buf[0..str.len], str);
self.im_len = @intCast(str.len); self.im_len = @intCast(str.len);
// If composing is done and character should be committed,
// It should be committed in preedit callback.
if (self.im_composing) {
self.im_commit_buffered = true;
}
// log.debug("input commit len={}", .{self.im_len}); // log.debug("input commit len={}", .{self.im_len});
} else { } else {
log.warn("not enough buffer space for input method commit", .{}); log.warn("not enough buffer space for input method commit", .{});
@ -1575,6 +1601,10 @@ fn gtkInputCommit(
return; return;
} }
// This prevents staying in composing state after commit even though
// input method has changed.
self.im_composing = false;
// We're not in a keypress, so this was sent from an on-screen emoji // We're not in a keypress, so this was sent from an on-screen emoji
// keyboard or someting like that. Send the characters directly to // keyboard or someting like that. Send the characters directly to
// the surface. // the surface.