QtVncClient モジュールの紹介

# QtVncClient モジュールの紹介

## はじめに

リモートデスクトップ技術は、現代のネットワーク環境において重要な役割を果たしています。特に、VNC（Virtual Network Computing）は、プラットフォームに依存しないリモートデスクトップ制御を可能にする技術として広く利用されています。今回は、Qt アプリケーション向けに VNC クライアント機能を提供する「QtVncClient」モジュールについて紹介します。このライブラリを使用することで、Qt 開発者は自分のアプリケーションにリモートデスクトップの表示や制御機能を簡単に統合することができます。

https://github.com/signal-slot/qtvncclient

## QtVncClient モジュールの紹介

### 概要

QtVncClient は、Qt アプリケーションに VNC クライアント機能を提供するモジュールです。このライブラリを使用することで、開発者は Qt アプリケーション内でリモートデスクトップの表示や制御を簡単に実装することができます。

### 主な機能

現在の実装では、以下の機能が提供されています：

- ホスト名/IP とポートを指定して VNC サーバーに接続
- VNC プロトコルバージョン 3.3 のサポート（3.7 と 3.8 の基本サポートも含む）
- 基本的なセキュリティタイプのサポート（主に認証なし）
- リモートキーボードとマウス制御
- フレームバッファ更新のための Raw エンコーディング
- シンプルな Qt インターフェース
- Tight および ZRLE エンコーディングのためのオプションの ZLIB サポート
- クロスプラットフォーム互換性

### 技術的な詳細

QtVncClient の中心となるのは `QVncClient` クラスです。このクラスは VNC プロトコルのクライアント実装を提供し、Qt アプリケーションが VNC サーバーに接続してフレームバッファ更新を受信し、キーボードやマウスイベントを送信してリモートデスクトップを制御することを可能にします。

```cpp
// QVncClient の基本的な使用例
#include <QtVncClient/qvncclient.h>
#include <QTcpSocket>

// VNC クライアントを作成
QVncClient* vncClient = new QVncClient(this);

// ソケットを作成して VNC サーバーに接続
QTcpSocket* socket = new QTcpSocket(this);
socket->connectToHost("192.168.1.100", 5900);

// VNC クライアントにソケットを設定
vncClient->setSocket(socket);

// VNC 画面を表示するために、imageChanged シグナルに接続
connect(vncClient, &QVncClient::imageChanged, this, [this, vncClient](const QRect &) {
    // 新しい画像で UI を更新
    QImage screen = vncClient->image();
    // 例：myLabel->setPixmap(QPixmap::fromImage(screen));
});

// 画面サイズの変更を処理
connect(vncClient, &QVncClient::framebufferSizeChanged, this, 
    [this](int width, int height) {
        // UI コンポーネントのサイズを適切に変更
    });
```

### エンコーディングのサポート

QtVncClient は、フレームバッファ更新のための複数のエンコーディングタイプをサポートしています：

1. **Raw エンコーディング**：
   - 圧縮なし、直接ピクセルデータ
   - 最も高い帯域幅使用量
   - 最も低い CPU 使用量
   - 高速なローカルネットワークに最適

2. **Hextile エンコーディング**：
   - 長方形を 16x16 のタイルに分割
   - 中程度の圧縮
   - 低い CPU 使用量
   - 中速ネットワークに適している

3. **ZRLE エンコーディング**：
   - Zlib Run-Length エンコーディング
   - 良好な圧縮
   - 中程度の CPU 使用量
   - 遅いネットワークに適している

4. **Tight エンコーディング**：
   - zlib 圧縮と JPEG を組み合わせる
   - 最高の圧縮率
   - より高い CPU 使用量
   - 低速ネットワークや帯域幅が制限されている場合に理想的
   - 特に写真コンテンツに効率的

ライブラリは、サーバーとの間で両方がサポートする最適なエンコーディングを自動的にネゴシエートします。利用可能な場合は、優れた圧縮のために Tight エンコーディングが優先されます。

## vnc-watcher サンプルの紹介

QtVncClient モジュールの使用方法を示すために、「vnc-watcher」というサンプルアプリケーションが提供されています。このアプリケーションは、QtVncClient を実際のシナリオで使用する方法を示しています。

### アプリケーションの概要

vnc-watcher は、VNC サーバーに接続してリモートデスクトップを表示し、制御するためのシンプルな UI を提供します。このアプリケーションは、QtVncClient モジュールの機能を活用して、以下の機能を実装しています：

- VNC サーバーのホスト名/IP とポートの設定
- リモートデスクトップの表示
- キーボードとマウス入力の転送
- 接続状態の管理と自動再接続

