📄 vnccanvas.java
字号:
rfb.is.readFully(zlibData);
if (rfb.rec != null && rfb.recordFromBeginning) {
rfb.rec.write(zlibData);
}
int stream_id = comp_ctl & 0x03;
if (tightInflaters[stream_id] == null) {
tightInflaters[stream_id] = new Inflater();
}
Inflater myInflater = tightInflaters[stream_id];
myInflater.setInput(zlibData);
byte[] buf = new byte[dataSize];
myInflater.inflate(buf);
if (rfb.rec != null && !rfb.recordFromBeginning) {
rfb.recordCompressedData(buf);
}
if (numColors != 0) {
// Indexed colors.
if (numColors == 2) {
// Two colors.
if (bytesPixel == 1) {
decodeMonoData(x, y, w, h, buf, palette8);
} else {
decodeMonoData(x, y, w, h, buf, palette24);
}
} else {
// More than two colors (assuming bytesPixel == 4).
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[buf[i++] & 0xFF];
}
}
}
} else if (useGradient) {
// Compressed "Gradient"-filtered data (assuming bytesPixel == 4).
decodeGradientData(x, y, w, h, buf);
} else {
// Compressed truecolor data.
if (bytesPixel == 1) {
int destOffset = y * rfb.framebufferWidth + x;
for (int dy = 0; dy < h; dy++) {
System.arraycopy(buf, dy * w, pixels8, destOffset, w);
destOffset += rfb.framebufferWidth;
}
} else {
int srcOffset = 0;
int destOffset, i;
for (int dy = 0; dy < h; dy++) {
myInflater.inflate(buf);
destOffset = (y + dy) * rfb.framebufferWidth + x;
for (i = 0; i < w; i++) {
pixels24[destOffset + i] =
(buf[srcOffset] & 0xFF)
<< 16 | (buf[srcOffset + 1] & 0xFF)
<< 8 | (buf[srcOffset + 2] & 0xFF);
srcOffset += 3;
}
}
}
}
}
handleUpdatedPixels(x, y, w, h);
scheduleRepaint(x, y, w, h);
}
//
// 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;
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--)
pixels24[i++] = palette[b >> n & 1];
}
for (n = 7; n >= 8 - w % 8; n--) {
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) {
int dx, dy, c;
byte[] prevRow = new byte[w * 3];
byte[] thisRow = new byte[w * 3];
byte[] pix = new byte[3];
int[] est = new int[3];
int offset = y * rfb.framebufferWidth + x;
for (dy = 0; dy < h; dy++) {
/* 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];
}
pixels24[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];
}
pixels24[offset++] =
(pix[0] & 0xFF)
<< 16 | (pix[1] & 0xFF)
<< 8 | (pix[2] & 0xFF);
}
System.arraycopy(thisRow, 0, prevRow, 0, w * 3);
offset += (rfb.framebufferWidth - w);
}
}
//
// 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) {
// Request repaint, deferred if necessary.
repaint(viewer.deferScreenUpdates, x, y, w, h);
}
//
// Handle events.
//
public void keyPressed(KeyEvent evt) {
processLocalKeyEvent(evt);
}
public void keyReleased(KeyEvent evt) {
processLocalKeyEvent(evt);
}
public void keyTyped(KeyEvent evt) {
evt.consume();
}
public void mousePressed(MouseEvent evt) {
processLocalMouseEvent(evt, false);
}
public void mouseReleased(MouseEvent evt) {
processLocalMouseEvent(evt, false);
}
public void mouseMoved(MouseEvent evt) {
processLocalMouseEvent(evt, true);
}
public void mouseDragged(MouseEvent evt) {
processLocalMouseEvent(evt, true);
}
public void processLocalKeyEvent(KeyEvent evt) {
if (viewer.rfb != null && rfb.inNormalProtocol) {
if (!inputEnabled) {
if ((evt.getKeyChar() == 'r' || evt.getKeyChar() == 'R')
&& evt.getID() == KeyEvent.KEY_PRESSED) {
// Request screen update.
try {
rfb.writeFramebufferUpdateRequest(
0,
0,
rfb.framebufferWidth,
rfb.framebufferHeight,
false);
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
// Input enabled.
synchronized (rfb) {
try {
rfb.writeKeyEvent(evt);
} catch (Exception e) {
e.printStackTrace();
}
rfb.notify();
}
}
}
// Don't ever pass keyboard events to AWT for default processing.
// Otherwise, pressing Tab would switch focus to ButtonPanel etc.
evt.consume();
}
public void processLocalMouseEvent(MouseEvent evt, boolean moved) {
if (viewer.rfb != null && rfb.inNormalProtocol) {
if (moved) {
softCursorMove(evt.getX(), evt.getY());
}
synchronized (rfb) {
try {
rfb.writePointerEvent(evt);
} catch (Exception e) {
e.printStackTrace();
}
rfb.notify();
}
}
}
//
// Ignored events.
//
public void mouseClicked(MouseEvent evt) {
}
public void mouseEntered(MouseEvent evt) {
}
public void mouseExited(MouseEvent evt) {
}
//////////////////////////////////////////////////////////////////
//
// Handle cursor shape updates (XCursor and RichCursor encodings).
//
boolean showSoftCursor = false;
int[] softCursorPixels;
MemoryImageSource softCursorSource;
Image softCursor;
int cursorX = 0, cursorY = 0;
int cursorWidth, cursorHeight;
int hotX, hotY;
//
// Handle cursor shape update (XCursor and RichCursor encodings).
//
synchronized void handleCursorShapeUpdate(
int encodingType,
int xhot,
int yhot,
int width,
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;
}
// Decode cursor pixel data.
softCursorPixels = new int[width * height];
if (encodingType == rfb.EncodingXCursor) {
// Read foreground and background colors of the cursor.
byte[] rgb = new byte[6];
rfb.is.readFully(rgb);
int[] colors =
{
(0xFF000000 | (rgb[3] & 0xFF)
<< 16 | (rgb[4] & 0xFF)
<< 8 | (rgb[5] & 0xFF)),
(0xFF000000 | (rgb[0] & 0xFF)
<< 16 | (rgb[1] & 0xFF)
<< 8 | (rgb[2] & 0xFF))};
// Read pixel and mask data.
byte[] pixBuf = new byte[bytesMaskData];
rfb.is.readFully(pixBuf);
byte[] maskBuf = new byte[bytesMaskData];
rfb.is.readFully(maskBuf);
// Decode pixel data into softCursorPixels[].
byte pixByte, maskByte;
int x, y, n, result;
int i = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width / 8; x++) {
pixByte = pixBuf[y * bytesPerRow + x];
maskByte = maskBuf[y * bytesPerRow + x];
for (n = 7; n >= 0; n--) {
if ((maskByte >> n & 1) != 0) {
result = colors[pixByte >> n & 1];
} else {
result = 0; // Transparent pixel
}
softCursorPixels[i++] = result;
}
}
for (n = 7; n >= 8 - width % 8; n--) {
if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
result = colors[pixBuf[y * bytesPerRow + x] >> n & 1];
} else {
result = 0; // Transparent pixel
}
softCursorPixels[i++] = result;
}
}
} else {
// encodingType == rfb.EncodingRichCursor
// Read pixel and mask data.
byte[] pixBuf = new byte[width * height * bytesPixel];
rfb.is.readFully(pixBuf);
byte[] maskBuf = new byte[bytesMaskData];
rfb.is.readFully(maskBuf);
// Decode pixel data into softCursorPixels[].
byte pixByte, maskByte;
int x, y, n, result;
int i = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width / 8; x++) {
maskByte = maskBuf[y * bytesPerRow + x];
for (n = 7; n >= 0; n--) {
if ((maskByte >> n & 1) != 0) {
if (bytesPixel == 1)
{
result = 0;
// sf@2005
switch (viewer.options.eightBitColors)
{
case 1:
result = cm8_256c.getRGB(pixBuf[i]);
break;
case 2:
case 4:
result = cm8_64c.getRGB(pixBuf[i]);
break;
case 3:
case 5:
result = cm8_8c.getRGB(pixBuf[i]);
break;
}
}
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
}
softCursorPixels[i++] = result;
}
}
for (n = 7; n >= 8 - width % 8; n--) {
if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
if (bytesPixel == 1)
{
result = 0;
// sf@2005
switch (viewer.options.eightBitColors)
{
case 1:
result = cm8_256c.getRGB(pixBuf[i]);
break;
case 2:
case 4:
result = cm8_64c.getRGB(pixBuf[i]);
break;
case 3:
case 5:
result = cm8_8c.getRGB(pixBuf[i]);
break;
} }
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
}
softCursorPixels[i++] = result;
}
}
}
// Draw the cursor on an off-screen image.
softCursorSource =
new MemoryImageSource(width, height, softCursorPixels, 0, width);
softCursor = createImage(softCursorSource);
// Set remaining data associated with cursor.
cursorWidth = width;
cursorHeight = height;
hotX = xhot;
hotY = yhot;
showSoftCursor = true;
// Show the cursor.
repaint(
viewer.deferCursorUpdates,
cursorX - hotX,
cursorY - hotY,
cursorWidth,
cursorHeight);
}
//
// marscha - PointerPos
// Handle cursor position update (PointerPos encoding).
//
synchronized void handleCursorPosUpdate(
int x,
int y) {
if (x >= rfb.framebufferWidth)
x = rfb.framebufferWidth - 1;
if (y >= rfb.framebufferHeight)
y = rfb.framebufferHeight - 1;
softCursorMove(x, y);
}
//
// softCursorMove(). Moves soft cursor into a particular location.
//
synchronized void softCursorMove(int x, int y) {
if (showSoftCursor) {
repaint(
viewer.deferCursorUpdates,
cursorX - hotX,
cursorY - hotY,
cursorWidth,
cursorHeight);
repaint(
viewer.deferCursorUpdates,
x - hotX,
y - hotY,
cursorWidth,
cursorHeight);
}
cursorX = x;
cursorY = y;
}
//
// softCursorFree(). Remove soft cursor, dispose resources.
//
synchronized void softCursorFree() {
if (showSoftCursor) {
showSoftCursor = false;
softCursor = null;
softCursorSource = null;
softCursorPixels = null;
repaint(
viewer.deferCursorUpdates,
cursorX - hotX,
cursorY - hotY,
cursorWidth,
cursorHeight);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -