diff options
-rw-r--r-- | vcl/win/dtrans/MtaOleClipb.cxx | 137 | ||||
-rw-r--r-- | vcl/win/dtrans/MtaOleClipb.hxx | 26 | ||||
-rw-r--r-- | vcl/win/dtrans/WinClipboard.cxx | 24 | ||||
-rw-r--r-- | vcl/win/dtrans/WinClipboard.hxx | 5 |
4 files changed, 36 insertions, 156 deletions
diff --git a/vcl/win/dtrans/MtaOleClipb.cxx b/vcl/win/dtrans/MtaOleClipb.cxx index d894ae7b5a48..7b8b2b637385 100644 --- a/vcl/win/dtrans/MtaOleClipb.cxx +++ b/vcl/win/dtrans/MtaOleClipb.cxx @@ -45,12 +45,7 @@ #include <systools/win32/comtools.hxx> -// namespace directives - -using osl::MutexGuard; -using osl::ClearableMutexGuard; - -namespace /* private */ +namespace { const wchar_t g_szWndClsName[] = L"MtaOleReqWnd###"; @@ -231,12 +226,7 @@ CMtaOleClipboard::CMtaOleClipboard( ) : m_hwndMtaOleReqWnd( nullptr ), // signals that the window is destroyed - to stop waiting any winproc result m_hEvtWndDisposed(CreateEventW(nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr)), - m_MtaOleReqWndClassAtom( 0 ), - m_pfncClipViewerCallback( nullptr ), - m_bRunClipboardNotifierThread( true ), - m_hClipboardChangedEvent( m_hClipboardChangedNotifierEvents[0] ), - m_hTerminateClipboardChangedNotifierEvent( m_hClipboardChangedNotifierEvents[1] ), - m_ClipboardChangedEventCount( 0 ) + m_pfncClipViewerCallback(nullptr) { OSL_ASSERT( nullptr != m_hEvtThrdReady ); SAL_WARN_IF(!m_hEvtWndDisposed, "dtrans", "CreateEventW failed: m_hEvtWndDisposed is nullptr"); @@ -246,20 +236,6 @@ CMtaOleClipboard::CMtaOleClipboard( ) : m_hOleThread = reinterpret_cast<HANDLE>(_beginthreadex( nullptr, 0, CMtaOleClipboard::oleThreadProc, this, 0, &m_uOleThreadId )); OSL_ASSERT( nullptr != m_hOleThread ); - - // setup the clipboard changed notifier thread - - m_hClipboardChangedNotifierEvents[0] = CreateEventW( nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr ); - OSL_ASSERT( nullptr != m_hClipboardChangedNotifierEvents[0] ); - - m_hClipboardChangedNotifierEvents[1] = CreateEventW( nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr ); - OSL_ASSERT( nullptr != m_hClipboardChangedNotifierEvents[1] ); - - unsigned uThreadId; - m_hClipboardChangedNotifierThread = reinterpret_cast<HANDLE>(_beginthreadex( - nullptr, 0, CMtaOleClipboard::clipboardChangedNotifierThreadProc, this, 0, &uThreadId )); - - OSL_ASSERT( nullptr != m_hClipboardChangedNotifierThread ); } // dtor @@ -270,35 +246,13 @@ CMtaOleClipboard::~CMtaOleClipboard( ) if ( nullptr != m_hEvtThrdReady ) ResetEvent( m_hEvtThrdReady ); - // terminate the clipboard changed notifier thread - m_bRunClipboardNotifierThread = false; - SetEvent( m_hTerminateClipboardChangedNotifierEvent ); - - // unblock whoever could still wait for event processing - if (m_hEvtWndDisposed) - SetEvent(m_hEvtWndDisposed); - - sal_uInt32 dwResult = WaitForSingleObject( - m_hClipboardChangedNotifierThread, MAX_WAIT_SHUTDOWN ); - - OSL_ENSURE( dwResult == WAIT_OBJECT_0, "clipboard notifier thread could not terminate" ); - - if ( nullptr != m_hClipboardChangedNotifierThread ) - CloseHandle( m_hClipboardChangedNotifierThread ); - - if ( nullptr != m_hClipboardChangedNotifierEvents[0] ) - CloseHandle( m_hClipboardChangedNotifierEvents[0] ); - - if ( nullptr != m_hClipboardChangedNotifierEvents[1] ) - CloseHandle( m_hClipboardChangedNotifierEvents[1] ); - // end the thread // because DestroyWindow can only be called // from within the thread that created the window sendMessage( MSG_SHUTDOWN ); // wait for thread shutdown - dwResult = WaitForSingleObject( m_hOleThread, MAX_WAIT_SHUTDOWN ); + DWORD dwResult = WaitForSingleObject(m_hOleThread, MAX_WAIT_SHUTDOWN); OSL_ENSURE( dwResult == WAIT_OBJECT_0, "OleThread could not terminate" ); if ( nullptr != m_hOleThread ) @@ -310,9 +264,6 @@ CMtaOleClipboard::~CMtaOleClipboard( ) if (m_hEvtWndDisposed) CloseHandle(m_hEvtWndDisposed); - if ( m_MtaOleReqWndClassAtom ) - UnregisterClassW( g_szWndClsName, nullptr ); - OSL_ENSURE( ( nullptr == m_pfncClipViewerCallback ), "Clipboard viewer not properly unregistered" ); } @@ -348,7 +299,6 @@ HRESULT CMtaOleClipboard::getClipboard( IDataObject** ppIDataObject ) } CAutoComInit comAutoInit; - LPSTREAM lpStream; *ppIDataObject = nullptr; @@ -433,10 +383,6 @@ bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncCli { bool bRet = false; - // we need exclusive access because the clipboard changed notifier - // thread also accesses this variable - MutexGuard aGuard( m_pfncClipViewerCallbackMutex ); - // register if not yet done if ( ( nullptr != pfncClipViewerCallback ) && ( nullptr == m_pfncClipViewerCallback ) ) { @@ -495,14 +441,8 @@ LRESULT CMtaOleClipboard::onClipboardUpdate() { // we don't send a notification if we are // registering ourself as clipboard - if ( !m_bInRegisterClipViewer ) - { - MutexGuard aGuard( m_ClipboardChangedEventCountMutex ); - - m_ClipboardChangedEventCount++; - SetEvent( m_hClipboardChangedEvent ); - } - + if (!m_bInRegisterClipViewer && m_pfncClipViewerCallback) + m_pfncClipViewerCallback(); return 0; } @@ -606,8 +546,11 @@ LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARA return lResult; } -void CMtaOleClipboard::createMtaOleReqWnd( ) +unsigned int CMtaOleClipboard::run() { + HRESULT hr = OleInitialize(nullptr); + OSL_ASSERT(SUCCEEDED(hr)); + WNDCLASSEXW wcex; SalData* pSalData = GetSalData(); @@ -628,19 +571,11 @@ void CMtaOleClipboard::createMtaOleReqWnd( ) wcex.lpszClassName = g_szWndClsName; wcex.hIconSm = nullptr; - m_MtaOleReqWndClassAtom = RegisterClassExW( &wcex ); + ATOM aMtaOleReqWndClassAtom = RegisterClassExW(&wcex); - if ( 0 != m_MtaOleReqWndClassAtom ) + if (0 != aMtaOleReqWndClassAtom) m_hwndMtaOleReqWnd = CreateWindowW( g_szWndClsName, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, pSalData->mhInst, nullptr ); -} - -unsigned int CMtaOleClipboard::run( ) -{ - HRESULT hr = OleInitialize( nullptr ); - OSL_ASSERT( SUCCEEDED( hr ) ); - - createMtaOleReqWnd( ); unsigned int nRet; @@ -659,6 +594,9 @@ unsigned int CMtaOleClipboard::run( ) else nRet = ~0U; + if (aMtaOleReqWndClassAtom) + UnregisterClassW(g_szWndClsName, nullptr); + OleUninitialize( ); return nRet; @@ -675,53 +613,6 @@ unsigned int WINAPI CMtaOleClipboard::oleThreadProc( LPVOID pParam ) return pInst->run( ); } -unsigned int WINAPI CMtaOleClipboard::clipboardChangedNotifierThreadProc( LPVOID pParam ) -{ - osl_setThreadName("CMtaOleClipboard::clipboardChangedNotifierThreadProc()"); - CMtaOleClipboard* pInst = static_cast< CMtaOleClipboard* >( pParam ); - OSL_ASSERT( nullptr != pInst ); - - CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ); - - // assuming we don't need a lock for - // a boolean variable like m_bRun... - while ( pInst->m_bRunClipboardNotifierThread ) - { - // process window messages because of CoInitializeEx - MSG Msg; - while (PeekMessageW(&Msg, nullptr, 0, 0, PM_REMOVE)) - DispatchMessageW(&Msg); - - // wait for clipboard changed or terminate event - MsgWaitForMultipleObjects(2, pInst->m_hClipboardChangedNotifierEvents, false, INFINITE, - QS_ALLINPUT | QS_ALLPOSTMESSAGE); - - ClearableMutexGuard aGuard( pInst->m_ClipboardChangedEventCountMutex ); - - if ( pInst->m_ClipboardChangedEventCount > 0 ) - { - pInst->m_ClipboardChangedEventCount--; - if ( 0 == pInst->m_ClipboardChangedEventCount ) - ResetEvent( pInst->m_hClipboardChangedEvent ); - - aGuard.clear( ); - - // nobody should touch m_pfncClipViewerCallback while we do - MutexGuard aClipViewerGuard( pInst->m_pfncClipViewerCallbackMutex ); - - // notify all clipboard listener - if ( pInst->m_pfncClipViewerCallback ) - pInst->m_pfncClipViewerCallback( ); - } - else - aGuard.clear( ); - } - - CoUninitialize( ); - - return 0; -} - bool CMtaOleClipboard::WaitForThreadReady( ) const { bool bRet = false; diff --git a/vcl/win/dtrans/MtaOleClipb.hxx b/vcl/win/dtrans/MtaOleClipb.hxx index c406f81aafd3..d0dd539d46a5 100644 --- a/vcl/win/dtrans/MtaOleClipb.hxx +++ b/vcl/win/dtrans/MtaOleClipb.hxx @@ -20,7 +20,6 @@ #pragma once #include <sal/types.h> -#include <osl/mutex.hxx> #include <objidl.h> @@ -31,12 +30,14 @@ // only from within the clipboard service and the methods // of the clipboard service are already synchronized +// Its thread creates a hidden window, which serves as a request target, so we +// can guarantee synchronization. + class CMtaOleClipboard { public: typedef void ( WINAPI *LPFNC_CLIPVIEWER_CALLBACK_t )( void ); -public: CMtaOleClipboard( ); ~CMtaOleClipboard( ); @@ -55,17 +56,12 @@ public: private: unsigned int run( ); - // create a hidden window which serves as a request target; so we - // guarantee synchronization - void createMtaOleReqWnd( ); - // message support bool postMessage( UINT msg, WPARAM wParam = 0, LPARAM lParam = 0 ); LRESULT sendMessage( UINT msg, WPARAM wParam = 0, LPARAM lParam = 0 ); // message handler functions; remember these functions are called // from a different thread context! - static HRESULT onSetClipboard( IDataObject* pIDataObject ); static HRESULT onGetClipboard( LPSTREAM* ppStream ); static HRESULT onFlushClipboard( ); @@ -77,34 +73,18 @@ private: static LRESULT CALLBACK mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static unsigned int WINAPI oleThreadProc( LPVOID pParam ); - static unsigned int WINAPI clipboardChangedNotifierThreadProc( LPVOID pParam ); - bool WaitForThreadReady( ) const; -private: HANDLE m_hOleThread; unsigned m_uOleThreadId; HANDLE m_hEvtThrdReady; HWND m_hwndMtaOleReqWnd; HANDLE m_hEvtWndDisposed; - ATOM m_MtaOleReqWndClassAtom; LPFNC_CLIPVIEWER_CALLBACK_t m_pfncClipViewerCallback; bool m_bInRegisterClipViewer; - bool m_bRunClipboardNotifierThread; - HANDLE m_hClipboardChangedNotifierThread; - HANDLE m_hClipboardChangedNotifierEvents[2]; - HANDLE& m_hClipboardChangedEvent; - HANDLE& m_hTerminateClipboardChangedNotifierEvent; - osl::Mutex m_ClipboardChangedEventCountMutex; - sal_Int32 m_ClipboardChangedEventCount; - - osl::Mutex m_pfncClipViewerCallbackMutex; - static CMtaOleClipboard* s_theMtaOleClipboardInst; -// not allowed -private: CMtaOleClipboard( const CMtaOleClipboard& ); CMtaOleClipboard& operator=( const CMtaOleClipboard& ); diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx index f50c1810f4ea..121b945ff4e9 100644 --- a/vcl/win/dtrans/WinClipboard.cxx +++ b/vcl/win/dtrans/WinClipboard.cxx @@ -63,6 +63,11 @@ CWinClipboard::CWinClipboard(const uno::Reference<uno::XComponentContext>& rxCon // the static callback function s_pCWinClipbImpl = this; registerClipboardViewer(); + + m_aNotifyClipboardChangeIdle.SetDebugName("CWinClipboard::m_aNotifyClipboardChangeIdle"); + m_aNotifyClipboardChangeIdle.SetPriority(TaskPriority::HIGH_IDLE); + m_aNotifyClipboardChangeIdle.SetInvokeHandler( + LINK(this, CWinClipboard, ClipboardContentChangedHdl)); } CWinClipboard::~CWinClipboard() @@ -236,8 +241,10 @@ void SAL_CALL CWinClipboard::removeClipboardListener( rBHelper.aLC.removeInterface(cppu::UnoType<decltype(listener)>::get(), listener); } -void CWinClipboard::notifyAllClipboardListener() +IMPL_LINK_NOARG(CWinClipboard, ClipboardContentChangedHdl, Timer*, void) { + m_foreignContent.clear(); + if (rBHelper.bDisposed) return; @@ -323,21 +330,20 @@ void CWinClipboard::onReleaseDataObject(CXNotifyingDataObject* theCaller) void CWinClipboard::registerClipboardViewer() { - m_MtaOleClipboard.registerClipViewer(CWinClipboard::onClipboardContentChanged); + m_MtaOleClipboard.registerClipViewer(CWinClipboard::onWM_CLIPBOARDUPDATE); } void CWinClipboard::unregisterClipboardViewer() { m_MtaOleClipboard.registerClipViewer(nullptr); } -void WINAPI CWinClipboard::onClipboardContentChanged() +void WINAPI CWinClipboard::onWM_CLIPBOARDUPDATE() { osl::MutexGuard aGuard(s_aMutex); - // reassociation to instance through static member - if (nullptr != s_pCWinClipbImpl) - { - s_pCWinClipbImpl->m_foreignContent.clear(); - s_pCWinClipbImpl->notifyAllClipboardListener(); - } + if (!s_pCWinClipbImpl) + return; + + if (!s_pCWinClipbImpl->m_aNotifyClipboardChangeIdle.IsActive()) + s_pCWinClipbImpl->m_aNotifyClipboardChangeIdle.Start(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/win/dtrans/WinClipboard.hxx b/vcl/win/dtrans/WinClipboard.hxx index 1b0a05a3450d..06bcdce0fc64 100644 --- a/vcl/win/dtrans/WinClipboard.hxx +++ b/vcl/win/dtrans/WinClipboard.hxx @@ -32,6 +32,7 @@ #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <osl/conditn.hxx> +#include <vcl/Idle.hxx> #include "MtaOleClipb.hxx" @@ -70,6 +71,7 @@ class CWinClipboard final CXNotifyingDataObject* m_pCurrentClipContent; com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable> m_foreignContent; osl::Mutex m_ClipContentMutex; + Idle m_aNotifyClipboardChangeIdle; static osl::Mutex s_aMutex; static CWinClipboard* s_pCWinClipbImpl; @@ -80,7 +82,8 @@ class CWinClipboard final void registerClipboardViewer(); void unregisterClipboardViewer(); - static void WINAPI onClipboardContentChanged(); + static void WINAPI onWM_CLIPBOARDUPDATE(); + DECL_DLLPRIVATE_LINK(ClipboardContentChangedHdl, Timer*, void); public: CWinClipboard(const css::uno::Reference<css::uno::XComponentContext>& rxContext, |