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 5 package io.flutter.embedding.engine.systemchannels; 6 7 import android.os.Build; 8 import android.support.annotation.NonNull; 9 import android.support.annotation.Nullable; 10 import android.view.InputDevice; 11 import android.view.KeyEvent; 12 13 import java.util.HashMap; 14 import java.util.Map; 15 16 import io.flutter.embedding.engine.dart.DartExecutor; 17 import io.flutter.plugin.common.BasicMessageChannel; 18 import io.flutter.plugin.common.JSONMessageCodec; 19 20 /** 21 * TODO(mattcarroll): fill in javadoc for KeyEventChannel. 22 */ 23 public class KeyEventChannel { 24 25 @NonNull 26 public final BasicMessageChannel<Object> channel; 27 KeyEventChannel(@onNull DartExecutor dartExecutor)28 public KeyEventChannel(@NonNull DartExecutor dartExecutor) { 29 this.channel = new BasicMessageChannel<>(dartExecutor, "flutter/keyevent", JSONMessageCodec.INSTANCE); 30 } 31 keyUp(@onNull FlutterKeyEvent keyEvent)32 public void keyUp(@NonNull FlutterKeyEvent keyEvent) { 33 Map<String, Object> message = new HashMap<>(); 34 message.put("type", "keyup"); 35 message.put("keymap", "android"); 36 encodeKeyEvent(keyEvent, message); 37 38 channel.send(message); 39 } 40 keyDown(@onNull FlutterKeyEvent keyEvent)41 public void keyDown(@NonNull FlutterKeyEvent keyEvent) { 42 Map<String, Object> message = new HashMap<>(); 43 message.put("type", "keydown"); 44 message.put("keymap", "android"); 45 encodeKeyEvent(keyEvent, message); 46 47 channel.send(message); 48 } 49 encodeKeyEvent(@onNull FlutterKeyEvent event, @NonNull Map<String, Object> message)50 private void encodeKeyEvent(@NonNull FlutterKeyEvent event, @NonNull Map<String, Object> message) { 51 message.put("flags", event.flags); 52 message.put("plainCodePoint", event.plainCodePoint); 53 message.put("codePoint", event.codePoint); 54 message.put("keyCode", event.keyCode); 55 message.put("scanCode", event.scanCode); 56 message.put("metaState", event.metaState); 57 if (event.complexCharacter != null) { 58 message.put("character", event.complexCharacter.toString()); 59 } 60 message.put("source", event.source); 61 message.put("vendorId", event.vendorId); 62 message.put("productId", event.productId); 63 } 64 65 /** 66 * Key event as defined by Flutter. 67 */ 68 public static class FlutterKeyEvent { 69 public final int deviceId; 70 public final int flags; 71 public final int plainCodePoint; 72 public final int codePoint; 73 public final int keyCode; 74 @Nullable 75 public final Character complexCharacter; 76 public final int scanCode; 77 public final int metaState; 78 public final int source; 79 public final int vendorId; 80 public final int productId; 81 FlutterKeyEvent( @onNull KeyEvent androidKeyEvent )82 public FlutterKeyEvent( 83 @NonNull KeyEvent androidKeyEvent 84 ) { 85 this(androidKeyEvent, null); 86 } 87 FlutterKeyEvent( @onNull KeyEvent androidKeyEvent, @Nullable Character complexCharacter )88 public FlutterKeyEvent( 89 @NonNull KeyEvent androidKeyEvent, 90 @Nullable Character complexCharacter 91 ) { 92 this( 93 androidKeyEvent.getDeviceId(), 94 androidKeyEvent.getFlags(), 95 androidKeyEvent.getUnicodeChar(0x0), 96 androidKeyEvent.getUnicodeChar(), 97 androidKeyEvent.getKeyCode(), 98 complexCharacter, 99 androidKeyEvent.getScanCode(), 100 androidKeyEvent.getMetaState(), 101 androidKeyEvent.getSource() 102 ); 103 } 104 FlutterKeyEvent( int deviceId, int flags, int plainCodePoint, int codePoint, int keyCode, @Nullable Character complexCharacter, int scanCode, int metaState, int source )105 public FlutterKeyEvent( 106 int deviceId, 107 int flags, 108 int plainCodePoint, 109 int codePoint, 110 int keyCode, 111 @Nullable Character complexCharacter, 112 int scanCode, 113 int metaState, 114 int source 115 ) { 116 this.deviceId = deviceId; 117 this.flags = flags; 118 this.plainCodePoint = plainCodePoint; 119 this.codePoint = codePoint; 120 this.keyCode = keyCode; 121 this.complexCharacter = complexCharacter; 122 this.scanCode = scanCode; 123 this.metaState = metaState; 124 this.source = source; 125 InputDevice device = InputDevice.getDevice(deviceId); 126 if (device != null) { 127 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 128 this.vendorId = device.getVendorId(); 129 this.productId = device.getProductId(); 130 } else { 131 this.vendorId = 0; 132 this.productId = 0; 133 } 134 } else { 135 this.vendorId = 0; 136 this.productId = 0; 137 } 138 } 139 } 140 } 141