diff options
author | solb@chromium.org <solb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 09:20:17 +0000 |
---|---|---|
committer | solb@chromium.org <solb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 09:20:17 +0000 |
commit | 192c7a49de6264582d38ad3ed83fc9dc554342f4 (patch) | |
tree | 623dd6593863c3941f8d3149311e949f66e6c4d9 /remoting | |
parent | 316ec762de4612c0ab8eb0e4154ec8dc515d6fd1 (diff) | |
download | chromium_src-192c7a49de6264582d38ad3ed83fc9dc554342f4.zip chromium_src-192c7a49de6264582d38ad3ed83fc9dc554342f4.tar.gz chromium_src-192c7a49de6264582d38ad3ed83fc9dc554342f4.tar.bz2 |
Add Android Chromoting client keyboard input
Tapping the screen with three fingers now shows more options, namely one to pop up a keyboard!
Review URL: https://chromiumcodereview.appspot.com/21120005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214646 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/android/java/AndroidManifest.xml | 7 | ||||
-rw-r--r-- | remoting/android/java/src/org/chromium/chromoting/Desktop.java | 45 | ||||
-rw-r--r-- | remoting/android/java/src/org/chromium/chromoting/DesktopView.java | 60 | ||||
-rw-r--r-- | remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java | 14 | ||||
-rw-r--r-- | remoting/client/jni/android_keymap.cc | 208 | ||||
-rw-r--r-- | remoting/client/jni/android_keymap.h | 23 | ||||
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.cc | 23 | ||||
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.h | 3 | ||||
-rw-r--r-- | remoting/client/jni/jni_interface.cc | 9 | ||||
-rw-r--r-- | remoting/remoting.gyp | 9 | ||||
-rw-r--r-- | remoting/resources/actionbar.xml | 12 | ||||
-rw-r--r-- | remoting/resources/strings.xml | 4 | ||||
-rw-r--r-- | remoting/resources/styles.xml | 8 |
13 files changed, 398 insertions, 27 deletions
diff --git a/remoting/android/java/AndroidManifest.xml b/remoting/android/java/AndroidManifest.xml index 02db6dd..16014ad 100644 --- a/remoting/android/java/AndroidManifest.xml +++ b/remoting/android/java/AndroidManifest.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.chromium.chromoting" - android:versionCode="5" - android:versionName="0.05"> + android:versionCode="6" + android:versionName="0.06"> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14"/> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> @@ -19,6 +19,7 @@ </activity> <activity android:name="Desktop" android:configChanges="orientation|screenSize" - android:theme="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"/> + android:theme="@style/Theme_ElusiveActionBar" + android:windowSoftInputMode="adjustResize"/> </application> </manifest> diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java index 36b6f74..7c8bb11 100644 --- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java +++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java @@ -7,6 +7,12 @@ package org.chromium.chromoting; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; import org.chromium.chromoting.jni.JniInterface; @@ -14,7 +20,7 @@ import org.chromium.chromoting.jni.JniInterface; * A simple screen that does nothing except display a DesktopView and notify it of rotations. */ public class Desktop extends Activity { - /** Whether the device has just been rotated. */ + /** The surface that displays the remote host's desktop feed. */ private DesktopView remoteHostDesktop; /** Called when the activity is first created. */ @@ -36,6 +42,41 @@ public class Desktop extends Activity { @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - remoteHostDesktop.requestCanvasRedraw(); + remoteHostDesktop.requestRecheckConstrainingDimension(); + } + + /** Called to initialize the action bar. */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.actionbar, menu); + return super.onCreateOptionsMenu(menu); + } + + /** Called whenever an action bar button is pressed. */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.actionbar_keyboard: + ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).toggleSoftInput(0, 0); + return true; + case R.id.actionbar_hide: + getActionBar().hide(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + /** Called when a hardware key is pressed, and usually when a software key is pressed. */ + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + JniInterface.keyboardAction(event.getKeyCode(), event.getAction() == KeyEvent.ACTION_DOWN); + + if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { + // We stop this event from propagating further to prevent the keyboard from closing. + return true; + } + + return super.dispatchKeyEvent(event); } } diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java index 52151c6..f02dd78 100644 --- a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java +++ b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java @@ -4,7 +4,8 @@ package org.chromium.chromoting; -import android.content.Context; +import android.app.ActionBar; +import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -52,6 +53,8 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. UNDEFINED, WIDTH, HEIGHT } + private ActionBar mActionBar; + private GestureDetector mScroller; private ScaleGestureDetector mZoomer; @@ -64,6 +67,9 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. /** Specifies the dimension by which the zoom level is being lower-bounded. */ private Constraint mConstraint; + /** Whether the dimension of constraint should be reckecked on the next aspect ratio change. */ + private boolean mRecheckConstraint; + /** Whether the right edge of the image was visible on-screen during the last render. */ private boolean mRightUsedToBeOut; @@ -73,11 +79,10 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. private int mMouseButton; private boolean mMousePressed; - /** Whether the canvas needs to be redrawn. The update occurs when its size is next updated. */ - private boolean mCanvasNeedsRedraw; - - public DesktopView(Context context) { + public DesktopView(Activity context) { super(context); + mActionBar = context.getActionBar(); + getHolder().addCallback(this); DesktopListener listener = new DesktopListener(); mScroller = new GestureDetector(context, listener); @@ -86,15 +91,15 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. mTransform = new Matrix(); mScreenWidth = 0; mScreenHeight = 0; + mConstraint = Constraint.UNDEFINED; + mRecheckConstraint = false; mRightUsedToBeOut = false; mBottomUsedToBeOut = false; mMouseButton = BUTTON_UNDEFINED; mMousePressed = false; - - mCanvasNeedsRedraw = false; } /** @@ -127,8 +132,8 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. boolean recenter = false; if (mConstraint == Constraint.UNDEFINED) { - mConstraint = image.getWidth()/image.getHeight() > mScreenWidth/mScreenHeight ? - Constraint.WIDTH : Constraint.HEIGHT; + mConstraint = (double)image.getWidth()/image.getHeight() > + (double)mScreenWidth/mScreenHeight ? Constraint.WIDTH : Constraint.HEIGHT; recenter = true; // We always rescale and recenter after a rotation. } @@ -209,9 +214,15 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. getHolder().unlockCanvasAndPost(canvas); } - /** Causes the canvas to be redrawn the next time our surface changes. */ - public void requestCanvasRedraw() { - mCanvasNeedsRedraw = true; + /** + * Causes the next canvas redraw to perform a check for which screen dimension more tightly + * constrains the view of the image. This should be called between the time that a screen size + * change is requested and the time it actually occurs. If it is not called in such a case, the + * screen will not be rearranged as aggressively (which is desirable when the software keyboard + * appears in order to allow it to cover the image without forcing a resize). + */ + public void requestRecheckConstrainingDimension() { + mRecheckConstraint = true; } /** @@ -221,15 +232,20 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. @Override public void surfaceChanged( SurfaceHolder holder, int format, int width, int height) { + mActionBar.hide(); + synchronized (mTransform) { mScreenWidth = width; mScreenHeight = height; - mConstraint = Constraint.UNDEFINED; + + if (mRecheckConstraint) { + mConstraint = Constraint.UNDEFINED; + mRecheckConstraint = false; + } } - if (mCanvasNeedsRedraw) { - JniInterface.redrawGraphics(); - mCanvasNeedsRedraw = false; + if (!JniInterface.redrawGraphics()) { + JniInterface.provideRedrawCallback(this); } } @@ -237,7 +253,6 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. @Override public void surfaceCreated(SurfaceHolder holder) { Log.i("deskview", "DesktopView.surfaceCreated(...)"); - JniInterface.provideRedrawCallback(this); } /** @@ -247,10 +262,9 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.i("deskview", "DesktopView.surfaceDestroyed(...)"); - JniInterface.provideRedrawCallback(null); - // Redraw the desktop as soon as the user switches back to this window. - mCanvasNeedsRedraw = true; + // Stop this canvas from being redrawn. + JniInterface.provideRedrawCallback(null); } /** Called when a mouse action is made. */ @@ -270,9 +284,13 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. */ @Override public boolean onTouchEvent(MotionEvent event) { + if (event.getPointerCount() == 3) { + mActionBar.show(); + } + boolean handled = mScroller.onTouchEvent(event) || mZoomer.onTouchEvent(event); - if (event.getPointerCount()==1) { + if (event.getPointerCount() == 1) { float[] coordinates = {event.getRawX(), event.getY()}; switch (event.getActionMasked()) { diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java index 0d7660b..5505618 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java @@ -179,7 +179,7 @@ public class JniInterface { /** Forces the native graphics thread to redraw to the canvas. */ public static boolean redrawGraphics() { synchronized(JniInterface.class) { - if (!sConnected) return false; + if (!sConnected || sRedrawCallback == null) return false; } scheduleRedrawNative(); @@ -222,6 +222,15 @@ public class JniInterface { mouseActionNative(x, y, whichButton, buttonDown); } + /** Presses and releases the specified key. */ + public static void keyboardAction(int keyCode, boolean keyDown) { + if (!sConnected) { + return; + } + + keyboardActionNative(keyCode, keyDown); + } + /** Performs the native response to the user's PIN. */ private static native void authenticationResponse(String pin); @@ -230,4 +239,7 @@ public class JniInterface { /** Passes mouse information to the native handling code. */ private static native void mouseActionNative(int x, int y, int whichButton, boolean buttonDown); + + /** Passes key press information to the native handling code. */ + private static native void keyboardActionNative(int keyCode, boolean keyDown); } diff --git a/remoting/client/jni/android_keymap.cc b/remoting/client/jni/android_keymap.cc new file mode 100644 index 0000000..f427046 --- /dev/null +++ b/remoting/client/jni/android_keymap.cc @@ -0,0 +1,208 @@ +// Copyright 2013 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. + +#include "remoting/client/jni/android_keymap.h" + +namespace { + +// These must be defined in the same order as the Android keycodes in +// <android/keycodes.h> and +// "ui/base/keycodes/keyboard_code_conversion_android.cc" . Some of these +// mappings assume a US keyboard layout for now. +const uint32 usb_keycodes[] = { + 0, // UNKNOWN + 0, // SOFT_LEFT + 0, // SOFT_RIGHT + 0, // HOME + 0, // BACK + 0, // CALL + 0, // ENDCALL + + 0x070027, // 0 + 0x07001e, // 1 + 0x07001f, // 2 + 0x070020, // 3 + 0x070021, // 4 + 0x070022, // 5 + 0x070023, // 6 + 0x070024, // 7 + 0x070025, // 8 + 0x070026, // 9 + + 0, // STAR + 0, // POUND + 0x070052, // DPAD_UP + 0x070051, // DPAD_DOWN + 0x070050, // DPAD_LEFT + 0x07004f, // DPAD_RIGHT + 0, // DPAD_CENTER + 0, // VOLUME_UP + 0, // VOLUME_DOWN + 0, // POWER + 0, // CAMERA + 0, // CLEAR + + 0x070004, // A + 0x070005, // B + 0x070006, // C + 0x070007, // D + 0x070008, // E + 0x070009, // F + 0x07000a, // G + 0x07000b, // H + 0x07000c, // I + 0x07000d, // J + 0x07000e, // K + 0x07000f, // L + 0x070010, // M + 0x070011, // N + 0x070012, // O + 0x070013, // P + 0x070014, // Q + 0x070015, // R + 0x070016, // S + 0x070017, // T + 0x070018, // U + 0x070019, // V + 0x07001a, // W + 0x07001b, // X + 0x07001c, // Y + 0x07001d, // Z + + 0x070036, // COMMA + 0x070037, // PERIOD + + 0x0700e2, // ALT_LEFT + 0x0700e6, // ALT_RIGHT + 0x0700e1, // SHIFT_LEFT + 0x0700e5, // SHIFT_RIGHT + + 0x07002b, // TAB + 0x07002c, // SPACE + + 0, // SYM + 0, // EXPLORER + 0, // ENVELOPE + + 0x070028, // ENTER + 0x07002a, // DEL (backspace) + + 0x070035, // GRAVE (backtick) + 0x07002d, // MINUS + 0x07002e, // EQUALS + 0x07002f, // LEFT_BRACKET + 0x070030, // RIGHT_BRACKET + 0x070031, // BACKSLASH + 0x070033, // SEMICOLON + 0x070034, // APOSTROPHE + 0x070038, // SLASH + + 0, // AT + 0, // NUM + 0, // HEADSETHOOK + 0, // FOCUS + 0, // PLUS + 0, // MENU + 0, // NOTIFICATION + 0, // SEARCH + 0, // MEDIA_PLAY_PAUSE + 0, // MEDIA_STOP + 0, // MEDIA_NEXT + 0, // MEDIA_PREVIOUS + 0, // MEDIA_REWIND + 0, // MEDIA_FAST_FORWARD + 0, // MUTE + + 0x07004b, // PAGE_UP + 0x07004e, // PAGE_DOWN + + 0, // PICTSYMBOLS + 0, // SWITCH_CHARSET + 0, // BUTTON_A + 0, // BUTTON_B + 0, // BUTTON_C + 0, // BUTTON_X + 0, // BUTTON_Y + 0, // BUTTON_Z + 0, // BUTTON_L1 + 0, // BUTTON_R1 + 0, // BUTTON_L2 + 0, // BUTTON_R2 + 0, // BUTTON_THUMBL + 0, // BUTTON_THUMBR + 0, // BUTTON_START + 0, // BUTTON_SELECT + 0, // BUTTON_MODE + + 0x070029, // ESCAPE + 0x07004c, // FORWARD_DEL + + 0x0700e0, // CTRL_LEFT + 0x0700e4, // CTRL_RIGHT + 0, // CAPS_LOCK + 0, // SCROLL_LOCK + 0x0700e3, // META_LEFT + 0x0700e7, // META_RIGHT + 0, // FUNCTION + + 0x070046, // SYSRQ (printscreen) + 0x070048, // BREAK (pause) + 0x07004a, // MOVE_HOME (home) + 0x07004d, // MOVE_END (end) + 0x070049, // INSERT + + 0, // FORWARD + 0, // MEDIA_PLAY + 0, // MEDIA_PAUSE + 0, // MEDIA_CLOSE + 0, // MEDIA_EJECT + 0, // MEDIA_RECORD + + 0x07003a, // F1 + 0x07003b, // F2 + 0x07003c, // F3 + 0x07003d, // F4 + 0x07003e, // F5 + 0x07003f, // F6 + 0x070040, // F7 + 0x070041, // F8 + 0x070042, // F9 + 0x070043, // F10 + 0x070044, // F11 + 0x070045, // F12 + + 0, // NUM_LOCK + + 0x070062, // NUMPAD_0 + 0x070059, // NUMPAD_1 + 0x07005a, // NUMPAD_2 + 0x07005b, // NUMPAD_3 + 0x07005c, // NUMPAD_4 + 0x07005d, // NUMPAD_5 + 0x07005e, // NUMPAD_6 + 0x07005f, // NUMPAD_7 + 0x070060, // NUMPAD_8 + 0x070061, // NUMPAD_9 + + 0x070054, // NUMPAD_DIVIDE + 0x070055, // NUMPAD_MULTIPLY + 0x070056, // NUMPAD_SUBTRACT + 0x070057, // NUMPAD_ADD + 0x070063, // NUMPAD_DOT + 0x070085, // NUMPAD_COMMA + 0x070058, // NUMPAD_ENTER + 0x070067, // NUMPAD_EQUALS + 0x0700b6, // NUMPAD_LEFT_PAREN + 0x0700b7, // NUMPAD_RIGHT_PAREN +}; + +} + +namespace remoting { + +uint32 AndroidKeycodeToUsbKeycode(int android) { + return usb_keycodes[android]; +} + +} // namespace remoting diff --git a/remoting/client/jni/android_keymap.h b/remoting/client/jni/android_keymap.h new file mode 100644 index 0000000..9a9f3a3 --- /dev/null +++ b/remoting/client/jni/android_keymap.h @@ -0,0 +1,23 @@ +// Copyright 2013 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. + +#ifndef REMOTING_CLIENT_JNI_ANDROID_KEYMAP_H_ +#define REMOTING_CLIENT_JNI_ANDROID_KEYMAP_H_ + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" + +namespace remoting { + +// This is a temporary hack to convert Android's virtual keycodes into USB +// scancodes. Unfortunately, the current solution uses key mappings whose +// layout is determined according to the client device's input locale instead +// of the host's internationalization preferences. The whole process needs to +// be rethought to accomplish this in an localizable and future-proof way. +// TODO(solb): crbug.com/265945 +uint32 AndroidKeycodeToUsbKeycode(int android); + +} // namespace remoting + +#endif diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc index ecf8632..dcec68f 100644 --- a/remoting/client/jni/chromoting_jni_instance.cc +++ b/remoting/client/jni/chromoting_jni_instance.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/logging.h" #include "remoting/client/audio_player.h" +#include "remoting/client/jni/android_keymap.h" #include "remoting/client/jni/chromoting_jni_runtime.h" #include "remoting/protocol/libjingle_transport_factory.h" @@ -105,6 +106,28 @@ void ChromotingJniInstance::PerformMouseAction( connection_->input_stub()->InjectMouseEvent(action); } +void ChromotingJniInstance::PerformKeyboardAction(int keyCode, bool keyDown) { + if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) { + jni_runtime_->network_task_runner()->PostTask( + FROM_HERE, + base::Bind(&ChromotingJniInstance::PerformKeyboardAction, + this, + keyCode, + keyDown)); + return; + } + + uint32 usbCode = AndroidKeycodeToUsbKeycode(keyCode); + if (usbCode) { + protocol::KeyEvent action; + action.set_usb_keycode(usbCode); + action.set_pressed(keyDown); + connection_->input_stub()->InjectKeyEvent(action); + } + else + LOG(WARNING) << "Ignoring unknown keycode: " << keyCode; +} + void ChromotingJniInstance::OnConnectionState( protocol::ConnectionToHost::State state, protocol::ErrorCode error) { diff --git a/remoting/client/jni/chromoting_jni_instance.h b/remoting/client/jni/chromoting_jni_instance.h index 5a26cf4..9fb1516 100644 --- a/remoting/client/jni/chromoting_jni_instance.h +++ b/remoting/client/jni/chromoting_jni_instance.h @@ -64,6 +64,9 @@ class ChromotingJniInstance protocol::MouseEvent_MouseButton button, bool buttonDown); + // Sends the provided keyboard scan code to the host. + void PerformKeyboardAction(int keyCode, bool keyDown); + // ClientUserInterface implementation. virtual void OnConnectionState( protocol::ConnectionToHost::State state, diff --git a/remoting/client/jni/jni_interface.cc b/remoting/client/jni/jni_interface.cc index 5dc462d..5ca45a0 100644 --- a/remoting/client/jni/jni_interface.cc +++ b/remoting/client/jni/jni_interface.cc @@ -127,4 +127,13 @@ JNIEXPORT void JNICALL JNI_IMPLEMENTATION(mouseActionNative)( button_down); } +JNIEXPORT void JNICALL JNI_IMPLEMENTATION(keyboardActionNative)( + JNIEnv* env, + jobject that, + jint key_code, + jboolean key_down) { + remoting::ChromotingJniRuntime::GetInstance()->session()-> + PerformKeyboardAction(key_code, key_down); +} + } // extern "C" diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index c8c14cd..890775c 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -1694,6 +1694,8 @@ '../google_apis/google_apis.gyp:google_apis', ], 'sources': [ + 'client/jni/android_keymap.cc', + 'client/jni/android_keymap.h', 'client/jni/chromoting_jni_instance.cc', 'client/jni/chromoting_jni_instance.h', 'client/jni/chromoting_jni_runtime.cc', @@ -1722,9 +1724,16 @@ ], }, { + 'destination': '<(SHARED_INTERMEDIATE_DIR)/remoting/android/res/menu', + 'files': [ + 'resources/actionbar.xml', + ], + }, + { 'destination': '<(SHARED_INTERMEDIATE_DIR)/remoting/android/res/values', 'files': [ 'resources/strings.xml', + 'resources/styles.xml', ], }, ], diff --git a/remoting/resources/actionbar.xml b/remoting/resources/actionbar.xml new file mode 100644 index 0000000..4cf611ed --- /dev/null +++ b/remoting/resources/actionbar.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Action bar buttons for the Android app--> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/actionbar_keyboard" + android:title="@string/actionbar_keyboard" + android:icon="@android:drawable/ic_menu_edit" + android:showAsAction="ifRoom|withText"/> + <item android:id="@+id/actionbar_hide" + android:title="@string/actionbar_hide" + android:icon="@android:drawable/ic_menu_close_clear_cancel" + android:showAsAction="ifRoom|withText"/> +</menu> diff --git a/remoting/resources/strings.xml b/remoting/resources/strings.xml index e2efc8e..27dad55 100644 --- a/remoting/resources/strings.xml +++ b/remoting/resources/strings.xml @@ -14,6 +14,10 @@ <string name="pin_entry_connect">Connect</string> <string name="pin_entry_cancel">Cancel</string> + <!--Action bar buttons--> + <string name="actionbar_hide">Hide</string> + <string name="actionbar_keyboard">Keyboard</string> + <!--Informative messages--> <string name="msg_pin_canceled">No PIN was provided, so the connection attempt was canceled</string> <string name="msg_pin_entered">Attempting to authenticate to specified host with provided PIN</string> diff --git a/remoting/resources/styles.xml b/remoting/resources/styles.xml new file mode 100644 index 0000000..ecd4929 --- /dev/null +++ b/remoting/resources/styles.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Activity styles for the Android app--> +<resources> + <style name="Theme_ElusiveActionBar"> + <item name="android:windowActionBarOverlay">true</item> + <item name="android:actionBarStyle">@android:style/Widget.DeviceDefault.ActionBar.Solid</item> + </style> +</resources> |