Flutter Engine
 
Loading...
Searching...
No Matches
FlutterKeyboardLayout.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <Carbon/Carbon.h>
8#include <cctype>
10
11@implementation FlutterKeyboardLayout {
12 NSData* _keyboardLayoutData;
13}
14
15@synthesize delegate = _delegate;
16
17/**
18 * Returns the current Unicode layout data (kTISPropertyUnicodeKeyLayoutData).
19 *
20 * To use the returned data, convert it to CFDataRef first, finds its bytes
21 * with CFDataGetBytePtr, then reinterpret it into const UCKeyboardLayout*.
22 * It's returned in NSData* to enable auto reference count.
23 */
24static NSData* CurrentKeyboardLayoutData() {
25 fml::CFRef<TISInputSourceRef> source(TISCopyCurrentKeyboardInputSource());
26 CFTypeRef layout_data = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData);
27 if (layout_data == nil) {
28 // TISGetInputSourceProperty returns null with Japanese keyboard layout.
29 // Using TISCopyCurrentKeyboardLayoutInputSource to fix NULL return.
30 // https://github.com/microsoft/node-native-keymap/blob/5f0699ded00179410a14c0e1b0e089fe4df8e130/src/keyboard_mac.mm#L91
31 source.Reset(TISCopyCurrentKeyboardLayoutInputSource());
32 layout_data = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData);
33 }
34 return (__bridge NSData*)layout_data;
35}
36
37/**
38 * NotificationCenter callback invoked on kTISNotifySelectedKeyboardInputSourceChanged events.
39 */
40static void OnKeyboardLayoutChanged(CFNotificationCenterRef center,
41 void* observer,
42 CFStringRef name,
43 const void* object,
44 CFDictionaryRef userInfo) {
45 FlutterKeyboardLayout* controller = (__bridge FlutterKeyboardLayout*)observer;
46 if (controller != nil) {
47 [controller onKeyboardLayoutChanged];
48 }
49}
50
51- (instancetype)initWithDelegate:(id<FlutterKeyboardLayoutDelegate>)delegate {
52 self = [super init];
53 if (self) {
54 _delegate = delegate;
55 // macOS fires this message when changing IMEs.
56 CFNotificationCenterRef cfCenter = CFNotificationCenterGetDistributedCenter();
57 __weak FlutterKeyboardLayout* weakSelf = self;
58 CFNotificationCenterAddObserver(cfCenter, (__bridge void*)weakSelf, OnKeyboardLayoutChanged,
59 kTISNotifySelectedKeyboardInputSourceChanged, NULL,
60 CFNotificationSuspensionBehaviorDeliverImmediately);
61 }
62 return self;
63}
64
65- (void)dealloc {
66 CFNotificationCenterRef cfCenter = CFNotificationCenterGetDistributedCenter();
67 CFNotificationCenterRemoveEveryObserver(cfCenter, (__bridge void*)self);
68}
69
70- (void)onKeyboardLayoutChanged {
71 _keyboardLayoutData = nil;
72 [_delegate keyboardLayoutDidChange];
73}
74
75- (flutter::LayoutClue)lookUpLayoutForKeyCode:(uint16_t)keyCode shift:(BOOL)shift {
76 if (_keyboardLayoutData == nil) {
77 _keyboardLayoutData = CurrentKeyboardLayoutData();
78 }
79 const UCKeyboardLayout* layout = reinterpret_cast<const UCKeyboardLayout*>(
80 CFDataGetBytePtr((__bridge CFDataRef)_keyboardLayoutData));
81
82 UInt32 deadKeyState = 0;
83 UniCharCount stringLength = 0;
84 UniChar resultChar;
85
86 UInt32 modifierState = ((shift ? shiftKey : 0) >> 8) & 0xFF;
87 UInt32 keyboardType = LMGetKbdLast();
88
89 bool isDeadKey = false;
90 OSStatus status =
91 UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierState, keyboardType,
92 kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &stringLength, &resultChar);
93 // For dead keys, press the same key again to get the printable representation of the key.
94 if (status == noErr && stringLength == 0 && deadKeyState != 0) {
95 isDeadKey = true;
96 status =
97 UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierState, keyboardType,
98 kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &stringLength, &resultChar);
99 }
100
101 if (status == noErr && stringLength == 1 && !std::iscntrl(resultChar)) {
102 return flutter::LayoutClue{resultChar, isDeadKey};
103 }
104 return flutter::LayoutClue{0, false};
105}
106
107@end
const char * name
Definition fuchsia.cc:49
UIKeyboardType keyboardType
int BOOL