summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2017-10-12 10:20:17 +0200
committerJan-Marek Glogowski <glogow@fbihome.de>2017-10-13 16:49:02 +0200
commit3bf6c97029d26ddf20007c47ca6b68e5cc52d846 (patch)
tree1185ae5aff1c42f87357590727bf64c2df9af439
parentfb4e7be5d4eac6d7c429c215e72de45ea28d86cd (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>
-rw-r--r--vcl/inc/win/saltimer.h6
-rw-r--r--vcl/win/app/salinst.cxx175
2 files changed, 150 insertions, 31 deletions
diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index 37976bbfaf8b..68973e1cadc3 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -47,6 +47,7 @@ public:
virtual void Stop() override;
inline bool IsDirectTimeout() const;
+ inline bool HasTimerElapsed() const;
};
inline bool WinSalTimer::IsDirectTimeout() const
@@ -54,6 +55,11 @@ inline bool WinSalTimer::IsDirectTimeout() const
return m_bDirectTimeout;
}
+inline bool WinSalTimer::HasTimerElapsed() const
+{
+ return m_bDirectTimeout || ExistsValidEvent();
+}
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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;