Files
VRCT/src-python/docs/details/clipboard.md

8.9 KiB
Raw Permalink Blame History

Clipboard 機能設計書

概要

VRCT のクリップボード機能は、VRChat 内でのテキスト送信効率を向上させるため、翻訳結果をクリップボードにコピーし、ペースト機能を提供します。

主要機能

1. テキストコピー

  • 翻訳結果をシステムクリップボードにコピー
  • 複数のバックエンド対応Windows clip、pyperclip、tkinter
  • UTF-16LE BOM 対応でクロスプラットフォーム互換性を確保

2. テキストペースト

  • Ctrl+V による自動ペースト
  • VRChat ウィンドウの自動フォーカス
  • カウントダウン機能で準備時間を確保

3. VR アプリ検出

  • OpenVR を用いた VRChat アプリ名の自動検出
  • バックグラウンドスレッドによる非同期監視
  • SteamVR の起動を待機・検出

クラス設計

Clipboard クラス

class Clipboard:
    def __init__(self)
    def enable(self) -> None
    def disable(self) -> None
    def copy(self, message: str) -> bool
    def paste(self, window_name: str|None = None, countdown: int = 0) -> bool

メンバ変数

  • is_enabled: クリップボード機能の有効/無効状態
  • app_name: VRChat アプリケーション名(自動検出)
  • _vr_monitor_thread: SteamVR 監視スレッド
  • _stop_monitoring: スレッド停止フラグ

主要メソッド

__init__()

初期化処理:

  1. VR 監視スレッドを起動
  2. SteamVR の起動を待機10秒間隔で確認

enable()

クリップボード機能を有効化:

  1. is_enabled フラグを True に設定
  2. _initialize() を呼び出し VR 監視を再開

disable()

クリップボード機能を無効化:

  1. is_enabled フラグを False に設定
  2. _stop_monitoring フラグを設定しスレッド停止
  3. スレッド終了を待機(タイムアウト 1秒

copy(message: str) -> bool

パラメータ:

  • message: クリップボードにコピーするテキスト

戻り値:

  • True: コピー成功
  • False: コピー失敗または無効状態

動作:

  1. is_enabled チェック
  2. copy_to_clipboard() 関数を呼び出し

paste(window_name: str|None = None, countdown: int = 0) -> bool

パラメータ:

  • window_name: フォーカス対象ウィンドウ(タイトル部分一致 or プロセス名)
  • countdown: ペースト前の待機秒数

戻り値:

  • True: ペースト送信成功
  • False: ペースト失敗または無効状態

動作:

  1. is_enabled チェック
  2. window_name 未指定時は自動検出した VRChat アプリ名を使用
  3. Windows 環境下でウィンドウをフォーカス(以下の順序)
    • ウィンドウタイトルで部分一致検索
    • マッチしない場合、プロセス名で検索
  4. ウィンドウフォーカス成功時、paste_via_pyautogui() でペースト実行

内部メソッド

_initialize()

VR 監視スレッドの初期化:

  1. _stop_monitoring を False に設定
  2. デーモンスレッドで _monitor_steamvr() を起動

_monitor_steamvr()

バックグラウンドスレッド処理:

  1. 10秒間隔で checkSteamvrRunning() を確認
  2. SteamVR 検出時に _setup_vr_app_name() を呼び出し
  3. _stop_monitoring が True になるまで監視

_setup_vr_app_name()

OpenVR を用いた VR アプリ名検出:

  1. OpenVR 初期化(VRApplication_Background モード)
  2. すべてのアプリケーション情報を取得
  3. steam.app で始まるキーを検索し app_name に設定
  4. 例外発生時は app_name を None に設定

支援関数

checkSteamvrRunning() -> bool

SteamVR が起動しているかを確認

  • プロセス名 vrmonitor.exeWindowsまたは vrmonitor(その他)を検索

copy_to_clipboard(text: str) -> bool

複数バックエンド対応のコピー関数

  1. Windows: clip コマンド + UTF-16LE BOM
  2. 汎用: pyperclip ライブラリ
  3. フォールバック: tkinter 使用

paste_via_pyautogui(countdown: int = 0) -> bool

PyAutoGUI を用いたペースト

  • pyautogui.hotkey('ctrl', 'v') で Ctrl+V を送信
  • カウントダウン実行

ウィンドウ検索関数Windows のみ)

