nux-1.16.0
|
00001 /* 00002 * Copyright 2010 Inalogic® Inc. 00003 * 00004 * This program is free software: you can redistribute it and/or modify it 00005 * under the terms of the GNU Lesser General Public License, as 00006 * published by the Free Software Foundation; either version 2.1 or 3.0 00007 * of the License. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranties of 00011 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 00012 * PURPOSE. See the applicable version of the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of both the GNU Lesser General Public 00016 * License along with this program. If not, see <http://www.gnu.org/licenses/> 00017 * 00018 * Authored by: Jay Taoko <jaytaoko@inalogic.com> 00019 * 00020 */ 00021 00022 00023 #include "GLResource.h" 00024 #include "NuxGraphics.h" 00025 #include "GpuDevice.h" 00026 #include "GLDeviceObjects.h" 00027 #include "GLResourceManager.h" 00028 00029 #include "GLTextureResourceManager.h" 00030 #include "GLVertexResourceManager.h" 00031 #include "GraphicsEngine.h" 00032 #include "GLWindowManager.h" 00033 #include "Events.h" 00034 #include "IniFile.h" 00035 00036 #include "GraphicsDisplay.h" 00037 00038 namespace nux 00039 { 00040 00041 // Compute the frame rate every FRAME_RATE_PERIODE; 00042 #define FRAME_RATE_PERIODE 10 00043 00044 void ClipOrCenterRectToMonitor (LPRECT prc, t_u32 flags) 00045 { 00046 HMONITOR hMonitor; 00047 MONITORINFO mi; 00048 RECT rc; 00049 int w = prc->right - prc->left; 00050 int h = prc->bottom - prc->top; 00051 00052 // 00053 // get the nearest monitor to the passed rect. 00054 // 00055 hMonitor = MonitorFromRect (prc, MONITOR_DEFAULTTONEAREST); 00056 00057 // 00058 // get the work area or entire monitor rect. 00059 // 00060 mi.cbSize = sizeof (mi); 00061 GetMonitorInfo (hMonitor, &mi); 00062 00063 //if (flags & MONITOR_WORKAREA) 00064 rc = mi.rcWork; 00065 // else 00066 // rc = mi.rcMonitor; 00067 00068 // 00069 // center or clip the passed rect to the monitor rect 00070 // 00071 //if (flags & MONITOR_CENTER) 00072 { 00073 prc->left = rc.left + (rc.right - rc.left - w) / 2; 00074 prc->top = rc.top + (rc.bottom - rc.top - h) / 2; 00075 prc->right = prc->left + w; 00076 prc->bottom = prc->top + h; 00077 } 00078 // else 00079 // { 00080 // prc->left = Max(rc.left, Min(rc.right-w, prc->left)); 00081 // prc->top = Max(rc.top, Min(rc.bottom-h, prc->top)); 00082 // prc->right = prc->left + w; 00083 // prc->bottom = prc->top + h; 00084 // } 00085 } 00086 00087 EventToNameStruct EventToName[] = 00088 { 00089 {NUX_NO_EVENT, TEXT ("NUX_NO_EVENT") }, 00090 {NUX_MOUSE_PRESSED, TEXT ("NUX_MOUSE_PRESSED") }, 00091 {NUX_MOUSE_RELEASED, TEXT ("NUX_MOUSE_RELEASED") }, 00092 {NUX_KEYDOWN, TEXT ("NUX_KEYDOWN") }, 00093 {NUX_KEYUP, TEXT ("NUX_KEYUP") }, 00094 {NUX_MOUSE_MOVE, TEXT ("NUX_MOUSE_MOVE") }, 00095 {NUX_SIZE_CONFIGURATION, TEXT ("NUX_SIZE_CONFIGURATION") }, 00096 {NUX_WINDOW_CONFIGURATION, TEXT ("NUX_WINDOW_CONFIGURATION") }, 00097 {NUX_WINDOW_ENTER_FOCUS, TEXT ("NUX_WINDOW_ENTER_FOCUS") }, 00098 {NUX_WINDOW_EXIT_FOCUS, TEXT ("NUX_WINDOW_EXIT_FOCUS") }, 00099 {NUX_WINDOW_DIRTY, TEXT ("NUX_WINDOW_DIRTY") }, 00100 {NUX_WINDOW_MOUSELEAVE, TEXT ("NUX_WINDOW_MOUSELEAVE") }, 00101 {NUX_TERMINATE_APP, TEXT ("NUX_TERMINATE_APP") } 00102 }; 00103 00104 //--------------------------------------------------------------------------------------------------------- 00105 HGLRC GraphicsDisplay::sMainGLRC = 0; 00106 HDC GraphicsDisplay::sMainDC = 0; 00107 00108 GraphicsDisplay::GraphicsDisplay() 00109 : event_ (NULL) 00110 , m_GfxInterfaceCreated (false) 00111 , m_fullscreen (false) 00112 , m_ScreenBitDepth (32) 00113 , m_num_device_modes (0) 00114 , m_index_of_current_mode (-1) 00115 , m_DeviceFactory (0) 00116 , m_GraphicsContext (0) 00117 // , m_GLEWContext(0) 00118 // , m_WGLEWContext(0) 00119 , m_Style (WINDOWSTYLE_NORMAL) 00120 , m_Cursor (0) 00121 , m_PauseGraphicsRendering (false) 00122 , m_ParentWindow (0) 00123 , m_dwExStyle (0) 00124 , m_dwStyle (0) 00125 { 00126 inlSetThreadLocalStorage (_TLS_GraphicsDisplay, this); 00127 00128 m_GfxInterfaceCreated = false; 00129 event_ = new Event(); 00130 GetDisplayInfo(); 00131 00132 m_WindowSize.width = 0; 00133 m_WindowSize.height = 0; 00134 00135 // A window never starts in a minimized state. 00136 m_is_window_minimized = false; 00137 00138 //_dnd_source_grab_active = false; 00139 _global_keyboard_grab_data = 0; 00140 _global_pointer_grab_data = 0; 00141 00142 } 00143 00144 //--------------------------------------------------------------------------------------------------------- 00145 GraphicsDisplay::~GraphicsDisplay() 00146 { 00147 NUX_SAFE_DELETE ( m_GraphicsContext ); 00148 NUX_SAFE_DELETE ( m_DeviceFactory ); 00149 00150 // NUX_SAFE_DELETE( m_WGLEWContext ); 00151 // NUX_SAFE_DELETE( m_GLEWContext ); 00152 00153 DestroyOpenGLWindow(); 00154 NUX_SAFE_DELETE ( event_ ); 00155 00156 inlSetThreadLocalStorage (_TLS_GraphicsDisplay, 0); 00157 } 00158 00159 //--------------------------------------------------------------------------------------------------------- 00160 bool GraphicsDisplay::IsGfxInterfaceCreated() 00161 { 00162 return m_GfxInterfaceCreated; 00163 } 00164 00165 //--------------------------------------------------------------------------------------------------------- 00166 static NCriticalSection CreateOpenGLWindow_CriticalSection; 00167 bool GraphicsDisplay::CreateOpenGLWindow(const TCHAR *WindowTitle, 00168 unsigned int WindowWidth, 00169 unsigned int WindowHeight, 00170 WindowStyle Style, 00171 const GraphicsDisplay *Parent, 00172 bool FullscreenFlag, 00173 bool create_rendering_data) 00174 { 00175 NScopeLock Scope (&CreateOpenGLWindow_CriticalSection); 00176 00177 RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values 00178 00179 m_GfxInterfaceCreated = false; 00180 00181 // FIXME : put at the end 00182 m_ViewportSize.width = WindowWidth; 00183 m_ViewportSize.height = WindowHeight; 00184 m_WindowSize.width = WindowWidth; 00185 m_WindowSize.height = WindowHeight; 00186 00187 // end of fixme 00188 00189 WindowRect.left = (long) 0; 00190 WindowRect.right = (long) m_ViewportSize.width; 00191 WindowRect.top = (long) 0; 00192 WindowRect.bottom = (long) m_ViewportSize.height; 00193 00194 m_fullscreen = FullscreenFlag; // Set The Global Fullscreen Flag 00195 m_index_of_current_mode = -1; // assume -1 if the mode is not fullscreen 00196 00197 00198 if (m_fullscreen) // Attempt Fullscreen Mode? 00199 { 00200 // check if resolution is supported 00201 bool mode_supported = false; 00202 00203 for (int num_modes = 0 ; num_modes < m_num_gfx_device_modes; num_modes++) 00204 { 00205 if ((m_gfx_device_modes[num_modes].width == m_ViewportSize.width) 00206 && (m_gfx_device_modes[num_modes].height == m_ViewportSize.height) 00207 && (m_gfx_device_modes[num_modes].format == m_ScreenBitDepth)) 00208 { 00209 mode_supported = true; 00210 m_index_of_current_mode = num_modes; 00211 break; 00212 } 00213 } 00214 00215 if (mode_supported == false) 00216 { 00217 if (inlWin32MessageBox (NULL, TEXT ("Info"), MBTYPE_Ok, MBICON_Information, MBMODAL_ApplicationModal, 00218 TEXT ("The requested fullscreen mode is not supported by your monitor.\nUsing windowed mode instead.") ) == MBRES_Yes) 00219 { 00220 m_fullscreen = FALSE; // Windowed Mode Selected. Fullscreen = FALSE 00221 } 00222 } 00223 00224 DEVMODE dmScreenSettings; // Device Mode 00225 memset (&dmScreenSettings, 0, sizeof (dmScreenSettings)); // Makes Sure Memory's Cleared 00226 dmScreenSettings.dmSize = sizeof (dmScreenSettings); // Size Of The Devmode Structure 00227 dmScreenSettings.dmPelsWidth = m_ViewportSize.width; // Selected Screen Width 00228 dmScreenSettings.dmPelsHeight = m_ViewportSize.height; // Selected Screen Height 00229 dmScreenSettings.dmBitsPerPel = m_ScreenBitDepth; // Selected Bits Per Pixel 00230 dmScreenSettings.dmDisplayFrequency = 60; 00231 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; 00232 00233 // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. 00234 if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) 00235 { 00236 if (inlWin32MessageBox (NULL, TEXT ("Info"), MBTYPE_Ok, MBICON_Information, MBMODAL_ApplicationModal, 00237 TEXT ("The requested fullscreen mode is not supported by your monitor.\nUsing windowed mode instead.") ) == MBRES_Yes) 00238 { 00239 m_fullscreen = FALSE; // Windowed Mode Selected. Fullscreen = FALSE 00240 } 00241 else 00242 { 00243 // Pop Up A Message Box Letting User Know The Program Is Closing. 00244 MessageBox (NULL, "Program Will Now Close.", "ERROR", MB_OK | MB_ICONSTOP); 00245 } 00246 } 00247 } 00248 00249 m_dwExStyle = 0; 00250 m_dwStyle = 0; 00251 00252 if (m_fullscreen) // Are We Still In Fullscreen Mode? 00253 { 00254 m_dwExStyle = WS_EX_APPWINDOW; // Window Extended Style 00255 m_dwStyle = WS_POPUP; // Windows Style 00256 ShowCursor (FALSE); // Hide Mouse Pointer 00257 } 00258 else 00259 { 00260 // Window Extended Style 00261 m_dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; 00262 // Windows Style 00263 m_dwStyle = WS_OVERLAPPED; // Creates an overlapped window. An overlapped window has a title bar and a border 00264 00265 // See Win32 Window Hierarchy and Styles: http://msdn.microsoft.com/en-us/library/ms997562.aspx 00266 00267 //WS_EX_APPWINDOW // Forces a top-level window onto the taskbar when the window is visible 00268 //WS_EX_WINDOWEDGE // Specifies that a window has a border with a raised edge 00269 00270 //WS_POPUP // Creates a pop-up window. This style cannot be used with the WS_CHILD style. 00271 //WS_SYSMENU // Creates a window that has a window menu on its title bar. The WS_CAPTION style must also be specified. 00272 //WS_SIZEBOX // Creates a window that has a sizing border. Same as the WS_THICKFRAME style. 00273 //WS_CAPTION // Creates a window that has a title bar (includes the WS_BORDER style). 00274 00275 m_Style = Style; 00276 00277 if (Style == WINDOWSTYLE_TOOL) 00278 { 00279 m_dwExStyle = WS_EX_TOOLWINDOW; 00280 m_dwStyle = WS_CAPTION | WS_SYSMENU; 00281 } 00282 else if (Style == WINDOWSTYLE_DIALOG) 00283 { 00284 m_dwExStyle = WS_EX_DLGMODALFRAME; 00285 m_dwStyle = WS_CAPTION | WS_SYSMENU; 00286 } 00287 else if (Style == WINDOWSTYLE_NOBORDER) 00288 { 00289 m_dwExStyle = WS_EX_TOPMOST | WS_EX_TOOLWINDOW; 00290 m_dwStyle = WS_POPUP; 00291 } 00292 else if (Style == WINDOWSTYLE_PANEL) 00293 { 00294 m_dwExStyle = 0; // Specifies that a window has a border with a raised edge 00295 m_dwStyle = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX; 00296 } 00297 else 00298 { 00299 // Normal Window: NormalWindow 00300 m_dwExStyle = WS_EX_APPWINDOW | // Forces a top-level window onto the taskbar when the window is visible 00301 WS_EX_WINDOWEDGE; // Specifies that a window has a border with a raised edge 00302 00303 m_dwStyle |= WS_CAPTION | // Creates a window that has a title bar. 00304 WS_SYSMENU | // Creates a window that has a window menu on its title bar. The WS_CAPTION style must also be specified. 00305 WS_THICKFRAME | // Creates a window that has a sizing border. 00306 WS_MINIMIZEBOX | // Creates a window that has a minimize button. 00307 WS_MAXIMIZEBOX | // Creates a window that has a maximize button. 00308 WS_BORDER; // Creates a window that has a thin-line border. 00309 } 00310 } 00311 // The AdjustWindowRectEx function calculates the required size of the window rectangle, 00312 // based on the desired size of the client rectangle. The window rectangle can then be passed to 00313 // the CreateWindowEx function to create a window whose client area is the desired size. 00314 AdjustWindowRectEx (&WindowRect, m_dwStyle, FALSE, m_dwExStyle); // Adjust Window To True Requested Size 00315 00316 RECT rect; 00317 rect.top = 0; 00318 rect.bottom = WindowRect.bottom - WindowRect.top; 00319 rect.left = 0; 00320 rect.right = WindowRect.right - WindowRect.left; 00321 int WindowX = 0; 00322 int WindowY = 0; 00323 00324 if (Parent) 00325 { 00326 m_ParentWindow = Parent->GetWindowHandle(); 00327 GetWindowRect (m_ParentWindow, &rect); 00328 00329 int width = rect.right - rect.left; 00330 int height = rect.bottom - rect.top; 00331 00332 WindowX = rect.left + (width - (WindowRect.right - WindowRect.left) ) / 2; 00333 WindowY = rect.top + (height - (WindowRect.bottom - WindowRect.top) ) / 2; 00334 } 00335 else if (!m_fullscreen) 00336 { 00337 ClipOrCenterRectToMonitor (&rect, 0); 00338 WindowX = rect.left; 00339 WindowY = rect.top; 00340 } 00341 00342 m_WindowTitle = WindowTitle; 00343 00344 // Create The Window 00345 if (! (m_hWnd = ::CreateWindowEx (m_dwExStyle, // Extended Style For The Window 00346 WINDOW_CLASS_NAME, // Class Name 00347 m_WindowTitle.GetTCharPtr(), // Window Title 00348 m_dwStyle | // Defined Window Style 00349 WS_CLIPSIBLINGS | // Required Window Style 00350 WS_CLIPCHILDREN, // Required Window Style 00351 WindowX, WindowY, // Window Position 00352 WindowRect.right - WindowRect.left, // Calculate Window Width 00353 WindowRect.bottom - WindowRect.top, // Calculate Window Height 00354 m_ParentWindow, // No Parent Window 00355 NULL, // No Menu 00356 gGLWindowManager.GetInstance(), // Instance 00357 NULL) ) ) // Dont Pass Anything To WM_CREATE 00358 { 00359 DestroyOpenGLWindow(); 00360 MessageBox (NULL, TEXT ("Window Creation Error."), TEXT ("ERROR"), MB_OK | MB_ICONERROR); 00361 // Return FALSE 00362 } 00363 00364 static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be 00365 { 00366 sizeof (PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 00367 1, // Version Number 00368 PFD_DRAW_TO_WINDOW | // Format Must Support Window 00369 PFD_SUPPORT_OPENGL | // Format Must Support OpenGL 00370 PFD_DOUBLEBUFFER, // Must Support Double Buffering 00371 PFD_TYPE_RGBA, // Request An RGBA Format 00372 24, // cColorBits 00373 // Specifies the number of color bitplanes in each color buffer. 00374 // For RGBA pixel types, it is the size of the color buffer, excluding the alpha bitplanes. 00375 // For color-index pixels, it is the size of the color-index buffer. 00376 00377 00378 0, // cRedBits 00379 // Specifies the number of red bitplanes in each RGBA color buffer. 00380 0, // cRedShift 00381 // Specifies the shift count for red bitplanes in each RGBA color buffer. 00382 0, // cGreenBits 00383 // Specifies the number of green bitplanes in each RGBA color buffer. 00384 0, // cGreenShift 00385 // Specifies the shift count for green bitplanes in each RGBA color buffer. 00386 0, // cBlueBits 00387 // Specifies the number of blue bitplanes in each RGBA color buffer. 00388 0, // cBlueShift 00389 // Specifies the shift count for blue bitplanes in each RGBA color buffer. 00390 00391 0, // cAlphaBits 00392 // Specifies the number of alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported. 00393 0, // cAlphaShift 00394 // Specifies the shift count for alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported. 00395 00396 0, // cAccumBits 00397 // Specifies the total number of bitplanes in the accumulation buffer. 00398 0, // cAccumRedBits 00399 // Specifies the number of red bitplanes in the accumulation buffer. 00400 0, // cAccumGreenBits 00401 // Specifies the number of green bitplanes in the accumulation buffer. 00402 0, // cAccumBlueBits 00403 // Specifies the number of blue bitplanes in the accumulation buffer. 00404 0, // cAccumAlphaBits 00405 // Specifies the number of alpha bitplanes in the accumulation buffer. 00406 24,// cDepthBits 00407 // Specifies the depth of the depth (z-axis) buffer. 00408 8, // cStencilBits 00409 // Specifies the depth of the stencil buffer. 00410 0, // cAuxBuffers 00411 // Specifies the number of auxiliary buffers. Auxiliary buffers are not supported. 00412 PFD_MAIN_PLANE, // iLayerType 00413 // Ignored. Earlier implementations of OpenGL used this member, but it is no longer used. 00414 0, // bReserved 00415 // 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. 00416 0, // dwLayerMask 00417 // Ignored. Earlier implementations of OpenGL used this member, but it is no longer used. 00418 0, // dwVisibleMask 00419 // 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. 00420 0, // dwDamageMask 00421 // Ignored. Earlier implementations of OpenGL used this member, but it is no longer used. 00422 }; 00423 00424 if (! (_device_context = GetDC (m_hWnd) ) ) // Did We Get A Device Context? 00425 { 00426 DestroyOpenGLWindow(); 00427 MessageBox (NULL, TEXT ("Can't Create A GL Device Context."), TEXT ("ERROR"), MB_OK | MB_ICONERROR); 00428 return FALSE; 00429 } 00430 00431 if (! (m_PixelFormat = ChoosePixelFormat (_device_context, &pfd) ) ) // Did Windows Find A Matching Pixel Format? 00432 { 00433 DestroyOpenGLWindow(); 00434 MessageBox (NULL, TEXT ("Can't Find A Suitable PixelFormat."), TEXT ("ERROR"), MB_OK | MB_ICONERROR); 00435 return FALSE; 00436 } 00437 00438 if (!SetPixelFormat (_device_context, m_PixelFormat, &pfd) ) // Are We Able To Set The Pixel Format? 00439 { 00440 DestroyOpenGLWindow(); 00441 MessageBox (NULL, TEXT ("Can't Set The PixelFormat."), TEXT ("ERROR"), MB_OK | MB_ICONERROR); 00442 return FALSE; 00443 } 00444 00445 if (! (_opengl_rendering_context = wglCreateContext (_device_context) ) ) // Are We Able To Get A Rendering Context? 00446 { 00447 DestroyOpenGLWindow(); 00448 MessageBox (NULL, TEXT ("Can't Create A GL Rendering Context."), TEXT ("ERROR"), MB_OK | MB_ICONERROR); 00449 return FALSE; 00450 } 00451 00452 if (sMainGLRC == 0) 00453 { 00454 sMainGLRC = _opengl_rendering_context; 00455 sMainDC = _device_context; 00456 } 00457 else 00458 { 00459 // wglMakeCurrent(_device_context, 0); 00460 // // Make the newly created context share it resources with all the other OpenGL context 00461 // if(wglShareLists(sMainGLRC, _opengl_rendering_context) == FALSE) 00462 // { 00463 // DWORD err = GetLastError(); 00464 // DestroyOpenGLWindow(); 00465 // MessageBox(NULL, TEXT("Can't share GL context."), TEXT("ERROR"), MB_OK|MB_ICONERROR); 00466 // return FALSE; 00467 // } 00468 } 00469 00470 // This creates a warning. It is a 64-bits compatibility issue. 00471 // When not in 64-bit you can disable the warning: 00472 // Project Properties --> C/C++ tab --> General --> Select "NO" for - Detect 64-bit Portability Issues. 00473 // See also SetWindowLongPtr 00474 SetWindowLongPtr (m_hWnd, GWLP_USERDATA, (NUX_PTRSIZE_LONG) this); 00475 00476 //::ShowWindow(m_hWnd,SW_SHOW); // Show The Window 00477 ::SetForegroundWindow (m_hWnd); // Slightly Higher Priority 00478 ::SetFocus (m_hWnd); // Sets Keyboard Focus To The Window 00479 00480 MakeGLContextCurrent(); 00481 glClearColor (0.0, 0.0, 0.0, 0.0); 00482 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 00483 SwapBuffer(); 00484 00485 m_GfxInterfaceCreated = true; 00486 00487 //m_GLEWContext = new GLEWContext(); 00488 //m_WGLEWContext = new WGLEWContext(); 00489 00490 HGLRC new_opengl_rendering_context = _opengl_rendering_context; 00491 m_DeviceFactory = new GpuDevice (m_ViewportSize.width, m_ViewportSize.height, BITFMT_R8G8B8A8, 00492 _device_context, 00493 new_opengl_rendering_context, 00494 1, 0, false); 00495 00496 if (new_opengl_rendering_context != 0) 00497 { 00498 _opengl_rendering_context = new_opengl_rendering_context; 00499 } 00500 00501 m_GraphicsContext = new GraphicsEngine (*this, create_rendering_data); 00502 00503 //EnableVSyncSwapControl(); 00504 //DisableVSyncSwapControl(); 00505 00506 InitGlobalGrabWindow (); 00507 00508 return true; 00509 } 00510 00511 bool GraphicsDisplay::CreateFromOpenGLWindow (HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext) 00512 { 00513 // Do not make the opengl context current 00514 // Do not swap the framebuffer 00515 // Do not clear the depth or color buffer 00516 // Do not enable/disable VSync 00517 00518 m_hWnd = WindowHandle; 00519 _device_context = WindowDCHandle; 00520 _opengl_rendering_context = OpenGLRenderingContext; 00521 00522 RECT rect; 00523 ::GetClientRect (m_hWnd, &rect); 00524 m_WindowSize = Size (rect.right - rect.left, rect.bottom - rect.top); 00525 m_ViewportSize = Size (rect.right - rect.left, rect.bottom - rect.top); 00526 00527 // The opengl context should be made current by an external entity. 00528 00529 m_GfxInterfaceCreated = true; 00530 m_DeviceFactory = new GpuDevice (m_ViewportSize.width, m_ViewportSize.height, BITFMT_R8G8B8A8, 00531 _device_context, 00532 _opengl_rendering_context); 00533 00534 m_GraphicsContext = new GraphicsEngine (*this); 00535 00536 InitGlobalGrabWindow (); 00537 00538 return true; 00539 } 00540 00541 GraphicsEngine* GraphicsDisplay::GetGraphicsEngine() const 00542 { 00543 return m_GraphicsContext; 00544 } 00545 00546 GpuDevice* GraphicsDisplay::GetGpuDevice () const 00547 { 00548 return m_DeviceFactory; 00549 } 00550 00551 //--------------------------------------------------------------------------------------------------------- 00552 // NUXTODO: remove this call. Make a direct access to GpuInfo via GpuDevice. 00553 bool GraphicsDisplay::HasFrameBufferSupport() 00554 { 00555 return m_DeviceFactory->GetGpuInfo ().Support_EXT_Framebuffer_Object (); 00556 } 00557 00558 //--------------------------------------------------------------------------------------------------------- 00559 void GraphicsDisplay::GetWindowSize (int &w, int &h) 00560 { 00561 w = m_WindowSize.width; 00562 h = m_WindowSize.height; 00563 } 00564 00565 //--------------------------------------------------------------------------------------------------------- 00566 int GraphicsDisplay::GetWindowWidth () 00567 { 00568 return m_WindowSize.width; 00569 } 00570 00571 //--------------------------------------------------------------------------------------------------------- 00572 int GraphicsDisplay::GetWindowHeight () 00573 { 00574 return m_WindowSize.height; 00575 } 00576 00577 void GraphicsDisplay::ResetWindowSize () 00578 { 00579 RECT rect; 00580 ::GetClientRect (m_hWnd, &rect); 00581 m_WindowSize = Size (rect.right - rect.left, rect.bottom - rect.top); 00582 m_ViewportSize = Size (rect.right - rect.left, rect.bottom - rect.top); 00583 } 00584 00585 //--------------------------------------------------------------------------------------------------------- 00586 void GraphicsDisplay::SetWindowSize (int width, int height) 00587 { 00588 RECT window_rect; 00589 RECT new_rect; 00590 ::GetWindowRect (m_hWnd, &window_rect); 00591 00592 new_rect.left = 0; 00593 new_rect.right = width; 00594 new_rect.top = 0; 00595 new_rect.bottom = height; 00596 BOOL b = ::AdjustWindowRectEx (&new_rect, m_dwStyle, FALSE, m_dwExStyle); // Adjust Window To True Requested Size 00597 00598 ::MoveWindow (m_hWnd, 00599 window_rect.left, 00600 window_rect.top, 00601 (new_rect.right - new_rect.left), 00602 (new_rect.bottom - new_rect.top), 00603 TRUE); 00604 } 00605 00606 //--------------------------------------------------------------------------------------------------------- 00607 void GraphicsDisplay::SetViewPort (int x, int y, int width, int height) 00608 { 00609 if (IsGfxInterfaceCreated ()) 00610 { 00611 //do not rely on m_ViewportSize: glViewport can be called directly 00612 m_ViewportSize.width = width; 00613 m_ViewportSize.height = height; 00614 00615 m_GraphicsContext->SetViewport (x, y, m_ViewportSize.width, m_ViewportSize.height); 00616 m_GraphicsContext->SetScissor (0, 0, width, height); 00617 } 00618 } 00619 00620 Point GraphicsDisplay::GetMouseScreenCoord () 00621 { 00622 POINT pt; 00623 ::GetCursorPos (&pt); 00624 ScreenToClient (m_hWnd, &pt); 00625 Point point (pt.x, pt.y); 00626 return point; 00627 } 00628 00629 Point GraphicsDisplay::GetMouseWindowCoord () 00630 { 00631 POINT pt; 00632 ::GetCursorPos (&pt); 00633 ::ScreenToClient (m_hWnd, &pt); 00634 Point point (pt.x, pt.y); 00635 return point; 00636 } 00637 00638 Point GraphicsDisplay::GetWindowCoord () 00639 { 00640 RECT rect; 00641 ::GetWindowRect (m_hWnd, &rect); 00642 Point point (rect.left, rect.top); 00643 return point; 00644 } 00645 00646 Rect GraphicsDisplay::GetWindowGeometry () 00647 { 00648 RECT rect; 00649 ::GetClientRect (m_hWnd, &rect); 00650 Rect geo (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 00651 return geo; 00652 } 00653 00654 Rect GraphicsDisplay::GetNCWindowGeometry () 00655 { 00656 RECT rect; 00657 ::GetWindowRect (m_hWnd, &rect); 00658 Rect geo (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 00659 return geo; 00660 } 00661 00662 void GraphicsDisplay::MakeGLContextCurrent (bool b) 00663 { 00664 HGLRC glrc = _opengl_rendering_context; 00665 00666 if (b == false) 00667 { 00668 glrc = 0; 00669 } 00670 00671 if (!wglMakeCurrent (_device_context, glrc) ) 00672 { 00673 NString error = inlGetSystemErrorMessage(); 00674 DestroyOpenGLWindow(); 00675 MessageBox (NULL, TEXT ("Can't Activate The GL Rendering Context."), TEXT ("ERROR"), MB_OK | MB_ICONERROR); 00676 } 00677 } 00678 00679 void GraphicsDisplay::SwapBuffer (bool glswap) 00680 { 00681 if (IsPauseThreadGraphicsRendering() ) 00682 return; 00683 00684 if (glswap) 00685 { 00686 SwapBuffers (_device_context); 00687 } 00688 00689 m_FrameTime = m_Timer.PassedMilliseconds(); 00690 00691 // if(16.6f - m_FrameTime > 0) 00692 // { 00693 // SleepForMilliseconds(16.6f - m_FrameTime); 00694 // } 00695 // 00696 // m_FrameTime = m_Timer.PassedMilliseconds(); 00697 // m_Timer.Reset(); 00698 // m_PeriodeTime += m_FrameTime; 00699 // 00700 // m_FrameCounter++; 00701 // m_FramePeriodeCounter++; 00702 // if(m_FramePeriodeCounter >= FRAME_RATE_PERIODE) 00703 // { 00704 // m_FrameRate = m_FramePeriodeCounter * 1000.0f / m_PeriodeTime; 00705 // m_PeriodeTime = 0.0f; 00706 // m_FramePeriodeCounter = 0; 00707 // } 00708 } 00709 //--------------------------------------------------------------------------------------------------------- 00710 void GraphicsDisplay::DestroyOpenGLWindow() 00711 { 00712 if (m_GfxInterfaceCreated == true) 00713 { 00714 if (m_fullscreen) // Are We In Fullscreen Mode? 00715 { 00716 ChangeDisplaySettings (NULL, 0); // If So Switch Back To The Desktop 00717 ShowCursor (TRUE); // Show Mouse Pointer 00718 } 00719 00720 if (_opengl_rendering_context) // Do We Have A Rendering Context? 00721 { 00722 if (!wglMakeCurrent (_device_context, NULL) ) // Are We Able To Release The DC And RC Contexts? 00723 { 00724 MessageBox (NULL, TEXT ("Release Of DC And RC Failed."), TEXT ("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); 00725 } 00726 00727 if (!wglDeleteContext (_opengl_rendering_context) ) // Are We Able To Delete The RC? 00728 { 00729 MessageBox (NULL, TEXT ("Release Rendering Context Failed."), TEXT ("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); 00730 } 00731 00732 _opengl_rendering_context = NULL; // Set RC To NULL 00733 } 00734 00735 if (_device_context && !ReleaseDC (m_hWnd, _device_context) ) // Are We Able To Release The DC 00736 { 00737 MessageBox (NULL, TEXT ("Release Device Context Failed."), TEXT ("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); 00738 _device_context = NULL; // Set DC To NULL 00739 } 00740 00741 if (m_hWnd && ! (::DestroyWindow (m_hWnd) ) ) // Are We Able To Destroy The Window? 00742 { 00743 MessageBox (NULL, TEXT ("Could Not Release window handle."), TEXT ("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); 00744 m_hWnd = NULL; // Set Window Handle To NULL 00745 } 00746 } 00747 00748 m_GfxInterfaceCreated = false; 00749 } 00750 00751 00752 // //--------------------------------------------------------------------------------------------------------- 00753 // // convert a MSWindows VK_x to an Fltk (X) Keysym: 00754 // // See also the inverse converter in Fl_get_key_win32.cxx 00755 // // This table is in numeric order by VK: 00756 // static const struct {unsigned short vk, fltk, extended;} vktab[] = { 00757 // {NUX_VK_BACK, NUX_BackSpace}, 00758 // {NUX_VK_TAB, NUX_Tab}, 00759 // {NUX_VK_CLEAR, NUX_Clear, 0xff0b/*XK_Clear*/}, 00760 // {NUX_VK_ENTER, NUX_Enter, NUX_KP_ENTER}, 00761 // {NUX_VK_SHIFT, NUX_Shift_L, NUX_EXT_Shift_R}, 00762 // {NUX_VK_CONTROL, NUX_Control_L, NUX_EXT_Control_R}, 00763 // {NUX_VK_MENU, NUX_Alt_L, NUX_EXT_Alt_R}, 00764 // {NUX_VK_PAUSE, NUX_Pause}, 00765 // {NUX_VK_CAPITAL, NUX_Caps_Lock}, 00766 // {NUX_VK_ESCAPE, NUX_Escape}, 00767 // {NUX_VK_SPACE, ' '}, 00768 // {NUX_VK_PAGE_UP, NUX_Page_Up /*KP+'9'*/, NUX_KP_PAGE_UP}, 00769 // {NUX_VK_PAGE_DOWN, NUX_Page_Down /*KP+'3'*/, NUX_KP_PAGE_DOWN}, 00770 // {NUX_VK_END, NUX_End /*KP+'1'*/, NUX_KP_END}, 00771 // {NUX_VK_HOME, NUX_Home /*KP+'7'*/, NUX_KP_HOME}, 00772 // {NUX_VK_LEFT, NUX_Left /*KP+'4'*/, NUX_KP_LEFT}, 00773 // {NUX_VK_UP, NUX_Up /*KP+'8'*/, NUX_KP_UP}, 00774 // {NUX_VK_RIGHT, NUX_Right /*KP+'6'*/, NUX_KP_RIGHT}, 00775 // {NUX_VK_DOWN, NUX_Down /*KP+'2'*/, NUX_KP_DOWN}, 00776 // {NUX_VK_SNAPSHOT, NUX_Print}, // does not work on NT 00777 // {NUX_VK_INSERT, NUX_Insert /*KP+'0'*/, NUX_KP_INSERT}, 00778 // {NUX_VK_DELETE, NUX_Delete /*KP+'.'*/, NUX_KP_DELETE}, 00779 // {NUX_VK_LWIN, NUX_LWin /*Meta_L*/}, 00780 // {NUX_VK_RWIN, NUX_RWin /*Meta_R*/}, 00781 // {NUX_VK_APPS, NUX_VK_APPS /*Menu*/}, 00782 // {NUX_VK_MULTIPLY, NUX_Multiply /*KP+'*'*/}, 00783 // {NUX_VK_ADD, NUX_Add /*KP+'+'*/}, 00784 // {NUX_VK_SUBTRACT, NUX_Subtract /*KP+'-'*/}, 00785 // {NUX_VK_DECIMAL, NUX_Decimal /*KP+'.'*/}, 00786 // {NUX_VK_DIVIDE, NUX_Divide /*KP+'/'*/}, 00787 // {NUX_VK_NUMLOCK, NUX_Numlock /*Num_Lock*/}, 00788 // {NUX_VK_SCROLL, NUX_Scroll /*Scroll_Lock*/}, 00789 // {0xba, ';'}, 00790 // {0xbb, '='}, 00791 // {0xbc, ','}, 00792 // {0xbd, '-'}, 00793 // {0xbe, '.'}, 00794 // {0xbf, '/'}, 00795 // {0xc0, '`'}, 00796 // {0xdb, '['}, 00797 // {0xdc, '\\'}, 00798 // {0xdd, ']'}, 00799 // {0xde, '\''} 00800 // }; 00801 00802 /* 00803 The extended-key flag indicates whether the keystroke message originated 00804 from one of the additional keys on the enhanced keyboard. The extended keys 00805 consist of the ALT and CTRL keys on the right-hand side of the keyboard; 00806 the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters 00807 to the left of the numeric keypad; the NUM LOCK key; the BREAK (CTRL+PAUSE) key; 00808 the PRINT SCRN key; and the divide (/) and ENTER keys in the numeric keypad. 00809 The extended-key flag is set if the key is an extended key. 00810 */ 00811 //--------------------------------------------------------------------------------------------------------- 00812 /*static int ms2fltk(int vk, int extended) 00813 { 00814 static unsigned short vklut[256]; 00815 static unsigned short extendedlut[256]; 00816 if (!vklut[1]) 00817 { 00818 // init the table 00819 unsigned int i; 00820 for (i = 0; i < 256; i++) 00821 { 00822 vklut[i] = i; //tolower(i); 00823 } 00824 // for (i=VK_F1; i<=VK_F16; i++) 00825 // { 00826 // vklut[i] = i+(FL_F-(VK_F1-1)); // (FL_F + 1 -> VK_F1) ... (FL_F + 16 -> VK_F16) 00827 // } 00828 // for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++) 00829 // { 00830 // vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0); // (FL_KP + '0' -> VK_NUMPAD0) ... (FL_KP + '9' = VK_NUMPAD9) 00831 // } 00832 for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) 00833 { 00834 vklut[vktab[i].vk] = vktab[i].fltk; 00835 extendedlut[vktab[i].vk] = vktab[i].extended; 00836 } 00837 for (i = 0; i < 256; i++) 00838 { 00839 if (!extendedlut[i]) 00840 extendedlut[i] = vklut[i]; 00841 } 00842 } 00843 00844 return extended ? extendedlut[vk] : vklut[vk]; 00845 }*/ 00846 //--------------------------------------------------------------------------------------------------------- 00847 static int mouse_event (HWND window, Event *event, int what, int button, 00848 WPARAM wParam, LPARAM lParam) 00849 { 00850 static int px, py, pmx, pmy; 00851 event->e_x = (signed short) LOWORD (lParam); 00852 event->e_y = (signed short) HIWORD (lParam); 00853 event->e_x_root = 0; 00854 event->e_y_root = 0; 00855 00856 POINT EventScreenPosition; 00857 00858 ClientToScreen (window, &EventScreenPosition); 00859 EventScreenPosition.x = event->e_x; 00860 EventScreenPosition.y = event->e_y; 00861 POINT WindowScreenPosition; 00862 WindowScreenPosition.x = WindowScreenPosition.y = 0; 00863 ClientToScreen (window, &WindowScreenPosition); 00864 00865 // Erase mouse event and mouse doubleclick events. Keep the mouse states. 00866 ulong _mouse_state = event->e_mouse_state & 0x0F000000; 00867 00868 // establish cause of the event 00869 // if(button == 1) 00870 // _mouse_state |= NUX_EVENT_BUTTON1; 00871 // else if(button == 2) 00872 // _mouse_state |= NUX_EVENT_BUTTON2; 00873 // else if(button == 3) 00874 // _mouse_state |= NUX_EVENT_BUTTON3; 00875 // else 00876 if (button == 4) 00877 { 00878 event->e_mouse_state |= NUX_EVENT_MOUSEWHEEL; 00879 event->e_event = NUX_MOUSE_WHEEL; 00880 00881 int zDelta = GET_WHEEL_DELTA_WPARAM (wParam); 00882 int xPos = (int) (short) LOWORD (lParam) - WindowScreenPosition.x; 00883 int yPos = (int) (short) HIWORD (lParam) - WindowScreenPosition.y; 00884 event->e_x = xPos; 00885 event->e_y = yPos; 00886 00887 event->e_wheeldelta = zDelta; 00888 return 1; 00889 } 00890 00891 // set the cause of the event 00892 switch (what) 00893 { 00894 case 0: 00895 { 00896 // mouse down 00897 if (button == 1) 00898 { 00899 _mouse_state |= NUX_STATE_BUTTON1_DOWN; 00900 _mouse_state |= NUX_EVENT_BUTTON1_DOWN; 00901 } 00902 else if (button == 2) 00903 { 00904 _mouse_state |= NUX_STATE_BUTTON2_DOWN; 00905 _mouse_state |= NUX_EVENT_BUTTON2_DOWN; 00906 } 00907 else if (button == 3) 00908 { 00909 _mouse_state |= NUX_STATE_BUTTON3_DOWN; 00910 _mouse_state |= NUX_EVENT_BUTTON3_DOWN; 00911 } 00912 } 00913 break; 00914 00915 case 1: 00916 { 00917 // double click 00918 if (button == 1) 00919 { 00920 _mouse_state |= NUX_EVENT_BUTTON1_DBLCLICK; 00921 _mouse_state |= NUX_STATE_BUTTON1_DOWN; 00922 _mouse_state |= NUX_EVENT_BUTTON1_DOWN; 00923 } 00924 else if (button == 2) 00925 { 00926 _mouse_state |= NUX_EVENT_BUTTON2_DBLCLICK; 00927 _mouse_state |= NUX_STATE_BUTTON2_DOWN; 00928 _mouse_state |= NUX_EVENT_BUTTON2_DOWN; 00929 } 00930 else if (button == 3) 00931 { 00932 _mouse_state |= NUX_EVENT_BUTTON3_DBLCLICK; 00933 _mouse_state |= NUX_STATE_BUTTON3_DOWN; 00934 _mouse_state |= NUX_EVENT_BUTTON3_DOWN; 00935 } 00936 } 00937 break; 00938 00939 case 2: 00940 { 00941 // button up 00942 if (button == 1) 00943 { 00944 _mouse_state &= ~NUX_STATE_BUTTON1_DOWN; 00945 _mouse_state |= NUX_EVENT_BUTTON1_UP; 00946 } 00947 else if (button == 2) 00948 { 00949 _mouse_state &= ~NUX_STATE_BUTTON2_DOWN; 00950 _mouse_state |= NUX_EVENT_BUTTON2_UP; 00951 } 00952 else if (button == 3) 00953 { 00954 _mouse_state &= ~NUX_STATE_BUTTON3_DOWN; 00955 _mouse_state |= NUX_EVENT_BUTTON3_UP; 00956 } 00957 } 00958 break; 00959 } 00960 00961 event->e_mouse_state = _mouse_state; 00962 00963 switch (what) 00964 { 00965 case 1: // double-click 00966 00967 if (event->e_is_click) 00968 { 00969 event->e_clicks++; 00970 // The SetCapture function sets the mouse capture to the specified window belonging to 00971 // the current thread. SetCapture captures mouse input either when the mouse is over the 00972 // capturing window, or when the mouse button was pressed while the mouse was over the 00973 // capturing window and the button is still down. Only one window at a time can capture the mouse. 00974 SetCapture (window); 00975 event->e_is_click = 1; 00976 px = pmx = event->e_x; 00977 py = pmy = event->e_y; 00978 event->e_event = NUX_MOUSE_DOUBLECLICK; 00979 return 1; 00980 } 00981 00982 case 0: // single-click 00983 event->e_clicks = 0; 00984 // The SetCapture function sets the mouse capture to the specified window belonging to 00985 // the current thread. SetCapture captures mouse input either when the mouse is over the 00986 // capturing window, or when the mouse button was pressed while the mouse was over the 00987 // capturing window and the button is still down. Only one window at a time can capture the mouse. 00988 SetCapture (window); 00989 event->e_is_click = 1; 00990 px = pmx = event->e_x; 00991 py = pmy = event->e_y; 00992 event->e_event = NUX_MOUSE_PRESSED; 00993 return 1; 00994 00995 case 2: // release: 00996 // The ReleaseCapture function releases the mouse capture from a window in the current thread 00997 // and restores normal mouse input processing. A window that has captured the mouse receives all 00998 // mouse input, regardless of the position of the cursor, except when a mouse button is clicked 00999 // while the cursor hot spot is in the window of another thread. 01000 ReleaseCapture(); 01001 event->e_event = NUX_MOUSE_RELEASED; 01002 return 1; 01003 01004 case 3: // move: 01005 default: // avoid compiler warning 01006 // MSWindows produces extra events even if mouse does not move, ignore them. 01007 // http://blogs.msdn.com/oldnewthing/archive/2003/10/01/55108.aspx: Why do I get spurious WM_MOUSEMOVE messages? 01008 if (event->e_x == pmx && event->e_y == pmy) 01009 return 1; 01010 01011 pmx = event->e_x; 01012 pmy = event->e_y; 01013 // if(abs(event->e_x - px)>5 || abs(event->e_y - py)>5) 01014 // event->e_is_click = 0; 01015 event->e_event = NUX_MOUSE_MOVE; 01016 return 1; 01017 } 01018 01019 return 0; 01020 } 01021 01022 unsigned int GetModifierKeyState() 01023 { 01024 unsigned int state = 0; 01025 unsigned short r = 0; 01026 01027 // For CapsLock, we don't want to know if the key is pressed Down or Up. 01028 // We really want to know the state of the the CapsLock: on (keyboard light is on) or off? 01029 r = GetKeyState (VK_CAPITAL); 01030 01031 if (r & 1) 01032 state |= NUX_STATE_CAPS_LOCK; 01033 01034 // For NumLock, we don't want to know if the key is pressed Down or Up. 01035 // We really want to know the state of the the NumLock: on (keyboard light is on) or off? 01036 r = GetKeyState (VK_NUMLOCK); 01037 01038 if (r & 1) 01039 state |= NUX_STATE_NUMLOCK; 01040 01041 r = GetKeyState (VK_SCROLL); 01042 01043 if (r & 0x8000) 01044 state |= NUX_STATE_SCROLLLOCK; 01045 01046 r = GetKeyState (VK_CONTROL); 01047 01048 if (r & 0x8000) 01049 state |= NUX_STATE_CTRL; 01050 01051 r = GetKeyState (VK_SHIFT); 01052 01053 if (r & 0x8000) 01054 state |= NUX_STATE_SHIFT; 01055 01056 r = GetKeyState (VK_MENU); 01057 01058 if (r & 0x8000) 01059 state |= NUX_STATE_ALT; 01060 01061 01062 01063 if ( (GetKeyState (VK_LWIN) | GetKeyState (VK_RWIN) ) &~1) 01064 { 01065 // WIN32 bug? GetKeyState returns garbage if the user hit the 01066 // meta key to pop up start menu. Sigh. 01067 if ( (GetAsyncKeyState (VK_LWIN) | GetAsyncKeyState (VK_RWIN) ) &~1) 01068 state |= NUX_STATE_META; 01069 } 01070 01071 return state; 01072 } 01073 01074 //--------------------------------------------------------------------------------------------------------- 01075 void GraphicsDisplay::GetSystemEvent (Event *evt) 01076 { 01077 MSG msg; 01078 event_->Reset(); 01079 // Erase mouse event and mouse doubleclick states. Keep the mouse states. 01080 event_->e_mouse_state &= 0x0F000000; 01081 01082 // Always set the second parameter of PeekMessage to NULL. Indeed, many services creates 01083 // windows on the program behalf. If pass the main window as filter, we will miss all the 01084 // messages from the other windows. 01085 // Same with GetMessage. 01086 if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE) ) // Is There A Message Waiting? If yes, remove it. 01087 { 01088 if (msg.message == NUX_THREADMSG_START_RENDERING) 01089 { 01090 m_PauseGraphicsRendering = false; 01091 MakeGLContextCurrent (true); 01092 } 01093 01094 TranslateMessage (&msg); 01095 DispatchMessage (&msg); 01096 01097 memcpy (evt, event_, sizeof (Event) ); 01098 } 01099 else 01100 { 01101 memcpy (evt, event_, sizeof (Event) ); 01102 } 01103 01104 if (msg.message == WM_QUIT) 01105 { 01106 // Re-post the message that we retrieved so other modal loops will catch it. 01107 // See [Modality, part 3: The WM_QUIT message] http://blogs.msdn.com/oldnewthing/archive/2005/02/22/378018.aspx 01108 PostQuitMessage (msg.wParam); 01109 01110 event_->e_event = NUX_TERMINATE_APP; 01111 memcpy (evt, event_, sizeof (Event) ); 01112 } 01113 01114 if (msg.message == -1) // error 01115 { 01116 event_->e_event = NUX_NO_EVENT; 01117 memcpy (evt, event_, sizeof (Event) ); 01118 } 01119 } 01120 01121 void GraphicsDisplay::ProcessForeignWin32Event (HWND hWnd, MSG msg, WPARAM wParam, LPARAM lParam, Event *event) 01122 { 01123 event_->Reset(); 01124 // Erase mouse event and mouse doubleclick states. Keep the mouse states. 01125 event_->e_mouse_state &= 0x0F000000; 01126 01127 // Always set the second parameter of PeekMessage to NULL. Indeed, many services creates 01128 // windows on the program behalf. If pass the main window as filter, we will miss all the 01129 // messages from the other windows. 01130 // Same with GetMessage. 01131 ProcessWin32Event (hWnd, msg.message, wParam, lParam); 01132 memcpy (event, event_, sizeof (Event) ); 01133 01134 if (msg.message != WM_QUIT) 01135 { 01136 // Re-post the message that we retrieved so other modal loops will catch it. 01137 // See [Modality, part 3: The WM_QUIT message] http://blogs.msdn.com/oldnewthing/archive/2005/02/22/378018.aspx 01138 PostQuitMessage (msg.wParam); 01139 01140 event_->e_event = NUX_TERMINATE_APP; 01141 memcpy (event, event_, sizeof (Event) ); 01142 } 01143 01144 if (msg.message == -1) // error 01145 { 01146 event_->e_event = NUX_NO_EVENT; 01147 memcpy (event, event_, sizeof (Event) ); 01148 } 01149 } 01150 01151 Event &GraphicsDisplay::GetCurrentEvent() 01152 { 01153 return *event_; 01154 } 01155 01156 //--------------------------------------------------------------------------------------------------------- 01157 LRESULT CALLBACK WndProcManager (HWND hWnd, // Handle For This Window 01158 UINT uMsg, // Message For This Window 01159 WPARAM wParam, // Additional Message Information 01160 LPARAM lParam) // Additional Message Information 01161 { 01162 // This creates a warning. It is a 64-bits compatibility issue. 01163 // When not in 64-bit you can disable the warning: 01164 // Project Properties --> C/C++ tab --> General --> Select "NO" for - Detect 64-bit Portability Issues. 01165 // See also GetWindowLongPtr 01166 GraphicsDisplay *GLWindow = reinterpret_cast<GraphicsDisplay *> (::GetWindowLongPtr (hWnd, GWLP_USERDATA) ); 01167 01168 if (GLWindow == 0) 01169 { 01170 switch (uMsg) 01171 { 01172 // These cases happens before GLWindow is set. So we must catch them here. 01173 01174 case WM_NCCREATE: 01175 { 01176 // Non Client Area 01177 01178 // WARNING: MUST RETURN TRUE TO CONTINUE WITH THE CREATION OF THE WINDOW 01179 // return TRUE; 01180 01181 // WARNING: Continue with DefWindowProc if you want the title of the window to appears 01182 // or you have to set it yourself before returning true 01183 break; 01184 } 01185 case WM_CREATE: 01186 { 01187 // WARNING: MUST RETURN 0 TO CONTINUE WITH THE CREATION OF THE WINDOW 01188 return 0; 01189 } 01190 } 01191 01192 return DefWindowProc (hWnd, uMsg, wParam, lParam); 01193 } 01194 01195 return GLWindow->ProcessWin32Event (hWnd, uMsg, wParam, lParam); 01196 } 01197 01198 LRESULT GraphicsDisplay::ProcessWin32Event (HWND hWnd, // Handle For This Window 01199 UINT uMsg, // Message For This Window 01200 WPARAM wParam, // Additional Message Information 01201 LPARAM lParam) // Additional Message Information 01202 { 01203 switch (uMsg) 01204 { 01205 case WM_DESTROY: 01206 { 01207 nuxDebugMsg (TEXT ("[GraphicsDisplay::WndProc]: Window \"%s\" received WM_DESTROY message."), m_WindowTitle.GetTCharPtr() ); 01208 break; 01209 } 01210 01211 case WM_CLOSE: 01212 { 01213 nuxDebugMsg (TEXT ("[GraphicsDisplay::WndProc]: Window \"%s\" received WM_CLOSE message."), m_WindowTitle.GetTCharPtr() ); 01214 // close? yes or no? 01215 PostQuitMessage (0); 01216 return 0; 01217 } 01218 01219 case WM_PAINT: 01220 { 01221 ValidateRect (hWnd, NULL); // validate the surface to avoid receiving WM_PAINT continuously 01222 event_->e_event = NUX_WINDOW_DIRTY; 01223 break; 01224 } 01225 01226 case WM_CAPTURECHANGED: 01227 { 01228 // The WM_CAPTURECHANGED message is sent to the window that is losing the mouse capture 01229 if ((HWND) lParam == hWnd) 01230 { 01231 // Cancel everything about the mouse state and send a NUX_WINDOW_EXIT_FOCUS message. 01232 event_->e_mouse_state = 0; 01233 //nuxDebugMsg(TEXT("Windows Msg: WM_CAPTURECHANGED/NUX_WINDOW_EXIT_FOCUS")); 01234 return 0; 01235 } 01236 01237 break; 01238 } 01239 01240 case WM_ENTERSIZEMOVE: 01241 { 01242 return 0; 01243 } 01244 01245 case WM_EXITSIZEMOVE: 01246 { 01247 RECT clientrect; 01248 GetClientRect ( hWnd, &clientrect); 01249 01250 event_->e_event = NUX_SIZE_CONFIGURATION; 01251 event_->width = clientrect.right - clientrect.left; 01252 event_->height = clientrect.bottom - clientrect.top; 01253 return 0; 01254 } 01255 01256 case WM_SIZE: 01257 { 01258 RECT clientrect; 01259 GetClientRect ( hWnd, &clientrect); 01260 01261 event_->e_event = NUX_NO_EVENT; //NUX_SIZE_CONFIGURATION; 01262 event_->width = clientrect.right - clientrect.left; 01263 event_->height = clientrect.bottom - clientrect.top; 01264 01265 //setViewPort(0, 0, clientrect.right - clientrect.left, clientrect.bottom - clientrect.top); 01266 m_WindowSize.width = clientrect.right - clientrect.left; 01267 m_WindowSize.height = clientrect.bottom - clientrect.top; 01268 01269 if ((wParam == SIZE_MAXHIDE) || (wParam == SIZE_MINIMIZED)) 01270 { 01271 m_is_window_minimized = true; 01272 } 01273 else 01274 { 01275 m_is_window_minimized = false; 01276 } 01277 01278 if ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED)) 01279 { 01280 event_->e_event = NUX_SIZE_CONFIGURATION; 01281 } 01282 01283 return 0; 01284 } 01285 01286 case WM_SETFOCUS: 01287 { 01288 event_->e_event = NUX_WINDOW_ENTER_FOCUS; 01289 event_->e_mouse_state = 0; 01290 01291 // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process(). 01292 // 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 01293 // outside of all widgets. A subsequent mouse down or mouse move event will set the correct values for e_x and e_y. 01294 event_->e_x = 0xFFFFFFFF; 01295 event_->e_y = 0xFFFFFFFF; 01296 event_->e_dx = 0; 01297 event_->e_dy = 0; 01298 event_->virtual_code = 0; 01299 //nuxDebugMsg(TEXT("Windows Msg: WM_SETFOCUS/NUX_WINDOW_ENTER_FOCUS")); 01300 break; 01301 } 01302 01303 case WM_KILLFOCUS: 01304 { 01305 event_->e_event = NUX_WINDOW_EXIT_FOCUS; 01306 event_->e_mouse_state = 0; 01307 01308 // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process() 01309 event_->e_x = 0xFFFFFFFF; 01310 event_->e_y = 0xFFFFFFFF; 01311 event_->e_dx = 0; 01312 event_->e_dy = 0; 01313 event_->virtual_code = 0; 01314 //nuxDebugMsg(TEXT("Windows Msg: WM_KILLFOCUS/NUX_WINDOW_EXIT_FOCUS")); 01315 break; 01316 } 01317 01318 case WM_NCHITTEST: 01319 { 01320 break; 01321 } 01322 01323 case WM_ACTIVATE: 01324 { 01325 if (LOWORD (wParam) != WA_INACTIVE) 01326 { 01327 event_->e_event = NUX_WINDOW_ENTER_FOCUS; 01328 } 01329 else 01330 { 01331 event_->e_event = NUX_WINDOW_EXIT_FOCUS; 01332 } 01333 event_->e_mouse_state = 0; 01334 01335 // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process(). 01336 // 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 01337 // outside of all widgets. A subsequent mouse down or mouse move event will set the correct values for e_x and e_y. 01338 event_->e_x = 0xFFFFFFFF; 01339 event_->e_y = 0xFFFFFFFF; 01340 event_->e_dx = 0; 01341 event_->e_dy = 0; 01342 event_->virtual_code = 0; 01343 01344 event_->e_key_modifiers = GetModifierKeyState(); 01345 return 0; 01346 } 01347 01348 case WM_ACTIVATEAPP: 01349 { 01350 if (wParam) 01351 { 01352 event_->e_event = NUX_WINDOW_ENTER_FOCUS; 01353 } 01354 else 01355 { 01356 event_->e_event = NUX_WINDOW_EXIT_FOCUS; 01357 } 01358 event_->e_mouse_state = 0; 01359 01360 // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process(). 01361 // 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 01362 // outside of all widgets. A subsequent mouse down or mouse move event will set the correct values for e_x and e_y. 01363 event_->e_x = 0xFFFFFFFF; 01364 event_->e_y = 0xFFFFFFFF; 01365 event_->e_dx = 0; 01366 event_->e_dy = 0; 01367 event_->virtual_code = 0; 01368 01369 event_->e_key_modifiers = GetModifierKeyState(); 01370 return 0; 01371 } 01372 01373 case WM_SYSKEYDOWN: 01374 case WM_KEYDOWN: 01375 { 01376 event_->e_event = NUX_KEYDOWN; 01377 event_->e_key_modifiers = GetModifierKeyState(); 01378 event_->e_keysym = wParam; 01379 01380 if ( (uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN) ) 01381 { 01382 event_->VirtualKeycodeState[GraphicsDisplay::Win32KeySymToINL (wParam) ] = 1; 01383 } 01384 01385 if (wParam == VK_CONTROL) 01386 { 01387 if (lParam & (1 << 24) ) 01388 { 01389 event_->e_keysym = NUX_VK_RCONTROL; 01390 } 01391 else 01392 { 01393 event_->e_keysym = NUX_VK_LCONTROL; 01394 } 01395 } 01396 01397 if (wParam == VK_MENU) 01398 { 01399 if (lParam & (1 << 24) ) 01400 { 01401 event_->e_keysym = NUX_VK_RALT; 01402 } 01403 else 01404 { 01405 event_->e_keysym = NUX_VK_LALT; 01406 } 01407 } 01408 01409 if (wParam == VK_SHIFT) 01410 { 01411 if (HIWORD (GetAsyncKeyState (VK_LSHIFT) ) ) 01412 { 01413 event_->e_keysym = NUX_VK_LSHIFT; 01414 } 01415 else if (HIWORD (GetAsyncKeyState (VK_RSHIFT) ) ) 01416 { 01417 event_->e_keysym = NUX_VK_RSHIFT; 01418 } 01419 } 01420 01421 break; 01422 } 01423 01424 case WM_SYSKEYUP: 01425 case WM_KEYUP: 01426 { 01427 event_->e_event = NUX_KEYUP; 01428 event_->e_key_modifiers = GetModifierKeyState(); 01429 event_->e_keysym = wParam; 01430 01431 if ( (uMsg == WM_KEYUP) || (uMsg == WM_SYSKEYUP) ) 01432 { 01433 event_->VirtualKeycodeState[GraphicsDisplay::Win32KeySymToINL (wParam) ] = 0; 01434 } 01435 01436 break; 01437 } 01438 01439 case WM_DEADCHAR: 01440 case WM_SYSDEADCHAR: 01441 case WM_CHAR: 01442 case WM_SYSCHAR: 01443 { 01444 event_->e_key_modifiers = GetModifierKeyState(); 01445 01446 // reset key repeat count to 0. 01447 event_->e_key_repeat_count = 0; 01448 01449 if (lParam & (1 << 31) ) 01450 { 01451 // key up events. 01452 event_->e_event = NUX_KEYUP; 01453 return 0; 01454 } 01455 else 01456 { 01457 // key down events. 01458 event_->e_event = NUX_KEYDOWN; 01459 event_->e_key_repeat_count = (int) (lParam & 0xff); 01460 } 01461 01462 01463 if ((wParam == '\b') || // backspace 01464 (wParam == '\t') || // tab 01465 (wParam == '\n') || // linefeed 01466 (wParam == '\r')) // carriage return 01467 { 01468 return 0; 01469 } 01470 01471 t_UTF16 *utf16_str = new t_UTF16 [4]; 01472 Memset (utf16_str, 0, sizeof (t_UTF16) * 4); 01473 Memcpy (utf16_str, (int*) &wParam, sizeof (wParam)); 01474 t_UTF16 *temp0 = utf16_str; 01475 01476 t_UTF8 *utf8_str = new t_UTF8 [NUX_EVENT_TEXT_BUFFER_SIZE]; 01477 Memset (utf8_str, 0, sizeof (t_UTF8) * NUX_EVENT_TEXT_BUFFER_SIZE); 01478 t_UTF8 *temp1 = utf8_str; 01479 01480 01481 ConversionResult res = ConvertUTF16toUTF8 ((const nux::t_UTF16 **) &temp0, 01482 utf16_str + sizeof (t_UTF16) * 4, 01483 &temp1, 01484 utf8_str + NUX_EVENT_TEXT_BUFFER_SIZE, 01485 lenientConversion); 01486 01487 if (res == conversionOK) 01488 { 01489 Memcpy (event_->e_text, utf8_str, NUX_EVENT_TEXT_BUFFER_SIZE); 01490 } 01491 delete utf8_str; 01492 delete utf16_str; 01493 01494 return 0; 01495 } 01496 01497 case WM_UNICHAR: 01498 { 01499 if (wParam == UNICODE_NOCHAR) 01500 return 1; 01501 01502 event_->e_key_modifiers = GetModifierKeyState(); 01503 01504 // reset key repeat count to 0. 01505 event_->e_key_repeat_count = 0; 01506 01507 if (lParam & (1 << 31) ) 01508 { 01509 // key up events. 01510 event_->e_event = NUX_KEYUP; 01511 return 0; 01512 } 01513 else 01514 { 01515 // key down events. 01516 event_->e_event = NUX_KEYDOWN; 01517 event_->e_key_repeat_count = (int) (lParam & 0xff); 01518 } 01519 01520 t_UTF32 *utf32_str = new t_UTF32 [4]; 01521 Memset (utf32_str, 0, sizeof (t_UTF32) * 4); 01522 Memcpy (utf32_str, (int*) &wParam, sizeof (wParam)); 01523 t_UTF32 *temp0 = utf32_str; 01524 01525 t_UTF8 *utf8_str = new t_UTF8 [NUX_EVENT_TEXT_BUFFER_SIZE]; 01526 Memset (utf8_str, 0, sizeof (t_UTF8) * NUX_EVENT_TEXT_BUFFER_SIZE); 01527 t_UTF8 *temp1 = utf8_str; 01528 01529 01530 ConversionResult res = ConvertUTF32toUTF8 ((const nux::t_UTF32 **) &temp0, 01531 utf32_str + sizeof (t_UTF32) * 4, 01532 &temp1, 01533 utf8_str + NUX_EVENT_TEXT_BUFFER_SIZE, 01534 lenientConversion); 01535 01536 if (res == conversionOK) 01537 { 01538 Memcpy (event_->e_text, utf8_str, NUX_EVENT_TEXT_BUFFER_SIZE); 01539 } 01540 delete utf8_str; 01541 delete utf32_str; 01542 } 01543 01544 case WM_LBUTTONDOWN: 01545 { 01546 mouse_event (hWnd, event_, 0, 1, wParam, lParam); 01547 //nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONDOWN")); 01548 return 0; 01549 } 01550 case WM_LBUTTONDBLCLK: 01551 { 01552 mouse_event (hWnd, event_, 1, 1, wParam, lParam); 01553 //nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONDBLCLK")); 01554 return 0; 01555 } 01556 case WM_LBUTTONUP: 01557 { 01558 mouse_event (hWnd, event_, 2, 1, wParam, lParam); 01559 //nuxDebugMsg(TEXT("Windows Msg: WM_LBUTTONUP")); 01560 return 0; 01561 } 01562 case WM_MBUTTONDOWN: 01563 { 01564 mouse_event (hWnd, event_, 0, 2, wParam, lParam); 01565 break; 01566 } 01567 case WM_MBUTTONDBLCLK: 01568 { 01569 mouse_event (hWnd, event_, 1, 2, wParam, lParam); 01570 break; 01571 } 01572 case WM_MBUTTONUP: 01573 { 01574 mouse_event (hWnd, event_, 2, 2, wParam, lParam); 01575 break; 01576 } 01577 case WM_RBUTTONDOWN: 01578 { 01579 mouse_event (hWnd, event_, 0, 3, wParam, lParam); 01580 break; 01581 } 01582 case WM_RBUTTONDBLCLK: 01583 { 01584 mouse_event (hWnd, event_, 1, 3, wParam, lParam); 01585 break; 01586 } 01587 case WM_RBUTTONUP: 01588 { 01589 mouse_event (hWnd, event_, 2, 3, wParam, lParam); 01590 break; 01591 } 01592 case WM_MOUSEWHEEL: 01593 { 01594 mouse_event (hWnd, event_, 0, 4, wParam, lParam); 01595 break; 01596 } 01597 01598 case WM_NCLBUTTONDBLCLK: 01599 { 01600 event_->e_event = NUX_WINDOW_CONFIGURATION; 01601 break; 01602 } 01603 case WM_NCLBUTTONDOWN: 01604 { 01605 event_->e_event = NUX_WINDOW_CONFIGURATION; 01606 break; 01607 } 01608 case WM_NCLBUTTONUP: 01609 { 01610 event_->e_event = NUX_WINDOW_CONFIGURATION; 01611 break; 01612 } 01613 case WM_NCMBUTTONDBLCLK: 01614 { 01615 event_->e_event = NUX_WINDOW_CONFIGURATION; 01616 break; 01617 } 01618 case WM_NCMBUTTONDOWN: 01619 { 01620 event_->e_event = NUX_WINDOW_CONFIGURATION; 01621 break; 01622 } 01623 case WM_NCMBUTTONUP: 01624 { 01625 event_->e_event = NUX_WINDOW_CONFIGURATION; 01626 break; 01627 } 01628 case WM_NCRBUTTONDBLCLK: 01629 { 01630 event_->e_event = NUX_WINDOW_CONFIGURATION; 01631 break; 01632 } 01633 case WM_NCRBUTTONDOWN: 01634 { 01635 event_->e_event = NUX_WINDOW_CONFIGURATION; 01636 break; 01637 } 01638 case WM_NCRBUTTONUP: 01639 { 01640 event_->e_event = NUX_WINDOW_CONFIGURATION; 01641 break; 01642 } 01643 01644 case WM_MOUSEMOVE: 01645 { 01646 mouse_event (hWnd, event_, 3, 0, wParam, lParam); 01647 //nuxDebugMsg(TEXT("Windows Msg: WM_MOUSEMOVE")); 01648 01649 TRACKMOUSEEVENT tme = { sizeof (tme) }; 01650 // Enable NUX_WINDOW_MOUSELEAVE event. 01651 tme.dwFlags = TME_LEAVE; 01652 tme.hwndTrack = hWnd; 01653 TrackMouseEvent (&tme); 01654 break; 01655 } 01656 01657 // Note: there is no WM_MOUSEENTER. WM_MOUSEENTER is equivalent to WM_MOUSEMOVE after a WM_MOUSELEAVE. 01658 case WM_MOUSELEAVE: 01659 { 01660 // All tracking requested by TrackMouseEvent is canceled when this message is generated. 01661 // The application must call TrackMouseEvent when the mouse reenters its window if 01662 // it requires further tracking of mouse hover behavior. 01663 event_->e_event = NUX_WINDOW_MOUSELEAVE; 01664 // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process() 01665 event_->e_x = 0xFFFFFFFF; 01666 event_->e_y = 0xFFFFFFFF; 01667 //nuxDebugMsg(TEXT("Windows Msg: WM_MOUSELEAVE/NUX_WINDOW_MOUSELEAVE")); 01668 break; 01669 } 01670 01671 case WM_SETCURSOR: 01672 01673 if ( (LOWORD (lParam) == HTCLIENT) && m_Cursor) 01674 { 01675 SetCursor (m_Cursor); 01676 return TRUE; //return FALSE; 01677 } 01678 else 01679 break; 01680 01681 case WM_COMMAND: 01682 { 01683 nuxDebugMsg (TEXT ("[GraphicsDisplay::WndProc]: Window \"%s\" received WM_COMMAND message."), m_WindowTitle.GetTCharPtr() ); 01684 break;; 01685 } 01686 01687 case WM_SYSCOMMAND: // Intercept System Commands 01688 { 01689 switch (wParam) // Check System Calls 01690 { 01691 case SC_CLOSE: 01692 break; 01693 case SC_CONTEXTHELP: 01694 break; 01695 case SC_DEFAULT: 01696 break; 01697 case SC_HOTKEY: 01698 break; 01699 case SC_HSCROLL: 01700 break; 01701 case SC_KEYMENU: 01702 break; 01703 case SC_MAXIMIZE: 01704 break; 01705 case SC_MINIMIZE: 01706 break; 01707 case SC_MONITORPOWER: 01708 break; 01709 case SC_MOUSEMENU: 01710 break; 01711 case SC_MOVE: 01712 break; 01713 case SC_NEXTWINDOW: 01714 break; 01715 case SC_PREVWINDOW: 01716 break; 01717 case SC_RESTORE: 01718 break; 01719 case SC_SCREENSAVE: 01720 break; 01721 case SC_SIZE: 01722 break; 01723 case SC_TASKLIST: 01724 break; 01725 case SC_VSCROLL: 01726 break; 01727 } 01728 01729 break; // Exit 01730 } 01731 } 01732 01733 return DefWindowProc (hWnd, uMsg, wParam, lParam); 01734 } 01735 01736 int GraphicsDisplay::Win32VKToNuxKey (int vk) 01737 { 01738 switch (vk) 01739 { 01740 case VK_CANCEL: 01741 return NUX_VK_CANCEL; 01742 case VK_BACK: 01743 return NUX_VK_BACKSPACE; 01744 case VK_TAB: 01745 return NUX_VK_TAB; 01746 case VK_CLEAR: 01747 return NUX_VK_CLEAR; 01748 case VK_RETURN: 01749 return NUX_VK_ENTER; 01750 case VK_SHIFT: 01751 return NUX_VK_SHIFT; 01752 01753 case VK_CONTROL: 01754 return NUX_VK_LCONTROL; 01755 case VK_LCONTROL: 01756 return NUX_VK_LCONTROL; 01757 case VK_RCONTROL: 01758 return NUX_VK_RCONTROL; 01759 01760 case VK_MENU: 01761 return NUX_VK_LALT; 01762 case VK_LMENU: 01763 return NUX_VK_LALT; 01764 case VK_RMENU: 01765 return NUX_VK_RALT; 01766 01767 case VK_PAUSE: 01768 return NUX_VK_PAUSE; 01769 case VK_CAPITAL: 01770 return NUX_VK_CAPITAL; 01771 case VK_ESCAPE: 01772 return NUX_VK_ESCAPE; 01773 01774 case VK_PRIOR: 01775 return NUX_VK_PAGE_UP; 01776 case VK_NEXT: 01777 return NUX_VK_PAGE_DOWN; 01778 case VK_END: 01779 return NUX_VK_END; 01780 case VK_HOME: 01781 return NUX_VK_HOME; 01782 case VK_LEFT: 01783 return NUX_VK_LEFT; 01784 case VK_UP: 01785 return NUX_VK_UP; 01786 case VK_RIGHT: 01787 return NUX_VK_RIGHT; 01788 case VK_DOWN: 01789 return NUX_VK_DOWN; 01790 01791 case VK_INSERT: 01792 return NUX_VK_INSERT; 01793 case VK_DELETE: 01794 return NUX_VK_DELETE; 01795 01796 case 0x30: 01797 return NUX_VK_0; 01798 case 0x31: 01799 return NUX_VK_1; 01800 case 0x32: 01801 return NUX_VK_2; 01802 case 0x33: 01803 return NUX_VK_3; 01804 case 0x34: 01805 return NUX_VK_4; 01806 case 0x35: 01807 return NUX_VK_5; 01808 case 0x36: 01809 return NUX_VK_6; 01810 case 0x37: 01811 return NUX_VK_7; 01812 case 0x38: 01813 return NUX_VK_8; 01814 case 0x39: 01815 return NUX_VK_9; 01816 case 0x41: 01817 return NUX_VK_A; 01818 case 0x42: 01819 return NUX_VK_B; 01820 case 0x43: 01821 return NUX_VK_C; 01822 case 0x44: 01823 return NUX_VK_D; 01824 case 0x45: 01825 return NUX_VK_E; 01826 case 0x46: 01827 return NUX_VK_F; 01828 case 0x47: 01829 return NUX_VK_G; 01830 case 0x48: 01831 return NUX_VK_H; 01832 case 0x49: 01833 return NUX_VK_I; 01834 case 0x4A: 01835 return NUX_VK_J; 01836 case 0x4B: 01837 return NUX_VK_K; 01838 case 0x4C: 01839 return NUX_VK_L; 01840 case 0x4D: 01841 return NUX_VK_M; 01842 case 0x4E: 01843 return NUX_VK_N; 01844 case 0x4F: 01845 return NUX_VK_O; 01846 case 0x50: 01847 return NUX_VK_P; 01848 case 0x51: 01849 return NUX_VK_Q; 01850 case 0x52: 01851 return NUX_VK_R; 01852 case 0x53: 01853 return NUX_VK_S; 01854 case 0x54: 01855 return NUX_VK_T; 01856 case 0x55: 01857 return NUX_VK_U; 01858 case 0x56: 01859 return NUX_VK_V; 01860 case 0x57: 01861 return NUX_VK_W; 01862 case 0x58: 01863 return NUX_VK_X; 01864 case 0x59: 01865 return NUX_VK_Y; 01866 case 0x5A: 01867 return NUX_VK_Z; 01868 01869 case VK_LWIN: 01870 return NUX_VK_LSUPER; // Windows key left 01871 case VK_RWIN: 01872 return NUX_VK_RSUPER; // Windows key right 01873 01874 case VK_NUMLOCK: 01875 return NUX_VK_NUMLOCK; 01876 case VK_SCROLL: 01877 return NUX_VK_SCROLL; 01878 case VK_LSHIFT: 01879 return NUX_VK_LSHIFT; 01880 case VK_RSHIFT: 01881 return NUX_VK_RSHIFT; 01882 01883 case VK_NUMPAD0: 01884 return NUX_KP_0; 01885 case VK_NUMPAD1: 01886 return NUX_KP_1; 01887 case VK_NUMPAD2: 01888 return NUX_KP_2; 01889 case VK_NUMPAD3: 01890 return NUX_KP_3; 01891 case VK_NUMPAD4: 01892 return NUX_KP_4; 01893 case VK_NUMPAD5: 01894 return NUX_KP_5; 01895 case VK_NUMPAD6: 01896 return NUX_KP_6; 01897 case VK_NUMPAD7: 01898 return NUX_KP_7; 01899 case VK_NUMPAD8: 01900 return NUX_KP_8; 01901 case VK_NUMPAD9: 01902 return NUX_KP_9; 01903 01904 case VK_MULTIPLY: 01905 return NUX_KP_MULTIPLY; 01906 case VK_ADD: 01907 return NUX_KP_ADD; 01908 case VK_SEPARATOR: 01909 return NUX_KP_SEPARATOR; 01910 case VK_SUBTRACT: 01911 return NUX_VK_SUBTRACT; 01912 case VK_DECIMAL: 01913 return NUX_VK_DECIMAL; 01914 case VK_DIVIDE: 01915 return NUX_VK_SLASH; 01916 01917 case VK_F1: 01918 return NUX_VK_F1; 01919 case VK_F2: 01920 return NUX_VK_F2; 01921 case VK_F3: 01922 return NUX_VK_F3; 01923 case VK_F4: 01924 return NUX_VK_F4; 01925 case VK_F5: 01926 return NUX_VK_F5; 01927 case VK_F6: 01928 return NUX_VK_F6; 01929 case VK_F7: 01930 return NUX_VK_F7; 01931 case VK_F8: 01932 return NUX_VK_F8; 01933 case VK_F9: 01934 return NUX_VK_F9; 01935 case VK_F10: 01936 return NUX_VK_F10; 01937 case VK_F11: 01938 return NUX_VK_F11; 01939 case VK_F12: 01940 return NUX_VK_F12; 01941 case VK_F13: 01942 return NUX_VK_F13; 01943 case VK_F14: 01944 return NUX_VK_F14; 01945 case VK_F15: 01946 return NUX_VK_F15; 01947 case VK_F16: 01948 return NUX_VK_F16; 01949 case VK_F17: 01950 return NUX_VK_F17; 01951 case VK_F18: 01952 return NUX_VK_F18; 01953 case VK_F19: 01954 return NUX_VK_F19; 01955 case VK_F20: 01956 return NUX_VK_F20; 01957 case VK_F21: 01958 return NUX_VK_F21; 01959 case VK_F22: 01960 return NUX_VK_F22; 01961 case VK_F23: 01962 return NUX_VK_F23; 01963 case VK_F24: 01964 return NUX_VK_F24; 01965 01966 default: 01967 return 0x0; 01968 } 01969 } 01970 01971 int GraphicsDisplay::Win32KeySymToINL (int Keysym) 01972 { 01973 return Keysym; 01974 01975 // switch (Keysym) 01976 // { 01977 // case VK_CANCEL: 01978 // return NUX_VK_CANCEL; 01979 // case VK_BACK: 01980 // return NUX_VK_BACKSPACE; 01981 // case VK_TAB: 01982 // return NUX_VK_TAB; 01983 // case VK_CLEAR: 01984 // return NUX_VK_CLEAR; 01985 // case VK_RETURN: 01986 // return NUX_VK_ENTER; 01987 // case VK_SHIFT: 01988 // return NUX_VK_SHIFT; 01989 // case VK_CONTROL: 01990 // return NUX_VK_CONTROL; 01991 // case VK_MENU: 01992 // return NUX_VK_MENU; // ALT key 01993 // case VK_PAUSE: 01994 // return NUX_VK_PAUSE; 01995 // case VK_CAPITAL: 01996 // return NUX_VK_CAPITAL; 01997 // case VK_ESCAPE: 01998 // return NUX_VK_ESCAPE; 01999 // case VK_SPACE: 02000 // return NUX_VK_SPACE; 02001 // case VK_PRIOR: 02002 // return NUX_VK_PAGE_UP; 02003 // case VK_NEXT: 02004 // return NUX_VK_PAGE_DOWN; 02005 // case VK_END: 02006 // return NUX_VK_END; 02007 // case VK_HOME: 02008 // return NUX_VK_HOME; 02009 // case VK_LEFT: 02010 // return NUX_VK_LEFT; 02011 // case VK_UP: 02012 // return NUX_VK_UP; 02013 // case VK_RIGHT: 02014 // return NUX_VK_RIGHT; 02015 // case VK_DOWN: 02016 // return NUX_VK_DOWN; 02017 // case VK_SELECT: 02018 // return NUX_VK_SELECT; 02019 // case VK_PRINT: 02020 // return NUX_VK_PRINT; 02021 // case VK_EXECUTE: 02022 // return NUX_VK_EXECUTE; 02023 // case VK_INSERT: 02024 // return NUX_VK_INSERT; 02025 // case VK_DELETE: 02026 // return NUX_VK_DELETE; 02027 // case VK_HELP: 02028 // return NUX_VK_HELP; 02029 // case 0x30: 02030 // return NUX_VK_0; 02031 // case 0x31: 02032 // return NUX_VK_1; 02033 // case 0x32: 02034 // return NUX_VK_2; 02035 // case 0x33: 02036 // return NUX_VK_3; 02037 // case 0x34: 02038 // return NUX_VK_4; 02039 // case 0x35: 02040 // return NUX_VK_5; 02041 // case 0x36: 02042 // return NUX_VK_6; 02043 // case 0x37: 02044 // return NUX_VK_7; 02045 // case 0x38: 02046 // return NUX_VK_8; 02047 // case 0x39: 02048 // return NUX_VK_9; 02049 // case 0x41: 02050 // return NUX_VK_A; 02051 // case 0x42: 02052 // return NUX_VK_B; 02053 // case 0x43: 02054 // return NUX_VK_C; 02055 // case 0x44: 02056 // return NUX_VK_D; 02057 // case 0x45: 02058 // return NUX_VK_E; 02059 // case 0x46: 02060 // return NUX_VK_F; 02061 // case 0x47: 02062 // return NUX_VK_G; 02063 // case 0x48: 02064 // return NUX_VK_H; 02065 // case 0x49: 02066 // return NUX_VK_I; 02067 // case 0x4A: 02068 // return NUX_VK_J; 02069 // case 0x4B: 02070 // return NUX_VK_K; 02071 // case 0x4C: 02072 // return NUX_VK_L; 02073 // case 0x4D: 02074 // return NUX_VK_M; 02075 // case 0x4E: 02076 // return NUX_VK_N; 02077 // case 0x4F: 02078 // return NUX_VK_O; 02079 // case 0x50: 02080 // return NUX_VK_P; 02081 // case 0x51: 02082 // return NUX_VK_Q; 02083 // case 0x52: 02084 // return NUX_VK_R; 02085 // case 0x53: 02086 // return NUX_VK_S; 02087 // case 0x54: 02088 // return NUX_VK_T; 02089 // case 0x55: 02090 // return NUX_VK_U; 02091 // case 0x56: 02092 // return NUX_VK_V; 02093 // case 0x57: 02094 // return NUX_VK_W; 02095 // case 0x58: 02096 // return NUX_VK_X; 02097 // case 0x59: 02098 // return NUX_VK_Y; 02099 // case 0x5A: 02100 // return NUX_VK_Z; 02101 // case VK_LWIN: 02102 // return NUX_VK_LWIN; // Windows key left 02103 // case VK_RWIN: 02104 // return NUX_VK_RWIN; // Windows key right 02105 // case VK_NUMPAD0: 02106 // return NUX_VK_NUMPAD0; 02107 // case VK_NUMPAD1: 02108 // return NUX_VK_NUMPAD1; 02109 // case VK_NUMPAD2: 02110 // return NUX_VK_NUMPAD2; 02111 // case VK_NUMPAD3: 02112 // return NUX_VK_NUMPAD3; 02113 // case VK_NUMPAD4: 02114 // return NUX_VK_NUMPAD4; 02115 // case VK_NUMPAD5: 02116 // return NUX_VK_NUMPAD5; 02117 // case VK_NUMPAD6: 02118 // return NUX_VK_NUMPAD6; 02119 // case VK_NUMPAD7: 02120 // return NUX_VK_NUMPAD7; 02121 // case VK_NUMPAD8: 02122 // return NUX_VK_NUMPAD8; 02123 // case VK_NUMPAD9: 02124 // return NUX_VK_NUMPAD9; 02125 // case VK_MULTIPLY: 02126 // return NUX_VK_MULTIPLY; 02127 // case VK_ADD: 02128 // return NUX_VK_ADD; 02129 // case VK_SEPARATOR: 02130 // return NUX_VK_SEPARATOR; 02131 // case VK_SUBTRACT: 02132 // return NUX_VK_SUBTRACT; 02133 // case VK_DECIMAL: 02134 // return NUX_VK_DECIMAL; 02135 // case VK_DIVIDE: 02136 // return NUX_VK_DIVIDE; 02137 // case VK_F1: 02138 // return NUX_VK_F1; 02139 // case VK_F2: 02140 // return NUX_VK_F2; 02141 // case VK_F3: 02142 // return NUX_VK_F3; 02143 // case VK_F4: 02144 // return NUX_VK_F4; 02145 // case VK_F5: 02146 // return NUX_VK_F5; 02147 // case VK_F6: 02148 // return NUX_VK_F6; 02149 // case VK_F7: 02150 // return NUX_VK_F7; 02151 // case VK_F8: 02152 // return NUX_VK_F8; 02153 // case VK_F9: 02154 // return NUX_VK_F9; 02155 // case VK_F10: 02156 // return NUX_VK_F10; 02157 // case VK_F11: 02158 // return NUX_VK_F11; 02159 // case VK_F12: 02160 // return NUX_VK_F12; 02161 // case VK_F13: 02162 // return NUX_VK_F13; 02163 // case VK_F14: 02164 // return NUX_VK_F14; 02165 // case VK_F15: 02166 // return NUX_VK_F15; 02167 // case VK_F16: 02168 // return NUX_VK_F16; 02169 // case VK_F17: 02170 // return NUX_VK_F17; 02171 // case VK_F18: 02172 // return NUX_VK_F18; 02173 // case VK_F19: 02174 // return NUX_VK_F19; 02175 // case VK_F20: 02176 // return NUX_VK_F20; 02177 // case VK_F21: 02178 // return NUX_VK_F21; 02179 // case VK_F22: 02180 // return NUX_VK_F22; 02181 // case VK_F23: 02182 // return NUX_VK_F23; 02183 // case VK_F24: 02184 // return NUX_VK_F24; 02185 // case VK_NUMLOCK: 02186 // return NUX_VK_NUMLOCK; 02187 // case VK_SCROLL: 02188 // return NUX_VK_SCROLL; 02189 // case VK_LSHIFT: 02190 // return NUX_VK_LSHIFT; 02191 // case VK_RSHIFT: 02192 // return NUX_VK_RSHIFT; 02193 // case VK_LCONTROL: 02194 // return NUX_VK_LCONTROL; 02195 // case VK_RCONTROL: 02196 // return NUX_VK_RCONTROL; 02197 // case VK_LMENU: 02198 // return NUX_VK_LMENU; 02199 // case VK_RMENU: 02200 // return NUX_VK_RMENU; 02201 // default: 02202 // return 0x0; 02203 // } 02204 } 02205 02206 void GraphicsDisplay::InitGlobalGrabWindow () 02207 { 02208 02209 } 02210 02211 bool GraphicsDisplay::GrabPointer (GrabReleaseCallback callback, void *data, bool replace_existing) 02212 { 02213 return false; 02214 } 02215 02216 bool GraphicsDisplay::UngrabPointer (void *data) 02217 { 02218 return true; 02219 } 02220 02221 bool GraphicsDisplay::PointerIsGrabbed () 02222 { 02223 return false; 02224 } 02225 02226 bool GraphicsDisplay::GrabKeyboard (GrabReleaseCallback callback, void *data, bool replace_existing) 02227 { 02228 return _global_keyboard_grab_active; 02229 } 02230 02231 bool GraphicsDisplay::UngrabKeyboard (void *data) 02232 { 02233 return true; 02234 } 02235 02236 bool GraphicsDisplay::KeyboardIsGrabbed () 02237 { 02238 return _global_keyboard_grab_active; 02239 } 02240 02241 //--------------------------------------------------------------------------------------------------------- 02242 void GraphicsDisplay::GetDisplayInfo() 02243 { 02244 DEVMODE devmode; 02245 INT iMode = 0; 02246 BOOL bRetVal; 02247 DeviceModes dm; 02248 m_num_gfx_device_modes = 0; 02249 02250 do 02251 { 02252 bRetVal = ::EnumDisplaySettings (NULL, iMode, &devmode); 02253 iMode++; 02254 02255 if (bRetVal) 02256 { 02257 dm.width = devmode.dmPelsWidth; 02258 dm.height = devmode.dmPelsHeight; 02259 dm.format = devmode.dmBitsPerPel; 02260 dm.refresh_rate = devmode.dmDisplayFrequency; 02261 m_gfx_device_modes.push_back (dm); 02262 m_num_gfx_device_modes++; 02263 } 02264 } 02265 while (bRetVal); 02266 } 02267 02268 //--------------------------------------------------------------------------------------------------------- 02269 void GraphicsDisplay::ShowWindow() 02270 { 02271 ::ShowWindow (m_hWnd, SW_SHOW); 02272 } 02273 02274 //--------------------------------------------------------------------------------------------------------- 02275 void GraphicsDisplay::HideWindow() 02276 { 02277 ::ShowWindow (m_hWnd, SW_HIDE); 02278 } 02279 02280 bool GraphicsDisplay::IsWindowVisible () 02281 { 02282 return (::IsWindowVisible (m_hWnd) ? true : false); 02283 } 02284 //--------------------------------------------------------------------------------------------------------- 02285 void GraphicsDisplay::EnterMaximizeWindow() 02286 { 02287 ::ShowWindow (m_hWnd, SW_MAXIMIZE); 02288 } 02289 02290 //--------------------------------------------------------------------------------------------------------- 02291 void GraphicsDisplay::ExitMaximizeWindow() 02292 { 02293 ::ShowWindow (m_hWnd, SW_RESTORE); 02294 } 02295 02296 //--------------------------------------------------------------------------------------------------------- 02297 void GraphicsDisplay::SetWindowTitle (const TCHAR *Title) 02298 { 02299 SetWindowText (m_hWnd, Title); 02300 } 02301 02302 //--------------------------------------------------------------------------------------------------------- 02303 // NUXTODO: remove this call. Make a direct access to GpuInfo via GpuDevice. 02304 bool GraphicsDisplay::HasVSyncSwapControl() const 02305 { 02306 return GetGpuDevice()->GetGpuInfo().Support_EXT_Swap_Control(); 02307 } 02308 02309 //--------------------------------------------------------------------------------------------------------- 02310 void GraphicsDisplay::EnableVSyncSwapControl() 02311 { 02312 if (HasVSyncSwapControl() ) 02313 { 02314 wglSwapIntervalEXT (1); 02315 } 02316 } 02317 02318 //--------------------------------------------------------------------------------------------------------- 02319 void GraphicsDisplay::DisableVSyncSwapControl() 02320 { 02321 if (HasVSyncSwapControl() ) 02322 { 02323 wglSwapIntervalEXT (0); 02324 } 02325 } 02326 02327 float GraphicsDisplay::GetFrameTime() const 02328 { 02329 return m_FrameTime; 02330 } 02331 02332 void GraphicsDisplay::ResetFrameTime() 02333 { 02334 m_Timer.Reset(); 02335 } 02336 02337 bool GraphicsDisplay::StartOpenFileDialog (FileDialogOption &fdo) 02338 { 02339 return Win32OpenFileDialog (GetWindowHandle(), fdo); 02340 } 02341 02342 bool GraphicsDisplay::StartSaveFileDialog (FileDialogOption &fdo) 02343 { 02344 return Win32SaveFileDialog (GetWindowHandle(), fdo); 02345 } 02346 02347 bool GraphicsDisplay::StartColorDialog (ColorDialogOption &cdo) 02348 { 02349 return Win32ColorDialog (GetWindowHandle(), cdo); 02350 } 02351 02352 //--------------------------------------------------------------------------------------------------------- 02353 void GraphicsDisplay::SetWindowCursor (HCURSOR cursor) 02354 { 02355 m_Cursor = cursor; 02356 } 02357 02358 //--------------------------------------------------------------------------------------------------------- 02359 HCURSOR GraphicsDisplay::GetWindowCursor() const 02360 { 02361 return m_Cursor; 02362 } 02363 02364 //--------------------------------------------------------------------------------------------------------- 02365 void GraphicsDisplay::PauseThreadGraphicsRendering() 02366 { 02367 m_PauseGraphicsRendering = true; 02368 MakeGLContextCurrent (false); 02369 } 02370 02371 //--------------------------------------------------------------------------------------------------------- 02372 bool GraphicsDisplay::IsPauseThreadGraphicsRendering() const 02373 { 02374 return m_PauseGraphicsRendering; 02375 } 02376 02377 }