diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-10-12 10:20:17 +0200 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-10-13 16:49:02 +0200 |
commit | 3bf6c97029d26ddf20007c47ca6b68e5cc52d846 (patch) | |
tree | 1185ae5aff1c42f87357590727bf64c2df9af439 /vcl/win/app/salinst.cxx | |
parent | fb4e7be5d4eac6d7c429c215e72de45ea28d86cd (diff) |
tdf#112975 WIN correctly handle VclInputFlags::OTHER
On Windows we can just check the message queue for existing
messages. But VclInputFlags::OTHER is used to check for any
messages, which can't be explicitly checked.
In the case of checking for VclInputFlags::OTHER while
excluding an other message type, we have to make multiple
PeekMessage calls and exclude all non-checked message ids.
Change-Id: I1cedd4b76444769842c74228fc547f0d924f8b60
Reviewed-on: https://gerrit.libreoffice.org/43337
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'vcl/win/app/salinst.cxx')
-rw-r--r-- | vcl/win/app/salinst.cxx | 175 |
1 files changed, 144 insertions, 31 deletions
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index 38db3d3bb17c..ade332297fc6 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -689,10 +689,119 @@ LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lPa return nRet; } +struct MsgRange +{ + UINT nStart; + UINT nEnd; +}; + +static std::vector<MsgRange> GetOtherRanges( VclInputFlags nType ) +{ + assert( nType != VCL_INPUT_ANY ); + + // this array must be kept sorted! + const UINT nExcludeMsgIds[] = + { + 0, + + WM_MOVE, // 3 + WM_SIZE, // 5 + WM_PAINT, // 15 + WM_KEYDOWN, // 256 + WM_TIMER, // 275 + + WM_MOUSEFIRST, // 512 + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + WM_MOUSELAST, // 521 + + SAL_MSG_POSTMOVE, // WM_USER+136 + SAL_MSG_POSTCALLSIZE, // WM_USER+137 + + SAL_MSG_TIMER_CALLBACK, // WM_USER+162 + + UINT_MAX + }; + const unsigned MAX_EXCL = SAL_N_ELEMENTS( nExcludeMsgIds ); + + bool aExcludeMsgList[ MAX_EXCL ] = { false, }; + std::vector<MsgRange> aResult; + + // set the excluded values + if ( !(nType & VclInputFlags::MOUSE) ) + { + for ( unsigned i = 0; nExcludeMsgIds[ 6 + i ] <= WM_MOUSELAST; ++i ) + aExcludeMsgList[ 6 + i ] = true; + } + + if ( !(nType & VclInputFlags::KEYBOARD) ) + aExcludeMsgList[ 4 ] = true; + + if ( !(nType & VclInputFlags::PAINT) ) + { + aExcludeMsgList[ 1 ] = true; + aExcludeMsgList[ 2 ] = true; + aExcludeMsgList[ 3 ] = true; + aExcludeMsgList[ 16 ] = true; + aExcludeMsgList[ 17 ] = true; + } + + if ( !(nType & VclInputFlags::TIMER) ) + { + aExcludeMsgList[ 5 ] = true; + aExcludeMsgList[ 18 ] = true; + } + + // build the message ranges to check + MsgRange aRange = { 0, 0 }; + bool doEnd = true; + for ( unsigned i = 1; i < MAX_EXCL; ++i ) + { + if ( aExcludeMsgList[ i ] ) + { + if ( !doEnd ) + { + if ( nExcludeMsgIds[ i ] == aRange.nStart ) + ++aRange.nStart; + else + doEnd = true; + } + if ( doEnd ) + { + aRange.nEnd = nExcludeMsgIds[ i ] - 1; + aResult.push_back( aRange ); + doEnd = false; + aRange.nStart = aRange.nEnd + 2; + } + } + } + + if ( aRange.nStart != UINT_MAX ) + { + aRange.nEnd = UINT_MAX; + aResult.push_back( aRange ); + } + + return aResult; +} + bool WinSalInstance::AnyInput( VclInputFlags nType ) { MSG aMsg; + if ( nType & VclInputFlags::TIMER ) + { + const WinSalTimer* pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); + if ( pTimer && pTimer->HasTimerElapsed() ) + return true; + } + if ( (nType & VCL_INPUT_ANY) == VCL_INPUT_ANY ) { // revert bugfix for #108919# which never reported timeouts when called from the timer handler @@ -702,32 +811,52 @@ bool WinSalInstance::AnyInput( VclInputFlags nType ) } else { - if ( nType & VclInputFlags::MOUSE ) - { - // Test for mouse input - if ( PeekMessageW( &aMsg, nullptr, WM_MOUSEFIRST, WM_MOUSELAST, - PM_NOREMOVE | PM_NOYIELD ) ) - return true; - } + const bool bCheck_KEYBOARD (nType & VclInputFlags::KEYBOARD); + const bool bCheck_OTHER (nType & VclInputFlags::OTHER); - if ( nType & VclInputFlags::KEYBOARD ) + // If there is a modifier key event, it counts as OTHER + // Previously we were simply ignoring these events... + if ( bCheck_KEYBOARD || bCheck_OTHER ) { - // Test for key input if ( PeekMessageW( &aMsg, nullptr, WM_KEYDOWN, WM_KEYDOWN, PM_NOREMOVE | PM_NOYIELD ) ) { - if ( (aMsg.wParam == VK_SHIFT) || - (aMsg.wParam == VK_CONTROL) || - (aMsg.wParam == VK_MENU) ) - return false; - else + const bool bIsModifier = ( (aMsg.wParam == VK_SHIFT) || + (aMsg.wParam == VK_CONTROL) || (aMsg.wParam == VK_MENU) ); + if ( bCheck_KEYBOARD && !bIsModifier ) + return true; + if ( bCheck_OTHER && bIsModifier ) return true; } } + // Other checks for all messages not excluded. + // The less we exclude, the less ranges have to be checked! + if ( bCheck_OTHER ) + { + // TIMER and KEYBOARD are already handled, so always exclude them! + VclInputFlags nOtherType = nType & + ~VclInputFlags(VclInputFlags::KEYBOARD | VclInputFlags::TIMER); + + std::vector<MsgRange> aMsgRangeList( GetOtherRanges( nOtherType ) ); + for ( MsgRange aRange : aMsgRangeList ) + if ( PeekMessageW( &aMsg, nullptr, aRange.nStart, + aRange.nEnd, PM_NOREMOVE | PM_NOYIELD ) ) + return true; + + // MOUSE and PAINT already handled, so skip futher checks + return false; + } + + if ( nType & VclInputFlags::MOUSE ) + { + if ( PeekMessageW( &aMsg, nullptr, WM_MOUSEFIRST, WM_MOUSELAST, + PM_NOREMOVE | PM_NOYIELD ) ) + return true; + } + if ( nType & VclInputFlags::PAINT ) { - // Test for paint input if ( PeekMessageW( &aMsg, nullptr, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) ) return true; @@ -748,22 +877,6 @@ bool WinSalInstance::AnyInput( VclInputFlags nType ) PM_NOREMOVE | PM_NOYIELD ) ) return true; } - - if ( nType & VclInputFlags::TIMER ) - { - // Test for timer input - if ( PeekMessageW( &aMsg, nullptr, WM_TIMER, WM_TIMER, - PM_NOREMOVE | PM_NOYIELD ) ) - return true; - - } - - if ( nType & VclInputFlags::OTHER ) - { - // Test for any input - if ( PeekMessageW( &aMsg, nullptr, 0, 0, PM_NOREMOVE | PM_NOYIELD ) ) - return true; - } } return false; |