Skip to content

Commit

Permalink
Release v1.0.2
Browse files Browse the repository at this point in the history
Enhancements:
- Combine legacy behaviour with touch behaviour for best of both worlds in click behaviour
- Add window permission manifest to fix ime behaviour
- Add scroll speed control
- Minor bugs here and there
  • Loading branch information
virresh committed Mar 8, 2021
1 parent 53ca1cb commit 25e4dfc
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 28 deletions.
4 changes: 3 additions & 1 deletion app/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/build
/build
/release/matvt-phone-app-release.apk
/release/output-metadata.json
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ android {
minSdkVersion 24
targetSdkVersion 29
versionCode 101
versionName '1.0.1'
versionName '1.0.2'

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
import android.util.Log;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.widget.Toast;

import androidx.annotation.NonNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

Expand All @@ -44,6 +47,8 @@ public class MouseEmulationEngine {

public static int bossKey;

public static int scrollSpeed;

private Handler timerHandler;

private Runnable previousRunnable;
Expand Down Expand Up @@ -178,7 +183,7 @@ private static GestureDescription createClick (PointF clickPoint) {
}

private static GestureDescription createSwipe (PointF originPoint, int direction, int momentum) {
final int DURATION = 10;
final int DURATION = scrollSpeed + 8;
Path clickPath = new Path();
PointF lineDirection = new PointF(originPoint.x + momentum * PointerControl.dirX[direction], originPoint.y + momentum * PointerControl.dirY[direction]);
clickPath.moveTo(originPoint.x, originPoint.y);
Expand Down Expand Up @@ -257,22 +262,32 @@ else if (keyEvent.getAction() == KeyEvent.ACTION_UP) {
}
else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) {
detachPreviousTimer();
if (keyEvent.getEventTime() - keyEvent.getDownTime() > 500) {
// if (keyEvent.getEventTime() - keyEvent.getDownTime() > 500) {
// unreliable long click event if button was pressed for more than 500 ms
int action = AccessibilityNodeInfo.ACTION_LONG_CLICK;
Point pInt = new Point((int) mPointerControl.getPointerLocation().x, (int) mPointerControl.getPointerLocation().y);
AccessibilityNodeInfo hitNode = findNode(null, action, pInt);

if (hitNode != null) {
hitNode.performAction(AccessibilityNodeInfo.FOCUS_INPUT);
consumed = hitNode.performAction(action);
int action = AccessibilityNodeInfo.ACTION_CLICK;
Point pInt = new Point((int) mPointerControl.getPointerLocation().x, (int) mPointerControl.getPointerLocation().y);
List<AccessibilityWindowInfo> windowList= mService.getWindows();
for (AccessibilityWindowInfo window : windowList) {
List<AccessibilityNodeInfo> nodeHierarchy = findNode(window.getRoot(), action, pInt);
for (int i=nodeHierarchy.size()-1; i>=0; i--){
if (consumed) return consumed;
AccessibilityNodeInfo hitNode = nodeHierarchy.get(i);
List<AccessibilityNodeInfo.AccessibilityAction> availableActions = hitNode.getActionList();
if (availableActions.contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_FOCUS)){
hitNode.performAction(AccessibilityNodeInfo.FOCUS_INPUT);
}
if (availableActions.contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_SELECT)){
hitNode.performAction(AccessibilityNodeInfo.ACTION_SELECT);
}
if (availableActions.contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK)){
consumed = hitNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
if (!consumed){
mService.dispatchGesture(createClick(mPointerControl.getPointerLocation()), null, null);
return true;
}
}
else {
mService.dispatchGesture(createClick(mPointerControl.getPointerLocation()), null, null);
return false;
}

}
}
return consumed;
Expand Down Expand Up @@ -315,17 +330,22 @@ public void onFinish() {
//// leaving it in for reference just in case needed in future, because looking up face cam
//// app's source might be a daunting task

private AccessibilityNodeInfo findNode (AccessibilityNodeInfo node, int action, Point pInt) {
private List<AccessibilityNodeInfo> findNode (AccessibilityNodeInfo node, int action, Point pInt) {
if (node == null) {
node = mService.getRootInActiveWindow();
}
if (node == null) {
Log.i(LOG_TAG, "Root Node ======>>>>>" + ((node != null) ? node.toString() : "null"));
}
List<AccessibilityNodeInfo> nodeInfos = new ArrayList<>();
Log.i(LOG_TAG, "Node found ?" + ((node != null) ? node.toString() : "null"));
node = findNodeHelper(node, action, pInt);
node = findNodeHelper(node, action, pInt, nodeInfos);
Log.i(LOG_TAG, "Node found ?" + ((node != null) ? node.toString() : "null"));
return node;
Log.i(LOG_TAG, "Number of Nodes ?=>>>>> " + nodeInfos.size());
return nodeInfos;
}

private AccessibilityNodeInfo findNodeHelper (AccessibilityNodeInfo node, int action, Point pInt) {
private AccessibilityNodeInfo findNodeHelper (AccessibilityNodeInfo node, int action, Point pInt, List<AccessibilityNodeInfo> nodeList) {
if (node == null) {
return null;
}
Expand All @@ -335,15 +355,17 @@ private AccessibilityNodeInfo findNodeHelper (AccessibilityNodeInfo node, int ac
// node doesn't contain cursor
return null;
}
// node contains cursor, add to node hierarchy
nodeList.add(node);
AccessibilityNodeInfo result = null;
result = node;
// if ((node.getActions() & action) != 0) {
// if ((node.getActions() & action) != 0 && node != null) {
// // possible to use this one, but keep searching children as well
// result = node;
// nodeList.add(node);
// }
int childCount = node.getChildCount();
for (int i=0; i<childCount; i++) {
AccessibilityNodeInfo child = findNodeHelper(node.getChild(i), action, pInt);
AccessibilityNodeInfo child = findNodeHelper(node.getChild(i), action, pInt, nodeList);
if (child != null) {
// always picks the last innermost clickable child
result = child;
Expand Down
27 changes: 26 additions & 1 deletion app/src/main/java/io/github/virresh/matvt/gui/GuiActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.github.virresh.matvt.helper.Helper;

import static io.github.virresh.matvt.engine.impl.MouseEmulationEngine.bossKey;
import static io.github.virresh.matvt.engine.impl.MouseEmulationEngine.scrollSpeed;

public class GuiActivity extends AppCompatActivity {
CountDownTimer repopulate;
Expand All @@ -42,6 +43,7 @@ public class GuiActivity extends AppCompatActivity {

Spinner sp_mouse_icon;
SeekBar dsbar_mouse_size;
SeekBar dsbar_scroll_speed;

public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 701;
public static int ACTION_ACCESSIBILITY_PERMISSION_REQUEST_CODE = 702;
Expand All @@ -60,6 +62,7 @@ protected void onCreate(Bundle savedInstanceState) {
cb_override = findViewById(R.id.cb_override);
sp_mouse_icon = findViewById(R.id.sp_mouse_icon);
dsbar_mouse_size = findViewById(R.id.dsbar_mouse_size);
dsbar_scroll_speed = findViewById(R.id.dsbar_mouse_scspeed);

// render icon style dropdown
IconStyleSpinnerAdapter iconStyleSpinnerAdapter = new IconStyleSpinnerAdapter(this, R.layout.spinner_icon_text_gui, R.id.textView, IconStyleSpinnerAdapter.getResourceList());
Expand Down Expand Up @@ -114,6 +117,25 @@ public void onStartTrackingTouch(SeekBar seekBar) {}
public void onStopTrackingTouch(SeekBar seekBar) {}
});

dsbar_scroll_speed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
// do not do anything if the progress change was done programmatically
Context ctx = getApplicationContext();
Helper.setScrollSpeed(ctx, progress);
scrollSpeed = progress;
// Toast.makeText(ctx, "Mouse size set. Changes will take effect from next restart.", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});

populateText();
findViewById(R.id.gui_setup_perm).setOnClickListener(view -> askPermissions());
}
Expand All @@ -129,7 +151,10 @@ private void checkValues(IconStyleSpinnerAdapter adapter) {
sp_mouse_icon.setSelection(adapter.getPosition(iconStyle));

int mouseSize = Helper.getMouseSizePref(ctx);
dsbar_mouse_size.setProgress(Math.max(Math.min(mouseSize, 4), 0));
dsbar_mouse_size.setProgress(Math.max(Math.min(mouseSize, dsbar_mouse_size.getMax()), 0));

int scrollSpeed = Helper.getScrollSpeed(ctx);
dsbar_scroll_speed.setProgress(Math.max(Math.min(scrollSpeed, dsbar_scroll_speed.getMax()), 0));
}

private void showBossLayout(boolean status) {
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/io/github/virresh/matvt/helper/Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class Helper {
static final String PREF_KEY_CB_OVERRIDE_VAL = "CB_OVERRIDE_VAL";
static final String PREF_KEY_MOUSE_ICON = "MOUSE_ICON";
static final String PREF_KEY_MOUSE_SIZE = "MOUSE_SIZE";
static final String PREF_KEY_SCROLL_SPEED = "SCROLL_SPEED";

public static boolean isAccessibilityDisabled(Context ctx) {
return !isAccServiceInstalled(ctx.getPackageName() + "/.services.MouseEventService", ctx);
Expand Down Expand Up @@ -96,4 +97,18 @@ public static void setMouseSizePref(Context ctx, int val) {
editor.commit();
}

public static int getScrollSpeed(Context ctx) {
SharedPreferences sp = ctx.getSharedPreferences(PREFS_ID, Context.MODE_PRIVATE);
return sp.getInt(PREF_KEY_SCROLL_SPEED, 4);
}

@SuppressLint("ApplySharedPref")
public static void setScrollSpeed(Context ctx, int val) {
SharedPreferences sp = ctx.getSharedPreferences(PREFS_ID, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt(PREF_KEY_SCROLL_SPEED, val);
editor.commit();
}


}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package io.github.virresh.matvt.services;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.provider.Settings;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;

import java.util.logging.Level;
import java.util.logging.Logger;

import io.github.virresh.matvt.engine.impl.MouseEmulationEngine;
import io.github.virresh.matvt.helper.Helper;
import io.github.virresh.matvt.view.OverlayView;

import static io.github.virresh.matvt.engine.impl.MouseEmulationEngine.bossKey;
import static io.github.virresh.matvt.engine.impl.MouseEmulationEngine.scrollSpeed;

public class MouseEventService extends AccessibilityService {

Expand All @@ -21,6 +26,7 @@ public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {}
@Override
protected boolean onKeyEvent(KeyEvent event) {
super.onKeyEvent(event);
Logger.getLogger("WTFLOGGER").log(Level.INFO, "Key ===>>>>>>>>>> " + event.getKeyCode());
if (Helper.isAnotherServiceInstalled(this) &&
event.getKeyCode() == KeyEvent.KEYCODE_HOME) return true;
if (Helper.isOverlayDisabled(this)) return false;
Expand All @@ -34,12 +40,18 @@ public void onInterrupt() {}
protected void onServiceConnected() {
super.onServiceConnected();
bossKey = KeyEvent.KEYCODE_VOLUME_MUTE;
scrollSpeed = Helper.getScrollSpeed(this);
if (Helper.isOverriding(this)) bossKey = Helper.getOverrideValue(this);
if (Settings.canDrawOverlays(this)) init();
}

private void init() {
OverlayView mOverlayView = new OverlayView(this);
AccessibilityServiceInfo asi = this.getServiceInfo();
if (asi != null) {
asi.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
this.setServiceInfo(asi);
}
mEngine = new MouseEmulationEngine(this, mOverlayView);
mEngine.init(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class MouseCursorView extends View {

private final PointF mPointerLocation;
private final Paint mPaintBox;
private final Bitmap mPointerBitmap;
private Bitmap mPointerBitmap;
private int pointerDrawableReference;
private int pointerSizeReference;

Expand All @@ -30,20 +30,24 @@ public MouseCursorView(Context context) {
setWillNotDraw(false);
mPointerLocation = new PointF();
mPaintBox = new Paint();

updateFromPreferences();
setBitmap(context);
}

private BitmapDrawable setBitmap(Context context) {
@SuppressLint("UseCompatLoadingForDrawables")
BitmapDrawable bp = (BitmapDrawable) context.getDrawable(pointerDrawableReference);
Bitmap originalBitmap = bp.getBitmap();
BitmapDrawable d = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(originalBitmap, 50 * pointerSizeReference, 50 * pointerSizeReference, true));
mPointerBitmap = d.getBitmap();
return d;
}

public void updateFromPreferences() {
Context ctx = getContext();
pointerDrawableReference = IconStyleSpinnerAdapter.textToResourceIdMap.getOrDefault(Helper.getMouseIconPref(ctx), R.drawable.pointer);
pointerSizeReference = Helper.getMouseSizePref(ctx) + 1;
setBitmap(getContext());
}

@Override
Expand Down
36 changes: 34 additions & 2 deletions app/src/main/res/layout/activity_gui.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
android:foregroundTint="@color/white"
android:max="4"
android:nextFocusUp="@id/gui_setup_perm"
android:nextFocusDown="@id/sp_mouse_icon"
android:nextFocusDown="@id/dsbar_mouse_scspeed"
android:progress="1"
android:progressBackgroundTint="@color/white_2"
android:progressTint="@color/white"
Expand All @@ -105,6 +105,38 @@

</LinearLayout>

<LinearLayout
android:id="@+id/mouse_scroll_speed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Scroll Speed (Fast to Slow)"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="20.0sp" />

<SeekBar
android:id="@+id/dsbar_mouse_scspeed"
style="@style/Widget.AppCompat.SeekBar.Discrete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:foregroundTint="@color/white"
android:max="20"
android:nextFocusUp="@id/dsbar_mouse_size"
android:nextFocusDown="@id/sp_mouse_icon"
android:progress="4"
android:progressBackgroundTint="@color/white_2"
android:progressTint="@color/white"
android:thumbTint="@color/white"
android:tickMarkTint="@color/white" />

</LinearLayout>

<LinearLayout
android:id="@+id/mouse_icon"
android:layout_width="match_parent"
Expand All @@ -128,7 +160,7 @@
android:layout_weight="0.5"
android:drawSelectorOnTop="true"
android:dropDownWidth="match_parent"
android:nextFocusUp="@id/dsbar_mouse_size"
android:nextFocusUp="@id/dsbar_mouse_scspeed"
android:nextFocusDown="@id/cb_override"
android:spinnerMode="dropdown" />
</LinearLayout>
Expand Down

0 comments on commit 25e4dfc

Please sign in to comment.