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 )
{
HWND active ;
// TODO really active? or parentToplevel(msg->hwnd)?
active = GetActiveWindow ( ) ;
if ( active ! = NULL )
// TODO find documentation that says IsDialogMessage() calls CallMsgFilter() for us, because that's what's happening
if ( IsDialogMessage ( active , msg ) ! = 0 )
return ;
TranslateMessage ( msg ) ;
DispatchMessageW ( msg ) ;
}
static int waitMessage ( MSG * msg )
{
int res ;
res = GetMessageW ( msg , NULL , 0 , 0 ) ;
if ( res < 0 ) {
logLastError ( L " error calling GetMessage() " ) ;
return 0 ; // bail out on error
}
return res ! = 0 ; // returns false on WM_QUIT
}
2016-04-22 13:06:22 -05:00
void uiMain ( void )
2016-05-24 21:14:05 -05:00
{
while ( uiMainStep ( 1 ) )
;
}
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 ;
2016-05-24 21:14:05 -05:00
if ( wait ) {
if ( ! waitMessage ( & msg ) )
return 0 ;
processMessage ( & msg ) ;
return 1 ;
}
// 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
}
void uiQuit ( void )
{
PostQuitMessage ( 0 ) ;
}
void uiQueueMain ( void ( * f ) ( void * data ) , void * data )
{
if ( PostMessageW ( utilWindow , msgQueued , ( WPARAM ) f , ( LPARAM ) data ) = = 0 )
// TODO this is likely not safe to call across threads (allocates memory)
logLastError ( L " error queueing function to run on main thread " ) ;
}