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

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: 's avatarMike Kaganski <mike.kaganski@collabora.com>
üst 9bdc1118
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "twain32shim.hxx" #include "twain32shim.hxx"
#include <comphelper/processfactory.hxx> #include <comphelper/processfactory.hxx>
#include <comphelper/scopeguard.hxx>
#include <config_folders.h> #include <config_folders.h>
#include <o3tl/char16_t2wchar_t.hxx> #include <o3tl/char16_t2wchar_t.hxx>
#include <osl/conditn.hxx> #include <osl/conditn.hxx>
...@@ -63,9 +64,11 @@ public: ...@@ -63,9 +64,11 @@ public:
Twain(); Twain();
~Twain(); ~Twain();
bool SelectSource(ScannerManager& rMgr); bool SelectSource(ScannerManager& rMgr, const VclPtr<vcl::Window>& xTopWindow);
bool PerformTransfer(ScannerManager& rMgr, 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; } TwainState GetState() const { return meState; }
...@@ -74,7 +77,7 @@ private: ...@@ -74,7 +77,7 @@ private:
class ShimListenerThread : public salhelper::Thread class ShimListenerThread : public salhelper::Thread
{ {
public: public:
ShimListenerThread(); ShimListenerThread(const VclPtr<vcl::Window>& xTopWindow);
~ShimListenerThread() override; ~ShimListenerThread() override;
void execute() override; void execute() override;
const OUString& getError() { return msErrorReported; } const OUString& getError() { return msErrorReported; }
...@@ -115,40 +118,20 @@ private: ...@@ -115,40 +118,20 @@ private:
void Notify(WPARAM nEvent); // called by shim communication thread to notify me void Notify(WPARAM nEvent); // called by shim communication thread to notify me
void NotifyXFer(LPARAM nHandle); // 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 void Reset(); // cleanup thread and manager
}; };
static Twain aTwain; static Twain aTwain;
css::uno::Reference<css::frame::XFrame> ImplGetActiveFrame() Twain::ShimListenerThread::ShimListenerThread(const VclPtr<vcl::Window>& xTopWindow)
{
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()
: salhelper::Thread("TWAINShimListenerThread") : salhelper::Thread("TWAINShimListenerThread")
, mxTopWindow(xTopWindow)
{ {
if (css::uno::Reference<css::frame::XFrame> xTopFrame = ImplGetActiveFrame()) if (mxTopWindow)
{ {
mxTopWindow = VCLUnoHelper::GetWindow(xTopFrame->getComponentWindow()); mxTopWindow->IncModalCount(); // the operation is modal to the frame
if (mxTopWindow)
{
mxTopWindow->IncModalCount(); // the operation is modal to the frame
}
} }
} }
...@@ -349,7 +332,7 @@ void Twain::Reset() ...@@ -349,7 +332,7 @@ void Twain::Reset()
mxMgr.clear(); mxMgr.clear();
} }
bool Twain::InitializeNewShim(ScannerManager& rMgr) bool Twain::InitializeNewShim(ScannerManager& rMgr, const VclPtr<vcl::Window>& xTopWindow)
{ {
osl::MutexGuard aGuard(maMutex); osl::MutexGuard aGuard(maMutex);
if (mpThread) if (mpThread)
...@@ -359,7 +342,7 @@ bool Twain::InitializeNewShim(ScannerManager& rMgr) ...@@ -359,7 +342,7 @@ bool Twain::InitializeNewShim(ScannerManager& rMgr)
mxMgr.set(static_cast<OWeakObject*>(const_cast<ScannerManager*>(mpCurMgr = &rMgr)), mxMgr.set(static_cast<OWeakObject*>(const_cast<ScannerManager*>(mpCurMgr = &rMgr)),
css::uno::UNO_QUERY); css::uno::UNO_QUERY);
mpThread.set(new ShimListenerThread()); mpThread.set(new ShimListenerThread(xTopWindow));
mpThread->launch(); mpThread->launch();
const bool bSuccess = mpThread->WaitInitialization(); const bool bSuccess = mpThread->WaitInitialization();
if (!bSuccess) if (!bSuccess)
...@@ -379,12 +362,12 @@ void Twain::NotifyXFer(LPARAM nHandle) ...@@ -379,12 +362,12 @@ void Twain::NotifyXFer(LPARAM nHandle)
reinterpret_cast<void*>(nHandle)); reinterpret_cast<void*>(nHandle));
} }
bool Twain::SelectSource(ScannerManager& rMgr) bool Twain::SelectSource(ScannerManager& rMgr, const VclPtr<vcl::Window>& xTopWindow)
{ {
osl::MutexGuard aGuard(maMutex); osl::MutexGuard aGuard(maMutex);
bool bRet = false; bool bRet = false;
if (InitializeNewShim(rMgr)) if (InitializeNewShim(rMgr, xTopWindow))
{ {
meState = TWAIN_STATE_NONE; meState = TWAIN_STATE_NONE;
bRet = mpThread->RequestSelectSource(); bRet = mpThread->RequestSelectSource();
...@@ -394,12 +377,13 @@ bool Twain::SelectSource(ScannerManager& rMgr) ...@@ -394,12 +377,13 @@ bool Twain::SelectSource(ScannerManager& rMgr)
} }
bool Twain::PerformTransfer(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); osl::MutexGuard aGuard(maMutex);
bool bRet = false; bool bRet = false;
if (InitializeNewShim(rMgr)) if (InitializeNewShim(rMgr, xTopWindow))
{ {
mxListener = rxListener; mxListener = rxListener;
meState = TWAIN_STATE_NONE; meState = TWAIN_STATE_NONE;
...@@ -409,6 +393,17 @@ bool Twain::PerformTransfer(ScannerManager& rMgr, ...@@ -409,6 +393,17 @@ bool Twain::PerformTransfer(ScannerManager& rMgr,
return bRet; return bRet;
} }
void Twain::WaitReadyForNextTask()
{
while ([&]() {
osl::MutexGuard aGuard(maMutex);
return bool(mpThread);
}())
{
Application::Reschedule(true);
}
}
IMPL_LINK(Twain, ImpNotifyHdl, void*, pParam, void) IMPL_LINK(Twain, ImpNotifyHdl, void*, pParam, void)
{ {
osl::MutexGuard aGuard(maMutex); osl::MutexGuard aGuard(maMutex);
...@@ -461,6 +456,23 @@ IMPL_LINK(Twain, ImpNotifyXferHdl, void*, pParam, void) ...@@ -461,6 +456,23 @@ IMPL_LINK(Twain, ImpNotifyXferHdl, void*, pParam, void)
mxListener.clear(); 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 } // namespace
void ScannerManager::AcquireData() {} void ScannerManager::AcquireData() {}
...@@ -568,7 +580,7 @@ css::uno::Sequence<ScannerContext> SAL_CALL ScannerManager::getAvailableScanners ...@@ -568,7 +580,7 @@ css::uno::Sequence<ScannerContext> SAL_CALL ScannerManager::getAvailableScanners
} }
sal_Bool SAL_CALL ScannerManager::configureScannerAndScan( 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); osl::MutexGuard aGuard(maProtector);
css::uno::Reference<XScannerManager> xThis(this); css::uno::Reference<XScannerManager> xThis(this);
...@@ -578,10 +590,26 @@ sal_Bool SAL_CALL ScannerManager::configureScannerAndScan( ...@@ -578,10 +590,26 @@ sal_Bool SAL_CALL ScannerManager::configureScannerAndScan(
ReleaseData(); 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) const css::uno::Reference<css::lang::XEventListener>& rxListener)
{ {
osl::MutexGuard aGuard(maProtector); osl::MutexGuard aGuard(maProtector);
...@@ -591,7 +619,7 @@ void SAL_CALL ScannerManager::startScan(const ScannerContext& rContext, ...@@ -591,7 +619,7 @@ void SAL_CALL ScannerManager::startScan(const ScannerContext& rContext,
throw ScannerException("Scanner does not exist", xThis, ScanError_InvalidContext); throw ScannerException("Scanner does not exist", xThis, ScanError_InvalidContext);
ReleaseData(); ReleaseData();
aTwain.PerformTransfer(*this, rxListener); aTwain.PerformTransfer(*this, rxListener, ImplGetActiveFrameWindow());
} }
ScanError SAL_CALL ScannerManager::getError(const ScannerContext& rContext) ScanError SAL_CALL ScannerManager::getError(const ScannerContext& rContext)
...@@ -606,7 +634,7 @@ ScanError SAL_CALL ScannerManager::getError(const ScannerContext& rContext) ...@@ -606,7 +634,7 @@ ScanError SAL_CALL ScannerManager::getError(const ScannerContext& rContext)
: ScanError_ScanErrorNone); : ScanError_ScanErrorNone);
} }
css::uno::Reference<css::awt::XBitmap> css::uno::Reference<css::awt::XBitmap>
SAL_CALL ScannerManager::getBitmap(const ScannerContext& /*rContext*/) SAL_CALL ScannerManager::getBitmap(const ScannerContext& /*rContext*/)
{ {
osl::MutexGuard aGuard(maProtector); osl::MutexGuard aGuard(maProtector);
......
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