### 実装の詳細

vnc-watcher の実装は、主に以下のコンポーネントで構成されています：

1. **MainWindow クラス**：
   - アプリケーションのメインウィンドウを提供
   - 接続設定 UI と VNC 表示領域を含む
   - 設定の保存と読み込み
   - 自動再接続ロジック

2. **VncWidget クラス**：
   - QVncClient からのフレームバッファ更新を表示
   - キーボードとマウスイベントを QVncClient に転送
   - 接続状態に基づいて表示を調整

以下は、VncWidget クラスの主要な部分です：

```cpp
// VncWidget クラスの主要な実装
void VncWidget::setClient(QVncClient *client)
{
    // ... 前のクライアントとの接続を解除 ...
    
    d->client = client;
    
    if (client) {
        // フレームバッファサイズの変更を処理
        connect(client, &QVncClient::framebufferSizeChanged, this, [this](int width, int height) {
            setFixedSize(width, height);
            update();
        });
        
        // 画像の変更を処理
        connect(client, &QVncClient::imageChanged, this, [this](const QRect &rect) {
            update(rect);
        });
        
        // 接続状態の変更を処理
        connect(client, &QVncClient::connectionStateChanged, this, [this](bool connected) {
            repaint();
            if (connected)
                window()->raise();
        });
    }
    
    emit clientChanged(client);
}

// 入力イベントの処理
void VncWidget::keyPressEvent(QKeyEvent *e)
{
    if (d->client) {
        d->client->handleKeyEvent(e);
    }
}

void VncWidget::mousePressEvent(QMouseEvent *e)
{
    if (d->client) {
        d->client->handlePointerEvent(e);
    }
}

// 描画イベントの処理
void VncWidget::paintEvent(QPaintEvent *e)
{
    // クライアントからの画像を描画
    QPainter p(this);
    if (!d->client || !d->client->socket() || d->client->socket()->state() != QTcpSocket::ConnectedState) {
        p.setOpacity(0.5);
        p.fillRect(e->rect(), Qt::lightGray);
        return;
    }
    
    p.drawImage(e->rect(), d->client->image(), e->rect());
}
```

### ビルドと実行

vnc-watcher サンプルアプリケーションは、以下の手順でビルドして実行できます：

1. CMake を使用してプロジェクト全体をビルド：
   ```
   mkdir -p build
   cd build
   cmake .. -DQT_BUILD_EXAMPLES:BOOL=ON
   cmake --build .
   ```

2. サンプルアプリケーションを実行：
   ```
   build/examples/vncclient/vnc-watcher
   ```

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="ja" dir="ltr">指定したサーバーとポートを監視して自動で VNC で繋げてくれるクライアントをサンプルとして作った。Qt で組み込み機器の GUI を開発する時とか、いちいち実機のタッチパネル見たり触ったりするのめんどくさかった。最終的にはそれは必要だけど、大体のことは VNC 経由で事足りる。開発効率爆上がり！ <a href="https://t.co/GG7MJwT80e">https://t.co/GG7MJwT80e</a> <a href="https://t.co/QBLKf7D2kY">pic.twitter.com/QBLKf7D2kY</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1894936591329828945?ref_src=twsrc%5Etfw">February 27, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## おわりに

QtVncClient モジュールは、Qt アプリケーションに VNC クライアント機能を簡単に統合するための強力なツールです。基本的な機能は既に実装されていますが、今後のロードマップには多くの改善点が含まれています：

- 完全なプロトコルサポート（RFB 3.7、3.8、およびそれ以降）
- 拡張されたセキュリティ機能（VNC 認証、TLS 暗号化、SSH トンネリングなど）
- より多くのエンコーディングのサポート
- パフォーマンスの最適化
- クリップボード統合、ファイル転送、画面録画などの拡張機能
- ユーザーエクスペリエンスの向上（ビュースケーリング、フルスクリーンモード、タッチ入力サポートなど）
- API の改善とコード品質の向上
- テストとドキュメントの拡充

QtVncClient は、LGPL-3.0、GPL-2.0、または GPL-3.0 ライセンスの下で利用可能です。このモジュールを使用することで、開発者はリモートデスクトップ機能を持つ強力な Qt アプリケーションを簡単に作成することができます。

Signal Slot Inc. が開発したこのオープンソースプロジェクトは、今後も継続的に改善され、より多くの機能が追加される予定です。プロジェクトの詳細やコントリビューションの方法については、公式リポジトリを参照してください。

https://github.com/signal-slot/qtvncclient