sakura
sakura copied to clipboard
マクロの Paste() が失敗する場合がある
問題内容
マクロの 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情報
スクリーンショット
試してみましたがこちらでは再現しませんでした。EOF行で実行すると(切り取りするデータが無い為に)Cut() に失敗するので警告音が鳴って Paste() が行われます。
ところでサクラエディタのコピーってレイアウト行に限定したコピーなんですね。VS Codeだとロジック行丸ごとのコピーでした。
サクラエディタ開発当時と現代で「当たり前」の基準が変わってますよね。
::OpenClipboard(hwnd);が成功するまで ::Sleep(0); して数回リトライすべき、の見解です。
(既にどっかに詳細書いた記憶です。)
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
というような事が書かれてました。
サクッと対策を実装できそうな感じなのに放置されていたので、Copilotに作業依頼してみました。
関係ないファイルが大量にコミットされているのが気になりますが、修正自体はそれなりにまともな印象です。
対処として作られた #2130 をマージしました。これによって @yoshinrt さんの環境で問題が解消するかは直接観測出来ないので分からないですがいったんこのissueをクローズします。(というか手動でcloseせずともmerge時に既に自動でcloseされていた。。)