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-21 04:37:24 -05:00
void uimsgloop_area ( HWND active , HWND focus , MSG * msg )
2014-08-20 22:38:22 -05:00
{
2014-08-21 04:37:24 -05:00
MSG copy ;
copy = * msg ;
switch ( copy . message ) {
case WM_KEYDOWN :
case WM_SYSKEYDOWN : // Alt+[anything] and F10 send these instead
copy . message = msgAreaKeyDown ;
break ;
case WM_KEYUP :
case WM_SYSKEYUP :
copy . message = msgAreaKeyUp ;
break ;
default :
goto notkey ;
}
// if we handled the key, don't do the default behavior
2014-08-20 22:38:22 -05:00
// don't call TranslateMessage(); we do our own keyboard handling
2014-08-21 04:37:24 -05:00
if ( DispatchMessage ( & copy ) ! = FALSE )
return ;
2014-08-25 21:06:40 -05:00
notkey :
2014-08-21 04:37:24 -05:00
if ( IsDialogMessage ( active , msg ) ! = 0 )
return ;
2014-08-20 22:38:22 -05:00
DispatchMessage ( msg ) ;
}
void uimsgloop_tab ( HWND active , HWND focus , MSG * msg )
{
BOOL hasChildren ;
BOOL idm ;
// 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
hasChildren = SendMessageW ( focus , msgTabCurrentTabHasChildren , 0 , 0 ) ;
if ( hasChildren )
tabEnterChildren ( focus ) ;
idm = IsDialogMessageW ( active , msg ) ;
if ( hasChildren )
tabLeaveChildren ( focus ) ;
if ( idm ! = 0 )
return ;
TranslateMessage ( msg ) ;
DispatchMessage ( msg ) ;
}
void uimsgloop_else ( MSG * msg )
{
TranslateMessage ( msg ) ;
DispatchMessage ( msg ) ;
}
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 ;
2014-08-13 09:41:27 -05:00
BOOL dodlgmessage ;
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-20 22:38:22 -05:00
if ( active = = NULL ) {
uimsgloop_else ( & msg ) ;
continue ;
}
// 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
focus = GetFocus ( ) ;
if ( focus ! = NULL ) {
2014-11-05 13:12:57 -06:00
switch ( windowClassOf ( focus , areaWindowClass , WC_TABCONTROLW , NULL ) ) {
case 0 : // areaWindowClass
2014-08-21 04:37:24 -05:00
uimsgloop_area ( active , focus , & msg ) ;
2014-08-20 22:38:22 -05:00
continue ;
2014-11-05 13:12:57 -06:00
case 1 : // WC_TABCONTROLW
2014-08-20 22:38:22 -05:00
uimsgloop_tab ( active , focus , & msg ) ;
continue ;
2014-08-14 12:05:31 -05:00
}
2014-08-20 22:38:22 -05:00
// else fall through
2014-08-13 09:41:27 -05:00
}
2014-08-20 22:38:22 -05:00
if ( IsDialogMessage ( active , & msg ) ! = 0 )
continue ;
uimsgloop_else ( & 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 )
{
2014-08-14 15:00:31 -05:00
LRESULT shared ;
2014-08-19 02:56:04 -05:00
size_t i ;
2014-08-14 15:00:31 -05:00
if ( sharedWndProc ( hwnd , uMsg , wParam , lParam , & shared ) )
return shared ;
2014-07-17 18:36:24 -05:00
switch ( uMsg ) {
2014-07-17 23:22:21 -05:00
case msgRequest :
2014-08-26 14:39:04 -05:00
doissue ( ( void * ) lParam ) ;
2014-08-19 02:31:53 -05:00
return 0 ;
2014-08-26 11:52:32 -05:00
case msgOpenFileDone :
finishOpenFile ( ( WCHAR * ) wParam , ( void * ) lParam ) ;
return 0 ;
2014-07-17 18:36:24 -05:00
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
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 ;
}