aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2016-02-23 11:17:05 +1100
committerNeil <nyamatongwe@gmail.com>2016-02-23 11:17:05 +1100
commite5a27cf16a0144a534ff07905380af5eedbbb76b (patch)
treee69c721389467400ac1b88d86d67426b82342114
parentfe0d39ee1c34dfeada9909af44646ce43f0ef226 (diff)
downloadscintilla-mirror-e5a27cf16a0144a534ff07905380af5eedbbb76b.tar.gz
Retry OpenClipboard if it fails as another application may have opened it.
-rw-r--r--doc/ScintillaHistory.html4
-rw-r--r--test/simpleTests.py7
-rw-r--r--win32/ScintillaWin.cxx21
3 files changed, 27 insertions, 5 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 6bdcb1e5d..1c5f2f356 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -538,6 +538,10 @@
<li>
IME target range displayed on Qt for OS X.
</li>
+ <li>
+ On Windows, make clipboard operations more robust by retrying OpenClipboard if it fails
+ as this may occur when another application has opened the clipboard.
+ </li>
</ul>
<h3>
<a href="http://www.scintilla.org/scite363.zip">Release 3.6.3</a>
diff --git a/test/simpleTests.py b/test/simpleTests.py
index c7240b269..62243dd49 100644
--- a/test/simpleTests.py
+++ b/test/simpleTests.py
@@ -493,13 +493,15 @@ class TestSimple(unittest.TestCase):
self.ed.AddText(5, b"a1b2c")
self.ed.SetSel(1,3)
self.ed.Cut()
- self.xite.DoEvents()
+ # Clipboard = "1b"
+ self.assertEquals(self.ed.Contents(), b"a2c")
self.assertEquals(self.ed.CanPaste(), 1)
self.ed.SetSel(0, 0)
self.ed.Paste()
self.assertEquals(self.ed.Contents(), b"1ba2c")
self.ed.SetSel(4,5)
self.ed.Copy()
+ # Clipboard = "c"
self.ed.SetSel(1,3)
self.ed.Paste()
self.assertEquals(self.ed.Contents(), b"1c2c")
@@ -508,13 +510,12 @@ class TestSimple(unittest.TestCase):
self.assertEquals(self.ed.Contents(), b"1c")
def testCopyAllowLine(self):
- self.xite.DoEvents()
lineEndType = self.ed.EOLMode
self.ed.EOLMode = self.ed.SC_EOL_LF
self.ed.AddText(5, b"a1\nb2")
self.ed.SetSel(1,1)
self.ed.CopyAllowLine()
- self.xite.DoEvents()
+ # Clipboard = "a1\n"
self.assertEquals(self.ed.CanPaste(), 1)
self.ed.SetSel(0, 0)
self.ed.Paste()
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index c9a712df2..2e9cce34a 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -2184,9 +2184,25 @@ public:
}
};
+// OpenClipboard may fail if another application has opened the clipboard.
+// Try up to 8 times, with an initial delay of 1 ms and an exponential back off
+// for a maximum total delay of 127 ms (1+2+4+8+16+32+64).
+static bool OpenClipboardRetry(HWND hwnd) {
+ for (int attempt=0; attempt<8; attempt++) {
+ if (attempt > 0) {
+ ::Sleep(1 << (attempt-1));
+ }
+ if (::OpenClipboard(hwnd)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void ScintillaWin::Paste() {
- if (!::OpenClipboard(MainHWND()))
+ if (!::OpenClipboardRetry(MainHWND())) {
return;
+ }
UndoGroup ug(pdoc);
const bool isLine = SelectionEmpty() &&
(::IsClipboardFormatAvailable(cfLineSelect) || ::IsClipboardFormatAvailable(cfVSLineTag));
@@ -2737,8 +2753,9 @@ void ScintillaWin::GetIntelliMouseParameters() {
}
void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
- if (!::OpenClipboard(MainHWND()))
+ if (!::OpenClipboardRetry(MainHWND())) {
return;
+ }
::EmptyClipboard();
GlobalMemory uniText;