diff --git a/app/build.gradle b/app/build.gradle
index 9fe7fe2..74fe705 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -15,8 +15,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
- versionCode 63
- versionName "3.5.9"
+ versionCode 64
+ versionName "3.6.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
diff --git a/app/src/main/java/android/androidVNC/AbstractBitmapData.java b/app/src/main/java/android/androidVNC/AbstractBitmapData.java
index bf63352..593e9a9 100644
--- a/app/src/main/java/android/androidVNC/AbstractBitmapData.java
+++ b/app/src/main/java/android/androidVNC/AbstractBitmapData.java
@@ -15,189 +15,172 @@ import android.widget.ImageView;
* Abstract interface between the VncCanvas and the bitmap and pixel data
* buffers that actually contain the data. This allows for implementations that
* use smaller bitmaps or buffers to save memory.
- *
+ *
* @author Michael A. MacDonald
- *
+ *
*/
abstract class AbstractBitmapData {
- int framebufferwidth;
- int framebufferheight;
- int bitmapwidth;
- int bitmapheight;
- RfbProto rfb;
- Bitmap mbitmap;
- int bitmapPixels[];
- Canvas memGraphics;
- boolean waitingForInput;
- VncCanvas vncCanvas;
- private AbstractBitmapDrawable drawable;
+ int framebufferwidth;
+ int framebufferheight;
+ int bitmapwidth;
+ int bitmapheight;
+ RfbProto rfb;
+ Bitmap mbitmap;
+ int bitmapPixels[];
+ Canvas memGraphics;
+ boolean waitingForInput;
+ VncCanvas vncCanvas;
+ private AbstractBitmapDrawable drawable;
- AbstractBitmapData(RfbProto p, VncCanvas c) {
- rfb = p;
- vncCanvas = c;
- framebufferwidth = rfb.framebufferWidth;
- framebufferheight = rfb.framebufferHeight;
- }
+ AbstractBitmapData(RfbProto p, VncCanvas c) {
+ rfb = p;
+ vncCanvas = c;
+ framebufferwidth = rfb.framebufferWidth;
+ framebufferheight = rfb.framebufferHeight;
+ }
- synchronized void doneWaiting() {
- waitingForInput = false;
- }
+ synchronized void doneWaiting() {
+ waitingForInput = false;
+ }
- final void invalidateMousePosition() {
- if (vncCanvas.connection.getUseLocalCursor()) {
- if (drawable == null)
- drawable = createDrawable();
- drawable.setCursorRect(vncCanvas.mouseX, vncCanvas.mouseY);
- vncCanvas.invalidate(drawable.cursorRect);
- }
- }
+ final void invalidateMousePosition() {
+ if (vncCanvas.connection.getUseLocalCursor()) {
+ if (drawable == null)
+ drawable = createDrawable();
+ drawable.setCursorRect(vncCanvas.mouseX, vncCanvas.mouseY);
+ vncCanvas.invalidate(drawable.cursorRect);
+ }
+ }
- /**
- *
- * @return The smallest scale supported by the implementation; the scale at
- * which the bitmap would be smaller than the screen
- */
- float getMinimumScale() {
- double scale = 0.75;
- int displayWidth = vncCanvas.getWidth();
- int displayHeight = vncCanvas.getHeight();
- for (; scale >= 0; scale -= 0.25) {
- if (scale * bitmapwidth < displayWidth
- || scale * bitmapheight < displayHeight)
- break;
- }
- return (float) (scale + 0.25);
- }
+ /**
+ *
+ * @return The smallest scale supported by the implementation; the scale at
+ * which the bitmap would be smaller than the screen
+ */
+ float getMinimumScale() {
+ double scale = 0.75;
+ int displayWidth = vncCanvas.getWidth();
+ int displayHeight = vncCanvas.getHeight();
+ for (; scale >= 0; scale -= 0.25) {
+ if (scale * bitmapwidth < displayWidth
+ || scale * bitmapheight < displayHeight)
+ break;
+ }
+ return (float) (scale + 0.25);
+ }
- /**
- * Send a request through the protocol to get the data for the currently
- * held bitmap
- *
- * @param incremental
- * True if we want incremental update; false for full update
- */
- abstract void writeFullUpdateRequest(boolean incremental)
- throws IOException;
+ /**
+ * Send a request through the protocol to get the data for the currently
+ * held bitmap
+ *
+ * @param incremental True if we want incremental update; false for full update
+ */
+ abstract void writeFullUpdateRequest(boolean incremental)
+ throws IOException;
- /**
- * Determine if a rectangle in full-frame coordinates can be drawn in the
- * existing buffer
- *
- * @param x
- * Top left x
- * @param y
- * Top left y
- * @param w
- * width (pixels)
- * @param h
- * height (pixels)
- * @return True if entire rectangle fits into current screen buffer, false
- * otherwise
- */
- abstract boolean validDraw(int x, int y, int w, int h);
+ /**
+ * Determine if a rectangle in full-frame coordinates can be drawn in the
+ * existing buffer
+ *
+ * @param x Top left x
+ * @param y Top left y
+ * @param w width (pixels)
+ * @param h height (pixels)
+ * @return True if entire rectangle fits into current screen buffer, false
+ * otherwise
+ */
+ abstract boolean validDraw(int x, int y, int w, int h);
- /**
- * Return an offset in the bitmapPixels array of a point in full-frame
- * coordinates
- *
- * @param x
- * @param y
- * @return Offset in bitmapPixels array of color data for that point
- */
- abstract int offset(int x, int y);
+ /**
+ * Return an offset in the bitmapPixels array of a point in full-frame
+ * coordinates
+ *
+ * @param x
+ * @param y
+ * @return Offset in bitmapPixels array of color data for that point
+ */
+ abstract int offset(int x, int y);
- /**
- * Update pixels in the bitmap with data from the bitmapPixels array,
- * positioned in full-frame coordinates
- *
- * @param x
- * Top left x
- * @param y
- * Top left y
- * @param w
- * width (pixels)
- * @param h
- * height (pixels)
- */
- abstract void updateBitmap(int x, int y, int w, int h);
+ /**
+ * Update pixels in the bitmap with data from the bitmapPixels array,
+ * positioned in full-frame coordinates
+ *
+ * @param x Top left x
+ * @param y Top left y
+ * @param w width (pixels)
+ * @param h height (pixels)
+ */
+ abstract void updateBitmap(int x, int y, int w, int h);
- /**
- * Create drawable appropriate for this data
- *
- * @return drawable
- */
- abstract AbstractBitmapDrawable createDrawable();
+ /**
+ * Create drawable appropriate for this data
+ *
+ * @return drawable
+ */
+ abstract AbstractBitmapDrawable createDrawable();
- /**
- * Call in UI thread; tell ImageView we've changed
- *
- * @param v
- * ImageView displaying bitmap data
- */
- void updateView(ImageView v) {
- if (drawable == null)
- drawable = createDrawable();
- v.setImageDrawable(drawable);
- v.invalidate();
- }
+ /**
+ * Call in UI thread; tell ImageView we've changed
+ *
+ * @param v ImageView displaying bitmap data
+ */
+ void updateView(ImageView v) {
+ if (drawable == null)
+ drawable = createDrawable();
- /**
- * Copy a rectangle from one part of the bitmap to another
- *
- * @param src
- * Rectangle in full-frame coordinates to be copied
- * @param dest
- * Destination rectangle in full-frame coordinates
- * @param paint
- * Paint specifier
- */
- abstract void copyRect(Rect src, Rect dest, Paint paint);
+ if (drawable != null) {
+ v.setImageDrawable(drawable);
+ v.invalidate();
+ }
+ }
- /**
- * Draw a rectangle in the bitmap with coordinates given in full frame
- *
- * @param x
- * Top left x
- * @param y
- * Top left y
- * @param w
- * width (pixels)
- * @param h
- * height (pixels)
- * @param paint
- * How to draw
- */
- abstract void drawRect(int x, int y, int w, int h, Paint paint);
+ /**
+ * Copy a rectangle from one part of the bitmap to another
+ *
+ * @param src Rectangle in full-frame coordinates to be copied
+ * @param dest Destination rectangle in full-frame coordinates
+ * @param paint Paint specifier
+ */
+ abstract void copyRect(Rect src, Rect dest, Paint paint);
- /**
- * Scroll position has changed.
- *
- * This method is called in the UI thread-- it updates internal status, but
- * does not change the bitmap data or send a network request until
- * syncScroll is called
- *
- * @param newx
- * Position of left edge of visible part in full-frame
- * coordinates
- * @param newy
- * Position of top edge of visible part in full-frame coordinates
- */
- abstract void scrollChanged(int newx, int newy);
+ /**
+ * Draw a rectangle in the bitmap with coordinates given in full frame
+ *
+ * @param x Top left x
+ * @param y Top left y
+ * @param w width (pixels)
+ * @param h height (pixels)
+ * @param paint How to draw
+ */
+ abstract void drawRect(int x, int y, int w, int h, Paint paint);
- /**
- * Sync scroll -- called from network thread; copies scroll changes from UI
- * to network state
- */
- abstract void syncScroll();
+ /**
+ * Scroll position has changed.
+ *
+ * This method is called in the UI thread-- it updates internal status, but
+ * does not change the bitmap data or send a network request until
+ * syncScroll is called
+ *
+ * @param newx Position of left edge of visible part in full-frame
+ * coordinates
+ * @param newy Position of top edge of visible part in full-frame coordinates
+ */
+ abstract void scrollChanged(int newx, int newy);
- /**
- * Release resources
- */
- void dispose() {
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
- if (mbitmap != null)
- mbitmap.recycle();
- memGraphics = null;
- bitmapPixels = null;
- }
+ /**
+ * Sync scroll -- called from network thread; copies scroll changes from UI
+ * to network state
+ */
+ abstract void syncScroll();
+
+ /**
+ * Release resources
+ */
+ void dispose() {
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ if (mbitmap != null)
+ mbitmap.recycle();
+ memGraphics = null;
+ bitmapPixels = null;
+ }
}
diff --git a/app/src/main/java/android/androidVNC/VncCanvas.java b/app/src/main/java/android/androidVNC/VncCanvas.java
index 554ac07..84b77b8 100644
--- a/app/src/main/java/android/androidVNC/VncCanvas.java
+++ b/app/src/main/java/android/androidVNC/VncCanvas.java
@@ -2055,6 +2055,17 @@ public class VncCanvas extends AppCompatImageView {
activity.onDisconnected();
}
+ public float getFramebufferWidth() {
+ return bitmapData.framebufferwidth;
+ }
+
+ public float getFramebufferHeight() {
+ return bitmapData.framebufferheight;
+ }
+
+ public AbstractBitmapData getBitmapData() {
+ return bitmapData;
+ }
class VNCOnTouchListener implements View.OnTouchListener {
diff --git a/app/src/main/java/android/androidVNC/VncCanvasActivity.java b/app/src/main/java/android/androidVNC/VncCanvasActivity.java
index 06a960a..fe89845 100644
--- a/app/src/main/java/android/androidVNC/VncCanvasActivity.java
+++ b/app/src/main/java/android/androidVNC/VncCanvasActivity.java
@@ -1,14 +1,14 @@
-/*
+/*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
@@ -45,6 +45,8 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.ZoomControls;
@@ -62,332 +64,333 @@ import androidx.appcompat.app.AppCompatActivity;
public abstract class VncCanvasActivity extends AppCompatActivity {
- static Display display = null;
- public static Activity activity;
+ static Display display = null;
+ public static Activity activity;
+ public float scale = 0;
- /**
- * @author Michael A. MacDonald
- */
- class ZoomInputHandler extends AbstractGestureInputHandler {
+ /**
+ * @author Michael A. MacDonald
+ */
+ class ZoomInputHandler extends AbstractGestureInputHandler {
- /**
- * In drag mode (entered with long press) you process mouse events
- * without sending them through the gesture detector
- */
- private boolean dragMode;
- /**
- * Key handler delegate that handles DPad-based mouse motion
- */
- private DPadMouseKeyHandler keyHandler;
+ /**
+ * In drag mode (entered with long press) you process mouse events
+ * without sending them through the gesture detector
+ */
+ private boolean dragMode;
+ /**
+ * Key handler delegate that handles DPad-based mouse motion
+ */
+ private DPadMouseKeyHandler keyHandler;
- /**
- * @param c
- */
- ZoomInputHandler() {
- super(VncCanvasActivity.this);
- keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
- }
+ /**
+ * @param c
+ */
+ ZoomInputHandler() {
+ super(VncCanvasActivity.this);
+ keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
+ }
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getHandlerDescription()
- */
- @Override
- public CharSequence getHandlerDescription() {
- return getResources().getString(R.string.input_mode_touch_pan_zoom_mouse);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getHandlerDescription()
+ */
+ @Override
+ public CharSequence getHandlerDescription() {
+ return getResources().getString(R.string.input_mode_touch_pan_zoom_mouse);
+ }
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getName()
- */
- @Override
- public String getName() {
- return TOUCH_ZOOM_MODE;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getName()
+ */
+ @Override
+ public String getName() {
+ return TOUCH_ZOOM_MODE;
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyDown(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyDown(keyCode, evt);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyDown(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyDown(keyCode, evt);
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyUp(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyUp(keyCode, evt);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyUp(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyUp(keyCode, evt);
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
- * view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent evt) {
- return trackballMouse(evt);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
+ * view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent evt) {
+ return trackballMouse(evt);
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onDown(android
- * .view.MotionEvent)
- */
- @Override
- public boolean onDown(MotionEvent e) {
- panner.stop();
- return true;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onDown(android
+ * .view.MotionEvent)
+ */
+ @Override
+ public boolean onDown(MotionEvent e) {
+ panner.stop();
+ return true;
+ }
- /**
- * Divide stated fling velocity by this amount to get initial velocity
- * per pan interval
- */
- static final float FLING_FACTOR = 8;
+ /**
+ * Divide stated fling velocity by this amount to get initial velocity
+ * per pan interval
+ */
+ static final float FLING_FACTOR = 8;
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onFling(android
- * .view.MotionEvent, android.view.MotionEvent, float, float)
- */
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- showZoomer(false);
- panner.start(-(velocityX / FLING_FACTOR), -(velocityY / FLING_FACTOR), new Panner.VelocityUpdater() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onFling(android
+ * .view.MotionEvent, android.view.MotionEvent, float, float)
+ */
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ showZoomer(false);
+ panner.start(-(velocityX / FLING_FACTOR), -(velocityY / FLING_FACTOR), new Panner.VelocityUpdater() {
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.Panner.VelocityUpdater#updateVelocity
- * (android.graphics.Point, long)
- */
- @Override
- public boolean updateVelocity(PointF p, long interval) {
- double scale = Math.pow(0.8, interval / 50.0);
- p.x *= scale;
- p.y *= scale;
- return (Math.abs(p.x) > 0.5 || Math.abs(p.y) > 0.5);
- }
- });
- return true;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.Panner.VelocityUpdater#updateVelocity
+ * (android.graphics.Point, long)
+ */
+ @Override
+ public boolean updateVelocity(PointF p, long interval) {
+ double scale = Math.pow(0.8, interval / 50.0);
+ p.x *= scale;
+ p.y *= scale;
+ return (Math.abs(p.x) > 0.5 || Math.abs(p.y) > 0.5);
+ }
+ });
+ return true;
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractGestureInputHandler#onTouchEvent(android
- * .view.MotionEvent)
- */
- @Override
- public boolean onTouchEvent(MotionEvent e) {
- // MK
- if (e.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractGestureInputHandler#onTouchEvent(android
+ * .view.MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent e) {
+ // MK
+ if (e.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
- if (dragMode) {
- vncCanvas.changeTouchCoordinatesToFullFrame(e);
- if (e.getAction() == MotionEvent.ACTION_UP) {
- dragMode = false;
- }
- return vncCanvas.processPointerEvent(e, true);
- } else {
- return super.onTouchEvent(e);
- }
- }
+ if (dragMode) {
+ vncCanvas.changeTouchCoordinatesToFullFrame(e);
+ if (e.getAction() == MotionEvent.ACTION_UP) {
+ dragMode = false;
+ }
+ return vncCanvas.processPointerEvent(e, true);
+ } else {
+ return super.onTouchEvent(e);
+ }
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onLongPress(
- * android.view.MotionEvent)
- */
- @Override
- public void onLongPress(MotionEvent e) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onLongPress(
+ * android.view.MotionEvent)
+ */
+ @Override
+ public void onLongPress(MotionEvent e) {
// showZoomer(true);
// BCFactory.getInstance().getBCHaptic().performLongPressHaptic(vncCanvas);
// dragMode = true;
// vncCanvas.processPointerEvent(vncCanvas.changeTouchCoordinatesToFullFrame(e), true);
- }
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onScroll(android
- * .view.MotionEvent, android.view.MotionEvent, float, float)
- */
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- if (inScaling) {
- return false;
- }
- showZoomer(false);
- return vncCanvas.pan((int) distanceX, (int) distanceY);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onScroll(android
+ * .view.MotionEvent, android.view.MotionEvent, float, float)
+ */
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ if (inScaling) {
+ return false;
+ }
+ showZoomer(false);
+ return vncCanvas.pan((int) distanceX, (int) distanceY);
+ }
- /*
- * (non-Javadoc)
- *
- * @see android.view.GestureDetector.SimpleOnGestureListener#
- * onSingleTapConfirmed (android.view.MotionEvent)
- */
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- vncCanvas.changeTouchCoordinatesToFullFrame(e);
- vncCanvas.processPointerEvent(e, true);
- e.setAction(MotionEvent.ACTION_UP);
- return vncCanvas.processPointerEvent(e, false);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.view.GestureDetector.SimpleOnGestureListener#
+ * onSingleTapConfirmed (android.view.MotionEvent)
+ */
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ vncCanvas.changeTouchCoordinatesToFullFrame(e);
+ vncCanvas.processPointerEvent(e, true);
+ e.setAction(MotionEvent.ACTION_UP);
+ return vncCanvas.processPointerEvent(e, false);
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onDoubleTap(
- * android.view.MotionEvent)
- */
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- vncCanvas.changeTouchCoordinatesToFullFrame(e);
- vncCanvas.processPointerEvent(e, true, true);
- e.setAction(MotionEvent.ACTION_UP);
- return vncCanvas.processPointerEvent(e, false, true);
- }
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onDoubleTap(
+ * android.view.MotionEvent)
+ */
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ vncCanvas.changeTouchCoordinatesToFullFrame(e);
+ vncCanvas.processPointerEvent(e, true, true);
+ e.setAction(MotionEvent.ACTION_UP);
+ return vncCanvas.processPointerEvent(e, false, true);
+ }
+ }
- public class TouchpadInputHandler extends AbstractGestureInputHandler {
+ public class TouchpadInputHandler extends AbstractGestureInputHandler {
- /**
- * In drag mode (entered with long press) you process mouse events
- * without sending them through the gesture detector
- */
- private boolean dragMode;
- float dragX, dragY;
- /**
- * Key handler delegate that handles DPad-based mouse motion
- */
- private DPadMouseKeyHandler keyHandler;
+ /**
+ * In drag mode (entered with long press) you process mouse events
+ * without sending them through the gesture detector
+ */
+ private boolean dragMode;
+ float dragX, dragY;
+ /**
+ * Key handler delegate that handles DPad-based mouse motion
+ */
+ private DPadMouseKeyHandler keyHandler;
- TouchpadInputHandler() {
- super(VncCanvasActivity.this);
- keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
- }
+ TouchpadInputHandler() {
+ super(VncCanvasActivity.this);
+ keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
+ }
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getHandlerDescription()
- */
- @Override
- public CharSequence getHandlerDescription() {
- return getResources().getString(R.string.input_mode_touchpad);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getHandlerDescription()
+ */
+ @Override
+ public CharSequence getHandlerDescription() {
+ return getResources().getString(R.string.input_mode_touchpad);
+ }
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getName()
- */
- @Override
- public String getName() {
- return TOUCHPAD_MODE;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getName()
+ */
+ @Override
+ public String getName() {
+ return TOUCHPAD_MODE;
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyDown(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyDown(keyCode, evt);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyDown(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyDown(keyCode, evt);
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyUp(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyUp(keyCode, evt);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.VncCanvasActivity.ZoomInputHandler#onKeyUp(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyUp(keyCode, evt);
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
- * view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent evt) {
- return trackballMouse(evt);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
+ * view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent evt) {
+ return trackballMouse(evt);
+ }
- /**
- * scale down delta when it is small. This will allow finer control when
- * user is making a small movement on touch screen. Scale up delta when
- * delta is big. This allows fast mouse movement when user is flinging.
- *
- * @param deltaX
- * @return
- */
- private float fineCtrlScale(float delta) {
- float sign = (delta > 0) ? 1 : -1;
- delta = Math.abs(delta);
- if (delta >= 1 && delta <= 3) {
- delta = 1;
- } else if (delta <= 10) {
- delta *= 0.34;
- } else if (delta <= 30) {
- delta *= delta / 30;
- } else if (delta <= 90) {
- delta *= (delta / 30);
- } else {
- delta *= 3.0;
- }
- return sign * delta;
- }
+ /**
+ * scale down delta when it is small. This will allow finer control when
+ * user is making a small movement on touch screen. Scale up delta when
+ * delta is big. This allows fast mouse movement when user is flinging.
+ *
+ * @param deltaX
+ * @return
+ */
+ private float fineCtrlScale(float delta) {
+ float sign = (delta > 0) ? 1 : -1;
+ delta = Math.abs(delta);
+ if (delta >= 1 && delta <= 3) {
+ delta = 1;
+ } else if (delta <= 10) {
+ delta *= 0.34;
+ } else if (delta <= 30) {
+ delta *= delta / 30;
+ } else if (delta <= 90) {
+ delta *= (delta / 30);
+ } else {
+ delta *= 3.0;
+ }
+ return sign * delta;
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onLongPress(
- * android.view.MotionEvent)
- */
- @Override
- public void onLongPress(MotionEvent e) {
- if(Config.enableDragOnLongPress)
- dragPointer(e);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onLongPress(
+ * android.view.MotionEvent)
+ */
+ @Override
+ public void onLongPress(MotionEvent e) {
+ if (Config.enableDragOnLongPress)
+ dragPointer(e);
+ }
private void dragPointer(MotionEvent e) {
@@ -399,19 +402,18 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
// send a mouse down event to the remote without moving the mouse.
remoteMouseStayPut(e);
vncCanvas.processPointerEvent(e, true);
-
}
/*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onScroll(android
- * .view.MotionEvent, android.view.MotionEvent, float, float)
- */
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- //VECTRAS: Disable this for now
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onScroll(android
+ * .view.MotionEvent, android.view.MotionEvent, float, float)
+ */
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ //VECTRAS: Disable this for now
// if (BCFactory.getInstance().getBCMotionEvent().getPointerCount(e2) > 1) {
// if (inScaling) {
// return false;
@@ -419,41 +421,43 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
// showZoomer(true);
// return vncCanvas.pan((int) distanceX, (int) distanceY);
// } else {
- // compute the relative movement offset on the remote screen.
- float deltaX = -distanceX * vncCanvas.getScale();
- float deltaY = -distanceY * vncCanvas.getScale();
- deltaX = fineCtrlScale(deltaX);
- deltaY = fineCtrlScale(deltaY);
+ // compute the relative movement offset on the remote screen.
+ float deltaX = -distanceX * vncCanvas.getScale();
+ float deltaY = -distanceY * vncCanvas.getScale();
+ deltaX = fineCtrlScale(deltaX);
+ deltaY = fineCtrlScale(deltaY);
- // compute the absolution new mouse pos on the remote site.
- float newRemoteX = vncCanvas.mouseX + deltaX;
- float newRemoteY = vncCanvas.mouseY + deltaY;
+ // compute the absolution new mouse pos on the remote site.
+ float newRemoteX = vncCanvas.mouseX + deltaX;
+ float newRemoteY = vncCanvas.mouseY + deltaY;
- if (dragMode) {
- if (e2.getAction() == MotionEvent.ACTION_UP) {
- dragMode = false;
- }
- dragX = e2.getX();
- dragY = e2.getY();
- e2.setLocation(newRemoteX, newRemoteY);
- return vncCanvas.processPointerEvent(e2, true);
- } else {
- e2.setLocation(newRemoteX, newRemoteY);
- vncCanvas.processPointerEvent(e2, false);
- }
+ if (dragMode) {
+ if (e2.getAction() == MotionEvent.ACTION_UP) {
+ dragMode = false;
+ }
+ dragX = e2.getX();
+ dragY = e2.getY();
+ e2.setLocation(newRemoteX, newRemoteY);
+ updateVirtualMouse(e2);
+ return vncCanvas.processPointerEvent(e2, true);
+ } else {
+ e2.setLocation(newRemoteX, newRemoteY);
+ updateVirtualMouse(e2);
+ vncCanvas.processPointerEvent(e2, false);
+ }
// }
- return true;
- }
+ return true;
+ }
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractGestureInputHandler#onTouchEvent(android
- * .view.MotionEvent)
- */
- @Override
- public boolean onTouchEvent(MotionEvent e) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractGestureInputHandler#onTouchEvent(android
+ * .view.MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent e) {
// MK
if (e.getAction() == MotionEvent.ACTION_CANCEL)
@@ -489,116 +493,126 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
}
e.setLocation(newRemoteX, newRemoteY);
+ updateVirtualMouse(e);
vncCanvas.processPointerEvent(e, down);
return super.onTouchEvent(e);
} else if (!Config.enableDragOnLongPress && e.getAction() == MotionEvent.ACTION_MOVE) {
e.setLocation(newRemoteX, newRemoteY);
+ updateVirtualMouse(e);
return vncCanvas.processPointerEvent(e, false);
} else {
- return super.onTouchEvent(e);
- }
- }
+ return super.onTouchEvent(e);
+ }
+ }
- public boolean rightClick(final MotionEvent e) {
- Thread t = new Thread(new Runnable() {
- public void run() {
- remoteMouseStayPut(e);
- // One
- // Log.v("Double Click", "One");
- vncCanvas.processPointerEvent(e, true, true);
- try {
- Thread.sleep(100);
- } catch (InterruptedException ex) {
- Logger.getLogger(VncCanvasActivity.class.getName()).log(Level.SEVERE, null, ex);
- }
- e.setAction(MotionEvent.ACTION_UP);
- vncCanvas.processPointerEvent(e, false, true);
- }
- });
- // t.setPriority(Thread.MAX_PRIORITY);
- t.start();
- return true;
+ public void updateVirtualMouse(MotionEvent e) {
+ if (cursorView.getVisibility() == View.VISIBLE) {
+ float viewX = e.getX();
+ float viewY = e.getY();
+ cursorView.update(viewX * scale, viewY * scale);
+ }
+ }
- }
+ public boolean rightClick(final MotionEvent e) {
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ remoteMouseStayPut(e);
+ // One
+ // Log.v("Double Click", "One");
+ vncCanvas.processPointerEvent(e, true, true);
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(VncCanvasActivity.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ e.setAction(MotionEvent.ACTION_UP);
+ vncCanvas.processPointerEvent(e, false, true);
+ }
+ });
+ // t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+ return true;
- public boolean leftClick(final MotionEvent e) {
- Thread t = new Thread(new Runnable() {
- public void run() {
- remoteMouseStayPut(e);
- // One
- // Log.v("Double Click", "One");
- vncCanvas.processPointerEvent(e, true, true);
- try {
- Thread.sleep(100);
- } catch (InterruptedException ex) {
- Logger.getLogger(VncCanvasActivity.class.getName()).log(Level.SEVERE, null, ex);
- }
- e.setAction(MotionEvent.ACTION_UP);
- vncCanvas.processPointerEvent(e, false, true);
- }
- });
- // t.setPriority(Thread.MAX_PRIORITY);
- t.start();
- return true;
+ }
- }
+ public boolean leftClick(final MotionEvent e) {
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ remoteMouseStayPut(e);
+ // One
+ // Log.v("Double Click", "One");
+ vncCanvas.processPointerEvent(e, true, true);
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(VncCanvasActivity.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ e.setAction(MotionEvent.ACTION_UP);
+ vncCanvas.processPointerEvent(e, false, true);
+ }
+ });
+ // t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+ return true;
- /**
- * Modify the event so that it does not move the mouse on the remote
- * server.
- *
- * @param e
- */
- private void remoteMouseStayPut(MotionEvent e) {
- e.setLocation(vncCanvas.mouseX, vncCanvas.mouseY);
+ }
- }
+ /**
+ * Modify the event so that it does not move the mouse on the remote
+ * server.
+ *
+ * @param e
+ */
+ private void remoteMouseStayPut(MotionEvent e) {
+ e.setLocation(vncCanvas.mouseX, vncCanvas.mouseY);
- /*
- * (non-Javadoc) confirmed single tap: do a single mouse click on remote
- * without moving the mouse.
- *
- * @see android.view.GestureDetector.SimpleOnGestureListener#
- * onSingleTapConfirmed (android.view.MotionEvent)
- */
+ }
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- singleClick(e);
- return true;
- // boolean multiTouch =
- // (BCFactory.getInstance().getBCMotionEvent().getPointerCount(e) >
- // 1);
- // remoteMouseStayPut(e);
- // vncCanvas.processPointerEvent(e, true, multiTouch ||
- // vncCanvas.cameraButtonDown);
- // e.setAction(MotionEvent.ACTION_UP);
- // return vncCanvas.processPointerEvent(e, false, multiTouch ||
- // vncCanvas.cameraButtonDown);
- }
+ /*
+ * (non-Javadoc) confirmed single tap: do a single mouse click on remote
+ * without moving the mouse.
+ *
+ * @see android.view.GestureDetector.SimpleOnGestureListener#
+ * onSingleTapConfirmed (android.view.MotionEvent)
+ */
- private boolean singleClick(final MotionEvent e) {
- Thread t = new Thread(new Runnable() {
- public void run() {
- remoteMouseStayPut(e);
- // One
- // Log.v("Double Click", "One");
- vncCanvas.processPointerEvent(e, true, false);
- try {
- Thread.sleep(50);
- } catch (InterruptedException ex) {
- Logger.getLogger(VncCanvasActivity.class.getName()).log(Level.SEVERE, null, ex);
- }
- e.setAction(MotionEvent.ACTION_UP);
- vncCanvas.processPointerEvent(e, false, false);
- }
- });
- // t.setPriority(Thread.MAX_PRIORITY);
- t.start();
- return true;
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ singleClick(e);
+ return true;
+ // boolean multiTouch =
+ // (BCFactory.getInstance().getBCMotionEvent().getPointerCount(e) >
+ // 1);
+ // remoteMouseStayPut(e);
+ // vncCanvas.processPointerEvent(e, true, multiTouch ||
+ // vncCanvas.cameraButtonDown);
+ // e.setAction(MotionEvent.ACTION_UP);
+ // return vncCanvas.processPointerEvent(e, false, multiTouch ||
+ // vncCanvas.cameraButtonDown);
+ }
- }
+ private boolean singleClick(final MotionEvent e) {
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ remoteMouseStayPut(e);
+ // One
+ // Log.v("Double Click", "One");
+ vncCanvas.processPointerEvent(e, true, false);
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(VncCanvasActivity.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ e.setAction(MotionEvent.ACTION_UP);
+ vncCanvas.processPointerEvent(e, false, false);
+ }
+ });
+ // t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+ return true;
+
+ }
public boolean middleClick(final MotionEvent e) {
Thread t = new Thread(new Runnable() {
@@ -624,23 +638,23 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
}
- /*
- * (non-Javadoc) double tap: do two left mouse right mouse clicks on
- * remote without moving the mouse.
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onDoubleTap(
- * android.view.MotionEvent)
- */
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- if(!Config.enableDragOnLongPress)
+ /*
+ * (non-Javadoc) double tap: do two left mouse right mouse clicks on
+ * remote without moving the mouse.
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onDoubleTap(
+ * android.view.MotionEvent)
+ */
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (!Config.enableDragOnLongPress)
processDoubleTap(e);
else
doubleClick(e);
return false;
- }
+ }
private void processDoubleTap(final MotionEvent e) {
Thread t = new Thread(new Runnable() {
@@ -660,33 +674,33 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
}
});
t.start();
- }
+ }
/*
- * (non-Javadoc)
- *
- * @see
- * android.view.GestureDetector.SimpleOnGestureListener#onDown(android
- * .view.MotionEvent)
- */
- @Override
- public boolean onDown(MotionEvent e) {
- panner.stop();
- return true;
- }
+ * (non-Javadoc)
+ *
+ * @see
+ * android.view.GestureDetector.SimpleOnGestureListener#onDown(android
+ * .view.MotionEvent)
+ */
+ @Override
+ public boolean onDown(MotionEvent e) {
+ panner.stop();
+ return true;
+ }
- private Object doubleClickLock = new Object();
+ private Object doubleClickLock = new Object();
- private boolean doubleClick(final MotionEvent e1) {
- Thread t = new Thread(new Runnable() {
- public void run() {
+ private boolean doubleClick(final MotionEvent e1) {
+ Thread t = new Thread(new Runnable() {
+ public void run() {
synchronized (doubleClickLock) {
//XXX: We make a copy of the event because we have some
// race condition here updating mouseX, mouseY
MotionEvent event = MotionEvent.obtain(e1.getDownTime(),
- e1.getEventTime(), e1.getAction(),
- e1.getX(), e1.getY(), e1.getMetaState());
+ e1.getEventTime(), e1.getAction(),
+ e1.getX(), e1.getY(), e1.getMetaState());
remoteMouseStayPut(event);
// One
@@ -716,1119 +730,1134 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
event.setAction(MotionEvent.ACTION_UP);
vncCanvas.processPointerEvent(event, false, false);
}
- }
- });
- // t.setPriority(Thread.MAX_PRIORITY);
- t.start();
- return true;
+ }
+ });
+ // t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+ return true;
- }
- }
+ }
+ }
- private final static String TAG = "VncCanvasActivity";
- public static AbstractInputHandler inputHandler;
- public VncCanvas vncCanvas;
+ private final static String TAG = "VncCanvasActivity";
+ public static AbstractInputHandler inputHandler;
+ public VncCanvas vncCanvas;
+ public VncCursorView cursorView;
- public MenuItem[] inputModeMenuItems;
- public AbstractInputHandler inputModeHandlers[];
- public ConnectionBean connection;
- public boolean trackballButtonDown;
- public static final int inputModeIds[] = { R.id.itemInputFitToScreen, R.id.itemInputTouchpad, R.id.itemInputMouse,
- R.id.itemInputPan, R.id.itemInputTouchPanTrackballMouse, R.id.itemInputDPadPanTouchMouse,
- R.id.itemInputTouchPanZoomMouse };
- ZoomControls zoomer;
- Panner panner;
+ public MenuItem[] inputModeMenuItems;
+ public AbstractInputHandler inputModeHandlers[];
+ public ConnectionBean connection;
+ public boolean trackballButtonDown;
+ public static final int inputModeIds[] = {R.id.itemInputFitToScreen, R.id.itemInputTouchpad, R.id.itemInputMouse,
+ R.id.itemInputPan, R.id.itemInputTouchPanTrackballMouse, R.id.itemInputDPadPanTouchMouse,
+ R.id.itemInputTouchPanZoomMouse};
+ ZoomControls zoomer;
+ Panner panner;
- @Override
- public void onCreate(Bundle icicle) {
+ @Override
+ public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- activity = this;
+ super.onCreate(icicle);
+ activity = this;
- Intent i = getIntent();
- connection = new ConnectionBean();
- Uri data = i.getData();
- if ((data != null) && (data.getScheme().equals("vnc"))) {
- String host = data.getHost();
- // This should not happen according to Uri contract, but bug
- // introduced in Froyo (2.2)
- // has made this parsing of host necessary
- int index = host.indexOf(':');
- int port;
- if (index != -1) {
- try {
- port = Integer.parseInt(host.substring(index + 1));
- } catch (NumberFormatException nfe) {
- port = 0;
- }
- host = host.substring(0, index);
- } else {
- port = data.getPort();
- }
- if (host.equals(VncConstants.CONNECTION)) {
- ConnectionBean bean = new ConnectionBean();
- if (bean != null) {
- bean.setConnectionId(connection.get_Id());
- }
- } else {
- connection.setAddress(host);
- connection.setNickname(connection.getAddress());
- connection.setPort(port);
- List path = data.getPathSegments();
- if (path.size() >= 1) {
- connection.setColorModel(path.get(1));
- }
- if (path.size() >= 2) {
- connection.setPassword(path.get(1));
- }
- }
- } else {
+ Intent i = getIntent();
+ connection = new ConnectionBean();
+ Uri data = i.getData();
+ if ((data != null) && (data.getScheme().equals("vnc"))) {
+ String host = data.getHost();
+ // This should not happen according to Uri contract, but bug
+ // introduced in Froyo (2.2)
+ // has made this parsing of host necessary
+ int index = host.indexOf(':');
+ int port;
+ if (index != -1) {
+ try {
+ port = Integer.parseInt(host.substring(index + 1));
+ } catch (NumberFormatException nfe) {
+ port = 0;
+ }
+ host = host.substring(0, index);
+ } else {
+ port = data.getPort();
+ }
+ if (host.equals(VncConstants.CONNECTION)) {
+ ConnectionBean bean = new ConnectionBean();
+ if (bean != null) {
+ bean.setConnectionId(connection.get_Id());
+ }
+ } else {
+ connection.setAddress(host);
+ connection.setNickname(connection.getAddress());
+ connection.setPort(port);
+ List path = data.getPathSegments();
+ if (path.size() >= 1) {
+ connection.setColorModel(path.get(1));
+ }
+ if (path.size() >= 2) {
+ connection.setPassword(path.get(1));
+ }
+ }
+ } else {
- Bundle extras = i.getExtras();
+ Bundle extras = i.getExtras();
- if (connection.getPort() == 0) {
- connection.setPort(5901);
- }
+ if (connection.getPort() == 0) {
+ connection.setPort(5901);
+ }
- // Parse a HOST:PORT entry
- String host = connection.getAddress();
- // if (host.indexOf(':') > -1) {
- // String p = host.substring(host.indexOf(':') + 1);
- // try {
- // connection.setPort(Integer.parseInt(p));
- // } catch (Exception e) {
- // }
- // connection.setAddress(host.substring(0, host.indexOf(':')));
- // }
- }
- connection.setPassword(null);
- setContentView();
+ // Parse a HOST:PORT entry
+ String host = connection.getAddress();
+ // if (host.indexOf(':') > -1) {
+ // String p = host.substring(host.indexOf(':') + 1);
+ // try {
+ // connection.setPort(Integer.parseInt(p));
+ // } catch (Exception e) {
+ // }
+ // connection.setAddress(host.substring(0, host.indexOf(':')));
+ // }
+ }
+ connection.setPassword(null);
+ setContentView();
- vncCanvas = (VncCanvas) findViewById(R.id.vnc_canvas);
- zoomer = (ZoomControls) findViewById(R.id.zoomer);
+ vncCanvas = (VncCanvas) findViewById(R.id.vnc_canvas);
+ zoomer = (ZoomControls) findViewById(R.id.zoomer);
+ cursorView = findViewById(R.id.cursorView);
- vncCanvas.initializeVncCanvas(connection, new Runnable() {
- public void run() {
- setModes();
- }
- });
- zoomer.hide();
- zoomer.setOnZoomInClickListener(new View.OnClickListener() {
+ vncCanvas.initializeVncCanvas(connection, new Runnable() {
+ public void run() {
+ setModes();
+ }
+ });
+ zoomer.hide();
+ zoomer.setOnZoomInClickListener(new View.OnClickListener() {
- /*
- * (non-Javadoc)
- *
- * @see android.view.View.OnClickListener#onClick(android.view.View)
- */
- @Override
- public void onClick(View v) {
- showZoomer(true);
- vncCanvas.scaling.zoomIn(VncCanvasActivity.this);
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.view.View.OnClickListener#onClick(android.view.View)
+ */
+ @Override
+ public void onClick(View v) {
+ showZoomer(true);
+ vncCanvas.scaling.zoomIn(VncCanvasActivity.this);
- }
- });
- zoomer.setOnZoomOutClickListener(new View.OnClickListener() {
+ }
+ });
+ zoomer.setOnZoomOutClickListener(new View.OnClickListener() {
- /*
- * (non-Javadoc)
- *
- * @see android.view.View.OnClickListener#onClick(android.view.View)
- */
- @Override
- public void onClick(View v) {
- showZoomer(true);
- vncCanvas.scaling.zoomOut(VncCanvasActivity.this);
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.view.View.OnClickListener#onClick(android.view.View)
+ */
+ @Override
+ public void onClick(View v) {
+ showZoomer(true);
+ vncCanvas.scaling.zoomOut(VncCanvasActivity.this);
- }
- });
- zoomer.setOnZoomInClickListener(new View.OnClickListener() {
+ }
+ });
+ zoomer.setOnZoomInClickListener(new View.OnClickListener() {
- /*
- * (non-Javadoc)
- *
- * @see android.view.View.OnClickListener#onClick(android.view.View)
- */
- @Override
- public void onClick(View v) {
- InputMethodManager inputMgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMgr.toggleSoftInput(0, 0);
- }
- });
- zoomer.setOnZoomOutClickListener(new View.OnClickListener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.view.View.OnClickListener#onClick(android.view.View)
+ */
+ @Override
+ public void onClick(View v) {
+ InputMethodManager inputMgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMgr.toggleSoftInput(0, 0);
+ }
+ });
+ zoomer.setOnZoomOutClickListener(new View.OnClickListener() {
- /*
- * (non-Javadoc)
- *
- * @see android.view.View.OnClickListener#onClick(android.view.View)
- */
- @Override
- public void onClick(View v) {
- InputMethodManager inputMgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMgr.toggleSoftInput(0, 0);
- }
- });
- panner = new Panner(this, vncCanvas.handler);
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.view.View.OnClickListener#onClick(android.view.View)
+ */
+ @Override
+ public void onClick(View v) {
+ InputMethodManager inputMgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMgr.toggleSoftInput(0, 0);
+ }
+ });
+ panner = new Panner(this, vncCanvas.handler);
- inputHandler = getInputHandlerById(R.id.itemInputFitToScreen);
+ inputHandler = getInputHandlerById(R.id.itemInputFitToScreen);
- display = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
- }
+ display = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+ }
- public void setContentView() {
- setContentView(R.layout.activity_vnc);
- }
+ public void setContentView() {
+ setContentView(R.layout.activity_vnc);
+ }
- /**
- * Set modes on start to match what is specified in the ConnectionBean;
- * color mode (already done) scaling, input mode
- */
- void setModes() {
- AbstractInputHandler handler = getInputHandlerByName(connection.getInputMode());
- AbstractScaling.getByScaleType(connection.getScaleMode()).setScaleTypeForActivity(this);
- this.inputHandler = handler;
- showPanningState();
- }
+ /**
+ * Set modes on start to match what is specified in the ConnectionBean;
+ * color mode (already done) scaling, input mode
+ */
+ void setModes() {
+ AbstractInputHandler handler = getInputHandlerByName(connection.getInputMode());
+ AbstractScaling.getByScaleType(connection.getScaleMode()).setScaleTypeForActivity(this);
+ this.inputHandler = handler;
+ showPanningState();
+ }
- ConnectionBean getConnection() {
- return connection;
- }
+ ConnectionBean getConnection() {
+ return connection;
+ }
- /*
- * (non-Javadoc)
- *
- * @see android.app.Activity#onPrepareDialog(int, android.app.Dialog)
- */
- @Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- super.onPrepareDialog(id, dialog);
- if (dialog instanceof ConnectionSettable) {
- ((ConnectionSettable) dialog).setConnection(connection);
- }
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.app.Activity#onPrepareDialog(int, android.app.Dialog)
+ */
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ super.onPrepareDialog(id, dialog);
+ if (dialog instanceof ConnectionSettable) {
+ ((ConnectionSettable) dialog).setConnection(connection);
+ }
+ }
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- // ignore orientation/keyboard change
- super.onConfigurationChanged(newConfig);
- }
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ // ignore orientation/keyboard change
+ super.onConfigurationChanged(newConfig);
+ }
- @Override
- protected void onStop() {
- vncCanvas.disableRepaints();
- super.onStop();
- }
+ @Override
+ protected void onStop() {
+ vncCanvas.disableRepaints();
+ super.onStop();
+ }
- @Override
- protected void onRestart() {
- vncCanvas.enableRepaints();
- super.onRestart();
- }
+ @Override
+ protected void onRestart() {
+ vncCanvas.enableRepaints();
+ super.onRestart();
+ }
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.vnccanvasactivitymenu, menu);
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.vnccanvasactivitymenu, menu);
- if (vncCanvas.scaling != null) {
- menu.findItem(vncCanvas.scaling.getId()).setChecked(true);
- }
+ if (vncCanvas.scaling != null) {
+ menu.findItem(vncCanvas.scaling.getId()).setChecked(true);
+ }
- Menu inputMenu = menu.findItem(R.id.itemInputMode).getSubMenu();
+ Menu inputMenu = menu.findItem(R.id.itemInputMode).getSubMenu();
- inputModeMenuItems = new MenuItem[inputModeIds.length];
- for (int i = 0; i < inputModeIds.length; i++) {
- inputModeMenuItems[i] = inputMenu.findItem(inputModeIds[i]);
- }
- updateInputMenu();
- return true;
- }
+ inputModeMenuItems = new MenuItem[inputModeIds.length];
+ for (int i = 0; i < inputModeIds.length; i++) {
+ inputModeMenuItems[i] = inputMenu.findItem(inputModeIds[i]);
+ }
+ updateInputMenu();
+ return true;
+ }
- /**
- * Change the input mode sub-menu to reflect change in scaling
- */
- public void updateInputMenu() {
- if (inputModeMenuItems == null || vncCanvas.scaling == null) {
- return;
- }
- for (MenuItem item : inputModeMenuItems) {
- item.setEnabled(vncCanvas.scaling.isValidInputMode(item.getItemId()));
- if (getInputHandlerById(item.getItemId()) == inputHandler) {
- item.setChecked(true);
- }
- }
- }
-
-
-
- /**
- * If id represents an input handler, return that; otherwise return null
- *
- * @param id
- * @return
- */
- public AbstractInputHandler getInputHandlerById(int id) {
- if (inputModeHandlers == null) {
- inputModeHandlers = new AbstractInputHandler[inputModeIds.length];
- }
- for (int i = 0; i < inputModeIds.length; ++i) {
- if (inputModeIds[i] == id) {
- if (inputModeHandlers[i] == null) {
- if (id == R.id.itemInputFitToScreen)
- inputModeHandlers[i] = new FitToScreenMode();
- else if (id == R.id.itemInputPan)
- inputModeHandlers[i] = new PanMode();
- else if (id == R.id.itemInputMouse)
- inputModeHandlers[i] = new MouseMode();
-
- else if (id == R.id.itemInputTouchPanTrackballMouse)
- inputModeHandlers[i] = new TouchPanTrackballMouse();
- else if (id == R.id.itemInputDPadPanTouchMouse)
- inputModeHandlers[i] = new DPadPanTouchMouseMode();
-
- else if (id == R.id.itemInputTouchPanZoomMouse)
- inputModeHandlers[i] = new ZoomInputHandler();
-
- else if (id == R.id.itemInputTouchpad)
- inputModeHandlers[i] = new TouchpadInputHandler();
- }
-
- return inputModeHandlers[i];
- }
- }
- return null;
- }
-
- AbstractInputHandler getInputHandlerByName(String name) {
- AbstractInputHandler result = null;
- for (int id : inputModeIds) {
- AbstractInputHandler handler = getInputHandlerById(id);
- if (handler.getName().equals(name)) {
- result = handler;
- break;
- }
- }
- if (result == null) {
- result = getInputHandlerById(R.id.itemInputTouchPanZoomMouse);
- }
- return result;
- }
-
- int getModeIdFromHandler(AbstractInputHandler handler) {
- for (int id : inputModeIds) {
- if (handler == getInputHandlerById(id)) {
- return id;
- }
- }
- return R.id.itemInputTouchPanZoomMouse;
- }
-
- private MetaKeyBean lastSentKey;
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (isFinishing()) {
- vncCanvas.closeConnection();
- vncCanvas.onDestroy();
+ /**
+ * Change the input mode sub-menu to reflect change in scaling
+ */
+ public void updateInputMenu() {
+ if (inputModeMenuItems == null || vncCanvas.scaling == null) {
+ return;
+ }
+ for (MenuItem item : inputModeMenuItems) {
+ item.setEnabled(vncCanvas.scaling.isValidInputMode(item.getItemId()));
+ if (getInputHandlerById(item.getItemId()) == inputHandler) {
+ item.setChecked(true);
+ }
+ }
+ }
- }
- }
+ /**
+ * If id represents an input handler, return that; otherwise return null
+ *
+ * @param id
+ * @return
+ */
+ public AbstractInputHandler getInputHandlerById(int id) {
+ if (inputModeHandlers == null) {
+ inputModeHandlers = new AbstractInputHandler[inputModeIds.length];
+ }
+ for (int i = 0; i < inputModeIds.length; ++i) {
+ if (inputModeIds[i] == id) {
+ if (inputModeHandlers[i] == null) {
+ if (id == R.id.itemInputFitToScreen)
+ inputModeHandlers[i] = new FitToScreenMode();
+ else if (id == R.id.itemInputPan)
+ inputModeHandlers[i] = new PanMode();
+ else if (id == R.id.itemInputMouse)
+ inputModeHandlers[i] = new MouseMode();
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
- MotionEvent e = MotionEvent.obtain(1000, 1000, MotionEvent.ACTION_DOWN, vncCanvas.mouseX, vncCanvas.mouseY,
- 0);
- ((TouchpadInputHandler) this.inputHandler).rightClick(e);
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+ else if (id == R.id.itemInputTouchPanTrackballMouse)
+ inputModeHandlers[i] = new TouchPanTrackballMouse();
+ else if (id == R.id.itemInputDPadPanTouchMouse)
+ inputModeHandlers[i] = new DPadPanTouchMouseMode();
+
+ else if (id == R.id.itemInputTouchPanZoomMouse)
+ inputModeHandlers[i] = new ZoomInputHandler();
+
+ else if (id == R.id.itemInputTouchpad)
+ inputModeHandlers[i] = new TouchpadInputHandler();
+ }
+
+ return inputModeHandlers[i];
+ }
+ }
+ return null;
+ }
+
+ AbstractInputHandler getInputHandlerByName(String name) {
+ AbstractInputHandler result = null;
+ for (int id : inputModeIds) {
+ AbstractInputHandler handler = getInputHandlerById(id);
+ if (handler.getName().equals(name)) {
+ result = handler;
+ break;
+ }
+ }
+ if (result == null) {
+ result = getInputHandlerById(R.id.itemInputTouchPanZoomMouse);
+ }
+ return result;
+ }
+
+ int getModeIdFromHandler(AbstractInputHandler handler) {
+ for (int id : inputModeIds) {
+ if (handler == getInputHandlerById(id)) {
+ return id;
+ }
+ }
+ return R.id.itemInputTouchPanZoomMouse;
+ }
+
+ private MetaKeyBean lastSentKey;
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (isFinishing()) {
+ vncCanvas.closeConnection();
+ vncCanvas.onDestroy();
+
+
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ MotionEvent e = MotionEvent.obtain(1000, 1000, MotionEvent.ACTION_DOWN, vncCanvas.mouseX, vncCanvas.mouseY,
+ 0);
+ ((TouchpadInputHandler) this.inputHandler).rightClick(e);
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
MotionEvent e = MotionEvent.obtain(1000, 1000, MotionEvent.ACTION_DOWN, vncCanvas.mouseX, vncCanvas.mouseY,
0);
((TouchpadInputHandler) this.inputHandler).leftClick(e);
return true;
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
- return super.onKeyDown(keyCode, evt);
- }
+ return super.onKeyDown(keyCode, evt);
+ }
- return inputHandler.onKeyDown(keyCode, evt);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- if (keyCode == KeyEvent.KEYCODE_MENU) {
- return super.onKeyUp(keyCode, evt);
- }
-
- return inputHandler.onKeyUp(keyCode, evt);
- }
-
- public void showPanningState() {
- // Toast.makeText(this, inputHandler.getHandlerDescription(),
- // Toast.LENGTH_SHORT).show();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.app.Activity#onTrackballEvent(android.view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- trackballButtonDown = true;
- break;
- case MotionEvent.ACTION_UP:
- trackballButtonDown = false;
- break;
- }
- return inputHandler.onTrackballEvent(event);
- }
+ return inputHandler.onKeyDown(keyCode, evt);
+ }
@Override
- public boolean onTouchEvent(MotionEvent event) {
- // MK
- if (event.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ if (keyCode == KeyEvent.KEYCODE_MENU) {
+ return super.onKeyUp(keyCode, evt);
+ }
- if(event.getAction() == MotionEvent.ACTION_DOWN)
+ return inputHandler.onKeyUp(keyCode, evt);
+ }
+
+ public void showPanningState() {
+ // Toast.makeText(this, inputHandler.getHandlerDescription(),
+ // Toast.LENGTH_SHORT).show();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.app.Activity#onTrackballEvent(android.view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ trackballButtonDown = true;
+ break;
+ case MotionEvent.ACTION_UP:
+ trackballButtonDown = false;
+ break;
+ }
+ return inputHandler.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // MK
+ if (event.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ if (event.getAction() == MotionEvent.ACTION_DOWN)
vncCanvas.mouseDown = true;
- else if(event.getAction() == MotionEvent.ACTION_UP)
+ else if (event.getAction() == MotionEvent.ACTION_UP)
vncCanvas.mouseDown = false;
- return inputHandler.onTouchEvent(event);
- }
+ return inputHandler.onTouchEvent(event);
+ }
- protected void selectColorModel() {
- // Stop repainting the desktop
- // because the display is composited!
- vncCanvas.disableRepaints();
+ protected void selectColorModel() {
+ // Stop repainting the desktop
+ // because the display is composited!
+ vncCanvas.disableRepaints();
- String[] choices = new String[COLORMODEL.values().length];
- int currentSelection = -1;
- for (int i = 0; i < choices.length; i++) {
- COLORMODEL cm = COLORMODEL.values()[i];
- choices[i] = cm.toString();
- if (vncCanvas.isColorModel(cm)) {
- currentSelection = i;
- }
- }
+ String[] choices = new String[COLORMODEL.values().length];
+ int currentSelection = -1;
+ for (int i = 0; i < choices.length; i++) {
+ COLORMODEL cm = COLORMODEL.values()[i];
+ choices[i] = cm.toString();
+ if (vncCanvas.isColorModel(cm)) {
+ currentSelection = i;
+ }
+ }
- final Dialog dialog = new Dialog(this);
- dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
- ListView list = new ListView(this);
- list.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_checked, choices));
- list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- list.setItemChecked(currentSelection, true);
- list.setOnItemClickListener(new OnItemClickListener() {
- public void onItemClick(AdapterView> arg0, View arg1, int arg2, long arg3) {
- if (dialog.isShowing()) {
- dialog.dismiss();
- }
- COLORMODEL cm = COLORMODEL.values()[arg2];
- vncCanvas.setColorModel(cm);
- connection.setColorModel(cm.nameString());
+ final Dialog dialog = new Dialog(this);
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ ListView list = new ListView(this);
+ list.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_checked, choices));
+ list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ list.setItemChecked(currentSelection, true);
+ list.setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView> arg0, View arg1, int arg2, long arg3) {
+ if (dialog.isShowing()) {
+ dialog.dismiss();
+ }
+ COLORMODEL cm = COLORMODEL.values()[arg2];
+ vncCanvas.setColorModel(cm);
+ connection.setColorModel(cm.nameString());
UIUtils.toastShort(VncCanvasActivity.this, "Updating Color Model to " + cm.toString());
- }
- });
- dialog.setOnDismissListener(new OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface arg0) {
- Log.i(TAG, "Color Model Selector dismissed");
- // Restore desktop repaints
- vncCanvas.enableRepaints();
- }
- });
- dialog.setContentView(list);
- dialog.show();
- }
-
- float panTouchX, panTouchY;
-
- /**
- * Pan based on touch motions
- *
- * @param event
- */
- private boolean pan(MotionEvent event) {
- float curX = event.getX();
- float curY = event.getY();
- int dX = (int) (panTouchX - curX);
- int dY = (int) (panTouchY - curY);
-
- return vncCanvas.pan(dX, dY);
- }
-
- boolean defaultKeyDownHandler(int keyCode, KeyEvent evt) {
- if (vncCanvas.processLocalKeyEvent(keyCode, evt)) {
- return true;
- }
- return super.onKeyDown(keyCode, evt);
- }
-
- boolean defaultKeyUpHandler(int keyCode, KeyEvent evt) {
- if (vncCanvas.processLocalKeyEvent(keyCode, evt)) {
- return true;
- }
- return super.onKeyUp(keyCode, evt);
- }
-
- boolean touchPan(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- panTouchX = event.getX();
- panTouchY = event.getY();
- break;
- case MotionEvent.ACTION_MOVE:
- pan(event);
- panTouchX = event.getX();
- panTouchY = event.getY();
- break;
- case MotionEvent.ACTION_UP:
- pan(event);
- break;
- }
- return true;
- }
-
- private static int convertTrackballDelta(double delta) {
- return (int) Math.pow(Math.abs(delta) * 6.01, 2.5) * (delta < 0.0 ? -1 : 1);
- }
-
- boolean trackballMouse(MotionEvent evt) {
- // MK
- if (evt.getAction() == MotionEvent.ACTION_CANCEL)
- return false;
-
- int dx = convertTrackballDelta(evt.getX());
- int dy = convertTrackballDelta(evt.getY());
-
- evt.offsetLocation(vncCanvas.mouseX + dx - evt.getX(), vncCanvas.mouseY + dy - evt.getY());
-
- if (vncCanvas.processPointerEvent(evt, trackballButtonDown)) {
- return true;
- }
- return VncCanvasActivity.super.onTouchEvent(evt);
- }
-
- long hideZoomAfterMs;
- static final long ZOOM_HIDE_DELAY_MS = 2500;
- HideZoomRunnable hideZoomInstance = new HideZoomRunnable();
-
- private void showZoomer(boolean force) {
-
- if (force || zoomer.getVisibility() != View.VISIBLE) {
- // zoomer.show();
- hideZoomAfterMs = SystemClock.uptimeMillis() + ZOOM_HIDE_DELAY_MS;
- vncCanvas.handler.postAtTime(hideZoomInstance, hideZoomAfterMs + 10);
- }
- }
-
- private class HideZoomRunnable implements Runnable {
-
- public void run() {
- if (SystemClock.uptimeMillis() >= hideZoomAfterMs) {
- zoomer.hide();
- }
- }
- }
-
- /**
- * Touches and dpad (trackball) pan the screen
- *
- * @author Michael A. MacDonald
- *
- */
- class PanMode implements AbstractInputHandler {
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- // DPAD KeyDown events are move MotionEvents in Panning Mode
- final int dPos = 100;
- boolean result = false;
- // MK
- if (evt.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- result = true;
- break;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE,
- panTouchX + dPos, panTouchY, 0));
- result = true;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE,
- panTouchX - dPos, panTouchY, 0));
- result = true;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX,
- panTouchY + dPos, 0));
- result = true;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX,
- panTouchY - dPos, 0));
- result = true;
- break;
- default:
- result = defaultKeyDownHandler(keyCode, evt);
- break;
- }
- return result;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- // Ignore KeyUp events for DPAD keys in Panning Mode; trackball
- // button switches to mouse mode
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- inputHandler = getInputHandlerById(R.id.itemInputMouse);
- connection.setInputMode(inputHandler.getName());
- updateInputMenu();
- showPanningState();
- return true;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- return true;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- return true;
- case KeyEvent.KEYCODE_DPAD_UP:
- return true;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- return true;
- }
- return defaultKeyUpHandler(keyCode, evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
- * .MotionEvent)
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // MK
- if (event.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
-
- return touchPan(event);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
- * view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent evt) {
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#handlerDescription()
- */
- @Override
- public CharSequence getHandlerDescription() {
- return getResources().getText(R.string.input_mode_panning);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getName()
- */
- @Override
- public String getName() {
- return "PAN_MODE";
- }
- }
-
- /**
- * The touchscreen pans the screen; the trackball moves and clicks the
- * mouse.
- *
- * @author Michael A. MacDonald
- *
- */
- public class TouchPanTrackballMouse implements AbstractInputHandler {
-
- private DPadMouseKeyHandler keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyDown(keyCode, evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyUp(keyCode, evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
- * .MotionEvent)
- */
- @Override
- public boolean onTouchEvent(MotionEvent evt) {
- // MK
- if (evt.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
-
- return touchPan(evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
- * view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent evt) {
- return trackballMouse(evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#handlerDescription()
- */
- @Override
- public CharSequence getHandlerDescription() {
- return getResources().getText(R.string.input_mode_touchpad_pan_trackball_mouse);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getName()
- */
- @Override
- public String getName() {
- return "TOUCH_PAN_TRACKBALL_MOUSE";
- }
- }
-
- public static final String FIT_SCREEN_NAME = "FIT_SCREEN";
- /**
- * Internal name for default input mode with Zoom scaling
- */
- public static final String TOUCH_ZOOM_MODE = "TOUCH_ZOOM_MODE";
- public static final String TOUCHPAD_MODE = "TOUCHPAD_MODE";
-
- /**
- * In fit-to-screen mode, no panning. Trackball and touchscreen work as
- * mouse.
- *
- * @author Michael A. MacDonald
- *
- */
- public class FitToScreenMode implements AbstractInputHandler {
-
- private DPadMouseKeyHandler keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyDown(keyCode, evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- return keyHandler.onKeyUp(keyCode, evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
- * .MotionEvent)
- */
- @Override
- public boolean onTouchEvent(MotionEvent evt) {
- // MK
- if (evt.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
-
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
- * view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent evt) {
- return trackballMouse(evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#handlerDescription()
- */
- @Override
- public CharSequence getHandlerDescription() {
- return getResources().getText(R.string.input_mode_fit_to_screen);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getName()
- */
- @Override
- public String getName() {
- return FIT_SCREEN_NAME;
- }
- }
-
- /**
- * Touch screen controls, clicks the mouse.
- *
- * @author Michael A. MacDonald
- *
- */
- class MouseMode implements AbstractInputHandler {
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- return true;
- }
- return defaultKeyDownHandler(keyCode, evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- inputHandler = getInputHandlerById(R.id.itemInputPan);
- showPanningState();
- connection.setInputMode(inputHandler.getName());
- updateInputMenu();
- return true;
- }
- return defaultKeyUpHandler(keyCode, evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
- * .MotionEvent)
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // Mouse Pointer Control Mode
- // Pointer event is absolute coordinates.
-
- // MK
- if (event.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
-
- vncCanvas.changeTouchCoordinatesToFullFrame(event);
- if (vncCanvas.processPointerEvent(event, true)) {
- return true;
- }
- return VncCanvasActivity.super.onTouchEvent(event);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
- * view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent evt) {
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#handlerDescription()
- */
- @Override
- public CharSequence getHandlerDescription() {
- return getResources().getText(R.string.input_mode_mouse);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getName()
- */
- @Override
- public String getName() {
- return "MOUSE";
- }
- }
-
- /**
- * Touch screen controls, clicks the mouse. DPad pans the screen
- *
- * @author Michael A. MacDonald
- *
- */
- class DPadPanTouchMouseMode implements AbstractInputHandler {
-
- private boolean isPanning;
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent evt) {
- int xv = 0;
- int yv = 0;
- boolean result = true;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- // xv = -1;
- vncCanvas.sendMetaKey(MetaKeyBean.keyArrowLeft);
- return result;
- // break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- // xv = 1;
- vncCanvas.sendMetaKey(MetaKeyBean.keyArrowRight);
- return result;
- // break;
- case KeyEvent.KEYCODE_DPAD_UP:
- // yv = -1;
- vncCanvas.sendMetaKey(MetaKeyBean.keyArrowUp);
- return result;
- // break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- // yv = 1;
- vncCanvas.sendMetaKey(MetaKeyBean.keyArrowDown);
- return result;
- // break;
- default:
- result = defaultKeyDownHandler(keyCode, evt);
- break;
- }
- if ((xv != 0 || yv != 0) && !isPanning) {
- final int x = xv;
- final int y = yv;
- isPanning = true;
- panner.start(x, y, new Panner.VelocityUpdater() {
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.Panner.VelocityUpdater#updateVelocity
- * (android.graphics.Point, long)
- */
- @Override
- public boolean updateVelocity(PointF p, long interval) {
- double scale = (2.0 * (double) interval / 50.0);
- if (Math.abs(p.x) < 500) {
- p.x += (int) (scale * x);
- }
- if (Math.abs(p.y) < 500) {
- p.y += (int) (scale * y);
- }
- return true;
- }
- });
- vncCanvas.pan(x, y);
- }
- return result;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
- * android.view.SimulateKeyEvent)
- */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent evt) {
- boolean result = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- panner.stop();
- isPanning = false;
- result = true;
- break;
- default:
- result = defaultKeyUpHandler(keyCode, evt);
- break;
- }
- return result;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
- * .MotionEvent)
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // Mouse Pointer Control Mode
- // Pointer event is absolute coordinates.
-
- // MK
- if (event.getAction() == MotionEvent.ACTION_CANCEL)
- return true;
-
- vncCanvas.changeTouchCoordinatesToFullFrame(event);
- if (vncCanvas.processPointerEvent(event, true)) {
- return true;
- }
- return VncCanvasActivity.super.onTouchEvent(event);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
- * view.MotionEvent)
- */
- @Override
- public boolean onTrackballEvent(MotionEvent evt) {
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#handlerDescription()
- */
- @Override
- public CharSequence getHandlerDescription() {
- return getResources().getText(R.string.input_mode_dpad_pan_touchpad_mouse);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.androidVNC.AbstractInputHandler#getName()
- */
- @Override
- public String getName() {
- return "DPAD_PAN_TOUCH_MOUSE";
- }
- }
+ }
+ });
+ dialog.setOnDismissListener(new OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface arg0) {
+ Log.i(TAG, "Color Model Selector dismissed");
+ // Restore desktop repaints
+ vncCanvas.enableRepaints();
+ }
+ });
+ dialog.setContentView(list);
+ dialog.show();
+ }
+
+ float panTouchX, panTouchY;
+
+ /**
+ * Pan based on touch motions
+ *
+ * @param event
+ */
+ private boolean pan(MotionEvent event) {
+ float curX = event.getX();
+ float curY = event.getY();
+ int dX = (int) (panTouchX - curX);
+ int dY = (int) (panTouchY - curY);
+
+ return vncCanvas.pan(dX, dY);
+ }
+
+ boolean defaultKeyDownHandler(int keyCode, KeyEvent evt) {
+ if (vncCanvas.processLocalKeyEvent(keyCode, evt)) {
+ return true;
+ }
+ return super.onKeyDown(keyCode, evt);
+ }
+
+ boolean defaultKeyUpHandler(int keyCode, KeyEvent evt) {
+ if (vncCanvas.processLocalKeyEvent(keyCode, evt)) {
+ return true;
+ }
+ return super.onKeyUp(keyCode, evt);
+ }
+
+ boolean touchPan(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ panTouchX = event.getX();
+ panTouchY = event.getY();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ pan(event);
+ panTouchX = event.getX();
+ panTouchY = event.getY();
+ break;
+ case MotionEvent.ACTION_UP:
+ pan(event);
+ break;
+ }
+ return true;
+ }
+
+ private static int convertTrackballDelta(double delta) {
+ return (int) Math.pow(Math.abs(delta) * 6.01, 2.5) * (delta < 0.0 ? -1 : 1);
+ }
+
+ boolean trackballMouse(MotionEvent evt) {
+ // MK
+ if (evt.getAction() == MotionEvent.ACTION_CANCEL)
+ return false;
+
+ int dx = convertTrackballDelta(evt.getX());
+ int dy = convertTrackballDelta(evt.getY());
+
+ evt.offsetLocation(vncCanvas.mouseX + dx - evt.getX(), vncCanvas.mouseY + dy - evt.getY());
+
+ if (vncCanvas.processPointerEvent(evt, trackballButtonDown)) {
+ return true;
+ }
+ return VncCanvasActivity.super.onTouchEvent(evt);
+ }
+
+ long hideZoomAfterMs;
+ static final long ZOOM_HIDE_DELAY_MS = 2500;
+ HideZoomRunnable hideZoomInstance = new HideZoomRunnable();
+
+ private void showZoomer(boolean force) {
+
+ if (force || zoomer.getVisibility() != View.VISIBLE) {
+ // zoomer.show();
+ hideZoomAfterMs = SystemClock.uptimeMillis() + ZOOM_HIDE_DELAY_MS;
+ vncCanvas.handler.postAtTime(hideZoomInstance, hideZoomAfterMs + 10);
+ }
+ }
+
+ private class HideZoomRunnable implements Runnable {
+
+ public void run() {
+ if (SystemClock.uptimeMillis() >= hideZoomAfterMs) {
+ zoomer.hide();
+ }
+ }
+ }
+
+ /**
+ * Touches and dpad (trackball) pan the screen
+ *
+ * @author Michael A. MacDonald
+ *
+ */
+ class PanMode implements AbstractInputHandler {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ // DPAD KeyDown events are move MotionEvents in Panning Mode
+ final int dPos = 100;
+ boolean result = false;
+ // MK
+ if (evt.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ result = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE,
+ panTouchX + dPos, panTouchY, 0));
+ result = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE,
+ panTouchX - dPos, panTouchY, 0));
+ result = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX,
+ panTouchY + dPos, 0));
+ result = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX,
+ panTouchY - dPos, 0));
+ result = true;
+ break;
+ default:
+ result = defaultKeyDownHandler(keyCode, evt);
+ break;
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ // Ignore KeyUp events for DPAD keys in Panning Mode; trackball
+ // button switches to mouse mode
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ inputHandler = getInputHandlerById(R.id.itemInputMouse);
+ connection.setInputMode(inputHandler.getName());
+ updateInputMenu();
+ showPanningState();
+ return true;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ return true;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ return true;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ return true;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ return true;
+ }
+ return defaultKeyUpHandler(keyCode, evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
+ * .MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // MK
+ if (event.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ return touchPan(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
+ * view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent evt) {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#handlerDescription()
+ */
+ @Override
+ public CharSequence getHandlerDescription() {
+ return getResources().getText(R.string.input_mode_panning);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getName()
+ */
+ @Override
+ public String getName() {
+ return "PAN_MODE";
+ }
+ }
+
+ /**
+ * The touchscreen pans the screen; the trackball moves and clicks the
+ * mouse.
+ *
+ * @author Michael A. MacDonald
+ *
+ */
+ public class TouchPanTrackballMouse implements AbstractInputHandler {
+
+ private DPadMouseKeyHandler keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyDown(keyCode, evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyUp(keyCode, evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
+ * .MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent evt) {
+ // MK
+ if (evt.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ return touchPan(evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
+ * view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent evt) {
+ return trackballMouse(evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#handlerDescription()
+ */
+ @Override
+ public CharSequence getHandlerDescription() {
+ return getResources().getText(R.string.input_mode_touchpad_pan_trackball_mouse);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getName()
+ */
+ @Override
+ public String getName() {
+ return "TOUCH_PAN_TRACKBALL_MOUSE";
+ }
+ }
+
+ public static final String FIT_SCREEN_NAME = "FIT_SCREEN";
+ /**
+ * Internal name for default input mode with Zoom scaling
+ */
+ public static final String TOUCH_ZOOM_MODE = "TOUCH_ZOOM_MODE";
+ public static final String TOUCHPAD_MODE = "TOUCHPAD_MODE";
+
+ /**
+ * In fit-to-screen mode, no panning. Trackball and touchscreen work as
+ * mouse.
+ *
+ * @author Michael A. MacDonald
+ *
+ */
+ public class FitToScreenMode implements AbstractInputHandler {
+
+ private DPadMouseKeyHandler keyHandler = new DPadMouseKeyHandler(VncCanvasActivity.this, vncCanvas.handler);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyDown(keyCode, evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ return keyHandler.onKeyUp(keyCode, evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
+ * .MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent evt) {
+ // MK
+ if (evt.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
+ * view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent evt) {
+ return trackballMouse(evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#handlerDescription()
+ */
+ @Override
+ public CharSequence getHandlerDescription() {
+ return getResources().getText(R.string.input_mode_fit_to_screen);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getName()
+ */
+ @Override
+ public String getName() {
+ return FIT_SCREEN_NAME;
+ }
+ }
+
+ /**
+ * Touch screen controls, clicks the mouse.
+ *
+ * @author Michael A. MacDonald
+ *
+ */
+ class MouseMode implements AbstractInputHandler {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ return true;
+ }
+ return defaultKeyDownHandler(keyCode, evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ inputHandler = getInputHandlerById(R.id.itemInputPan);
+ showPanningState();
+ connection.setInputMode(inputHandler.getName());
+ updateInputMenu();
+ return true;
+ }
+ return defaultKeyUpHandler(keyCode, evt);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
+ * .MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // Mouse Pointer Control Mode
+ // Pointer event is absolute coordinates.
+
+ // MK
+ if (event.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ vncCanvas.changeTouchCoordinatesToFullFrame(event);
+ if (vncCanvas.processPointerEvent(event, true)) {
+ return true;
+ }
+ return VncCanvasActivity.super.onTouchEvent(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
+ * view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent evt) {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#handlerDescription()
+ */
+ @Override
+ public CharSequence getHandlerDescription() {
+ return getResources().getText(R.string.input_mode_mouse);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getName()
+ */
+ @Override
+ public String getName() {
+ return "MOUSE";
+ }
+ }
+
+ /**
+ * Touch screen controls, clicks the mouse. DPad pans the screen
+ *
+ * @author Michael A. MacDonald
+ *
+ */
+ class DPadPanTouchMouseMode implements AbstractInputHandler {
+
+ private boolean isPanning;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyDown(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent evt) {
+ int xv = 0;
+ int yv = 0;
+ boolean result = true;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ // xv = -1;
+ vncCanvas.sendMetaKey(MetaKeyBean.keyArrowLeft);
+ return result;
+ // break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ // xv = 1;
+ vncCanvas.sendMetaKey(MetaKeyBean.keyArrowRight);
+ return result;
+ // break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ // yv = -1;
+ vncCanvas.sendMetaKey(MetaKeyBean.keyArrowUp);
+ return result;
+ // break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ // yv = 1;
+ vncCanvas.sendMetaKey(MetaKeyBean.keyArrowDown);
+ return result;
+ // break;
+ default:
+ result = defaultKeyDownHandler(keyCode, evt);
+ break;
+ }
+ if ((xv != 0 || yv != 0) && !isPanning) {
+ final int x = xv;
+ final int y = yv;
+ isPanning = true;
+ panner.start(x, y, new Panner.VelocityUpdater() {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.Panner.VelocityUpdater#updateVelocity
+ * (android.graphics.Point, long)
+ */
+ @Override
+ public boolean updateVelocity(PointF p, long interval) {
+ double scale = (2.0 * (double) interval / 50.0);
+ if (Math.abs(p.x) < 500) {
+ p.x += (int) (scale * x);
+ }
+ if (Math.abs(p.y) < 500) {
+ p.y += (int) (scale * y);
+ }
+ return true;
+ }
+ });
+ vncCanvas.pan(x, y);
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#onKeyUp(int,
+ * android.view.SimulateKeyEvent)
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent evt) {
+ boolean result = false;
+
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ panner.stop();
+ isPanning = false;
+ result = true;
+ break;
+ default:
+ result = defaultKeyUpHandler(keyCode, evt);
+ break;
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTouchEvent(android.view
+ * .MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // Mouse Pointer Control Mode
+ // Pointer event is absolute coordinates.
+
+ // MK
+ if (event.getAction() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ vncCanvas.changeTouchCoordinatesToFullFrame(event);
+ if (vncCanvas.processPointerEvent(event, true)) {
+ return true;
+ }
+ return VncCanvasActivity.super.onTouchEvent(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * android.androidVNC.AbstractInputHandler#onTrackballEvent(android.
+ * view.MotionEvent)
+ */
+ @Override
+ public boolean onTrackballEvent(MotionEvent evt) {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#handlerDescription()
+ */
+ @Override
+ public CharSequence getHandlerDescription() {
+ return getResources().getText(R.string.input_mode_dpad_pan_touchpad_mouse);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.androidVNC.AbstractInputHandler#getName()
+ */
+ @Override
+ public String getName() {
+ return "DPAD_PAN_TOUCH_MOUSE";
+ }
+ }
public void onConnected() {
}
- public void onDisconnected() {
+ public void onDisconnected() {
- }
+ }
- public void reconnect() {
- // Recreate canvas to change resolution as resolution when changed in some Linux OS may cause canvas to not resize accordingly.
+ public void reconnect() {
+ // Recreate canvas to change resolution as resolution when changed in some Linux OS may cause canvas to not resize accordingly.
- // Remove old canvas
- ViewGroup parent = findViewById(R.id.vnc_canvas_layout);
- parent.removeView(vncCanvas);
+ // Remove old canvas
+ ViewGroup parent = findViewById(R.id.vnc_canvas_layout);
+ parent.removeView(vncCanvas);
- // Create new canvas
- VncCanvas newCanvas = new VncCanvas(this);
- newCanvas.setId(R.id.vnc_canvas); // Reassign ID
- newCanvas.setKeepScreenOn(true);
+ // Create new canvas
+ VncCanvas newCanvas = new VncCanvas(this);
+ newCanvas.setId(R.id.vnc_canvas); // Reassign ID
+ newCanvas.setKeepScreenOn(true);
// Add to parent
- RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- );
- params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ );
+ params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
- parent.addView(newCanvas, params);
+ parent.addView(newCanvas, params);
// Reassign reference variable
- vncCanvas = newCanvas;
+ vncCanvas = newCanvas;
- vncCanvas.initializeVncCanvas(connection, new Runnable() {
- public void run() {
- setModes();
- }
- });
- }
+ vncCanvas.initializeVncCanvas(connection, new Runnable() {
+ public void run() {
+ setModes();
+ }
+ });
+ }
+
+ public void syncCursorViewWithBitmap() {
+ scale = (float) vncCanvas.getHeight() / vncCanvas.getFramebufferHeight();
+
+ vncCanvas.post(() -> {
+ LinearLayout.LayoutParams lp =
+ (LinearLayout.LayoutParams) cursorView.getLayoutParams();
+
+ lp.width = Math.round(vncCanvas.getFramebufferWidth() * scale);
+ lp.height = Math.round(vncCanvas.getFramebufferHeight() * scale);
+
+ cursorView.setLayoutParams(lp);
+ });
+ }
}
diff --git a/app/src/main/java/android/androidVNC/VncCursorView.java b/app/src/main/java/android/androidVNC/VncCursorView.java
new file mode 100644
index 0000000..72c676b
--- /dev/null
+++ b/app/src/main/java/android/androidVNC/VncCursorView.java
@@ -0,0 +1,53 @@
+package android.androidVNC;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+import com.vectras.vm.R;
+
+public class VncCursorView extends View {
+
+ private Bitmap cursor;
+ private float x, y;
+
+ public VncCursorView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public VncCursorView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public VncCursorView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
+
+ private void init(Context context) {
+ cursor = BitmapFactory.decodeResource(
+ context.getResources(),
+ R.drawable.xc_left_ptr
+ );
+ }
+
+ public void update(float x, float y) {
+ this.x = x;
+ this.y = y;
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(@NonNull Canvas canvas) {
+ if (cursor != null) {
+ canvas.drawBitmap(cursor, x, y, null);
+ }
+ }
+}
diff --git a/app/src/main/java/com/vectras/qemu/MainSettingsManager.java b/app/src/main/java/com/vectras/qemu/MainSettingsManager.java
index c4ac0d1..7f42d1e 100644
--- a/app/src/main/java/com/vectras/qemu/MainSettingsManager.java
+++ b/app/src/main/java/com/vectras/qemu/MainSettingsManager.java
@@ -1143,4 +1143,16 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean("showLastCrashLog", false);
}
+
+ public static void setShowVirtualMouse(Context context, Boolean _boolean) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ SharedPreferences.Editor edit = prefs.edit();
+ edit.putBoolean("showVirtualMouse", _boolean);
+ edit.apply();
+ }
+
+ public static Boolean getShowVirtualMouse(Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ return prefs.getBoolean("showVirtualMouse", false);
+ }
}
diff --git a/app/src/main/java/com/vectras/qemu/MainVNCActivity.java b/app/src/main/java/com/vectras/qemu/MainVNCActivity.java
index 45f7007..431af89 100644
--- a/app/src/main/java/com/vectras/qemu/MainVNCActivity.java
+++ b/app/src/main/java/com/vectras/qemu/MainVNCActivity.java
@@ -79,7 +79,7 @@ public class MainVNCActivity extends VncCanvasActivity {
private final String TAG = "MainVNCActivity";
public static MainVNCActivity getContext;
private final int retryLimit = 3;
- private ActivityVncBinding binding;
+ public ActivityVncBinding binding;
private ControlsFragmentBinding bindingControls;
private DesktopControlsBinding bindingDesktopControls;
private GameControlsBinding bindingGameControls;
@@ -163,6 +163,8 @@ public class MainVNCActivity extends VncCanvasActivity {
// Do not attempt to reconnect while connected.
reconnect();
});
+
+ binding.cursorView.setVisibility(MainSettingsManager.getShowVirtualMouse(this) || VMManager.isNeedUseVirtualMouse() ? View.VISIBLE : View.GONE);
}
private void setDefaulViewMode() {
@@ -668,7 +670,7 @@ public class MainVNCActivity extends VncCanvasActivity {
} else {
try {
return super.dispatchKeyEvent(event);
- } catch (ClassCastException e) {
+ } catch (Exception e) {
return true;
}
}
@@ -767,6 +769,7 @@ public class MainVNCActivity extends VncCanvasActivity {
binding.lnNosignal.setVisibility(View.GONE);
this.vncCanvas.setFocusableInTouchMode(true);
+ syncCursorViewWithBitmap();
});
}
@@ -1081,9 +1084,14 @@ public class MainVNCActivity extends VncCanvasActivity {
});
bindingDesktopControls.middleBtn.setOnClickListener(v -> {
- MotionEvent e = MotionEvent.obtain(1000, 1000, MotionEvent.ACTION_DOWN, vncCanvas.mouseX, vncCanvas.mouseY,
- 0);
- ((TouchpadInputHandler) VncCanvasActivity.inputHandler).middleClick(e);
+ try {
+ MotionEvent e = MotionEvent.obtain(1000, 1000, MotionEvent.ACTION_DOWN, vncCanvas.mouseX, vncCanvas.mouseY,
+ 0);
+ ((TouchpadInputHandler) VncCanvasActivity.inputHandler).middleClick(e);
+ } catch (Exception e) {
+ VMManager.sendMiddleMouseKey();
+ VMManager.sendMiddleMouseKey();
+ }
});
bindingDesktopControls.leftClickBtn.setOnClickListener(v -> {
diff --git a/app/src/main/java/com/vectras/vm/VMCreatorActivity.java b/app/src/main/java/com/vectras/vm/VMCreatorActivity.java
index c04afb2..0eda2d3 100644
--- a/app/src/main/java/com/vectras/vm/VMCreatorActivity.java
+++ b/app/src/main/java/com/vectras/vm/VMCreatorActivity.java
@@ -627,7 +627,7 @@ public class VMCreatorActivity extends AppCompatActivity {
.into(binding.ivIcon);
} else {
binding.ivAddThubnail.setImageResource(R.drawable.round_add_24);
- VMManager.setIconWithName(binding.ivIcon, current.itemName);
+ VMManager.setIconWithName(binding.ivIcon, Objects.requireNonNull(binding.title.getText()).toString());
}
} else {
binding.ivAddThubnail.setImageResource(R.drawable.round_add_24);
diff --git a/app/src/main/java/com/vectras/vm/VMManager.java b/app/src/main/java/com/vectras/vm/VMManager.java
index 5cab167..5287432 100644
--- a/app/src/main/java/com/vectras/vm/VMManager.java
+++ b/app/src/main/java/com/vectras/vm/VMManager.java
@@ -222,6 +222,8 @@ public class VMManager {
return result.toString();
}
+ //This can be removed because QMP currently uses sockets instead of open ports.
+ @Deprecated
public static int startRandomPort() {
int _result;
Random _random = new Random();
@@ -229,13 +231,15 @@ public class VMManager {
int _max = 65535;
_result = _random.nextInt(_max - _min + 1) + _min;
- if (FileUtils.isFileExists(AppConfig.romsdatajson)) {
+ if (FileUtils.isFileExists(AppConfig.romsdatajson) || FileUtils.canRead(AppConfig.romsdatajson)) {
if (FileUtils.readAFile(AppConfig.romsdatajson).contains("\"qmpPort\":" + _result)) {
_result = _random.nextInt(_max - _min + 1) + _min;
}
if (FileUtils.readAFile(AppConfig.romsdatajson).contains("\"qmpPort\":" + _result)) {
_result = _random.nextInt(_max - _min + 1) + _min;
}
+ } else {
+ _result = 8080;
}
return _result;
@@ -985,6 +989,12 @@ public class VMManager {
_dialog.dismiss();
});
+ _view.findViewById(R.id.ln_virtualmouse).setOnClickListener(v -> {
+ MainVNCActivity.getContext.binding.cursorView.setVisibility(MainVNCActivity.getContext.binding.cursorView.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
+ MainSettingsManager.setShowVirtualMouse(_activity, MainVNCActivity.getContext.binding.cursorView.getVisibility() == View.VISIBLE);
+ _dialog.dismiss();
+ });
+
_view.findViewById(R.id.ln_mouse).setOnClickListener(v -> {
MainVNCActivity.getContext.onMouseMode();
_dialog.dismiss();
@@ -1356,6 +1366,14 @@ public class VMManager {
|| _qemuCommand.contains("-machine pc-q35");
}
+ public static boolean isNeedUseVirtualMouse() {
+ return lastQemuCommand.contains("-vga qxl") ||
+ lastQemuCommand.contains("-vga virtio") ||
+ lastQemuCommand.contains("-device qxl-vga") ||
+ lastQemuCommand.contains("-device virtio-vga") ||
+ lastQemuCommand.contains("-device virtio-gpu");
+ }
+
public static String addAudioDevSdl(String env) {
final String audioDevParam = ",audiodev=defaultaudiodev -audiodev sdl,id=defaultaudiodev ";
String result = env;
diff --git a/app/src/main/java/com/vectras/vm/utils/FileUtils.java b/app/src/main/java/com/vectras/vm/utils/FileUtils.java
index 7b93873..69b560e 100644
--- a/app/src/main/java/com/vectras/vm/utils/FileUtils.java
+++ b/app/src/main/java/com/vectras/vm/utils/FileUtils.java
@@ -598,18 +598,19 @@ public class FileUtils {
public static boolean moveFile(String oldfilename, String newFolderPath, String newFilename) {
File folder = new File(newFolderPath);
if (!folder.exists())
- folder.mkdirs();
+ folder.mkdirs();
File oldfile = new File(oldfilename);
File newFile = new File(newFolderPath, newFilename);
- if (!newFile.exists())
- try {
- newFile.createNewFile();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ if (!newFile.exists()) {
+ try {
+ newFile.createNewFile();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
return oldfile.renameTo(newFile);
}
@@ -739,6 +740,11 @@ public class FileUtils {
}
}
+ public static boolean canRead(String filePath) {
+ File file = new File(filePath);
+ return file.canRead();
+ }
+
public static String readAFile(String filePath) {
StringBuilder content = new StringBuilder();
try (FileInputStream inputStream = new FileInputStream(filePath);
diff --git a/app/src/main/res/drawable/highlight_mouse_cursor_24px.xml b/app/src/main/res/drawable/highlight_mouse_cursor_24px.xml
new file mode 100644
index 0000000..6c055b2
--- /dev/null
+++ b/app/src/main/res/drawable/highlight_mouse_cursor_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/xc_left_ptr.png b/app/src/main/res/drawable/xc_left_ptr.png
new file mode 100644
index 0000000..db2aada
Binary files /dev/null and b/app/src/main/res/drawable/xc_left_ptr.png differ
diff --git a/app/src/main/res/layout/activity_vnc.xml b/app/src/main/res/layout/activity_vnc.xml
index a46c797..a96ad3a 100644
--- a/app/src/main/res/layout/activity_vnc.xml
+++ b/app/src/main/res/layout/activity_vnc.xml
@@ -1,7 +1,7 @@
-
-
+
+
+
+
+
+
@@ -41,9 +52,9 @@
android:id="@+id/ln_nosignal"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="#E6000000"
android:gravity="center"
- android:orientation="vertical"
- android:background="#E6000000">
+ android:orientation="vertical">
+ android:textColor="@android:color/white"
+ android:textSize="20sp" />
+ android:textColor="@android:color/white" />
diff --git a/app/src/main/res/layout/dialog_change_removable_devices.xml b/app/src/main/res/layout/dialog_change_removable_devices.xml
index 3c98b2a..67b1160 100644
--- a/app/src/main/res/layout/dialog_change_removable_devices.xml
+++ b/app/src/main/res/layout/dialog_change_removable_devices.xml
@@ -219,6 +219,26 @@
android:text="@string/refresh"/>
+
+
+
+
+
3dfx is not available.
Refresh
We are very sorry about an incident that occurred and app crashed earlier.
+ Show virtual mouse
+ Hide virtual mouse
diff --git a/web/data/UpdateConfig.json b/web/data/UpdateConfig.json
index aa52dcf..e62aacf 100644
--- a/web/data/UpdateConfig.json
+++ b/web/data/UpdateConfig.json
@@ -5,11 +5,11 @@
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
"Message": "3.5.0
\n3dfx is back!",
"cancellable": true,
- "versionCodeBeta":"63",
- "versionNameBeta":"3.5.9",
- "versionNameBetas":"3.0.0,3.1.0,3.2.1,3.2.2,3.2.3,3.2.4,3.2.5,3.2.6,3.2.7,3.2.8,3.2.9,3.2.10,3.3.1,3.3.2,3.3.3,3.3.4,3.3.5,3.3.6,3.3.7,3.3.8,3.3.9,3.4.1,3.4.2,3.4.3,3.4.4,3.4.5,3.4.6,3.4.7,3.4.8,3.4.9,3.5.1,3.5.2,3.5.3,3.5.4,3.5.5,3.5.6,3.5.7,3.5.8,3.5.9",
+ "versionCodeBeta":"64",
+ "versionNameBeta":"3.6.0",
+ "versionNameBetas":"3.0.0,3.1.0,3.2.1,3.2.2,3.2.3,3.2.4,3.2.5,3.2.6,3.2.7,3.2.8,3.2.9,3.2.10,3.3.1,3.3.2,3.3.3,3.3.4,3.3.5,3.3.6,3.3.7,3.3.8,3.3.9,3.4.1,3.4.2,3.4.3,3.4.4,3.4.5,3.4.6,3.4.7,3.4.8,3.4.9,3.5.1,3.5.2,3.5.3,3.5.4,3.5.5,3.5.6,3.5.7,3.5.8,3.5.9,3.6.0",
"sizeBeta": "43 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
- "MessageBeta": "3.5.9
Bugs fixed.",
+ "MessageBeta": "3.6.0
Bugs fixed.",
"cancellableBeta": true
}