diff --git a/sky/services/engine/input_event.mojom b/sky/services/engine/input_event.mojom index aa04188c49f..6afa870387a 100644 --- a/sky/services/engine/input_event.mojom +++ b/sky/services/engine/input_event.mojom @@ -8,6 +8,15 @@ module sky; enum EventType { UNKNOWN, BACK, + KEY_PRESSED, + KEY_RELEASED, +}; + +struct KeyData { + int32 key_code; + int32 flags; + int32 scan_code; + int32 meta_state; }; // TODO(abarth): Should we have a malloc-free way of creating an input event @@ -15,4 +24,5 @@ enum EventType { struct InputEvent { EventType type; int64 time_stamp; + KeyData? key_data; }; diff --git a/sky/services/raw_keyboard/BUILD.gn b/sky/services/raw_keyboard/BUILD.gn new file mode 100644 index 00000000000..eb59423060c --- /dev/null +++ b/sky/services/raw_keyboard/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "raw_keyboard.mojom", + ] + + deps = [ + "//sky/services/engine:interfaces" + ] +} + +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") + + android_library("raw_keyboard_lib") { + java_files = [ + "src/org/domokit/raw_keyboard/RawKeyboardServiceImpl.java", + "src/org/domokit/raw_keyboard/RawKeyboardServiceState.java", + ] + + deps = [ + "//base:base_java", + "//mojo/public/java:bindings", + "//mojo/public/java:system", + "//sky/services/engine:interfaces_java", + ":interfaces_java", + ] + } +} + diff --git a/sky/services/raw_keyboard/raw_keyboard.mojom b/sky/services/raw_keyboard/raw_keyboard.mojom new file mode 100644 index 00000000000..0e8dec233ed --- /dev/null +++ b/sky/services/raw_keyboard/raw_keyboard.mojom @@ -0,0 +1,17 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[DartPackage="sky_services"] +module raw_keyboard; + +import "sky/services/engine/input_event.mojom"; + +interface RawKeyboardListener { + OnKey(sky.InputEvent event); +}; + +interface RawKeyboardService { + AddListener(RawKeyboardListener listener); + RemoveListener(RawKeyboardListener listener); +}; diff --git a/sky/services/raw_keyboard/src/org/domokit/raw_keyboard/RawKeyboardServiceImpl.java b/sky/services/raw_keyboard/src/org/domokit/raw_keyboard/RawKeyboardServiceImpl.java new file mode 100644 index 00000000000..ea32eab81f4 --- /dev/null +++ b/sky/services/raw_keyboard/src/org/domokit/raw_keyboard/RawKeyboardServiceImpl.java @@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.domokit.raw_keyboard; + +import org.chromium.mojo.system.MojoException; +import org.chromium.mojom.raw_keyboard.RawKeyboardListener; +import org.chromium.mojom.raw_keyboard.RawKeyboardService; + +/** + * Android implementation of Keyboard. + */ +public class RawKeyboardServiceImpl implements RawKeyboardService { + // We have a unique ServiceImpl per connection. However multiple views + // can be sending us key events simultaneously. + private static RawKeyboardServiceState sViewState; + + public RawKeyboardServiceImpl() { + } + + public static void setViewState(RawKeyboardServiceState state) { + if (sViewState != null) sViewState.close(); + sViewState = state; + } + + @Override + public void addListener(RawKeyboardListener listener) { + sViewState.addListener(listener); + } + + @Override + public void removeListener(RawKeyboardListener listener) { + sViewState.removeListener(listener); + } + + @Override + public void onConnectionError(MojoException e) {} + + @Override + public void close() { + if (sViewState == null) return; + sViewState.close(); + } +} diff --git a/sky/services/raw_keyboard/src/org/domokit/raw_keyboard/RawKeyboardServiceState.java b/sky/services/raw_keyboard/src/org/domokit/raw_keyboard/RawKeyboardServiceState.java new file mode 100644 index 00000000000..36d328aefd2 --- /dev/null +++ b/sky/services/raw_keyboard/src/org/domokit/raw_keyboard/RawKeyboardServiceState.java @@ -0,0 +1,69 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.domokit.raw_keyboard; + +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; + +import java.util.ArrayList; + +import org.chromium.mojo.system.MojoException; +import org.chromium.mojom.raw_keyboard.RawKeyboardListener; +import org.chromium.mojom.raw_keyboard.RawKeyboardService; +import org.chromium.mojom.sky.InputEvent; +import org.chromium.mojom.sky.EventType; +import org.chromium.mojom.sky.KeyData; + +/** + * Per-View raw keyboard state. + */ +public class RawKeyboardServiceState implements View.OnKeyListener { + private static final String TAG = "RawKeyboardServiceState"; + + private ArrayList mListeners = new ArrayList(); + + public RawKeyboardServiceState() { + } + + public void addListener(RawKeyboardListener listener) { + mListeners.add(listener); + } + + public void removeListener(RawKeyboardListener listener) { + mListeners.remove(listener); + listener.close(); + } + + public void close() { + } + + @Override + public boolean onKey(View v, int keyCode, KeyEvent nativeEvent) { + if (mListeners.isEmpty()) + return false; + InputEvent event = new InputEvent(); + switch (nativeEvent.getAction()) { + case KeyEvent.ACTION_DOWN: + event.type = EventType.KEY_PRESSED; + break; + case KeyEvent.ACTION_UP: + event.type = EventType.KEY_RELEASED; + break; + default: + Log.w(TAG, "Unknown key event received"); + return false; + } + KeyData keyData = new KeyData(); + keyData.flags = nativeEvent.getFlags(); + keyData.scanCode = nativeEvent.getScanCode(); + keyData.metaState = nativeEvent.getMetaState(); + keyData.keyCode = keyCode; + event.keyData = keyData; + for (RawKeyboardListener listener : mListeners) + listener.onKey(event); + return true; + } +} diff --git a/sky/shell/BUILD.gn b/sky/shell/BUILD.gn index d0af62cdd6a..081bbdfc0b3 100644 --- a/sky/shell/BUILD.gn +++ b/sky/shell/BUILD.gn @@ -151,6 +151,8 @@ if (is_android) { "//sky/services/media:media_lib", "//sky/services/oknet", "//sky/services/pointer:interfaces_java", + "//sky/services/raw_keyboard:raw_keyboard_lib", + "//sky/services/raw_keyboard:interfaces_java", "//sky/services/updater:interfaces_java", "//sky/services/vsync:interfaces_java", "//sky/services/vsync:vsync_lib", diff --git a/sky/shell/android/org/domokit/sky/shell/PlatformViewAndroid.java b/sky/shell/android/org/domokit/sky/shell/PlatformViewAndroid.java index c12827d7e1a..4737deb7a2a 100644 --- a/sky/shell/android/org/domokit/sky/shell/PlatformViewAndroid.java +++ b/sky/shell/android/org/domokit/sky/shell/PlatformViewAndroid.java @@ -6,6 +6,7 @@ package org.domokit.sky.shell; import android.content.Context; import android.os.Build; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceHolder; @@ -31,6 +32,9 @@ import org.chromium.mojom.sky.ViewportMetrics; import java.util.ArrayList; import java.util.List; +import org.domokit.raw_keyboard.RawKeyboardServiceImpl; +import org.domokit.raw_keyboard.RawKeyboardServiceState; + /** * A view containing Sky */ @@ -43,6 +47,7 @@ public class PlatformViewAndroid extends SurfaceView { private final SurfaceHolder.Callback mSurfaceCallback; private final EdgeDims mPadding; private final KeyboardServiceState mKeyboardState; + private final RawKeyboardServiceState mRawKeyboardState; /** * Dimensions in each of the four cardinal directions. @@ -100,6 +105,23 @@ public class PlatformViewAndroid extends SurfaceView { // TODO(eseidel): We need per-view services! mKeyboardState = new KeyboardServiceState(this); KeyboardServiceImpl.setViewState(mKeyboardState); + + mRawKeyboardState = new RawKeyboardServiceState(); + RawKeyboardServiceImpl.setViewState(mRawKeyboardState); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (mRawKeyboardState.onKey(this, keyCode, event)) + return true; + return super.onKeyUp(keyCode, event); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (mRawKeyboardState.onKey(this, keyCode, event)) + return true; + return super.onKeyDown(keyCode, event); } SkyEngine getEngine() { diff --git a/sky/shell/android/org/domokit/sky/shell/SkyApplication.java b/sky/shell/android/org/domokit/sky/shell/SkyApplication.java index 5fb72860ebb..8166bcd43f6 100644 --- a/sky/shell/android/org/domokit/sky/shell/SkyApplication.java +++ b/sky/shell/android/org/domokit/sky/shell/SkyApplication.java @@ -21,12 +21,14 @@ import org.chromium.mojom.activity.PathService; import org.chromium.mojom.keyboard.KeyboardService; import org.chromium.mojom.media.MediaService; import org.chromium.mojom.mojo.NetworkService; +import org.chromium.mojom.raw_keyboard.RawKeyboardService; import org.chromium.mojom.sensors.SensorService; import org.chromium.mojom.vsync.VSyncProvider; import org.domokit.activity.ActivityImpl; import org.domokit.activity.PathServiceImpl; import org.domokit.media.MediaServiceImpl; import org.domokit.oknet.NetworkServiceImpl; +import org.domokit.raw_keyboard.RawKeyboardServiceImpl; import org.domokit.vsync.VSyncProviderImpl; /** @@ -99,6 +101,13 @@ public class SkyApplication extends BaseChromiumApplication { } }); + registry.register(RawKeyboardService.MANAGER.getName(), new ServiceFactory() { + @Override + public void connectToService(Context context, Core core, MessagePipeHandle pipe) { + RawKeyboardService.MANAGER.bind(new RawKeyboardServiceImpl(), pipe); + } + }); + registry.register(MediaService.MANAGER.getName(), new ServiceFactory() { @Override public void connectToService(Context context, Core core, MessagePipeHandle pipe) {