public VNCConsole(String displayName, int columns, int rows, int charW, int charH) {
    this.displayName = displayName;
    this.columns = columns;
    this.rows = rows;
    charSize = new Dimension(charW, charH);

    buffer = new VNCConsoleBuffer(columns, rows, charSize, clients);

    in = buffer.inputStream();
    out = buffer.printStream();

    // Start thread
    new Thread(this, "VNCConsole-" + displayName).start();
  }
  @Override
  public void keyEvent(RFBClient client, boolean down, int key) throws IOException {
    // Ignore modifiers
    int[] mask = new int[2];
    keysym.toMask(key, mask);
    if (mask[0] != KeyEvent.VK_UNDEFINED) return;

    if (down) {
      int[] vk = new int[2];
      keysym.toVK(key, vk);
      if (vk[0] == KeyEvent.VK_UNDEFINED)
        // Standard key
        buffer.input(key);
      else
        // Virtual key
        buffer.inputVK(vk[0]);
    }
  }
 @Override
 public void frameBufferUpdateRequest(
     RFBClient client, boolean incremental, int x, int y, int w, int h) throws IOException {
   client.writeFrameBufferUpdate(buffer.getRects(client, incremental));
 }
 @Override
 public void setPixelFormat(RFBClient client, PixelFormat pixelFormat) throws IOException {
   pixelFormat.setDirectColorModel(buffer.getFont(client).getDirectColorModel());
 }