2014-08-14 09:42:10 -05:00
// 17 july 2014
2014-07-17 18:36:24 -05:00
# include "winapi_windows.h"
# include "_cgo_export.h"
2014-08-14 09:42:10 -05:00
// note that this includes the terminating '\0'
2014-08-14 10:30:48 -05:00
// this also assumes WC_TABCONTROL is longer than areaWindowClass
# define NCLASSNAME (sizeof WC_TABCONTROL / sizeof WC_TABCONTROL[0])
2014-08-13 09:41:27 -05:00
2014-07-17 18:36:24 -05:00
void uimsgloop ( void )
{
MSG msg ;
int res ;
2014-08-14 10:30:48 -05:00
HWND active , focus ;
WCHAR classchk [ NCLASSNAME ] ;
2014-08-13 09:41:27 -05:00
BOOL dodlgmessage ;
2014-08-14 10:30:48 -05:00
BOOL istab ;
BOOL idm ;
2014-07-17 18:36:24 -05:00
for ( ; ; ) {
SetLastError ( 0 ) ;
2014-07-17 22:14:22 -05:00
res = GetMessageW ( & msg , NULL , 0 , 0 ) ;
2014-07-17 18:36:24 -05:00
if ( res < 0 )
xpanic ( " error calling GetMessage() " , GetLastError ( ) ) ;
2014-08-14 09:42:10 -05:00
if ( res = = 0 ) // WM_QUIT
2014-07-17 18:36:24 -05:00
break ;
2014-08-12 16:18:45 -05:00
active = GetActiveWindow ( ) ;
2014-08-13 09:41:27 -05:00
if ( active ! = NULL ) {
2014-08-14 10:30:48 -05:00
// bit of logic involved here:
// we don't want dialog messages passed into Areas, so we don't call IsDialogMessageW() there
// as for Tabs, we can't have both WS_TABSTOP and WS_EX_CONTROLPARENT set at the same time, so we hotswap the two styles to get the behavior we want
// theoretically we could use the class atom to avoid a wcscmp()
// however, raymond chen advises against this - http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx (and we're not in control of the Tab class, before you say anything)
// we could also theoretically just send msgAreaDefocuses directly, but what DefWindowProc() does to a WM_APP message is undocumented
2014-08-13 09:41:27 -05:00
dodlgmessage = TRUE ;
2014-08-14 10:30:48 -05:00
istab = FALSE ;
2014-08-13 09:41:27 -05:00
focus = GetFocus ( ) ;
if ( focus ! = NULL ) {
2014-08-14 10:30:48 -05:00
if ( GetClassNameW ( focus , classchk , NCLASSNAME ) = = 0 )
2014-08-13 09:41:27 -05:00
xpanic ( " error getting name of focused window class for Area check " , GetLastError ( ) ) ;
if ( wcscmp ( classchk , areaWindowClass ) = = 0 )
2014-08-13 13:09:53 -05:00
dodlgmessage = FALSE ;
2014-08-14 10:30:48 -05:00
else if ( wcscmp ( classchk , WC_TABCONTROL ) = = 0 )
2014-08-14 12:05:31 -05:00
// THIS BIT IS IMPORTANT
// if the current tab has no children, then there will be no children left in the dialog to tab to, and IsDialogMessageW() will loop forever
istab = ( BOOL ) SendMessageW ( focus , msgTabCurrentTabHasChildren , 0 , 0 ) ;
2014-08-13 09:41:27 -05:00
}
2014-08-14 12:05:31 -05:00
if ( dodlgmessage ) {
if ( istab )
tabEnterChildren ( focus ) ;
2014-08-14 10:30:48 -05:00
idm = IsDialogMessageW ( active , & msg ) ;
2014-08-14 12:05:31 -05:00
if ( istab )
tabLeaveChildren ( focus ) ;
if ( idm ! = 0 )
continue ;
}
2014-08-13 09:41:27 -05:00
}
2014-07-17 18:36:24 -05:00
TranslateMessage ( & msg ) ;
2014-07-17 22:14:22 -05:00
DispatchMessageW ( & msg ) ;
2014-07-17 18:36:24 -05:00
}
}
void issue ( void * request )
{
SetLastError ( 0 ) ;
2014-07-17 23:22:21 -05:00
if ( PostMessageW ( msgwin , msgRequest , 0 , ( LPARAM ) request ) = = 0 )
2014-07-17 18:36:24 -05:00
xpanic ( " error issuing request " , GetLastError ( ) ) ;
}
HWND msgwin ;
# define msgwinclass L"gouimsgwin"
static LRESULT CALLBACK msgwinproc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
switch ( uMsg ) {
case WM_COMMAND :
return forwardCommand ( hwnd , uMsg , wParam , lParam ) ;
2014-07-25 14:58:24 -05:00
case WM_NOTIFY :
return forwardNotify ( hwnd , uMsg , wParam , lParam ) ;
2014-07-17 23:22:21 -05:00
case msgRequest :
2014-07-19 08:57:01 -05:00
doissue ( ( void * ) lParam ) ;
2014-07-17 18:36:24 -05:00
return 0 ;
default :
2014-07-17 22:14:22 -05:00
return DefWindowProcW ( hwnd , uMsg , wParam , lParam ) ;
2014-07-17 18:36:24 -05:00
}
xmissedmsg ( " message-only " , " msgwinproc() " , uMsg ) ;
2014-08-14 09:42:10 -05:00
return 0 ; // unreachable
2014-07-17 18:36:24 -05:00
}
DWORD makemsgwin ( char * * errmsg )
{
2014-07-17 22:14:22 -05:00
WNDCLASSW wc ;
2014-07-17 18:36:24 -05:00
HWND hwnd ;
2014-07-17 22:14:22 -05:00
ZeroMemory ( & wc , sizeof ( WNDCLASSW ) ) ;
2014-07-17 18:36:24 -05:00
wc . lpfnWndProc = msgwinproc ;
wc . hInstance = hInstance ;
wc . hIcon = hDefaultIcon ;
wc . hCursor = hArrowCursor ;
wc . hbrBackground = ( HBRUSH ) ( COLOR_BTNFACE + 1 ) ;
wc . lpszClassName = msgwinclass ;
2014-07-17 22:14:22 -05:00
if ( RegisterClassW ( & wc ) = = 0 ) {
2014-07-17 18:36:24 -05:00
* errmsg = " error registering message-only window classs " ;
return GetLastError ( ) ;
}
2014-07-17 22:14:22 -05:00
msgwin = CreateWindowExW (
2014-07-17 18:36:24 -05:00
0 ,
msgwinclass , L " package ui message-only window " ,
0 ,
CW_USEDEFAULT , CW_USEDEFAULT ,
CW_USEDEFAULT , CW_USEDEFAULT ,
HWND_MESSAGE , NULL , hInstance , NULL ) ;
if ( msgwin = = NULL ) {
* errmsg = " error creating message-only window " ;
return GetLastError ( ) ;
}
return 0 ;
}