summaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2018-12-30 12:56:29 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2018-12-30 12:33:33 +0100
commit485d2df7d574f721adfe887433a79d8ae98becda (patch)
treec485e466663d046ce88b3c101d3b75874aa664a7 /extensions
parent9bdc1118c7b7fe10529b3320daa278f108e8f2c3 (diff)
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.kaganski@collabora.com>
Diffstat (limited to 'extensions')
-rw-r--r--extensions/source/scanner/scanwin.cxx106
1 files changed, 67 insertions, 39 deletions
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);