2019-04-21 12:54:39 -05:00
// 6 april 2015
# include "uipriv_windows.hpp"
HINSTANCE uipriv_hInstance = NULL ;
int uipriv_nCmdShow ;
2019-04-28 15:23:25 -05:00
# ifndef uiStatic
BOOL WINAPI DllMain ( HINSTANCE hInstance , DWORD fdwReason , LPVOID lpvReserved )
{
if ( fdwReason = = DLL_PROCESS_ATTACH )
uipriv_hInstance = hInstance ;
return TRUE ;
}
static inline void setHInstance ( void )
{
// do nothing; set by DllMain() above
}
# else
// see https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483
EXTERN_C IMAGE_DOS_HEADER __ImageBase ;
static inline void setHInstance ( void )
{
uipriv_hInstance = ( HINSTANCE ) ( & __ImageBase ) ;
}
# endif
2019-04-21 12:54:39 -05:00
//HFONT hMessageFont;
# define wantedICCClasses ( \
ICC_STANDARD_CLASSES | /* user32.dll controls */ \
ICC_PROGRESS_CLASS | /* progress bars */ \
ICC_TAB_CLASSES | /* tabs */ \
ICC_LISTVIEW_CLASSES | /* table headers */ \
ICC_UPDOWN_CLASS | /* spinboxes */ \
ICC_BAR_CLASSES | /* trackbar */ \
ICC_DATE_CLASSES | /* date/time picker */ \
0 )
2019-04-28 15:35:25 -05:00
# define errLoadDefaultIconFailed "failed to load default icon"
# define errLoadDefaultCursorFailed "failed to load default cursor"
2019-04-28 15:23:25 -05:00
# define errInitUtilWindowFailed "failed to initialize the utility window"
2019-04-21 13:49:16 -05:00
# define errICCFailed "InitCommonControlsEx() failed"
# define errICCFailedNoLastError "InitCommonControlsEx() failed, but didn't specify why. This usually means you forgot the Common Controls v6 manifest; refer to the libui documentation for instructions."
# define errCoInitializeFailed "CoInitialize() failed"
# define errHRESULTInitErrorsSuffix ": 0x00000000"
static const char * initErrors [ ] = {
2019-04-28 15:35:25 -05:00
errLoadDefaultIconFailed errHRESULTInitErrorsSuffix
errLoadDefaultCursorFailed errHRESULTInitErrorsSuffix
2019-04-28 15:23:25 -05:00
errInitUtilWindowFailed errHRESULTInitErrorsSuffix
2019-04-21 13:49:16 -05:00
errICCFailed errHRESULTInitErrorsSuffix ,
errICCFailedNoLastError ,
errCoInitializeFailed errHRESULTInitErrorsSuffix ,
NULL ,
} ;
# define uiprivInitReturnHRESULT(err, msg, hr) uiprivInitReturnErrorf(err, "%s: 0x%08I32X", msg, hr)
2019-05-09 11:07:28 -05:00
const char * * uiprivSysInitErrors ( void )
{
return initErrors ;
}
2019-05-29 00:02:15 -05:00
static DWORD mainThread ;
static BOOL initialized = FALSE ; // TODO deduplicate this from common/init.c
2019-05-29 20:10:44 -05:00
bool uiprivSysInit ( void * options , uiInitError * err )
2019-04-21 12:54:39 -05:00
{
STARTUPINFOW si ;
2019-04-28 15:23:25 -05:00
HICON hDefaultIcon ;
HCURSOR hDefaultCursor ;
2019-04-21 12:54:39 -05:00
INITCOMMONCONTROLSEX icc ;
HRESULT hr ;
2019-04-28 15:23:25 -05:00
setHInstance ( ) ;
2019-04-21 12:54:39 -05:00
uipriv_nCmdShow = SW_SHOWDEFAULT ;
GetStartupInfoW ( & si ) ;
if ( ( si . dwFlags & STARTF_USESHOWWINDOW ) ! = 0 )
uipriv_nCmdShow = si . wShowWindow ;
2019-04-28 15:23:25 -05:00
hr = uiprivHrLoadIconW ( NULL , IDI_APPLICATION , & hDefaultIcon ) ;
if ( hr ! = S_OK )
return uiprivInitReturnHRESULT ( err , errLoadDefaultIconFailed , hr ) ;
hr = uiprivHrLoadCursorW ( NULL , IDC_ARROW , & hDefaultCursor ) ;
if ( hr ! = S_OK )
return uiprivInitReturnHRESULT ( err , errLoadDefaultCursorFailed , hr ) ;
hr = uiprivInitUtilWindow ( hDefaultIcon , hDefaultCursor ) ;
if ( hr ! = S_OK )
return uiprivInitReturnHRESULT ( err , errInitUtilWindowFailed , hr ) ;
2019-04-21 12:54:39 -05:00
ZeroMemory ( & icc , sizeof ( INITCOMMONCONTROLSEX ) ) ;
icc . dwSize = sizeof ( INITCOMMONCONTROLSEX ) ;
icc . dwICC = wantedICCClasses ;
2019-04-21 13:49:16 -05:00
if ( InitCommonControlsEx ( & icc ) = = 0 ) {
DWORD lasterr ;
lasterr = GetLastError ( ) ;
if ( lasterr = = 0 )
return uiprivInitReturnError ( err , errICCFailedNoLastError ) ;
2019-04-28 15:23:25 -05:00
hr = HRESULT_FROM_WIN32 ( lasterr ) ;
return uiprivInitReturnHRESULT ( err , errICCFailed , hr ) ;
2019-04-21 13:49:16 -05:00
}
2019-04-21 12:54:39 -05:00
2019-04-21 14:08:09 -05:00
/* hr = CoInitialize(NULL);
2019-04-21 12:54:39 -05:00
if ( hr ! = S_OK & & hr ! = S_FALSE )
return ieHRESULT ( " initializing COM " , hr ) ;
// LONGTERM initialize COM security
2019-04-21 13:49:16 -05:00
// LONGTERM turn off COM exception handling
2019-04-21 14:08:09 -05:00
*/
2019-05-29 00:02:15 -05:00
mainThread = GetCurrentThreadId ( ) ;
initialized = TRUE ;
2019-05-29 20:10:44 -05:00
return true ;
2019-04-21 12:54:39 -05:00
}
2019-04-28 15:23:25 -05:00
void uiMain ( void )
{
MSG msg ;
HRESULT hr ;
2019-04-21 12:57:19 -05:00
2019-05-29 00:02:15 -05:00
if ( ! uiprivCheckInitializedAndThread ( ) )
return ;
2019-04-28 15:23:25 -05:00
for ( ; ; ) {
2019-04-29 22:12:39 -05:00
hr = uiprivHrGetMessageW ( & msg , NULL , 0 , 0 ) ;
if ( hr = = S_FALSE ) // WM_QUIT
return ;
2019-04-28 15:23:25 -05:00
if ( hr ! = S_OK ) {
// TODO log error
return ;
}
// TODO IsDialogMessage()
TranslateMessage ( & msg ) ;
DispatchMessageW ( & msg ) ;
}
}
void uiQuit ( void )
2019-04-21 12:54:39 -05:00
{
2019-05-29 00:02:15 -05:00
if ( ! uiprivCheckInitializedAndThread ( ) )
return ;
2019-04-28 15:23:25 -05:00
PostQuitMessage ( 0 ) ;
2019-04-21 12:54:39 -05:00
}
2019-04-21 12:57:19 -05:00
2019-04-28 15:23:25 -05:00
void uiQueueMain ( void ( * f ) ( void * data ) , void * data )
{
HRESULT hr ;
2019-05-29 00:02:15 -05:00
if ( ! initialized ) {
uiprivProgrammerError ( uiprivProgrammerErrorNotInitialized , uiprivFunc ) ;
return ;
}
2019-04-28 15:23:25 -05:00
hr = uiprivHrPostMessageW ( uiprivUtilWindow , uiprivUtilWindowMsgQueueMain , ( WPARAM ) f , ( LPARAM ) data ) ;
if ( hr ! = S_OK ) {
// TODO handle error
}
}
2019-05-27 09:45:55 -05:00
2019-05-29 00:02:15 -05:00
bool uiprivSysCheckThread ( void )
{
return GetCurrentThreadId ( ) = = mainThread ;
}
2019-05-27 09:45:55 -05:00
void uiprivReportError ( const char * prefix , const char * msg , const char * suffix , bool internal )
{
// Print to both stderr and the debugger; the former handles the case of a console and the latter handles the case of not.
// TODO find a reliable way to check if stderr is connected (the mere presence of a console window is not one)
fprintf ( stderr , " *** %s: %s. %s \n " , prefix , msg , suffix ) ;
// Use OutputDebugStringA() directly because these *are* runtime MBCS strings.
OutputDebugStringA ( prefix ) ;
OutputDebugStringA ( " : " ) ;
OutputDebugStringA ( msg ) ;
OutputDebugStringA ( " . " ) ;
OutputDebugStringA ( suffix ) ;
OutputDebugStringA ( " \n " ) ;
DebugBreak ( ) ;
abort ( ) ; // we shouldn't reach here
}