I am not sure if anyone will know the answer to this unless they have worked with VNC before, or even this exact VNC Client app.
I am working with the source code of multi-VNC client for android (https://github.com/bk138/multivnc). My question is how to update the frame buffer of the VNC Client (in VNCCo.java) AS I SCROLL, not after I am done scrolling and my finger has left the screen (mouse button is toggled off).
The screen on my mobile device stops updating the Framebuffer when I put my finger down and start scrolling. I know that pointer inputs are constantly being updated as my finger scrolls on the screen because I can see the VNC SERVER scrolling as my finger scrolls on my Android device, but the Android device is not updating (it seems to freeze on the screen until my finger lifts up). I want to change this so that the framebuffer updates as my finger scrolls.
I've tried every hack I can think of including adding the "update framebuffer" section in "processNormalProtocol" (which I know is updating the frame constantly) to the section in VNCOutputThread that deals with pointer events, but with no luck. (THANK YOU SO MUCH FOR A POINTER IF ANY OF YOU HAVE AN IDEA)
processNormalProtocol: Everything in "while(maintainCoection)" (where the framebuffer is being updated) I've tried adding to where the pointer events are processed, which I show in the next section of code below.
VNCCo.java
private void processNormalProtocol(final Context context, final ProgressDialog pd, final Ruable setModes) throws Exception {
// initialize on login
try {
// initialize on login
Log.d(TAG, "Coection initialized");
bitmapData.writeFullUpdateRequest(false);
canvas.handler.post(setModes);
//
// main input loop
//
// Not entering the while loop when the finger is dragging
while (maintainCoection) {
bitmapData.syncScroll();
// This is where the code stops when we put a finger touch on screen
// Read message type from the server.
int msgType_2 = rfb.readServerMessageType();
//int msgType_2 = 0;
bitmapData.doneWaiting();
// Process the message depending on its type.
switch (msgType_2) {
case it.anddev.bradipao.janus.RfbProto.FramebufferUpdate:
rfb.readFramebufferUpdate();
for (int i = 0; i < rfb.updateNRects; i++) {
rfb.readFramebufferUpdateRectHdr();
int rx = rfb.updateRectX, ry = rfb.updateRectY;
int rw = rfb.updateRectW, rh = rfb.updateRectH;
if (rfb.updateRectEncoding == it.anddev.bradipao.janus.RfbProto.EncodingLastRect) {
Log.v(TAG, "rfb.EncodingLastRect");
break;
}
if (rfb.updateRectEncoding == it.anddev.bradipao.janus.RfbProto.EncodingNewFBSize) {
rfb.setFramebufferSize(rw, rh);
// - updateFramebufferSize();
Log.v(TAG, "rfb.EncodingNewFBSize");
break;
}
if (rfb.updateRectEncoding == it.anddev.bradipao.janus.RfbProto.EncodingXCursor || rfb.updateRectEncoding == it.anddev.bradipao.janus.RfbProto.EncodingRichCursor) {
// - handleCursorShapeUpdate(rfb.updateRectEncoding,
// rx,
// ry, rw, rh);
Log.v(TAG, "rfb.EncodingCursor");
continue;
}
if (rfb.updateRectEncoding == it.anddev.bradipao.janus.RfbProto.EncodingPointerPos) {
canvas.mouseX = rx;
canvas.mouseY = ry;
continue;
}
rfb.startTiming();
switch (rfb.updateRectEncoding) {
case it.anddev.bradipao.janus.RfbProto.EncodingRaw:
handleRawRect(rx, ry, rw, rh);
break;
case it.anddev.bradipao.janus.RfbProto.EncodingCopyRect:
handleCopyRect(rx, ry, rw, rh);
Log.v(TAG, "CopyRect is Buggy!");
break;
case it.anddev.bradipao.janus.RfbProto.EncodingRRE:
handleRRERect(rx, ry, rw, rh);
break;
case it.anddev.bradipao.janus.RfbProto.EncodingCoRRE:
handleCoRRERect(rx, ry, rw, rh);
break;
case it.anddev.bradipao.janus.RfbProto.EncodingHextile:
handleHextileRect(rx, ry, rw, rh);
break;
case it.anddev.bradipao.janus.RfbProto.EncodingZRLE:
// This case opens RFB readFully, which is linked to the timing of data scroll
System.out.println("WHEN FINGER IS NOT DOWN"+msgType_2);
handleZRLERect(rx, ry, rw, rh);
break;
case it.anddev.bradipao.janus.RfbProto.EncodingZlib:
handleZlibRect(rx, ry, rw, rh);
break;
default:
Log.e(TAG, "Unknown RFB rectangle encoding " + rfb.updateRectEncoding + " (0x" + Integer.toHexString(rfb.updateRectEncoding) + ")");
}
rfb.stopTiming();
// Hide progress dialog
canvas.handler.post(new Ruable() {
public void run() {
System.out.println("Public Void RUN is Called");
if(pd.isShowing())
pd.dismiss();
}
});
}
boolean fullUpdateNeeded = false;
if (pendingColorModel != null) {
setPixelFormat();
fullUpdateNeeded = true;
}
setEncodings(true);
if(framebufferUpdatesEnabled)
bitmapData.writeFullUpdateRequest(!fullUpdateNeeded);
break;
case it.anddev.bradipao.janus.RfbProto.SetColourMapEntries:
throw new Exception("Can't handle SetColourMapEntries message");
case it.anddev.bradipao.janus.RfbProto.Bell:
canvas.handler.post( new Ruable() {
public void run() { Toast.makeText(context, "VNC Beep", Toast.LENGTH_SHORT); }
});
break;
case it.anddev.bradipao.janus.RfbProto.ServerCutText:
serverCutText = rfb.readServerCutText();
Log.d(TAG, "got server cuttext: " + serverCutText);
break;
case it.anddev.bradipao.janus.RfbProto.TextChat:
// UltraVNC extension
String msg = rfb.readTextChatMsg();
if (msg != null && msg.length() > 0) {
// TODO implement chat interface
}
break;
default:
throw new Exception("Unknown RFB message type " + msgType_2);
}
}
}
catch (Exception e) {
throw e;
}
finally {
// unlock this lock, probably was held when IO exception occured
try {
bitmapDataPixelsLock.unlock();
}
catch(Exception e) {
}
Log.v(TAG, "Closing VNC Coection");
rfb.close();
System.gc();
}
}
sendPointerEvent(ev.pointer) is where I have tried adding the framebuffer update
private class VNCOutputThread extends Thread {
public void run() {
if(Utils.DEBUG()) Log.d(TAG, "OutputThread started!");
//
// main output loop
//
while (maintainCoection) {
// check input queue
OutputEvent ev;
while( (ev = outputEventQueue.poll()) != null ) {
if(ev.pointer != null)
sendPointerEvent(ev.pointer);
if(ev.key != null)
sendKeyEvent(ev.key);
if(ev.ffur != null)
try {
bitmapData.writeFullUpdateRequest(ev.ffur.incremental);
} catch (IOException e) {
e.printStackTrace();
}
if(ev.cuttext != null)
sendCutText(ev.cuttext.text);
}
// at this point, queue is empty, wait for input instead of hogging CPU
synchronized (outputEventQueue) {
try {
outputEventQueue.wait();
} catch (InterruptedException e) {
// go on
}
}
}
if(Utils.DEBUG()) Log.d(TAG, "OutputThread done!");
}
