2016-04-22 13:06:22 -05:00
// 6 april 2015
# include "uipriv_windows.hpp"
2016-04-22 13:36:21 -05:00
static HHOOK filter ;
static LRESULT CALLBACK filterProc ( int code , WPARAM wParam , LPARAM lParam )
{
MSG * msg = ( MSG * ) lParam ;
if ( code < 0 )
goto callNext ;
2016-04-22 13:56:09 -05:00
if ( areaFilter ( msg ) ) // don't continue to our IsDialogMessage() hack if the area handled it
goto discard ;
2016-04-22 13:36:21 -05:00
2016-04-22 13:56:09 -05:00
// TODO IsDialogMessage() hack here
// otherwise keep going
goto callNext ;
2016-04-22 13:36:21 -05:00
2016-04-22 13:56:09 -05:00
discard :
2016-04-22 13:36:21 -05:00
// we handled it; discard the message so the dialog manager doesn't see it
return 1 ;
callNext :
2016-04-23 21:29:54 -05:00
return CallNextHookEx ( filter , code , wParam , lParam ) ;
2016-04-22 13:36:21 -05:00
}
int registerMessageFilter ( void )
{
filter = SetWindowsHookExW ( WH_MSGFILTER ,
filterProc ,
hInstance ,
GetCurrentThreadId ( ) ) ;
return filter ! = NULL ;
}
void unregisterMessageFilter ( void )
{
2016-04-23 21:29:54 -05:00
if ( UnhookWindowsHookEx ( filter ) = = 0 )
2016-04-22 13:36:21 -05:00
logLastError ( L " error unregistering libui message filter " ) ;
}
2016-05-24 21:14:05 -05:00
// LONGTERM http://blogs.msdn.com/b/oldnewthing/archive/2005/04/08/406509.aspx when adding accelerators, TranslateAccelerators() before IsDialogMessage()
static void processMessage ( MSG * msg )
{
2016-05-29 18:55:53 -05:00
HWND correctParent ;
if ( msg - > hwnd ! = NULL )
correctParent = parentToplevel ( msg - > hwnd ) ;
else // just to be safe
correctParent = GetActiveWindow ( ) ;
if ( correctParent ! = NULL )
// this calls our mesage filter above for us
if ( IsDialogMessage ( correctParent , msg ) ! = 0 )
2016-05-24 21:14:05 -05:00
return ;
TranslateMessage ( msg ) ;
DispatchMessageW ( msg ) ;
}
2016-06-17 08:22:31 -05:00
void uiMainSteps ( void )
2016-06-16 13:12:47 -05:00
{
2016-06-17 08:22:31 -05:00
// don't need to do anything here
2016-06-16 13:12:47 -05:00
}
2016-05-24 21:14:05 -05:00
static int peekMessage ( MSG * msg )
{
BOOL res ;
res = PeekMessageW ( msg , NULL , 0 , 0 , PM_REMOVE ) ;
if ( res = = 0 )
return 2 ; // no message available
if ( msg - > message ! = WM_QUIT )
return 1 ; // a message
return 0 ; // WM_QUIT
}
int uiMainStep ( int wait )
2016-04-22 13:06:22 -05:00
{
MSG msg ;
2019-04-28 15:23:25 -05:00
if ( wait ) { /* deleted */ }
2016-05-24 21:14:05 -05:00
// don't wait for a message
switch ( peekMessage ( & msg ) ) {
case 0 : // quit
// TODO PostQuitMessage() again?
return 0 ;
case 1 : // process a message
processMessage ( & msg ) ;
// fall out to the case for no message
2016-04-22 13:06:22 -05:00
}
2016-05-24 21:14:05 -05:00
return 1 ; // no message
2016-04-22 13:06:22 -05:00
}
2018-08-09 03:28:10 -05:00
static std : : map < uiprivTimer * , bool > timers ;
2017-08-19 17:32:52 -05:00
void uiTimer ( int milliseconds , int ( * f ) ( void * data ) , void * data )
{
2018-04-18 20:04:12 -05:00
uiprivTimer * timer ;
timer = uiprivNew ( uiprivTimer ) ;
timer - > f = f ;
timer - > data = data ;
2018-04-18 20:09:24 -05:00
// note that timer IDs are pointer sized precisely so we can use them as timer IDs; see https://blogs.msdn.microsoft.com/oldnewthing/20150924-00/?p=91521
2018-04-18 20:04:12 -05:00
if ( SetTimer ( utilWindow , ( UINT_PTR ) timer , milliseconds , NULL ) = = 0 )
logLastError ( L " error calling SetTimer() in uiTimer() " ) ;
2018-08-09 03:28:10 -05:00
timers [ timer ] = true ;
}
void uiprivFreeTimer ( uiprivTimer * t )
{
timers . erase ( t ) ;
uiprivFree ( t ) ;
}
2018-08-09 03:49:07 -05:00
// since timers use uiprivAlloc(), we have to clean them up in uiUninit(), or else we'll get dangling allocation errors
2018-08-09 03:28:10 -05:00
void uiprivUninitTimers ( void )
{
// TODO why doesn't auto t : timers work?
for ( auto t = timers . begin ( ) ; t ! = timers . end ( ) ; t + + )
uiprivFree ( t - > first ) ;
timers . clear ( ) ;
2017-08-19 17:32:52 -05:00
}