为什么 NSResponder 中的 interpretKeyEvents 会忽略某些重复的键?

Why are certain repeated keys ignored by interpretKeyEvents in NSResponder?

提问人:jimspin 提问时间:6/24/2023 最后编辑:jimspin 更新时间:6/27/2023 访问量:66

问:

我有一个调用事件的 NSView。对于某些键(如字母“a”),按住该键会导致重复调用 。对于其他键,如“x”,调用一次,仅此而已。我想按住始终拨打 。我猜按住这些键被解释为其他东西,但我找不到它。我已经按照文档的描述实现了,但也从未调用过。interpretKeyEventskeyDowninsertTextinsertTextinsertTextdoCommandBySelector

下面是一个演示该行为的最小示例程序。

// clang++ -framework AppKit -o proof-of-concept proof-of-concept.mm

#include <stdio.h>
#import <Cocoa/Cocoa.h>

@interface AppView : NSView<NSTextInputClient>
@end

@implementation AppView

- (void)keyDown:(NSEvent *)event {
    printf("keydown\n");
    [self interpretKeyEvents:[NSArray arrayWithObject:event]];
}

- (void)insertText:(id)string replacementRange:(NSRange)replacementRange {
    printf("insertText\n");
}

- (BOOL)acceptsFirstResponder { return YES; }
- (void)setMarkedText:(id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange {}
- (void)unmarkText {}
- (NSRange)selectedRange { return NSMakeRange(NSNotFound, 0); }
- (NSRange)markedRange { return NSMakeRange(NSNotFound, 0); }
- (BOOL)hasMarkedText { return NO; }
- (nullable NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange { return nil; }
- (NSArray<NSAttributedStringKey> *)validAttributesForMarkedText { return [NSArray array]; }
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange { return NSMakeRect(0, 0, 0, 0); }
- (NSUInteger)characterIndexForPoint:(NSPoint)point { return 0; }

@end

int main(int argc, char **argv, char **envp, char **apple) {
    [NSApplication sharedApplication];
    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];

    NSRect windowDimensions = NSMakeRect(0, 0, 300, 300);
    NSWindow *window = [[NSWindow alloc] initWithContentRect:windowDimensions
                                         styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskResizable
                                         backing:NSBackingStoreBuffered
                                         defer:NO];

    AppView *windowView = [[AppView alloc] initWithFrame:windowDimensions];
    [window setContentView:windowView];
    [window makeKeyAndOrderFront:nil];

    [NSApp run];
    return 0;
}

有没有解释为什么通过调用来处理一些键重复而忽略其他键?interpretKeyEventsinsertText

Objective-C 可可 NSSeverser

评论

0赞 Willeke 6/25/2023
欢迎使用 Stack Overflow。问题是什么,“为什么某些重复的键被忽略?”或“如何调试?”?请阅读如何提出好问题?并编辑问题。interpretKeyEvents
0赞 Willeke 6/27/2023
我试图重现该问题,但要求所有重复的键。请发布一个最小的可重复示例insertText

答:

0赞 jimspin 6/27/2023 #1

事实证明,问题出在字符重音弹出菜单上。这个问题帮助我弄清楚了。从来没有为我显示过弹出窗口,因此我感到困惑。我认为这是因为我没有提供任何系统光标信息,因此应用程序不知道在哪里显示它,但是我还没有确认这一点。

添加禁用了我的应用程序的重音弹出框并解决了问题。[[NSUserDefaults standardUserDefaults] setBool: NO forKey: @"ApplePressAndHoldEnabled"];

评论

1赞 Willeke 6/27/2023
如果你不实施,你为什么要打电话?interpretKeyEventsNSTextInputClient
0赞 jimspin 6/28/2023
来自表情符号和符号字符查看器的输入仅在 上通过,因此无论如何我都需要实现该路径。 似乎是将字符数据从 to 传递的约定,而不是将其从 中取出并调用 myself。insertTextinterpretKeyEventskeyDowninsertTextNSEventinsertText