Skip to content

Commit e36e44a

Browse files
blahgeekkovidgoyal
authored andcommitted
macOS: do not pass input events while having marked text
fix chinese input method backspacing issue macOS: Set pre-edit text for IME macOS: implement glfwPlatformUpdateIMEState set firstRectForCharacterRange correctly macOS: update IME position on each input macOS: use float instead of int for updateIMEState minor fix macOS: ignore marked text on deadkey fixes german keyboard input macOS: convert markedRect to screen coord
1 parent eaba3cf commit e36e44a

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

glfw/cocoa_window.m

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ @interface GLFWContentView : NSView <NSTextInputClient>
529529
_GLFWwindow* window;
530530
NSTrackingArea* trackingArea;
531531
NSMutableAttributedString* markedText;
532+
NSRect markedRect;
532533
}
533534

534535
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
@@ -545,6 +546,7 @@ - (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
545546
window = initWindow;
546547
trackingArea = nil;
547548
markedText = [[NSMutableAttributedString alloc] init];
549+
markedRect = NSMakeRect(0.0, 0.0, 0.0, 0.0);
548550

549551
[self updateTrackingAreas];
550552
[self registerForDraggedTypes:@[NSPasteboardTypeFileURL]];
@@ -815,6 +817,8 @@ - (void)keyDown:(NSEvent *)event
815817
const int mods = translateFlags(flags);
816818
const int key = translateKey(scancode, GLFW_TRUE);
817819
const GLFWbool process_text = !window->ns.textInputFilterCallback || window->ns.textInputFilterCallback(key, mods, scancode, flags) != 1;
820+
const bool previous_has_marked_text = [self hasMarkedText];
821+
[self unmarkText];
818822
_glfw.ns.text[0] = 0;
819823
if (!_glfw.ns.unicodeData) {
820824
// Using the cocoa API for key handling is disabled, as there is no
@@ -859,6 +863,20 @@ - (void)keyDown:(NSEvent *)event
859863
if (is_ascii_control_char(_glfw.ns.text[0])) _glfw.ns.text[0] = 0; // don't send text for ascii control codes
860864
debug_key(@"text: %s glfw_key: %s\n",
861865
format_text(_glfw.ns.text), _glfwGetKeyName(key));
866+
debug_key(@"marked text: %@", markedText);
867+
if (!window->ns.deadKeyState) {
868+
if ([self hasMarkedText]) {
869+
_glfwInputKeyboard(window, key, scancode, GLFW_PRESS, mods,
870+
[[markedText string] UTF8String], 1); // update pre-edit text
871+
} else if (previous_has_marked_text) {
872+
_glfwInputKeyboard(window, key, scancode, GLFW_PRESS, mods,
873+
NULL, 1); // clear pre-edit text
874+
}
875+
if (([self hasMarkedText] || previous_has_marked_text) && !_glfw.ns.text[0]) {
876+
// do not pass keys like BACKSPACE while there's pre-edit text, let IME handle it
877+
return;
878+
}
879+
}
862880
_glfwInputKeyboard(window, key, scancode, GLFW_PRESS, mods, _glfw.ns.text, 0);
863881
}
864882

@@ -997,6 +1015,28 @@ - (void)unmarkText
9971015
[[markedText mutableString] setString:@""];
9981016
}
9991017

1018+
void _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int d) {
1019+
[w->ns.view updateIMEStateFor: which left:(CGFloat)a top:(CGFloat)b cellWidth:(CGFloat)c cellHeight:(CGFloat)d];
1020+
}
1021+
1022+
- (void)updateIMEStateFor:(int)which
1023+
left:(CGFloat)left
1024+
top:(CGFloat)top
1025+
cellWidth:(CGFloat)cellWidth
1026+
cellHeight:(CGFloat)cellHeight
1027+
{
1028+
left /= window->ns.xscale;
1029+
top /= window->ns.yscale;
1030+
cellWidth /= window->ns.xscale;
1031+
cellHeight /= window->ns.yscale;
1032+
debug_key(@"updateIMEState: %f, %f, %f, %f\n", left, top, cellWidth, cellHeight);
1033+
const NSRect frame = [window->ns.view frame];
1034+
const NSRect rectInView = NSMakeRect(left,
1035+
frame.size.height - top - cellHeight,
1036+
cellWidth, cellHeight);
1037+
markedRect = [window->ns.object convertRectToScreen: rectInView];
1038+
}
1039+
10001040
- (NSArray*)validAttributesForMarkedText
10011041
{
10021042
return [NSArray array];
@@ -1016,8 +1056,7 @@ - (NSUInteger)characterIndexForPoint:(NSPoint)point
10161056
- (NSRect)firstRectForCharacterRange:(NSRange)range
10171057
actualRange:(NSRangePointer)actualRange
10181058
{
1019-
const NSRect frame = [window->ns.view frame];
1020-
return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0);
1059+
return markedRect;
10211060
}
10221061

10231062
- (void)insertText:(id)string replacementRange:(NSRange)replacementRange

glfw/input.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ GLFWAPI void glfwUpdateIMEState(GLFWwindow* handle, int which, int a, int b, int
919919
assert(window != NULL);
920920

921921
_GLFW_REQUIRE_INIT();
922-
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
922+
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND) || defined(_GLFW_COCOA)
923923
_glfwPlatformUpdateIMEState(window, which, a, b, c, d);
924924
#else
925925
(void)window; (void)which; (void)a; (void)b; (void)c; (void)d;

kitty/keys.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ on_key_input(int key, int scancode, int action, int mods, const char* text, int
143143
} else debug("committed pre-edit text: (null)\n");
144144
return;
145145
case 0:
146+
// for macOS, update ime position on every key input
147+
// because the position is required before next input
148+
#if defined(__APPLE__)
149+
update_ime_position(global_state.callback_os_window, w, screen);
150+
#endif
146151
break;
147152
default:
148153
debug("invalid state, ignoring\n");

0 commit comments

Comments
 (0)