xricht17 / twpp

TWAIN framework for C++11. Makes development of applications and data sources much easier.
MIT License
39 stars 17 forks source link

State automatically changes back to XferReady after first image is handled in Windows #24

Closed juha-matikainen closed 4 years ago

juha-matikainen commented 4 years ago

Hi, There is a bug in Source::processEvent() which causes DsState to automatically change back to XferReady after first image is handled. I believe same affects also Source::waitReady(). Tested while DSM is loaded with preferOld=true.

In Windows implementation d()->m_readyMsg is set to new value only when it is not Msg::Null

        auto rc = dsm(DataGroup::Control, Dat::Event, Msg::ProcessEvent, twEvent);
        switch (rc){
            case ReturnCode::DsEvent:
            case ReturnCode::NotDsEvent:
                if (d()->m_readyMsg == Msg::Null){
                    d()->m_readyMsg = twEvent.message();
                }

                break;
            default:
                return rc;
        }

        auto msg = d()->m_readyMsg;

But it is not set back to Msg::Null in case of XferReady (or CloseDSOk) when handled later

        switch (msg){
            case Msg::XferReady: // ok/scan button <=> Msg::EnableDs
                d()->m_state = DsState::XferReady;
                // fallthrough
            case Msg::CloseDsOk: // ok/scan button <=> Msg::EnableDsUiOnly
                return ReturnCode::Success;

So as a result next DsEvent or NotDsEvent after XferReady is again handled as XferReady causing DsState mismatch between application and source.

This can be fixed by setting d()->m_readyMsg to Msg::Null after being handled.

        switch (msg){
            case Msg::XferReady: // ok/scan button <=> Msg::EnableDs
                d()->m_state = DsState::XferReady;
                // fallthrough
            case Msg::CloseDsOk: // ok/scan button <=> Msg::EnableDsUiOnly
                d()->m_readyMsg = Msg::Null; // <--- clear to not handle XferReady again
                return ReturnCode::Success;
xricht17 commented 4 years ago

Hi Juha,

Thanks for this great bug report. I'll fix it ASAP.

xricht17 commented 4 years ago

Should be fixed now. Please verify.

juha-matikainen commented 4 years ago

Thanks for the quick fix! Reviewed and tested successfully with processEvent(). I would expect waitReady() to also work as d()->m_readyMsg handling is same.