すべてのプロダクト
Search
ドキュメントセンター

Cloud Phone:Web SDK を使用した Safari での貼り付け

最終更新日:Dec 11, 2025

Safari にはセキュリティ上の制限があり、クリップボードにアクセスすると貼り付けバブルボタンが表示されます。これは、ローカルクライアントからクラウドスマホへのコンテンツの同期を妨げる可能性があります。このトピックでは、Web SDK を使用して、ローカルのクリップボードから Safari ブラウザにテキストを貼り付ける方法について説明します。

ソリューション概要

  1. ローカルクライアントにクリップボードボタンを追加します。このボタンをクリックすると、バブル入力ボックスが開きます。

  2. バブル入力ボックスに、クラウドスマホに送信したいコンテンツを入力します。

  3. バブル入力ボックスの [今すぐ貼り付け] ボタンをクリックして、コンテンツをクラウドスマホのクリップボードと入力ボックスに同期します。

実装手順

クラウドスマホのパラメーター構成

  • readClipboardDataByUser を `true` に設定します。これにより、ソフトウェア開発キット (SDK) がクリップボードを自動的に読み取るのを防ぎます。

  • useCustomIme を `true` に設定して、ローカルの入力メソッドエディター (IME) を有効にします。コンテンツをクラウドスマホの入力ボックスに同期するには、ローカル IME を有効にする必要があります。

// ブラウザが Safari かどうかを確認
function isSafari() {
    return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
}
// メインコントロールの構成。SDK によるクリップボードの自動読み取りを無効にし、ローカル IME を有効にします。
connConfig = {..., readClipboardDataByUser:isSafari(), useCustomIme:true}; 
var appInfo = {
  ...,
  connConfig: connConfig,
  ...
};
var sessionParam = {
  ...,
  appInfo: appInfo,
  ....
};
var wuyingSdk = Wuying.WebSDK;
session = wuyingSdk.createSession('appstream', sessionParam);
// サムネイルの構成。ローカル IME を有効にします。
this.thumbnail = new window.Wuying.ThumbnailSDK({
  ...,
  connectionConfig: {
    useCustomIme: true,
  },
},
{
  onConnected: (data) => {
    this.thumbnail.session.getLocalConfig().setClipboardEnabled(true);
  },
  onDisConnected: (data) => {},
  onThumbnailData: (url) => {},
}
);

バブル入力ボックスの構築

クライアントにクリップボードボタンを構築できます。このボタンをクリックすると、クリップボードと対話するダイアログボックスが開きます。リファレンスとして、次のコードをご参照ください。

function showInput() {
  showCustomDialog();
  // モーダルオーバーレイをクリックしてダイアログボックスを閉じます
  document.querySelector('.modal-overlay').addEventListener('click', function (e) {
      if (e.target === this) {
          closeModal();
      }
  });

  // ESC キーを押してダイアログボックスを閉じます
  document.addEventListener('keydown', function (e) {
      if (e.key === 'Escape') {
          closeModal();
      }
  });
}

function closeModal() {
  console.log('closeModal');
  const overlay = document.querySelector('.modal-overlay');
  if (overlay) {
      overlay.style.display = 'none';
      overlay.remove();
  }
}

function submitContent() {
  const content = document.querySelector('.input-field').value.trim();
  if (!content) {
      alert('コンテンツを入力してください');
      return;
  }
  // コンテンツをクラウドスマホに同期します
  sendMsgToCloudPhoneOperation(content);
  closeModal();
}

function showCustomDialog() {
  // モーダルのバックグラウンドを作成します
  const overlay = document.createElement('div');
  overlay.className = 'modal-overlay';
  // モーダルがすべてのイベントをキャプチャし、最上位に表示されるようにします
  overlay.style.pointerEvents = 'all';
  overlay.style.zIndex = '9999';
  
  // イベントが下位レイヤーに伝播しないようにします
  const stopPropagation = function(e) {
      e.stopPropagation();
  };
  
  overlay.addEventListener('contextmenu', stopPropagation, true);
  
  // すべてのキーボードイベントをインターセプトするイベントリスナーを追加します
  overlay.addEventListener('keydown', stopPropagation, true);
  overlay.addEventListener('keyup', stopPropagation, true);
  overlay.addEventListener('keypress', stopPropagation, true);
  
  overlay.innerHTML = `
      <div class="modal">
          <div class="modal-header">
              <h2 class="modal-title">クリップボード</h2>
              <button class="close-btn" onclick="closeModal()">×</button>
          </div>
          
          <div class="input-container">
              <textarea 
                  class="input-field" 
                  placeholder="コンテンツを入力"
                  maxlength="500"
              ></textarea>
          </div>
          
          <button class="submit-btn" onclick="submitContent()">
              今すぐ貼り付け
          </button>
      </div>
  `;

  document.body.appendChild(overlay);
  
  // モーダルが開いたときにテキストエリアにフォーカスを当て、キーボードイベントがキャプチャされるようにします
  setTimeout(() => {
      const textarea = overlay.querySelector('.input-field');
      if (textarea) {
          textarea.focus();
      }
  }, 100);
}

コピーしたテキストのクラウドスマホへの送信

同期タスクのトリガー

function submitContent() {
  const content = document.querySelector('.input-field').value.trim();
  if (!content) {
      alert('コンテンツを入力してください');
      return;
  }
  // コンテンツをクラウドスマホに同期します
  sendMsgToCloudPhoneOperation(content);
  closeModal();
}

コンテンツのクラウドスマホへの同期

function sendMsgToCloudPhoneOperation(msg) {
  // メインコントロール
  if (session) {
    session.setClipboardModule('sendClipboardDataToRemote', msg) 
  }
  // サムネイル
  for (const [key, value] of thumbnailSDKMap) {
      console.log('thumbnail sendMsgToCloudPhoneOperation ', key, msg);
      value.thumbnail.session.getClipboardModule().sendClipboardDataToRemote(msg);
  }
}

注意事項

新しいダイアログボックスは、すべてのキーボードイベントを処理して、他のデスクトップ要素にキャプチャされないようにする必要があります。他の要素がこれらのイベントをキャプチャすると、ダイアログボックスで通常のキー入力が正しく登録されません。リファレンスとして、次の構成をご参照ください。

overlay.addEventListener('contextmenu', stopPropagation, true);

// すべてのキーボードイベントをインターセプトするイベントリスナーを追加します
overlay.addEventListener('keydown', stopPropagation, true);
overlay.addEventListener('keyup', stopPropagation, true);
overlay.addEventListener('keypress', stopPropagation, true);