forked from matthieu-campion/nui3
/
nglKernel.h
473 lines (375 loc) · 12.8 KB
/
nglKernel.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
/*
NUI3 - C++ cross-platform GUI framework for OpenGL based applications
Copyright (C) 2002-2003 Sebastien Metrot
licence: see nui3/LICENCE.TXT
*/
/*!
\file nglKernel.h
\brief Kernel, application abstraction base class
*/
#ifndef __nglKernel_h__
#define __nglKernel_h__
#include "nglPath.h"
#include "nglString.h"
class nglKernel;
class nglPath;
extern NGL_API nglKernel* App;
/*!<
A well designed program should have only one global. This is the unique NGL global,
pointing to the unique instance of the kernel. Since nglKernel is an abstract class,
\a App real type is necessary a descendant of nglKernel. See nglApplication and
the NGL_APP_CREATE macro for instance.
*/
#include <assert.h>
/* Default verbose level
*/
#ifdef _DEBUG_
// The mac (and GCC?) has brain dead assert system that does NOTHING.
# ifdef _CARBON_
# define __ASSERT_SYS(test) { if (!(test)) Debugger(); }
# elif defined(_WIN32_)
# define __ASSERT_SYS(test) { if (!(test)) { __asm { int 3 } }; }
#else
# define __ASSERT_SYS(test) assert(test);
# endif
# define NGL_LOG_DEFAULT NGL_LOG_INFO
#else
# define __ASSERT_SYS(test)
# define NGL_LOG_DEFAULT NGL_LOG_ERROR
#endif
#define __T(x) _T(x)
#define __TFILE__ __T(__FILE__)
#define __NGL_ASSERT(test) \
if (!(test)) { NGL_OUT(_T("%ls(%d): ") _T(#test) _T(" failed\n"), __TFILE__, __LINE__); __ASSERT_SYS(test) }
#define __NGL_ASSERTR(test, result) \
if (!(test)) { NGL_OUT(_T("%ls(%d): ") _T(#test) _T(" failed\n"), __TFILE__, __LINE__); __ASSERT_SYS(test) return result; }
/* ASSERT(R) facility
*/
#ifdef _DEBUG_
# define NGL_ASSERT(x) __NGL_ASSERT(x)
# define NGL_ASSERTR(x,y) __NGL_ASSERTR(x,y)
#else
# define NGL_ASSERT(x)
# define NGL_ASSERTR(x,y)
#endif // _DEBUG_
/* DEBUG facility
*/
#ifdef _DEBUG_
# define NGL_DEBUG(x) if (App->GetDebug()) { x }
#else
# define NGL_DEBUG(x)
#endif
#include "nglEvent.h"
#include "nglError.h"
#include "nglString.h"
#include "nglLog.h"
#include "nglConsole.h"
#include "nglPath.h"
#include "nglTimer.h"
#ifndef _NOCLIPBOARD_
# include "nglClipBoard.h"
#endif
#if (!defined _NODND_ && !defined _NOCLIPBOARD_)
# include "nglDataTypesRegistry.h"
#endif
#include <list>
class nglDeviceInfo;
//! Kernel, application abstraction base class
/*!
NGL is a framework which can run in various environments. The most trivial one
is a regular application. A more advanced scenario would be running as a
plugin into a hosting application, such as a web browser for instance.
The kernel is the common interface to all these environments : wether your
program is compiled as a regular application or a plugin, one and only one
instance of nglKernel is always available in a single environment (to be
more precise, in a single process). It provides these essential services :
- initialisation and exit callbacks
- event manager interfaces, used internally by timers, windows, etc
- a global and unique <em>application log</em>, which is used by almost any
instance of a regular NGL class
- a global and unique <em>application console</em>, which is the default
output for the <em>application log</em>. See nglConsole for more info
on the default console
- various other global services
nglKernel is an abstract class. You must refer to nglKernel derivates to
create an instance. See the ubiquitous nglApplication for instance.
The unique nglKernel object is always available via the \a App pointer.
*/
class NGL_API nglKernel : public nglError, public nglEvent
{
public:
typedef void (*ExitFunc) (void); ///< Cleanup callback type. See AddExit()
/** @name Life cycle */
//@{
virtual void Quit(int Code = 0);
/*!<
Request application ending
\param Code exit code
Note that some instances (such as plugins) might ignore a call to this method.
*/
virtual void AddExit (ExitFunc Func);
/*!< Register a shutdown callback
\param Func callback function, must be either a C function or a static C++ method
Register a callback to be triggered when the application is shuting down.
Handlers are called in reverse order of registering (last registered is called first).
*/
virtual void DelExit (ExitFunc Func);
/*!< Unregister a shutdown callback
\param Func callback function
Unregister a callback registered with AddExit().
*/
//@}
/** @name Runtime debugging */
//@{
virtual void SetDebug(bool Debug);
/*!<
Set run-time debug status
Code enclosed in the DEBUG() macro can be (des)activated at run-time either with SetDebug(),
either with the '--nodebug' command-line option if you invoke nglApplication::ParseDefaultArgs().
*/
virtual bool GetDebug() { return mDebug; }
/*!<
Return run-time debug status
See SetDebug().
*/
//@}
/** @name Logging and output */
//@{
virtual nglLog& GetLog();
/*!<
Gives the application log.
Notably used by the NGL_OUT() and NGL_LOG() macros.
*/
virtual nglConsole& GetConsole();
/*!<
Gives the application console.
*/
virtual void SetConsole(nglConsole* pConsole);
/*!<
Set application console. User still owns the \p pConsole objects
(ie. remember to delete it on application exit).
*/
//@}
/** @name Application context */
//@{
const nglPath& GetPath();
/*!<
\return current application's path (includes the binary file name)
*/
const nglString& GetName();
/*!<
\return current application name
The application name is implicitely obtained from the application's executable
name. However it can be set explicitely with SetName() at any time. The application
name serves at least two purposes :
- allow per-application resources settings (TODO: resources!)
- nglWindow objects will use the application name as their default title
*/
int GetArgCount();
/*!<
Return the number of user arguments passed along the execution of the
program. \b Caution \b ! The executable name (or invocation name) is
not included, use GetName() for this purpose.
*/
const nglString& GetArg(int Index);
/*!<
Return one of the user arguments passed along the execution of the
program. \a Index must be between 0 (first argument) and GetArgCount() - 1.
\b Caution \b ! The executable name (or invocation name) is
not included, use GetName() for this purpose.
If \a Index is out of range, returns an empty string.
*/
//@}
#ifndef _NOCLIPBOARD_
/** @name Clipboard */
//@{
virtual nglClipBoard &GetClipBoard();
virtual void GetClipboard(nglString& rClipboard);
/*!<
Get the clipboard text content
\return If there is text in the clipboard, returns it, or return an empty string
*/
virtual bool SetClipboard(const nglString& rString);
/*!<
Set the text content of the clipboard
\param rString the text to put into the clipboard
\return returns false if the clipboard is not available (maybe temporarily)
*/
//@}
#endif//_NOCLIPBOARD_
#if (!defined _NODND_ || !defined _NOCLIPBOARD_)
/** @name DataTypesRegistry */
//@{
virtual nglDataTypesRegistry& GetDataTypesRegistry();
//@}
#endif//_NODND_ || _NOCLIPBOARD_
/** @name User callbacks */
//@{
virtual void OnInit();
/*!<
This method is called at startup time, as soon as the application is ready to run.
There is always at least one argument, (ArgCnt > 0) and it contains the application
name. User parameters are not available on all platforms (MacOS being one
of them).
*/
virtual void OnExit (int Code);
/*!<
This method is called when the application exits.
\param Code exit code
The exit code is returned by the process to the system. It should be 0
for normal termination (ie. no error encountered), positive otherwise.
The application only quits if :
- Quit() has been explicitely called and the control has been given back to the event loop
- the process received a signal (\e Unix \e only). HUP, INT, QUIT, PIPE and TERM are
currently intercepted.
*/
//@}
virtual void OnDeviceAdded(const nglDeviceInfo* pDeviceInfo);
/*!<
This method is called when a new device is connected to this computer. This can be used to detect new input devices and nglPathVolumes.
\param rDeviceInfo a description of the device.
*/
//@}
virtual void OnDeviceRemoved(const nglDeviceInfo* pDeviceInfo);
/*!<
This method is called when a device is removed from this computer. This can be used to detect input devices and nglPathVolumes removal.
\param rDeviceInfo a description of the device.
*/
//@}
protected:
// Life cycle
nglKernel();
virtual ~nglKernel();
void IncRef();
void DecRef();
void Init();
void Exit();
void SetName (const nglString& rName);
void SetPath (const nglPath& rPath);
void ParseCmdLine (char* pCmdLine);
void AddArg (const nglString& rArg);
void DelArg (int Pos, int Count = 1);
// Internal callbacks
void CallOnInit();
void CallOnExit(int Code);
// From nglError
virtual const nglChar* OnError (uint& rError) const;
#ifdef _UIKIT_
// Called right before the application will be terminated by iPhone OS
virtual void OnWillExit();
#endif
private:
typedef std::list<ExitFunc> ExitFuncList;
typedef std::vector<nglString> ArgList;
uint mRefCount;
bool mDebug;
nglLog* mpLog;
nglConsole* mpCon;
#ifndef _NOCLIPBOARD_
nglClipBoard mClipboard;
#endif
bool mOwnCon;
ExitFuncList mExitFuncs;
nglPath mPath;
nglString mName;
ArgList mArgs;
#if !defined _NODND_ && !defined _NOCLIPBOARD_
nglDataTypesRegistry mDataTypesRegistry;
#endif
nglKernel(const nglKernel&) {} // Undefined copy constructor
#ifdef _WIN32_
protected:
friend class nglConsole;
friend class nglTimer;
friend class nglWindow;
friend class nglInputDeviceDirectX;
friend class nglContext;
friend class nglOffscreenContext;
friend class nglClipBoard;
public:
virtual HINSTANCE GetHInstance() const;
protected:
virtual HWND GetHWnd() const;
virtual HDC GetDC() const;
virtual HFONT GetSystemFont() const;
virtual LPDIRECT3D9 GetDirect3D() const;
bool SysInit(HINSTANCE Inst);
private:
mutable HINSTANCE mHInstance;
mutable HDC mHDC;
mutable HWND mHWnd;
mutable HFONT mSystemFont;
int mResolutionChanged;
bool mShowConsole;
mutable LPDIRECT3D9 mpDirect3D;
static LRESULT CALLBACK MainWndProcStatic (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT MainWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
#endif // _WIN32_
friend class nglPluginKernel;
friend class nglPlugin;
#ifdef _UNIX_
public:
virtual void AddEvent (nglEvent* pEvent);
virtual void DelEvent (nglEvent* pEvent);
virtual void AddTimer (nglTimer* pTimer);
virtual void DelTimer (nglTimer* pTimer);
/* To avoid complex design, we consider the windowing support API
* as part of the core kernel API.
*/
virtual void* GetDisplay();
virtual void AddWindow (class nglWindow* pWin);
virtual void DelWindow (class nglWindow* pWin);
protected:
bool SysInit();
virtual void OnEvent(uint Flags); // From nglEvent
friend class nglWindow;
/* This is needed under Linux because the events are processed using
* a member of nglApplication, so only nglApplication is able to process
* events. nglWindows modalState functions are just plain calls to these ones.
*/
virtual void EnterModalState();
virtual void ExitModalState();
bool mModalState;
private:
void CatchSignal (int Signal, void (*pHandler)(int));
static void OnSignal (int Signal);
#endif // _UNIX_
#ifdef _CARBON_
protected:
bool mExitPosted;
bool SysInit();
friend pascal OSStatus nglVolumeEventHandler (EventHandlerCallRef eventHandlerCallRef, EventRef eventRef, void* userData);
std::list<nglPathVolume> mVolumes;
EventHandlerRef mEventHandlerRef;
EventHandlerProcPtr mEventHandlerUPP;
#endif // _CARBON_
#ifdef _UIKIT_
protected:
//#FIXME: Volume Handling
bool SysInit();
friend void objCCallOnInit(void* pUIApplication);
friend void objCCallOnExit(int Code);
friend void objCCallOnWillExit();
void CallOnWillExit();
void* mpUIApplication;
public:
void * GetUIApplication() { return mpUIApplication; }
#endif//_UIKIT_
};
/*
* NGL kernel log/debug macros
*/
// NGL_OUT(_T("i=%d\n"), i)
#define NGL_OUT App->GetConsole().Output
#define NGL_OUTV App->GetConsole().Outputv
// NGL_LOG(_T("net"), NGL_LOG_INFO, "i=%d\n", i)
#define NGL_LOG App->GetLog().Log
#define NGL_LOGV App->GetLog().Logv
//! From C++ Coding Standards
//! allows fast cast in release and checked in debug
template<typename TTarget, typename TSource> inline TTarget checked_cast(TSource *src) {
NGL_ASSERT(dynamic_cast<TTarget>(src) == static_cast<TTarget>(src) && "checked_cast failed");
return static_cast<TTarget>(src);
}
#endif // __nglKernel_h__