Skip to content

Commit f75e458

Browse files
committed
Calculate and take into account window decoration, nav bar and/or insets
to remove potential pointer offset caused by them. Add an option to disable the behavior. Fixed nav bar hiding content in general settings and while connected.
1 parent e659532 commit f75e458

File tree

12 files changed

+212
-109
lines changed

12 files changed

+212
-109
lines changed

bVNC/src/main/java/com/iiordanov/bVNC/RemoteCanvasActivity.java

Lines changed: 132 additions & 66 deletions
Large diffs are not rendered by default.

bVNC/src/main/java/com/iiordanov/bVNC/input/TouchInputDelegate.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,17 @@ public interface TouchInputDelegate {
5555
* @return true if DPad should be rotated
5656
*/
5757
boolean getRotateDpad();
58+
59+
60+
/**
61+
* Gets pointer offset in x axis due to e.g. insets
62+
* @return the width of the left inset
63+
*/
64+
int getxPointerOffset();
65+
66+
/**
67+
* Gets pointer offset in y axis due to e.g. window decorations
68+
* @return the height of the window decoration
69+
*/
70+
int getyPointerOffset();
5871
}

bVNC/src/main/java/com/iiordanov/bVNC/input/TouchInputHandlerGeneric.java

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@
2121
package com.iiordanov.bVNC.input;
2222
import com.undatech.opaque.Viewable;
2323

24+
import android.annotation.SuppressLint;
25+
import android.os.Build;
2426
import android.os.SystemClock;
2527
import android.view.GestureDetector;
2628
import android.view.MotionEvent;
2729
import android.view.ScaleGestureDetector;
2830

31+
import androidx.annotation.NonNull;
2932
import androidx.core.view.InputDeviceCompat;
3033

