[[project @ 10] googlecode@antlersoft.com**20090109233228 Ignore-this: cb670cc9371fb52270b9d11afebecda4 Add ability to support large framebuffers by only pulling down what you need to display. Add new input mode-- use trackball to control mouse Refactor to make input modes clean Revamp VNC canvas menu and build from resources; sub-menus to select input modes and scaling Fix broken bell notification ] adddir ./androidVNC/res/menu addfile ./androidVNC/res/menu/vnccanvasactivitymenu.xml addfile ./androidVNC/src/android/androidVNC/AbstractBitmapData.java addfile ./androidVNC/src/android/androidVNC/AbstractInputHandler.java addfile ./androidVNC/src/android/androidVNC/CompactBitmapData.java addfile ./androidVNC/src/android/androidVNC/LargeBitmapData.java hunk ./androidVNC/res/menu/vnccanvasactivitymenu.xml 1 +
hunk ./androidVNC/res/values/strings.xml 4 ++ * 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 + * @param newy Position of right edge of visible part + */ + abstract void scrollChanged( int newx, int newy); + + /** + * Sync scroll -- called from network thread; copies scroll changes from UI to network state + */ + abstract void syncScroll(); + + /** + * Release resources + */ + void dispose() + { + if ( mbitmap!=null ) + mbitmap.recycle(); + memGraphics = null; + bitmapPixels = null; + } +} hunk ./androidVNC/src/android/androidVNC/AbstractInputHandler.java 1 +/** + * Copyright (C) 2009 Michael A. MacDonald + */ +package android.androidVNC; + +import android.view.KeyEvent; +import android.view.MotionEvent; + +/** + * The VncCanvasActivity has several different ways of handling input from the touchscreen, + * keyboard, buttons and trackball. These will be represented by different implementations + * of this interface. Putting the different modes in different classes + * will keep the logic clean. The relevant Activity callbacks in VncCanvasActivity + * are forwarded to methods in AbstractInputHandler. + *
+ * It is expected that the implementations will be contained within
+ * VncCanvasActivity, so they can do things like super.VncCanvasActivity.onXXX to invoke
+ * default behavior.
+ * @author Michael A. MacDonald
+ *
+ */
+interface AbstractInputHandler {
+ /**
+ * Note: Menu key code is handled before this is called
+ * @see android.app.Activity#onKeyDown(int keyCode, KeyEvent evt)
+ */
+ boolean onKeyDown(int keyCode, KeyEvent evt);
+ /**
+ * Note: Menu key code is handled before this is called
+ * @see android.app.Activity#onKeyUp(int keyCode, KeyEvent evt)
+ */
+ boolean onKeyUp(int keyCode, KeyEvent evt);
+ /* (non-Javadoc)
+ * @see android.app.Activity#onTrackballEvent(android.view.MotionEvent)
+ */
+ boolean onTrackballEvent( MotionEvent evt);
+ /* (non-Javadoc)
+ * @see android.app.Activity#onTrackballEvent(android.view.MotionEvent)
+ */
+ boolean onTouchEvent( MotionEvent evt);
+
+ /**
+ * Return a user-friendly description for this mode; it will be displayed in a toaster
+ * when changing modes.
+ * @return
+ */
+ CharSequence getHandlerDescription();
+}
hunk ./androidVNC/src/android/androidVNC/CompactBitmapData.java 1
+/**
+ * Copyright (C) 2009 Michael A. MacDonald
+ */
+package android.androidVNC;
+
+import java.io.IOException;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.widget.ImageView;
+
+/**
+ * @author Michael A. MacDonald
+ *
+ */
+class CompactBitmapData extends AbstractBitmapData {
+
+ CompactBitmapData(RfbProto rfb)
+ {
+ super(rfb);
+ bitmapwidth=framebufferwidth=rfb.framebufferWidth;
+ bitmapheight=framebufferheight=rfb.framebufferHeight;
+ mbitmap = Bitmap.createBitmap(rfb.framebufferWidth, rfb.framebufferHeight, Bitmap.Config.RGB_565);
+ memGraphics = new Canvas(mbitmap);
+ bitmapPixels = new int[rfb.framebufferWidth * rfb.framebufferHeight];
+ }
+
+ @Override
+ void writeFullUpdateRequest(boolean incremental) throws IOException {
+ rfb.writeFramebufferUpdateRequest(0, 0, framebufferwidth, framebufferheight, incremental);
+ }
+
+ @Override
+ boolean validDraw(int x, int y, int w, int h) {
+ return true;
+ }
+
+ @Override
+ int offset(int x, int y) {
+ return y * bitmapwidth + x;
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#updateBitmap(int, int, int, int)
+ */
+ @Override
+ void updateBitmap(int x, int y, int w, int h) {
+ mbitmap.setPixels(bitmapPixels, offset(x,y), bitmapwidth, x, y, w, h);
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#updateView(android.widget.ImageView)
+ */
+ @Override
+ void updateView(ImageView v) {
+ v.setImageBitmap(mbitmap);
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#copyRect(android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)
+ */
+ @Override
+ void copyRect(Rect src, Rect dest, Paint paint) {
+ memGraphics.drawBitmap(mbitmap, src, dest, paint);
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#drawRect(int, int, int, int, android.graphics.Paint)
+ */
+ @Override
+ void drawRect(int x, int y, int w, int h, Paint paint) {
+ memGraphics.drawRect(x, y, x + w, y + h, paint);
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#scrollChanged(int, int)
+ */
+ @Override
+ void scrollChanged(int newx, int newy) {
+ // Don't need to do anything here
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#syncScroll()
+ */
+ @Override
+ void syncScroll() {
+ // Don't need anything here either
+
+ }
+}
hunk ./androidVNC/src/android/androidVNC/LargeBitmapData.java 1
+/**
+ * Copyright (C) 2009 Michael A. MacDonald
+ */
+package android.androidVNC;
+
+import java.io.IOException;
+
+import android.graphics.drawable.DrawableContainer;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.widget.ImageView;
+
+/**
+ * @author Michael A. MacDonald
+ *
+ */
+class LargeBitmapData extends AbstractBitmapData {
+
+ int xoffset;
+ int yoffset;
+ int scrolledToX;
+ int scrolledToY;
+ int origwidth;
+ int origheight;
+ private LargeBitmapDrawable drawable;
+ private Rect invalidRect;
+ private Rect bitmapRect;
+
+ class LargeBitmapDrawable extends DrawableContainer
+ {
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.DrawableContainer#draw(android.graphics.Canvas)
+ */
+ @Override
+ public void draw(Canvas canvas) {
+ //android.util.Log.i("LBM", "Drawing "+xoffset+" "+yoffset);
+ int xoff, yoff;
+ synchronized ( LargeBitmapDrawable.this )
+ {
+ xoff=xoffset;
+ yoff=yoffset;
+ }
+ canvas.drawBitmap(mbitmap, xoff, yoff, new Paint());
+ }
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.DrawableContainer#getIntrinsicHeight()
+ */
+ @Override
+ public int getIntrinsicHeight() {
+ return framebufferheight;
+ }
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.DrawableContainer#getIntrinsicWidth()
+ */
+ @Override
+ public int getIntrinsicWidth() {
+ return framebufferwidth;
+ }
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.DrawableContainer#getOpacity()
+ */
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.DrawableContainer#isStateful()
+ */
+ @Override
+ public boolean isStateful() {
+ return false;
+ }
+ }
+
+ LargeBitmapData(RfbProto p, int displayWidth, int displayHeight)
+ {
+ super(p);
+ framebufferwidth=rfb.framebufferWidth;
+ framebufferheight=rfb.framebufferHeight;
+ origwidth=displayWidth;
+ origheight=displayHeight;
+ bitmapwidth=origwidth * 2;
+ bitmapheight=origheight * 2;
+ mbitmap = Bitmap.createBitmap(bitmapwidth, bitmapheight, Bitmap.Config.RGB_565);
+ memGraphics = new Canvas(mbitmap);
+ bitmapPixels = new int[bitmapwidth * bitmapheight];
+ drawable=new LargeBitmapDrawable();
+ invalidRect=new Rect();
+ bitmapRect=new Rect(0,0,bitmapwidth,bitmapheight);
+ }
+
+ void clearInvalid()
+ {
+ invalidRect.bottom=invalidRect.top=yoffset;
+ invalidRect.left=invalidRect.right=xoffset;
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#copyRect(android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)
+ */
+ @Override
+ void copyRect(Rect src, Rect dest, Paint paint) {
+ // TODO copy rect working?
+ throw new RuntimeException( "copyrect Not implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#drawRect(int, int, int, int, android.graphics.Paint)
+ */
+ @Override
+ void drawRect(int x, int y, int w, int h, Paint paint) {
+ x-=xoffset;
+ y-=yoffset;
+ memGraphics.drawRect(x, y, x+w, y+h, paint);
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#offset(int, int)
+ */
+ @Override
+ int offset(int x, int y) {
+ return (y - yoffset) * bitmapwidth + x - xoffset;
+ }
+
+ /* (non-Javadoc)
+ * @see android.androidVNC.AbstractBitmapData#scrollChanged(int, int)
+ */
+ @Override
+ synchronized void scrollChanged(int newx, int newy) {
+ //android.util.Log.i("LBM","scroll "+newx+" "+newy);
+ newx+=(framebufferwidth-origwidth)/2;
+ newy+=(framebufferheight-origheight)/2;
+ if ( ! ( newx-xoffset>=0 && newx-xoffset+origwidth<=bitmapwidth && newy-yoffset>=0 && newy-yoffset+origheight<=bitmapheight))
+ {
+ //android.util.Log.i("LBM","scroll "+newx+" "+newy);
+ int xindex, yindex;
+ xindex = -1;
+ yindex = -1;
+ if ( newx
+ * This class has no knowledge of the android-specific UI; it sees framebuffer updates
+ * and input events as defined in the RFB protocol.
+ *
+ */
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 314
- void writeVersionMsg() throws IOException {
+ synchronized void writeVersionMsg() throws IOException {
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 871
- void writeFramebufferUpdateRequest(int x, int y, int w, int h,
+ synchronized void writeFramebufferUpdateRequest(int x, int y, int w, int h,
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 896
- void writeSetPixelFormat(int bitsPerPixel, int depth, boolean bigEndian,
+ synchronized void writeSetPixelFormat(int bitsPerPixel, int depth, boolean bigEndian,
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 929
- void writeFixColourMapEntries(int firstColour, int nColours,
+ synchronized void writeFixColourMapEntries(int firstColour, int nColours,
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 958
- void writeSetEncodings(int[] encs, int len) throws IOException {
+ synchronized void writeSetEncodings(int[] encs, int len) throws IOException {
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 980
- void writeClientCutText(String text) throws IOException {
+ synchronized void writeClientCutText(String text) throws IOException {
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1006
- // Useful shortcuts for modifier masks.
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1007
- final static int CTRL_MASK = KeyEvent.META_SYM_ON;
- final static int SHIFT_MASK = KeyEvent.META_SHIFT_ON;
- final static int META_MASK = 0;
- final static int ALT_MASK = KeyEvent.META_ALT_ON;
-
-
- //
- // Write a pointer event message. We may need to send modifier key events
- // around it to set the correct modifier state.
- //
- int pointerMask = 0;
-
- void writePointerEvent(MotionEvent evt) throws IOException {
- int modifiers = evt.getMetaState();
-
- int mask2 = 2;
-// int mask3 = 4;
-
- if (evt.getAction() == MotionEvent.ACTION_DOWN) {
- if ((modifiers & KeyEvent.META_ALT_ON) != 0) {
- pointerMask = mask2;
- modifiers &= ~ALT_MASK;
-// } else if ((modifiers & KeyEvent.META_SYM_ON) != 0) {
-// pointerMask = mask3;
-// modifiers &= ~META_MASK;
- } else {
- pointerMask = 1;
- }
- } else if (evt.getAction() == MotionEvent.ACTION_UP) {
- pointerMask = 0;
- if ((modifiers & KeyEvent.META_ALT_ON) != 0) {
- modifiers &= ~ALT_MASK;
- }
-// else if ((modifiers & KeyEvent.META_SYM_ON) != 0) {
-// modifiers &= ~META_MASK;
-// }
- }
-
- eventBufLen = 0;
- writeModifierKeyEvents(modifiers);
+ /**
+ * Write a pointer event message. We may need to send modifier key events
+ * around it to set the correct modifier state.
+ * @param x
+ * @param y
+ * @param modifiers
+ * @param pointerMask
+ * @throws IOException
+ */
+ synchronized void writePointerEvent( int x, int y, int modifiers, int pointerMask) throws IOException
+ {
+ eventBufLen = 0;
+ writeModifierKeyEvents(modifiers);
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1021
- int x = (int) evt.getX();
- int y = (int) evt.getY();
+ eventBuf[eventBufLen++] = (byte) PointerEvent;
+ eventBuf[eventBufLen++] = (byte) pointerMask;
+ eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff);
+ eventBuf[eventBufLen++] = (byte) (x & 0xff);
+ eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff);
+ eventBuf[eventBufLen++] = (byte) (y & 0xff);
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1028
- if (x < 0) x = 0;
- if (y < 0) y = 0;
+ //
+ // Always release all modifiers after an "up" event
+ //
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1032
- eventBuf[eventBufLen++] = (byte) PointerEvent;
- eventBuf[eventBufLen++] = (byte) pointerMask;
- eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff);
- eventBuf[eventBufLen++] = (byte) (x & 0xff);
- eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff);
- eventBuf[eventBufLen++] = (byte) (y & 0xff);
+ if (pointerMask == 0) {
+ writeModifierKeyEvents(0);
+ }
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1036
- //
- // Always release all modifiers after an "up" event
- //
-
- if (pointerMask == 0) {
- writeModifierKeyEvents(0);
- }
-
- os.write(eventBuf, 0, eventBufLen);
+ os.write(eventBuf, 0, eventBufLen);
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1041
- final int CTRLALT = CTRL_MASK | ALT_MASK;
+ final int CTRLALT = VncCanvas.CTRL_MASK | VncCanvas.ALT_MASK;
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1067
- boolean writeKeyEvent(int keyCode, KeyEvent evt) throws IOException {
+ synchronized boolean writeKeyEvent(int keyCode, KeyEvent evt) throws IOException {
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1119
- if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK))
- writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0);
+ if ((newModifiers & VncCanvas.CTRL_MASK) != (oldModifiers & VncCanvas.CTRL_MASK))
+ writeKeyEvent(0xffe3, (newModifiers & VncCanvas.CTRL_MASK) != 0);
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1122
- if ((newModifiers & SHIFT_MASK) != (oldModifiers & SHIFT_MASK))
- writeKeyEvent(0xffe1, (newModifiers & SHIFT_MASK) != 0);
+ if ((newModifiers & VncCanvas.SHIFT_MASK) != (oldModifiers & VncCanvas.SHIFT_MASK))
+ writeKeyEvent(0xffe1, (newModifiers & VncCanvas.SHIFT_MASK) != 0);
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1125
- if ((newModifiers & META_MASK) != (oldModifiers & META_MASK))
- writeKeyEvent(0xffe7, (newModifiers & META_MASK) != 0);
+ if ((newModifiers & VncCanvas.META_MASK) != (oldModifiers & VncCanvas.META_MASK))
+ writeKeyEvent(0xffe7, (newModifiers & VncCanvas.META_MASK) != 0);
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1128
- if ((newModifiers & ALT_MASK) != (oldModifiers & ALT_MASK))
- writeKeyEvent(0xffe9, (newModifiers & ALT_MASK) != 0);
+ if ((newModifiers & VncCanvas.ALT_MASK) != (oldModifiers & VncCanvas.ALT_MASK))
+ writeKeyEvent(0xffe9, (newModifiers & VncCanvas.ALT_MASK) != 0);
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1229
- void writeOpenChat() throws Exception {
+ synchronized void writeOpenChat() throws Exception {
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1237
- void writeCloseChat() throws Exception {
+ synchronized void writeCloseChat() throws Exception {
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1245
- void writeFinishedChat() throws Exception {
+ synchronized void writeFinishedChat() throws Exception {
hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1282
- public void writeChatMessage(String msg) throws Exception {
+ public synchronized void writeChatMessage(String msg) throws Exception {
hunk ./androidVNC/src/android/androidVNC/Utils.java 6
-import android.app.Notification;
-import android.app.NotificationManager;
hunk ./androidVNC/src/android/androidVNC/Utils.java 42
- public static void notify(Context _context, String tickerText) {
- NotificationManager manager = (NotificationManager) _context.getSystemService(Context.NOTIFICATION_SERVICE);
- Notification n = new Notification();
- n.defaults = Notification.DEFAULT_ALL;
- n.tickerText = tickerText;
- n.icon = android.R.drawable.stat_sys_warning;
- manager.notify(nextNoticeID(), n);
- }
-
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 67
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 72
+import android.view.Display;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 80
+
+ // Available to activity
+ int mouseX, mouseY;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 105
- private Bitmap mbitmap;
- private int bitmapPixels[];
- private Canvas memGraphics;
+ AbstractBitmapData bitmapData;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 183
- // because we are ouf of memory. :(
+ // because we are out of memory. :(
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 260
- mbitmap = Bitmap.createBitmap(rfb.framebufferWidth, rfb.framebufferHeight, Bitmap.Config.RGB_565);
- memGraphics = new Canvas(mbitmap);
- bitmapPixels = new int[rfb.framebufferWidth * rfb.framebufferHeight];
+ Display display=((VncCanvasActivity)getContext()).getWindowManager().getDefaultDisplay();
+ int dx=display.getWidth();
+ int dy=display.getHeight();
+ int max=(dx>dy) ? dx : dy;
+ if ( rfb.framebufferWidth>max*2 || rfb.framebufferHeight>max*2)
+ bitmapData=new LargeBitmapData(rfb,dx,dy);
+ else
+ bitmapData=new CompactBitmapData(rfb);
+ mouseX=rfb.framebufferWidth/2;
+ mouseY=rfb.framebufferHeight/2;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 292
- public void processNormalProtocol(Context context, ProgressDialog pd) throws Exception {
+ public void processNormalProtocol(final Context context, ProgressDialog pd) throws Exception {
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 294
- rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, rfb.framebufferHeight, false);
+ bitmapData.writeFullUpdateRequest(false);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 300
-
+ bitmapData.syncScroll();
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 303
-
+ bitmapData.doneWaiting();
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 308
- @SuppressWarnings("unused")
- boolean cursorPosReceived = false;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 336
- // - softCursorMove(rx, ry);
- cursorPosReceived = true;
+ mouseX=rx;
+ mouseY=ry;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 386
- rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, rfb.framebufferHeight, !fullUpdateNeeded);
+ bitmapData.writeFullUpdateRequest(!fullUpdateNeeded);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 394
- Utils.notify(context, "VNC Beep!");
+ handler.post( new Runnable() {
+ public void run() { Toast.makeText( context, "VNC Beep", Toast.LENGTH_SHORT); }
+ });
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 428
- mbitmap.recycle();
- memGraphics = null;
- bitmapPixels = null;
+ if ( bitmapData!=null) bitmapData.dispose();
+ }
+
+ /**
+ * Warp the mouse to x, y in the RFB coordinates
+ * @param x
+ * @param y
+ */
+ void warpMouse(int x, int y)
+ {
+ mouseX=x;
+ mouseY=y;
+ try
+ {
+ rfb.writePointerEvent(x, y, 0, MOUSE_BUTTON_NONE);
+ }
+ catch ( IOException ioe)
+ {
+ Log.w(TAG,ioe);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see android.view.View#onScrollChanged(int, int, int, int)
+ */
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ super.onScrollChanged(l, t, oldl, oldt);
+ bitmapData.scrollChanged(l, t);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 464
- int firstoffset = y * rfb.framebufferWidth + x;
+ boolean valid=bitmapData.validDraw(x, y, w, h);
+ int[] pixels=bitmapData.bitmapPixels;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 472
-
- offset = dy * rfb.framebufferWidth + x;
+ if ( ! valid)
+ continue;
+ offset = bitmapData.offset(x, dy);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 476
- bitmapPixels[offset + i] = colorPalette[0xFF & buf[i]];
+ pixels[offset + i] = colorPalette[0xFF & buf[i]];
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 485
-
- offset = dy * rfb.framebufferWidth + x;
+ if ( ! valid)
+ continue;
+ offset = bitmapData.offset(x, dy);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 489
- bitmapPixels[offset + i] = // 0xFF << 24 |
+ pixels[offset + i] = // 0xFF << 24 |
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 494
+
+ if ( ! valid)
+ return;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 498
- mbitmap.setPixels(bitmapPixels, firstoffset, rfb.framebufferWidth, x, y, w, h);
+ bitmapData.updateBitmap( x, y, w, h);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 511
- setImageBitmap(mbitmap);
+ bitmapData.updateView(VncCanvas.this);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 514
-
+
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 519
-
+
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 568
+ // Useful shortcuts for modifier masks.
+
+ final static int CTRL_MASK = KeyEvent.META_SYM_ON;
+ final static int SHIFT_MASK = KeyEvent.META_SHIFT_ON;
+ final static int META_MASK = 0;
+ final static int ALT_MASK = KeyEvent.META_ALT_ON;
+
+ private static final int MOUSE_BUTTON_NONE = 0;
+ private static final int MOUSE_BUTTON_1 = 1;
+ private static final int MOUSE_BUTTON_2 = 2;
+ /**
+ * Current state of "mouse" buttons
+ * Alt meta means use second mouse button
+ * 0 = none
+ * 1 = default button
+ * 2 = second button
+ */
+ private int pointerMask = MOUSE_BUTTON_NONE;
+
+ /**
+ * Convert a motion event to a format suitable for sending over the wire
+ * @param evt motion event; x and y must already have been converted from screen coordinates
+ * to remote frame buffer coordinates. ALT meta state flag is interpreted as second mouse
+ * button
+ * @return true if event was actually sent
+ */
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 596
- synchronized (rfb) {
- try {
- rfb.writePointerEvent(evt);
- } catch (Exception e) {
- e.printStackTrace();
- }
- rfb.notify();
+ int modifiers = evt.getMetaState();
+
+ if (evt.getAction() == MotionEvent.ACTION_DOWN) {
+ if ((modifiers & KeyEvent.META_ALT_ON) != 0) {
+ pointerMask = MOUSE_BUTTON_2;
+ modifiers &= ~ALT_MASK;
+// } else if ((modifiers & KeyEvent.META_SYM_ON) != 0) {
+// pointerMask = mask3;
+// modifiers &= ~META_MASK;
+ } else {
+ pointerMask = MOUSE_BUTTON_1;
+ }
+ } else if (evt.getAction() == MotionEvent.ACTION_UP) {
+ pointerMask = 0;
+ if ((modifiers & KeyEvent.META_ALT_ON) != 0) {
+ modifiers &= ~ALT_MASK;
+ }
+// else if ((modifiers & KeyEvent.META_SYM_ON) != 0) {
+// modifiers &= ~META_MASK;
+// }
+ }
+ mouseX=(int)evt.getX();
+ mouseY=(int)evt.getY();
+ if ( mouseX<0) mouseX=0;
+ else if ( mouseX>=rfb.framebufferWidth) mouseX=rfb.framebufferWidth-1;
+ if ( mouseY<0) mouseY=0;
+ else if ( mouseY>=rfb.framebufferHeight) mouseY=rfb.framebufferHeight-1;
+ try {
+ rfb.writePointerEvent(mouseX,mouseY,modifiers,pointerMask);
+ } catch (Exception e) {
+ e.printStackTrace();
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 665
- return mbitmap.getWidth();
+ return bitmapData.framebufferwidth;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 669
- return mbitmap.getHeight();
+ return bitmapData.framebufferheight;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 673
- int xoffset = (mbitmap.getWidth() - getWidth()) / 2;
+ int xoffset = (bitmapData.framebufferwidth - getWidth()) / 2;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 678
- int yoffset = (mbitmap.getHeight() - getHeight()) / 2;
+ int yoffset = (bitmapData.framebufferheight - getHeight()) / 2;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 768
+ if ( ! bitmapData.validDraw(x, y, w, h))
+ return;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 787
- memGraphics.drawBitmap(mbitmap, new Rect(leftSrc, topSrc, rightSrc, bottomSrc), new Rect(leftDest, topDest, rightDest, bottomDest), paint);
+ bitmapData.copyRect(new Rect(leftSrc, topSrc, rightSrc, bottomSrc), new Rect(leftDest, topDest, rightDest, bottomDest), paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 797
-
+ boolean valid=bitmapData.validDraw(x, y, w, h);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 811
- memGraphics.drawRect(x, y, x + w, y + h, paint);
+ if ( valid)
+ bitmapData.drawRect(x, y, w, h, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 816
+ if ( ! valid)
+ return;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 835
- memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint);
+ bitmapData.drawRect(sx, sy, sw, sh, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 846
+ boolean valid=bitmapData.validDraw(x, y, w, h);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 860
- memGraphics.drawRect(x, y, x + w, y + h, paint);
+ if ( valid)
+ bitmapData.drawRect(x, y, w, h, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 865
+ if ( ! valid)
+ return;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 884
- memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint);
+ bitmapData.drawRect(sx, sy, sw, sh, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 934
+ boolean valid=bitmapData.validDraw(tx, ty, tw, th);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 948
- memGraphics.drawRect(tx, ty, tx + tw, ty + th, paint);
+ if ( valid )
+ bitmapData.drawRect(tx, ty, tw, th, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 986
- memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint);
+ if ( valid)
+ bitmapData.drawRect(sx, sy, sw, sh, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1001
- memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint);
+ if ( valid)
+ bitmapData.drawRect(sx, sy, sw, sh, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1018
- memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint);
+ if ( valid )
+ bitmapData.drawRect(sx, sy, sw, sh, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1046
+
+ boolean valid=bitmapData.validDraw(x, y, w, h);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1070
- memGraphics.drawRect(tx, ty, tx + tw, ty + th, paint);
+ if ( valid)
+ bitmapData.drawRect(tx, ty, tw, th, paint);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1088
- handleUpdatedZrleTile(tx, ty, tw, th);
+ if ( valid )
+ handleUpdatedZrleTile(tx, ty, tw, th);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1103
-
+ boolean valid = bitmapData.validDraw(x, y, w, h);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1117
+
+ int[] pixels=bitmapData.bitmapPixels;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1126
- offset = dy * rfb.framebufferWidth + x;
+ if ( ! valid)
+ continue;
+ offset = bitmapData.offset(x, dy);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1130
- bitmapPixels[offset + i] = colorPalette[0xFF & buf[i]];
+ pixels[offset + i] = colorPalette[0xFF & buf[i]];
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1139
- offset = dy * rfb.framebufferWidth + x;
+ if ( ! valid)
+ continue;
+ offset = bitmapData.offset(x, dy);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1143
- bitmapPixels[offset + i] = (buf[i * 4 + 2] & 0xFF) << 16 | (buf[i * 4 + 1] & 0xFF) << 8 | (buf[i * 4] & 0xFF);
+ pixels[offset + i] = (buf[i * 4 + 2] & 0xFF) << 16 | (buf[i * 4 + 1] & 0xFF) << 8 | (buf[i * 4] & 0xFF);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1147
- int firstoffset = y * rfb.framebufferWidth + x;
- mbitmap.setPixels(bitmapPixels, firstoffset, rfb.framebufferWidth, x, y, w, h);
+ if ( ! valid)
+ return;
+ bitmapData.updateBitmap(x, y, w, h);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1291
- int offsetDst = (y * rfb.framebufferWidth + x);
+ int offsetDst = bitmapData.offset(x, y);
+ int[] destPixels=bitmapData.bitmapPixels;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1294
- System.arraycopy(zrleTilePixels, offsetSrc, bitmapPixels, offsetDst, w);
+ System.arraycopy(zrleTilePixels, offsetSrc, destPixels, offsetDst, w);
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1296
- offsetDst += rfb.framebufferWidth;
+ offsetDst += bitmapData.bitmapwidth;
hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 1299
- int firstoffset = y * rfb.framebufferWidth + x;
- mbitmap.setPixels(bitmapPixels, firstoffset, rfb.framebufferWidth, x, y, w, h);
+ bitmapData.updateBitmap(x, y, w, h);
hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 30
+import android.view.Display;
hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 46
- private final static String TAG = "VncCanvasActivity";
hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 47
- private boolean panningMode = true;
+ private final static String TAG = "VncCanvasActivity";
hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 49
- private VncCanvas vncCanvas;
+ AbstractInputHandler inputHandler;
+
+ VncCanvas vncCanvas;
+
hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 54
- private final static int MENU_ITEM_INFO = Menu.FIRST;
- private final static int MENU_ITEM_SETTINGS = Menu.FIRST + 1;
- private final static int MENU_ITEM_ONE2ONE = Menu.FIRST + 2;
- private final static int MENU_ITEM_FITSCREEN = Menu.FIRST + 3;
- private final static int MENU_ITEM_DISCONNECT = Menu.FIRST + 4;
- private final static int MENU_ITEM_CTRLALTDEL = Menu.FIRST + 5;
+ private MenuItem[] inputModeMenuItems;
+ private AbstractInputHandler inputModeHandlers[];
+ private static final int inputModeIds[] = { R.id.itemInputFitToScreen, R.id.itemInputMouse, R.id.itemInputPan, R.id.itemInputTouchPanTrackballMouse };
hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 88
+
+ inputHandler=getInputHandlerById(R.id.itemInputFitToScreen);
hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 113
- super.onCreateOptionsMenu(menu);
- menu.add(Menu.NONE, MENU_ITEM_INFO, 0, "Info").setShortcut('1', 'i').setIcon(android.R.drawable.ic_menu_info_details);
- menu.add(Menu.NONE, MENU_ITEM_SETTINGS, 0, "Settings").setShortcut('2', 's').setIcon(android.R.drawable.ic_menu_preferences);
- menu.add(Menu.NONE, MENU_ITEM_ONE2ONE, 0, "1:1").setShortcut('3', 'r').setIcon(android.R.drawable.ic_menu_zoom);
- menu.add(Menu.NONE, MENU_ITEM_FITSCREEN, 0, "Fit-to-Screen").setShortcut('4', 'c').setIcon(android.R.drawable.ic_menu_zoom);
- menu.add(Menu.NONE, MENU_ITEM_CTRLALTDEL, 0, "Ctrl-Alt-Del").setShortcut('6', 'a').setIcon(android.R.drawable.ic_menu_share);
- menu.add(Menu.NONE, MENU_ITEM_DISCONNECT, 0, "Disconnect").setShortcut('5', 'd').setIcon(android.R.drawable.ic_menu_close_clear_cancel);
- return super.onCreateOptionsMenu(menu);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- // Hide the button for the current scaling mode
- boolean isFitToScreen = vncCanvas.getScaleType() == ScaleType.FIT_CENTER;
- menu.findItem(MENU_ITEM_ONE2ONE).setVisible(isFitToScreen);
- menu.findItem(MENU_ITEM_FITSCREEN).setVisible(!isFitToScreen);
+ getMenuInflater().inflate(R.menu.vnccanvasactivitymenu, menu);
+
+ Menu inputMenu = menu.findItem( R.id.itemInputMode).getSubMenu();
+
+ inputModeMenuItems = new MenuItem[inputModeIds.length];
+ for ( int i=0; i