find_windows_by_title_substring(substring: str) -> list

ウィンドウタイトルで部分一致検索

find_windows_by_process_name(proc_name: str) -> list

プロセス名でウィンドウを検索

focus_window(hwnd) -> bool

指定ウィンドウをアクティブ化

依存ライブラリ

ライブラリ 用途 オプション
pyautogui キー入力シミュレーション 必須(ペースト機能)
pyperclip クリップボード操作 オプション(フォールバック)
tkinter クリップボード操作 オプション(フォールバック)
openvr VR アプリ名検出 必須
psutil プロセス検索 必須

動作フロー

初期化フロー

Clipboard.__init__()
  └─ _initialize()
      └─ スレッド起動: _monitor_steamvr()
          └─ 10秒間隔で SteamVR 監視
             └─ 検出時: _setup_vr_app_name()
                └─ VRChat アプリ名を app_name に設定

コピー・ペーストフロー

Model.setCopyToClipboard(text)
  └─ clipboard.copy(text)
     └─ copy_to_clipboard(text)  [成功/失敗]

Model.setPasteFromClipboard()
  └─ clipboard.paste(window_name=self.app_name)
     └─ find_windows_by_title_substring() [Windows]
        or find_windows_by_process_name()
     └─ focus_window(hwnd)
     └─ paste_via_pyautogui(countdown)

有効/無効制御

コンフィグ設定

  • config.ENABLE_CLIPBOARD: True/False でクリップボード機能を制御
  • Controller 側で config.ENABLE_CLIPBOARD をチェックし、True の場合のみ setCopyToClipboard()setPasteFromClipboard() を呼び出し

制御メソッドClipboard クラス内部)

# 有効化内部API、通常は使用しない
clipboard.enable()

# 無効化内部API、通常は使用しない
clipboard.disable()

注意: 現在の実装では、Controller は clipboard.enable()/disable() を呼び出さず、config.ENABLE_CLIPBOARD フラグのみで制御します。Clipboard インスタンスは常に初期化されており、VR 監視スレッドも稼働し続けます。

API エンドポイントController

/get/data/clipboard          - 現在の有効/無効状態を取得
/set/enable/clipboard        - config.ENABLE_CLIPBOARD を True に設定
/set/disable/clipboard       - config.ENABLE_CLIPBOARD を False に設定

エラーハンドリング

失敗時の動作

  • コピー失敗: False を返却、リトライなし
  • ペースト失敗: False を返却、リトライなし
  • VR アプリ名検出失敗: app_name を None に設定、現在フォーカス中のウィンドウにペースト

例外処理

  • OpenVR 初期化失敗時は app_name = None に設定
  • プロセス検索例外も握りつぶし
  • ウィンドウフォーカス失敗はログのみ出力

パフォーマンス考慮

スレッド設計

  • VR 監視スレッドは デーモンスレッド(アプリ終了時の強制停止可能)
  • 10秒間隔で監視CPU 負荷最小化)

クリップボード操作

  • コピー・ペースト操作はメインスレッド実行
  • ウィンドウフォーカス後に 0.2秒スリープで安定性向上

セキュリティ・プライバシー

データ保護

  • クリップボードデータは一切ログ出力されない
  • VR アプリ名のみ app_name として保持

OS 依存性

  • Windows: clip コマンド、ctypes によるウィンドウ制御
  • その他 OS: pyperclip/tkinter フォールバック、自動フォーカス機能なし

制限事項・既知の問題

  1. 非 Windows 環境

    • ウィンドウフォーカス機能は Windows のみ対応
    • その他 OS では現在フォーカス中のウィンドウにペースト
  2. VRChat アプリ名検出

    • OpenVR が利用可能で SteamVR が起動している必要がある
    • steam.app 接頭辞のアプリのみ認識
  3. PyAutoGUI の制限

    • キー入力シミュレーションはOS依存
    • 一部アプリケーションではセキュリティ制限により失敗する可能性あり
  4. クリップボードバッファ

    • Ctrl+V 送信のタイミングはユーザー判断(カウントダウン機能あり)
    • クリップボード内容の永続化はしない

参考資料