3134
import com.iiordanov.bVNC.Constants;
@@ -39,7 +42,7 @@ abstract class TouchInputHandlerGeneric extends GestureDetector.SimpleOnGestureL
3942
implements TouchInputHandler, ScaleGestureDetector.OnScaleGestureListener {
4043
private static final String TAG = "InputHandlerGeneric";
4144
protected final boolean debugLogging;
42-
int maxSwipeSpeed = 1;
45+
int maxSwipeSpeed;
4346
// If swipe events are registered once every baseSwipeTime miliseconds, then
4447
// swipeSpeed will be one. If more often, swipe-speed goes up, if less, down.
4548
final long baseSwipeTime = 400;
@@ -79,8 +82,8 @@ abstract class TouchInputHandlerGeneric extends GestureDetector.SimpleOnGestureL
7982
boolean scrollRight = false;
8083
// These variables indicate whether the dpad should be used as arrow keys
8184
// and whether it should be rotated.
82-
boolean useDpadAsArrows = false;
83-
boolean rotateDpad = false;
85+
boolean useDpadAsArrows;
86+
boolean rotateDpad;
8487
// The variables which indicates how many scroll events to send per swipe
8588
// event and the maximum number to send at one time.
8689
long swipeSpeed = 1;
@@ -124,8 +127,8 @@ abstract class TouchInputHandlerGeneric extends GestureDetector.SimpleOnGestureL
124127

125128
displayDensity = viewable.getDisplayDensity();
126129

127-
distXQueue = new LinkedList<Float>();
128-
distYQueue = new LinkedList<Float>();
130+
distXQueue = new LinkedList<>();
131+
distYQueue = new LinkedList<>();
129132

130133
baseSwipeDist = baseSwipeDist * displayDensity;
131134
startSwipeDist = startSwipeDist * displayDensity;
@@ -139,32 +142,39 @@ abstract class TouchInputHandlerGeneric extends GestureDetector.SimpleOnGestureL
139142
* @return the appropriate X coordinate.
140143
*/
141144
protected int getX(MotionEvent e) {
142-
float scale = viewable.getZoomFactor();
143-
return (int) (viewable.getAbsX() + e.getX() / scale);
145+
return getScaledX(e, viewable.getZoomFactor());
146+
}
147+
148+
private int getScaledX(MotionEvent e, float scale) {
149+
int xoff = touchInputDelegate.getxPointerOffset();
150+
return (int) (viewable.getAbsX() + (e.getX() - (float)xoff)/ scale);
144151
}
145152

146153
/**
147154
* Function to get appropriate Y coordinate from motion event for this input handler.
148155
* @return the appropriate Y coordinate.
149156
*/
150157
protected int getY(MotionEvent e) {
151-
float scale = viewable.getZoomFactor();
152-
return (int) (viewable.getAbsY() + (e.getY() - 1.f * viewable.getTop()) / scale);
158+
return getScaledY(e, viewable.getZoomFactor());
159+
}
160+
161+
private int getScaledY(MotionEvent e, float scale) {
162+
int yoff = touchInputDelegate.getyPointerOffset();
163+
return (int) (viewable.getAbsY() + (e.getY() - (float)yoff) / scale);
153164
}
154165

155166
/**
156167
* Handles actions performed by a mouse-like device.
157168
* @param e touch or generic motion event
158-
* @return
159169
*/
160170
protected boolean handleMouseActions(MotionEvent e) {
161171
boolean used = false;
162172
final int action = e.getActionMasked();
163173
final int meta = e.getMetaState();
164174
final int bstate = e.getButtonState();
165175
float scale = viewable.getZoomFactor();
166-
int x = (int) (viewable.getAbsX() + e.getX() / scale);
167-
int y = (int) (viewable.getAbsY() + (e.getY() - 1.f * viewable.getTop()) / scale);
176+
int x = getScaledX(e, scale);
177+
int y = getScaledY(e, scale);
168178

169179
switch (action) {
170180
// If a mouse button was pressed or mouse was moved.
@@ -270,9 +280,6 @@ protected boolean handleMouseActions(MotionEvent e) {
270280

271281
/**
272282
* Sends scroll events with previously set direction and speed.
273-
* @param x
274-
* @param y
275-
* @param meta
276283
*/
277284
protected void sendScrollEvents(int x, int y, int meta) {
278285
GeneralUtils.debugLog(debugLogging, TAG, "sendScrollEvents");
@@ -298,11 +305,11 @@ protected void sendScrollEvents(int x, int y, int meta) {
298305
remoteInput.getPointer().releaseButton(x, y, meta);
299306
}
300307

301-
/*
308+
/**
302309
* @see android.view.GestureDetector.SimpleOnGestureListener#onSingleTapConfirmed(android.view.MotionEvent)
303310
*/
304311
@Override
305-
public boolean onSingleTapConfirmed(MotionEvent e) {
312+
public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
306313
GeneralUtils.debugLog(debugLogging, TAG, "onSingleTapConfirmed, e: " + e);
307314
performLeftClick(e);
308315
return true;
@@ -317,7 +324,7 @@ private void performLeftClick(MotionEvent e) {
317324
viewable.movePanToMakePointerVisible();
318325
}
319326

320-
/*
327+
/**
321328
* @see android.view.GestureDetector.SimpleOnGestureListener#onDoubleTap(android.view.MotionEvent)
322329
*/
323330
@Override
@@ -336,7 +343,7 @@ public boolean onDoubleTap(MotionEvent e) {
336343
return true;
337344
}
338345

339-
/*
346+
/**
340347
* @see android.view.GestureDetector.SimpleOnGestureListener#onLongPress(android.view.MotionEvent)
341348
*/
342349
@Override
@@ -402,9 +409,10 @@ private void detectImmersiveSwipe(float y) {
402409
}
403410
}
404411

405-
/*
406-
* @see com.iiordanov.bVNC.input.InputHandler#0yonTouchEvent(android.view.MotionEvent)
412+
/**
413+
* @see com.iiordanov.bVNC.input.TouchInputHandlerGeneric#onTouchEvent(android.view.MotionEvent)
407414
*/
415+
@SuppressLint("ObsoleteSdkInt")
408416
@Override
409417
public boolean onTouchEvent(MotionEvent e) {
410418
GeneralUtils.debugLog(debugLogging, TAG, "onTouchEvent, e: " + e);
@@ -421,7 +429,7 @@ public boolean onTouchEvent(MotionEvent e) {
421429
disregardNextOnFling = true;
422430
}
423431

424-
if (android.os.Build.VERSION.SDK_INT >= 14) {
432+
if (Build.VERSION.SDK_INT >= 14) {
425433
// Handle and consume actions performed by a (e.g. USB or bluetooth) mouse.
426434
if (handleMouseActions(e))
427435
return true;
@@ -537,15 +545,14 @@ public boolean onTouchEvent(MotionEvent e) {
537545
break;
538546

539547
case 2:
540-
switch (action) {
541-
case MotionEvent.ACTION_POINTER_DOWN:
542-
if (!inScaling) {
543-
// This boolean prevents the right-click from firing simultaneously as a middle button click.
544-
thirdPointerWasDown = true;
545-
remoteInput.getPointer().middleButtonDown(getX(e), getY(e), meta);
546-
// Enter middle-drag mode.
547-
middleDragMode = true;
548-
}
548+
if (action == MotionEvent.ACTION_POINTER_DOWN) {
549+
if (!inScaling) {
550+
// This boolean prevents the right-click from firing simultaneously as a middle button click.
551+
thirdPointerWasDown = true;
552+
remoteInput.getPointer().middleButtonDown(getX(e), getY(e), meta);
553+
// Enter middle-drag mode.
554+
middleDragMode = true;
555+
}
549556
}
550557
break;
551558
}
@@ -554,7 +561,7 @@ public boolean onTouchEvent(MotionEvent e) {
554561
return gestureDetector.onTouchEvent(e);
555562
}
556563

557-
/*
564+
/**
558565
* @see android.view.ScaleGestureDetector.OnScaleGestureListener#onScale(android.view.ScaleGestureDetector)
559566
*/
560567
@Override
@@ -625,7 +632,7 @@ public boolean onScale(ScaleGestureDetector detector) {
625632
}
626633

627634
if (eventConsumed && viewable != null) {
628-
if (inScaling == false) {
635+
if (!inScaling) {
629636
inScaling = true;
630637
}
631638
GeneralUtils.debugLog(debugLogging, TAG, "Changing zoom level: " + detector.getScaleFactor());
@@ -635,11 +642,11 @@ public boolean onScale(ScaleGestureDetector detector) {
635642
return eventConsumed;
636643
}
637644

638-
/*
645+
/**
639646
* @see android.view.ScaleGestureDetector.OnScaleGestureListener#onScaleBegin(android.view.ScaleGestureDetector)
640647
*/
641648
@Override
642-
public boolean onScaleBegin(ScaleGestureDetector detector) {
649+
public boolean onScaleBegin(@NonNull ScaleGestureDetector detector) {
643650
GeneralUtils.debugLog(debugLogging, TAG, "onScaleBegin (" + xInitialFocus + "," + yInitialFocus + ")");
644651
inScaling = false;
645652
scalingJustFinished = false;
@@ -652,11 +659,11 @@ public boolean onScaleBegin(ScaleGestureDetector detector) {
652659
return true;
653660
}
654661

655-
/*
662+
/**
656663
* @see android.view.ScaleGestureDetector.OnScaleGestureListener#onScaleEnd(android.view.ScaleGestureDetector)
657664
*/
658665
@Override
659-
public void onScaleEnd(ScaleGestureDetector detector) {
666+
public void onScaleEnd(@NonNull ScaleGestureDetector detector) {
660667
GeneralUtils.debugLog(debugLogging, TAG, "onScaleEnd");
661668
inScaling = false;
662669
inSwiping = false;
@@ -665,8 +672,6 @@ public void onScaleEnd(ScaleGestureDetector detector) {
665672

666673
/**
667674
* Returns the sign of the given number.
668-
* @param number
669-
* @return
670675
*/
671676
protected float getSign(float number) {
672677
float sign;

bVNC/src/main/java/com/iiordanov/bVNC/input/TouchInputHandlerSingleHanded.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import android.widget.ImageButton;
2828
import android.widget.RelativeLayout;
2929

30+
import androidx.annotation.NonNull;
31+
3032
import com.undatech.opaque.InputCarriable;
3133
import com.undatech.opaque.util.GeneralUtils;
3234
import com.undatech.remoteClientUi.R;
@@ -191,7 +193,7 @@ private void initializeSingleHandedMode(MotionEvent e) {
191193
* @see com.iiordanov.bVNC.input.InputHandlerGeneric#onSingleTapConfirmed(android.view.MotionEvent)
192194
*/
193195
@Override
194-
public boolean onSingleTapConfirmed(MotionEvent e) {
196+
public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
195197
GeneralUtils.debugLog(debugLogging, TAG, "onSingleTapConfirmed");
196198

197199
boolean buttonsVisible = (singleHandOpts.getVisibility() == View.VISIBLE);

bVNC/src/main/res/layout-large/canvas.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:id="@+id/canvasLayout"
34
android:layout_width="fill_parent"
45
android:layout_height="fill_parent"
56
android:background="@android:color/background_dark"
67
android:orientation="vertical"
7-
android:fitsSystemWindows="true"
8+
android:fitsSystemWindows="false"
89
>
910

1011
<com.iiordanov.bVNC.RemoteCanvas

bVNC/src/main/res/layout/canvas.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:id="@+id/canvasLayout"
34
android:layout_width="fill_parent"
45
android:layout_height="fill_parent"
56
android:background="@android:color/background_dark"
67
android:orientation="vertical"
7-
android:fitsSystemWindows="true"
8+
android:fitsSystemWindows="false"
89
>
910

1011
<com.iiordanov.bVNC.RemoteCanvas

bVNC/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ Known issues:
417417
<string name="landscape_force">Force Landscape Orientation</string>
418418

419419
<string name="left_handed_mode">Left-Handed Mode</string>
420+
<string name="disable_pointer_offset_correction">Disable pointer offset correction</string>
420421

421422
<string name="list_caption">List</string>
422423
<string name="list_name_caption">List Name</string>

bVNC/src/main/res/xml/global_preferences.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
3-
android:fitsSystemWindows="true">
3+
android:fitsSystemWindows="true" android:paddingRight="26dip">
4+
<EditTextPreference/>
45
<SwitchPreferenceCompat
56
android:defaultValue="false"
67
android:key="disableImmersive"
@@ -40,6 +41,10 @@
4041
android:key="scrollSpeed"
4142
android:max="9"
4243
android:title="@string/scroll_speed" />
44+
<SwitchPreferenceCompat
45+
android:defaultValue="false"
46+
android:key="disablePointerOffsetCalculation"
47+
android:title="@string/disable_pointer_offset_correction" />
4348
<PreferenceCategory android:title="@string/applies_to_new_connections_only">
4449
<!--input_methods android:key must match Constants.defaultInputMethodTag -->
4550
<ListPreference

bVNC/src/main/res/xml/global_preferences_rdp.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
android:defaultValue="true"
55
android:key="preferSendingUnicode"
66
android:title="@string/prefer_sending_unicode" />
7+
<EditTextPreference/>
78
</PreferenceScreen>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
3+
<EditTextPreference/>
34
</PreferenceScreen>

0 commit comments

Comments
 (0)