sakura icon indicating copy to clipboard operation
sakura copied to clipboard

マクロの Paste() が失敗する場合がある

Open yoshinrt opened this issue 1 year ago • 3 comments

問題内容

マクロの Paste() が失敗することがあるようです.

再現手順

SetDrawSwitch( 0 );
Cut();
Paste();
SetDrawSwitch( 1 );
ReDraw();

上記のマクロをキーに割り当て,EOF以外 の行で実行すると,Paste() の実行に失敗し警告音が鳴ります.

https://github.com/sakura-editor/sakura/blob/fe4cc6d17e0e9f0e58f13c6c3cca9147b7751e32/sakura_core/_os/CClipboard.cpp#L42-L46

で ::OpenClipboard() に失敗し,

https://github.com/sakura-editor/sakura/blob/fe4cc6d17e0e9f0e58f13c6c3cca9147b7751e32/sakura_core/view/CEditView.cpp#L2295-L2297

の if が成立してしまうようです.

再現頻度

  • https://github.com/sakura-editor/sakura/actions/runs/9992367305/artifacts/1715223953 で 100% 再現する
  • fe4cc6d17e0e9f0e58f13c6c3cca9147b7751e32 を手元でリリースビルド (x64) したもので 100% 再現する
  • デバッグビルド (x64) では再現しない
  • マクロ 1行目の SetDrawSwitch をコメントアウトすると再現しない
  • CEditView.cpp 2295行目にブレークを張って一時停止→再開すると,リリースビルドでも再現しない

以上から,タイミングに依存している気がします.環境によってはなかなか再現しないかもしれません.

問題のカテゴリ

  • プログラムの動作上の問題

環境情報

  • OS バージョン Windows 11 Pro 23H2

  • サクラエディタバージョン

サクラエディタ開発版(64bit) Ver. 2.4.2.6117 GHA (fe4cc6d17)
(GitHash fe4cc6d17e0e9f0e58f13c6c3cca9147b7751e32)
(GitURL https://github.com/sakura-editor/sakura)

      Compile Info: V_A641940 WPR WIN601/I800/C000/N601
      Last Modified: 2024/7/18 22:27:17
  • PC情報

スクリーンショット

yoshinrt avatar Aug 01 '24 14:08 yoshinrt

試してみましたがこちらでは再現しませんでした。EOF行で実行すると(切り取りするデータが無い為に)Cut() に失敗するので警告音が鳴って Paste() が行われます。

ところでサクラエディタのコピーってレイアウト行に限定したコピーなんですね。VS Codeだとロジック行丸ごとのコピーでした。

beru avatar Aug 02 '24 23:08 beru

サクラエディタ開発当時と現代で「当たり前」の基準が変わってますよね。

::OpenClipboard(hwnd);が成功するまで ::Sleep(0); して数回リトライすべき、の見解です。

(既にどっかに詳細書いた記憶です。)

berryzplus avatar Aug 03 '24 16:08 berryzplus

OpenClipboard は失敗する事が普通にあるんですね、知らなかったです。

https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-openclipboard を読んでみると

OpenClipboard fails if another window has the clipboard open.

と書かれてますね。。

あと検索してヒットした https://groups.google.com/g/scintilla-interest/c/HIuFrgTL8RM?pli=1 には

On Windows the OpenClipboard call, used before reading or writing the clipboard, can fail. This may occur because another application has opened the clipboard. Currently Scintilla fails the Cut/Copy/Paste/… operation when it can not open the clipboard. Normally clipboard operations are driven by the user so do not often overlap. However, sometimes another application such as a clipboard viewer or a virtual machine with a bridged clipboard may be acting on the clipboard in the background. On my main Windows box, it appears that DropBox is causing problems by opening the clipboard when it changes.

It would be possible to retry the OpenClipboard call if it fails. Other APIs, such as the .Net Clipboard.SetDataObject include retry parameters with default behaviour of retrying up to 10 times with a delay between attempts of 100 milliseconds.

  • 他のアプリがクリップボードを開いてると失敗する
  • 通常はクリップボード操作はユーザーが行うので被る事はそんなに無いはずだけど、クリップボードビューワーや仮想マシン、ドロップボックス等のアプリがバックグラウンドで動いていると問題が起きる事がある
  • .NETの Clipboard.SetDataObject にはリトライ用の引数がある。link

というような事が書かれてました。

beru avatar Aug 03 '24 23:08 beru

サクッと対策を実装できそうな感じなのに放置されていたので、Copilotに作業依頼してみました。

関係ないファイルが大量にコミットされているのが気になりますが、修正自体はそれなりにまともな印象です。

berryzplus avatar Aug 26 '25 09:08 berryzplus

対処として作られた #2130 をマージしました。これによって @yoshinrt さんの環境で問題が解消するかは直接観測出来ないので分からないですがいったんこのissueをクローズします。(というか手動でcloseせずともmerge時に既に自動でcloseされていた。。)

beru avatar Nov 09 '25 06:11 beru