~thumper/nux/next-changes

« back to all changes in this revision

Viewing changes to NuxGraphics/Gfx_OpenGL.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-01 21:15:42 UTC
  • Revision ID: neil.patel@canonical.com-20100901211542-cw2ce3ak28unouwb
Add NuxGraphics with licensing

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2010 Inalogic Inc.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it 
 
5
 * under the terms of the GNU Lesser General Public License version 3, as
 
6
 * published by the  Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but 
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of 
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 
 
11
 * PURPOSE.  See the applicable version of the GNU Lesser General Public 
 
12
 * License for more details.
 
13
 * 
 
14
 * You should have received a copy of both the GNU Lesser General Public 
 
15
 * License version 3 along with this program.  If not, see 
 
16
 * <http://www.gnu.org/licenses/>
 
17
 *
 
18
 * Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com>
 
19
 *
 
20
 */
 
21
 
 
22
 
 
23
#include "GLResource.h"
 
24
#include "GLDeviceFactory.h"
 
25
#include "GLDeviceObjects.h"
 
26
#include "GLResourceManager.h"
 
27
 
 
28
#include "GLTextureResourceManager.h"
 
29
#include "GLVertexResourceManager.h"
 
30
#include "OpenGLEngine.h"
 
31
#include "GLWindowManager.h"
 
32
#include "Gfx_Events.h"
 
33
#include "IniFile.h"
 
34
 
 
35
#include "Gfx_OpenGL.h"
 
36
 
 
37
NAMESPACE_BEGIN_OGL
 
38
 
 
39
// Compute the frame rate every FRAME_RATE_PERIODE;
 
40
#define FRAME_RATE_PERIODE    10
 
41
 
 
42
#define INL_MISSING_GL_EXTENSION_MESSAGE_BOX(message) {MessageBox(NULL, TEXT("Missing extension: " #message), TEXT("ERROR"), MB_OK|MB_ICONERROR); exit(-1);}
 
43
#define INL_ERROR_EXIT_MESSAGE(message) inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, #message " The program will exit.")); exit(-1);
 
44
 
 
45
void ClipOrCenterRectToMonitor(LPRECT prc, t_u32 flags)
 
46
{
 
47
    HMONITOR hMonitor;
 
48
    MONITORINFO mi;
 
49
    RECT        rc;
 
50
    int         w = prc->right  - prc->left;
 
51
    int         h = prc->bottom - prc->top;
 
52
 
 
53
    //
 
54
    // get the nearest monitor to the passed rect.
 
55
    //
 
56
    hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);
 
57
 
 
58
    //
 
59
    // get the work area or entire monitor rect.
 
60
    //
 
61
    mi.cbSize = sizeof(mi);
 
62
    GetMonitorInfo(hMonitor, &mi);
 
63
 
 
64
    //if (flags & MONITOR_WORKAREA)
 
65
        rc = mi.rcWork;
 
66
//    else
 
67
//        rc = mi.rcMonitor;
 
68
 
 
69
    //
 
70
    // center or clip the passed rect to the monitor rect
 
71
    //
 
72
    //if (flags & MONITOR_CENTER)
 
73
    {
 
74
        prc->left   = rc.left + (rc.right  - rc.left - w) / 2;
 
75
        prc->top    = rc.top  + (rc.bottom - rc.top  - h) / 2;
 
76
        prc->right  = prc->left + w;
 
77
        prc->bottom = prc->top  + h;
 
78
    }
 
79
//    else
 
80
//    {
 
81
//        prc->left   = Max(rc.left, Min(rc.right-w,  prc->left));
 
82
//        prc->top    = Max(rc.top,  Min(rc.bottom-h, prc->top));
 
83
//        prc->right  = prc->left + w;
 
84
//        prc->bottom = prc->top  + h;
 
85
//    }
 
86
}
 
87
 
 
88
EventToNameStruct EventToName[] = 
 
89
{
 
90
    {INL_NO_EVENT,               TEXT("INL_NO_EVENT")},
 
91
    {INL_MOUSE_PRESSED,          TEXT("INL_MOUSE_PRESSED")},
 
92
    {INL_MOUSE_RELEASED,         TEXT("INL_MOUSE_RELEASED")},
 
93
    {INL_KEYDOWN,                TEXT("INL_KEYDOWN")},
 
94
    {INL_KEYUP,                  TEXT("INL_KEYUP")},
 
95
    {INL_MOUSE_MOVE,             TEXT("INL_MOUSE_MOVE")},
 
96
    {INL_SIZE_CONFIGURATION,     TEXT("INL_SIZE_CONFIGURATION")},
 
97
    {INL_WINDOW_CONFIGURATION,   TEXT("INL_WINDOW_CONFIGURATION")},
 
98
    {INL_WINDOW_ENTER_FOCUS,     TEXT("INL_WINDOW_ENTER_FOCUS")},
 
99
    {INL_WINDOW_EXIT_FOCUS,      TEXT("INL_WINDOW_EXIT_FOCUS")},
 
100
    {INL_WINDOW_DIRTY,           TEXT("INL_WINDOW_DIRTY")},
 
101
    {INL_WINDOW_MOUSELEAVE,      TEXT("INL_WINDOW_MOUSELEAVE")},
 
102
    {INL_TERMINATE_APP,          TEXT("INL_TERMINATE_APP")}
 
103
};
 
104
 
 
105
//---------------------------------------------------------------------------------------------------------
 
106
HGLRC GLWindowImpl::sMainGLRC = 0;
 
107
HDC   GLWindowImpl::sMainDC = 0;
 
108
 
 
109
GLWindowImpl::GLWindowImpl()
 
110
:   m_pEvent(NULL)
 
111
,   m_GfxInterfaceCreated(false)
 
112
,   m_fullscreen(false)
 
113
,   m_ScreenBitDepth(32)
 
114
,   m_num_device_modes(0)
 
115
,   m_index_of_current_mode(-1)
 
116
,   m_BackupFrameBuffer(true)
 
117
,   m_DeviceFactory(0)
 
118
,   m_GraphicsContext(0)
 
119
// ,   m_GLEWContext(0)
 
120
// ,   m_WGLEWContext(0)
 
121
,   m_Style(WINDOWSTYLE_NORMAL)
 
122
,   m_Cursor(0)
 
123
,   m_PauseGraphicsRendering(false)
 
124
,   m_ParentWindow(0)
 
125
,   m_dwExStyle(0)
 
126
,   m_dwStyle(0)
 
127
{
 
128
    inlSetThreadLocalStorage(ThreadLocal_GLWindowImpl, this);
 
129
 
 
130
        m_GfxInterfaceCreated = false;
 
131
        m_pEvent = new IEvent();
 
132
        GetDisplayInfo();
 
133
 
 
134
    m_WindowSize.SetWidth(0);
 
135
        m_WindowSize.SetHeight(0);
 
136
 
 
137
    // A window never starts in a minimized state.
 
138
    m_is_window_minimized = false;
 
139
 
 
140
 
 
141
    FilePath m_FilePath;
 
142
    m_FilePath.AddSearchPath(TEXT("")); // for case where fully qualified path is given
 
143
    m_FilePath.AddSearchPath(TEXT("./ini"));
 
144
    m_FilePath.AddSearchPath(TEXT("../ini"));
 
145
    m_FilePath.AddSearchPath(TEXT("../../ini"));
 
146
    m_FilePath.AddSearchPath(TEXT("../../../ini"));
 
147
 
 
148
 
 
149
    NString file_search = TEXT("inalogic.ini");
 
150
    NString FileName = m_FilePath.GetFile(file_search.GetTCharPtr());
 
151
    if (FileName == TEXT(""))
 
152
    {
 
153
        nuxDebugMsg(TEXT("[GLWindowImpl::GLWindowImpl] Can't find inalogic.ini file."));
 
154
        inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
155
            TEXT("Can't find .ini file.\nThe program will exit."));
 
156
        exit(-1);
 
157
    }
 
158
 
 
159
    if(FileName != TEXT(""))
 
160
    {
 
161
        NString key_name = TEXT("UseBackupFBO");
 
162
        NString section_name = TEXT("OpenGLSystem");
 
163
 
 
164
        if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()) == false)
 
165
        {
 
166
            nuxDebugMsg(TEXT("[GLWindowImpl::GLWindowImpl] Key [%s] does not exit in .ini file."));
 
167
        }
 
168
        else
 
169
        {
 
170
            NString value = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
 
171
            if((value == TEXT("1")) || (value == TEXT("true")))
 
172
            {
 
173
                m_BackupFrameBuffer = true;
 
174
            }
 
175
            else
 
176
            {
 
177
                m_BackupFrameBuffer = false;
 
178
            }
 
179
        }
 
180
 
 
181
        section_name = TEXT("SearchPath");
 
182
        key_name = TEXT("FontPath");
 
183
        if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()))
 
184
        {
 
185
            NString FontPath = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
 
186
            FontPath.ParseToArray(m_FontSearchPath, TEXT(";"));
 
187
        }
 
188
        else
 
189
        {
 
190
            nuxDebugMsg(TEXT("[GLWindowImpl::GLWindowImpl] Failed to read font search path from .ini file."));
 
191
            inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
192
                TEXT("Failed to read font search path from .ini file.\nThe program will exit."));
 
193
            exit(-1);
 
194
 
 
195
        }
 
196
 
 
197
        key_name = TEXT("UITexturePath");
 
198
        if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()))
 
199
        {
 
200
            NString UITexturePath = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
 
201
            UITexturePath.ParseToArray(m_UITextureSearchPath, TEXT(";"));
 
202
        }
 
203
        else
 
204
        {
 
205
            nuxDebugMsg(TEXT("[GLWindowImpl::GLWindowImpl] Failed to read texture search path from .ini file."));
 
206
            inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
207
                TEXT("Failed to read texture search path from .ini file.\nThe program will exit."));
 
208
            exit(-1);
 
209
        }
 
210
 
 
211
        key_name = TEXT("ShaderPath");
 
212
        if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()))
 
213
        {
 
214
            NString ShaderPath = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
 
215
            ShaderPath.ParseToArray(m_ShaderSearchPath, TEXT(";"));
 
216
        }
 
217
        else
 
218
        {
 
219
            nuxDebugMsg(TEXT("[GLWindowImpl::GLWindowImpl] Failed to read shader search path from .ini file."));
 
220
            inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
221
                TEXT("Failed to read shader search path from .ini file.\nThe program will exit."));
 
222
            exit(-1);
 
223
        }
 
224
    }
 
225
 
 
226
    m_ResourcePathLocation.AddSearchPath(TEXT(""));
 
227
    m_ResourcePathLocation.AddSearchPath(TEXT("./"));
 
228
    m_ResourcePathLocation.AddSearchPath(TEXT("../"));
 
229
    m_ResourcePathLocation.AddSearchPath(TEXT("../../"));
 
230
    m_ResourcePathLocation.AddSearchPath(TEXT("./Data"));
 
231
    m_ResourcePathLocation.AddSearchPath(TEXT("../Data"));
 
232
    m_ResourcePathLocation.AddSearchPath(TEXT("../../Data"));
 
233
    m_ResourcePathLocation.AddSearchPath(TEXT("../../../Data"));
 
234
 
 
235
    m_ResourcePathLocation.AddSearchPath(m_FontSearchPath);
 
236
    m_ResourcePathLocation.AddSearchPath(m_ShaderSearchPath);
 
237
    m_ResourcePathLocation.AddSearchPath(m_UITextureSearchPath);
 
238
}
 
239
 
 
240
//---------------------------------------------------------------------------------------------------------
 
241
GLWindowImpl::~GLWindowImpl()
 
242
{
 
243
    INL_SAFE_DELETE( m_GraphicsContext );
 
244
    INL_SAFE_DELETE( m_DeviceFactory );
 
245
 
 
246
//     INL_SAFE_DELETE( m_WGLEWContext );
 
247
//     INL_SAFE_DELETE( m_GLEWContext );
 
248
 
 
249
    DestroyOpenGLWindow();
 
250
    INL_SAFE_DELETE( m_pEvent );
 
251
 
 
252
    inlSetThreadLocalStorage(ThreadLocal_GLWindowImpl, 0);
 
253
}
 
254
 
 
255
//---------------------------------------------------------------------------------------------------------
 
256
NString GLWindowImpl::FindResourceLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
 
257
{
 
258
    NString path = m_ResourcePathLocation.GetFile(ResourceFileName);
 
259
 
 
260
    if(path == TEXT("") && ErrorOnFail)
 
261
    {
 
262
        nuxDebugMsg(TEXT("[GLWindowImpl::FindResourceLocation] Failed to locate resource file: %s."), ResourceFileName);
 
263
        inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
264
            TEXT("Failed to locate resource file %s.\nThe program will exit."), ResourceFileName);
 
265
        exit(1);
 
266
    }
 
267
    return path;
 
268
}
 
269
 
 
270
NString GLWindowImpl::FindUITextureLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
 
271
{
 
272
    FilePath searchpath;
 
273
    searchpath.AddSearchPath(m_UITextureSearchPath);
 
274
    NString path = searchpath.GetFile(ResourceFileName);
 
275
 
 
276
    if((path == TEXT("")) && ErrorOnFail)
 
277
    {
 
278
        nuxDebugMsg(TEXT("[GLWindowImpl::FindResourceLocation] Failed to locate ui texture file: %s."), ResourceFileName);
 
279
        inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
280
            TEXT("Failed to locate ui texture file %s.\nThe program will exit."), ResourceFileName);
 
281
        exit(1);
 
282
    }
 
283
    return path;
 
284
}
 
285
 
 
286
NString GLWindowImpl::FindShaderLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
 
287
{
 
288
    FilePath searchpath;
 
289
    searchpath.AddSearchPath(m_ShaderSearchPath);
 
290
    NString path = searchpath.GetFile(ResourceFileName);
 
291
 
 
292
    if((path == TEXT("")) && ErrorOnFail)
 
293
    {
 
294
        nuxDebugMsg(TEXT("[GLWindowImpl::FindResourceLocation] Failed to locate shader file: %s."), ResourceFileName);
 
295
        inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
296
            TEXT("Failed to locate shader file %s.\nThe program will exit."), ResourceFileName);
 
297
        exit(1);
 
298
    }
 
299
    return path;
 
300
}
 
301
 
 
302
NString GLWindowImpl::FindFontLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
 
303
{
 
304
    FilePath searchpath;
 
305
    searchpath.AddSearchPath(m_FontSearchPath);
 
306
    NString path = searchpath.GetFile(ResourceFileName);
 
307
 
 
308
    if((path == TEXT("")) && ErrorOnFail)
 
309
    {
 
310
        nuxDebugMsg(TEXT("[GLWindowImpl::FindResourceLocation] Failed to locate font file file: %s."), ResourceFileName);
 
311
        inlWin32MessageBox(NULL, TEXT("Error"), MBTYPE_Ok, MBICON_Error, MBMODAL_ApplicationModal, 
 
312
            TEXT("Failed to locate font file %s.\nThe program will exit."), ResourceFileName);
 
313
        exit(1);
 
314
    }
 
315
    return path;
 
316
}
 
317
 
 
318
 
 
319
//---------------------------------------------------------------------------------------------------------
 
320
bool GLWindowImpl::IsGfxInterfaceCreated()
 
321
{
 
322
        return m_GfxInterfaceCreated;
 
323
}
 
324
 
 
325
//---------------------------------------------------------------------------------------------------------
 
326
static NCriticalSection CreateOpenGLWindow_CriticalSection;
 
327
bool GLWindowImpl::CreateOpenGLWindow(const TCHAR* WindowTitle,
 
328
                                      unsigned int WindowWidth,
 
329
                                      unsigned int WindowHeight,
 
330
                                      WindowStyle Style,
 
331
                                      const GLWindowImpl* Parent,
 
332
                                      bool FullscreenFlag)
 
