import java.net.*;
public class RfbPlayer extends java.applet.Applet
- implements java.lang.Runnable, WindowListener {
+ implements java.lang.Runnable, WindowListener {
boolean inAnApplet = true;
boolean inSeparateFrame = false;
// main() is called when run as a java program from the command line.
// It simply runs the applet inside a newly-created frame.
//
-
public static void main(String[] argv) {
RfbPlayer p = new RfbPlayer();
p.mainArgs = argv;
//
// init()
//
-
public void init() {
readParameters();
if (inSeparateFrame) {
vncFrame = new Frame("RFB Session Player");
if (!inAnApplet) {
- vncFrame.add("Center", this);
+ vncFrame.add("Center", this);
}
vncContainer = vncFrame;
} else {
//
// run() - executed by the rfbThread to read RFB data.
//
-
public void run() {
gridbag = new GridBagLayout();
try {
if (inAnApplet) {
- url = new URL(getCodeBase(), sessionURL);
+ url = new URL(getCodeBase(), sessionURL);
} else {
- url = new URL(sessionURL);
+ url = new URL(sessionURL);
}
rfb = new RfbProto(url);
if (inSeparateFrame) {
- // Create a panel which itself is resizeable and can hold
- // non-resizeable VncCanvas component at the top left corner.
- Panel canvasPanel = new Panel();
- canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
- canvasPanel.add(vc);
-
- // Create a ScrollPane which will hold a panel with VncCanvas
- // inside.
- desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
- gbc.fill = GridBagConstraints.BOTH;
- gridbag.setConstraints(desktopScrollPane, gbc);
- desktopScrollPane.add(canvasPanel);
-
- // Finally, add our ScrollPane to the Frame window.
- vncFrame.add(desktopScrollPane);
- vncFrame.setTitle(rfb.desktopName);
- vncFrame.pack();
- vc.resizeDesktopFrame();
+ // Create a panel which itself is resizeable and can hold
+ // non-resizeable VncCanvas component at the top left corner.
+ Panel canvasPanel = new Panel();
+ canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+ canvasPanel.add(vc);
+
+ // Create a ScrollPane which will hold a panel with VncCanvas
+ // inside.
+ desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
+ gbc.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(desktopScrollPane, gbc);
+ desktopScrollPane.add(canvasPanel);
+
+ // Finally, add our ScrollPane to the Frame window.
+ vncFrame.add(desktopScrollPane);
+ vncFrame.setTitle(rfb.desktopName);
+ vncFrame.pack();
+ vc.resizeDesktopFrame();
} else {
- // Just add the VncCanvas component to the Applet.
- gridbag.setConstraints(vc, gbc);
- add(vc);
- validate();
+ // Just add the VncCanvas component to the Applet.
+ gridbag.setConstraints(vc, gbc);
+ add(vc);
+ validate();
}
while (true) {
- try {
- setPaused(!autoPlay);
- rfb.fbs.setSpeed(playbackSpeed);
- if (initialTimeOffset > rfb.fbs.getTimeOffset())
- setPos(initialTimeOffset); // don't seek backwards here
- vc.processNormalProtocol();
- } catch (EOFException e) {
- if (e.getMessage() != null && e.getMessage().equals("[REWIND]")) {
- // A special type of EOFException allowing us to seek backwards.
- initialTimeOffset = rfb.fbs.getSeekOffset();
- autoPlay = !rfb.fbs.isPaused();
- } else {
- // Return to the beginning after the playback is finished.
- initialTimeOffset = 0;
- autoPlay = false;
- }
+ try {
+ setPaused(!autoPlay);
+ rfb.fbs.setSpeed(playbackSpeed);
+ if (initialTimeOffset > rfb.fbs.getTimeOffset())
+ setPos(initialTimeOffset); // don't seek backwards here
+ vc.processNormalProtocol();
+ } catch (EOFException e) {
+ if (e.getMessage() != null && e.getMessage().equals("[REWIND]")) {
+ // A special type of EOFException allowing us to seek backwards.
+ initialTimeOffset = rfb.fbs.getSeekOffset();
+ autoPlay = !rfb.fbs.isPaused();
+ } else {
+ // Return to the beginning after the playback is finished.
+ initialTimeOffset = 0;
+ autoPlay = false;
+ }
rfb.newSession(url);
vc.updateFramebufferSize();
- }
+ }
}
} catch (FileNotFoundException e) {
e.printStackTrace();
fatalError(e.toString());
}
-
+
}
public void setPaused(boolean paused) {
rfb.fbs.setTimeOffset(pos);
}
-
public void updatePos() {
if (showControls)
buttonPanel.setPos(rfb.fbs.getTimeOffset());
// param_name/param_value pairs where the names and values correspond to
// those expected in the html applet tag source.
//
-
public void readParameters() {
sessionURL = readParameter("URL", true);
if (inAnApplet) {
str = readParameter("Open New Window", false);
if (str != null && str.equalsIgnoreCase("Yes"))
- inSeparateFrame = true;
+ inSeparateFrame = true;
}
// Fine tuning options.
if (inAnApplet) {
String s = getParameter(name);
if ((s == null) && required) {
- fatalError(name + " parameter not specified");
+ fatalError(name + " parameter not specified");
}
return s;
}
for (int i = 0; i < mainArgs.length; i += 2) {
if (mainArgs[i].equalsIgnoreCase(name)) {
- try {
- return mainArgs[i+1];
- } catch (Exception e) {
- if (required) {
- fatalError(name + " parameter not specified");
- }
- return null;
- }
+ try {
+ return mainArgs[i + 1];
+ } catch (Exception e) {
+ if (required) {
+ fatalError(name + " parameter not specified");
+ }
+ return null;
+ }
}
}
if (required) {
long result = defaultValue;
if (str != null) {
try {
- result = Long.parseLong(str);
- } catch (NumberFormatException e) { }
+ result = Long.parseLong(str);
+ } catch (NumberFormatException e) {
+ }
}
return result;
}
double result = defaultValue;
if (str != null) {
try {
- result = Double.valueOf(str).doubleValue();
- } catch (NumberFormatException e) { }
+ result = Double.valueOf(str).doubleValue();
+ } catch (NumberFormatException e) {
+ }
}
return result;
}
//
// fatalError() - print out a fatal error message.
//
-
public void fatalError(String str) {
System.out.println(str);
if (inAnApplet) {
vncContainer.removeAll();
if (rfb != null) {
- rfb = null;
+ rfb = null;
}
Label errLabel = new Label(str);
errLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30));
vncContainer.add(errLabel);
if (inSeparateFrame) {
- vncFrame.pack();
+ vncFrame.pack();
} else {
- validate();
+ validate();
}
Thread.currentThread().stop();
} else {
//
// This method is called before the applet is destroyed.
//
-
public void destroy() {
vncContainer.removeAll();
if (rfb != null) {
//
// Close application properly on window close event.
//
-
public void windowClosing(WindowEvent evt) {
vncContainer.removeAll();
if (rfb != null)
//
// Ignore window events we're not interested in.
//
+ public void windowActivated(WindowEvent evt) {
+ }
+
+ public void windowDeactivated(WindowEvent evt) {
+ }
+
+ public void windowOpened(WindowEvent evt) {
+ }
+
+ public void windowClosed(WindowEvent evt) {
+ }
+
+ public void windowIconified(WindowEvent evt) {
+ }
+
+ public void windowDeiconified(WindowEvent evt) {
+ }
- public void windowActivated (WindowEvent evt) {}
- public void windowDeactivated (WindowEvent evt) {}
- public void windowOpened(WindowEvent evt) {}
- public void windowClosed(WindowEvent evt) {}
- public void windowIconified(WindowEvent evt) {}
- public void windowDeiconified(WindowEvent evt) {}
}
class RfbProto {
final String versionMsg = "RFB 003.003\n";
- final static int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
- final static int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;
-
- final static int FramebufferUpdate = 0, SetColourMapEntries = 1, Bell = 2,
- ServerCutText = 3;
-
- final int SetPixelFormat = 0, FixColourMapEntries = 1, SetEncodings = 2,
- FramebufferUpdateRequest = 3, KeyboardEvent = 4, PointerEvent = 5,
- ClientCutText = 6;
-
- final static int
- EncodingRaw = 0,
- EncodingCopyRect = 1,
- EncodingRRE = 2,
- EncodingCoRRE = 4,
- EncodingHextile = 5,
- EncodingZlib = 6,
- EncodingTight = 7,
- EncodingCompressLevel0 = 0xFFFFFF00,
- EncodingQualityLevel0 = 0xFFFFFFE0,
- EncodingXCursor = 0xFFFFFF10,
- EncodingRichCursor = 0xFFFFFF11,
- EncodingLastRect = 0xFFFFFF20,
- EncodingNewFBSize = 0xFFFFFF21;
-
- final int HextileRaw = (1 << 0);
- final int HextileBackgroundSpecified = (1 << 1);
- final int HextileForegroundSpecified = (1 << 2);
- final int HextileAnySubrects = (1 << 3);
- final int HextileSubrectsColoured = (1 << 4);
-
- final static int TightExplicitFilter = 0x04;
- final static int TightFill = 0x08;
- final static int TightJpeg = 0x09;
- final static int TightMaxSubencoding = 0x09;
- final static int TightFilterCopy = 0x00;
- final static int TightFilterPalette = 0x01;
- final static int TightFilterGradient = 0x02;
-
- final static int TightMinToCompress = 12;
+ final static int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
+ final static int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;
+
+ final static int FramebufferUpdate = 0, SetColourMapEntries = 1, Bell = 2, ServerCutText =
+ 3;
+
+ final int SetPixelFormat = 0, FixColourMapEntries = 1, SetEncodings = 2, FramebufferUpdateRequest =
+ 3, KeyboardEvent = 4, PointerEvent = 5, ClientCutText = 6;
+
+ final static int EncodingRaw = 0, EncodingCopyRect = 1, EncodingRRE = 2, EncodingCoRRE =
+ 4, EncodingHextile = 5, EncodingZlib = 6, EncodingTight = 7, EncodingCompressLevel0 =
+ 0xFFFFFF00, EncodingQualityLevel0 = 0xFFFFFFE0, EncodingXCursor =
+ 0xFFFFFF10, EncodingRichCursor = 0xFFFFFF11, EncodingLastRect =
+ 0xFFFFFF20, EncodingNewFBSize = 0xFFFFFF21;
+
+ final int HextileRaw = (1 << 0);
+ final int HextileBackgroundSpecified = (1 << 1);
+ final int HextileForegroundSpecified = (1 << 2);
+ final int HextileAnySubrects = (1 << 3);
+ final int HextileSubrectsColoured = (1 << 4);
+
+ final static int TightExplicitFilter = 0x04;
+ final static int TightFill = 0x08;
+ final static int TightJpeg = 0x09;
+ final static int TightMaxSubencoding = 0x09;
+ final static int TightFilterCopy = 0x00;
+ final static int TightFilterPalette = 0x01;
+ final static int TightFilterGradient = 0x02;
+
+ final static int TightMinToCompress = 12;
FbsInputStream fbs;
DataInputStream is;
//
// Constructor.
//
-
RfbProto(URL url) throws Exception {
fbs = null;
newSession(url);
//
// Open new session URL.
//
-
public void newSession(URL url) throws Exception {
if (fbs != null)
fbs.close();
//
// Read server's protocol version message.
//
-
int serverMajor, serverMinor;
void readVersionMsg() throws IOException {
is.readFully(b);
- if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ')
- || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9')
- || (b[6] < '0') || (b[6] > '9') || (b[7] != '.')
- || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9')
- || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n'))
- {
+ if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') ||
+ (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') || (b[6] <
+ '0') || (b[6] > '9') || (b[7] != '.') || (b[8] < '0') || (b[8] > '9') ||
+ (b[9] < '0') || (b[9] > '9') || (b[10] < '0') || (b[10] > '9') ||
+ (b[11] != '\n')) {
throw new IOException("Incorrect protocol version");
}
//
// Find out the authentication scheme.
//
-
int readAuthScheme() throws IOException {
int authScheme = is.readInt();
//
// Read the server initialisation message
//
-
String desktopName;
int framebufferWidth, framebufferHeight;
int bitsPerPixel, depth;
//
// Set new framebuffer size
//
-
void setFramebufferSize(int width, int height) {
framebufferWidth = width;
framebufferHeight = height;
//
// Read the server message type
//
-
int readServerMessageType() throws IOException {
return is.readUnsignedByte();
}
//
// Read a FramebufferUpdate message
//
-
int updateNRects;
void readFramebufferUpdate() throws IOException {
}
// Read a FramebufferUpdate rectangle header
-
int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
void readFramebufferUpdateRectHdr() throws IOException {
updateRectEncoding = is.readInt();
if ((updateRectEncoding == EncodingLastRect) ||
- (updateRectEncoding == EncodingNewFBSize))
+ (updateRectEncoding == EncodingNewFBSize))
return;
if ((updateRectX + updateRectW > framebufferWidth) ||
- (updateRectY + updateRectH > framebufferHeight)) {
+ (updateRectY + updateRectH > framebufferHeight)) {
throw new IOException("Framebuffer update rectangle too large: " +
- updateRectW + "x" + updateRectH + " at (" +
- updateRectX + "," + updateRectY + ")");
+ updateRectW + "x" + updateRectH + " at (" +
+ updateRectX + "," + updateRectY + ")");
}
}
// Read CopyRect source X and Y.
-
int copyRectSrcX, copyRectSrcY;
void readCopyRect() throws IOException {
//
// Read a ServerCutText message
//
-
String readServerCutText() throws IOException {
byte[] pad = new byte[3];
is.readFully(pad);
//
// Read integer in compact representation
//
-
int readCompactLen() throws IOException {
int portion = is.readUnsignedByte();
int len = portion & 0x7F;
portion = is.readUnsignedByte();
len |= (portion & 0x7F) << 7;
if ((portion & 0x80) != 0) {
- portion = is.readUnsignedByte();
- len |= (portion & 0xFF) << 14;
+ portion = is.readUnsignedByte();
+ len |= (portion & 0xFF) << 14;
}
}
return len;
//
// VncCanvas is a subclass of Canvas which draws a VNC desktop on it.
//
-
class VncCanvas extends Canvas implements Observer {
RfbPlayer player;
//
// The constructor.
//
-
VncCanvas(RfbPlayer player) throws IOException {
this.player = player;
rfb = player.rfb;
//
// Callback methods to determine geometry of our Component.
//
-
public Dimension getPreferredSize() {
return new Dimension(rfb.framebufferWidth, rfb.framebufferHeight);
}
//
// All painting is performed here.
//
-
public void update(Graphics g) {
paint(g);
}
// Override the ImageObserver interface method to handle drawing of
// JPEG-encoded data.
//
-
public boolean imageUpdate(Image img, int infoflags,
- int x, int y, int width, int height) {
+ int x, int y, int width, int height) {
if ((infoflags & (ALLBITS | ABORT)) == 0) {
return true; // We need more image data.
} else {
// If the whole image is available, draw it now.
if ((infoflags & ALLBITS) != 0) {
- if (jpegRect != null) {
- synchronized(jpegRect) {
- memGraphics.drawImage(img, jpegRect.x, jpegRect.y, null);
- scheduleRepaint(jpegRect.x, jpegRect.y,
- jpegRect.width, jpegRect.height);
- jpegRect.notify();
- }
- }
+ if (jpegRect != null) {
+ synchronized(jpegRect) {
+ memGraphics.drawImage(img, jpegRect.x, jpegRect.y, null);
+ scheduleRepaint(jpegRect.x, jpegRect.y,
+ jpegRect.width, jpegRect.height);
+ jpegRect.notify();
+ }
+ }
}
return false; // All image data was processed.
}
memImage = player.createImage(fbWidth, fbHeight);
memGraphics = memImage.getGraphics();
} else if (memImage.getWidth(null) != fbWidth ||
- memImage.getHeight(null) != fbHeight) {
+ memImage.getHeight(null) != fbHeight) {
synchronized(memImage) {
- memImage = player.createImage(fbWidth, fbHeight);
- memGraphics = memImage.getGraphics();
+ memImage = player.createImage(fbWidth, fbHeight);
+ memGraphics = memImage.getGraphics();
}
}
// of geometry or pixel format.
pixels24 = new int[fbWidth * fbHeight];
pixelsSource =
- new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
+ new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
pixelsSource.setAnimated(true);
rawPixelsImage = createImage(pixelsSource);
// Update the size of desktop containers.
if (player.inSeparateFrame) {
if (player.desktopScrollPane != null)
- resizeDesktopFrame();
+ resizeDesktopFrame();
} else {
setSize(fbWidth, fbHeight);
}
// ScrollPane. -- const
Insets insets = player.desktopScrollPane.getInsets();
player.desktopScrollPane.setSize(rfb.framebufferWidth +
- 2 * Math.min(insets.left, insets.right),
- rfb.framebufferHeight +
- 2 * Math.min(insets.top, insets.bottom));
+ 2 * Math.min(insets.left, insets.right),
+ rfb.framebufferHeight +
+ 2 * Math.min(insets.top, insets.bottom));
player.vncFrame.pack();
// processNormalProtocol() - executed by the rfbThread to deal with
// the RFB data.
//
-
public void processNormalProtocol() throws Exception {
zlibInflater = new Inflater();
switch (msgType) {
case 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 == rfb.EncodingLastRect)
- break;
-
- if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) {
- rfb.setFramebufferSize(rfb.updateRectW, rfb.updateRectH);
- updateFramebufferSize();
- break;
- }
-
- if (rfb.updateRectEncoding == rfb.EncodingXCursor ||
- rfb.updateRectEncoding == rfb.EncodingRichCursor) {
- throw new Exception("Sorry, no support for" +
- " cursor shape updates yet");
- }
-
- switch (rfb.updateRectEncoding) {
- case RfbProto.EncodingRaw:
- handleRawRect(rx, ry, rw, rh);
- break;
- case RfbProto.EncodingCopyRect:
- handleCopyRect(rx, ry, rw, rh);
- break;
- case RfbProto.EncodingRRE:
- handleRRERect(rx, ry, rw, rh);
- break;
- case RfbProto.EncodingCoRRE:
- handleCoRRERect(rx, ry, rw, rh);
- break;
- case RfbProto.EncodingHextile:
- handleHextileRect(rx, ry, rw, rh);
- break;
- case RfbProto.EncodingZlib:
+ 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 == rfb.EncodingLastRect)
+ break;
+
+ if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) {
+ rfb.setFramebufferSize(rfb.updateRectW, rfb.updateRectH);
+ updateFramebufferSize();
+ break;
+ }
+
+ if (rfb.updateRectEncoding == rfb.EncodingXCursor ||
+ rfb.updateRectEncoding == rfb.EncodingRichCursor) {
+ throw new Exception("Sorry, no support for" +
+ " cursor shape updates yet");
+ }
+
+ switch (rfb.updateRectEncoding) {
+ case RfbProto.EncodingRaw:
+ handleRawRect(rx, ry, rw, rh);
+ break;
+ case RfbProto.EncodingCopyRect:
+ handleCopyRect(rx, ry, rw, rh);
+ break;
+ case RfbProto.EncodingRRE:
+ handleRRERect(rx, ry, rw, rh);
+ break;
+ case RfbProto.EncodingCoRRE:
+ handleCoRRERect(rx, ry, rw, rh);
+ break;
+ case RfbProto.EncodingHextile:
+ handleHextileRect(rx, ry, rw, rh);
+ break;
+ case RfbProto.EncodingZlib:
handleZlibRect(rx, ry, rw, rh);
- break;
- case RfbProto.EncodingTight:
- handleTightRect(rx, ry, rw, rh);
- break;
- default:
- throw new Exception("Unknown RFB rectangle encoding " +
- rfb.updateRectEncoding);
- }
- }
- break;
+ break;
+ case RfbProto.EncodingTight:
+ handleTightRect(rx, ry, rw, rh);
+ break;
+ default:
+ throw new Exception("Unknown RFB rectangle encoding " +
+ rfb.updateRectEncoding);
+ }
+ }
+ break;
case RfbProto.SetColourMapEntries:
- throw new Exception("Can't handle SetColourMapEntries message");
+ throw new Exception("Can't handle SetColourMapEntries message");
case RfbProto.Bell:
Toolkit.getDefaultToolkit().beep();
- break;
+ break;
case RfbProto.ServerCutText:
- String s = rfb.readServerCutText();
- break;
+ String s = rfb.readServerCutText();
+ break;
default:
- throw new Exception("Unknown RFB message type " + msgType);
+ throw new Exception("Unknown RFB message type " + msgType);
}
player.updatePos();
//
// Handle a raw rectangle.
//
-
void handleRawRect(int x, int y, int w, int h) throws IOException {
byte[] buf = new byte[w * 4];
rfb.is.readFully(buf);
offset = dy * rfb.framebufferWidth + x;
for (i = 0; i < w; i++) {
- pixels24[offset + i] =
- (buf[i * 4 + 2] & 0xFF) << 16 |
- (buf[i * 4 + 1] & 0xFF) << 8 |
- (buf[i * 4] & 0xFF);
+ pixels24[offset + i] =
+ (buf[i * 4 + 2] & 0xFF) << 16 |
+ (buf[i * 4 + 1] & 0xFF) << 8 |
+ (buf[i * 4] & 0xFF);
}
}
//
// Handle a CopyRect rectangle.
//
-
void handleCopyRect(int x, int y, int w, int h) throws IOException {
rfb.readCopyRect();
memGraphics.copyArea(rfb.copyRectSrcX, rfb.copyRectSrcY, w, h,
- x - rfb.copyRectSrcX, y - rfb.copyRectSrcY);
+ x - rfb.copyRectSrcX, y - rfb.copyRectSrcY);
scheduleRepaint(x, y, w, h);
}
//
// Handle an RRE-encoded rectangle.
//
-
void handleRRERect(int x, int y, int w, int h) throws IOException {
int nSubrects = rfb.is.readInt();
//
// Handle a CoRRE-encoded rectangle.
//
-
void handleCoRRERect(int x, int y, int w, int h) throws IOException {
int nSubrects = rfb.is.readInt();
//
// These colors should be kept between handleHextileSubrect() calls.
- private Color hextile_bg, hextile_fg;
+ private Color hextile_bg, hextile_fg;
void handleHextileRect(int x, int y, int w, int h) throws IOException {
for (int ty = y; ty < y + h; ty += 16) {
int th = 16;
if (y + h - ty < 16)
- th = y + h - ty;
+ th = y + h - ty;
for (int tx = x; tx < x + w; tx += 16) {
- int tw = 16;
- if (x + w - tx < 16)
- tw = x + w - tx;
+ int tw = 16;
+ if (x + w - tx < 16)
+ tw = x + w - tx;
- handleHextileSubrect(tx, ty, tw, th);
+ handleHextileSubrect(tx, ty, tw, th);
}
// Finished with a row of tiles, now let's show it.
//
// Handle one tile in the Hextile-encoded data.
//
-
void handleHextileSubrect(int tx, int ty, int tw, int th)
- throws IOException {
+ throws IOException {
byte[] buf = new byte[256 * 4];
if ((subencoding & rfb.HextileRaw) != 0) {
int count, offset;
for (int j = ty; j < ty + th; j++) {
- rfb.is.readFully(buf, 0, tw * 4);
- offset = j * rfb.framebufferWidth + tx;
- for (count = 0; count < tw; count++) {
- pixels24[offset + count] =
- (buf[count * 4 + 2] & 0xFF) << 16 |
- (buf[count * 4 + 1] & 0xFF) << 8 |
- (buf[count * 4] & 0xFF);
- }
+ rfb.is.readFully(buf, 0, tw * 4);
+ offset = j * rfb.framebufferWidth + tx;
+ for (count = 0; count < tw; count++) {
+ pixels24[offset + count] =
+ (buf[count * 4 + 2] & 0xFF) << 16 |
+ (buf[count * 4 + 1] & 0xFF) << 8 |
+ (buf[count * 4] & 0xFF);
+ }
}
handleUpdatedPixels(tx, ty, tw, th);
return;
int b1, b2, sx, sy, sw, sh;
if ((subencoding & rfb.HextileSubrectsColoured) != 0) {
for (int j = 0; j < nSubrects; j++) {
- rfb.is.readFully(buf, 0, 4);
- hextile_fg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
- b1 = rfb.is.readUnsignedByte();
- b2 = rfb.is.readUnsignedByte();
- sx = tx + (b1 >> 4);
- sy = ty + (b1 & 0xf);
- sw = (b2 >> 4) + 1;
- sh = (b2 & 0xf) + 1;
- memGraphics.setColor(hextile_fg);
- memGraphics.fillRect(sx, sy, sw, sh);
+ rfb.is.readFully(buf, 0, 4);
+ hextile_fg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF);
+ b1 = rfb.is.readUnsignedByte();
+ b2 = rfb.is.readUnsignedByte();
+ sx = tx + (b1 >> 4);
+ sy = ty + (b1 & 0xf);
+ sw = (b2 >> 4) + 1;
+ sh = (b2 & 0xf) + 1;
+ memGraphics.setColor(hextile_fg);
+ memGraphics.fillRect(sx, sy, sw, sh);
}
} else {
memGraphics.setColor(hextile_fg);
for (int j = 0; j < nSubrects; j++) {
- b1 = rfb.is.readUnsignedByte();
- b2 = rfb.is.readUnsignedByte();
- sx = tx + (b1 >> 4);
- sy = ty + (b1 & 0xf);
- sw = (b2 >> 4) + 1;
- sh = (b2 & 0xf) + 1;
- memGraphics.fillRect(sx, sy, sw, sh);
+ b1 = rfb.is.readUnsignedByte();
+ b2 = rfb.is.readUnsignedByte();
+ sx = tx + (b1 >> 4);
+ sy = ty + (b1 & 0xf);
+ sw = (b2 >> 4) + 1;
+ sh = (b2 & 0xf) + 1;
+ memGraphics.fillRect(sx, sy, sw, sh);
}
}
}
//
// Handle a Zlib-encoded rectangle.
//
-
void handleZlibRect(int x, int y, int w, int h) throws Exception {
int nBytes = rfb.is.readInt();
byte[] buf = new byte[w * 4];
int i, offset;
for (int dy = y; dy < y + h; dy++) {
- zlibInflater.inflate(buf);
- offset = dy * rfb.framebufferWidth + x;
- for (i = 0; i < w; i++) {
- pixels24[offset + i] =
- (buf[i * 4 + 2] & 0xFF) << 16 |
- (buf[i * 4 + 1] & 0xFF) << 8 |
- (buf[i * 4] & 0xFF);
- }
+ zlibInflater.inflate(buf);
+ offset = dy * rfb.framebufferWidth + x;
+ for (i = 0; i < w; i++) {
+ pixels24[offset + i] =
+ (buf[i * 4 + 2] & 0xFF) << 16 |
+ (buf[i * 4 + 1] & 0xFF) << 8 |
+ (buf[i * 4] & 0xFF);
+ }
}
- }
- catch (DataFormatException dfe) {
+ } catch (DataFormatException dfe) {
throw new Exception(dfe.toString());
}
//
// Handle a Tight-encoded rectangle.
//
-
void handleTightRect(int x, int y, int w, int h) throws Exception {
int comp_ctl = rfb.is.readUnsignedByte();
// Flush zlib streams if we are told by the server to do so.
for (int stream_id = 0; stream_id < 4; stream_id++) {
if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) {
- tightInflaters[stream_id] = null;
+ tightInflaters[stream_id] = null;
}
comp_ctl >>= 1;
}
// Let the imageUpdate() method do the actual drawing, here just
// wait until the image is fully loaded and drawn.
synchronized(jpegRect) {
- Toolkit.getDefaultToolkit().prepareImage(jpegImage, -1, -1, this);
- try {
- // Wait no longer than three seconds.
- jpegRect.wait(3000);
- } catch (InterruptedException e) {
- throw new Exception("Interrupted while decoding JPEG image");
- }
+ Toolkit.getDefaultToolkit().prepareImage(jpegImage, -1, -1, this);
+ try {
+ // Wait no longer than three seconds.
+ jpegRect.wait(3000);
+ } catch (InterruptedException e) {
+ throw new Exception("Interrupted while decoding JPEG image");
+ }
}
// Done, jpegRect is not needed any more.
if ((comp_ctl & rfb.TightExplicitFilter) != 0) {
int filter_id = rfb.is.readUnsignedByte();
if (filter_id == rfb.TightFilterPalette) {
- numColors = rfb.is.readUnsignedByte() + 1;
- byte[] buf = new byte[numColors * 3];
- rfb.is.readFully(buf);
- for (int i = 0; i < numColors; i++) {
- palette24[i] = ((buf[i * 3] & 0xFF) << 16 |
- (buf[i * 3 + 1] & 0xFF) << 8 |
- (buf[i * 3 + 2] & 0xFF));
- }
- if (numColors == 2)
- rowSize = (w + 7) / 8;
+ numColors = rfb.is.readUnsignedByte() + 1;
+ byte[] buf = new byte[numColors * 3];
+ rfb.is.readFully(buf);
+ for (int i = 0; i < numColors; i++) {
+ palette24[i] = ((buf[i * 3] & 0xFF) << 16 |
+ (buf[i * 3 + 1] & 0xFF) << 8 |
+ (buf[i * 3 + 2] & 0xFF));
+ }
+ if (numColors == 2)
+ rowSize = (w + 7) / 8;
} else if (filter_id == rfb.TightFilterGradient) {
- useGradient = true;
+ useGradient = true;
} else if (filter_id != rfb.TightFilterCopy) {
- throw new Exception("Incorrect tight filter id: " + filter_id);
+ throw new Exception("Incorrect tight filter id: " + filter_id);
}
}
if (numColors == 0)
if (dataSize < rfb.TightMinToCompress) {
// Data size is small - not compressed with zlib.
if (numColors != 0) {
- // Indexed colors.
- byte[] indexedData = new byte[dataSize];
- rfb.is.readFully(indexedData);
- if (numColors == 2) {
- // Two colors.
- decodeMonoData(x, y, w, h, indexedData, palette24);
- } else {
- // 3..255 colors.
- int i = 0;
- for (int dy = y; dy < y + h; dy++) {
- for (int dx = x; dx < x + w; dx++) {
- pixels24[dy * rfb.framebufferWidth + dx] =
- palette24[indexedData[i++] & 0xFF];
- }
- }
- }
+ // Indexed colors.
+ byte[] indexedData = new byte[dataSize];
+ rfb.is.readFully(indexedData);
+ if (numColors == 2) {
+ // Two colors.
+ decodeMonoData(x, y, w, h, indexedData, palette24);
+ } else {
+ // 3..255 colors.
+ int i = 0;
+ for (int dy = y; dy < y + h; dy++) {
+ for (int dx = x; dx < x + w; dx++) {
+ pixels24[dy * rfb.framebufferWidth + dx] =
+ palette24[indexedData[i++] & 0xFF];
+ }
+ }
+ }
} else if (useGradient) {
- // "Gradient"-processed data
- byte[] buf = new byte[w * h * 3];
- rfb.is.readFully(buf);
- decodeGradientData(x, y, w, h, buf);
+ // "Gradient"-processed data
+ byte[] buf = new byte[w * h * 3];
+ rfb.is.readFully(buf);
+ decodeGradientData(x, y, w, h, buf);
} else {
- // Raw truecolor data.
- byte[] buf = new byte[w * 3];
- int i, offset;
- for (int dy = y; dy < y + h; dy++) {
- rfb.is.readFully(buf);
- offset = dy * rfb.framebufferWidth + x;
- for (i = 0; i < w; i++) {
- pixels24[offset + i] =
- (buf[i * 3] & 0xFF) << 16 |
- (buf[i * 3 + 1] & 0xFF) << 8 |
- (buf[i * 3 + 2] & 0xFF);
- }
- }
+ // Raw truecolor data.
+ byte[] buf = new byte[w * 3];
+ int i, offset;
+ for (int dy = y; dy < y + h; dy++) {
+ rfb.is.readFully(buf);
+ offset = dy * rfb.framebufferWidth + x;
+ for (i = 0; i < w; i++) {
+ pixels24[offset + i] =
+ (buf[i * 3] & 0xFF) << 16 |
+ (buf[i * 3 + 1] & 0xFF) << 8 |
+ (buf[i * 3 + 2] & 0xFF);
+ }
+ }
}
} else {
// Data was compressed with zlib.
rfb.is.readFully(zlibData);
int stream_id = comp_ctl & 0x03;
if (tightInflaters[stream_id] == null) {
- tightInflaters[stream_id] = new Inflater();
+ tightInflaters[stream_id] = new Inflater();
}
Inflater myInflater = tightInflaters[stream_id];
myInflater.setInput(zlibData);
try {
- if (numColors != 0) {
- // Indexed colors.
- byte[] indexedData = new byte[dataSize];
- myInflater.inflate(indexedData);
- if (numColors == 2) {
- // Two colors.
- decodeMonoData(x, y, w, h, indexedData, palette24);
- } else {
- // More than two colors.
- int i = 0;
- for (int dy = y; dy < y + h; dy++) {
- for (int dx = x; dx < x + w; dx++) {
- pixels24[dy * rfb.framebufferWidth + dx] =
- palette24[indexedData[i++] & 0xFF];
- }
- }
- }
- } else if (useGradient) {
- // Compressed "Gradient"-filtered data.
- byte[] buf = new byte[w * h * 3];
- myInflater.inflate(buf);
- decodeGradientData(x, y, w, h, buf);
- } else {
- // Compressed truecolor data.
- byte[] buf = new byte[w * 3];
- int i, offset;
- for (int dy = y; dy < y + h; dy++) {
- myInflater.inflate(buf);
- offset = dy * rfb.framebufferWidth + x;
- for (i = 0; i < w; i++) {
- pixels24[offset + i] =
- (buf[i * 3] & 0xFF) << 16 |
- (buf[i * 3 + 1] & 0xFF) << 8 |
- (buf[i * 3 + 2] & 0xFF);
- }
- }
- }
- }
- catch(DataFormatException dfe) {
- throw new Exception(dfe.toString());
+ if (numColors != 0) {
+ // Indexed colors.
+ byte[] indexedData = new byte[dataSize];
+ myInflater.inflate(indexedData);
+ if (numColors == 2) {
+ // Two colors.
+ decodeMonoData(x, y, w, h, indexedData, palette24);
+ } else {
+ // More than two colors.
+ int i = 0;
+ for (int dy = y; dy < y + h; dy++) {
+ for (int dx = x; dx < x + w; dx++) {
+ pixels24[dy * rfb.framebufferWidth + dx] =
+ palette24[indexedData[i++] & 0xFF];
+ }
+ }
+ }
+ } else if (useGradient) {
+ // Compressed "Gradient"-filtered data.
+ byte[] buf = new byte[w * h * 3];
+ myInflater.inflate(buf);
+ decodeGradientData(x, y, w, h, buf);
+ } else {
+ // Compressed truecolor data.
+ byte[] buf = new byte[w * 3];
+ int i, offset;
+ for (int dy = y; dy < y + h; dy++) {
+ myInflater.inflate(buf);
+ offset = dy * rfb.framebufferWidth + x;
+ for (i = 0; i < w; i++) {
+ pixels24[offset + i] =
+ (buf[i * 3] & 0xFF) << 16 |
+ (buf[i * 3 + 1] & 0xFF) << 8 |
+ (buf[i * 3 + 2] & 0xFF);
+ }
+ }
+ }
+ } catch (DataFormatException dfe) {
+ throw new Exception(dfe.toString());
}
}
//
// Decode 1bpp-encoded bi-color rectangle.
//
-
void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette) {
int dx, dy, n;
for (dy = 0; dy < h; dy++) {
for (dx = 0; dx < w / 8; dx++) {
- b = src[dy*rowBytes+dx];
- for (n = 7; n >= 0; n--)
- pixels24[i++] = palette[b >> n & 1];
+ b = src[dy * rowBytes + dx];
+ for (n = 7; n >= 0; n--)
+ pixels24[i++] = palette[b >> n & 1];
}
for (n = 7; n >= 8 - w % 8; n--) {
- pixels24[i++] = palette[src[dy*rowBytes+dx] >> n & 1];
+ pixels24[i++] = palette[src[dy * rowBytes + dx] >> n & 1];
}
i += (rfb.framebufferWidth - w);
}
//
// Decode data processed with the "Gradient" filter.
//
-
- void decodeGradientData (int x, int y, int w, int h, byte[] buf) {
+ void decodeGradientData(int x, int y, int w, int h, byte[] buf) {
int dx, dy, c;
byte[] prevRow = new byte[w * 3];
/* First pixel in a row */
for (c = 0; c < 3; c++) {
- pix[c] = (byte)(prevRow[c] + buf[dy * w * 3 + c]);
- thisRow[c] = pix[c];
+ pix[c] = (byte)(prevRow[c] + buf[dy * w * 3 + c]);
+ thisRow[c] = pix[c];
}
pixels24[offset++] =
- (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
+ (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];
- }
- pixels24[offset++] =
- (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
+ 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];
+ }
+ pixels24[offset++] =
+ (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF);
}
System.arraycopy(thisRow, 0, prevRow, 0, w * 3);
//
// Display newly updated area of pixels.
//
-
void handleUpdatedPixels(int x, int y, int w, int h) {
// Draw updated pixels of the off-screen image.
//
// Tell JVM to repaint specified desktop area.
//
-
void scheduleRepaint(int x, int y, int w, int h) {
if (rfb.fbs.isSeeking()) {
// Do nothing, and remember we are seeking.
seekMode = true;
} else {
if (seekMode) {
- // Immediate repaint of the whole desktop after seeking.
- repaint();
+ // Immediate repaint of the whole desktop after seeking.
+ repaint();
} else {
- // Usual incremental repaint.
- repaint(player.deferScreenUpdates, x, y, w, h);
+ // Usual incremental repaint.
+ repaint(player.deferScreenUpdates, x, y, w, h);
}
seekMode = false;
}
// switching to the `paused' mode. In such cases we want to repaint
// our desktop if we were seeking.
//
-
public void update(Observable o, Object arg) {
// Immediate repaint of the whole desktop after seeking.
repaint();