extensions/source/scanner/scanwin.cxx | 106 +++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 39 deletions(-)
New commits: commit 485d2df7d574f721adfe887433a79d8ae98becda Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Dec 30 12:56:29 2018 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Dec 30 12:33:33 2018 +0100 tdf#42075: Perform scan after selecting a scanner on Windows On Windows, we use dialogs provided by system TWAIN DSM. We can't add a "Scan" button to the "Select source" dialog; but it's reasonable to assume that user would select a scanner to scan, so let's proceed to scan when user confirms selection in the dialog. Change-Id: Ic49b1ce914db65221d52d9378369afa5278d95d1 Reviewed-on: https://gerrit.libreoffice.org/65736 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/extensions/source/scanner/scanwin.cxx b/extensions/source/scanner/scanwin.cxx index 24068e12b1ee..9370f69b2105 100644 --- a/extensions/source/scanner/scanwin.cxx +++ b/extensions/source/scanner/scanwin.cxx @@ -24,6 +24,7 @@ #include "twain32shim.hxx" #include <comphelper/processfactory.hxx> +#include <comphelper/scopeguard.hxx> #include <config_folders.h> #include <o3tl/char16_t2wchar_t.hxx> #include <osl/conditn.hxx> @@ -63,9 +64,11 @@ public: Twain(); ~Twain(); - bool SelectSource(ScannerManager& rMgr); + bool SelectSource(ScannerManager& rMgr, const VclPtr<vcl::Window>& xTopWindow); bool PerformTransfer(ScannerManager& rMgr, - const css::uno::Reference<css::lang::XEventListener>& rxListener); + const css::uno::Reference<css::lang::XEventListener>& rxListener, + const VclPtr<vcl::Window>& xTopWindow); + void WaitReadyForNextTask(); TwainState GetState() const { return meState; } @@ -74,7 +77,7 @@ private: class ShimListenerThread : public salhelper::Thread { public: - ShimListenerThread(); + ShimListenerThread(const VclPtr<vcl::Window>& xTopWindow); ~ShimListenerThread() override; void execute() override; const OUString& getError() { return msErrorReported; } @@ -115,40 +118,20 @@ private: void Notify(WPARAM nEvent); // called by shim communication thread to notify me void NotifyXFer(LPARAM nHandle); // called by shim communication thread to notify me - bool InitializeNewShim(ScannerManager& rMgr); + bool InitializeNewShim(ScannerManager& rMgr, const VclPtr<vcl::Window>& xTopWindow); void Reset(); // cleanup thread and manager }; static Twain aTwain; -css::uno::Reference<css::frame::XFrame> ImplGetActiveFrame() -{ - try - { - // query desktop instance - css::uno::Reference<css::frame::XDesktop2> xDesktop - = css::frame::Desktop::create(comphelper::getProcessComponentContext()); - if (css::uno::Reference<css::frame::XFrame> xActiveFrame = xDesktop->getActiveFrame()) - return xActiveFrame; - } - catch (const css::uno::Exception&) - { - } - SAL_WARN("extensions.scanner", "ImplGetActiveFrame: Could not determine active frame!"); - return css::uno::Reference<css::frame::XFrame>(); -} - -Twain::ShimListenerThread::ShimListenerThread() +Twain::ShimListenerThread::ShimListenerThread(const VclPtr<vcl::Window>& xTopWindow) : salhelper::Thread("TWAINShimListenerThread") + , mxTopWindow(xTopWindow) { - if (css::uno::Reference<css::frame::XFrame> xTopFrame = ImplGetActiveFrame()) + if (mxTopWindow) { - mxTopWindow = VCLUnoHelper::GetWindow(xTopFrame->getComponentWindow()); - if (mxTopWindow) - { - mxTopWindow->IncModalCount(); // the operation is modal to the frame - } + mxTopWindow->IncModalCount(); // the operation is modal to the frame } } @@ -349,7 +332,7 @@ void Twain::Reset() mxMgr.clear(); } -bool Twain::InitializeNewShim(ScannerManager& rMgr) +bool Twain::InitializeNewShim(ScannerManager& rMgr, const VclPtr<vcl::Window>& xTopWindow) { osl::MutexGuard aGuard(maMutex); if (mpThread) @@ -359,7 +342,7 @@ bool Twain::InitializeNewShim(ScannerManager& rMgr) mxMgr.set(static_cast<OWeakObject*>(const_cast<ScannerManager*>(mpCurMgr = &rMgr)), css::uno::UNO_QUERY); - mpThread.set(new ShimListenerThread()); + mpThread.set(new ShimListenerThread(xTopWindow)); mpThread->launch(); const bool bSuccess = mpThread->WaitInitialization(); if (!bSuccess) @@ -379,12 +362,12 @@ void Twain::NotifyXFer(LPARAM nHandle) reinterpret_cast<void*>(nHandle)); } -bool Twain::SelectSource(ScannerManager& rMgr) +bool Twain::SelectSource(ScannerManager& rMgr, const VclPtr<vcl::Window>& xTopWindow) { osl::MutexGuard aGuard(maMutex); bool bRet = false; - if (InitializeNewShim(rMgr)) + if (InitializeNewShim(rMgr, xTopWindow)) { meState = TWAIN_STATE_NONE; bRet = mpThread->RequestSelectSource(); @@ -394,12 +377,13 @@ bool Twain::SelectSource(ScannerManager& rMgr) } bool Twain::PerformTransfer(ScannerManager& rMgr, - const css::uno::Reference<css::lang::XEventListener>& rxListener) + const css::uno::Reference<css::lang::XEventListener>& rxListener, + const VclPtr<vcl::Window>& xTopWindow) { osl::MutexGuard aGuard(maMutex); bool bRet = false; - if (InitializeNewShim(rMgr)) + if (InitializeNewShim(rMgr, xTopWindow)) { mxListener = rxListener; meState = TWAIN_STATE_NONE; @@ -409,6 +393,17 @@ bool Twain::PerformTransfer(ScannerManager& rMgr, return bRet; } +void Twain::WaitReadyForNextTask() +{ + while ([&]() { + osl::MutexGuard aGuard(maMutex); + return bool(mpThread); + }()) + { + Application::Reschedule(true); + } +} + IMPL_LINK(Twain, ImpNotifyHdl, void*, pParam, void) { osl::MutexGuard aGuard(maMutex); @@ -461,6 +456,23 @@ IMPL_LINK(Twain, ImpNotifyXferHdl, void*, pParam, void) mxListener.clear(); } +VclPtr<vcl::Window> ImplGetActiveFrameWindow() +{ + try + { + // query desktop instance + css::uno::Reference<css::frame::XDesktop2> xDesktop + = css::frame::Desktop::create(comphelper::getProcessComponentContext()); + if (css::uno::Reference<css::frame::XFrame> xActiveFrame = xDesktop->getActiveFrame()) + return VCLUnoHelper::GetWindow(xActiveFrame->getComponentWindow()); + } + catch (const css::uno::Exception&) + { + } + SAL_WARN("extensions.scanner", "ImplGetActiveFrame: Could not determine active frame!"); + return nullptr; +} + } // namespace void ScannerManager::AcquireData() {} @@ -568,7 +580,7 @@ css::uno::Sequence<ScannerContext> SAL_CALL ScannerManager::getAvailableScanners } sal_Bool SAL_CALL ScannerManager::configureScannerAndScan( - ScannerContext& rContext, const css::uno::Reference<css::lang::XEventListener>&) + ScannerContext& rContext, const css::uno::Reference<css::lang::XEventListener>& rxListener) { osl::MutexGuard aGuard(maProtector); css::uno::Reference<XScannerManager> xThis(this); @@ -578,10 +590,26 @@ sal_Bool SAL_CALL ScannerManager::configureScannerAndScan( ReleaseData(); - return aTwain.SelectSource(*this); + VclPtr<vcl::Window> xTopWindow = ImplGetActiveFrameWindow(); + if (xTopWindow) + xTopWindow->IncModalCount(); // to avoid changes between the two operations that each + // block the window + comphelper::ScopeGuard aModalGuard([xTopWindow]() { + if (xTopWindow) + xTopWindow->DecModalCount(); + }); + + const bool bSelected = aTwain.SelectSource(*this, xTopWindow); + if (bSelected) + { + aTwain.WaitReadyForNextTask(); + aTwain.PerformTransfer(*this, rxListener, xTopWindow); + } + return bSelected; } -void SAL_CALL ScannerManager::startScan(const ScannerContext& rContext, +void SAL_CALL +ScannerManager::startScan(const ScannerContext& rContext, const css::uno::Reference<css::lang::XEventListener>& rxListener) { osl::MutexGuard aGuard(maProtector); @@ -591,7 +619,7 @@ void SAL_CALL ScannerManager::startScan(const ScannerContext& rContext, throw ScannerException("Scanner does not exist", xThis, ScanError_InvalidContext); ReleaseData(); - aTwain.PerformTransfer(*this, rxListener); + aTwain.PerformTransfer(*this, rxListener, ImplGetActiveFrameWindow()); } ScanError SAL_CALL ScannerManager::getError(const ScannerContext& rContext) @@ -606,7 +634,7 @@ ScanError SAL_CALL ScannerManager::getError(const ScannerContext& rContext) : ScanError_ScanErrorNone); } - css::uno::Reference<css::awt::XBitmap> +css::uno::Reference<css::awt::XBitmap> SAL_CALL ScannerManager::getBitmap(const ScannerContext& /*rContext*/) { osl::MutexGuard aGuard(maProtector); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits