2
* Copyright 2010 Inalogic Inc.
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.
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.
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/>
18
* Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com>
23
#include "GLResource.h"
24
#include "GLDeviceFactory.h"
25
#include "GLDeviceObjects.h"
26
#include "GLResourceManager.h"
28
#include "GLTextureResourceManager.h"
29
#include "GLVertexResourceManager.h"
30
#include "OpenGLEngine.h"
31
#include "GLWindowManager.h"
32
#include "Gfx_Events.h"
35
#include "Gfx_OpenGL.h"
39
// Compute the frame rate every FRAME_RATE_PERIODE;
40
#define FRAME_RATE_PERIODE 10
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);
45
void ClipOrCenterRectToMonitor(LPRECT prc, t_u32 flags)
50
int w = prc->right - prc->left;
51
int h = prc->bottom - prc->top;
54
// get the nearest monitor to the passed rect.
56
hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);
59
// get the work area or entire monitor rect.
61
mi.cbSize = sizeof(mi);
62
GetMonitorInfo(hMonitor, &mi);
64
//if (flags & MONITOR_WORKAREA)
70
// center or clip the passed rect to the monitor rect
72
//if (flags & MONITOR_CENTER)
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;
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;
88
EventToNameStruct EventToName[] =
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")}
105
//---------------------------------------------------------------------------------------------------------
106
HGLRC GLWindowImpl::sMainGLRC = 0;
107
HDC GLWindowImpl::sMainDC = 0;
109
GLWindowImpl::GLWindowImpl()
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)
118
, m_GraphicsContext(0)
119
// , m_GLEWContext(0)
120
// , m_WGLEWContext(0)
121
, m_Style(WINDOWSTYLE_NORMAL)
123
, m_PauseGraphicsRendering(false)
128
inlSetThreadLocalStorage(ThreadLocal_GLWindowImpl, this);
130
m_GfxInterfaceCreated = false;
131
m_pEvent = new IEvent();
134
m_WindowSize.SetWidth(0);
135
m_WindowSize.SetHeight(0);
137
// A window never starts in a minimized state.
138
m_is_window_minimized = false;
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"));
149
NString file_search = TEXT("inalogic.ini");
150
NString FileName = m_FilePath.GetFile(file_search.GetTCharPtr());
151
if (FileName == TEXT(""))
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."));
159
if(FileName != TEXT(""))
161
NString key_name = TEXT("UseBackupFBO");
162
NString section_name = TEXT("OpenGLSystem");
164
if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()) == false)
166
nuxDebugMsg(TEXT("[GLWindowImpl::GLWindowImpl] Key [%s] does not exit in .ini file."));
170
NString value = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
171
if((value == TEXT("1")) || (value == TEXT("true")))
173
m_BackupFrameBuffer = true;
177
m_BackupFrameBuffer = false;
181
section_name = TEXT("SearchPath");
182
key_name = TEXT("FontPath");
183
if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()))
185
NString FontPath = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
186
FontPath.ParseToArray(m_FontSearchPath, TEXT(";"));
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."));
197
key_name = TEXT("UITexturePath");
198
if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()))
200
NString UITexturePath = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
201
UITexturePath.ParseToArray(m_UITextureSearchPath, TEXT(";"));
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."));
211
key_name = TEXT("ShaderPath");
212
if(CIniFile::RecordExists(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr()))
214
NString ShaderPath = CIniFile::GetValue(key_name.GetTCharPtr(), section_name.GetTCharPtr(), FileName.GetTCharPtr());
215
ShaderPath.ParseToArray(m_ShaderSearchPath, TEXT(";"));
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."));
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"));
235
m_ResourcePathLocation.AddSearchPath(m_FontSearchPath);
236
m_ResourcePathLocation.AddSearchPath(m_ShaderSearchPath);
237
m_ResourcePathLocation.AddSearchPath(m_UITextureSearchPath);
240
//---------------------------------------------------------------------------------------------------------
241
GLWindowImpl::~GLWindowImpl()
243
INL_SAFE_DELETE( m_GraphicsContext );
244
INL_SAFE_DELETE( m_DeviceFactory );
246
// INL_SAFE_DELETE( m_WGLEWContext );
247
// INL_SAFE_DELETE( m_GLEWContext );
249
DestroyOpenGLWindow();
250
INL_SAFE_DELETE( m_pEvent );
252
inlSetThreadLocalStorage(ThreadLocal_GLWindowImpl, 0);
255
//---------------------------------------------------------------------------------------------------------
256
NString GLWindowImpl::FindResourceLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
258
NString path = m_ResourcePathLocation.GetFile(ResourceFileName);
260
if(path == TEXT("") && ErrorOnFail)
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);
270
NString GLWindowImpl::FindUITextureLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
273
searchpath.AddSearchPath(m_UITextureSearchPath);
274
NString path = searchpath.GetFile(ResourceFileName);
276
if((path == TEXT("")) && ErrorOnFail)
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);
286
NString GLWindowImpl::FindShaderLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
289
searchpath.AddSearchPath(m_ShaderSearchPath);
290
NString path = searchpath.GetFile(ResourceFileName);
292
if((path == TEXT("")) && ErrorOnFail)
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);
302
NString GLWindowImpl::FindFontLocation(const TCHAR* ResourceFileName, bool ErrorOnFail)
305
searchpath.AddSearchPath(m_FontSearchPath);
306
NString path = searchpath.GetFile(ResourceFileName);
308
if((path == TEXT("")) && ErrorOnFail)
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);
319
//---------------------------------------------------------------------------------------------------------
320
bool GLWindowImpl::IsGfxInterfaceCreated()
322
return m_GfxInterfaceCreated;
325
//---------------------------------------------------------------------------------------------------------
326
static NCriticalSection CreateOpenGLWindow_CriticalSection;
327
bool GLWindowImpl::CreateOpenGLWindow(const TCHAR* WindowTitle,
328
unsigned int WindowWidth,
329
unsigned int WindowHeight,
331
const GLWindowImpl* Parent,
334
NScopeLock Scope(&CreateOpenGLWindow_CriticalSection);
336
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
338
m_GfxInterfaceCreated = false;
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);
348
WindowRect.left = (long)0;
349
WindowRect.right = (long)m_ViewportSize.GetWidth();
350
WindowRect.top = (long)0;
351
WindowRect.bottom = (long)m_ViewportSize.GetHeight();
353
m_fullscreen = FullscreenFlag; // Set The Global Fullscreen Flag
354
m_index_of_current_mode = -1; // assume -1 if the mode is not fullscreen
357
if (m_fullscreen) // Attempt Fullscreen Mode?
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++)
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))
367
mode_supported = true;
368
m_index_of_current_mode = num_modes;
373
if(mode_supported == false)
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)
378
m_fullscreen = FALSE; // Windowed Mode Selected. Fullscreen = FALSE
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;
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)
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)
396
m_fullscreen = FALSE; // Windowed Mode Selected. Fullscreen = FALSE
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);
409
if(m_fullscreen) // Are We Still In Fullscreen Mode?
411
m_dwExStyle = WS_EX_APPWINDOW; // Window Extended Style
412
m_dwStyle = WS_POPUP; // Windows Style
413
ShowCursor(TRUE); // Hide Mouse Pointer
417
// Window Extended Style
418
m_dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
420
m_dwStyle = WS_OVERLAPPED; // Creates an overlapped window. An overlapped window has a title bar and a border
423
// See Win32 Window Hierarchy and Styles: http://msdn.microsoft.com/en-us/library/ms997562.aspx
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
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).
434
if(Style == WINDOWSTYLE_TOOL)
436
m_dwExStyle = WS_EX_TOOLWINDOW;
437
m_dwStyle = WS_CAPTION | WS_SYSMENU;
439
else if(Style == WINDOWSTYLE_DIALOG)
441
m_dwExStyle = WS_EX_DLGMODALFRAME;
442
m_dwStyle = WS_CAPTION | WS_SYSMENU;
444
else if(Style == WINDOWSTYLE_NOBORDER)
446
m_dwExStyle = WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
447
m_dwStyle = WS_POPUP;
449
else if(Style == WINDOWSTYLE_PANEL)
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;
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
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.
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
475
rect.bottom = WindowRect.bottom-WindowRect.top;
477
rect.right = WindowRect.right-WindowRect.left;
482
m_ParentWindow = Parent->GetWindowHandle();
483
GetWindowRect(m_ParentWindow, &rect);
485
int width = rect.right - rect.left;
486
int height = rect.bottom - rect.top;
488
WindowX = rect.left + (width - (WindowRect.right-WindowRect.left))/2;
489
WindowY = rect.top + (height - (WindowRect.bottom-WindowRect.top))/2;
493
ClipOrCenterRectToMonitor(&rect, 0);
498
m_WindowTitle = WindowTitle;
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
511
gGLWindowManager.GetInstance(), // Instance
512
NULL))) // Dont Pass Anything To WM_CREATE
514
DestroyOpenGLWindow();
515
MessageBox(NULL, TEXT("Window Creation Error."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
516
exit(1); // Return FALSE
519
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
521
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
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
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.
534
// Specifies the number of red bitplanes in each RGBA color buffer.
536
// Specifies the shift count for red bitplanes in each RGBA color buffer.
538
// Specifies the number of green bitplanes in each RGBA color buffer.
540
// Specifies the shift count for green bitplanes in each RGBA color buffer.
542
// Specifies the number of blue bitplanes in each RGBA color buffer.
544
// Specifies the shift count for blue bitplanes in each RGBA color buffer.
547
// Specifies the number of alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported.
549
// Specifies the shift count for alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported.
552
// Specifies the total number of bitplanes in the accumulation buffer.
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.
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.
562
// Specifies the depth of the depth (z-axis) buffer.
564
// Specifies the depth of the stencil buffer.
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.
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.
572
// Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
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.
576
// Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
579
if (!(m_hDC = GetDC(m_hWnd))) // Did We Get A Device Context?
581
DestroyOpenGLWindow();
582
MessageBox(NULL, TEXT("Can't Create A GL Device Context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
586
if (!(m_PixelFormat = ChoosePixelFormat(m_hDC, &pfd))) // Did Windows Find A Matching Pixel Format?
588
DestroyOpenGLWindow();
589
MessageBox(NULL, TEXT("Can't Find A Suitable PixelFormat."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
593
if(!SetPixelFormat(m_hDC, m_PixelFormat, &pfd)) // Are We Able To Set The Pixel Format?
595
DestroyOpenGLWindow();
596
MessageBox(NULL, TEXT("Can't Set The PixelFormat."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
600
if (!(m_GLRC = wglCreateContext(m_hDC))) // Are We Able To Get A Rendering Context?
602
DestroyOpenGLWindow();
603
MessageBox(NULL, TEXT("Can't Create A GL Rendering Context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
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)
618
// DWORD err = GetLastError();
619
// DestroyOpenGLWindow();
620
// MessageBox(NULL, TEXT("Can't share GL context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
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);
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
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);
640
m_GfxInterfaceCreated = true;
642
//m_GLEWContext = new GLEWContext();
643
//m_WGLEWContext = new WGLEWContext();
645
m_DeviceFactory = new GLDeviceFactory(m_ViewportSize.GetWidth(), m_ViewportSize.GetHeight(), BITFMT_R8G8B8A8);
646
m_GraphicsContext = new GraphicsContext(*this);
648
//EnableVSyncSwapControl();
649
//DisableVSyncSwapControl();
654
bool GLWindowImpl::CreateFromOpenGLWindow(HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext)
656
m_hWnd = WindowHandle;
657
m_hDC = WindowDCHandle;
658
m_GLRC = OpenGLRenderingContext;
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);
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);
670
m_GfxInterfaceCreated = true;
671
m_DeviceFactory = new GLDeviceFactory(m_ViewportSize.GetWidth(), m_ViewportSize.GetHeight(), BITFMT_R8G8B8A8);
672
m_GraphicsContext = new GraphicsContext(*this);
677
//---------------------------------------------------------------------------------------------------------
678
bool GLWindowImpl::HasFrameBufferSupport()
680
return m_DeviceFactory->SUPPORT_GL_EXT_FRAMEBUFFER_OBJECT() && m_BackupFrameBuffer;
683
//---------------------------------------------------------------------------------------------------------
684
void GLWindowImpl::GetWindowSize(int &w, int &h)
686
w = m_WindowSize.GetWidth();
687
h = m_WindowSize.GetHeight();
690
//---------------------------------------------------------------------------------------------------------
691
unsigned int GLWindowImpl::GetWindowWidth()
693
return m_WindowSize.GetWidth();
696
//---------------------------------------------------------------------------------------------------------
697
unsigned int GLWindowImpl::GetWindowHeight()
699
return m_WindowSize.GetHeight();
702
//---------------------------------------------------------------------------------------------------------
703
void GLWindowImpl::SetWindowSize(int width, int height)
707
::GetWindowRect(m_hWnd, &window_rect);
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
716
(new_rect.right - new_rect.left),
717
(new_rect.bottom - new_rect.top),
721
//---------------------------------------------------------------------------------------------------------
722
void GLWindowImpl::SetViewPort(int x, int y, int width, int height)
724
if(IsGfxInterfaceCreated())
726
//do not rely on m_ViewportSize: glViewport can be called directly
727
m_ViewportSize.SetWidth(width);
728
m_ViewportSize.SetHeight(height);
730
m_GraphicsContext->SetViewport(x, y, m_ViewportSize.GetWidth(), m_ViewportSize.GetHeight());
731
m_GraphicsContext->SetScissor(0, 0, width, height);
735
Point GLWindowImpl::GetMouseScreenCoord()
739
ScreenToClient(m_hWnd, &pt);
740
Point point(pt.x, pt.y);
744
Point GLWindowImpl::GetMouseWindowCoord()
748
::ScreenToClient(m_hWnd, &pt);
749
Point point(pt.x, pt.y);
753
Point GLWindowImpl::GetWindowCoord()
756
::GetWindowRect(m_hWnd, &rect);
757
Point point(rect.left, rect.top);
761
Rect GLWindowImpl::GetWindowGeometry()
764
::GetClientRect(m_hWnd, &rect);
765
Rect geo(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
769
Rect GLWindowImpl::GetNCWindowGeometry()
772
::GetWindowRect(m_hWnd, &rect);
773
Rect geo(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
777
//---------------------------------------------------------------------------------------------------------
778
//void GLWindowImpl::EnableBackupFrameBuffer()
780
// if(m_BackupFrameBuffer)
782
// m_MainFBO->Enable();
786
//void GLWindowImpl::DisableBackupFrameBuffer()
788
// if(m_BackupFrameBuffer)
790
// m_MainFBO->Disable();
794
//void GLWindowImpl::BackupFrameBufferBind()
796
// if(m_BackupFrameBuffer)
798
// m_MainFBO->BindToTexUnit0();
801
//---------------------------------------------------------------------------------------------------------
802
void GLWindowImpl::MakeGLContextCurrent(bool b)
810
if(!wglMakeCurrent(m_hDC, glrc))
812
NString error = inlGetSystemErrorMessage();
813
DestroyOpenGLWindow();
814
MessageBox(NULL, TEXT("Can't Activate The GL Rendering Context."), TEXT("ERROR"), MB_OK|MB_ICONERROR);
817
//---------------------------------------------------------------------------------------------------------
818
void GLWindowImpl::SwapBuffer(bool glswap)
820
if(IsPauseThreadGraphicsRendering())
828
m_FrameTime = m_Timer.PassedMilliseconds();
830
// if(16.6f - m_FrameTime > 0)
832
// SleepForMilliseconds(16.6f - m_FrameTime);
835
// m_FrameTime = m_Timer.PassedMilliseconds();
837
// m_PeriodeTime += m_FrameTime;
840
// m_FramePeriodeCounter++;
841
// if(m_FramePeriodeCounter >= FRAME_RATE_PERIODE)
843
// m_FrameRate = m_FramePeriodeCounter * 1000.0f / m_PeriodeTime;
844
// m_PeriodeTime = 0.0f;
845
// m_FramePeriodeCounter = 0;
848
//---------------------------------------------------------------------------------------------------------
849
void GLWindowImpl::DestroyOpenGLWindow()
851
if(m_GfxInterfaceCreated == true)
853
if (m_fullscreen) // Are We In Fullscreen Mode?
855
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
856
ShowCursor(TRUE); // Show Mouse Pointer
859
if (m_GLRC) // Do We Have A Rendering Context?
861
if (!wglMakeCurrent(m_hDC, NULL)) // Are We Able To Release The DC And RC Contexts?
863
MessageBox(NULL, TEXT("Release Of DC And RC Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
866
if (!wglDeleteContext(m_GLRC)) // Are We Able To Delete The RC?
868
MessageBox(NULL, TEXT("Release Rendering Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
870
m_GLRC = NULL; // Set RC To NULL
873
if (m_hDC && !ReleaseDC(m_hWnd, m_hDC)) // Are We Able To Release The DC
875
MessageBox(NULL, TEXT("Release Device Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
876
m_hDC = NULL; // Set DC To NULL
879
if (m_hWnd && !(::DestroyWindow(m_hWnd))) // Are We Able To Destroy The Window?
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
885
m_GfxInterfaceCreated = false;
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*/},
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.
948
//---------------------------------------------------------------------------------------------------------
949
/*static int ms2fltk(int vk, int extended)
951
static unsigned short vklut[256];
952
static unsigned short extendedlut[256];
957
for (i = 0; i < 256; i++)
959
vklut[i] = i; //tolower(i);
961
// for (i=VK_F1; i<=VK_F16; i++)
963
// vklut[i] = i+(FL_F-(VK_F1-1)); // (FL_F + 1 -> VK_F1) ... (FL_F + 16 -> VK_F16)
965
// for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++)
967
// vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0); // (FL_KP + '0' -> VK_NUMPAD0) ... (FL_KP + '9' = VK_NUMPAD9)
969
for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++)
971
vklut[vktab[i].vk] = vktab[i].fltk;
972
extendedlut[vktab[i].vk] = vktab[i].extended;
974
for (i = 0; i < 256; i++)
977
extendedlut[i] = vklut[i];
981
return extended ? extendedlut[vk] : vklut[vk];
983
//---------------------------------------------------------------------------------------------------------
984
static int mouse_event(HWND window, IEvent* m_pEvent, int what, int button,
985
WPARAM wParam, LPARAM lParam)
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;
993
POINT EventScreenPosition;
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);
1002
// Erase mouse event and mouse doubleclick events. Keep the mouse states.
1003
ulong _mouse_state = m_pEvent->e_mouse_state & 0x0F000000;
1005
// establish cause of the event
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;
1015
m_pEvent->e_mouse_state |= INL_EVENT_MOUSEWHEEL;
1016
m_pEvent->e_event = INL_MOUSEWHEEL;
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;
1024
m_pEvent->e_wheeldelta = zDelta;
1028
// set the cause of the event
1036
_mouse_state |= INL_STATE_BUTTON1_DOWN;
1037
_mouse_state |= INL_EVENT_BUTTON1_DOWN;
1039
else if(button == 2)
1041
_mouse_state |= INL_STATE_BUTTON2_DOWN;
1042
_mouse_state |= INL_EVENT_BUTTON2_DOWN;
1044
else if(button == 3)
1046
_mouse_state |= INL_STATE_BUTTON3_DOWN;
1047
_mouse_state |= INL_EVENT_BUTTON3_DOWN;
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;
1069
_mouse_state &= ~INL_STATE_BUTTON1_DOWN;
1070
_mouse_state |= INL_EVENT_BUTTON1_UP;
1072
else if(button == 2)
1074
_mouse_state &= ~INL_STATE_BUTTON2_DOWN;
1075
_mouse_state |= INL_EVENT_BUTTON2_UP;
1077
else if(button == 3)
1079
_mouse_state &= ~INL_STATE_BUTTON3_DOWN;
1080
_mouse_state |= INL_EVENT_BUTTON3_UP;
1086
m_pEvent->e_mouse_state = _mouse_state;
1090
case 1: // double-click
1091
if(m_pEvent->e_is_click)
1093
m_pEvent->e_clicks++;
1096
case 0: // single-click
1097
m_pEvent->e_clicks = 0;
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.
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;
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.
1116
m_pEvent->e_event = INL_MOUSE_RELEASED;
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)
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;
1135
unsigned int GetModifierKeyState()
1137
unsigned int state = 0;
1138
unsigned short r = 0;
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);
1144
state |= INL_STATE_CAPS_LOCK;
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);
1150
state |= INL_STATE_NUMLOCK;
1152
r = GetKeyState(VK_SCROLL);
1154
state |= INL_STATE_SCROLLLOCK;
1156
r = GetKeyState(VK_CONTROL);
1158
state |= INL_STATE_CTRL;
1160
r = GetKeyState(VK_SHIFT);
1162
state |= INL_STATE_SHIFT;
1164
r = GetKeyState(VK_MENU);
1166
state |= INL_STATE_ALT;
1170
if ((GetKeyState(VK_LWIN)|GetKeyState(VK_RWIN))&~1)
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;
1181
//---------------------------------------------------------------------------------------------------------
1182
void GLWindowImpl::GetSystemEvent(IEvent *evt)
1186
// Erase mouse event and mouse doubleclick states. Keep the mouse states.
1187
m_pEvent->e_mouse_state &= 0x0F000000;
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.
1195
if(msg.message == INL_THREADMSG_START_RENDERING)
1197
m_PauseGraphicsRendering = false;
1198
MakeGLContextCurrent(true);
1201
TranslateMessage(&msg); // Translate The Message
1202
DispatchMessage(&msg);
1204
memcpy(evt, m_pEvent, sizeof(IEvent));
1208
memcpy(evt, m_pEvent, sizeof(IEvent));
1211
if(msg.message == WM_QUIT)
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);
1217
m_pEvent->e_event = INL_TERMINATE_APP;
1218
memcpy(evt, m_pEvent, sizeof(IEvent));
1221
if(msg.message == -1) // error
1223
m_pEvent->e_event = INL_NO_EVENT;
1224
memcpy(evt, m_pEvent, sizeof(IEvent));
1228
IEvent& GLWindowImpl::GetCurrentEvent()
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
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));
1249
// These cases happens before GLWindow is set. So we must catch them here.
1255
// WARNING: MUST RETURN TRUE TO CONTINUE WITH THE CREATION OF THE WINDOW
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
1264
// WARNING: MUST RETURN 0 TO CONTINUE WITH THE CREATION OF THE WINDOW
1268
return DefWindowProc(hWnd, uMsg, wParam, lParam);
1270
return GLWindow->WndProc(hWnd, uMsg, wParam, lParam);
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
1282
nuxDebugMsg(TEXT("[GLWindowImpl::WndProc]: Window \"%s\" received WM_DESTROY message."), m_WindowTitle.GetTCharPtr());
1288
nuxDebugMsg(TEXT("[GLWindowImpl::WndProc]: Window \"%s\" received WM_CLOSE message."), m_WindowTitle.GetTCharPtr());
1289
// close? yes or no?
1296
ValidateRect(hWnd, NULL); // validate the surface to avoid receiving WM_PAINT continuously
1297
m_pEvent->e_event = INL_WINDOW_DIRTY;
1301
case WM_CAPTURECHANGED:
1303
// The WM_CAPTURECHANGED message is sent to the window that is losing the mouse capture
1304
if((HWND)lParam != hWnd)
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"));
1314
case WM_ENTERSIZEMOVE:
1319
case WM_EXITSIZEMOVE:
1322
GetClientRect( hWnd, &clientrect);
1324
m_pEvent->e_event = INL_SIZE_CONFIGURATION;
1325
m_pEvent->width = clientrect.right - clientrect.left;
1326
m_pEvent->height = clientrect.bottom - clientrect.top;
1333
GetClientRect( hWnd, &clientrect);
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;
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);
1343
if((wParam == SIZE_MAXHIDE) || (wParam == SIZE_MINIMIZED))
1345
m_is_window_minimized = true;
1349
m_is_window_minimized = false;
1352
if((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED))
1354
m_pEvent->e_event = INL_SIZE_CONFIGURATION;
1362
m_pEvent->e_event = INL_WINDOW_ENTER_FOCUS;
1363
m_pEvent->e_mouse_state = 0;
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;
1372
m_pEvent->virtual_code = 0;
1373
//nuxDebugMsg(TEXT("Windows Msg: WM_SETFOCUS/INL_WINDOW_ENTER_FOCUS"));
1379
m_pEvent->e_event = INL_WINDOW_EXIT_FOCUS;
1380
m_pEvent->e_mouse_state = 0;
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;
1387
m_pEvent->virtual_code = 0;
1388
//nuxDebugMsg(TEXT("Windows Msg: WM_KILLFOCUS/INL_WINDOW_EXIT_FOCUS"));
1399
if(LOWORD(wParam)!=WA_INACTIVE)
1401
m_pEvent->e_key_modifiers = GetModifierKeyState();
1406
case WM_ACTIVATEAPP:
1409
m_pEvent->e_key_modifiers = GetModifierKeyState();
1416
m_pEvent->e_event = INL_KEYDOWN;
1417
m_pEvent->e_key_modifiers = GetModifierKeyState();
1418
m_pEvent->e_keysym = wParam;
1420
if((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN))
1422
m_pEvent->VirtualKeycodeState[GLWindowImpl::Win32KeySymToINL(wParam)] = 1;
1425
if(wParam == VK_CONTROL)
1427
if(lParam & (1 << 24))
1429
m_pEvent->e_keysym = INL_VK_RCONTROL;
1433
m_pEvent->e_keysym = INL_VK_LCONTROL;
1437
if(wParam == VK_MENU)
1439
if(lParam & (1 << 24))
1441
m_pEvent->e_keysym = INL_VK_RMENU;
1445
m_pEvent->e_keysym = INL_VK_LMENU;
1449
if(wParam == VK_SHIFT)
1451
if(HIWORD(GetAsyncKeyState(VK_LSHIFT)))
1453
m_pEvent->e_keysym = INL_VK_LSHIFT;
1455
else if(HIWORD(GetAsyncKeyState(VK_RSHIFT)))
1457
m_pEvent->e_keysym = INL_VK_RSHIFT;
1467
m_pEvent->e_event = INL_KEYUP;
1468
m_pEvent->e_key_modifiers = GetModifierKeyState();
1469
m_pEvent->e_keysym = wParam;
1471
if((uMsg == WM_KEYUP) || (uMsg == WM_SYSKEYUP))
1473
m_pEvent->VirtualKeycodeState[GLWindowImpl::Win32KeySymToINL(wParam)] = 0;
1479
case WM_SYSDEADCHAR:
1483
m_pEvent->e_key_modifiers = GetModifierKeyState();
1485
// reset key repeat count to 0.
1486
m_pEvent->e_key_repeat_count = 0;
1487
if (lParam & (1<<31))
1490
m_pEvent->e_event = INL_KEYUP;
1496
m_pEvent->e_event = INL_KEYDOWN;
1497
m_pEvent->e_key_repeat_count = (int)(lParam & 0xff);
1500
static char buffer[2];
1501
buffer[0] = 0; buffer[1] = 0;
1502
if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR)
1504
buffer[0] = char(wParam);
1505
m_pEvent->e_length = 1;
1510
m_pEvent->e_length = 0;
1513
m_pEvent->e_text = buffer;
1517
case WM_LBUTTONDOWN:
1519
mouse_event(hWnd, m_pEvent, 0, 1, wParam, lParam);
1520
//nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONDOWN"));
1523
case WM_LBUTTONDBLCLK:
1525
mouse_event(hWnd, m_pEvent, 1, 1, wParam, lParam);
1526
//nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONDBLCLK"));
1531
mouse_event(hWnd, m_pEvent, 2, 1, wParam, lParam);
1532
//nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONUP"));
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;}
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;}
1546
{mouse_event(hWnd, m_pEvent, 2, 3, wParam, lParam); break;}
1549
mouse_event(hWnd, m_pEvent, 0, 4, wParam, lParam); break;
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;}
1573
mouse_event(hWnd, m_pEvent, 3, 0, wParam, lParam);
1574
//nuxDebugMsg(TEXT("Windows Msg: WM_MOUSEMOVE"));
1576
TRACKMOUSEEVENT tme = { sizeof(tme) };
1577
// Enable INL_WINDOW_MOUSELEAVE event.
1578
tme.dwFlags = TME_LEAVE;
1579
tme.hwndTrack = hWnd;
1580
TrackMouseEvent(&tme);
1584
// Note: there is no WM_MOUSEENTER. WM_MOUSEENTER is equivalent to WM_MOUSEMOVE after a WM_MOUSELEAVE.
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"));
1599
if((LOWORD(lParam) == HTCLIENT) && m_Cursor)
1601
SetCursor(m_Cursor);
1602
return TRUE; //return FALSE;
1609
nuxDebugMsg(TEXT("[GLWindowImpl::WndProc]: Window \"%s\" received WM_COMMAND message."), m_WindowTitle.GetTCharPtr());
1613
case WM_SYSCOMMAND: // Intercept System Commands
1615
switch (wParam) // Check System Calls
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;
1640
return DefWindowProc(hWnd,uMsg,wParam,lParam);
1643
int GLWindowImpl::Win32KeySymToINL(int Keysym)
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;
1763
//---------------------------------------------------------------------------------------------------------
1764
void GLWindowImpl::GetDisplayInfo()
1772
bRetVal = ::EnumDisplaySettings(NULL, iMode, &devmode);
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);
1786
//---------------------------------------------------------------------------------------------------------
1787
void GLWindowImpl::ShowWindow()
1789
::ShowWindow(m_hWnd, SW_RESTORE);
1792
//---------------------------------------------------------------------------------------------------------
1793
void GLWindowImpl::HideWindow()
1795
::ShowWindow(m_hWnd, SW_MINIMIZE);
1798
//---------------------------------------------------------------------------------------------------------
1799
void GLWindowImpl::EnterMaximizeWindow()
1801
::ShowWindow(m_hWnd, SW_MAXIMIZE);
1804
//---------------------------------------------------------------------------------------------------------
1805
void GLWindowImpl::ExitMaximizeWindow()
1807
::ShowWindow(m_hWnd, SW_RESTORE);
1810
//---------------------------------------------------------------------------------------------------------
1811
void GLWindowImpl::SetWindowTitle(const TCHAR* Title)
1813
SetWindowText(m_hWnd, Title);
1816
//---------------------------------------------------------------------------------------------------------
1817
bool GLWindowImpl::HasVSyncSwapControl() const
1819
return GetThreadGLDeviceFactory()->SUPPORT_WGL_EXT_SWAP_CONTROL();
1822
//---------------------------------------------------------------------------------------------------------
1823
void GLWindowImpl::EnableVSyncSwapControl()
1826
if(HasVSyncSwapControl())
1828
wglSwapIntervalEXT(1);
1833
//---------------------------------------------------------------------------------------------------------
1834
void GLWindowImpl::DisableVSyncSwapControl()
1837
if(HasVSyncSwapControl())
1839
wglSwapIntervalEXT(0);
1844
float GLWindowImpl::GetFrameTime() const
1849
void GLWindowImpl::ResetFrameTime()
1854
bool GLWindowImpl::StartOpenFileDialog(FileDialogOption& fdo)
1856
return Win32OpenFileDialog(GetWindowHandle(), fdo);
1859
bool GLWindowImpl::StartSaveFileDialog(FileDialogOption& fdo)
1861
return Win32SaveFileDialog(GetWindowHandle(), fdo);
1864
bool GLWindowImpl::StartColorDialog(ColorDialogOption& cdo)
1866
return Win32ColorDialog(GetWindowHandle(), cdo);
1869
//---------------------------------------------------------------------------------------------------------
1870
void GLWindowImpl::SetWindowCursor(HCURSOR cursor)
1875
//---------------------------------------------------------------------------------------------------------
1876
HCURSOR GLWindowImpl::GetWindowCursor() const
1881
//---------------------------------------------------------------------------------------------------------
1882
void GLWindowImpl::PauseThreadGraphicsRendering()
1884
m_PauseGraphicsRendering = true;
1885
MakeGLContextCurrent(false);
1888
//---------------------------------------------------------------------------------------------------------
1889
bool GLWindowImpl::IsPauseThreadGraphicsRendering() const
1891
return m_PauseGraphicsRendering;