From 612d98d8f8f8df846e58fcddbe00ed148c4fa1e6 Mon Sep 17 00:00:00 2001 From: Kyungrok Chung Date: Sun, 10 Mar 2024 15:05:53 +0900 Subject: [PATCH] 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 --- src/apprt/gtk/Surface.zig | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index 6758deb48..fe8968acd 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -251,6 +251,7 @@ inspector: ?*inspector.Inspector = null, in_keypress: bool = false, im_context: *c.GtkIMContext, im_composing: bool = false, +im_commit_buffered: bool = false, im_buf: [128]u8 = undefined, im_len: u7 = 0, @@ -1521,6 +1522,25 @@ fn gtkInputPreeditChanged( ud: ?*anyopaque, ) callconv(.C) void { 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; // 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); 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}); } else { log.warn("not enough buffer space for input method commit", .{}); @@ -1575,6 +1601,10 @@ fn gtkInputCommit( 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 // keyboard or someting like that. Send the characters directly to // the surface.