summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
authormasiullah <masiullah@gmail.com>2012-07-14 19:05:57 +0530
committerDavid Ferguson <ferguson.david@gmail.com>2013-04-09 13:03:14 -0400
commitd8ddc09cd2a0246bc2a403c540b301373c6d974a (patch)
tree220c41066477fc5c6eab4b2b58f723b6f3c5e874 /policy
parentb5e8b8ce6f49e28b46955f6a31b71e02eac5f333 (diff)
downloadframeworks_base-d8ddc09cd2a0246bc2a403c540b301373c6d974a.zip
frameworks_base-d8ddc09cd2a0246bc2a403c540b301373c6d974a.tar.gz
frameworks_base-d8ddc09cd2a0246bc2a403c540b301373c6d974a.tar.bz2
Stylus gestures features (1/2)
Forward-port of https://github.com/CyanogenMod/android_frameworks_base/commit/9f3ee9f7c0877fcfbe90a7c176481f949194fb75 to JB Change-Id: I9c8a03dce226d2463659846ff3a12435efdf5c1d
Diffstat (limited to 'policy')
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java264
1 files changed, 263 insertions, 1 deletions
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 41d67bc..bde50e0 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -40,11 +40,20 @@ import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.ActionBarView;
import android.app.KeyguardManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.content.ActivityNotFoundException;
+import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -53,10 +62,14 @@ import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.provider.Settings;
import android.util.AndroidRuntimeException;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -65,6 +78,8 @@ import android.util.SparseArray;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ContextThemeWrapper;
+import android.view.GestureDetector;
+import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Gravity;
import android.view.IRotationWatcher;
import android.view.IWindowManager;
@@ -92,10 +107,14 @@ import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.TextView;
+import android.widget.Toast;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.R;
+
/**
* Android-specific Window.
* <p>
@@ -180,7 +199,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private int mTitleColor = 0;
private boolean mAlwaysReadCloseOnTouchAttr = false;
-
+
+ private boolean mEnableGestures;
+
+ private Context mContext;
private ContextMenuBuilder mContextMenu;
private MenuDialogHelper mContextMenuHelper;
private boolean mClosingActionMenu;
@@ -190,6 +212,36 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private AudioManager mAudioManager;
private KeyguardManager mKeyguardManager;
+ private final class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(Settings.System
+ .getUriFor(Settings.System.ENABLE_STYLUS_GESTURES), false,
+ this);
+ checkGestures();
+ }
+
+ void unobserve() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ checkGestures();
+ }
+
+ void checkGestures() {
+ mEnableGestures = Settings.System.getInt(
+ mContext.getContentResolver(),
+ Settings.System.ENABLE_STYLUS_GESTURES, 0) == 1;
+ }
+ }
+
private int mUiOptions = 0;
private boolean mInvalidatePanelMenuPosted;
@@ -215,6 +267,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
public PhoneWindow(Context context) {
super(context);
+ mContext = context;
mLayoutInflater = LayoutInflater.from(context);
}
@@ -1812,9 +1865,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private PopupWindow mActionModePopup;
private Runnable mShowActionModePopup;
+ private SettingsObserver mSettingsObserver;
+
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
+ mSettingsObserver = new SettingsObserver(new Handler());
}
@Override
@@ -1895,8 +1951,210 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return false;
}
+ private final StylusGestureFilter mStylusFilter = new StylusGestureFilter();
+
+ private class StylusGestureFilter extends SimpleOnGestureListener {
+
+ private final static int SWIPE_UP = 1;
+ private final static int SWIPE_DOWN = 2;
+ private final static int SWIPE_LEFT = 3;
+ private final static int SWIPE_RIGHT = 4;
+ private final static int PRESS_LONG = 5;
+ private final static int TAP_DOUBLE = 6;
+ private final static double SWIPE_MIN_DISTANCE = 25.0;
+ private final static double SWIPE_MIN_VELOCITY = 50.0;
+ private final static int KEY_NO_ACTION = 1000;
+ private final static int KEY_HOME = 1001;
+ private final static int KEY_BACK = 1002;
+ private final static int KEY_MENU = 1003;
+ private final static int KEY_SEARCH = 1004;
+ private final static int KEY_RECENT = 1005;
+ private final static int KEY_APP = 1006;
+ private GestureDetector mDetector;
+ private final static String TAG = "StylusGestureFilter";
+
+ public StylusGestureFilter() {
+ mDetector = new GestureDetector(this);
+ }
+
+ public boolean onTouchEvent(MotionEvent event) {
+ return mDetector.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+
+ final float xDistance = Math.abs(e1.getX() - e2.getX());
+ final float yDistance = Math.abs(e1.getY() - e2.getY());
+
+ velocityX = Math.abs(velocityX);
+ velocityY = Math.abs(velocityY);
+ boolean result = false;
+
+ if (velocityX > (SWIPE_MIN_VELOCITY * getResources().getDisplayMetrics().density)
+ && xDistance > (SWIPE_MIN_DISTANCE * getResources().getDisplayMetrics().density)
+ && xDistance > yDistance) {
+ if (e1.getX() > e2.getX()) { // right to left
+ // Swipe Left
+ dispatchStylusAction(SWIPE_LEFT);
+ } else {
+ // Swipe Right
+ dispatchStylusAction(SWIPE_RIGHT);
+ }
+ result = true;
+ } else if (velocityY > (SWIPE_MIN_VELOCITY * getResources().getDisplayMetrics().density)
+ && yDistance > (SWIPE_MIN_DISTANCE * getResources().getDisplayMetrics().density)
+ && yDistance > xDistance) {
+ if (e1.getY() > e2.getY()) { // bottom to up
+ // Swipe Up
+ dispatchStylusAction(SWIPE_UP);
+ } else {
+ // Swipe Down
+ dispatchStylusAction(SWIPE_DOWN);
+ }
+ result = true;
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent arg0) {
+ dispatchStylusAction(TAP_DOUBLE);
+ return true;
+ }
+
+ public void onLongPress(MotionEvent e) {
+ dispatchStylusAction(PRESS_LONG);
+ }
+
+ }
+
+ private void menuAction() {
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_MENU));
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
+ KeyEvent.KEYCODE_MENU));
+
+ }
+
+ private void backAction() {
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_BACK));
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
+ KeyEvent.KEYCODE_BACK));
+ }
+
+ private void dispatchStylusAction(int gestureAction) {
+ final ContentResolver resolver = mContext.getContentResolver();
+ boolean isSystemUI = mContext.getPackageName().equals("com.android.systemui");
+ String setting = null;
+ int dispatchAction = -1;
+ switch (gestureAction) {
+ case StylusGestureFilter.SWIPE_LEFT:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_LEFT_SWIPE);
+ break;
+ case StylusGestureFilter.SWIPE_RIGHT:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_RIGHT_SWIPE);
+ break;
+ case StylusGestureFilter.SWIPE_UP:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_UP_SWIPE);
+ break;
+ case StylusGestureFilter.SWIPE_DOWN:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_DOWN_SWIPE);
+ break;
+ case StylusGestureFilter.TAP_DOUBLE:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_DOUBLE_TAP);
+ break;
+ case StylusGestureFilter.PRESS_LONG:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_LONG_PRESS);
+ break;
+ default:
+ return;
+ }
+
+ try {
+ int value = Integer.valueOf(setting);
+ if (value == StylusGestureFilter.KEY_NO_ACTION) {
+ return;
+ }
+ dispatchAction = value;
+ } catch (NumberFormatException e) {
+ dispatchAction = StylusGestureFilter.KEY_APP;
+ }
+
+ // Dispatching action
+ switch (dispatchAction) {
+ case StylusGestureFilter.KEY_HOME:
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(homeIntent);
+ break;
+ case StylusGestureFilter.KEY_BACK:
+ backAction();
+ break;
+ case StylusGestureFilter.KEY_MENU:
+ // Menu action on notificationbar / systemui will be converted
+ // to back action
+ if (isSystemUI) {
+ backAction();
+ break;
+ }
+ menuAction();
+ break;
+ case StylusGestureFilter.KEY_SEARCH:
+ // Search action on notificationbar / systemui will be converted
+ // to back action
+ if (isSystemUI) {
+ backAction();
+ break;
+ }
+ launchDefaultSearch();
+ break;
+ case StylusGestureFilter.KEY_RECENT:
+ IStatusBarService mStatusBarService = IStatusBarService.Stub
+ .asInterface(ServiceManager.getService("statusbar"));
+ try {
+ mStatusBarService.toggleRecentApps();
+ } catch (RemoteException e) {
+ }
+ break;
+ case StylusGestureFilter.KEY_APP:
+ // Launching app on notificationbar / systemui will be preceded
+ // with a back Action
+ if (isSystemUI) {
+ backAction();
+ }
+ try {
+ final PackageManager pm = mContext.getPackageManager();
+ Intent launchIntent = pm.getLaunchIntentForPackage(setting);
+ if (launchIntent != null) {
+ mContext.startActivity(launchIntent);
+ }
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(mContext, mContext.getString(R.string.stylus_app_not_installed, setting),
+ Toast.LENGTH_LONG).show();
+ }
+ break;
+ }
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
+ // Stylus events with side button pressed are filtered and other
+ // events are processed normally.
+ if (mEnableGestures
+ && MotionEvent.BUTTON_SECONDARY == ev.getButtonState()) {
+ mStylusFilter.onTouchEvent(ev);
+ return false;
+ }
final Callback cb = getCallback();
return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)
: super.dispatchTouchEvent(ev);
@@ -2462,6 +2720,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ mSettingsObserver.observe();
+
updateWindowResizeState();
final Callback cb = getCallback();
@@ -2485,6 +2745,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ mSettingsObserver.unobserve();
+
final Callback cb = getCallback();
if (cb != null && mFeatureId < 0) {
cb.onDetachedFromWindow();