Back to index

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