📄 rfbproto.java
字号:
b[15] = (byte) greenShift; b[16] = (byte) blueShift; os.write(b); } // // Write a FixColourMapEntries message. The values in the red, green and // blue arrays are from 0 to 65535. // void writeFixColourMapEntries(int firstColour, int nColours, int[] red, int[] green, int[] blue) throws IOException { byte[] b = new byte[6 + nColours * 6]; b[0] = (byte) FixColourMapEntries; b[2] = (byte) ((firstColour >> 8) & 0xff); b[3] = (byte) (firstColour & 0xff); b[4] = (byte) ((nColours >> 8) & 0xff); b[5] = (byte) (nColours & 0xff); for (int i = 0; i < nColours; i++) { b[6 + i * 6] = (byte) ((red[i] >> 8) & 0xff); b[6 + i * 6 + 1] = (byte) (red[i] & 0xff); b[6 + i * 6 + 2] = (byte) ((green[i] >> 8) & 0xff); b[6 + i * 6 + 3] = (byte) (green[i] & 0xff); b[6 + i * 6 + 4] = (byte) ((blue[i] >> 8) & 0xff); b[6 + i * 6 + 5] = (byte) (blue[i] & 0xff); } os.write(b); } // // Write a SetEncodings message // void writeSetEncodings(int[] encs, int len) throws IOException { byte[] b = new byte[4 + 4 * len]; b[0] = (byte) SetEncodings; b[2] = (byte) ((len >> 8) & 0xff); b[3] = (byte) (len & 0xff); for (int i = 0; i < len; i++) { b[4 + 4 * i] = (byte) ((encs[i] >> 24) & 0xff); b[5 + 4 * i] = (byte) ((encs[i] >> 16) & 0xff); b[6 + 4 * i] = (byte) ((encs[i] >> 8) & 0xff); b[7 + 4 * i] = (byte) (encs[i] & 0xff); } os.write(b); } // // Write a ClientCutText message // void writeClientCutText(String text) throws IOException { byte[] b = new byte[8 + text.length()]; b[0] = (byte) ClientCutText; b[4] = (byte) ((text.length() >> 24) & 0xff); b[5] = (byte) ((text.length() >> 16) & 0xff); b[6] = (byte) ((text.length() >> 8) & 0xff); b[7] = (byte) (text.length() & 0xff); System.arraycopy(text.getBytes(), 0, b, 8, text.length()); os.write(b); } // // A buffer for putting pointer and keyboard events before being sent. This // is to ensure that multiple RFB events generated from a single Java Event // will all be sent in a single network packet. The maximum possible // length is 4 modifier down events, a single key event followed by 4 // modifier up events i.e. 9 key events or 72 bytes. // byte[] eventBuf = new byte[72]; int eventBufLen; // Useful shortcuts for modifier masks. final static int CTRL_MASK = InputEvent.CTRL_MASK; final static int SHIFT_MASK = InputEvent.SHIFT_MASK; final static int META_MASK = InputEvent.META_MASK; final static int ALT_MASK = InputEvent.ALT_MASK; // // Write a pointer event message. We may need to send modifier key events // around it to set the correct modifier state. // int pointerMask = 0; void writePointerEvent(MouseEvent evt) throws IOException { int modifiers = evt.getModifiers(); int mask2 = 2; int mask3 = 4; if (viewer.options.reverseMouseButtons2And3) { mask2 = 4; mask3 = 2; } // Note: For some reason, AWT does not set BUTTON1_MASK on left // button presses. Here we think that it was the left button if // modifiers do not include BUTTON2_MASK or BUTTON3_MASK. if (evt.getID() == MouseEvent.MOUSE_PRESSED) { if ((modifiers & InputEvent.BUTTON2_MASK) != 0) { pointerMask = mask2; modifiers &= ~ALT_MASK; } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) { pointerMask = mask3; modifiers &= ~META_MASK; } else { pointerMask = 1; } } else if (evt.getID() == MouseEvent.MOUSE_RELEASED) { pointerMask = 0; if ((modifiers & InputEvent.BUTTON2_MASK) != 0) { modifiers &= ~ALT_MASK; } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) { modifiers &= ~META_MASK; } } eventBufLen = 0; writeModifierKeyEvents(modifiers); int x = evt.getX(); int y = evt.getY(); if (x < 0) x = 0; if (y < 0) y = 0; eventBuf[eventBufLen++] = (byte) PointerEvent; eventBuf[eventBufLen++] = (byte) pointerMask; eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); eventBuf[eventBufLen++] = (byte) (x & 0xff); eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); eventBuf[eventBufLen++] = (byte) (y & 0xff); // // Always release all modifiers after an "up" event // if (pointerMask == 0) { writeModifierKeyEvents(0); } os.write(eventBuf, 0, eventBufLen); } // // Write a key event message. We may need to send modifier key events // around it to set the correct modifier state. Also we need to translate // from the Java key values to the X keysym values used by the RFB protocol. // void writeKeyEvent(KeyEvent evt) throws IOException { int keyChar = evt.getKeyChar(); // // Ignore event if only modifiers were pressed. // // Some JVMs return 0 instead of CHAR_UNDEFINED in getKeyChar(). if (keyChar == 0) keyChar = KeyEvent.CHAR_UNDEFINED; if (keyChar == KeyEvent.CHAR_UNDEFINED) { int code = evt.getKeyCode(); if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_SHIFT || code == KeyEvent.VK_META || code == KeyEvent.VK_ALT) return; } // // Key press or key release? // boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); int key; if (evt.isActionKey()) { // // An action key should be one of the following. // If not then just ignore the event. // switch(evt.getKeyCode()) { case KeyEvent.VK_HOME: key = 0xff50; break; case KeyEvent.VK_LEFT: key = 0xff51; break; case KeyEvent.VK_UP: key = 0xff52; break; case KeyEvent.VK_RIGHT: key = 0xff53; break; case KeyEvent.VK_DOWN: key = 0xff54; break; case KeyEvent.VK_PAGE_UP: key = 0xff55; break; case KeyEvent.VK_PAGE_DOWN: key = 0xff56; break; case KeyEvent.VK_END: key = 0xff57; break; case KeyEvent.VK_INSERT: key = 0xff63; break; case KeyEvent.VK_F1: key = 0xffbe; break; case KeyEvent.VK_F2: key = 0xffbf; break; case KeyEvent.VK_F3: key = 0xffc0; break; case KeyEvent.VK_F4: key = 0xffc1; break; case KeyEvent.VK_F5: key = 0xffc2; break; case KeyEvent.VK_F6: key = 0xffc3; break; case KeyEvent.VK_F7: key = 0xffc4; break; case KeyEvent.VK_F8: key = 0xffc5; break; case KeyEvent.VK_F9: key = 0xffc6; break; case KeyEvent.VK_F10: key = 0xffc7; break; case KeyEvent.VK_F11: key = 0xffc8; break; case KeyEvent.VK_F12: key = 0xffc9; break; default: return; } } else { // // A "normal" key press. Ordinary ASCII characters go straight through. // For CTRL-<letter>, CTRL is sent separately so just send <letter>. // Backspace, tab, return, escape and delete have special keysyms. // Anything else we ignore. // key = keyChar; if (key < 0x20) { if (evt.isControlDown()) { key += 0x60; } else { switch(key) { case KeyEvent.VK_BACK_SPACE: key = 0xff08; break; case KeyEvent.VK_TAB: key = 0xff09; break; case KeyEvent.VK_ENTER: key = 0xff0d; break; case KeyEvent.VK_ESCAPE: key = 0xff1b; break; } } } else if (key == 0x7f) { // Delete key = 0xffff; } else if (key > 0xff) { // JDK1.1 on X incorrectly passes some keysyms straight through, // so we do too. JDK1.1.4 seems to have fixed this. // The keysyms passed are 0xff00 .. XK_BackSpace .. XK_Delete // Also, we pass through foreign currency keysyms (0x20a0..0x20af). if ((key < 0xff00 || key > 0xffff) && !(key >= 0x20a0 && key <= 0x20af)) return; } } // Fake keyPresses for keys that only generates keyRelease events if ((key == 0xe5) || (key == 0xc5) || // XK_aring / XK_Aring (key == 0xe4) || (key == 0xc4) || // XK_adiaeresis / XK_Adiaeresis (key == 0xf6) || (key == 0xd6) || // XK_odiaeresis / XK_Odiaeresis (key == 0xa7) || (key == 0xbd) || // XK_section / XK_onehalf (key == 0xa3)) { // XK_sterling // Make sure we do not send keypress events twice on platforms // with correct JVMs (those that actually report KeyPress for all // keys) if (down) brokenKeyPressed = true; if (!down && !brokenKeyPressed) { // We've got a release event for this key, but haven't received // a press. Fake it. eventBufLen = 0; writeModifierKeyEvents(evt.getModifiers()); writeKeyEvent(key, true); os.write(eventBuf, 0, eventBufLen); } if (!down) brokenKeyPressed = false; } eventBufLen = 0; writeModifierKeyEvents(evt.getModifiers()); writeKeyEvent(key, down); // Always release all modifiers after an "up" event if (!down) writeModifierKeyEvents(0); os.write(eventBuf, 0, eventBufLen); } // // Add a raw key event with the given X keysym to eventBuf. // void writeKeyEvent(int keysym, boolean down) { eventBuf[eventBufLen++] = (byte) KeyboardEvent; eventBuf[eventBufLen++] = (byte) (down ? 1 : 0); eventBuf[eventBufLen++] = (byte) 0; eventBuf[eventBufLen++] = (byte) 0; eventBuf[eventBufLen++] = (byte) ((keysym >> 24) & 0xff); eventBuf[eventBufLen++] = (byte) ((keysym >> 16) & 0xff); eventBuf[eventBufLen++] = (byte) ((keysym >> 8) & 0xff); eventBuf[eventBufLen++] = (byte) (keysym & 0xff); } // // Write key events to set the correct modifier state. // int oldModifiers = 0; void writeModifierKeyEvents(int newModifiers) { if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); if ((newModifiers & SHIFT_MASK) != (oldModifiers & SHIFT_MASK)) writeKeyEvent(0xffe1, (newModifiers & SHIFT_MASK) != 0); if ((newModifiers & META_MASK) != (oldModifiers & META_MASK)) writeKeyEvent(0xffe7, (newModifiers & META_MASK) != 0); if ((newModifiers & ALT_MASK) != (oldModifiers & ALT_MASK)) writeKeyEvent(0xffe9, (newModifiers & ALT_MASK) != 0); oldModifiers = newModifiers; } // // Compress and write the data into the recorded session file. This // method assumes the recording is on (rec != null). // void recordCompressedData(byte[] data, int off, int len) throws IOException { Deflater deflater = new Deflater(); deflater.setInput(data, off, len); int bufSize = len + len / 100 + 12; byte[] buf = new byte[bufSize]; deflater.finish(); int compressedSize = deflater.deflate(buf); recordCompactLen(compressedSize); rec.write(buf, 0, compressedSize); } void recordCompressedData(byte[] data) throws IOException { recordCompressedData(data, 0, data.length); } // // Write an integer in compact representation (1..3 bytes) into the // recorded session file. This method assumes the recording is on // (rec != null). // void recordCompactLen(int len) throws IOException { byte[] buf = new byte[3]; int bytes = 0; buf[bytes++] = (byte)(len & 0x7F); if (len > 0x7F) { buf[bytes-1] |= 0x80; buf[bytes++] = (byte)(len >> 7 & 0x7F); if (len > 0x3FFF) { buf[bytes-1] |= 0x80; buf[bytes++] = (byte)(len >> 14 & 0xFF); } } rec.write(buf, 0, bytes); } public void startTiming() { timing = true; // Carry over up to 1s worth of previous rate for smoothing. if (timeWaitedIn100us > 10000) { timedKbits = timedKbits * 10000 / timeWaitedIn100us; timeWaitedIn100us = 10000; } } public void stopTiming() { timing = false; if (timeWaitedIn100us < timedKbits/2) timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s } public long kbitsPerSecond() { return timedKbits * 10000 / timeWaitedIn100us; } public long timeWaited() { return timeWaitedIn100us; } public void readFully(byte b[]) throws IOException { readFully(b, 0, b.length); } public void readFully(byte b[], int off, int len) throws IOException { long before = 0; if (timing) before = System.currentTimeMillis(); is.readFully(b, off, len); if (timing) { long after = System.currentTimeMillis(); long newTimeWaited = (after - before) * 10; int newKbits = len * 8 / 1000; // limit rate to between 10kbit/s and 40Mbit/s if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000; if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4; timeWaitedIn100us += newTimeWaited; timedKbits += newKbits; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -