aboutsummaryrefslogtreecommitdiff
path: root/KBars/app
diff options
context:
space:
mode:
Diffstat (limited to 'KBars/app')
-rw-r--r--KBars/app/build.gradle34
-rw-r--r--KBars/app/src/main/AndroidManifest.xml32
-rw-r--r--KBars/app/src/main/assets/background.pngbin0 -> 20352 bytes
-rw-r--r--KBars/app/src/main/java/js/kbars/CameraBackgroundMenuItem.java102
-rw-r--r--KBars/app/src/main/java/js/kbars/DropShadowActivity.java40
-rw-r--r--KBars/app/src/main/java/js/kbars/FitSystemWindowsActivity.java184
-rw-r--r--KBars/app/src/main/java/js/kbars/IdentifyBarsButton.java21
-rw-r--r--KBars/app/src/main/java/js/kbars/ImageBackgroundMenuItem.java109
-rw-r--r--KBars/app/src/main/java/js/kbars/ImmersiveModeToggleButton.java79
-rw-r--r--KBars/app/src/main/java/js/kbars/KBarsActivity.java273
-rw-r--r--KBars/app/src/main/java/js/kbars/KBarsCar.java38
-rw-r--r--KBars/app/src/main/java/js/kbars/KBarsDream.java47
-rw-r--r--KBars/app/src/main/java/js/kbars/LightsOutModeToggleButton.java26
-rw-r--r--KBars/app/src/main/java/js/kbars/MediaModeToggleButton.java95
-rw-r--r--KBars/app/src/main/java/js/kbars/RandomColorBackgroundMenuItem.java29
-rw-r--r--KBars/app/src/main/java/js/kbars/SystemGestureDebugger.java216
-rw-r--r--KBars/app/src/main/java/js/kbars/ToastActivity.java117
-rw-r--r--KBars/app/src/main/java/js/kbars/TouchTrackingLayout.java298
-rw-r--r--KBars/app/src/main/java/js/kbars/TransparencyToggleButton.java43
-rw-r--r--KBars/app/src/main/java/js/kbars/Util.java42
-rw-r--r--KBars/app/src/main/res/drawable-hdpi-v4/ic_launcher.pngbin0 -> 2327 bytes
-rw-r--r--KBars/app/src/main/res/drawable-mdpi-v4/ic_launcher.pngbin0 -> 1530 bytes
-rw-r--r--KBars/app/src/main/res/drawable-xhdpi-v4/ic_launcher.pngbin0 -> 3235 bytes
-rw-r--r--KBars/app/src/main/res/drawable-xxhdpi-v4/ic_launcher.pngbin0 -> 4663 bytes
-rw-r--r--KBars/app/src/main/res/raw/clipcanvas.mp4bin0 -> 1137202 bytes
-rw-r--r--KBars/app/src/main/res/values/strings.xml8
-rw-r--r--KBars/app/src/main/res/values/styles.xml7
27 files changed, 1840 insertions, 0 deletions
diff --git a/KBars/app/build.gradle b/KBars/app/build.gradle
new file mode 100644
index 0000000..eee6df5
--- /dev/null
+++ b/KBars/app/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.application'
+
+apply plugin: 'kotlin-android'
+
+apply plugin: 'kotlin-android-extensions'
+
+android {
+ compileSdkVersion 26
+ buildToolsVersion "26.0.0"
+ defaultConfig {
+ applicationId "js.kbars"
+ minSdkVersion 19
+ targetSdkVersion 26
+ versionCode 100
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
+ implementation 'com.android.support:appcompat-v7:25.4.0'
+ testImplementation 'junit:junit:4.12'
+}
diff --git a/KBars/app/src/main/AndroidManifest.xml b/KBars/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f330c7b
--- /dev/null
+++ b/KBars/app/src/main/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="js.kbars">
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:debuggable="true" android:allowBackup="true">
+ <activity android:label="@string/app_name" android:name=".KBarsActivity" android:launchMode="singleTask">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:label="DropShadowActivity" android:name=".DropShadowActivity">
+ </activity>
+ <activity android:label="(kbars-toast)" android:name=".ToastActivity" android:launchMode="singleTask">
+ </activity>
+ <service android:label="(kbars-dream)" android:name=".KBarsDream" android:exported="true">
+ <intent-filter>
+ <action android:name="android.service.dreams.DreamService" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </service>
+ <activity android:label="(kbars-car)" android:name=".KBarsCar" android:exported="true" android:launchMode="singleTask">
+ <meta-data android:name="android.dock_home" android:value="true" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.CAR_DOCK" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/KBars/app/src/main/assets/background.png b/KBars/app/src/main/assets/background.png
new file mode 100644
index 0000000..aae8a33
--- /dev/null
+++ b/KBars/app/src/main/assets/background.png
Binary files differ
diff --git a/KBars/app/src/main/java/js/kbars/CameraBackgroundMenuItem.java b/KBars/app/src/main/java/js/kbars/CameraBackgroundMenuItem.java
new file mode 100644
index 0000000..8d25d34
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/CameraBackgroundMenuItem.java
@@ -0,0 +1,102 @@
+package js.kbars;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.View;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public final class CameraBackgroundMenuItem implements OnMenuItemClickListener {
+ public static final int REQUEST_CODE = 123;
+ private final Activity mActivity;
+ private final View mTarget;
+
+ public CameraBackgroundMenuItem(Menu menu, Activity activity, View target) {
+ this.mActivity = activity;
+ this.mTarget = target;
+ menu.add("Camera image background...").setOnMenuItemClickListener(this);
+ loadBitmap();
+ }
+
+ public boolean onMenuItemClick(MenuItem item) {
+ chooseBackground();
+ return true;
+ }
+
+ public void onActivityResult(int resultCode, Intent data) {
+ if (resultCode == -1) {
+ Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
+ if (bitmap != null) {
+ setTargetBackground(bitmap);
+ saveBitmap(bitmap);
+ }
+ }
+ }
+
+ private void chooseBackground() {
+ this.mActivity.startActivityForResult(new Intent("android.media.action.IMAGE_CAPTURE"), REQUEST_CODE);
+ }
+
+ private File bitmapFile() {
+ return new File(this.mActivity.getCacheDir(), "background.png");
+ }
+
+ private void saveBitmap(Bitmap bitmap) {
+ FileNotFoundException e;
+ Throwable th;
+ File f = bitmapFile();
+ if (f.exists()) {
+ f.delete();
+ }
+ if (bitmap != null) {
+ FileOutputStream out = null;
+ try {
+ FileOutputStream out2 = new FileOutputStream(f);
+ bitmap.compress(CompressFormat.PNG, 100, out2);
+ out2.close();
+ } catch (FileNotFoundException e1) {
+ e1.printStackTrace();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ private void loadBitmap() {
+ Bitmap bitmap = loadBitmapFromCache();
+ if (bitmap == null) {
+ bitmap = loadBitmapFromAssets();
+ }
+ setTargetBackground(bitmap);
+ }
+
+ private Bitmap loadBitmapFromCache() {
+ File f = bitmapFile();
+ return f.exists() ? BitmapFactory.decodeFile(f.getAbsolutePath()) : null;
+ }
+
+ private Bitmap loadBitmapFromAssets() {
+ try {
+ return BitmapFactory.decodeStream(this.mActivity.getAssets().open("background.png"));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void setTargetBackground(Bitmap bitmap) {
+ if (bitmap == null) {
+ this.mTarget.setBackground(null);
+ } else {
+ this.mTarget.setBackground(new BitmapDrawable(this.mActivity.getResources(), bitmap));
+ }
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/DropShadowActivity.java b/KBars/app/src/main/java/js/kbars/DropShadowActivity.java
new file mode 100644
index 0000000..79577d9
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/DropShadowActivity.java
@@ -0,0 +1,40 @@
+package js.kbars;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.BlurMaskFilter;
+import android.graphics.BlurMaskFilter.Blur;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+
+public class DropShadowActivity extends Activity {
+ private final Context mContext = this;
+ private ImageView mImageView;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.mImageView = new ImageView(this.mContext);
+ this.mImageView.setBackgroundColor(-1);
+ this.mImageView.setScaleType(ScaleType.CENTER);
+ this.mImageView.setScaleX(1.0f);
+ this.mImageView.setScaleY(1.0f);
+ setContentView(this.mImageView);
+ setImage();
+ }
+
+ private void setImage() {
+ BlurMaskFilter blurFilter = new BlurMaskFilter(1.0f, Blur.SOLID);
+ Paint shadowPaint = new Paint();
+ int[] offsetXY = new int[2];
+ Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), 17301624);
+ Bitmap shadowImage32 = originalBitmap.extractAlpha(shadowPaint, offsetXY).copy(Config.ARGB_8888, true);
+ new Canvas(shadowImage32).drawBitmap(originalBitmap, (float) ((-offsetXY[0]) - 10), (float) ((-offsetXY[1]) - 10), null);
+ this.mImageView.setImageBitmap(shadowImage32);
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/FitSystemWindowsActivity.java b/KBars/app/src/main/java/js/kbars/FitSystemWindowsActivity.java
new file mode 100644
index 0000000..35ff6ae
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/FitSystemWindowsActivity.java
@@ -0,0 +1,184 @@
+package js.kbars;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnSystemUiVisibilityChangeListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class FitSystemWindowsActivity extends Activity {
+ private static final int SYSTEM_UI_CLEARABLE_FLAGS = 7;
+ private static final int SYSTEM_UI_FLAG_ALLOW_TRANSIENT = 2048;
+ private static final int SYSTEM_UI_FLAG_TRANSPARENT_NAVIGATION = 8192;
+ private static final int SYSTEM_UI_FLAG_TRANSPARENT_STATUS = 4096;
+ private final Context mContext = this;
+ private FlagStateTextView mFlagStateTextView;
+ private final Handler mHandler = new Handler();
+ private LinearLayout mLayout;
+ private final Runnable mUpdateText = new Runnable() {
+ public void run() {
+ FitSystemWindowsActivity.this.mFlagStateTextView.updateText();
+ }
+ };
+
+ private static class Flag implements Comparable<Flag> {
+ public static Flag[] ALL = find();
+ public String caption;
+ public int value;
+
+ private Flag() {
+ }
+
+ private static Flag[] find() {
+ List<Flag> flags = new ArrayList();
+ String prefix = "SYSTEM_UI_FLAG_";
+ for (Field f : View.class.getFields()) {
+ if (f.getName().startsWith(prefix)) {
+ Flag flag = new Flag();
+ flag.caption = f.getName().substring(prefix.length()).replace("NAVIGATION", "NAV").replace("TRANSPARENT", "TRANSP").replace("LAYOUT", "LAY");
+ try {
+ flag.value = f.getInt(null);
+ if (flag.value != 0) {
+ flags.add(flag);
+ }
+ } catch (Throwable t) {
+ RuntimeException runtimeException = new RuntimeException(t);
+ }
+ }
+ }
+ Collections.sort(flags);
+ return (Flag[]) flags.toArray(new Flag[flags.size()]);
+ }
+
+ public int compareTo(Flag another) {
+ if (this.value < another.value) {
+ return -1;
+ }
+ return this.value > another.value ? 1 : 0;
+ }
+ }
+
+ private class FlagCheckBox extends CheckBox {
+ private final Flag mFlag;
+
+ public FlagCheckBox(Context context, Flag flag) {
+ super(context);
+ setText(flag.caption);
+ this.mFlag = flag;
+ }
+ }
+
+ private class FlagSetButton extends Button {
+ public FlagSetButton(Context context) {
+ super(context);
+ setText("Set visibility");
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ FlagSetButton.this.set();
+ }
+ });
+ }
+
+ private void set() {
+ ViewGroup parent = (ViewGroup) getParent();
+ int n = parent.getChildCount();
+ int vis = 0;
+ for (int i = 0; i < n; i++) {
+ View v = parent.getChildAt(i);
+ if (v instanceof FlagCheckBox) {
+ FlagCheckBox cb = (FlagCheckBox) v;
+ if (cb.isChecked()) {
+ vis |= cb.mFlag.value;
+ }
+ }
+ }
+ FitSystemWindowsActivity.this.update(vis);
+ }
+ }
+
+ private class FlagStateTextView extends TextView {
+ public FlagStateTextView(Context context) {
+ super(context);
+ updateText();
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ FlagStateTextView.this.updateText();
+ }
+ });
+ }
+
+ private void updateText() {
+ StringBuilder sb = new StringBuilder();
+ append(sb, "vis", FitSystemWindowsActivity.this.mLayout.getSystemUiVisibility());
+ append(sb, "win", getWindowSystemUiVisibility());
+ setText(sb.toString());
+ }
+
+ private void append(StringBuilder sb, String caption, int vis) {
+ if (sb.length() > 0) {
+ sb.append('\n');
+ }
+ sb.append(caption).append(':');
+ boolean first = true;
+ for (Flag flag : Flag.ALL) {
+ if ((flag.value & vis) != 0) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(flag.caption);
+ }
+ }
+ }
+ }
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.mLayout = new LinearLayout(this.mContext) {
+ protected boolean fitSystemWindows(Rect insets) {
+ Rect insetsBefore = new Rect(insets);
+ String msg = String.format("before=%s\nrt=%s\nafter=%s", new Object[]{insetsBefore.toShortString(), Boolean.valueOf(super.fitSystemWindows(insets)), insets.toShortString()});
+ return super.fitSystemWindows(insets);
+ }
+ };
+ this.mLayout.setOrientation(1);
+ for (Flag flag : Flag.ALL) {
+ this.mLayout.addView(new FlagCheckBox(this.mContext, flag));
+ }
+ this.mLayout.addView(new FlagSetButton(this.mContext));
+ LinearLayout linearLayout = this.mLayout;
+ View flagStateTextView = new FlagStateTextView(this.mContext);
+ this.mFlagStateTextView = (FlagStateTextView) flagStateTextView;
+ linearLayout.addView(flagStateTextView);
+ this.mLayout.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
+ public void onSystemUiVisibilityChange(int vis) {
+ FitSystemWindowsActivity.this.updateTextDelayed();
+ }
+ });
+ this.mLayout.setPadding(0, 146, 0, 0);
+ setContentView(this.mLayout);
+ }
+
+ private void update(int vis) {
+ this.mLayout.setSystemUiVisibility(vis);
+ updateTextDelayed();
+ }
+
+ private void updateTextDelayed() {
+ this.mHandler.removeCallbacks(this.mUpdateText);
+ this.mHandler.postDelayed(this.mUpdateText, 500);
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/IdentifyBarsButton.java b/KBars/app/src/main/java/js/kbars/IdentifyBarsButton.java
new file mode 100644
index 0000000..18223d0
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/IdentifyBarsButton.java
@@ -0,0 +1,21 @@
+package js.kbars;
+
+import android.content.Context;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class IdentifyBarsButton extends Button {
+ public IdentifyBarsButton(Context context) {
+ super(context);
+ setText("Identify system bars");
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ IdentifyBarsButton.this.identifyBars();
+ }
+ });
+ }
+
+ private void identifyBars() {
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/ImageBackgroundMenuItem.java b/KBars/app/src/main/java/js/kbars/ImageBackgroundMenuItem.java
new file mode 100644
index 0000000..8052d9e
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/ImageBackgroundMenuItem.java
@@ -0,0 +1,109 @@
+package js.kbars;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.View;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public final class ImageBackgroundMenuItem implements OnMenuItemClickListener {
+ public static final int REQUEST_CODE = 234;
+ private static final String TAG = ImageBackgroundMenuItem.class.getSimpleName();
+ private final Activity mActivity;
+ private final View mTarget;
+
+ public ImageBackgroundMenuItem(Menu menu, Activity activity, View target) {
+ this.mActivity = activity;
+ this.mTarget = target;
+ menu.add("Select image background...").setOnMenuItemClickListener(this);
+ loadBitmap();
+ }
+
+ public boolean onMenuItemClick(MenuItem item) {
+ chooseBackground();
+ return true;
+ }
+
+ public void onActivityResult(int resultCode, Intent data) {
+ if (resultCode == -1) {
+ Uri image = data.getData();
+ try {
+ Bitmap bitmap = BitmapFactory.decodeStream(this.mActivity.getContentResolver().openInputStream(image));
+ if (bitmap != null) {
+ setTargetBackground(bitmap);
+ saveBitmap(bitmap);
+ }
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Error getting image " + image, e);
+ }
+ }
+ }
+
+ private void chooseBackground() {
+ Intent photoPickerIntent = new Intent("android.intent.action.PICK");
+ photoPickerIntent.setType("image/*");
+ this.mActivity.startActivityForResult(photoPickerIntent, REQUEST_CODE);
+ }
+
+ private File bitmapFile() {
+ return new File(this.mActivity.getCacheDir(), "background.png");
+ }
+
+ private void saveBitmap(Bitmap bitmap) {
+ FileNotFoundException e;
+ Throwable th;
+ File f = bitmapFile();
+ if (f.exists()) {
+ f.delete();
+ }
+ if (bitmap != null) {
+ try {
+ FileOutputStream out = new FileOutputStream(f);
+ bitmap.compress(CompressFormat.PNG, 100, out);
+ out.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ private void loadBitmap() {
+ Bitmap bitmap = loadBitmapFromCache();
+ if (bitmap == null) {
+ bitmap = loadBitmapFromAssets();
+ }
+ setTargetBackground(bitmap);
+ }
+
+ private Bitmap loadBitmapFromCache() {
+ File f = bitmapFile();
+ return f.exists() ? BitmapFactory.decodeFile(f.getAbsolutePath()) : null;
+ }
+
+ private Bitmap loadBitmapFromAssets() {
+ try {
+ return BitmapFactory.decodeStream(this.mActivity.getAssets().open("background.png"));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void setTargetBackground(Bitmap bitmap) {
+ if (bitmap == null) {
+ this.mTarget.setBackground(null);
+ } else {
+ this.mTarget.setBackground(new BitmapDrawable(this.mActivity.getResources(), bitmap));
+ }
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/ImmersiveModeToggleButton.java b/KBars/app/src/main/java/js/kbars/ImmersiveModeToggleButton.java
new file mode 100644
index 0000000..a904b37
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/ImmersiveModeToggleButton.java
@@ -0,0 +1,79 @@
+package js.kbars;
+
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnSystemUiVisibilityChangeListener;
+import android.widget.Button;
+
+public final class ImmersiveModeToggleButton extends Button {
+ private final KBarsActivity mActivity;
+ private final String mCaption;
+ private final int mImmersiveFlags;
+ private boolean mImmersiveMode;
+
+ public ImmersiveModeToggleButton(KBarsActivity activity, String caption, int immersiveFlags) {
+ super(activity);
+ this.mActivity = activity;
+ this.mCaption = caption;
+ this.mImmersiveFlags = immersiveFlags;
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ ImmersiveModeToggleButton.this.toggleImmersiveMode("clicked");
+ }
+ });
+ updateImmersiveModeButton();
+ setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
+ public void onSystemUiVisibilityChange(int visibility) {
+ ImmersiveModeToggleButton.this.onSysuiChanged(visibility);
+ }
+ });
+ }
+
+ private void toggleImmersiveMode(String reason) {
+ boolean z;
+ boolean z2 = false;
+ Log.d(KBarsActivity.TAG, "toggleImmersiveMode reason=" + reason);
+ if (this.mImmersiveMode) {
+ z = false;
+ } else {
+ z = true;
+ }
+ this.mImmersiveMode = z;
+ updateImmersiveModeButton();
+ KBarsActivity kBarsActivity = this.mActivity;
+ if (!this.mImmersiveMode) {
+ z2 = true;
+ }
+ kBarsActivity.setSoloButton(z2, this, true);
+ }
+
+ private void updateImmersiveModeButton() {
+ Log.d(KBarsActivity.TAG, "updateButtons mImmersiveMode=" + this.mImmersiveMode);
+ setText(this.mImmersiveMode ? "Exit " + this.mCaption + " mode" : "Enter " + this.mCaption + " mode");
+ setSystemUiVisibility(this.mImmersiveMode ? this.mImmersiveFlags : KBarsActivity.BASE_FLAGS);
+ }
+
+ private void onSysuiChanged(int vis) {
+ boolean hideStatus;
+ boolean hideSomething = false;
+ Log.d(KBarsActivity.TAG, "sysui changed: " + Integer.toHexString(vis));
+ if ((vis & 4) != 0) {
+ hideStatus = true;
+ } else {
+ hideStatus = false;
+ }
+ boolean hideNav;
+ if ((vis & 2) != 0) {
+ hideNav = true;
+ } else {
+ hideNav = false;
+ }
+ if (hideStatus || hideNav) {
+ hideSomething = true;
+ }
+ if (this.mImmersiveMode && !hideSomething) {
+ toggleImmersiveMode("sysui_changed");
+ }
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/KBarsActivity.java b/KBars/app/src/main/java/js/kbars/KBarsActivity.java
new file mode 100644
index 0000000..33733ac
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/KBarsActivity.java
@@ -0,0 +1,273 @@
+package js.kbars;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.DisplayMetrics;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.FrameLayout.LayoutParams;
+import android.widget.LinearLayout;
+import android.widget.Toast;
+import java.util.ArrayList;
+import java.util.List;
+
+public class KBarsActivity extends Activity {
+ public static final int BASE_FLAGS = 1792;
+ static final boolean DEBUG = true;
+ public static final int FLAG_TRANSLUCENT_NAVIGATION = 134217728;
+ public static final int FLAG_TRANSLUCENT_STATUS = 67108864;
+ private static final int IMMERSIVE_FLAGS = 3846;
+ private static final int IMMERSIVE_FLAGS_STICKY = 5894;
+ private static final int SYSTEM_UI_FLAG_IMMERSIVE = 2048;
+ private static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096;
+ static final String TAG = Util.logTag(KBarsActivity.class);
+ private List<View> mButtons = new ArrayList();
+ private CameraBackgroundMenuItem mCameraBackgroundMenuItem;
+ private final Context mContext = this;
+ private EditText mEditText;
+ private TouchTrackingLayout mFrame;
+ private ImageBackgroundMenuItem mImageBackgroundMenuItem;
+
+ private static final class DebugButton extends Button {
+ private final Handler mHandler = new Handler();
+ private final Runnable mNavTransOff = new Runnable() {
+ public void run() {
+ DebugButton.this.setNavTrans(false);
+ }
+ };
+ private final Runnable mNavTransOn = new Runnable() {
+ public void run() {
+ DebugButton.this.setNavTrans(true);
+ DebugButton.this.cancelTrans();
+ DebugButton.this.mHandler.postDelayed(DebugButton.this.mNavTransOff, 5000);
+ }
+ };
+
+ public DebugButton(Context context) {
+ super(context);
+ setText("Debug");
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ DebugButton.this.fallingToast();
+ }
+ });
+ }
+
+ private void cancelTrans() {
+ this.mHandler.removeCallbacks(this.mNavTransOn);
+ this.mHandler.removeCallbacks(this.mNavTransOff);
+ }
+
+ private void setNavTrans(boolean trans) {
+ Window w = ((Activity) getContext()).getWindow();
+ if (trans) {
+ w.addFlags(KBarsActivity.FLAG_TRANSLUCENT_STATUS);
+ } else {
+ w.clearFlags(KBarsActivity.FLAG_TRANSLUCENT_STATUS);
+ }
+ }
+
+ public void fallingToast() {
+ this.mNavTransOff.run();
+ Toast.makeText(getContext(), "Here is a toast", 1).show();
+ cancelTrans();
+ this.mHandler.postDelayed(this.mNavTransOn, 1000);
+ }
+ }
+
+ private static final class InvisibleButton extends Button {
+ public InvisibleButton(Context context) {
+ super(context);
+ super.setVisibility(4);
+ }
+
+ public void setVisibility(int visibility) {
+ }
+ }
+
+ protected void onCreate(Bundle savedInstanceState) {
+ boolean portrait;
+ int i = 0;
+ super.onCreate(savedInstanceState);
+ getWindow().requestFeature(9);
+ DisplayMetrics dm = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getRealMetrics(dm);
+ Toast.makeText(this.mContext, dm.widthPixels + "x" + dm.heightPixels + " supported=" + areTranslucentBarsSupported(), 0).show();
+ getActionBar().setTitle("kbars " + Util.getVersionName(this.mContext));
+ getActionBar().setBackgroundDrawable(new ColorDrawable(0));
+ this.mFrame = new TouchTrackingLayout(this.mContext);
+ LinearLayout allButtons = new LinearLayout(this.mContext);
+ Configuration config = getResources().getConfiguration();
+ if (((float) config.screenWidthDp) / ((float) config.screenHeightDp) < 1.0f) {
+ portrait = true;
+ } else {
+ portrait = false;
+ }
+ if (portrait) {
+ i = 1;
+ }
+ allButtons.setOrientation(i);
+ LinearLayout buttons1 = new LinearLayout(this.mContext);
+ buttons1.setOrientation(1);
+ LinearLayout buttons2 = new LinearLayout(this.mContext);
+ buttons2.setOrientation(1);
+ allButtons.addView(buttons1);
+ allButtons.addView(buttons2);
+ LayoutParams buttonsLP = new LayoutParams(-2, -2);
+ buttonsLP.gravity = 17;
+ this.mFrame.addView(allButtons, buttonsLP);
+ this.mEditText = new EditText(this.mContext);
+ this.mEditText.setVisibility(8);
+ buttons1.addView(this.mEditText, -1, -2);
+ buttons1.addView(new TransparencyToggleButton(this.mContext, "status bar", FLAG_TRANSLUCENT_STATUS));
+ buttons1.addView(new TransparencyToggleButton(this.mContext, "navigation bar", FLAG_TRANSLUCENT_NAVIGATION));
+ buttons1.addView(new InvisibleButton(this.mContext));
+ buttons2.addView(new ImmersiveModeToggleButton(this, "immersive", IMMERSIVE_FLAGS));
+ buttons2.addView(new ImmersiveModeToggleButton(this, "sticky immersive", IMMERSIVE_FLAGS_STICKY));
+ buttons2.addView(new LightsOutModeToggleButton(this.mContext));
+ buttons2.addView(new MediaModeToggleButton(this.mContext, this.mFrame));
+ buttons2.addView(new InvisibleButton(this.mContext));
+ setContentView(this.mFrame);
+ addButtons(buttons1);
+ addButtons(buttons2);
+ }
+
+ private void addButtons(LinearLayout buttons) {
+ for (int i = 0; i < buttons.getChildCount(); i++) {
+ this.mButtons.add(buttons.getChildAt(i));
+ }
+ }
+
+ private boolean areTranslucentBarsSupported() {
+ int id = getResources().getIdentifier("config_enableTranslucentDecor", "bool", "android");
+ if (id == 0) {
+ return false;
+ }
+ return getResources().getBoolean(id);
+ }
+
+ public boolean onCreateOptionsMenu(Menu menu) {
+ RandomColorBackgroundMenuItem randomColorBackgroundMenuItem = new RandomColorBackgroundMenuItem(menu, this.mFrame);
+ this.mImageBackgroundMenuItem = new ImageBackgroundMenuItem(menu, this, this.mFrame);
+ this.mCameraBackgroundMenuItem = new CameraBackgroundMenuItem(menu, this, this.mFrame);
+ createDebugMenuItem(menu);
+ createEditTextMenuItem(menu);
+ createOrientationMenuItem(menu, R.string.action_portrait, 1);
+ createOrientationMenuItem(menu, R.string.action_landscape, 0);
+ createOrientationMenuItem(menu, R.string.action_reverse_portrait, 9);
+ createOrientationMenuItem(menu, R.string.action_reverse_landscape, 8);
+ return true;
+ }
+
+ private void createOrientationMenuItem(Menu menu, int text, final int orientation) {
+ MenuItem mi = menu.add(text);
+ mi.setShowAsAction(0);
+ mi.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ KBarsActivity.this.setRequestedOrientation(orientation);
+ return true;
+ }
+ });
+ }
+
+ private void createDebugMenuItem(Menu menu) {
+ final MenuItem mi = menu.add("Show gesture debugging");
+ mi.setShowAsActionFlags(0);
+ mi.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ boolean debug;
+ if (KBarsActivity.this.mFrame.getDebug()) {
+ debug = false;
+ } else {
+ debug = true;
+ }
+ KBarsActivity.this.mFrame.setDebug(debug);
+ mi.setTitle(new StringBuilder(String.valueOf(debug ? "Hide" : "Show")).append(" gesture debugging").toString());
+ return true;
+ }
+ });
+ }
+
+ private void createEditTextMenuItem(Menu menu) {
+ final MenuItem mi = menu.add("Show EditText");
+ mi.setShowAsActionFlags(0);
+ mi.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ boolean isVisible;
+ int i = 0;
+ if (KBarsActivity.this.mEditText.getVisibility() == 0) {
+ isVisible = true;
+ } else {
+ isVisible = false;
+ }
+ EditText access$1 = KBarsActivity.this.mEditText;
+ if (isVisible) {
+ i = 8;
+ }
+ access$1.setVisibility(i);
+ mi.setTitle(new StringBuilder(String.valueOf(isVisible ? "Show" : "Hide")).append(" EditText").toString());
+ return true;
+ }
+ });
+ }
+
+ public void setSoloButton(boolean visible, View solo, boolean animate) {
+ int i;
+ int vis = 0;
+ if (visible) {
+ i = 1;
+ } else {
+ i = 0;
+ }
+ float alpha = (float) i;
+ if (!visible) {
+ vis = 4;
+ }
+ final int _vis = vis;
+ for (final View view : this.mButtons) {
+ if (!(view == solo || (view instanceof EditText))) {
+ view.setEnabled(visible);
+ if (animate) {
+ view.animate().alpha(alpha).setListener(new AnimatorListener() {
+ public void onAnimationCancel(Animator animation) {
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ view.setVisibility(_vis);
+ }
+
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ public void onAnimationStart(Animator animation) {
+ }
+ }).start();
+ } else {
+ view.setVisibility(vis);
+ }
+ }
+ }
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == CameraBackgroundMenuItem.REQUEST_CODE) {
+ this.mCameraBackgroundMenuItem.onActivityResult(resultCode, data);
+ }
+ if (requestCode == ImageBackgroundMenuItem.REQUEST_CODE) {
+ this.mImageBackgroundMenuItem.onActivityResult(resultCode, data);
+ }
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/KBarsCar.java b/KBars/app/src/main/java/js/kbars/KBarsCar.java
new file mode 100644
index 0000000..c280c95
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/KBarsCar.java
@@ -0,0 +1,38 @@
+package js.kbars;
+
+import android.app.Activity;
+import android.app.UiModeManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+public class KBarsCar extends Activity {
+ private static final String TAG = Util.logTag(KBarsCar.class);
+ private final Context mContext = this;
+ private View mView;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ requestWindowFeature(1);
+ super.onCreate(savedInstanceState);
+ this.mView = new View(this.mContext);
+ this.mView.setBackgroundColor(-65536);
+ setFullscreen();
+ setContentView(this.mView);
+ this.mView.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ ((UiModeManager) KBarsCar.this.mContext.getSystemService("uimode")).disableCarMode(1);
+ KBarsCar.this.finish();
+ }
+ });
+ }
+
+ protected void onResume() {
+ super.onResume();
+ setFullscreen();
+ }
+
+ private void setFullscreen() {
+ this.mView.setSystemUiVisibility(5382);
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/KBarsDream.java b/KBars/app/src/main/java/js/kbars/KBarsDream.java
new file mode 100644
index 0000000..7a4c92b
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/KBarsDream.java
@@ -0,0 +1,47 @@
+package js.kbars;
+
+import android.content.Context;
+import android.os.Handler;
+import android.service.dreams.DreamService;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnSystemUiVisibilityChangeListener;
+
+public class KBarsDream extends DreamService {
+ private static final String TAG = Util.logTag(KBarsDream.class);
+ private final Context mContext = this;
+ private final Handler mHandler = new Handler();
+ private View mView;
+
+ public void onCreate() {
+ super.onCreate();
+ setInteractive(true);
+ }
+
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ this.mView = new View(this.mContext);
+ getWindow().addFlags(1024);
+ setFullscreen();
+ this.mView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
+ public void onSystemUiVisibilityChange(int visibility) {
+ Log.d(KBarsDream.TAG, "onSystemUiVisibilityChange " + Integer.toHexString(visibility));
+ KBarsDream.this.setFullscreen();
+ }
+ });
+ this.mView.setBackgroundColor(-16776961);
+ setContentView(this.mView);
+ }
+
+ public void onWindowFocusChanged(boolean hasFocus) {
+ Log.d(TAG, "onWindowFocusChanged " + hasFocus);
+ super.onWindowFocusChanged(hasFocus);
+ if (hasFocus) {
+ setFullscreen();
+ }
+ }
+
+ private void setFullscreen() {
+ this.mView.setSystemUiVisibility(5382);
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/LightsOutModeToggleButton.java b/KBars/app/src/main/java/js/kbars/LightsOutModeToggleButton.java
new file mode 100644
index 0000000..9593142
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/LightsOutModeToggleButton.java
@@ -0,0 +1,26 @@
+package js.kbars;
+
+import android.content.Context;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public final class LightsOutModeToggleButton extends Button {
+ private boolean mLightsOut;
+
+ public LightsOutModeToggleButton(Context context) {
+ super(context);
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ LightsOutModeToggleButton.this.mLightsOut = !LightsOutModeToggleButton.this.mLightsOut;
+ LightsOutModeToggleButton.this.update();
+ }
+ });
+ update();
+ }
+
+ private void update() {
+ setText(new StringBuilder(String.valueOf(this.mLightsOut ? "Exit" : "Enter")).append(" lights out mode").toString());
+ setSystemUiVisibility(this.mLightsOut ? 1 : 0);
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/MediaModeToggleButton.java b/KBars/app/src/main/java/js/kbars/MediaModeToggleButton.java
new file mode 100644
index 0000000..1e2b19d
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/MediaModeToggleButton.java
@@ -0,0 +1,95 @@
+package js.kbars;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnSystemUiVisibilityChangeListener;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.FrameLayout.LayoutParams;
+import android.widget.VideoView;
+
+public final class MediaModeToggleButton extends Button {
+ private static final int MEDIA_FLAGS = 1798;
+ private final FrameLayout mFrame;
+ private boolean mMediaMode;
+ private VideoView mVideo;
+
+ public MediaModeToggleButton(Context context, FrameLayout frame) {
+ super(context);
+ this.mFrame = frame;
+ setText("Enter media mode");
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ MediaModeToggleButton.this.setSystemUiVisibility(MediaModeToggleButton.MEDIA_FLAGS);
+ }
+ });
+ setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
+ public void onSystemUiVisibilityChange(int vis) {
+ MediaModeToggleButton.this.updateSysUi(vis);
+ }
+ });
+ initVideo();
+ updateSysUi(0);
+ }
+
+ private void initVideo() {
+ this.mVideo = new VideoView(getContext());
+ this.mVideo.setVisibility(8);
+ LayoutParams videoLP = new LayoutParams(-1, -1);
+ videoLP.gravity = 17;
+ this.mFrame.addView(this.mVideo, videoLP);
+ this.mVideo.setOnPreparedListener(new OnPreparedListener() {
+ public void onPrepared(MediaPlayer mp) {
+ mp.setLooping(true);
+ }
+ });
+ this.mVideo.setVideoURI(Uri.parse("android.resource://" + getContext().getPackageName() + "/" + R.raw.clipcanvas));
+ this.mVideo.setBackgroundColor(0);
+ }
+
+ private void updateSysUi(int vis) {
+ boolean requested;
+ boolean hideStatus;
+ boolean hideNav;
+ boolean hideSomething;
+ if (getSystemUiVisibility() == MEDIA_FLAGS) {
+ requested = true;
+ } else {
+ requested = false;
+ }
+ if ((vis & 4) != 0) {
+ hideStatus = true;
+ } else {
+ hideStatus = false;
+ }
+ if ((vis & 2) != 0) {
+ hideNav = true;
+ } else {
+ hideNav = false;
+ }
+ if (hideStatus || hideNav) {
+ hideSomething = true;
+ } else {
+ hideSomething = false;
+ }
+ Log.d(KBarsActivity.TAG, String.format("vis change hideStatus=%s hideNav=%s hideSomething=%s mMediaMode=%s", new Object[]{Boolean.valueOf(hideStatus), Boolean.valueOf(hideNav), Boolean.valueOf(hideSomething), Boolean.valueOf(this.mMediaMode)}));
+ this.mMediaMode = false;
+ if (requested && hideStatus && hideNav) {
+ this.mMediaMode = true;
+ } else {
+ setSystemUiVisibility(KBarsActivity.BASE_FLAGS);
+ }
+ if (this.mMediaMode) {
+ this.mVideo.setVisibility(0);
+ this.mVideo.start();
+ return;
+ }
+ this.mVideo.setVisibility(8);
+ this.mVideo.stopPlayback();
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/RandomColorBackgroundMenuItem.java b/KBars/app/src/main/java/js/kbars/RandomColorBackgroundMenuItem.java
new file mode 100644
index 0000000..d1895f3
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/RandomColorBackgroundMenuItem.java
@@ -0,0 +1,29 @@
+package js.kbars;
+
+import android.graphics.Color;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.View;
+import java.util.Random;
+
+public class RandomColorBackgroundMenuItem implements OnMenuItemClickListener {
+ private static final Random RANDOM = new Random();
+ private final View mTarget;
+
+ public RandomColorBackgroundMenuItem(Menu menu, View target) {
+ this.mTarget = target;
+ MenuItem mi = menu.add("Random color background");
+ mi.setShowAsActionFlags(0);
+ mi.setOnMenuItemClickListener(this);
+ }
+
+ private void setColorBackground() {
+ this.mTarget.setBackgroundColor(Color.rgb(RANDOM.nextInt(255), RANDOM.nextInt(255), RANDOM.nextInt(255)));
+ }
+
+ public boolean onMenuItemClick(MenuItem item) {
+ setColorBackground();
+ return true;
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/SystemGestureDebugger.java b/KBars/app/src/main/java/js/kbars/SystemGestureDebugger.java
new file mode 100644
index 0000000..3992a82
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/SystemGestureDebugger.java
@@ -0,0 +1,216 @@
+package js.kbars;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.MotionEvent;
+
+public class SystemGestureDebugger {
+ private static final boolean DEBUG = false;
+ private static final int MAX_TRACKED_POINTERS = 32;
+ private static final int SWIPE_FROM_BOTTOM = 2;
+ private static final int SWIPE_FROM_RIGHT = 3;
+ private static final int SWIPE_FROM_TOP = 1;
+ private static final int SWIPE_NONE = 0;
+ private static final long SWIPE_TIMEOUT_MS = 500;
+ private static final String TAG = Util.logTag(SystemGestureDebugger.class);
+ private static final int UNTRACKED_POINTER = -1;
+ private final Callbacks mCallbacks;
+ private final float[] mCurrentX = new float[MAX_TRACKED_POINTERS];
+ private final float[] mCurrentY = new float[MAX_TRACKED_POINTERS];
+ private boolean mDebugFireable;
+ private final int[] mDownPointerId = new int[MAX_TRACKED_POINTERS];
+ private int mDownPointers;
+ private final long[] mDownTime = new long[MAX_TRACKED_POINTERS];
+ private final float[] mDownX = new float[MAX_TRACKED_POINTERS];
+ private final float[] mDownY = new float[MAX_TRACKED_POINTERS];
+ private final long[] mElapsedThreshold = new long[MAX_TRACKED_POINTERS];
+ private final int mSwipeDistanceThreshold;
+ private boolean mSwipeFireable;
+ private final int mSwipeStartThreshold;
+ int screenHeight;
+ int screenWidth;
+
+ interface Callbacks {
+ void onDebug();
+
+ void onSwipeFromBottom();
+
+ void onSwipeFromRight();
+
+ void onSwipeFromTop();
+ }
+
+ public static class DownPointerInfo {
+ public float currentX;
+ public float currentY;
+ public int downPointerId;
+ public long downTime;
+ public float downX;
+ public float downY;
+ public long elapsedThreshold;
+ }
+
+ public static class ThresholdInfo {
+ public int distance;
+ public long elapsed;
+ public int start;
+ }
+
+ public SystemGestureDebugger(Context context, Callbacks callbacks) {
+ this.mCallbacks = (Callbacks) checkNull("callbacks", callbacks);
+ this.mSwipeStartThreshold = ((Context) checkNull("context", context)).getResources().getDimensionPixelSize(((Integer) Util.getField("com.android.internal.R$dimen", "status_bar_height")).intValue());
+ this.mSwipeDistanceThreshold = this.mSwipeStartThreshold;
+ Log.d(TAG, String.format("startThreshold=%s endThreshold=%s", new Object[]{Integer.valueOf(this.mSwipeStartThreshold), Integer.valueOf(this.mSwipeDistanceThreshold)}));
+ }
+
+ private static <T> T checkNull(String name, T arg) {
+ if (arg != null) {
+ return arg;
+ }
+ throw new IllegalArgumentException(new StringBuilder(String.valueOf(name)).append(" must not be null").toString());
+ }
+
+ public void onPointerEvent(MotionEvent event) {
+ boolean z = true;
+ boolean z2 = DEBUG;
+ switch (event.getActionMasked()) {
+ case SWIPE_NONE /*0*/:
+ this.mSwipeFireable = true;
+ this.mDebugFireable = true;
+ this.mDownPointers = SWIPE_NONE;
+ captureDown(event, SWIPE_NONE);
+ return;
+ case 1:
+ case SWIPE_FROM_RIGHT /*3*/:
+ this.mSwipeFireable = DEBUG;
+ this.mDebugFireable = DEBUG;
+ return;
+ case 2:
+ if (this.mSwipeFireable) {
+ int swipe = detectSwipe(event);
+ if (swipe == 0) {
+ z2 = true;
+ }
+ this.mSwipeFireable = z2;
+ if (swipe == 1) {
+ this.mCallbacks.onSwipeFromTop();
+ return;
+ } else if (swipe == 2) {
+ this.mCallbacks.onSwipeFromBottom();
+ return;
+ } else if (swipe == SWIPE_FROM_RIGHT) {
+ this.mCallbacks.onSwipeFromRight();
+ return;
+ } else {
+ return;
+ }
+ }
+ return;
+ case 5:
+ captureDown(event, event.getActionIndex());
+ if (this.mDebugFireable) {
+ if (event.getPointerCount() >= 5) {
+ z = DEBUG;
+ }
+ this.mDebugFireable = z;
+ if (!this.mDebugFireable) {
+ this.mCallbacks.onDebug();
+ return;
+ }
+ return;
+ }
+ return;
+ default:
+ return;
+ }
+ }
+
+ private void captureDown(MotionEvent event, int pointerIndex) {
+ int i = findIndex(event.getPointerId(pointerIndex));
+ if (i != UNTRACKED_POINTER) {
+ this.mDownX[i] = event.getX(pointerIndex);
+ this.mDownY[i] = event.getY(pointerIndex);
+ this.mDownTime[i] = event.getEventTime();
+ }
+ }
+
+ private int findIndex(int pointerId) {
+ for (int i = SWIPE_NONE; i < this.mDownPointers; i++) {
+ if (this.mDownPointerId[i] == pointerId) {
+ return i;
+ }
+ }
+ if (this.mDownPointers == MAX_TRACKED_POINTERS || pointerId == UNTRACKED_POINTER) {
+ return UNTRACKED_POINTER;
+ }
+ int[] iArr = this.mDownPointerId;
+ int i2 = this.mDownPointers;
+ this.mDownPointers = i2 + 1;
+ iArr[i2] = pointerId;
+ return this.mDownPointers + UNTRACKED_POINTER;
+ }
+
+ private int detectSwipe(MotionEvent move) {
+ int historySize = move.getHistorySize();
+ int pointerCount = move.getPointerCount();
+ for (int p = SWIPE_NONE; p < pointerCount; p++) {
+ int i = findIndex(move.getPointerId(p));
+ if (i != UNTRACKED_POINTER) {
+ int swipe;
+ for (int h = SWIPE_NONE; h < historySize; h++) {
+ swipe = detectSwipe(i, move.getHistoricalEventTime(h), move.getHistoricalX(p, h), move.getHistoricalY(p, h));
+ if (swipe != 0) {
+ return swipe;
+ }
+ }
+ swipe = detectSwipe(i, move.getEventTime(), move.getX(p), move.getY(p));
+ if (swipe != 0) {
+ return swipe;
+ }
+ }
+ }
+ return SWIPE_NONE;
+ }
+
+ private int detectSwipe(int i, long time, float x, float y) {
+ float fromX = this.mDownX[i];
+ float fromY = this.mDownY[i];
+ long elapsed = time - this.mDownTime[i];
+ this.mCurrentX[i] = x;
+ this.mCurrentY[i] = y;
+ boolean reachedThreshold = ((fromY > ((float) this.mSwipeStartThreshold) || y <= ((float) this.mSwipeDistanceThreshold) + fromY) && ((fromY < ((float) (this.screenHeight - this.mSwipeStartThreshold)) || y >= fromY - ((float) this.mSwipeDistanceThreshold)) && (fromX < ((float) (this.screenWidth - this.mSwipeStartThreshold)) || x >= fromX - ((float) this.mSwipeDistanceThreshold)))) ? DEBUG : true;
+ if (!reachedThreshold) {
+ this.mElapsedThreshold[i] = elapsed;
+ }
+ if (fromY <= ((float) this.mSwipeStartThreshold) && y > ((float) this.mSwipeDistanceThreshold) + fromY && elapsed < SWIPE_TIMEOUT_MS) {
+ return 1;
+ }
+ if (fromY >= ((float) (this.screenHeight - this.mSwipeStartThreshold)) && y < fromY - ((float) this.mSwipeDistanceThreshold) && elapsed < SWIPE_TIMEOUT_MS) {
+ return 2;
+ }
+ if (fromX < ((float) (this.screenWidth - this.mSwipeStartThreshold)) || x >= fromX - ((float) this.mSwipeDistanceThreshold) || elapsed >= SWIPE_TIMEOUT_MS) {
+ return SWIPE_NONE;
+ }
+ return SWIPE_FROM_RIGHT;
+ }
+
+ public int getDownPointers() {
+ return this.mDownPointers;
+ }
+
+ public void getDownPointerInfo(int index, DownPointerInfo out) {
+ out.downPointerId = this.mDownPointerId[index];
+ out.downX = this.mDownX[index];
+ out.downY = this.mDownY[index];
+ out.downTime = this.mDownTime[index];
+ out.currentX = this.mCurrentX[index];
+ out.currentY = this.mCurrentY[index];
+ out.elapsedThreshold = this.mElapsedThreshold[index];
+ }
+
+ public void getThresholdInfo(ThresholdInfo out) {
+ out.start = this.mSwipeStartThreshold;
+ out.distance = this.mSwipeDistanceThreshold;
+ out.elapsed = SWIPE_TIMEOUT_MS;
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/ToastActivity.java b/KBars/app/src/main/java/js/kbars/ToastActivity.java
new file mode 100644
index 0000000..18f9a89
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/ToastActivity.java
@@ -0,0 +1,117 @@
+package js.kbars;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnSystemUiVisibilityChangeListener;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class ToastActivity extends Activity {
+ private static final int ALLOW_TRANSIENT = 2048;
+ private static final String TAG = Util.logTag(ToastActivity.class);
+ private View mContent;
+ private final Context mContext = this;
+ boolean mImmersive;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LinearLayout buttons = new LinearLayout(this.mContext);
+ buttons.setOrientation(1);
+ for (final Method m : getClass().getDeclaredMethods()) {
+ if (Modifier.isPublic(m.getModifiers()) && m.getParameterTypes().length == 0) {
+ Button btn = new Button(this.mContext);
+ btn.setText(m.getName());
+ btn.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ try {
+ m.invoke(ToastActivity.this.mContext, new Object[0]);
+ } catch (Throwable t) {
+ Log.w(ToastActivity.TAG, "Error running " + m.getName(), t);
+ }
+ }
+ });
+ buttons.addView(btn);
+ }
+ }
+ setContentView(buttons);
+ this.mContent = buttons;
+ setSysui();
+ this.mContent.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
+ public void onSystemUiVisibilityChange(int visibility) {
+ if ((visibility & 2) == 0) {
+ ToastActivity.this.mImmersive = false;
+ ToastActivity.this.setSysui();
+ }
+ }
+ });
+ }
+
+ public void toast1() {
+ Toast.makeText(this.mContext, "toast!", 0).show();
+ }
+
+ public void toast2() {
+ Toast t = Toast.makeText(this.mContext, "toast!", 0);
+ TextView tv = new TextView(this.mContext);
+ tv.setBackgroundColor(-65536);
+ tv.setText("setView");
+ t.setView(tv);
+ t.show();
+ }
+
+ public void toast3() {
+ Toast t = Toast.makeText(this.mContext, "toast!", 0);
+ TextView tv = new TextView(this.mContext) {
+ protected boolean fitSystemWindows(Rect insets) {
+ Rect before = new Rect(insets);
+ boolean rt = super.fitSystemWindows(insets);
+ Log.d(ToastActivity.TAG, String.format("before=%s rt=%s after=%s", new Object[]{before.toShortString(), Boolean.valueOf(rt), insets.toShortString()}));
+ return rt;
+ }
+ };
+ Log.d(TAG, "fitsSystemWindows=" + tv.getFitsSystemWindows());
+ tv.setFitsSystemWindows(true);
+ tv.setSystemUiVisibility(768);
+ tv.setBackgroundColor(-65536);
+ tv.setText("setView");
+ t.setView(tv);
+ t.show();
+ }
+
+ public void hideNav() {
+ this.mContent.setSystemUiVisibility(2);
+ }
+
+ public void dangerToast() {
+ Toast t = Toast.makeText(this.mContext, "toast!", 0);
+ TextView tv = new TextView(this.mContext);
+ tv.setSystemUiVisibility(512);
+ tv.setBackgroundColor(-65536);
+ tv.setText("setView");
+ t.setView(tv);
+ t.setGravity(80, 0, 90);
+ t.show();
+ }
+
+ public void toggleImmersive() {
+ this.mImmersive = !this.mImmersive;
+ setSysui();
+ }
+
+ private void setSysui() {
+ int flags = 2560;
+ if (this.mImmersive) {
+ flags = 2560 | 2;
+ }
+ this.mContent.setSystemUiVisibility(flags);
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/TouchTrackingLayout.java b/KBars/app/src/main/java/js/kbars/TouchTrackingLayout.java
new file mode 100644
index 0000000..83e6c30
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/TouchTrackingLayout.java
@@ -0,0 +1,298 @@
+package js.kbars;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+import android.widget.FrameLayout;
+import java.util.ArrayList;
+import java.util.List;
+import js.kbars.SystemGestureDebugger.DownPointerInfo;
+import js.kbars.SystemGestureDebugger.ThresholdInfo;
+
+public class TouchTrackingLayout extends FrameLayout {
+ private static final boolean DEBUG_EVENTS = true;
+ private static final int MAX_INFO_LINES = 6;
+ private static final int MAX_POINTERS = 5;
+ private static final int MAX_POINTS = 5000;
+ private static final String TAG = Util.logTag(TouchTrackingLayout.class);
+ private boolean mDebug;
+ private final DownPointerInfo mDownPointerInfo = new DownPointerInfo();
+ private final SystemGestureDebugger mGestures;
+ private final Paint mInfoPaint = new Paint();
+ private final StringBuilder[] mInfoText = allocateInfoText();
+ private final int mInfoTextLineHeight;
+ private final int mInfoTextOffset;
+ private final int[] mScribbleCounts = new int[MAX_POINTERS];
+ private final Paint mScribblePaint = new Paint();
+ private final List<float[]> mScribblePoints = allocatePoints();
+ private final int mTextSize;
+ private final ThresholdInfo mThresholdInfo = new ThresholdInfo();
+ private final float[] mThresholdLines = new float[16];
+ private final Paint mThresholdPaint = new Paint();
+
+ public TouchTrackingLayout(Context context) {
+ super(context);
+ setWillNotDraw(false);
+ int densityDpi = Util.getDensityDpi(context);
+ this.mTextSize = (int) (((float) densityDpi) / 12.0f);
+ this.mInfoTextLineHeight = (int) (((float) densityDpi) / 11.0f);
+ this.mInfoTextOffset = (int) (((float) densityDpi) / 1.7f);
+ Log.d(TAG, "mTextSize=" + this.mTextSize + " mInfoTextLineHeight=" + this.mInfoTextLineHeight + " mInfoTextOffset=" + this.mInfoTextOffset);
+ this.mScribblePaint.setColor(-13388315);
+ this.mScribblePaint.setStrokeWidth((float) this.mTextSize);
+ this.mScribblePaint.setStrokeCap(Cap.ROUND);
+ this.mScribblePaint.setStyle(Style.STROKE);
+ this.mGestures = new SystemGestureDebugger(context, new SystemGestureDebugger.Callbacks() {
+ public void onSwipeFromTop() {
+ Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onSwipeFromTop");
+ }
+
+ public void onSwipeFromRight() {
+ Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onSwipeFromRight");
+ }
+
+ public void onSwipeFromBottom() {
+ Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onSwipeFromBottom");
+ }
+
+ public void onDebug() {
+ Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onDebug");
+ }
+ });
+ this.mGestures.getThresholdInfo(this.mThresholdInfo);
+ this.mInfoPaint.setTypeface(Typeface.MONOSPACE);
+ this.mInfoPaint.setTextSize((float) this.mTextSize);
+ this.mInfoPaint.setStyle(Style.STROKE);
+ this.mInfoPaint.setColor(-13388315);
+ this.mThresholdPaint.setColor(-13388315);
+ this.mThresholdPaint.setStrokeWidth(1.0f);
+ this.mThresholdPaint.setStyle(Style.STROKE);
+ addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ TouchTrackingLayout.this.mGestures.screenWidth = right - left;
+ TouchTrackingLayout.this.mGestures.screenHeight = bottom - top;
+ TouchTrackingLayout.this.horLine(0, TouchTrackingLayout.this.mThresholdInfo.start);
+ TouchTrackingLayout.this.horLine(1, TouchTrackingLayout.this.mGestures.screenHeight - TouchTrackingLayout.this.mThresholdInfo.start);
+ TouchTrackingLayout.this.verLine(2, TouchTrackingLayout.this.mThresholdInfo.start);
+ TouchTrackingLayout.this.verLine(3, TouchTrackingLayout.this.mGestures.screenWidth - TouchTrackingLayout.this.mThresholdInfo.start);
+ }
+ });
+ }
+
+ public boolean getDebug() {
+ return this.mDebug;
+ }
+
+ public void setDebug(boolean debug) {
+ this.mDebug = debug;
+ invalidate();
+ }
+
+ protected boolean fitSystemWindows(Rect insets) {
+ Rect insetsBefore = new Rect(insets);
+ boolean rt = super.fitSystemWindows(insets);
+ Log.d(TAG, String.format("fitSystemWindows insetsBefore=%s insetsAfter=%s rt=%s", new Object[]{insetsBefore.toShortString(), insets.toShortString(), Boolean.valueOf(rt)}));
+ return rt;
+ }
+
+ private void horLine(int lineNum, int y) {
+ this.mThresholdLines[(lineNum * 4) + 0] = 0.0f;
+ float[] fArr = this.mThresholdLines;
+ int i = (lineNum * 4) + 1;
+ float f = (float) y;
+ this.mThresholdLines[(lineNum * 4) + 3] = f;
+ fArr[i] = f;
+ this.mThresholdLines[(lineNum * 4) + 2] = (float) this.mGestures.screenWidth;
+ }
+
+ private void verLine(int lineNum, int x) {
+ float[] fArr = this.mThresholdLines;
+ int i = (lineNum * 4) + 0;
+ float f = (float) x;
+ this.mThresholdLines[(lineNum * 4) + 2] = f;
+ fArr[i] = f;
+ this.mThresholdLines[(lineNum * 4) + 1] = 0.0f;
+ this.mThresholdLines[(lineNum * 4) + 3] = (float) this.mGestures.screenHeight;
+ }
+
+ private static StringBuilder[] allocateInfoText() {
+ StringBuilder[] rt = new StringBuilder[MAX_INFO_LINES];
+ for (int i = 0; i < rt.length; i++) {
+ rt[i] = new StringBuilder();
+ }
+ return rt;
+ }
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ super.onTouchEvent(ev);
+ this.mGestures.onPointerEvent(ev);
+ computeInfoText();
+ onMotionEvent(ev);
+ return true;
+ }
+
+ protected void onDraw(Canvas canvas) {
+ int i;
+ for (i = 0; i < this.mScribbleCounts.length; i++) {
+ int c = this.mScribbleCounts[i];
+ if (c > 0) {
+ canvas.drawLines((float[]) this.mScribblePoints.get(i), 0, c - 2, this.mScribblePaint);
+ }
+ }
+ if (this.mDebug) {
+ int leftMargin = this.mThresholdInfo.start + (this.mTextSize / 4);
+ for (i = 0; i < this.mInfoText.length; i++) {
+ StringBuilder sb = this.mInfoText[i];
+ canvas.drawText(sb, 0, sb.length(), (float) leftMargin, (float) (this.mInfoTextOffset + (this.mInfoTextLineHeight * i)), this.mInfoPaint);
+ }
+ canvas.drawLines(this.mThresholdLines, this.mThresholdPaint);
+ }
+ }
+
+ private void computeInfoText() {
+ int dpc = this.mGestures.getDownPointers();
+ for (int i = 0; i < this.mInfoText.length; i++) {
+ StringBuilder sb = this.mInfoText[i];
+ sb.delete(0, sb.length());
+ if (i == 0) {
+ sb.append("th ");
+ pad(sb, 9, this.mThresholdInfo.start);
+ sb.append(" ");
+ pad(sb, 9, this.mThresholdInfo.distance);
+ sb.append(' ');
+ pad(sb, MAX_POINTERS, (int) this.mThresholdInfo.elapsed);
+ sb.append("ms");
+ } else if (i - 1 < dpc) {
+ this.mGestures.getDownPointerInfo(i - 1, this.mDownPointerInfo);
+ sb.append('p');
+ sb.append(this.mDownPointerInfo.downPointerId);
+ sb.append(' ');
+ sb.append('(');
+ pad(sb, 4, (int) this.mDownPointerInfo.downX);
+ sb.append(',');
+ pad(sb, 4, (int) this.mDownPointerInfo.downY);
+ sb.append(')');
+ sb.append(' ');
+ sb.append('(');
+ pad(sb, 4, (int) (this.mDownPointerInfo.currentX - this.mDownPointerInfo.downX));
+ sb.append(',');
+ pad(sb, 4, (int) (this.mDownPointerInfo.currentY - this.mDownPointerInfo.downY));
+ sb.append(')');
+ sb.append(' ');
+ pad(sb, 4, (int) this.mDownPointerInfo.elapsedThreshold);
+ sb.append("ms");
+ }
+ }
+ }
+
+ private static void pad(StringBuilder sb, int len, int num) {
+ int n = num;
+ if (num < 0) {
+ n = Math.abs(num);
+ len--;
+ }
+ int nl = n > 0 ? ((int) Math.log10((double) n)) + 1 : 1;
+ while (true) {
+ int nl2 = nl + 1;
+ if (nl >= len) {
+ break;
+ }
+ sb.append(' ');
+ nl = nl2;
+ }
+ if (num < 0) {
+ sb.append('-');
+ }
+ sb.append(n);
+ }
+
+ private static List<float[]> allocatePoints() {
+ List<float[]> points = new ArrayList();
+ for (int i = 0; i < MAX_POINTERS; i++) {
+ points.add(new float[MAX_POINTS]);
+ }
+ return points;
+ }
+
+ private void onMotionEvent(MotionEvent ev) {
+ long evt;
+ int p;
+ Log.d(TAG, "EVENT " + ev);
+ if (ev.getActionMasked() == 0) {
+ clearScribbles();
+ }
+ int hs = ev.getHistorySize();
+ int ps = ev.getPointerCount();
+ for (int h = 0; h < hs; h++) {
+ evt = ev.getHistoricalEventTime(h);
+ for (p = 0; p < ps; p++) {
+ int pid = ev.getPointerId(p);
+ float hx = ev.getHistoricalX(p, h);
+ float hy = ev.getHistoricalY(p, h);
+ String str = TAG;
+ Object[] objArr = new Object[MAX_POINTERS];
+ objArr[0] = Long.valueOf(evt);
+ objArr[1] = Integer.valueOf(p);
+ objArr[2] = Integer.valueOf(pid);
+ objArr[3] = Float.valueOf(hx);
+ objArr[4] = Float.valueOf(hy);
+ Log.d(str, String.format("h.evt=%s p=%s pid=%s x=%s y=%s", objArr));
+ recordScribblePoint(pid, hx, hy);
+ }
+ }
+ evt = ev.getEventTime();
+ for (p = 0; p < ps; p++) {
+ int pid = ev.getPointerId(p);
+ float x = ev.getX(p);
+ float y = ev.getY(p);
+ String str = TAG;
+ Object[] objArr = new Object[MAX_POINTERS];
+ objArr[0] = Long.valueOf(evt);
+ objArr[1] = Integer.valueOf(p);
+ objArr[2] = Integer.valueOf(pid);
+ objArr[3] = Float.valueOf(x);
+ objArr[4] = Float.valueOf(y);
+ Log.d(str, String.format("c.evt=%s p=%s pid=%s x=%s y=%s", objArr));
+ recordScribblePoint(pid, x, y);
+ }
+ invalidate();
+ }
+
+ private void clearScribbles() {
+ for (int i = 0; i < this.mScribbleCounts.length; i++) {
+ this.mScribbleCounts[i] = 0;
+ }
+ }
+
+ private void recordScribblePoint(int pid, float x, float y) {
+ if (pid < MAX_POINTERS) {
+ float[] pts = (float[]) this.mScribblePoints.get(pid);
+ int oldCount = this.mScribbleCounts[pid];
+ if (oldCount + 4 >= MAX_POINTS) {
+ return;
+ }
+ int[] iArr;
+ if (oldCount == 0) {
+ pts[oldCount + 0] = x;
+ pts[oldCount + 1] = y;
+ iArr = this.mScribbleCounts;
+ iArr[pid] = iArr[pid] + 2;
+ return;
+ }
+ pts[oldCount + 0] = x;
+ pts[oldCount + 1] = y;
+ pts[oldCount + 2] = x;
+ pts[oldCount + 3] = y;
+ iArr = this.mScribbleCounts;
+ iArr[pid] = iArr[pid] + 4;
+ }
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/TransparencyToggleButton.java b/KBars/app/src/main/java/js/kbars/TransparencyToggleButton.java
new file mode 100644
index 0000000..ef14d85
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/TransparencyToggleButton.java
@@ -0,0 +1,43 @@
+package js.kbars;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.Button;
+
+public final class TransparencyToggleButton extends Button {
+ private final String mDescription;
+ private boolean mTransparent;
+ private final int mWmFlag;
+
+ public TransparencyToggleButton(Context context, String description, int wmFlag) {
+ super(context);
+ this.mDescription = description;
+ this.mWmFlag = wmFlag;
+ setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ TransparencyToggleButton.this.toggle("clicked");
+ }
+ });
+ update();
+ }
+
+ private void toggle(String reason) {
+ Log.d(KBarsActivity.TAG, "toggle reason=" + reason);
+ this.mTransparent = !this.mTransparent;
+ update();
+ }
+
+ private void update() {
+ setText("Make " + this.mDescription + " " + (this.mTransparent ? "opaque" : "transparent"));
+ Window w = ((Activity) getContext()).getWindow();
+ if (this.mTransparent) {
+ w.addFlags(this.mWmFlag);
+ } else {
+ w.clearFlags(this.mWmFlag);
+ }
+ }
+}
diff --git a/KBars/app/src/main/java/js/kbars/Util.java b/KBars/app/src/main/java/js/kbars/Util.java
new file mode 100644
index 0000000..5cd4971
--- /dev/null
+++ b/KBars/app/src/main/java/js/kbars/Util.java
@@ -0,0 +1,42 @@
+package js.kbars;
+
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+import java.lang.reflect.Field;
+
+public class Util {
+ public static String logTag(Class<?> c) {
+ return "kbars." + c.getSimpleName();
+ }
+
+ public static Object getField(Object obj, String fieldName) {
+ Class<?> c = obj.getClass();
+ try {
+ if (obj instanceof String) {
+ c = c.getClassLoader().loadClass((String) obj);
+ obj = null;
+ }
+ Field f = c.getDeclaredField(fieldName);
+ f.setAccessible(true);
+ return f.get(obj);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ public static int getDensityDpi(Context context) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ ((WindowManager) context.getSystemService("window")).getDefaultDisplay().getMetrics(metrics);
+ return metrics.densityDpi;
+ }
+
+ public static String getVersionName(Context context) {
+ try {
+ return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/KBars/app/src/main/res/drawable-hdpi-v4/ic_launcher.png b/KBars/app/src/main/res/drawable-hdpi-v4/ic_launcher.png
new file mode 100644
index 0000000..b899b9e
--- /dev/null
+++ b/KBars/app/src/main/res/drawable-hdpi-v4/ic_launcher.png
Binary files differ
diff --git a/KBars/app/src/main/res/drawable-mdpi-v4/ic_launcher.png b/KBars/app/src/main/res/drawable-mdpi-v4/ic_launcher.png
new file mode 100644
index 0000000..d2b481b
--- /dev/null
+++ b/KBars/app/src/main/res/drawable-mdpi-v4/ic_launcher.png
Binary files differ
diff --git a/KBars/app/src/main/res/drawable-xhdpi-v4/ic_launcher.png b/KBars/app/src/main/res/drawable-xhdpi-v4/ic_launcher.png
new file mode 100644
index 0000000..4a26260
--- /dev/null
+++ b/KBars/app/src/main/res/drawable-xhdpi-v4/ic_launcher.png
Binary files differ
diff --git a/KBars/app/src/main/res/drawable-xxhdpi-v4/ic_launcher.png b/KBars/app/src/main/res/drawable-xxhdpi-v4/ic_launcher.png
new file mode 100644
index 0000000..cdae26b
--- /dev/null
+++ b/KBars/app/src/main/res/drawable-xxhdpi-v4/ic_launcher.png
Binary files differ
diff --git a/KBars/app/src/main/res/raw/clipcanvas.mp4 b/KBars/app/src/main/res/raw/clipcanvas.mp4
new file mode 100644
index 0000000..e41f4c7
--- /dev/null
+++ b/KBars/app/src/main/res/raw/clipcanvas.mp4
Binary files differ
diff --git a/KBars/app/src/main/res/values/strings.xml b/KBars/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..ea4b9c2
--- /dev/null
+++ b/KBars/app/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">(kbars)</string>
+ <string name="action_landscape">Landscape</string>
+ <string name="action_portrait">Portrait</string>
+ <string name="action_reverse_landscape">Reverse Landscape</string>
+ <string name="action_reverse_portrait">Reverse Portrait</string>
+</resources>
diff --git a/KBars/app/src/main/res/values/styles.xml b/KBars/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..fd4fc97
--- /dev/null
+++ b/KBars/app/src/main/res/values/styles.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="AppBaseTheme">
+ </style>
+ <style name="AppTheme">
+ </style>
+</resources>