feat: Windows, Use a clipboard format listener to monitor the clipboard
On Windows monitor the clipboard using a Clipboard format listener instead of the legacy clipboard viewer chain, which was unreliable as it required other programs to maintain the clipboard chain properly and couldn't recover it any window in the clipboard viewer chain stopped responding to messages. Monitor the clipboard sequence number to not process the clipboard more than once.
This commit is contained in:
parent
5026eea60a
commit
252d11a316
2 changed files with 21 additions and 23 deletions
|
|
@ -119,7 +119,7 @@ MSWindowsScreen::MSWindowsScreen(
|
||||||
m_screensaverNotify(false),
|
m_screensaverNotify(false),
|
||||||
m_screensaverActive(false),
|
m_screensaverActive(false),
|
||||||
m_window(NULL),
|
m_window(NULL),
|
||||||
m_nextClipboardWindow(NULL),
|
m_clipboardSequenceNumber(0),
|
||||||
m_ownClipboard(false),
|
m_ownClipboard(false),
|
||||||
m_desks(NULL),
|
m_desks(NULL),
|
||||||
m_keyState(NULL),
|
m_keyState(NULL),
|
||||||
|
|
@ -237,7 +237,9 @@ void MSWindowsScreen::enable()
|
||||||
);
|
);
|
||||||
|
|
||||||
// install our clipboard snooper
|
// install our clipboard snooper
|
||||||
m_nextClipboardWindow = SetClipboardViewer(m_window);
|
if (!AddClipboardFormatListener(m_window)) {
|
||||||
|
LOG((CLOG_DEBUG "failed to add the clipboard format listener: %d", GetLastError()));
|
||||||
|
}
|
||||||
|
|
||||||
// track the active desk and (re)install the hooks
|
// track the active desk and (re)install the hooks
|
||||||
m_desks->enable();
|
m_desks->enable();
|
||||||
|
|
@ -268,8 +270,9 @@ void MSWindowsScreen::disable()
|
||||||
m_keyState->disable();
|
m_keyState->disable();
|
||||||
|
|
||||||
// stop snooping the clipboard
|
// stop snooping the clipboard
|
||||||
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
if (!RemoveClipboardFormatListener(m_window)) {
|
||||||
m_nextClipboardWindow = NULL;
|
LOG((CLOG_DEBUG "failed to remove the clipboard format listener: %d", GetLastError()));
|
||||||
|
}
|
||||||
|
|
||||||
// uninstall fix timer
|
// uninstall fix timer
|
||||||
if (m_fixTimer != NULL) {
|
if (m_fixTimer != NULL) {
|
||||||
|
|
@ -1021,23 +1024,20 @@ bool MSWindowsScreen::onPreDispatchPrimary(HWND, UINT message, WPARAM wParam, LP
|
||||||
bool MSWindowsScreen::onEvent(HWND, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
bool MSWindowsScreen::onEvent(HWND, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||||
{
|
{
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case WM_DRAWCLIPBOARD:
|
|
||||||
// first pass on the message
|
|
||||||
if (m_nextClipboardWindow != NULL) {
|
|
||||||
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now handle the message
|
case WM_CLIPBOARDUPDATE: {
|
||||||
return onClipboardChange();
|
DWORD clipboardSequenceNumber = GetClipboardSequenceNumber();
|
||||||
|
LOG(
|
||||||
|
(CLOG_DEBUG "clipboard update: sequence number %d, current %d", clipboardSequenceNumber,
|
||||||
|
m_clipboardSequenceNumber)
|
||||||
|
);
|
||||||
|
|
||||||
case WM_CHANGECBCHAIN:
|
if (clipboardSequenceNumber && (clipboardSequenceNumber != m_clipboardSequenceNumber)) {
|
||||||
if (m_nextClipboardWindow == (HWND)wParam) {
|
m_clipboardSequenceNumber = clipboardSequenceNumber;
|
||||||
m_nextClipboardWindow = (HWND)lParam;
|
onClipboardChange();
|
||||||
LOG((CLOG_DEBUG "clipboard chain: new next: 0x%08x", m_nextClipboardWindow));
|
|
||||||
} else if (m_nextClipboardWindow != NULL) {
|
|
||||||
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
|
|
||||||
}
|
}
|
||||||
return true;
|
return 0; // message processed
|
||||||
|
}
|
||||||
|
|
||||||
case WM_DISPLAYCHANGE:
|
case WM_DISPLAYCHANGE:
|
||||||
return onDisplayChange();
|
return onDisplayChange();
|
||||||
|
|
@ -1430,7 +1430,7 @@ bool MSWindowsScreen::onDisplayChange()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MSWindowsScreen::onClipboardChange()
|
void MSWindowsScreen::onClipboardChange()
|
||||||
{
|
{
|
||||||
// now notify client that somebody changed the clipboard (unless
|
// now notify client that somebody changed the clipboard (unless
|
||||||
// we're the owner).
|
// we're the owner).
|
||||||
|
|
@ -1445,8 +1445,6 @@ bool MSWindowsScreen::onClipboardChange()
|
||||||
LOG((CLOG_DEBUG "clipboard changed: %s owned", kAppId));
|
LOG((CLOG_DEBUG "clipboard changed: %s owned", kAppId));
|
||||||
m_ownClipboard = true;
|
m_ownClipboard = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
|
void MSWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ private: // HACK
|
||||||
bool onMouseWheel(SInt32 xDelta, SInt32 yDelta);
|
bool onMouseWheel(SInt32 xDelta, SInt32 yDelta);
|
||||||
bool onScreensaver(bool activated);
|
bool onScreensaver(bool activated);
|
||||||
bool onDisplayChange();
|
bool onDisplayChange();
|
||||||
bool onClipboardChange();
|
void onClipboardChange();
|
||||||
|
|
||||||
// warp cursor without discarding queued events
|
// warp cursor without discarding queued events
|
||||||
void warpCursorNoFlush(SInt32 x, SInt32 y);
|
void warpCursorNoFlush(SInt32 x, SInt32 y);
|
||||||
|
|
@ -314,7 +314,7 @@ private:
|
||||||
// clipboard stuff. our window is used mainly as a clipboard
|
// clipboard stuff. our window is used mainly as a clipboard
|
||||||
// owner and as a link in the clipboard viewer chain.
|
// owner and as a link in the clipboard viewer chain.
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
HWND m_nextClipboardWindow;
|
DWORD m_clipboardSequenceNumber;
|
||||||
bool m_ownClipboard;
|
bool m_ownClipboard;
|
||||||
|
|
||||||
// one desk per desktop and a cond var to communicate with it
|
// one desk per desktop and a cond var to communicate with it
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue