diff options
author | wimba.com <wimba.com@3789f03b-4d11-0410-bbf8-ca57d06f2519> | 2005-02-11 23:06:24 +0000 |
---|---|---|
committer | wimba.com <wimba.com@3789f03b-4d11-0410-bbf8-ca57d06f2519> | 2005-02-11 23:06:24 +0000 |
commit | d2ddbc73a632e8e826f9e9fc26c886b09d268f6e (patch) | |
tree | fd53020d86854705231070d552a38d945f8be1b6 /java/src/com/tightvnc/rfbplayer | |
parent | e8e1910bc39402d9547324a5d439d11a8febb2e2 (diff) | |
download | tigervnc-d2ddbc73a632e8e826f9e9fc26c886b09d268f6e.tar.gz tigervnc-d2ddbc73a632e8e826f9e9fc26c886b09d268f6e.zip |
Fix player so that the canvas properly sizes when frame buffer changes size. Also, get rid of some ghost cursors that were getting left behind. Did a lot to bring the VncCanvas more in line with that of the viewer.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2544 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'java/src/com/tightvnc/rfbplayer')
-rw-r--r-- | java/src/com/tightvnc/rfbplayer/VncCanvas.java | 607 |
1 files changed, 385 insertions, 222 deletions
diff --git a/java/src/com/tightvnc/rfbplayer/VncCanvas.java b/java/src/com/tightvnc/rfbplayer/VncCanvas.java index 9cc98a24..f27a3500 100644 --- a/java/src/com/tightvnc/rfbplayer/VncCanvas.java +++ b/java/src/com/tightvnc/rfbplayer/VncCanvas.java @@ -1,5 +1,6 @@ // -// Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved. +// Copyright (C) 2004 Horizon Wimba. All Rights Reserved. +// Copyright (C) 2001-2003 HorizonLive.com, Inc. All Rights Reserved. // Copyright (C) 2001 Constantin Kaplinsky. All Rights Reserved. // Copyright (C) 2000 Tridia Corporation. All Rights Reserved. // Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. @@ -34,17 +35,23 @@ import java.util.zip.*; // // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. // -class VncCanvas extends Canvas implements Observer { +class VncCanvas extends Component + implements Observer { - RfbPlayer player; + RfbPlayer appClass; RfbProto rfb; - ColorModel cm24; + ColorModel cm8, cm24; + int bytesPixel; Image memImage; Graphics memGraphics; + Image offImage; + Graphics offGraphics; + Image rawPixelsImage; MemoryImageSource pixelsSource; + byte[] pixels8; int[] pixels24; // Zlib encoder's data. @@ -77,22 +84,32 @@ class VncCanvas extends Canvas implements Observer { // The constructor. // VncCanvas(RfbPlayer player) throws IOException { - this.player = player; - rfb = player.rfb; + this.appClass = player; + rfb = appClass.rfb; seekMode = false; cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); - updateFramebufferSize(); + setPixelFormat(); + // Style canvas. setBackground(Color.white); + + } + + // + // Override the 1.4 focus traversal keys accesor to allow + // our keyListener to receive tab presses. + // + public boolean getFocusTraversalKeysEnabled() { + return false; } // // Callback methods to determine geometry of our Component. // public Dimension getPreferredSize() { - Dimension d = player.desktopScrollPane.getViewportSize(); + Dimension d = appClass.desktopScrollPane.getViewportSize(); Dimension sz = new Dimension(rfb.framebufferWidth, rfb.framebufferHeight); if (d.width > sz.width) sz.width = d.width; @@ -111,7 +128,7 @@ class VncCanvas extends Canvas implements Observer { Point getImageOrigin() { int x = 0, y = 0; - Dimension d = player.desktopScrollPane.getViewportSize(); + Dimension d = appClass.desktopScrollPane.getViewportSize(); if (rfb.framebufferWidth < d.width) x = d.width / 2 - rfb.framebufferWidth / 2; if (rfb.framebufferHeight < d.height) @@ -126,41 +143,66 @@ class VncCanvas extends Canvas implements Observer { paint(g); } - public synchronized void paint(Graphics g) { + public void paint(Graphics g) { Point o = getImageOrigin(); Dimension d = getPreferredSize(); + + // create new offscreen + if (offImage == null) { + offImage = createImage(d.width, d.height); + offGraphics = offImage.getGraphics(); + } else if (offImage.getWidth(null) != d.width || + offImage.getHeight(null) != d.height) { + offGraphics.dispose(); + offGraphics = null; + offImage.flush(); + offImage = null; + offImage = createImage(d.width, d.height); + offGraphics = offImage.getGraphics(); + } + synchronized(memImage) { - g.drawImage(memImage, o.x, o.y, null); - - // fill in background - if (o.x > 0 || o.y > 0) { - // left, right, top, bottom - Color c = g.getColor(); - g.setColor(Color.white); - g.fillRect(0, 0, o.x, d.height); - g.fillRect(o.x + rfb.framebufferWidth, 0, d.width - (o.x + - rfb.framebufferWidth), d.height); - g.fillRect(o.x, 0, rfb.framebufferWidth, o.y); - g.fillRect(o.x, o.y + rfb.framebufferHeight, rfb.framebufferWidth, - d.height - (o.y + rfb.framebufferHeight)); - g.setColor(DARK_GRAY); - g.drawRect(o.x - 1, o.y - 1, rfb.framebufferWidth + 1, - rfb.framebufferHeight + 1); - g.setColor(c); - } + offGraphics.drawImage(memImage, o.x, o.y, null); + } + + // fill in background + if (o.x > 0 || o.y > 0) { + // left, right, top, bottom + Color c = g.getColor(); + offGraphics.setColor(Color.white); + offGraphics.fillRect(0, 0, o.x, d.height); + offGraphics.fillRect(o.x + rfb.framebufferWidth, 0, d.width - (o.x + + rfb.framebufferWidth), d.height); + offGraphics.fillRect(o.x, 0, rfb.framebufferWidth, o.y); + offGraphics.fillRect(o.x, o.y + rfb.framebufferHeight, + rfb.framebufferWidth, d.height - (o.y + + rfb.framebufferHeight)); + offGraphics.setColor(c); } + + // draw border + Color oc = g.getColor(); + offGraphics.setColor(DARK_GRAY); + offGraphics.drawRect(o.x - 1, o.y - 1, rfb.framebufferWidth + 1, + rfb.framebufferHeight + 1); + offGraphics.setColor(oc); + + // draw cursor if (showSoftCursor) { int x0 = cursorX - hotX, y0 = cursorY - hotY; x0 += o.x; y0 += o.y; Rectangle r = new Rectangle(x0, y0, cursorWidth, cursorHeight); if (r.intersects(g.getClipBounds())) { - Rectangle c = g.getClipBounds(); - g.setClip(o.x, o.y, rfb.framebufferWidth, rfb.framebufferHeight); - g.drawImage(softCursor, x0, y0, null); - g.setClip(c.x, c.y, c.width, c.height); + offGraphics.setClip(o.x, o.y, rfb.framebufferWidth, + rfb.framebufferHeight); + offGraphics.drawImage(softCursor, x0, y0, null); + offGraphics.setClip(null); } } + + // draw offscreen + g.drawImage(offImage, 0, 0, null); } // @@ -187,6 +229,11 @@ class VncCanvas extends Canvas implements Observer { } } + private void setPixelFormat() throws IOException { + bytesPixel = 4; + updateFramebufferSize(); + } + void updateFramebufferSize() { // Useful shortcuts. @@ -197,39 +244,50 @@ class VncCanvas extends Canvas implements Observer { // its geometry should be changed. It's not necessary to replace // existing image if only pixel format should be changed. if (memImage == null) { - memImage = player.createImage(fbWidth, fbHeight); + memImage = appClass.createImage(fbWidth, fbHeight); memGraphics = memImage.getGraphics(); } else if (memImage.getWidth(null) != fbWidth || memImage.getHeight(null) != fbHeight) { synchronized(memImage) { - memImage = player.createImage(fbWidth, fbHeight); + memImage = appClass.createImage(fbWidth, fbHeight); memGraphics = memImage.getGraphics(); } } // Images with raw pixels should be re-allocated on every change // of geometry or pixel format. - pixels24 = new int[fbWidth * fbHeight]; - pixelsSource = - new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth); + if (bytesPixel == 1) { + pixels24 = null; + pixels8 = new byte[fbWidth * fbHeight]; + + pixelsSource = + new MemoryImageSource(fbWidth, fbHeight, cm8, pixels8, 0, fbWidth); + } else { + pixels8 = null; + pixels24 = new int[fbWidth * fbHeight]; + + pixelsSource = + new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth); + } pixelsSource.setAnimated(true); rawPixelsImage = createImage(pixelsSource); // Update the size of desktop containers unless seeking - if (!seekMode) { - if (player.inSeparateFrame) { - if (player.desktopScrollPane != null) - resizeDesktopFrame(); + if (!seekMode && appClass.desktopScrollPane != null) { + if (appClass.inSeparateFrame) { + resizeDesktopFrame(); } else { - setSize(fbWidth, fbHeight); + resizeEmbeddedApplet(); + // if the framebuffer shrunk, need to clear and repaint + appClass.desktopScrollPane.clearAndRepaint(); } } } void resizeDesktopFrame() { // determine screen size - Dimension screenSize = player.vncFrame.getToolkit().getScreenSize(); - Dimension scrollSize = player.desktopScrollPane.getSize(); + Dimension screenSize = appClass.vncFrame.getToolkit().getScreenSize(); + Dimension scrollSize = appClass.desktopScrollPane.getSize(); // Reduce Screen Size by 30 pixels in each direction; // This is a (poor) attempt to account for @@ -242,7 +300,7 @@ class VncCanvas extends Canvas implements Observer { // Further reduce the screen size to account for the // scroll pane's insets. - Insets insets = player.desktopScrollPane.getInsets(); + Insets insets = appClass.desktopScrollPane.getInsets(); screenSize.height -= insets.top + insets.bottom; screenSize.width -= insets.left + insets.right; @@ -260,24 +318,25 @@ class VncCanvas extends Canvas implements Observer { h = screenSize.height; needResize = true; } - if (needResize) - player.desktopScrollPane.setSize(w, h); + if (needResize) { + appClass.desktopScrollPane.setSize(w, h); + appClass.desktopScrollPane.validate(); + } // size the canvas setSize(getPreferredSize()); - player.vncFrame.pack(); + appClass.vncFrame.pack(); } void resizeEmbeddedApplet() { // resize scroll pane if necessary - Dimension scrollSize = player.desktopScrollPane.getSize(); - if (scrollSize.width != player.dispW || - scrollSize.height != player.dispH) { - player.desktopScrollPane.setSize(player.dispW, player.dispH); + Dimension scrollSize = appClass.desktopScrollPane.getSize(); + if (scrollSize.width != appClass.dispW || + scrollSize.height != appClass.dispH) { + appClass.desktopScrollPane.setSize(appClass.dispW, appClass.dispH); } - - player.desktopScrollPane.validate(); + appClass.desktopScrollPane.validate(); // size the canvas setSize(getPreferredSize()); } @@ -292,27 +351,29 @@ class VncCanvas extends Canvas implements Observer { tightInflaters = new Inflater[4]; // Show current time position in the control panel. - player.updatePos(); + appClass.updatePos(); // Tell our FbsInputStream object to notify us when it goes to the // `paused' mode. rfb.fbs.addObserver(this); - // Main dispatch loop. + // + // main dispatch loop + // while (true) { int msgType = rfb.readServerMessageType(); + // Process the message depending on its type. switch (msgType) { case RfbProto.FramebufferUpdate: rfb.readFramebufferUpdate(); + boolean cursorPosReceived = false; + for (int i = 0; i < rfb.updateNRects; i++) { rfb.readFramebufferUpdateRectHdr(); - - boolean cursorPosReceived = false; - int rx = rfb.updateRectX, ry = rfb.updateRectY; int rw = rfb.updateRectW, rh = rfb.updateRectH; @@ -320,8 +381,8 @@ class VncCanvas extends Canvas implements Observer { break; if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) { - if (rfb.updateRectW != 0 && rfb.updateRectH != 0) { - rfb.setFramebufferSize(rfb.updateRectW, rfb.updateRectH); + if (rw != 0 && rh != 0) { + rfb.setFramebufferSize(rw, rh); updateFramebufferSize(); } break; @@ -332,11 +393,6 @@ class VncCanvas extends Canvas implements Observer { handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, rw, rh); continue; } -// if (rfb.updateRectEncoding == rfb.EncodingXCursor || -// rfb.updateRectEncoding == rfb.EncodingRichCursor) { -// throw new Exception("Sorry, no support for" + -// " cursor shape updates yet"); -// } if (rfb.updateRectEncoding == rfb.EncodingPointerPos) { softCursorMove(rx, ry); @@ -385,38 +441,55 @@ class VncCanvas extends Canvas implements Observer { break; default: - throw new Exception("Unknown RFB message type " + - Integer.toString(msgType, 16)); + throw new Exception("Unknown RFB message type " + msgType); } - player.updatePos(); + appClass.updatePos(); } } // - // Handle a raw rectangle. + // Handle a raw rectangle. The second form with paint==false is used + // by the Hextile decoder for raw-encoded tiles. // void handleRawRect(int x, int y, int w, int h) throws IOException { + handleRawRect(x, y, w, h, true); + } - byte[] buf = new byte[w * 4]; - 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 * 4 + 2] & 0xFF) << 16 | - (buf[i * 4 + 1] & 0xFF) << 8 | - (buf[i * 4] & 0xFF); + void handleRawRect(int x, int y, int w, int h, boolean paint) + throws IOException { + + if (bytesPixel == 1) { + for (int dy = y; dy < y + h; dy++) { + rfb.is.readFully(pixels8, dy * rfb.framebufferWidth + x, w); + //if (rfb.rec != null) { + // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); + //} + } + } else { + byte[] buf = new byte[w * 4]; + int i, offset; + for (int dy = y; dy < y + h; dy++) { + rfb.is.readFully(buf); + //if (rfb.rec != null) { + // rfb.rec.write(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); + } } } handleUpdatedPixels(x, y, w, h); - scheduleRepaint(x, y, w, h); + if (paint) + scheduleRepaint(x, y, w, h); } - // // Handle a CopyRect rectangle. // @@ -462,7 +535,6 @@ class VncCanvas extends Canvas implements Observer { // Handle a CoRRE-encoded rectangle. // void handleCoRRERect(int x, int y, int w, int h) throws IOException { - int nSubrects = rfb.is.readInt(); int sx, sy, sw, sh; @@ -496,8 +568,8 @@ class VncCanvas extends Canvas implements Observer { void handleHextileRect(int x, int y, int w, int h) throws IOException { - hextile_bg = new Color(0, 0, 0); - hextile_fg = new Color(0, 0, 0); + hextile_bg = new Color(0); + hextile_fg = new Color(0); for (int ty = y; ty < y + h; ty += 16) { int th = 16; @@ -578,6 +650,7 @@ class VncCanvas extends Canvas implements Observer { memGraphics.setColor(hextile_fg); memGraphics.fillRect(sx, sy, sw, sh); } + } else { memGraphics.setColor(hextile_fg); for (int j = 0; j < nSubrects; j++) { @@ -589,6 +662,7 @@ class VncCanvas extends Canvas implements Observer { sh = (b2 & 0xf) + 1; memGraphics.fillRect(sx, sy, sw, sh); } + } } @@ -657,6 +731,7 @@ class VncCanvas extends Canvas implements Observer { memGraphics.fillRect(x, y, w, h); scheduleRepaint(x, y, w, h); return; + } if (comp_ctl == rfb.TightJpeg) { @@ -713,7 +788,7 @@ class VncCanvas extends Canvas implements Observer { throw new Exception("Incorrect tight filter id: " + filter_id); } } - if (numColors == 0) + if (numColors == 0 && bytesPixel == 4) rowSize *= 3; // Read, optionally uncompress and decode data. @@ -726,9 +801,13 @@ class VncCanvas extends Canvas implements Observer { rfb.is.readFully(indexedData); if (numColors == 2) { // Two colors. + //if (bytesPixel == 1) { + // decodeMonoData(x, y, w, h, indexedData, palette8); + //} else { decodeMonoData(x, y, w, h, indexedData, palette24); + //} } else { - // 3..255 colors. + // 3..255 colors (assuming bytesPixel == 4). int i = 0; for (int dy = y; dy < y + h; dy++) { for (int dx = x; dx < x + w; dx++) { @@ -744,16 +823,28 @@ class VncCanvas extends Canvas implements Observer { 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); + if (bytesPixel == 1) { + for (int dy = y; dy < y + h; dy++) { + rfb.is.readFully(pixels8, dy * rfb.framebufferWidth + x, w); + //if (rfb.rec != null) { + // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); + //} + } + } else { + byte[] buf = new byte[w * 3]; + int i, offset; + for (int dy = y; dy < y + h; dy++) { + rfb.is.readFully(buf); + //if (rfb.rec != null) { + // rfb.rec.write(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); + } } } } @@ -816,8 +907,28 @@ class VncCanvas extends Canvas implements Observer { } // - // Decode 1bpp-encoded bi-color rectangle. + // Decode 1bpp-encoded bi-color rectangle (8-bit and 24-bit versions). // + void decodeMonoData(int x, int y, int w, int h, byte[] src, byte[] palette) { + + int dx, dy, n; + int i = y * rfb.framebufferWidth + x; + int rowBytes = (w + 7) / 8; + byte b; + + for (dy = 0; dy < h; dy++) { + for (dx = 0; dx < w / 8; dx++) { + b = src[dy * rowBytes + dx]; + for (n = 7; n >= 0; n--) + pixels8[i++] = palette[b >> n & 1]; + } + for (n = 7; n >= 8 - w % 8; n--) { + pixels8[i++] = palette[src[dy * rowBytes + dx] >> n & 1]; + } + i += (rfb.framebufferWidth - w); + } + } + void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette) { int dx, dy, n; @@ -883,27 +994,48 @@ class VncCanvas extends Canvas implements Observer { } } - // // Display newly updated area of pixels. // void handleUpdatedPixels(int x, int y, int w, int h) { // Draw updated pixels of the off-screen image. - pixelsSource.newPixels(x, y, w, h); memGraphics.setClip(x, y, w, h); memGraphics.drawImage(rawPixelsImage, 0, 0, null); memGraphics.setClip(0, 0, rfb.framebufferWidth, rfb.framebufferHeight); } + // + // 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. + seekMode = false; + if (showSoftCursor) + scrollToPoint(cursorX, cursorY); + updateFramebufferSize(); + repaint(); + } else { + // Usual incremental repaint. + Point o = getImageOrigin(); + repaint(appClass.deferScreenUpdates, o.x + x, o.y + y, w, h); + } + } + } + + ////////////////////////////////////////////////////////////////// // // Handle cursor shape updates (XCursor and RichCursor encodings). // boolean showSoftCursor = false; - int[] softCursorPixels; MemoryImageSource softCursorSource; Image softCursor; @@ -912,7 +1044,6 @@ class VncCanvas extends Canvas implements Observer { int origCursorWidth, origCursorHeight; int hotX, hotY; int origHotX, origHotY; - int deferCursorUpdates = 10; // // Handle cursor shape update (XCursor and RichCursor encodings). @@ -922,29 +1053,57 @@ class VncCanvas extends Canvas implements Observer { int height) throws IOException { - int bytesPerRow = (width + 7) / 8; - int bytesMaskData = bytesPerRow * height; - softCursorFree(); if (width * height == 0) return; -// // Ignore cursor shape data if requested by user. -// -// if (viewer.options.ignoreCursorUpdates) { -// if (encodingType == rfb.EncodingXCursor) { -// rfb.is.skipBytes(6 + bytesMaskData * 2); -// } else { -// // rfb.EncodingRichCursor -// rfb.is.skipBytes(width * height + bytesMaskData); -// } -// return; -// } + // Ignore cursor shape data if requested by user. + //if (appClass.options.ignoreCursorUpdates) { + if (false) { + int bytesPerRow = (width + 7) / 8; + int bytesMaskData = bytesPerRow * height; + + if (encodingType == rfb.EncodingXCursor) { + rfb.is.skipBytes(6 + bytesMaskData * 2); + } else { + // rfb.EncodingRichCursor + rfb.is.skipBytes(width * height + bytesMaskData); + } + return; + } // Decode cursor pixel data. + softCursorSource = decodeCursorShape(encodingType, width, height); + + // Set original (non-scaled) cursor dimensions. + origCursorWidth = width; + origCursorHeight = height; + origHotX = xhot; + origHotY = yhot; - softCursorPixels = new int[width * height]; + // Create off-screen cursor image. + createSoftCursor(); + + // Show the cursor. + showSoftCursor = true; + Point p = getImageOrigin(); + scheduleCursorRepaint(cursorX - hotX + p.x, cursorY - hotY + p.y, + cursorWidth, cursorHeight, 5); + } + + // + // decodeCursorShape(). Decode cursor pixel data and return + // corresponding MemoryImageSource instance. + // + synchronized MemoryImageSource decodeCursorShape(int encodingType, int width, + int height) + throws IOException { + + int bytesPerRow = (width + 7) / 8; + int bytesMaskData = bytesPerRow * height; + + int[] softCursorPixels = new int[width * height]; if (encodingType == rfb.EncodingXCursor) { @@ -994,7 +1153,7 @@ class VncCanvas extends Canvas implements Observer { // encodingType == rfb.EncodingRichCursor // Read pixel and mask data. - byte[] pixBuf = new byte[width * height * 4]; + byte[] pixBuf = new byte[width * height * bytesPixel]; rfb.is.readFully(pixBuf); byte[] maskBuf = new byte[bytesMaskData]; rfb.is.readFully(maskBuf); @@ -1008,35 +1167,30 @@ class VncCanvas extends Canvas implements Observer { maskByte = maskBuf[y * bytesPerRow + x]; for (n = 7; n >= 0; n--) { if ((maskByte >> n & 1) != 0) { -// if (bytesPerPixel == 1) { -// result = cm8.getRGB(pixBuf[i]); -// } else { - result = (pixBuf[i * 4] & 0xFF) << 24 | - (pixBuf[i * 4 + 1] & 0xFF) << 16 | - (pixBuf[i * 4 + 2] & 0xFF) << 8 | - (pixBuf[i * 4 + 3] & 0xFF); - //result = 0xFF000000 | - // (pixBuf[i * 4 + 1] & 0xFF) << 16 | - // (pixBuf[i * 4 + 2] & 0xFF) << 8 | - // (pixBuf[i * 4 + 3] & 0xFF); -// } + if (bytesPixel == 1) { + result = cm8.getRGB(pixBuf[i]); + } else { + result = (pixBuf[i * 4] & 0xFF) << 24 | + (pixBuf[i * 4 + 1] & 0xFF) << 16 | + (pixBuf[i * 4 + 2] & 0xFF) << 8 | + (pixBuf[i * 4 + 3] & 0xFF); + } } else { result = 0; // Transparent pixel } softCursorPixels[i++] = result; } } - for (n = 7; n >= 8 - width % 8; n--) { if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) { -// if (bytesPerPixel == 1) { -// result = cm8.getRGB(pixBuf[i]); -// } else { - result = 0xFF000000 | - (pixBuf[i * 4 + 1] & 0xFF) << 16 | - (pixBuf[i * 4 + 2] & 0xFF) << 8 | - (pixBuf[i * 4 + 3] & 0xFF); -// } + if (bytesPixel == 1) { + result = cm8.getRGB(pixBuf[i]); + } else { + result = 0xFF000000 | + (pixBuf[i * 4 + 1] & 0xFF) << 16 | + (pixBuf[i * 4 + 2] & 0xFF) << 8 | + (pixBuf[i * 4 + 3] & 0xFF); + } } else { result = 0; // Transparent pixel } @@ -1046,68 +1200,70 @@ class VncCanvas extends Canvas implements Observer { } - // Draw the cursor on an off-screen image. - - softCursorSource = - new MemoryImageSource(width, height, softCursorPixels, 0, width); - softCursor = Toolkit.getDefaultToolkit().createImage(softCursorSource); -// if (inputEnabled && viewer.options.scaleCursor != 0) { -// int w = (width * viewer.options.scaleCursor) / 100; -// int h = (height * viewer.options.scaleCursor) / 100; -// Image newCursor = softCursor.getScaledInstance(w, h, Image.SCALE_SMOOTH); -// softCursor = newCursor; -// cursorWidth = w; -// cursorHeight = h; -// hotX = (xhot * viewer.options.scaleCursor) / 100; -// hotY = (yhot * viewer.options.scaleCursor) / 100; -// } else { - cursorWidth = width; - cursorHeight = height; - hotX = xhot; - hotY = yhot; -// } - - // Set data associated with cursor. - origCursorWidth = width; - origCursorHeight = height; - origHotX = xhot; - origHotY = yhot; - - showSoftCursor = true; - - // Show the cursor. - scheduleRepaint(cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight); + return new MemoryImageSource(width, height, softCursorPixels, 0, width); } - private void scrollToPoint(int x, int y) { - boolean needScroll = false; + // + // createSoftCursor(). Assign softCursor new Image (scaled if necessary). + // Uses softCursorSource as a source for new cursor image. + // + synchronized void createSoftCursor() { - if (player.desktopScrollPane == null) + if (softCursorSource == null) return; - Dimension d = player.desktopScrollPane.getSize(); - Point topLeft = player.desktopScrollPane.getScrollPosition(); - Point botRight = new Point(topLeft.x + d.width, topLeft.y + d.height); - - if (x < topLeft.x + SCROLL_MARGIN) { - // shift left - topLeft.x = x - SCROLL_MARGIN; - needScroll = true; - } else if (x > botRight.x - SCROLL_MARGIN) { - // shift right - topLeft.x = x - d.width + SCROLL_MARGIN; - needScroll = true; + int scaleCursor = 100; + //int scaleCursor = appClass.options.scaleCursor; + //if (scaleCursor == 0 || !inputEnabled) + //scaleCursor = 100; + + // Save original cursor coordinates. + int x = cursorX - hotX; + int y = cursorY - hotY; + int w = cursorWidth; + int h = cursorHeight; + + cursorWidth = (origCursorWidth * scaleCursor + 50) / 100; + cursorHeight = (origCursorHeight * scaleCursor + 50) / 100; + hotX = (origHotX * scaleCursor + 50) / 100; + hotY = (origHotY * scaleCursor + 50) / 100; + softCursor = Toolkit.getDefaultToolkit().createImage(softCursorSource); + + if (scaleCursor != 100) { + softCursor = softCursor.getScaledInstance(cursorWidth, cursorHeight, + Image.SCALE_SMOOTH); } - if (y < topLeft.y + SCROLL_MARGIN) { - // shift up - topLeft.y = y - SCROLL_MARGIN; - needScroll = true; - } else if (y > botRight.y - SCROLL_MARGIN) { - // shift down - topLeft.y = y - d.height + SCROLL_MARGIN; - needScroll = true; + } + + private void scrollToPoint(int x, int y) { + // Automatic viewport scrolling + if (appClass.desktopScrollPane != null) { + boolean needScroll = false; + Dimension d = appClass.desktopScrollPane.getViewportSize(); + Point topLeft = appClass.desktopScrollPane.getScrollPosition(); + Point botRight = new Point(topLeft.x + d.width, topLeft.y + d.height); + + if (x < topLeft.x + SCROLL_MARGIN) { + // shift left + topLeft.x = x - SCROLL_MARGIN; + needScroll = true; + } else if (x > botRight.x - SCROLL_MARGIN) { + // shift right + topLeft.x = x - d.width + SCROLL_MARGIN; + needScroll = true; + } + if (y < topLeft.y + SCROLL_MARGIN) { + // shift up + topLeft.y = y - SCROLL_MARGIN; + needScroll = true; + } else if (y > botRight.y - SCROLL_MARGIN) { + // shift down + topLeft.y = y - d.height + SCROLL_MARGIN; + needScroll = true; + } + if (needScroll) + appClass.desktopScrollPane.setScrollPosition(topLeft.x, topLeft.y); } - player.desktopScrollPane.setScrollPosition(topLeft.x, topLeft.y); } // @@ -1119,19 +1275,16 @@ class VncCanvas extends Canvas implements Observer { int oldY = cursorY + o.y; cursorX = x; cursorY = y; - - // paint and scroll if (showSoftCursor) { - scheduleRepaint(oldX - hotX, oldY - hotY, cursorWidth, cursorHeight); - scheduleRepaint(cursorX - hotX + o.x, cursorY - hotY + o.y, cursorWidth, - cursorHeight); + scheduleCursorRepaint(oldX - hotX, oldY - hotY, cursorWidth, cursorHeight, + 0); + scheduleCursorRepaint(cursorX - hotX + o.x, cursorY - hotY + o.y, + cursorWidth, cursorHeight, 1); if (!seekMode) scrollToPoint(x, y); } - - cursorX = x; - cursorY = y; } + // // softCursorFree(). Remove soft cursor, dispose resources. // @@ -1140,17 +1293,40 @@ class VncCanvas extends Canvas implements Observer { showSoftCursor = false; softCursor = null; softCursorSource = null; - softCursorPixels = null; - Point o = getImageOrigin(); - scheduleRepaint(cursorX - hotX + o.x, cursorY - hotY + o.y, cursorWidth, - cursorHeight); + Point p = getImageOrigin(); + scheduleCursorRepaint(cursorX - hotX + p.x, cursorY - hotY + p.y, + cursorWidth, cursorHeight, 3); } } + + Point getFrameCenter() { + Dimension d = appClass.desktopScrollPane.getViewportSize(); + Point p = appClass.desktopScrollPane.getScrollPosition(); + if (d.width > rfb.framebufferWidth) + p.x = d.width / 2; + else + p.x += d.width / 2; + if (d.height > rfb.framebufferHeight) + p.y = d.height / 2; + else + p.y += d.height / 2; + return p; + } + // - // Tell JVM to repaint specified desktop area. + // We are observing our FbsInputStream object to get notified on + // switching to the `paused' mode. In such cases we want to repaint + // our desktop if we were seeking. // - void scheduleRepaint(int x, int y, int w, int h) { + public void update(Observable o, Object arg) { + // Immediate repaint of the whole desktop after seeking. + repaint(); + // Let next scheduleRepaint() call invoke incremental drawing. + seekMode = false; + } + + void scheduleCursorRepaint(int x, int y, int w, int h, int n) { if (rfb.fbs.isSeeking()) { // Do nothing, and remember we are seeking. seekMode = true; @@ -1164,22 +1340,9 @@ class VncCanvas extends Canvas implements Observer { repaint(); } else { // Usual incremental repaint. - Point o = getImageOrigin(); - repaint(player.deferScreenUpdates, o.x + x, o.y + y, w, h); + repaint(appClass.deferScreenUpdates, x, y, w, h); } } } - // - // We are observing our FbsInputStream object to get notified on - // 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(); - // Let next scheduleRepaint() call invoke incremental drawing. - seekMode = false; - } - } |