333
{
 
334
    NScopeLock Scope(&CreateOpenGLWindow_CriticalSection);
 
335
 
 
336
        RECT            WindowRect;                             // Grabs Rectangle Upper Left / Lower Right Values
 
337
 
 
338
        m_GfxInterfaceCreated = false;
 
339
 
 
340
        // FIXME : put at the end
 
341
        m_ViewportSize.SetWidth(WindowWidth);
 
342
        m_ViewportSize.SetHeight(WindowHeight);
 
343
        m_WindowSize.SetWidth(WindowWidth);
 
344
        m_WindowSize.SetHeight(WindowHeight);
 
345
 
 
346
        // end of fixme
 
347
 
 
348
        WindowRect.left     = (long)0;
 
349
        WindowRect.right    = (long)m_ViewportSize.GetWidth();
 
350
        WindowRect.top      = (long)0;  
 
351
        WindowRect.bottom   = (long)m_ViewportSize.GetHeight();
 
352
 
 
353
        m_fullscreen = FullscreenFlag;                                                          // Set The Global Fullscreen Flag
 
354
        m_index_of_current_mode = -1;                                                           // assume -1 if the mode is not fullscreen
 
355
 
 
356
 
 
357
        if (m_fullscreen)                                                                               // Attempt Fullscreen Mode?
 
358
        {
 
359
                // check if resolution is supported
 
360
                bool mode_supported = false;
 
361
                for(int num_modes = 0 ; num_modes < m_num_gfx_device_modes; num_modes++)
 
362
                {
 
363
                        if((m_gfx_device_modes[num_modes].width == m_ViewportSize.GetWidth()) 
 
364
                                && (m_gfx_device_modes[num_modes].height == m_ViewportSize.GetHeight())
 
365
                                && (m_gfx_device_modes[num_modes].format == m_ScreenBitDepth))
 
366
                        {
 
367
                                mode_supported = true;
 
368
                                m_index_of_current_mode = num_modes;
 
369
                                break;
 
370
                        }
 
371
                }
 
372
 
 
373
                if(mode_supported == false)
 
374
                {
 
375
            if(inlWin32MessageBox(NULL, TEXT("Info"), MBTYPE_Ok, MBICON_Information, MBMODAL_ApplicationModal,
 
376
                TEXT("The requested fullscreen mode is not supported by your monitor.\nUsing windowed mode instead.")) == MBRES_Yes)
 
377
                        {
 
378
                                m_fullscreen = FALSE;           // Windowed Mode Selected.  Fullscreen = FALSE
 
379
                        }
 
380
                }
 
381
 
 
382
                DEVMODE dmScreenSettings;                                               // Device Mode
 
383
                memset(&dmScreenSettings,0,sizeof(dmScreenSettings));                   // Makes Sure Memory's Cleared
 
384
                dmScreenSettings.dmSize = sizeof(dmScreenSettings);                     // Size Of The Devmode Structure
 
385
                dmScreenSettings.dmPelsWidth    = m_ViewportSize.GetWidth();                 // Selected Screen Width
 
386
                dmScreenSettings.dmPelsHeight   = m_ViewportSize.GetHeight();                // Selected Screen Height
 
387
                dmScreenSettings.dmBitsPerPel   = m_ScreenBitDepth;                              // Selected Bits Per Pixel
 
388
                dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
 
389
 
 
390
                // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
 
391
                if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
 
392
                {
 
393
            if(inlWin32MessageBox(NULL, TEXT("Info"), MBTYPE_Ok, MBICON_Information, MBMODAL_ApplicationModal,
 
394
                TEXT("The requested fullscreen mode is not supported by your monitor.\nUsing windowed mode instead.")) == MBRES_Yes)
 
395
                        {
 
396
                                m_fullscreen = FALSE;                   // Windowed Mode Selected.  Fullscreen = FALSE
 
397
                        }
 
398
                        else
 
399
                        {
 
400
                                // Pop Up A Message Box Letting User Know The Program Is Closing.
 
401
                                MessageBox(NULL,"Program Will Now Close.","ERROR", MB_OK|MB_ICONSTOP);
 
402
                                exit(1);
 
403
                        }
 
404
                }
 
405
        }
 
406
 
 
407
    m_dwExStyle = 0;
 
408
    m_dwStyle = 0;
 
409
        if(m_fullscreen)                                    // Are We Still In Fullscreen Mode?
 
410
        {
 
411
                m_dwExStyle = WS_EX_APPWINDOW;                    // Window Extended Style
 
412
                m_dwStyle = WS_POPUP;                             // Windows Style
 
413
                ShowCursor(TRUE);                               // Hide Mouse Pointer
 
414
        }
 
415
        else
 
416
        {
 
417
        // Window Extended Style
 
418
                m_dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
 
419
        // Windows Style
 
420
        m_dwStyle = WS_OVERLAPPED;    // Creates an overlapped window. An overlapped window has a title bar and a border
 
421
        }
 
422
 
 
423
    // See Win32 Window Hierarchy and Styles: http://msdn.microsoft.com/en-us/library/ms997562.aspx
 
424
 
 
425
    //WS_EX_APPWINDOW       // Forces a top-level window onto the taskbar when the window is visible
 
426
    //WS_EX_WINDOWEDGE      // Specifies that a window has a border with a raised edge
 
427
 
 
428
    //WS_POPUP      // Creates a pop-up window. This style cannot be used with the WS_CHILD style.
 
429
    //WS_SYSMENU    // Creates a window that has a window menu on its title bar. The WS_CAPTION style must also be specified.
 
430
    //WS_SIZEBOX    // Creates a window that has a sizing border. Same as the WS_THICKFRAME style.
 
431
    //WS_CAPTION    // Creates a window that has a title bar (includes the WS_BORDER style).
 
432
 
 
433
    m_Style = Style;
 
434
    if(Style == WINDOWSTYLE_TOOL)
 
435
    {
 
436
        m_dwExStyle = WS_EX_TOOLWINDOW;
 
437
        m_dwStyle = WS_CAPTION | WS_SYSMENU;
 
438
    }
 
439
    else if(Style == WINDOWSTYLE_DIALOG)
 
440
    {
 
441
        m_dwExStyle = WS_EX_DLGMODALFRAME;
 
442
        m_dwStyle = WS_CAPTION | WS_SYSMENU;
 
443
    }
 
444
    else if(Style == WINDOWSTYLE_NOBORDER)
 
445
    {
 
446
        m_dwExStyle = WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
 
447
        m_dwStyle = WS_POPUP;
 
448
    }
 
449
    else if(Style == WINDOWSTYLE_PANEL)
 
450
    {
 
451
        m_dwExStyle = 0;           // Specifies that a window has a border with a raised edge
 
452
        m_dwStyle = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX;
 
453
    }
 
454
    else
 
455
    {
 
456
        // Normal Window: NormalWindow
 
457
        m_dwExStyle = WS_EX_APPWINDOW |   // Forces a top-level window onto the taskbar when the window is visible
 
458
            WS_EX_WINDOWEDGE;           // Specifies that a window has a border with a raised edge
 
459
 
 
460
        m_dwStyle |= WS_CAPTION | // Creates a window that has a title bar.
 
461
            WS_SYSMENU |        // Creates a window that has a window menu on its title bar. The WS_CAPTION style must also be specified.
 
462
            WS_THICKFRAME |     // Creates a window that has a sizing border.
 
463
            WS_MINIMIZEBOX |    // Creates a window that has a minimize button.
 
464
            WS_MAXIMIZEBOX |    // Creates a window that has a maximize button.
 
465
            WS_BORDER;          // Creates a window that has a thin-line border.
 
466
    }
 
467
 
 
468
    // The AdjustWindowRectEx function calculates the required size of the window rectangle,
 
469
    // based on the desired size of the client rectangle. The window rectangle can then be passed to
 
470
    // the CreateWindowEx function to create a window whose client area is the desired size.
 
471
        AdjustWindowRectEx(&WindowRect, m_dwStyle, FALSE, m_dwExStyle);     // Adjust Window To True Requested Size
 
472
 
 
473
    RECT rect;
 
474
    rect.top = 0;
 
475
    rect.bottom = WindowRect.bottom-WindowRect.top;
 
476
    rect.left = 0;
 
477
    rect.right = WindowRect.right-WindowRect.left;
 
478
    int WindowX = 0;
 
479
    int WindowY = 0;
 
480
    if(Parent)
 
481
    {
 
482
        m_ParentWindow = Parent->GetWindowHandle();
 
483
        GetWindowRect(m_ParentWindow, &rect);
 
484
 
 
485
        int width = rect.right - rect.left;
 
486
        int height = rect.bottom - rect.top;
 
487
 
 
488
        WindowX = rect.left + (width - (WindowRect.right-WindowRect.left))/2;
 
489
        WindowY = rect.top + (height - (WindowRect.bottom-WindowRect.top))/2;
 
490
    }
 
491
    else
 
492
    {
 
493
        ClipOrCenterRectToMonitor(&rect, 0);
 
494
        WindowX = rect.left;
 
495
        WindowY = rect.top;
 
496
    }
 
497
    
 
498
    m_WindowTitle = WindowTitle;
 
499
        // Create The Window
 
500
    if (!(m_hWnd = ::CreateWindowEx(m_dwExStyle,                        // Extended Style For The Window
 
501
                                WINDOW_CLASS_NAME,                  // Class Name
 
502
                                m_WindowTitle.GetTCharPtr(),        // Window Title
 
503
                                m_dwStyle |                           // Defined Window Style
 
504
                                WS_CLIPSIBLINGS |                   // Required Window Style
 
505
                                WS_CLIPCHILDREN,                    // Required Window Style
 
506
                                WindowX, WindowY,                   // Window Position
 
507
                                WindowRect.right-WindowRect.left,   // Calculate Window Width
 
508
                                WindowRect.bottom-WindowRect.top,   // Calculate Window Height
 
509
                                m_ParentWindow,                     // No Parent Window
 
510
                                NULL,                               // No Menu
 
511
                                gGLWindowManager.GetInstance(),     // Instance
 
512
                                NULL)))                             // Dont Pass Anything To WM_CREATE
 
513
        {
 
514
                DestroyOpenGLWindow();
 
515
                MessageBox(NULL, TEXT("Window Creation Error."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
 
516
                exit(1);                                                    // Return FALSE
 
517
        }
 
518
 
 
519
        static  PIXELFORMATDESCRIPTOR pfd=                              // pfd Tells Windows How We Want Things To Be
 
520
        {
 
521
                sizeof(PIXELFORMATDESCRIPTOR),                          // Size Of This Pixel Format Descriptor
 
522
                1,                                                                                      // Version Number
 
523
                PFD_DRAW_TO_WINDOW |                                            // Format Must Support Window
 
524
                PFD_SUPPORT_OPENGL |                                            // Format Must Support OpenGL
 
525
                PFD_DOUBLEBUFFER,                                   // Must Support Double Buffering
 
526
                PFD_TYPE_RGBA,                                                          // Request An RGBA Format
 
527
        24,     //        cColorBits
 
528
            //        Specifies the number of color bitplanes in each color buffer. 
 
529
            //        For RGBA pixel types, it is the size of the color buffer, excluding the alpha bitplanes. 
 
530
            //        For color-index pixels, it is the size of the color-index buffer.
 
531
        
 
532
 
 
533
        0, //        cRedBits
 
534
           //        Specifies the number of red bitplanes in each RGBA color buffer.
 
535
        0, //        cRedShift
 
536
           //        Specifies the shift count for red bitplanes in each RGBA color buffer.
 
537
        0, //        cGreenBits
 
538
           //        Specifies the number of green bitplanes in each RGBA color buffer.
 
539
        0, //        cGreenShift
 
540
           //        Specifies the shift count for green bitplanes in each RGBA color buffer.
 
541
        0, //        cBlueBits
 
542
           //        Specifies the number of blue bitplanes in each RGBA color buffer.
 
543
        0, //        cBlueShift
 
544
           //        Specifies the shift count for blue bitplanes in each RGBA color buffer.
 
545
 
 
546
        0, //        cAlphaBits
 
547
           //        Specifies the number of alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported.
 
548
        0, //        cAlphaShift
 
549
           //        Specifies the shift count for alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported.
 
550
 
 
551
        0, //        cAccumBits
 
552
           //        Specifies the total number of bitplanes in the accumulation buffer.
 
553
        0, //        cAccumRedBits
 
554
           //        Specifies the number of red bitplanes in the accumulation buffer.
 
555
        0, //        cAccumGreenBits
 
556
           //        Specifies the number of green bitplanes in the accumulation buffer.
 
557
        0, //        cAccumBlueBits
 
558
           //        Specifies the number of blue bitplanes in the accumulation buffer.
 
559
        0, //        cAccumAlphaBits
 
560
           //        Specifies the number of alpha bitplanes in the accumulation buffer.
 
561
        24,//        cDepthBits
 
562
           //        Specifies the depth of the depth (z-axis) buffer.
 
563
        8, //        cStencilBits
 
564
           //        Specifies the depth of the stencil buffer.
 
565
        0, //        cAuxBuffers
 
566
           //        Specifies the number of auxiliary buffers. Auxiliary buffers are not supported.
 
567
        PFD_MAIN_PLANE,   //        iLayerType
 
568
           //        Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
 
569
        0, //        bReserved
 
570
           //        Specifies the number of overlay and underlay planes. Bits 0 through 3 specify up to 15 overlay planes and bits 4 through 7 specify up to 15 underlay planes.
 
571
        0, //        dwLayerMask
 
572
           //        Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
 
573
        0, //        dwVisibleMask
 
574
           //        Specifies the transparent color or index of an underlay plane. When the pixel type is RGBA, dwVisibleMask is a transparent RGB color value. When the pixel type is color index, it is a transparent index value.
 
575
        0, //        dwDamageMask
 
576
           //        Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
 
577
        };
 
578
 
 
579
        if (!(m_hDC = GetDC(m_hWnd)))   // Did We Get A Device Context?
 
580
        {
 
581
                DestroyOpenGLWindow();
 
582
                MessageBox(NULL, TEXT("Can't Create A GL Device Context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
 
583
                return FALSE;
 
584
        }
 
585
 
 
586
        if (!(m_PixelFormat = ChoosePixelFormat(m_hDC, &pfd)))    // Did Windows Find A Matching Pixel Format?
 
587
        {
 
588
                DestroyOpenGLWindow();
 
589
                MessageBox(NULL, TEXT("Can't Find A Suitable PixelFormat."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
 
590
                return FALSE;
 
591
        }
 
592
 
 
593
        if(!SetPixelFormat(m_hDC, m_PixelFormat, &pfd))           // Are We Able To Set The Pixel Format?
 
594
        {
 
595
                DestroyOpenGLWindow();
 
596
                MessageBox(NULL, TEXT("Can't Set The PixelFormat."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
 
597
                return FALSE;
 
598
        }
 
599
 
 
600
        if (!(m_GLRC = wglCreateContext(m_hDC)))                   // Are We Able To Get A Rendering Context?
 
601
        {
 
602
                DestroyOpenGLWindow();
 
603
                MessageBox(NULL, TEXT("Can't Create A GL Rendering Context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
 
604
                return FALSE;
 
605
        }
 
606
 
 
607
    if(sMainGLRC == 0)
 
608
    {
 
609
        sMainGLRC = m_GLRC;
 
610
        sMainDC = m_hDC;
 
611
    }
 
612
    else
 
613
    {
 
614
//         wglMakeCurrent(m_hDC, 0);
 
615
//         // Make the newly created context share it resources with all the other OpenGL context
 
616
//         if(wglShareLists(sMainGLRC, m_GLRC) == FALSE)
 
617
//         {
 
618
//             DWORD err = GetLastError();
 
619
//             DestroyOpenGLWindow();
 
620
//             MessageBox(NULL, TEXT("Can't share GL context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
 
621
//             return FALSE;
 
622
//         }
 
623
    }
 
624
 
 
625
    // This creates a  warning. It is a 64-bits compatibility issue. 
 
626
    // When not in 64-bit you can disable the warning:
 
627
    // Project Properties --> C/C++ tab --> General --> Select "NO" for - Detect 64-bit Portability Issues.
 
628
    // See also SetWindowLongPtr
 
629
    SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (INL_PTRSIZE_LONG) this); 
 
630
 
 
631
    //::ShowWindow(m_hWnd,SW_SHOW);                                             // Show The Window
 
632
    ::SetForegroundWindow(m_hWnd);                                              // Slightly Higher Priority
 
633
    ::SetFocus(m_hWnd);                                                                 // Sets Keyboard Focus To The Window
 
634
 
 
635
        MakeGLContextCurrent();
 
636
    glClearColor(0.0, 0.0, 0.0, 0.0);
 
637
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
638
    SwapBuffer();
 
639
 
 
640
        m_GfxInterfaceCreated = true;
 
641
 
 
642
    //m_GLEWContext = new GLEWContext();
 
643
    //m_WGLEWContext = new WGLEWContext();
 
644
 
 
645
    m_DeviceFactory = new GLDeviceFactory(m_ViewportSize.GetWidth(), m_ViewportSize.GetHeight(), BITFMT_R8G8B8A8);
 
646
    m_GraphicsContext = new GraphicsContext(*this);
 
647
 
 
648
    //EnableVSyncSwapControl();
 
649
    //DisableVSyncSwapControl();
 
650
 
 
651
        return true;
 
652
}
 
653
 
 
654
bool GLWindowImpl::CreateFromOpenGLWindow(HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext)
 
655
{
 
656
    m_hWnd = WindowHandle;
 
657
    m_hDC = WindowDCHandle;
 
658
    m_GLRC = OpenGLRenderingContext;
 
659
 
 
660
    RECT rect;
 
661
    ::GetClientRect(m_hWnd, &rect);
 
662
    m_WindowSize = Size(rect.right - rect.left, rect.bottom - rect.top);
 
663
    m_ViewportSize = Size(rect.right - rect.left, rect.bottom - rect.top);
 
664
 
 
665
    MakeGLContextCurrent();
 
666
    glClearColor(0.0, 0.0, 0.0, 0.0);
 
667
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
668
    SwapBuffer();
 
669
 
 
670
    m_GfxInterfaceCreated = true;
 
671
    m_DeviceFactory = new GLDeviceFactory(m_ViewportSize.GetWidth(), m_ViewportSize.GetHeight(), BITFMT_R8G8B8A8);
 
672
    m_GraphicsContext = new GraphicsContext(*this);
 
673
 
 
674
    return true;
 
675
}
 
676
 
 
677
//---------------------------------------------------------------------------------------------------------
 
678
bool GLWindowImpl::HasFrameBufferSupport()
 
679
{
 
680
    return m_DeviceFactory->SUPPORT_GL_EXT_FRAMEBUFFER_OBJECT() && m_BackupFrameBuffer;
 
681
}
 
682
 
 
683
//---------------------------------------------------------------------------------------------------------
 
684
void GLWindowImpl::GetWindowSize(int &w, int &h)
 
685
{
 
686
        w = m_WindowSize.GetWidth();
 
687
        h = m_WindowSize.GetHeight();
 
688
}
 
689
 
 
690
//---------------------------------------------------------------------------------------------------------
 
691
unsigned int GLWindowImpl::GetWindowWidth()
 
692
{
 
693
        return m_WindowSize.GetWidth();
 
694
}
 
695
 
 
696
//---------------------------------------------------------------------------------------------------------
 
697
unsigned int GLWindowImpl::GetWindowHeight()
 
698
{
 
699
    return m_WindowSize.GetHeight();
 
700
}
 
701
 
 
702
//---------------------------------------------------------------------------------------------------------
 
703
void GLWindowImpl::SetWindowSize(int width, int height)
 
704
{
 
705
    RECT window_rect;
 
706
    RECT new_rect;
 
707
    ::GetWindowRect(m_hWnd, &window_rect);
 
708
 
 
709
    new_rect.left = 0; new_rect.right = width;
 
710
    new_rect.top = 0; new_rect.bottom = height;
 
711
    BOOL b = ::AdjustWindowRectEx(&new_rect, m_dwStyle, FALSE, m_dwExStyle);     // Adjust Window To True Requested Size
 
712
 
 
713
    ::MoveWindow(m_hWnd,
 
714
        window_rect.left,
 
715
        window_rect.top,
 
716
        (new_rect.right - new_rect.left),
 
717
        (new_rect.bottom - new_rect.top),
 
718
        TRUE);
 
719
}
 
720
 
 
721
//---------------------------------------------------------------------------------------------------------
 
722
void GLWindowImpl::SetViewPort(int x, int y, int width, int height)
 
723
{
 
724
    if(IsGfxInterfaceCreated())
 
725
    {
 
726
        //do not rely on m_ViewportSize: glViewport can be called directly
 
727
        m_ViewportSize.SetWidth(width);
 
728
        m_ViewportSize.SetHeight(height);
 
729
 
 
730
        m_GraphicsContext->SetViewport(x, y, m_ViewportSize.GetWidth(), m_ViewportSize.GetHeight());
 
731
        m_GraphicsContext->SetScissor(0, 0, width, height);
 
732
    }
 
733
}
 
734
 
 
735
Point GLWindowImpl::GetMouseScreenCoord()
 
736
{
 
737
    POINT pt;
 
738
    ::GetCursorPos(&pt);
 
739
    ScreenToClient(m_hWnd, &pt);
 
740
    Point point(pt.x, pt.y);
 
741
    return point;
 
742
}
 
743
 
 
744
Point GLWindowImpl::GetMouseWindowCoord()
 
745
{
 
746
    POINT pt;
 
747
    ::GetCursorPos(&pt);
 
748
    ::ScreenToClient(m_hWnd, &pt);
 
749
    Point point(pt.x, pt.y);
 
750
    return point;
 
751
}
 
752
 
 
753
Point GLWindowImpl::GetWindowCoord()
 
754
{
 
755
    RECT rect;
 
756
    ::GetWindowRect(m_hWnd, &rect);
 
757
    Point point(rect.left, rect.top);
 
758
    return point;
 
759
}
 
760
 
 
761
Rect GLWindowImpl::GetWindowGeometry()
 
762
{
 
763
    RECT rect;
 
764
    ::GetClientRect(m_hWnd, &rect);
 
765
    Rect geo(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
 
766
    return geo;
 
767
}
 
768
 
 
769
Rect GLWindowImpl::GetNCWindowGeometry()
 
770
{
 
771
    RECT rect;
 
772
    ::GetWindowRect(m_hWnd, &rect);
 
773
    Rect geo(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
 
774
    return geo;
 
775
}
 
776
 
 
777
//---------------------------------------------------------------------------------------------------------
 
778
//void GLWindowImpl::EnableBackupFrameBuffer()
 
779
//{
 
780
//    if(m_BackupFrameBuffer)
 
781
//    {
 
782
//        m_MainFBO->Enable();
 
783
//    }
 
784
//}
 
785
//
 
786
//void GLWindowImpl::DisableBackupFrameBuffer()
 
787
//{
 
788
//    if(m_BackupFrameBuffer)
 
789
//    {
 
790
//        m_MainFBO->Disable();
 
791
//    }
 
792
//}
 
793
//
 
794
//void GLWindowImpl::BackupFrameBufferBind()
 
795
//{
 
796
//    if(m_BackupFrameBuffer)
 
797
//    {
 
798
//        m_MainFBO->BindToTexUnit0();
 
799
//    }
 
800
//}
 
801
//---------------------------------------------------------------------------------------------------------
 
802
void GLWindowImpl::MakeGLContextCurrent(bool b)
 
803
{
 
804
    HGLRC glrc = m_GLRC;
 
805
    if(b == false)
 
806
    {
 
807
        glrc = 0;
 
808
    }
 
809
 
 
810
    if(!wglMakeCurrent(m_hDC, glrc))
 
811
    {
 
812
        NString error = inlGetSystemErrorMessage();
 
813
        DestroyOpenGLWindow();
 
814
        MessageBox(NULL, TEXT("Can't Activate The GL Rendering Context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
 
815
    }
 
816
}
 
817
//---------------------------------------------------------------------------------------------------------
 
818
void GLWindowImpl::SwapBuffer(bool glswap)
 
819
{
 
820
    if(IsPauseThreadGraphicsRendering())
 
821
        return;
 
822
 
 
823
    if(glswap)
 
824
    {
 
825
            SwapBuffers(m_hDC);
 
826
    }
 
827
 
 
828
    m_FrameTime = m_Timer.PassedMilliseconds();
 
829
 
 
830
//     if(16.6f - m_FrameTime > 0)
 
831
//     {
 
832
//         SleepForMilliseconds(16.6f - m_FrameTime);
 
833
//     }
 
834
// 
 
835
//     m_FrameTime = m_Timer.PassedMilliseconds();
 
836
//     m_Timer.Reset();
 
837
//     m_PeriodeTime += m_FrameTime;
 
838
// 
 
839
//     m_FrameCounter++;
 
840
//     m_FramePeriodeCounter++;
 
841
//     if(m_FramePeriodeCounter >= FRAME_RATE_PERIODE)
 
842
//     {
 
843
//         m_FrameRate = m_FramePeriodeCounter * 1000.0f / m_PeriodeTime;
 
844
//         m_PeriodeTime = 0.0f;
 
845
//         m_FramePeriodeCounter = 0;
 
846
//     }
 
847
}
 
848
//---------------------------------------------------------------------------------------------------------
 
849
void GLWindowImpl::DestroyOpenGLWindow()
 
850
{
 
851
    if(m_GfxInterfaceCreated == true)
 
852
    {
 
853
            if (m_fullscreen)                                                                           // Are We In Fullscreen Mode?
 
854
            {
 
855
                    ChangeDisplaySettings(NULL,0);                                      // If So Switch Back To The Desktop
 
856
                    ShowCursor(TRUE);                                                           // Show Mouse Pointer
 
857
            }
 
858
 
 
859
            if (m_GLRC)                                                                                 // Do We Have A Rendering Context?
 
860
            {
 
861
                    if (!wglMakeCurrent(m_hDC, NULL))                                   // Are We Able To Release The DC And RC Contexts?
 
862
                    {
 
863
                            MessageBox(NULL, TEXT("Release Of DC And RC Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 
864
                    }
 
865
 
 
866
                    if (!wglDeleteContext(m_GLRC))                                              // Are We Able To Delete The RC?
 
867
                    {
 
868
                            MessageBox(NULL, TEXT("Release Rendering Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 
869
                    }
 
870
                    m_GLRC = NULL;                                                                              // Set RC To NULL
 
871
            }
 
872
 
 
873
            if (m_hDC && !ReleaseDC(m_hWnd, m_hDC))                                     // Are We Able To Release The DC
 
874
            {
 
875
                    MessageBox(NULL, TEXT("Release Device Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 
876
                    m_hDC = NULL;                                                                               // Set DC To NULL
 
877
            }
 
878
 
 
879
        if (m_hWnd && !(::DestroyWindow(m_hWnd)))                                       // Are We Able To Destroy The Window?
 
880
            {
 
881
                    MessageBox(NULL, TEXT("Could Not Release window handle."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 
882
                    m_hWnd = NULL;                                                                              // Set Window Handle To NULL
 
883
            }
 
884
    }
 
885
    m_GfxInterfaceCreated = false;
 
886
}
 
887
 
 
888
 
 
889
// //---------------------------------------------------------------------------------------------------------
 
890
// // convert a MSWindows VK_x to an Fltk (X) Keysym:
 
891
// // See also the inverse converter in Fl_get_key_win32.cxx
 
892
// // This table is in numeric order by VK:
 
893
// static const struct {unsigned short vk, fltk, extended;} vktab[] = {
 
894
//     {INL_VK_BACK,        INL_BackSpace},
 
895
//     {INL_VK_TAB,         INL_Tab},
 
896
//     {INL_VK_CLEAR,       INL_Clear,      0xff0b/*XK_Clear*/},
 
897
//     {INL_VK_ENTER,       INL_Enter,      INL_KP_ENTER},
 
898
//     {INL_VK_SHIFT,       INL_Shift_L,        INL_EXT_Shift_R},
 
899
//     {INL_VK_CONTROL, INL_Control_L,  INL_EXT_Control_R},
 
900
//     {INL_VK_MENU,        INL_Alt_L,      INL_EXT_Alt_R},
 
901
//     {INL_VK_PAUSE,       INL_Pause},
 
902
//     {INL_VK_CAPITAL, INL_Caps_Lock},
 
903
//     {INL_VK_ESCAPE,      INL_Escape},
 
904
//     {INL_VK_SPACE,       ' '},
 
905
//     {INL_VK_PAGE_UP, INL_Page_Up     /*KP+'9'*/,         INL_KP_PAGE_UP},
 
906
//     {INL_VK_PAGE_DOWN,  INL_Page_Down   /*KP+'3'*/,      INL_KP_PAGE_DOWN},
 
907
//     {INL_VK_END,         INL_End         /*KP+'1'*/,     INL_KP_END},
 
908
//     {INL_VK_HOME,        INL_Home        /*KP+'7'*/,     INL_KP_HOME},
 
909
//     {INL_VK_LEFT,        INL_Left        /*KP+'4'*/,     INL_KP_LEFT},
 
910
//     {INL_VK_UP,              INL_Up          /*KP+'8'*/,         INL_KP_UP},
 
911
//     {INL_VK_RIGHT,       INL_Right       /*KP+'6'*/,     INL_KP_RIGHT},
 
912
//     {INL_VK_DOWN,        INL_Down        /*KP+'2'*/,     INL_KP_DOWN},
 
913
//     {INL_VK_SNAPSHOT,        INL_Print},         // does not work on NT
 
914
//     {INL_VK_INSERT,      INL_Insert      /*KP+'0'*/,     INL_KP_INSERT},
 
915
//     {INL_VK_DELETE,      INL_Delete      /*KP+'.'*/,     INL_KP_DELETE},
 
916
//     {INL_VK_LWIN,        INL_LWin        /*Meta_L*/},
 
917
//     {INL_VK_RWIN,        INL_RWin        /*Meta_R*/},
 
918
//     {INL_VK_APPS,        INL_VK_APPS     /*Menu*/},
 
919
//     {INL_VK_MULTIPLY,        INL_Multiply    /*KP+'*'*/},
 
920
//     {INL_VK_ADD,         INL_Add         /*KP+'+'*/},
 
921
//     {INL_VK_SUBTRACT,        INL_Subtract    /*KP+'-'*/},
 
922
//     {INL_VK_DECIMAL, INL_Decimal     /*KP+'.'*/},
 
923
//     {INL_VK_DIVIDE,      INL_Divide      /*KP+'/'*/},
 
924
//     {INL_VK_NUMLOCK, INL_Numlock     /*Num_Lock*/},
 
925
//     {INL_VK_SCROLL,      INL_Scroll      /*Scroll_Lock*/},
 
926
//     {0xba,   ';'},
 
927
//     {0xbb,   '='},
 
928
//     {0xbc,   ','},
 
929
//     {0xbd,   '-'},
 
930
//     {0xbe,   '.'},
 
931
//     {0xbf,   '/'},
 
932
//     {0xc0,   '`'},
 
933
//     {0xdb,   '['},
 
934
//     {0xdc,   '\\'},
 
935
//     {0xdd,   ']'},
 
936
//     {0xde,   '\''}
 
937
// };
 
938
 
 
939
 /*
 
940
     The extended-key flag indicates whether the keystroke message originated
 
941
     from one of the additional keys on the enhanced keyboard. The extended keys
 
942
     consist of the ALT and CTRL keys on the right-hand side of the keyboard;
 
943
     the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters
 
944
     to the left of the numeric keypad; the NUM LOCK key; the BREAK (CTRL+PAUSE) key;
 
945
     the PRINT SCRN key; and the divide (/) and ENTER keys in the numeric keypad.
 
946
     The extended-key flag is set if the key is an extended key.
 
947
 */
 
948
//---------------------------------------------------------------------------------------------------------
 
949
/*static int ms2fltk(int vk, int extended)
 
950
{
 
951
    static unsigned short vklut[256];
 
952
    static unsigned short extendedlut[256];
 
953
    if (!vklut[1])
 
954
    {
 
955
        // init the table
 
956
        unsigned int i;
 
957
        for (i = 0; i < 256; i++) 
 
958
        {
 
959
            vklut[i] = i; //tolower(i);
 
960
        }
 
961
//        for (i=VK_F1; i<=VK_F16; i++)
 
962
//        {
 
963
//            vklut[i] = i+(FL_F-(VK_F1-1));   // (FL_F + 1 -> VK_F1) ... (FL_F + 16 -> VK_F16)
 
964
//        }
 
965
//        for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++)
 
966
//        {
 
967
//            vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0);    // (FL_KP + '0' -> VK_NUMPAD0) ... (FL_KP + '9' = VK_NUMPAD9)
 
968
//        }
 
969
        for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++)
 
970
        {
 
971
            vklut[vktab[i].vk] = vktab[i].fltk;
 
972
            extendedlut[vktab[i].vk] = vktab[i].extended;
 
973
        }
 
974
        for (i = 0; i < 256; i++)
 
975
        {
 
976
            if (!extendedlut[i])
 
977
                extendedlut[i] = vklut[i];
 
978
        }
 
979
    }
 
980
 
 
981
    return extended ? extendedlut[vk] : vklut[vk];
 
982
}*/
 
983
//---------------------------------------------------------------------------------------------------------
 
984
static int mouse_event(HWND window, IEvent* m_pEvent, int what, int button,
 
985
                       WPARAM wParam, LPARAM lParam)
 
986
{
 
987
    static int px, py, pmx, pmy;
 
988
    m_pEvent->e_x = (signed short)LOWORD(lParam);
 
989
    m_pEvent->e_y = (signed short)HIWORD(lParam);
 
990
    m_pEvent->e_x_root = 0;
 
991
    m_pEvent->e_y_root = 0;
 
992
 
 
993
    POINT EventScreenPosition;
 
994
 
 
995
    ClientToScreen(window, &EventScreenPosition);
 
996
    EventScreenPosition.x = m_pEvent->e_x;
 
997
    EventScreenPosition.y = m_pEvent->e_y;
 
998
    POINT WindowScreenPosition;
 
999
    WindowScreenPosition.x = WindowScreenPosition.y = 0;
 
1000
    ClientToScreen(window, &WindowScreenPosition);
 
1001
 
 
1002
    // Erase mouse event and mouse doubleclick events. Keep the mouse states.
 
1003
    ulong _mouse_state = m_pEvent->e_mouse_state & 0x0F000000;
 
1004
 
 
1005
    // establish cause of the event
 
1006
//     if(button == 1)
 
1007
//         _mouse_state |= INL_EVENT_BUTTON1;
 
1008
//     else if(button == 2)
 
1009
//         _mouse_state |= INL_EVENT_BUTTON2;
 
1010
//     else if(button == 3)
 
1011
//         _mouse_state |= INL_EVENT_BUTTON3;
 
1012
//     else 
 
1013
        if(button == 4)
 
1014
    {
 
1015
        m_pEvent->e_mouse_state |= INL_EVENT_MOUSEWHEEL;
 
1016
        m_pEvent->e_event = INL_MOUSEWHEEL;
 
1017
 
 
1018
        int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
 
1019
        int xPos = (int)(short)LOWORD(lParam) - WindowScreenPosition.x; 
 
1020
        int yPos = (int)(short)HIWORD(lParam) - WindowScreenPosition.y;
 
1021
        m_pEvent->e_x = xPos;
 
1022
        m_pEvent->e_y = yPos;
 
1023
 
 
1024
        m_pEvent->e_wheeldelta = zDelta;
 
1025
        return 1;
 
1026
    }
 
1027
 
 
1028
    // set the cause of the event
 
1029
    switch(what)
 
1030
    {
 
1031
    case 0:
 
1032
        {
 
1033
            // mouse down
 
1034
            if(button == 1)
 
1035
            {
 
1036
                _mouse_state |= INL_STATE_BUTTON1_DOWN;
 
1037
                _mouse_state |= INL_EVENT_BUTTON1_DOWN;
 
1038
            }
 
1039
            else if(button == 2)
 
1040
            {
 
1041
                _mouse_state |= INL_STATE_BUTTON2_DOWN;
 
1042
                _mouse_state |= INL_EVENT_BUTTON2_DOWN;
 
1043
            }
 
1044
            else if(button == 3)
 
1045
            {
 
1046
                _mouse_state |= INL_STATE_BUTTON3_DOWN;
 
1047
                _mouse_state |= INL_EVENT_BUTTON3_DOWN;
 
1048
            }
 
1049
        }
 
1050
        break;
 
1051
 
 
1052
    case 1:
 
1053
        {
 
1054
            // double click
 
1055
            if(button == 1)
 
1056
                _mouse_state |= INL_EVENT_BUTTON1_DBLCLICK;
 
1057
            else if(button == 2)
 
1058
                _mouse_state |= INL_EVENT_BUTTON2_DBLCLICK;
 
1059
            else if(button == 3)
 
1060
                _mouse_state |= INL_EVENT_BUTTON3_DBLCLICK;
 
1061
        }
 
1062
        break;
 
1063
 
 
1064
    case 2:
 
1065
        {
 
1066
            // button up
 
1067
            if(button == 1)
 
1068
            {
 
1069
                _mouse_state &= ~INL_STATE_BUTTON1_DOWN;
 
1070
                _mouse_state |= INL_EVENT_BUTTON1_UP;
 
1071
            }
 
1072
            else if(button == 2)
 
1073
            {
 
1074
                _mouse_state &= ~INL_STATE_BUTTON2_DOWN;
 
1075
                _mouse_state |= INL_EVENT_BUTTON2_UP;
 
1076
            }
 
1077
            else if(button == 3)
 
1078
            {
 
1079
                _mouse_state &= ~INL_STATE_BUTTON3_DOWN;
 
1080
                _mouse_state |= INL_EVENT_BUTTON3_UP;
 
1081
            }
 
1082
        }
 
1083
        break;
 
1084
    }
 
1085
 
 
1086
    m_pEvent->e_mouse_state = _mouse_state;
 
1087
 
 
1088
    switch (what)
 
1089
    {
 
1090
    case 1: // double-click
 
1091
        if(m_pEvent->e_is_click)
 
1092
        {
 
1093
            m_pEvent->e_clicks++;
 
1094
            goto J1;
 
1095
        }
 
1096
    case 0: // single-click
 
1097
        m_pEvent->e_clicks = 0;
 
1098
    J1:
 
1099
        // The SetCapture function sets the mouse capture to the specified window belonging to
 
1100
        // the current thread. SetCapture captures mouse input either when the mouse is over the
 
1101
        // capturing window, or when the mouse button was pressed while the mouse was over the
 
1102
        // capturing window and the button is still down. Only one window at a time can capture the mouse.
 
1103
        SetCapture(window);
 
1104
        m_pEvent->e_is_click = 1;
 
1105
        px = pmx = m_pEvent->e_x;
 
1106
        py = pmy = m_pEvent->e_y;
 
1107
        m_pEvent->e_event = INL_MOUSE_PRESSED;
 
1108
        return 1;
 
1109
 
 
1110
    case 2: // release:
 
1111
        // The ReleaseCapture function releases the mouse capture from a window in the current thread
 
1112
        // and restores normal mouse input processing. A window that has captured the mouse receives all
 
1113
        // mouse input, regardless of the position of the cursor, except when a mouse button is clicked
 
1114
        // while the cursor hot spot is in the window of another thread. 
 
1115
        ReleaseCapture();
 
1116
        m_pEvent->e_event = INL_MOUSE_RELEASED;
 
1117
        return 1;
 
1118
 
 
1119
    case 3: // move:
 
1120
    default: // avoid compiler warning
 
1121
        // MSWindows produces extra events even if mouse does not move, ignore them.
 
1122
        // http://blogs.msdn.com/oldnewthing/archive/2003/10/01/55108.aspx: Why do I get spurious WM_MOUSEMOVE messages?
 
1123
        if (m_pEvent->e_x == pmx && m_pEvent->e_y == pmy)
 
1124
            return 1;
 
1125
        pmx = m_pEvent->e_x; 
 
1126
        pmy = m_pEvent->e_y;
 
1127
//        if(abs(m_pEvent->e_x - px)>5 || abs(m_pEvent->e_y - py)>5)
 
1128
//            m_pEvent->e_is_click = 0;
 
1129
        m_pEvent->e_event = INL_MOUSE_MOVE;
 
1130
        return 1;
 
1131
    }
 
1132
    return 0;
 
1133
}
 
1134
 
 
1135
unsigned int GetModifierKeyState()
 
1136
{
 
1137
    unsigned int state = 0;
 
1138
    unsigned short r = 0;
 
1139
    
 
1140
    // For CapsLock, we don't want to know if the key is pressed Down or Up.
 
1141
    // We really want to know the state of the the CapsLock: on (keyboard light is on) or off?
 
1142
    r = GetKeyState(VK_CAPITAL);
 
1143
    if (r & 1)
 
1144
        state |= INL_STATE_CAPS_LOCK;
 
1145
 
 
1146
    // For NumLock, we don't want to know if the key is pressed Down or Up.
 
1147
    // We really want to know the state of the the NumLock: on (keyboard light is on) or off?
 
1148
    r = GetKeyState(VK_NUMLOCK);
 
1149
    if (r & 1)
 
1150
        state |= INL_STATE_NUMLOCK;
 
1151
 
 
1152
    r = GetKeyState(VK_SCROLL);
 
1153
    if (r & 0x8000) 
 
1154
        state |= INL_STATE_SCROLLLOCK;
 
1155
 
 
1156
    r = GetKeyState(VK_CONTROL);
 
1157
    if (r & 0x8000) 
 
1158
        state |= INL_STATE_CTRL;
 
1159
 
 
1160
    r = GetKeyState(VK_SHIFT);
 
1161
    if (r & 0x8000) 
 
1162
        state |= INL_STATE_SHIFT;
 
1163
 
 
1164
    r = GetKeyState(VK_MENU);
 
1165
    if (r & 0x8000)
 
1166
        state |= INL_STATE_ALT;
 
1167
 
 
1168
 
 
1169
 
 
1170
    if ((GetKeyState(VK_LWIN)|GetKeyState(VK_RWIN))&~1) 
 
1171
    {
 
1172
        // WIN32 bug?  GetKeyState returns garbage if the user hit the
 
1173
        // meta key to pop up start menu.  Sigh.
 
1174
        if ((GetAsyncKeyState(VK_LWIN)|GetAsyncKeyState(VK_RWIN))&~1)
 
1175
            state |= INL_STATE_META;
 
1176
    }
 
1177
 
 
1178
    return state;
 
1179
}
 
1180
 
 
1181
//---------------------------------------------------------------------------------------------------------
 
1182
void GLWindowImpl::GetSystemEvent(IEvent *evt)
 
1183
{
 
1184
    MSG         msg;
 
1185
    m_pEvent->Reset();
 
1186
    // Erase mouse event and mouse doubleclick states. Keep the mouse states.
 
1187
    m_pEvent->e_mouse_state &= 0x0F000000;
 
1188
 
 
1189
    // Always set the second parameter of PeekMessage to NULL. Indeed, many services creates
 
1190
    // windows on the program behalf. If pass the main window as filter, we will miss all the
 
1191
    // messages from the other windows.
 
1192
    // Same with GetMessage.
 
1193
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))        // Is There A Message Waiting? If yes, remove it.
 
1194
    {
 
1195
        if(msg.message == INL_THREADMSG_START_RENDERING)
 
1196
        {
 
1197
            m_PauseGraphicsRendering = false;
 
1198
            MakeGLContextCurrent(true);
 
1199
        }
 
1200
 
 
1201
        TranslateMessage(&msg);                             // Translate The Message
 
1202
        DispatchMessage(&msg);  
 
1203
 
 
1204
        memcpy(evt, m_pEvent, sizeof(IEvent));
 
1205
    }
 
1206
    else
 
1207
    {
 
1208
        memcpy(evt, m_pEvent, sizeof(IEvent));
 
1209
    }
 
1210
 
 
1211
    if(msg.message == WM_QUIT)
 
1212
    {
 
1213
        // Re-post the message that we retrieved so other modal loops will catch it.
 
1214
        // See [Modality, part 3: The WM_QUIT message] http://blogs.msdn.com/oldnewthing/archive/2005/02/22/378018.aspx
 
1215
        PostQuitMessage(msg.wParam);
 
1216
 
 
1217
        m_pEvent->e_event = INL_TERMINATE_APP;
 
1218
        memcpy(evt, m_pEvent, sizeof(IEvent));
 
1219
    }
 
1220
 
 
1221
    if(msg.message == -1)  // error
 
1222
    {
 
1223
        m_pEvent->e_event = INL_NO_EVENT;
 
1224
        memcpy(evt, m_pEvent, sizeof(IEvent));
 
1225
    }
 
1226
 
1227
 
 
1228
IEvent& GLWindowImpl::GetCurrentEvent()
 
1229
{
 
1230
    return *m_pEvent;
 
1231
}
 
1232
 
 
1233
//---------------------------------------------------------------------------------------------------------
 
1234
LRESULT CALLBACK WndProcManager(HWND    hWnd,                   // Handle For This Window
 
1235
                                                                UINT    uMsg,                   // Message For This Window
 
1236
                                                                WPARAM  wParam,                 // Additional Message Information
 
1237
                                                                LPARAM  lParam)                 // Additional Message Information
 
1238
{
 
1239
    // This creates a  warning. It is a 64-bits compatibility issue. 
 
1240
    // When not in 64-bit you can disable the warning:
 
1241
    // Project Properties --> C/C++ tab --> General --> Select "NO" for - Detect 64-bit Portability Issues.
 
1242
    // See also GetWindowLongPtr
 
1243
    GLWindowImpl* GLWindow = reinterpret_cast<GLWindowImpl*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
 
1244
 
 
1245
    if(GLWindow == 0)
 
1246
    {
 
1247
        switch (uMsg)
 
1248
        {
 
1249
            // These cases happens before GLWindow is set. So we must catch them here.
 
1250
 
 
1251
        case WM_NCCREATE:
 
1252
            {
 
1253
                // Non Client Area
 
1254
 
 
1255
                // WARNING: MUST RETURN TRUE TO CONTINUE WITH THE CREATION OF THE WINDOW
 
1256
                // return TRUE;
 
1257
 
 
1258
                // WARNING: Continue with DefWindowProc if you want the title of the window to appears
 
1259
                // or you have to set it yourself before returning true
 
1260
                break;
 
1261
            }
 
1262
        case WM_CREATE:
 
1263
            {
 
1264
                // WARNING: MUST RETURN 0 TO CONTINUE WITH THE CREATION OF THE WINDOW
 
1265
                return 0;
 
1266
            }
 
1267
        }
 
1268
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
 
1269
    }
 
1270
    return GLWindow->WndProc(hWnd, uMsg, wParam, lParam);
 
1271
}
 
1272
 
 
1273
LRESULT GLWindowImpl::WndProc(HWND      hWnd,           // Handle For This Window
 
1274
                              UINT      uMsg,           // Message For This Window
 
1275
                              WPARAM    wParam,         // Additional Message Information
 
1276
                              LPARAM    lParam)         // Additional Message Information
 
1277
{
 
1278
        switch (uMsg)
 
1279
        {
 
1280
        case WM_DESTROY:
 
1281
        {
 
1282
            nuxDebugMsg(TEXT("[GLWindowImpl::WndProc]: Window \"%s\" received WM_DESTROY message."), m_WindowTitle.GetTCharPtr());
 
1283
            break;
 
1284
        }
 
1285
 
 
1286
        case WM_CLOSE:
 
1287
        {
 
1288
            nuxDebugMsg(TEXT("[GLWindowImpl::WndProc]: Window \"%s\" received WM_CLOSE message."), m_WindowTitle.GetTCharPtr());
 
1289
            // close? yes or no?
 
1290
            PostQuitMessage(0);
 
1291
            return 0;
 
1292
        }
 
1293
 
 
1294
                case WM_PAINT:
 
1295
                {
 
1296
                        ValidateRect(hWnd, NULL); //  validate the surface to avoid receiving WM_PAINT continuously
 
1297
            m_pEvent->e_event = INL_WINDOW_DIRTY;
 
1298
            break;
 
1299
                }
 
1300
 
 
1301
                case WM_CAPTURECHANGED:
 
1302
                {
 
1303
            // The WM_CAPTURECHANGED message is sent to the window that is losing the mouse capture
 
1304
            if((HWND)lParam != hWnd)
 
1305
            {
 
1306
                // Cancel everything about the mouse state and send a INL_WINDOW_EXIT_FOCUS message.
 
1307
                m_pEvent->e_mouse_state = 0;
 
1308
                //nuxDebugMsg(TEXT("Windows Msg: WM_CAPTURECHANGED/INL_WINDOW_EXIT_FOCUS"));
 
1309
                return 0;
 
1310
            }
 
1311
                        break;
 
1312
                }
 
1313
 
 
1314
                case WM_ENTERSIZEMOVE:
 
1315
                {
 
1316
                        return 0;
 
1317
                }
 
1318
 
 
1319
        case WM_EXITSIZEMOVE:
 
1320
        {
 
1321
            RECT clientrect;
 
1322
            GetClientRect( hWnd, &clientrect);
 
1323
 
 
1324
            m_pEvent->e_event = INL_SIZE_CONFIGURATION;
 
1325
            m_pEvent->width =  clientrect.right - clientrect.left;
 
1326
            m_pEvent->height =  clientrect.bottom - clientrect.top;
 
1327
            return 0;
 
1328
        }
 
1329
 
 
1330
        case WM_SIZE:
 
1331
                {               
 
1332
                        RECT clientrect;
 
1333
                        GetClientRect( hWnd, &clientrect);
 
1334
 
 
1335
                        m_pEvent->e_event = INL_NO_EVENT; //INL_SIZE_CONFIGURATION;
 
1336
                        m_pEvent->width =  clientrect.right - clientrect.left;
 
1337
                        m_pEvent->height =  clientrect.bottom - clientrect.top;
 
1338
 
 
1339
                        //setViewPort(0, 0, clientrect.right - clientrect.left, clientrect.bottom - clientrect.top);
 
1340
            m_WindowSize.SetWidth(clientrect.right - clientrect.left);
 
1341
            m_WindowSize.SetHeight(clientrect.bottom - clientrect.top);
 
1342
 
 
1343
            if((wParam == SIZE_MAXHIDE) || (wParam == SIZE_MINIMIZED))
 
1344
            {
 
1345
                m_is_window_minimized = true;
 
1346
            }
 
1347
            else
 
1348
            {
 
1349
                m_is_window_minimized = false;
 
1350
            }
 
1351
 
 
1352
            if((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED))
 
1353
            {
 
1354
                m_pEvent->e_event = INL_SIZE_CONFIGURATION;
 
1355
            }
 
1356
 
 
1357
                        return 0;
 
1358
                }
 
1359
 
 
1360
        case WM_SETFOCUS:
 
1361
            {
 
1362
                m_pEvent->e_event = INL_WINDOW_ENTER_FOCUS;
 
1363
                m_pEvent->e_mouse_state = 0;
 
1364
 
 
1365
                // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process().
 
1366
                // Because WM_SETFOCUS can happen with the mouse outside of the client area, we set e_x and e_y so that the mouse will be 
 
1367
                // outside of all widgets. A subsequent mouse down or mouse move event will set the correct values for e_x and e_y.
 
1368
                m_pEvent->e_x = 0xFFFFFFFF;
 
1369
                m_pEvent->e_y = 0xFFFFFFFF;
 
1370
                m_pEvent->e_dx = 0;
 
1371
                m_pEvent->e_dy = 0;
 
1372
                m_pEvent->virtual_code = 0;
 
1373
                //nuxDebugMsg(TEXT("Windows Msg: WM_SETFOCUS/INL_WINDOW_ENTER_FOCUS"));
 
1374
                break;
 
1375
            }
 
1376
 
 
1377
        case WM_KILLFOCUS:
 
1378
            {
 
1379
                m_pEvent->e_event = INL_WINDOW_EXIT_FOCUS;
 
1380
                m_pEvent->e_mouse_state = 0;
 
1381
 
 
1382
                // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process()
 
1383
                m_pEvent->e_x = 0xFFFFFFFF;
 
1384
                m_pEvent->e_y = 0xFFFFFFFF;
 
1385
                m_pEvent->e_dx = 0;
 
1386
                m_pEvent->e_dy = 0;
 
1387
                m_pEvent->virtual_code = 0;
 
1388
                //nuxDebugMsg(TEXT("Windows Msg: WM_KILLFOCUS/INL_WINDOW_EXIT_FOCUS"));
 
1389
                break;
 
1390
            }
 
1391
 
 
1392
        case WM_NCHITTEST:
 
1393
            {
 
1394
                break;
 
1395
            }
 
1396
 
 
1397
        case WM_ACTIVATE:
 
1398
            {
 
1399
                if(LOWORD(wParam)!=WA_INACTIVE)
 
1400
                {
 
1401
                    m_pEvent->e_key_modifiers = GetModifierKeyState();
 
1402
                    return 0;
 
1403
                }
 
1404
            }
 
1405
 
 
1406
        case WM_ACTIVATEAPP:
 
1407
            if (wParam)
 
1408
            {
 
1409
                m_pEvent->e_key_modifiers = GetModifierKeyState();
 
1410
                return 0;
 
1411
            }
 
1412
 
 
1413
        case WM_SYSKEYDOWN:
 
1414
        case WM_KEYDOWN:
 
1415
            {
 
1416
                m_pEvent->e_event = INL_KEYDOWN;
 
1417
                m_pEvent->e_key_modifiers = GetModifierKeyState();
 
1418
                m_pEvent->e_keysym = wParam;
 
1419
 
 
1420
                if((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN))
 
1421
                {
 
1422
                    m_pEvent->VirtualKeycodeState[GLWindowImpl::Win32KeySymToINL(wParam)] = 1;
 
1423
                }
 
1424
                
 
1425
                if(wParam == VK_CONTROL)
 
1426
                {
 
1427
                    if(lParam & (1 << 24))
 
1428
                    {
 
1429
                        m_pEvent->e_keysym = INL_VK_RCONTROL;
 
1430
                    }
 
1431
                    else
 
1432
                    {
 
1433
                        m_pEvent->e_keysym = INL_VK_LCONTROL;
 
1434
                    }
 
1435
                }
 
1436
 
 
1437
                if(wParam == VK_MENU)
 
1438
                {
 
1439
                    if(lParam & (1 << 24))
 
1440
                    {
 
1441
                        m_pEvent->e_keysym = INL_VK_RMENU;
 
1442
                    }
 
1443
                    else
 
1444
                    {
 
1445
                        m_pEvent->e_keysym = INL_VK_LMENU;
 
1446
                    }
 
1447
                }
 
1448
 
 
1449
                if(wParam == VK_SHIFT)
 
1450
                {
 
1451
                    if(HIWORD(GetAsyncKeyState(VK_LSHIFT)))
 
1452
                    {
 
1453
                        m_pEvent->e_keysym = INL_VK_LSHIFT;
 
1454
                    }
 
1455
                    else if(HIWORD(GetAsyncKeyState(VK_RSHIFT)))
 
1456
                    {
 
1457
                        m_pEvent->e_keysym = INL_VK_RSHIFT;
 
1458
                    }
 
1459
                }
 
1460
 
 
1461
                break;
 
1462
            }
 
1463
            
 
1464
        case WM_SYSKEYUP:
 
1465
        case WM_KEYUP:
 
1466
            {
 
1467
                m_pEvent->e_event = INL_KEYUP;
 
1468
                m_pEvent->e_key_modifiers = GetModifierKeyState();
 
1469
                m_pEvent->e_keysym = wParam;
 
1470
 
 
1471
                if((uMsg == WM_KEYUP) || (uMsg == WM_SYSKEYUP))
 
1472
                {
 
1473
                    m_pEvent->VirtualKeycodeState[GLWindowImpl::Win32KeySymToINL(wParam)] = 0;
 
1474
                }
 
1475
                break;
 
1476
            }            
 
1477
 
 
1478
        case WM_DEADCHAR:
 
1479
        case WM_SYSDEADCHAR:
 
1480
        case WM_CHAR:
 
1481
        case WM_SYSCHAR: 
 
1482
            {
 
1483
                m_pEvent->e_key_modifiers = GetModifierKeyState();
 
1484
 
 
1485
                // reset key repeat count to 0.
 
1486
                m_pEvent->e_key_repeat_count = 0;
 
1487
                if (lParam & (1<<31)) 
 
1488
                { 
 
1489
                    // key up events.
 
1490
                    m_pEvent->e_event = INL_KEYUP;
 
1491
                    return 0;
 
1492
                }
 
1493
                else
 
1494
                {
 
1495
                    // key down events.
 
1496
                    m_pEvent->e_event = INL_KEYDOWN;
 
1497
                    m_pEvent->e_key_repeat_count = (int)(lParam & 0xff);
 
1498
                }
 
1499
 
 
1500
                static char buffer[2];
 
1501
                buffer[0] = 0; buffer[1] = 0;
 
1502
                if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) 
 
1503
                {
 
1504
                    buffer[0] = char(wParam);
 
1505
                    m_pEvent->e_length = 1;
 
1506
                }
 
1507
                else
 
1508
                {
 
1509
                    buffer[0] = 0;
 
1510
                    m_pEvent->e_length = 0;
 
1511
                }
 
1512
 
 
1513
                m_pEvent->e_text = buffer;
 
1514
                return 0;
 
1515
            }
 
1516
 
 
1517
        case WM_LBUTTONDOWN:  
 
1518
            {
 
1519
                mouse_event(hWnd, m_pEvent, 0, 1, wParam, lParam);
 
1520
                //nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONDOWN"));
 
1521
                return 0;
 
1522
            }
 
1523
        case WM_LBUTTONDBLCLK:
 
1524
            {
 
1525
                mouse_event(hWnd, m_pEvent, 1, 1, wParam, lParam);
 
1526
                //nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONDBLCLK"));
 
1527
                return 0;
 
1528
            }
 
1529
        case WM_LBUTTONUP:    
 
1530
            {
 
1531
                mouse_event(hWnd, m_pEvent, 2, 1, wParam, lParam);
 
1532
                //nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONUP"));
 
1533
                return 0;
 
1534
            }
 
1535
        case WM_MBUTTONDOWN:  
 
1536
            {mouse_event(hWnd, m_pEvent, 0, 2, wParam, lParam);  break;}
 
1537
        case WM_MBUTTONDBLCLK:
 
1538
            {mouse_event(hWnd, m_pEvent, 1, 2, wParam, lParam);  break;}
 
1539
        case WM_MBUTTONUP:    
 
1540
            {mouse_event(hWnd, m_pEvent, 2, 2, wParam, lParam);  break;}
 
1541
        case WM_RBUTTONDOWN:  
 
1542
            {mouse_event(hWnd, m_pEvent, 0, 3, wParam, lParam);  break;}
 
1543
        case WM_RBUTTONDBLCLK:
 
1544
            {mouse_event(hWnd, m_pEvent, 1, 3, wParam, lParam);  break;}
 
1545
        case WM_RBUTTONUP:    
 
1546
            {mouse_event(hWnd, m_pEvent, 2, 3, wParam, lParam);  break;}
 
1547
        case WM_MOUSEWHEEL:    
 
1548
            {
 
1549
                mouse_event(hWnd, m_pEvent, 0, 4, wParam, lParam);  break;
 
1550
            }
 
1551
 
 
1552
        case WM_NCLBUTTONDBLCLK:
 
1553
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1554
        case WM_NCLBUTTONDOWN:
 
1555
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1556
        case WM_NCLBUTTONUP:
 
1557
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1558
        case WM_NCMBUTTONDBLCLK:
 
1559
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1560
        case WM_NCMBUTTONDOWN:
 
1561
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1562
        case WM_NCMBUTTONUP:
 
1563
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1564
        case WM_NCRBUTTONDBLCLK:
 
1565
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1566
        case WM_NCRBUTTONDOWN:
 
1567
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1568
        case WM_NCRBUTTONUP:
 
1569
            {m_pEvent->e_event = INL_WINDOW_CONFIGURATION; break;}
 
1570
 
 
1571
        case WM_MOUSEMOVE:
 
1572
            {
 
1573
                mouse_event(hWnd, m_pEvent, 3, 0, wParam, lParam);
 
1574
                //nuxDebugMsg(TEXT("Windows Msg: WM_MOUSEMOVE"));
 
1575
 
 
1576
                TRACKMOUSEEVENT tme = { sizeof(tme) };
 
1577
                // Enable INL_WINDOW_MOUSELEAVE event.
 
1578
                tme.dwFlags = TME_LEAVE;
 
1579
                tme.hwndTrack = hWnd;
 
1580
                TrackMouseEvent(&tme);
 
1581
                break;
 
1582
            }
 
1583
 
 
1584
        // Note: there is no WM_MOUSEENTER. WM_MOUSEENTER is equivalent to WM_MOUSEMOVE after a WM_MOUSELEAVE.
 
1585
        case WM_MOUSELEAVE:
 
1586
            {
 
1587
                // All tracking requested by TrackMouseEvent is canceled when this message is generated.
 
1588
                // The application must call TrackMouseEvent when the mouse reenters its window if
 
1589
                // it requires further tracking of mouse hover behavior.
 
1590
                m_pEvent->e_event = INL_WINDOW_MOUSELEAVE;
 
1591
                // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process()
 
1592
                m_pEvent->e_x = 0xFFFFFFFF;
 
1593
                m_pEvent->e_y = 0xFFFFFFFF;
 
1594
                //nuxDebugMsg(TEXT("Windows Msg: WM_MOUSELEAVE/INL_WINDOW_MOUSELEAVE"));
 
1595
                break;
 
1596
            }
 
1597
 
 
1598
        case WM_SETCURSOR:
 
1599
            if((LOWORD(lParam) == HTCLIENT) && m_Cursor)
 
1600
            {
 
1601
                SetCursor(m_Cursor);
 
1602
                return TRUE; //return FALSE;
 
1603
            }
 
1604
            else
 
1605
                break;
 
1606
 
 
1607
                case WM_COMMAND:
 
1608
                {
 
1609
            nuxDebugMsg(TEXT("[GLWindowImpl::WndProc]: Window \"%s\" received WM_COMMAND message."), m_WindowTitle.GetTCharPtr());
 
1610
                        break;;
 
1611
                }
 
1612
 
 
1613
        case WM_SYSCOMMAND:                             // Intercept System Commands
 
1614
            {
 
1615
                switch (wParam)                         // Check System Calls
 
1616
                {
 
1617
                case SC_CLOSE: break;
 
1618
                case SC_CONTEXTHELP: break;
 
1619
                case SC_DEFAULT: break;
 
1620
                case SC_HOTKEY: break;
 
1621
                case SC_HSCROLL: break;
 
1622
                case SC_KEYMENU: break;
 
1623
                case SC_MAXIMIZE: break;
 
1624
                case SC_MINIMIZE: break;
 
1625
                case SC_MONITORPOWER: break;
 
1626
                case SC_MOUSEMENU: break;
 
1627
                case SC_MOVE: break;
 
1628
                case SC_NEXTWINDOW: break;
 
1629
                case SC_PREVWINDOW: break;
 
1630
                case SC_RESTORE: break;
 
1631
                case SC_SCREENSAVE: break;
 
1632
                case SC_SIZE: break;
 
1633
                case SC_TASKLIST: break;
 
1634
                case SC_VSCROLL: break;
 
1635
                }
 
1636
                break;                                                                  // Exit
 
1637
            }
 
1638
        }
 
1639
 
 
1640
        return DefWindowProc(hWnd,uMsg,wParam,lParam);
 
1641
}
 
1642
 
 
1643
int GLWindowImpl::Win32KeySymToINL(int Keysym)
 
1644
{
 
1645
    switch(Keysym)
 
1646
    {
 
1647
    case VK_CANCEL:         return INL_VK_CANCEL;
 
1648
    case VK_BACK:           return INL_VK_BACKSPACE;
 
1649
    case VK_TAB:            return INL_VK_TAB;
 
1650
    case VK_CLEAR:          return INL_VK_CLEAR;
 
1651
    case VK_RETURN:         return INL_VK_ENTER;
 
1652
    case VK_SHIFT:          return INL_VK_SHIFT;
 
1653
    case VK_CONTROL:        return INL_VK_CONTROL;
 
1654
    case VK_MENU:           return INL_VK_MENU; // ALT key
 
1655
    case VK_PAUSE:          return INL_VK_PAUSE;
 
1656
    case VK_CAPITAL:        return INL_VK_CAPITAL;
 
1657
    case VK_ESCAPE:         return INL_VK_ESCAPE;
 
1658
    case VK_SPACE:          return INL_VK_SPACE;
 
1659
    case VK_PRIOR:          return INL_VK_PAGE_UP;
 
1660
    case VK_NEXT:           return INL_VK_PAGE_DOWN;
 
1661
    case VK_END:            return INL_VK_END;
 
1662
    case VK_HOME:           return INL_VK_HOME;
 
1663
    case VK_LEFT:           return INL_VK_LEFT;
 
1664
    case VK_UP:             return INL_VK_UP;
 
1665
    case VK_RIGHT:          return INL_VK_RIGHT;
 
1666
    case VK_DOWN:           return INL_VK_DOWN;
 
1667
    case VK_SELECT:         return INL_VK_SELECT;
 
1668
    case VK_PRINT:          return INL_VK_PRINT;
 
1669
    case VK_EXECUTE:        return INL_VK_EXECUTE;
 
1670
    case VK_INSERT:         return INL_VK_INSERT;
 
1671
    case VK_DELETE:         return INL_VK_DELETE;
 
1672
    case VK_HELP:           return INL_VK_HELP;
 
1673
    case 0x30:              return INL_VK_0;
 
1674
    case 0x31:              return INL_VK_1;
 
1675
    case 0x32:              return INL_VK_2;
 
1676
    case 0x33:              return INL_VK_3;
 
1677
    case 0x34:              return INL_VK_4;
 
1678
    case 0x35:              return INL_VK_5;
 
1679
    case 0x36:              return INL_VK_6;
 
1680
    case 0x37:              return INL_VK_7;
 
1681
    case 0x38:              return INL_VK_8;
 
1682
    case 0x39:              return INL_VK_9;
 
1683
    case 0x41:              return INL_VK_A;
 
1684
    case 0x42:              return INL_VK_B;
 
1685
    case 0x43:              return INL_VK_C;
 
1686
    case 0x44:              return INL_VK_D;
 
1687
    case 0x45:              return INL_VK_E;
 
1688
    case 0x46:              return INL_VK_F;
 
1689
    case 0x47:              return INL_VK_G;
 
1690
    case 0x48:              return INL_VK_H;
 
1691
    case 0x49:              return INL_VK_I;
 
1692
    case 0x4A:              return INL_VK_J;
 
1693
    case 0x4B:              return INL_VK_K;
 
1694
    case 0x4C:              return INL_VK_L;
 
1695
    case 0x4D:              return INL_VK_M;
 
1696
    case 0x4E:              return INL_VK_N;
 
1697
    case 0x4F:              return INL_VK_O;
 
1698
    case 0x50:              return INL_VK_P;
 
1699
    case 0x51:              return INL_VK_Q;
 
1700
    case 0x52:              return INL_VK_R;
 
1701
    case 0x53:              return INL_VK_S;
 
1702
    case 0x54:              return INL_VK_T;
 
1703
    case 0x55:              return INL_VK_U;
 
1704
    case 0x56:              return INL_VK_V;
 
1705
    case 0x57:              return INL_VK_W;
 
1706
    case 0x58:              return INL_VK_X;
 
1707
    case 0x59:              return INL_VK_Y;
 
1708
    case 0x5A:              return INL_VK_Z;
 
1709
    case VK_LWIN:           return INL_VK_LWIN; // Windows key left
 
1710
    case VK_RWIN:           return INL_VK_RWIN; // Windows key right
 
1711
    case VK_NUMPAD0:        return INL_VK_NUMPAD0;
 
1712
    case VK_NUMPAD1:        return INL_VK_NUMPAD1;
 
1713
    case VK_NUMPAD2:        return INL_VK_NUMPAD2;
 
1714
    case VK_NUMPAD3:        return INL_VK_NUMPAD3;
 
1715
    case VK_NUMPAD4:        return INL_VK_NUMPAD4;
 
1716
    case VK_NUMPAD5:        return INL_VK_NUMPAD5;
 
1717
    case VK_NUMPAD6:        return INL_VK_NUMPAD6;
 
1718
    case VK_NUMPAD7:        return INL_VK_NUMPAD7;
 
1719
    case VK_NUMPAD8:        return INL_VK_NUMPAD8;
 
1720
    case VK_NUMPAD9:        return INL_VK_NUMPAD9;
 
1721
    case VK_MULTIPLY:       return INL_VK_MULTIPLY;
 
1722
    case VK_ADD:            return INL_VK_ADD;
 
1723
    case VK_SEPARATOR:      return INL_VK_SEPARATOR;
 
1724
    case VK_SUBTRACT:       return INL_VK_SUBTRACT;
 
1725
    case VK_DECIMAL:        return INL_VK_DECIMAL;
 
1726
    case VK_DIVIDE:         return INL_VK_DIVIDE;
 
1727
    case VK_F1:             return INL_VK_F1;
 
1728
    case VK_F2:             return INL_VK_F2;
 
1729
    case VK_F3:             return INL_VK_F3;
 
1730
    case VK_F4:             return INL_VK_F4;
 
1731
    case VK_F5:             return INL_VK_F5;
 
1732
    case VK_F6:             return INL_VK_F6;
 
1733
    case VK_F7:             return INL_VK_F7;
 
1734
    case VK_F8:             return INL_VK_F8;
 
1735
    case VK_F9:             return INL_VK_F9;
 
1736
    case VK_F10:            return INL_VK_F10;
 
1737
    case VK_F11:            return INL_VK_F11;
 
1738
    case VK_F12:            return INL_VK_F12;
 
1739
    case VK_F13:            return INL_VK_F13;
 
1740
    case VK_F14:            return INL_VK_F14;
 
1741
    case VK_F15:            return INL_VK_F15;
 
1742
    case VK_F16:            return INL_VK_F16;
 
1743
    case VK_F17:            return INL_VK_F17;
 
1744
    case VK_F18:            return INL_VK_F18;
 
1745
    case VK_F19:            return INL_VK_F19;
 
1746
    case VK_F20:            return INL_VK_F20;
 
1747
    case VK_F21:            return INL_VK_F21;
 
1748
    case VK_F22:            return INL_VK_F22;
 
1749
    case VK_F23:            return INL_VK_F23;
 
1750
    case VK_F24:            return INL_VK_F24;
 
1751
    case VK_NUMLOCK:        return INL_VK_NUMLOCK;
 
1752
    case VK_SCROLL:         return INL_VK_SCROLL;
 
1753
    case VK_LSHIFT:         return INL_VK_LSHIFT;
 
1754
    case VK_RSHIFT:         return INL_VK_RSHIFT;
 
1755
    case VK_LCONTROL:       return INL_VK_LCONTROL;
 
1756
    case VK_RCONTROL:       return INL_VK_RCONTROL;
 
1757
    case VK_LMENU:          return INL_VK_LMENU;
 
1758
    case VK_RMENU:          return INL_VK_RMENU;
 
1759
    default:                return 0x0;
 
1760
    }
 
1761
}
 
1762
 
 
1763
//---------------------------------------------------------------------------------------------------------
 
1764
void GLWindowImpl::GetDisplayInfo()
 
1765
{
 
1766
    DEVMODE   devmode;
 
1767
    INT         iMode = 0;
 
1768
    BOOL                bRetVal;
 
1769
    DeviceModes dm;
 
1770
    do
 
1771
    {
 
1772
        bRetVal = ::EnumDisplaySettings(NULL, iMode, &devmode);
 
1773
        iMode++;
 
1774
        if (bRetVal)
 
1775
        {
 
1776
            dm.width        = devmode.dmPelsWidth;
 
1777
            dm.height       = devmode.dmPelsHeight;
 
1778
            dm.format       = devmode.dmBitsPerPel;
 
1779
            dm.refresh_rate = devmode.dmDisplayFrequency;
 
1780
            m_gfx_device_modes.push_back(dm);
 
1781
        }
 
1782
    }
 
1783
    while (bRetVal);
 
1784
}
 
1785
 
 
1786
//---------------------------------------------------------------------------------------------------------
 
1787
void GLWindowImpl::ShowWindow()
 
1788
{
 
1789
    ::ShowWindow(m_hWnd, SW_RESTORE);
 
1790
}
 
1791
 
 
1792
//---------------------------------------------------------------------------------------------------------
 
1793
void GLWindowImpl::HideWindow()
 
1794
{
 
1795
    ::ShowWindow(m_hWnd, SW_MINIMIZE);
 
1796
}
 
1797
 
 
1798
//---------------------------------------------------------------------------------------------------------
 
1799
void GLWindowImpl::EnterMaximizeWindow()
 
1800
{
 
1801
    ::ShowWindow(m_hWnd, SW_MAXIMIZE);
 
1802
}
 
1803
 
 
1804
//---------------------------------------------------------------------------------------------------------
 
1805
void GLWindowImpl::ExitMaximizeWindow()
 
1806
{
 
1807
    ::ShowWindow(m_hWnd, SW_RESTORE);
 
1808
}
 
1809
 
 
1810
//---------------------------------------------------------------------------------------------------------
 
1811
void GLWindowImpl::SetWindowTitle(const TCHAR* Title)
 
1812
{
 
1813
    SetWindowText(m_hWnd, Title);
 
1814
}
 
1815
 
 
1816
//---------------------------------------------------------------------------------------------------------
 
1817
bool GLWindowImpl::HasVSyncSwapControl() const
 
1818
 
1819
    return GetThreadGLDeviceFactory()->SUPPORT_WGL_EXT_SWAP_CONTROL();
 
1820
}
 
1821
 
 
1822
//---------------------------------------------------------------------------------------------------------
 
1823
void GLWindowImpl::EnableVSyncSwapControl()
 
1824
{
 
1825
#if WIN32
 
1826
    if(HasVSyncSwapControl())
 
1827
    {
 
1828
        wglSwapIntervalEXT(1);
 
1829
    }
 
1830
#endif
 
1831
}
 
1832
 
 
1833
//---------------------------------------------------------------------------------------------------------
 
1834
void GLWindowImpl::DisableVSyncSwapControl()
 
1835
{
 
1836
#if WIN32
 
1837
    if(HasVSyncSwapControl())
 
1838
    {
 
1839
        wglSwapIntervalEXT(0);
 
1840
    }
 
1841
#endif
 
1842
}
 
1843
 
 
1844
float GLWindowImpl::GetFrameTime() const
 
1845
{
 
1846
    return m_FrameTime;
 
1847
}
 
1848
 
 
1849
void GLWindowImpl::ResetFrameTime()
 
1850
{
 
1851
    m_Timer.Reset();
 
1852
}
 
1853
 
 
1854
bool GLWindowImpl::StartOpenFileDialog(FileDialogOption& fdo)
 
1855
{
 
1856
    return Win32OpenFileDialog(GetWindowHandle(), fdo);
 
1857
}
 
1858
 
 
1859
bool GLWindowImpl::StartSaveFileDialog(FileDialogOption& fdo)
 
1860
{
 
1861
    return Win32SaveFileDialog(GetWindowHandle(), fdo);
 
1862
}
 
1863
 
 
1864
bool GLWindowImpl::StartColorDialog(ColorDialogOption& cdo)
 
1865
{
 
1866
    return Win32ColorDialog(GetWindowHandle(), cdo);
 
1867
}
 
1868
 
 
1869
//---------------------------------------------------------------------------------------------------------
 
1870
void GLWindowImpl::SetWindowCursor(HCURSOR cursor)
 
1871
{
 
1872
    m_Cursor = cursor;
 
1873
}
 
1874
 
 
1875
//---------------------------------------------------------------------------------------------------------
 
1876
HCURSOR GLWindowImpl::GetWindowCursor() const
 
1877
{
 
1878
    return m_Cursor;
 
1879
}
 
1880
 
 
1881
//---------------------------------------------------------------------------------------------------------
 
1882
void GLWindowImpl::PauseThreadGraphicsRendering()
 
1883
{
 
1884
    m_PauseGraphicsRendering = true;
 
1885
    MakeGLContextCurrent(false);
 
1886
}
 
1887
 
 
1888
//---------------------------------------------------------------------------------------------------------
 
1889
bool GLWindowImpl::IsPauseThreadGraphicsRendering() const
 
1890
{
 
1891
    return m_PauseGraphicsRendering;
 
1892
}
 
1893
 
 
1894
NAMESPACE_END_OGL