// Path: bVNC/src/com/iiordanov/runsoft/bVNC/input/RemotePointer.java
// public abstract class RemotePointer {
//     
//     /**
//      * Current and previous state of "mouse" buttons
//      */
//     protected int pointerMask = 0;
//     protected int prevPointerMask = 0;
// 
//     protected RemoteCanvas vncCanvas;
//     protected Context context;
//     protected Handler handler;
//     protected RfbConnectable rfb;
//     
//     /**
//      * Indicates where the mouse pointer is located.
//      */
//     public int mouseX, mouseY;
//     
//     public RemotePointer (RfbConnectable r, RemoteCanvas v, Handler h) {
//         rfb = r;
//         mouseX=rfb.framebufferWidth()/2;
//         mouseY=rfb.framebufferHeight()/2;
//         vncCanvas = v;
//         handler = h;
//         context = v.getContext();
//     }
//     
//     protected boolean shouldBeRightClick (KeyEvent e) {
//         boolean result = false;
//         int keyCode = e.getKeyCode();
//         
//         // If the camera button is pressed
//         if (keyCode == KeyEvent.KEYCODE_CAMERA) {
//             result = true;
//         // Or the back button is pressed
//         } else if (keyCode == KeyEvent.KEYCODE_BACK) {
//             // Determine SDK
//             boolean preGingerBread = android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD;
//             // Whether the source is a mouse (getSource() is not available pre-Gingerbread)
//             boolean mouseSource = (!preGingerBread && e.getSource() == InputDevice.SOURCE_MOUSE);
//             // Whether the device has a qwerty keyboard
//             boolean noQwertyKbd = (context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_QWERTY);
//             // Whether the device is pre-Gingerbread or the event came from the "hard buttons"
//             boolean fromVirtualHardKey = preGingerBread || (e.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0;
//             if (mouseSource || noQwertyKbd || fromVirtualHardKey) {
//                 result = true;
//             }
//         }
//         
//         return result;
//     }
//     
//     abstract public int getX();
//     abstract public int getY();
//     abstract public void setX(int newX);
//     abstract public void setY(int newY);
//     abstract public void warpMouse(int x, int y);
//     abstract public void mouseFollowPan();
//     abstract boolean handleHardwareButtons(int keyCode, KeyEvent evt, int combinedMetastate);
//     abstract public boolean processPointerEvent(MotionEvent evt, boolean downEvent, 
//                                        boolean useRightButton, boolean useMiddleButton, boolean useScrollButton, int direction);
//     abstract public boolean processPointerEvent(MotionEvent evt, boolean downEvent, 
//                                        boolean useRightButton, boolean useMiddleButton);
//     abstract public boolean processPointerEvent(MotionEvent evt, boolean downEvent, boolean useRightButton);
//     abstract public boolean processPointerEvent(int x, int y, int action, int modifiers, boolean mouseIsDown, boolean useRightButton);
//     
//     abstract public boolean processPointerEvent(int x, int y, int action, int modifiers, boolean mouseIsDown, boolean useRightButton,
//                                         boolean useMiddleButton, boolean useScrollButton, int direction);
// }


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.util.Log;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import com.iiordanov.runsoft.bVNC.input.RemotePointer;
            }
            pixels[offset++] = (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);

            /* Remaining pixels of a row */
            for (dx = 1; dx < w; dx++) {
                for (c = 0; c < 3; c++) {
                    est[c] = ((prevRow[dx * 3 + c] & 0xFF) + (pix[c] & 0xFF) -
                              (prevRow[(dx-1) * 3 + c] & 0xFF));
                    if (est[c] > 0xFF) {
                        est[c] = 0xFF;
                    } else if (est[c] < 0x00) {
                        est[c] = 0x00;
                    }
                    pix[c] = (byte)(est[c] + buf[(dy * w + dx) * 3 + c]);
                    thisRow[dx * 3 + c] = pix[c];
                }
                pixels[offset++] = (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
            }

            System.arraycopy(thisRow, 0, prevRow, 0, w * 3);
            offset += (bitmapData.bitmapwidth - w);
        }
    }

    /**
     * Handles cursor shape update (XCursor and RichCursor encodings).
     */
    synchronized void
    handleCursorShapeUpdate(RfbProto rfb, int encodingType, int hotX, int hotY, int w, int h) throws IOException {

// Path: bVNC/src/com/iiordanov/runsoft/bVNC/input/RemotePointer.java
// public abstract class RemotePointer {
//     
//     /**
//      * Current and previous state of "mouse" buttons
//      */
//     protected int pointerMask = 0;
//     protected int prevPointerMask = 0;
// 
//     protected RemoteCanvas vncCanvas;
//     protected Context context;
//     protected Handler handler;
//     protected RfbConnectable rfb;
//     
//     /**
//      * Indicates where the mouse pointer is located.
//      */
//     public int mouseX, mouseY;
//     
//     public RemotePointer (RfbConnectable r, RemoteCanvas v, Handler h) {
//         rfb = r;
//         mouseX=rfb.framebufferWidth()/2;
//         mouseY=rfb.framebufferHeight()/2;
//         vncCanvas = v;
//         handler = h;
//         context = v.getContext();
//     }
//     
//     protected boolean shouldBeRightClick (KeyEvent e) {
//         boolean result = false;
//         int keyCode = e.getKeyCode();
//         
//         // If the camera button is pressed
//         if (keyCode == KeyEvent.KEYCODE_CAMERA) {
//             result = true;
//         // Or the back button is pressed
//         } else if (keyCode == KeyEvent.KEYCODE_BACK) {
//             // Determine SDK
//             boolean preGingerBread = android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD;
//             // Whether the source is a mouse (getSource() is not available pre-Gingerbread)
//             boolean mouseSource = (!preGingerBread && e.getSource() == InputDevice.SOURCE_MOUSE);
//             // Whether the device has a qwerty keyboard
//             boolean noQwertyKbd = (context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_QWERTY);
//             // Whether the device is pre-Gingerbread or the event came from the "hard buttons"
//             boolean fromVirtualHardKey = preGingerBread || (e.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0;
//             if (mouseSource || noQwertyKbd || fromVirtualHardKey) {
//                 result = true;
//             }
//         }
//         
//         return result;
//     }
//     
//     abstract public int getX();
//     abstract public int getY();
//     abstract public void setX(int newX);
//     abstract public void setY(int newY);
//     abstract public void warpMouse(int x, int y);
//     abstract public void mouseFollowPan();
//     abstract boolean handleHardwareButtons(int keyCode, KeyEvent evt, int combinedMetastate);
//     abstract public boolean processPointerEvent(MotionEvent evt, boolean downEvent, 
//                                        boolean useRightButton, boolean useMiddleButton, boolean useScrollButton, int direction);
//     abstract public boolean processPointerEvent(MotionEvent evt, boolean downEvent, 
//                                        boolean useRightButton, boolean useMiddleButton);
//     abstract public boolean processPointerEvent(MotionEvent evt, boolean downEvent, boolean useRightButton);
//     abstract public boolean processPointerEvent(int x, int y, int action, int modifiers, boolean mouseIsDown, boolean useRightButton);
//     
//     abstract public boolean processPointerEvent(int x, int y, int action, int modifiers, boolean mouseIsDown, boolean useRightButton,
//                                         boolean useMiddleButton, boolean useScrollButton, int direction);
// }


// Path: bVNC/src/com/iiordanov/runsoft/bVNC/Decoder.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.util.Log;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import com.iiordanov.runsoft.bVNC.input.RemotePointer;

            }
            pixels[offset++] = (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);

            /* Remaining pixels of a row */
            for (dx = 1; dx < w; dx++) {
                for (c = 0; c < 3; c++) {
                    est[c] = ((prevRow[dx * 3 + c] & 0xFF) + (pix[c] & 0xFF) -
                              (prevRow[(dx-1) * 3 + c] & 0xFF));
                    if (est[c] > 0xFF) {
                        est[c] = 0xFF;
                    } else if (est[c] < 0x00) {
                        est[c] = 0x00;
                    }
                    pix[c] = (byte)(est[c] + buf[(dy * w + dx) * 3 + c]);
                    thisRow[dx * 3 + c] = pix[c];
                }
                pixels[offset++] = (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
            }

            System.arraycopy(thisRow, 0, prevRow, 0, w * 3);
            offset += (bitmapData.bitmapwidth - w);
        }
    }

    /**
     * Handles cursor shape update (XCursor and RichCursor encodings).
     */
    synchronized void
    handleCursorShapeUpdate(RfbProto rfb, int encodingType, int hotX, int hotY, int w, int h) throws IOException {

        RemotePointer p = vncCanvas.getPointer();