Kaydet (Commit) a30dbe34 authored tarafından Mike Kaganski's avatar Mike Kaganski

Win: implement Clipboard Format Listener instead of obsolete Viewer

https://docs.microsoft.com/en-us/windows/desktop/dataxchg/using-the-clipboard
discusses the techniques to monitor clipboard contents on Windows, and
recommends Clipboard Format Listener for Vista+.

https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setclipboardviewer
further mentions that using the current "Clipboard Viewer Window" approach,
"The clipboard viewer chain can be broken by an application that fails to
handle the clipboard chain messages properly".

This change reimplements our listener to use recommended way; this
should make our clipboard handling more robust, avoiding the need to
handle the chain with other applications' windows.

Change-Id: Ib33b27a57d7a6af2ab7e3e59d030aa55329694f9
Reviewed-on: https://gerrit.libreoffice.org/62909Reviewed-by: 's avatarMike Kaganski <mike.kaganski@collabora.com>
Tested-by: 's avatarMike Kaganski <mike.kaganski@collabora.com>
üst 994cf675
...@@ -161,7 +161,6 @@ CMtaOleClipboard::CMtaOleClipboard( ) : ...@@ -161,7 +161,6 @@ CMtaOleClipboard::CMtaOleClipboard( ) :
m_hEvtThrdReady( nullptr ), m_hEvtThrdReady( nullptr ),
m_hwndMtaOleReqWnd( nullptr ), m_hwndMtaOleReqWnd( nullptr ),
m_MtaOleReqWndClassAtom( 0 ), m_MtaOleReqWndClassAtom( 0 ),
m_hwndNextClipViewer( nullptr ),
m_pfncClipViewerCallback( nullptr ), m_pfncClipViewerCallback( nullptr ),
m_bRunClipboardNotifierThread( true ), m_bRunClipboardNotifierThread( true ),
m_hClipboardChangedEvent( m_hClipboardChangedNotifierEvents[0] ), m_hClipboardChangedEvent( m_hClipboardChangedNotifierEvents[0] ),
...@@ -238,8 +237,7 @@ CMtaOleClipboard::~CMtaOleClipboard( ) ...@@ -238,8 +237,7 @@ CMtaOleClipboard::~CMtaOleClipboard( )
if ( m_MtaOleReqWndClassAtom ) if ( m_MtaOleReqWndClassAtom )
UnregisterClassW( g_szWndClsName, nullptr ); UnregisterClassW( g_szWndClsName, nullptr );
OSL_ENSURE( ( nullptr == m_pfncClipViewerCallback ) && OSL_ENSURE( ( nullptr == m_pfncClipViewerCallback ),
!IsWindow( m_hwndNextClipViewer ),
"Clipboard viewer not properly unregistered" ); "Clipboard viewer not properly unregistered" );
} }
...@@ -354,7 +352,7 @@ bool CMtaOleClipboard::registerClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipV ...@@ -354,7 +352,7 @@ bool CMtaOleClipboard::registerClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipV
bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback ) bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback )
{ {
bool bRet = true; bool bRet = false;
// we need exclusive access because the clipboard changed notifier // we need exclusive access because the clipboard changed notifier
// thread also accesses this variable // thread also accesses this variable
...@@ -366,13 +364,9 @@ bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncCli ...@@ -366,13 +364,9 @@ bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncCli
// SetClipboardViewer sends a WM_DRAWCLIPBOARD message we ignore // SetClipboardViewer sends a WM_DRAWCLIPBOARD message we ignore
// this message if we register ourself as clip viewer // this message if we register ourself as clip viewer
m_bInRegisterClipViewer = true; m_bInRegisterClipViewer = true;
m_hwndNextClipViewer = SetClipboardViewer( m_hwndMtaOleReqWnd ); bRet = AddClipboardFormatListener(m_hwndMtaOleReqWnd);
m_bInRegisterClipViewer = false; m_bInRegisterClipViewer = false;
// if there is no other cb-viewer the
// return value is NULL!!!
bRet = IsWindow( m_hwndNextClipViewer );
// save the new callback function // save the new callback function
m_pfncClipViewerCallback = pfncClipViewerCallback; m_pfncClipViewerCallback = pfncClipViewerCallback;
} }
...@@ -382,8 +376,7 @@ bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncCli ...@@ -382,8 +376,7 @@ bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncCli
// unregister if input parameter is NULL and we previously registered // unregister if input parameter is NULL and we previously registered
// as clipboard viewer // as clipboard viewer
ChangeClipboardChain( m_hwndMtaOleReqWnd, m_hwndNextClipViewer ); bRet = RemoveClipboardFormatListener(m_hwndMtaOleReqWnd);
m_hwndNextClipViewer = nullptr;
} }
return bRet; return bRet;
...@@ -417,32 +410,9 @@ LRESULT CMtaOleClipboard::onFlushClipboard( ) ...@@ -417,32 +410,9 @@ LRESULT CMtaOleClipboard::onFlushClipboard( )
return static_cast<LRESULT>( OleFlushClipboard( ) ); return static_cast<LRESULT>( OleFlushClipboard( ) );
} }
// handle clipboard chain change event // handle clipboard update event
LRESULT CMtaOleClipboard::onChangeCBChain( HWND hWndRemove, HWND hWndNext ) LRESULT CMtaOleClipboard::onClipboardUpdate()
{
if ( hWndRemove == m_hwndNextClipViewer )
m_hwndNextClipViewer = hWndNext;
else if ( IsWindow( m_hwndNextClipViewer ) )
{
// forward the message to the next one
DWORD_PTR dwpResult;
SendMessageTimeoutW(
m_hwndNextClipViewer,
WM_CHANGECBCHAIN,
reinterpret_cast<WPARAM>(hWndRemove),
reinterpret_cast<LPARAM>(hWndNext),
SMTO_BLOCK,
MAX_CLIPEVENT_PROCESSING_TIME,
&dwpResult );
}
return 0;
}
// handle draw clipboard event
LRESULT CMtaOleClipboard::onDrawClipboard( )
{ {
// we don't send a notification if we are // we don't send a notification if we are
// registering ourself as clipboard // registering ourself as clipboard
...@@ -456,20 +426,6 @@ LRESULT CMtaOleClipboard::onDrawClipboard( ) ...@@ -456,20 +426,6 @@ LRESULT CMtaOleClipboard::onDrawClipboard( )
aGuard.clear( ); aGuard.clear( );
} }
// forward the message to the next viewer in the chain
if ( IsWindow( m_hwndNextClipViewer ) )
{
DWORD_PTR dwpResult;
SendMessageTimeoutW(
m_hwndNextClipViewer,
WM_DRAWCLIPBOARD,
static_cast< WPARAM >( 0 ),
static_cast< LPARAM >( 0 ),
SMTO_BLOCK,
MAX_CLIPEVENT_PROCESSING_TIME,
&dwpResult );
}
return 0; return 0;
} }
...@@ -543,13 +499,8 @@ LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARA ...@@ -543,13 +499,8 @@ LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARA
reinterpret_cast<CMtaOleClipboard::LPFNC_CLIPVIEWER_CALLBACK_t>(wParam)); reinterpret_cast<CMtaOleClipboard::LPFNC_CLIPVIEWER_CALLBACK_t>(wParam));
break; break;
case WM_CHANGECBCHAIN: case WM_CLIPBOARDUPDATE:
lResult = pImpl->onChangeCBChain( lResult = pImpl->onClipboardUpdate();
reinterpret_cast< HWND >( wParam ), reinterpret_cast< HWND >( lParam ) );
break;
case WM_DRAWCLIPBOARD:
lResult = pImpl->onDrawClipboard( );
break; break;
case MSG_SHUTDOWN: case MSG_SHUTDOWN:
......
...@@ -72,9 +72,8 @@ private: ...@@ -72,9 +72,8 @@ private:
static LRESULT onFlushClipboard( ); static LRESULT onFlushClipboard( );
bool onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback ); bool onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback );
// win32 clipboard-viewer support // win32 clipboard listener support
LRESULT onChangeCBChain( HWND hWndRemove, HWND hWndNext ); LRESULT onClipboardUpdate();
LRESULT onDrawClipboard( );
static LRESULT CALLBACK mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static LRESULT CALLBACK mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
static unsigned int WINAPI oleThreadProc( LPVOID pParam ); static unsigned int WINAPI oleThreadProc( LPVOID pParam );
...@@ -89,7 +88,6 @@ private: ...@@ -89,7 +88,6 @@ private:
HANDLE m_hEvtThrdReady; HANDLE m_hEvtThrdReady;
HWND m_hwndMtaOleReqWnd; HWND m_hwndMtaOleReqWnd;
ATOM m_MtaOleReqWndClassAtom; ATOM m_MtaOleReqWndClassAtom;
HWND m_hwndNextClipViewer;
LPFNC_CLIPVIEWER_CALLBACK_t m_pfncClipViewerCallback; LPFNC_CLIPVIEWER_CALLBACK_t m_pfncClipViewerCallback;
bool m_bInRegisterClipViewer; bool m_bInRegisterClipViewer;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment