win32_window.c
Go to the documentation of this file.
00001 //========================================================================
00002 // GLFW 3.1 Win32 - www.glfw.org
00003 //------------------------------------------------------------------------
00004 // Copyright (c) 2002-2006 Marcus Geelnard
00005 // Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
00006 //
00007 // This software is provided 'as-is', without any express or implied
00008 // warranty. In no event will the authors be held liable for any damages
00009 // arising from the use of this software.
00010 //
00011 // Permission is granted to anyone to use this software for any purpose,
00012 // including commercial applications, and to alter it and redistribute it
00013 // freely, subject to the following restrictions:
00014 //
00015 // 1. The origin of this software must not be misrepresented; you must not
00016 //    claim that you wrote the original software. If you use this software
00017 //    in a product, an acknowledgment in the product documentation would
00018 //    be appreciated but is not required.
00019 //
00020 // 2. Altered source versions must be plainly marked as such, and must not
00021 //    be misrepresented as being the original software.
00022 //
00023 // 3. This notice may not be removed or altered from any source
00024 //    distribution.
00025 //
00026 //========================================================================
00027 
00028 #include "internal.h"
00029 
00030 #include <stdlib.h>
00031 #include <malloc.h>
00032 #include <string.h>
00033 #include <windowsx.h>
00034 #include <shellapi.h>
00035 
00036 #define _GLFW_KEY_INVALID -2
00037 
00038 #define _GLFW_WNDCLASSNAME L"GLFW30"
00039 
00040 
00041 // Returns the window style for the specified window
00042 //
00043 static DWORD getWindowStyle(const _GLFWwindow* window)
00044 {
00045     DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
00046 
00047     if (window->decorated && !window->monitor)
00048     {
00049         style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
00050 
00051         if (window->resizable)
00052             style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
00053     }
00054     else
00055         style |= WS_POPUP;
00056 
00057     return style;
00058 }
00059 
00060 // Returns the extended window style for the specified window
00061 //
00062 static DWORD getWindowExStyle(const _GLFWwindow* window)
00063 {
00064     DWORD style = WS_EX_APPWINDOW;
00065 
00066     if (window->decorated && !window->monitor)
00067         style |= WS_EX_WINDOWEDGE;
00068 
00069     return style;
00070 }
00071 
00072 // Updates the cursor clip rect
00073 //
00074 static void updateClipRect(_GLFWwindow* window)
00075 {
00076     RECT clipRect;
00077     GetClientRect(window->win32.handle, &clipRect);
00078     ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
00079     ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
00080     ClipCursor(&clipRect);
00081 }
00082 
00083 // Hide the mouse cursor
00084 //
00085 static void hideCursor(_GLFWwindow* window)
00086 {
00087     POINT pos;
00088 
00089     ClipCursor(NULL);
00090 
00091     if (GetCursorPos(&pos))
00092     {
00093         if (WindowFromPoint(pos) == window->win32.handle)
00094             SetCursor(NULL);
00095     }
00096 }
00097 
00098 // Disable the mouse cursor
00099 //
00100 static void disableCursor(_GLFWwindow* window)
00101 {
00102     POINT pos;
00103 
00104     updateClipRect(window);
00105 
00106     if (GetCursorPos(&pos))
00107     {
00108         if (WindowFromPoint(pos) == window->win32.handle)
00109             SetCursor(NULL);
00110     }
00111 }
00112 
00113 // Restores the mouse cursor
00114 //
00115 static void restoreCursor(_GLFWwindow* window)
00116 {
00117     POINT pos;
00118 
00119     ClipCursor(NULL);
00120 
00121     if (GetCursorPos(&pos))
00122     {
00123         if (WindowFromPoint(pos) == window->win32.handle)
00124         {
00125             if (window->cursor)
00126                 SetCursor(window->cursor->win32.handle);
00127             else
00128                 SetCursor(LoadCursorW(NULL, IDC_ARROW));
00129         }
00130     }
00131 }
00132 
00133 // Translates a GLFW standard cursor to a resource ID
00134 //
00135 static LPWSTR translateCursorShape(int shape)
00136 {
00137     switch (shape)
00138     {
00139         case GLFW_ARROW_CURSOR:
00140             return IDC_ARROW;
00141         case GLFW_IBEAM_CURSOR:
00142             return IDC_IBEAM;
00143         case GLFW_CROSSHAIR_CURSOR:
00144             return IDC_CROSS;
00145         case GLFW_HAND_CURSOR:
00146             return IDC_HAND;
00147         case GLFW_HRESIZE_CURSOR:
00148             return IDC_SIZEWE;
00149         case GLFW_VRESIZE_CURSOR:
00150             return IDC_SIZENS;
00151     }
00152 
00153     return NULL;
00154 }
00155 
00156 // Retrieves and translates modifier keys
00157 //
00158 static int getKeyMods(void)
00159 {
00160     int mods = 0;
00161 
00162     if (GetKeyState(VK_SHIFT) & (1 << 31))
00163         mods |= GLFW_MOD_SHIFT;
00164     if (GetKeyState(VK_CONTROL) & (1 << 31))
00165         mods |= GLFW_MOD_CONTROL;
00166     if (GetKeyState(VK_MENU) & (1 << 31))
00167         mods |= GLFW_MOD_ALT;
00168     if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & (1 << 31))
00169         mods |= GLFW_MOD_SUPER;
00170 
00171     return mods;
00172 }
00173 
00174 // Retrieves and translates modifier keys
00175 //
00176 static int getAsyncKeyMods(void)
00177 {
00178     int mods = 0;
00179 
00180     if (GetAsyncKeyState(VK_SHIFT) & (1 << 31))
00181         mods |= GLFW_MOD_SHIFT;
00182     if (GetAsyncKeyState(VK_CONTROL) & (1 << 31))
00183         mods |= GLFW_MOD_CONTROL;
00184     if (GetAsyncKeyState(VK_MENU) & (1 << 31))
00185         mods |= GLFW_MOD_ALT;
00186     if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & (1 << 31))
00187         mods |= GLFW_MOD_SUPER;
00188 
00189     return mods;
00190 }
00191 
00192 // Translates a Windows key to the corresponding GLFW key
00193 //
00194 static int translateKey(WPARAM wParam, LPARAM lParam)
00195 {
00196     if (wParam == VK_CONTROL)
00197     {
00198         // The CTRL keys require special handling
00199 
00200         MSG next;
00201         DWORD time;
00202 
00203         // Is this an extended key (i.e. right key)?
00204         if (lParam & 0x01000000)
00205             return GLFW_KEY_RIGHT_CONTROL;
00206 
00207         // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
00208         // want the RALT message, so we try to see if the next message
00209         // is a RALT message. In that case, this is a false LCTRL!
00210         time = GetMessageTime();
00211 
00212         if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
00213         {
00214             if (next.message == WM_KEYDOWN ||
00215                 next.message == WM_SYSKEYDOWN ||
00216                 next.message == WM_KEYUP ||
00217                 next.message == WM_SYSKEYUP)
00218             {
00219                 if (next.wParam == VK_MENU &&
00220                     (next.lParam & 0x01000000) &&
00221                     next.time == time)
00222                 {
00223                     // Next message is a RALT down message, which
00224                     // means that this is not a proper LCTRL message
00225                     return _GLFW_KEY_INVALID;
00226                 }
00227             }
00228         }
00229 
00230         return GLFW_KEY_LEFT_CONTROL;
00231     }
00232 
00233     return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];
00234 }
00235 
00236 // Enter full screen mode
00237 //
00238 static GLboolean enterFullscreenMode(_GLFWwindow* window)
00239 {
00240     GLFWvidmode mode;
00241     GLboolean status;
00242     int xpos, ypos;
00243 
00244     status = _glfwSetVideoMode(window->monitor, &window->videoMode);
00245 
00246     _glfwPlatformGetVideoMode(window->monitor, &mode);
00247     _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
00248 
00249     SetWindowPos(window->win32.handle, HWND_TOPMOST,
00250                  xpos, ypos, mode.width, mode.height, SWP_NOCOPYBITS);
00251 
00252     return status;
00253 }
00254 
00255 // Leave full screen mode
00256 //
00257 static void leaveFullscreenMode(_GLFWwindow* window)
00258 {
00259     _glfwRestoreVideoMode(window->monitor);
00260 }
00261 
00262 // Window callback function (handles window events)
00263 //
00264 static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
00265                                    WPARAM wParam, LPARAM lParam)
00266 {
00267     _GLFWwindow* window = (_GLFWwindow*) GetWindowLongPtrW(hWnd, 0);
00268 
00269     switch (uMsg)
00270     {
00271         case WM_NCCREATE:
00272         {
00273             CREATESTRUCTW* cs = (CREATESTRUCTW*) lParam;
00274             SetWindowLongPtrW(hWnd, 0, (LONG_PTR) cs->lpCreateParams);
00275             break;
00276         }
00277 
00278         case WM_SETFOCUS:
00279         {
00280             if (window->cursorMode != GLFW_CURSOR_NORMAL)
00281                 _glfwPlatformApplyCursorMode(window);
00282 
00283             _glfwInputWindowFocus(window, GL_TRUE);
00284             return 0;
00285         }
00286 
00287         case WM_KILLFOCUS:
00288         {
00289             if (window->cursorMode != GLFW_CURSOR_NORMAL)
00290                 restoreCursor(window);
00291 
00292             if (window->monitor && window->autoIconify)
00293                 _glfwPlatformIconifyWindow(window);
00294 
00295             _glfwInputWindowFocus(window, GL_FALSE);
00296             return 0;
00297         }
00298 
00299         case WM_SYSCOMMAND:
00300         {
00301             switch (wParam & 0xfff0)
00302             {
00303                 case SC_SCREENSAVE:
00304                 case SC_MONITORPOWER:
00305                 {
00306                     if (window->monitor)
00307                     {
00308                         // We are running in full screen mode, so disallow
00309                         // screen saver and screen blanking
00310                         return 0;
00311                     }
00312                     else
00313                         break;
00314                 }
00315 
00316                 // User trying to access application menu using ALT?
00317                 case SC_KEYMENU:
00318                     return 0;
00319             }
00320             break;
00321         }
00322 
00323         case WM_CLOSE:
00324         {
00325             _glfwInputWindowCloseRequest(window);
00326             return 0;
00327         }
00328 
00329         case WM_KEYDOWN:
00330         case WM_SYSKEYDOWN:
00331         {
00332             const int scancode = (lParam >> 16) & 0x1ff;
00333             const int key = translateKey(wParam, lParam);
00334             if (key == _GLFW_KEY_INVALID)
00335                 break;
00336 
00337             _glfwInputKey(window, key, scancode, GLFW_PRESS, getKeyMods());
00338             break;
00339         }
00340 
00341         case WM_CHAR:
00342         {
00343             _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);
00344             return 0;
00345         }
00346 
00347         case WM_SYSCHAR:
00348         {
00349             _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_FALSE);
00350             return 0;
00351         }
00352 
00353         case WM_UNICHAR:
00354         {
00355             // This message is not sent by Windows, but is sent by some
00356             // third-party input method engines
00357 
00358             if (wParam == UNICODE_NOCHAR)
00359             {
00360                 // Returning TRUE here announces support for this message
00361                 return TRUE;
00362             }
00363 
00364             _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);
00365             return FALSE;
00366         }
00367 
00368         case WM_KEYUP:
00369         case WM_SYSKEYUP:
00370         {
00371             const int mods = getKeyMods();
00372             const int scancode = (lParam >> 16) & 0x1ff;
00373             const int key = translateKey(wParam, lParam);
00374             if (key == _GLFW_KEY_INVALID)
00375                 break;
00376 
00377             if (wParam == VK_SHIFT)
00378             {
00379                 // Release both Shift keys on Shift up event, as only one event
00380                 // is sent even if both keys are released
00381                 _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);
00382                 _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods);
00383             }
00384             else if (wParam == VK_SNAPSHOT)
00385             {
00386                 // Key down is not reported for the print screen key
00387                 _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
00388                 _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
00389             }
00390             else
00391                 _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
00392 
00393             break;
00394         }
00395 
00396         case WM_LBUTTONDOWN:
00397         case WM_RBUTTONDOWN:
00398         case WM_MBUTTONDOWN:
00399         case WM_XBUTTONDOWN:
00400         {
00401             const int mods = getKeyMods();
00402 
00403             SetCapture(hWnd);
00404 
00405             if (uMsg == WM_LBUTTONDOWN)
00406                 _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
00407             else if (uMsg == WM_RBUTTONDOWN)
00408                 _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);
00409             else if (uMsg == WM_MBUTTONDOWN)
00410                 _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);
00411             else
00412             {
00413                 if (HIWORD(wParam) == XBUTTON1)
00414                     _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_PRESS, mods);
00415                 else if (HIWORD(wParam) == XBUTTON2)
00416                     _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS, mods);
00417 
00418                 return TRUE;
00419             }
00420 
00421             return 0;
00422         }
00423 
00424         case WM_LBUTTONUP:
00425         case WM_RBUTTONUP:
00426         case WM_MBUTTONUP:
00427         case WM_XBUTTONUP:
00428         {
00429             const int mods = getKeyMods();
00430 
00431             ReleaseCapture();
00432 
00433             if (uMsg == WM_LBUTTONUP)
00434                 _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods);
00435             else if (uMsg == WM_RBUTTONUP)
00436                 _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods);
00437             else if (uMsg == WM_MBUTTONUP)
00438                 _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods);
00439             else
00440             {
00441                 if (HIWORD(wParam) == XBUTTON1)
00442                     _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_RELEASE, mods);
00443                 else if (HIWORD(wParam) == XBUTTON2)
00444                     _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE, mods);
00445 
00446                 return TRUE;
00447             }
00448 
00449             return 0;
00450         }
00451 
00452         case WM_MOUSEMOVE:
00453         {
00454             const int x = GET_X_LPARAM(lParam);
00455             const int y = GET_Y_LPARAM(lParam);
00456 
00457             if (window->cursorMode == GLFW_CURSOR_DISABLED)
00458             {
00459                 if (_glfw.cursorWindow != window)
00460                     break;
00461 
00462                 _glfwInputCursorMotion(window,
00463                                        x - window->win32.cursorPosX,
00464                                        y - window->win32.cursorPosY);
00465             }
00466             else
00467                 _glfwInputCursorMotion(window, x, y);
00468 
00469             window->win32.cursorPosX = x;
00470             window->win32.cursorPosY = y;
00471 
00472             if (!window->win32.cursorTracked)
00473             {
00474                 TRACKMOUSEEVENT tme;
00475                 ZeroMemory(&tme, sizeof(tme));
00476                 tme.cbSize = sizeof(tme);
00477                 tme.dwFlags = TME_LEAVE;
00478                 tme.hwndTrack = window->win32.handle;
00479                 TrackMouseEvent(&tme);
00480 
00481                 window->win32.cursorTracked = GL_TRUE;
00482                 _glfwInputCursorEnter(window, GL_TRUE);
00483             }
00484 
00485             return 0;
00486         }
00487 
00488         case WM_MOUSELEAVE:
00489         {
00490             window->win32.cursorTracked = GL_FALSE;
00491             _glfwInputCursorEnter(window, GL_FALSE);
00492             return 0;
00493         }
00494 
00495         case WM_MOUSEWHEEL:
00496         {
00497             _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
00498             return 0;
00499         }
00500 
00501         case WM_MOUSEHWHEEL:
00502         {
00503             // This message is only sent on Windows Vista and later
00504             // NOTE: The X-axis is inverted for consistency with OS X and X11.
00505             _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
00506             return 0;
00507         }
00508 
00509         case WM_SIZE:
00510         {
00511             if (_glfw.cursorWindow == window)
00512             {
00513                 if (window->cursorMode == GLFW_CURSOR_DISABLED)
00514                     updateClipRect(window);
00515             }
00516 
00517             if (!window->win32.iconified && wParam == SIZE_MINIMIZED)
00518             {
00519                 window->win32.iconified = GL_TRUE;
00520                 if (window->monitor)
00521                     leaveFullscreenMode(window);
00522 
00523                 _glfwInputWindowIconify(window, GL_TRUE);
00524             }
00525             else if (window->win32.iconified &&
00526                      (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED))
00527             {
00528                 window->win32.iconified = GL_FALSE;
00529                 if (window->monitor)
00530                     enterFullscreenMode(window);
00531 
00532                 _glfwInputWindowIconify(window, GL_FALSE);
00533             }
00534 
00535             _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
00536             _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
00537             return 0;
00538         }
00539 
00540         case WM_MOVE:
00541         {
00542             if (_glfw.cursorWindow == window)
00543             {
00544                 if (window->cursorMode == GLFW_CURSOR_DISABLED)
00545                     updateClipRect(window);
00546             }
00547 
00548             // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
00549             // those macros do not handle negative window positions correctly
00550             _glfwInputWindowPos(window,
00551                                 GET_X_LPARAM(lParam),
00552                                 GET_Y_LPARAM(lParam));
00553             return 0;
00554         }
00555 
00556         case WM_PAINT:
00557         {
00558             _glfwInputWindowDamage(window);
00559             break;
00560         }
00561 
00562         case WM_ERASEBKGND:
00563         {
00564             return TRUE;
00565         }
00566 
00567         case WM_SETCURSOR:
00568         {
00569             if (_glfw.cursorWindow == window && LOWORD(lParam) == HTCLIENT)
00570             {
00571                 if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
00572                     window->cursorMode == GLFW_CURSOR_DISABLED)
00573                 {
00574                     SetCursor(NULL);
00575                     return TRUE;
00576                 }
00577                 else if (window->cursor)
00578                 {
00579                     SetCursor(window->cursor->win32.handle);
00580                     return TRUE;
00581                 }
00582             }
00583 
00584             break;
00585         }
00586 
00587         case WM_DEVICECHANGE:
00588         {
00589             if (DBT_DEVNODES_CHANGED == wParam)
00590             {
00591                 _glfwInputMonitorChange();
00592                 return TRUE;
00593             }
00594             break;
00595         }
00596 
00597         case WM_DROPFILES:
00598         {
00599             HDROP drop = (HDROP) wParam;
00600             POINT pt;
00601             int i;
00602 
00603             const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
00604             char** paths = calloc(count, sizeof(char*));
00605 
00606             // Move the mouse to the position of the drop
00607             DragQueryPoint(drop, &pt);
00608             _glfwInputCursorMotion(window, pt.x, pt.y);
00609 
00610             for (i = 0;  i < count;  i++)
00611             {
00612                 const UINT length = DragQueryFileW(drop, i, NULL, 0);
00613                 WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
00614 
00615                 DragQueryFileW(drop, i, buffer, length + 1);
00616                 paths[i] = _glfwCreateUTF8FromWideString(buffer);
00617 
00618                 free(buffer);
00619             }
00620 
00621             _glfwInputDrop(window, count, (const char**) paths);
00622 
00623             for (i = 0;  i < count;  i++)
00624                 free(paths[i]);
00625             free(paths);
00626 
00627             DragFinish(drop);
00628             return 0;
00629         }
00630     }
00631 
00632     return DefWindowProc(hWnd, uMsg, wParam, lParam);
00633 }
00634 
00635 // Translate client window size to full window size (including window borders)
00636 //
00637 static void getFullWindowSize(_GLFWwindow* window,
00638                               int clientWidth, int clientHeight,
00639                               int* fullWidth, int* fullHeight)
00640 {
00641     RECT rect = { 0, 0, clientWidth, clientHeight };
00642     AdjustWindowRectEx(&rect, getWindowStyle(window),
00643                        FALSE, getWindowExStyle(window));
00644     *fullWidth = rect.right - rect.left;
00645     *fullHeight = rect.bottom - rect.top;
00646 }
00647 
00648 // Creates the GLFW window and rendering context
00649 //
00650 static int createWindow(_GLFWwindow* window,
00651                         const _GLFWwndconfig* wndconfig,
00652                         const _GLFWctxconfig* ctxconfig,
00653                         const _GLFWfbconfig* fbconfig)
00654 {
00655     int xpos, ypos, fullWidth, fullHeight;
00656     WCHAR* wideTitle;
00657 
00658     if (wndconfig->monitor)
00659     {
00660         GLFWvidmode mode;
00661 
00662         // NOTE: This window placement is temporary and approximate, as the
00663         //       correct position and size cannot be known until the monitor
00664         //       video mode has been set
00665         _glfwPlatformGetMonitorPos(wndconfig->monitor, &xpos, &ypos);
00666         _glfwPlatformGetVideoMode(wndconfig->monitor, &mode);
00667         fullWidth  = mode.width;
00668         fullHeight = mode.height;
00669     }
00670     else
00671     {
00672         xpos = CW_USEDEFAULT;
00673         ypos = CW_USEDEFAULT;
00674 
00675         getFullWindowSize(window,
00676                           wndconfig->width, wndconfig->height,
00677                           &fullWidth, &fullHeight);
00678     }
00679 
00680     wideTitle = _glfwCreateWideStringFromUTF8(wndconfig->title);
00681     if (!wideTitle)
00682     {
00683         _glfwInputError(GLFW_PLATFORM_ERROR,
00684                         "Win32: Failed to convert window title to UTF-16");
00685         return GL_FALSE;
00686     }
00687 
00688     window->win32.handle = CreateWindowExW(getWindowExStyle(window),
00689                                            _GLFW_WNDCLASSNAME,
00690                                            wideTitle,
00691                                            getWindowStyle(window),
00692                                            xpos, ypos,
00693                                            fullWidth, fullHeight,
00694                                            NULL, // No parent window
00695                                            NULL, // No window menu
00696                                            GetModuleHandleW(NULL),
00697                                            window); // Pass object to WM_CREATE
00698 
00699     free(wideTitle);
00700 
00701     if (!window->win32.handle)
00702     {
00703         _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window");
00704         return GL_FALSE;
00705     }
00706 
00707     if (_glfw_ChangeWindowMessageFilterEx)
00708     {
00709         _glfw_ChangeWindowMessageFilterEx(window->win32.handle,
00710                                           WM_DROPFILES, MSGFLT_ALLOW, NULL);
00711         _glfw_ChangeWindowMessageFilterEx(window->win32.handle,
00712                                           WM_COPYDATA, MSGFLT_ALLOW, NULL);
00713         _glfw_ChangeWindowMessageFilterEx(window->win32.handle,
00714                                           WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
00715     }
00716 
00717     if (wndconfig->floating && !wndconfig->monitor)
00718     {
00719         SetWindowPos(window->win32.handle,
00720                      HWND_TOPMOST,
00721                      0, 0, 0, 0,
00722                      SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
00723     }
00724 
00725     DragAcceptFiles(window->win32.handle, TRUE);
00726 
00727     if (!_glfwCreateContext(window, ctxconfig, fbconfig))
00728         return GL_FALSE;
00729 
00730     return GL_TRUE;
00731 }
00732 
00733 // Destroys the GLFW window and rendering context
00734 //
00735 static void destroyWindow(_GLFWwindow* window)
00736 {
00737     _glfwDestroyContext(window);
00738 
00739     if (window->win32.handle)
00740     {
00741         DestroyWindow(window->win32.handle);
00742         window->win32.handle = NULL;
00743     }
00744 }
00745 
00746 
00750 
00751 // Registers the GLFW window class
00752 //
00753 GLboolean _glfwRegisterWindowClass(void)
00754 {
00755     WNDCLASSW wc;
00756 
00757     wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
00758     wc.lpfnWndProc   = (WNDPROC) windowProc;
00759     wc.cbClsExtra    = 0;                           // No extra class data
00760     wc.cbWndExtra    = sizeof(void*) + sizeof(int); // Make room for one pointer
00761     wc.hInstance     = GetModuleHandleW(NULL);
00762     wc.hCursor       = LoadCursorW(NULL, IDC_ARROW);
00763     wc.hbrBackground = NULL;                        // No background
00764     wc.lpszMenuName  = NULL;                        // No menu
00765     wc.lpszClassName = _GLFW_WNDCLASSNAME;
00766 
00767     // Load user-provided icon if available
00768     wc.hIcon = LoadIconW(GetModuleHandleW(NULL), L"GLFW_ICON");
00769     if (!wc.hIcon)
00770     {
00771         // No user-provided icon found, load default icon
00772         wc.hIcon = LoadIconW(NULL, IDI_WINLOGO);
00773     }
00774 
00775     if (!RegisterClassW(&wc))
00776     {
00777         _glfwInputError(GLFW_PLATFORM_ERROR,
00778                         "Win32: Failed to register window class");
00779         return GL_FALSE;
00780     }
00781 
00782     return GL_TRUE;
00783 }
00784 
00785 // Unregisters the GLFW window class
00786 //
00787 void _glfwUnregisterWindowClass(void)
00788 {
00789     UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
00790 }
00791 
00792 
00796 
00797 int _glfwPlatformCreateWindow(_GLFWwindow* window,
00798                               const _GLFWwndconfig* wndconfig,
00799                               const _GLFWctxconfig* ctxconfig,
00800                               const _GLFWfbconfig* fbconfig)
00801 {
00802     int status;
00803 
00804     if (!createWindow(window, wndconfig, ctxconfig, fbconfig))
00805         return GL_FALSE;
00806 
00807     status = _glfwAnalyzeContext(window, ctxconfig, fbconfig);
00808 
00809     if (status == _GLFW_RECREATION_IMPOSSIBLE)
00810         return GL_FALSE;
00811 
00812     if (status == _GLFW_RECREATION_REQUIRED)
00813     {
00814         // Some window hints require us to re-create the context using WGL
00815         // extensions retrieved through the current context, as we cannot check
00816         // for WGL extensions or retrieve WGL entry points before we have a
00817         // current context (actually until we have implicitly loaded the ICD)
00818 
00819         // Yes, this is strange, and yes, this is the proper way on Win32
00820 
00821         // As Windows only allows you to set the pixel format once for a
00822         // window, we need to destroy the current window and create a new one
00823         // to be able to use the new pixel format
00824 
00825         // Technically, it may be possible to keep the old window around if
00826         // we're just creating an OpenGL 3.0+ context with the same pixel
00827         // format, but it's not worth the added code complexity
00828 
00829         // First we clear the current context (the one we just created)
00830         // This is usually done by glfwDestroyWindow, but as we're not doing
00831         // full GLFW window destruction, it's duplicated here
00832         _glfwPlatformMakeContextCurrent(NULL);
00833 
00834         // Next destroy the Win32 window and WGL context (without resetting or
00835         // destroying the GLFW window object)
00836         destroyWindow(window);
00837 
00838         // ...and then create them again, this time with better APIs
00839         if (!createWindow(window, wndconfig, ctxconfig, fbconfig))
00840             return GL_FALSE;
00841     }
00842 
00843     if (window->monitor)
00844     {
00845         _glfwPlatformShowWindow(window);
00846         if (!enterFullscreenMode(window))
00847             return GL_FALSE;
00848     }
00849 
00850     return GL_TRUE;
00851 }
00852 
00853 void _glfwPlatformDestroyWindow(_GLFWwindow* window)
00854 {
00855     if (window->monitor)
00856         leaveFullscreenMode(window);
00857 
00858     destroyWindow(window);
00859 }
00860 
00861 void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
00862 {
00863     WCHAR* wideTitle = _glfwCreateWideStringFromUTF8(title);
00864     if (!wideTitle)
00865     {
00866         _glfwInputError(GLFW_PLATFORM_ERROR,
00867                         "Win32: Failed to convert window title to UTF-16");
00868         return;
00869     }
00870 
00871     SetWindowTextW(window->win32.handle, wideTitle);
00872     free(wideTitle);
00873 }
00874 
00875 void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
00876 {
00877     POINT pos = { 0, 0 };
00878     ClientToScreen(window->win32.handle, &pos);
00879 
00880     if (xpos)
00881         *xpos = pos.x;
00882     if (ypos)
00883         *ypos = pos.y;
00884 }
00885 
00886 void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
00887 {
00888     RECT rect = { xpos, ypos, xpos, ypos };
00889     AdjustWindowRectEx(&rect, getWindowStyle(window),
00890                        FALSE, getWindowExStyle(window));
00891     SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
00892                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
00893 }
00894 
00895 void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
00896 {
00897     RECT area;
00898     GetClientRect(window->win32.handle, &area);
00899 
00900     if (width)
00901         *width = area.right;
00902     if (height)
00903         *height = area.bottom;
00904 }
00905 
00906 void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
00907 {
00908     if (window->monitor)
00909         enterFullscreenMode(window);
00910     else
00911     {
00912         int fullWidth, fullHeight;
00913         getFullWindowSize(window, width, height, &fullWidth, &fullHeight);
00914 
00915         SetWindowPos(window->win32.handle, HWND_TOP,
00916                      0, 0, fullWidth, fullHeight,
00917                      SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
00918     }
00919 }
00920 
00921 void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
00922 {
00923     _glfwPlatformGetWindowSize(window, width, height);
00924 }
00925 
00926 void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
00927                                      int* left, int* top,
00928                                      int* right, int* bottom)
00929 {
00930     RECT rect;
00931     int width, height;
00932 
00933     _glfwPlatformGetWindowSize(window, &width, &height);
00934     SetRect(&rect, 0, 0, width, height);
00935     AdjustWindowRectEx(&rect, getWindowStyle(window),
00936                        FALSE, getWindowExStyle(window));
00937 
00938     if (left)
00939         *left = -rect.left;
00940     if (top)
00941         *top = -rect.top;
00942     if (right)
00943         *right = rect.right - width;
00944     if (bottom)
00945         *bottom = rect.bottom - height;
00946 }
00947 
00948 void _glfwPlatformIconifyWindow(_GLFWwindow* window)
00949 {
00950     ShowWindow(window->win32.handle, SW_MINIMIZE);
00951 }
00952 
00953 void _glfwPlatformRestoreWindow(_GLFWwindow* window)
00954 {
00955     ShowWindow(window->win32.handle, SW_RESTORE);
00956 }
00957 
00958 void _glfwPlatformShowWindow(_GLFWwindow* window)
00959 {
00960     ShowWindow(window->win32.handle, SW_SHOW);
00961     BringWindowToTop(window->win32.handle);
00962     SetForegroundWindow(window->win32.handle);
00963     SetFocus(window->win32.handle);
00964 }
00965 
00966 void _glfwPlatformUnhideWindow(_GLFWwindow* window)
00967 {
00968     ShowWindow(window->win32.handle, SW_SHOW);
00969 }
00970 
00971 void _glfwPlatformHideWindow(_GLFWwindow* window)
00972 {
00973     ShowWindow(window->win32.handle, SW_HIDE);
00974 }
00975 
00976 int _glfwPlatformWindowFocused(_GLFWwindow* window)
00977 {
00978     return window->win32.handle == GetActiveWindow();
00979 }
00980 
00981 int _glfwPlatformWindowIconified(_GLFWwindow* window)
00982 {
00983     return IsIconic(window->win32.handle);
00984 }
00985 
00986 int _glfwPlatformWindowVisible(_GLFWwindow* window)
00987 {
00988     return IsWindowVisible(window->win32.handle);
00989 }
00990 
00991 void _glfwPlatformPollEvents(void)
00992 {
00993     MSG msg;
00994 
00995     while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
00996     {
00997         if (msg.message == WM_QUIT)
00998         {
00999             // Treat WM_QUIT as a close on all windows
01000             // While GLFW does not itself post WM_QUIT, other processes may post
01001             // it to this one, for example Task Manager
01002 
01003             _GLFWwindow* window = _glfw.windowListHead;
01004             while (window)
01005             {
01006                 _glfwInputWindowCloseRequest(window);
01007                 window = window->next;
01008             }
01009         }
01010         else
01011         {
01012             TranslateMessage(&msg);
01013             DispatchMessageW(&msg);
01014         }
01015     }
01016 
01017     if (_glfw.cursorWindow)
01018     {
01019         _GLFWwindow* window = _glfw.cursorWindow;
01020 
01021         // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
01022         // This is the only async event handling in GLFW, but it solves some
01023         // nasty problems
01024         {
01025             const int mods = getAsyncKeyMods();
01026 
01027             // Get current state of left and right shift keys
01028             const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
01029             const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
01030 
01031             // See if this differs from our belief of what has happened
01032             // (we only have to check for lost key up events)
01033             if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1)
01034                 _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods);
01035 
01036             if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1)
01037                 _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);
01038         }
01039 
01040         if (window->cursorMode == GLFW_CURSOR_DISABLED)
01041         {
01042             int width, height;
01043             _glfwPlatformGetWindowSize(window, &width, &height);
01044 
01045             // NOTE: Re-center the cursor only if it has moved since the last
01046             //       call, to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
01047             if (window->win32.cursorPosX != width / 2 ||
01048                 window->win32.cursorPosY != height / 2)
01049             {
01050                 _glfwPlatformSetCursorPos(window, width / 2, height / 2);
01051             }
01052         }
01053     }
01054 }
01055 
01056 void _glfwPlatformWaitEvents(void)
01057 {
01058     WaitMessage();
01059 
01060     _glfwPlatformPollEvents();
01061 }
01062 
01063 void _glfwPlatformPostEmptyEvent(void)
01064 {
01065     _GLFWwindow* window = _glfw.windowListHead;
01066     PostMessage(window->win32.handle, WM_NULL, 0, 0);
01067 }
01068 
01069 void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
01070 {
01071     POINT pos;
01072 
01073     if (GetCursorPos(&pos))
01074     {
01075         ScreenToClient(window->win32.handle, &pos);
01076 
01077         if (xpos)
01078             *xpos = pos.x;
01079         if (ypos)
01080             *ypos = pos.y;
01081     }
01082 }
01083 
01084 void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
01085 {
01086     POINT pos = { (int) xpos, (int) ypos };
01087 
01088     // Store the new position so it can be recognized later
01089     window->win32.cursorPosX = pos.x;
01090     window->win32.cursorPosY = pos.y;
01091 
01092     ClientToScreen(window->win32.handle, &pos);
01093     SetCursorPos(pos.x, pos.y);
01094 }
01095 
01096 void _glfwPlatformApplyCursorMode(_GLFWwindow* window)
01097 {
01098     switch (window->cursorMode)
01099     {
01100         case GLFW_CURSOR_NORMAL:
01101             restoreCursor(window);
01102             break;
01103         case GLFW_CURSOR_HIDDEN:
01104             hideCursor(window);
01105             break;
01106         case GLFW_CURSOR_DISABLED:
01107             disableCursor(window);
01108             break;
01109     }
01110 }
01111 
01112 int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
01113                               const GLFWimage* image,
01114                               int xhot, int yhot)
01115 {
01116     HDC dc;
01117     HBITMAP bitmap, mask;
01118     BITMAPV5HEADER bi;
01119     ICONINFO ii;
01120     DWORD* target = 0;
01121     BYTE* source = (BYTE*) image->pixels;
01122     int i;
01123 
01124     ZeroMemory(&bi, sizeof(bi));
01125     bi.bV5Size        = sizeof(BITMAPV5HEADER);
01126     bi.bV5Width       = image->width;
01127     bi.bV5Height      = -image->height;
01128     bi.bV5Planes      = 1;
01129     bi.bV5BitCount    = 32;
01130     bi.bV5Compression = BI_BITFIELDS;
01131     bi.bV5RedMask     = 0x00ff0000;
01132     bi.bV5GreenMask   = 0x0000ff00;
01133     bi.bV5BlueMask    = 0x000000ff;
01134     bi.bV5AlphaMask   = 0xff000000;
01135 
01136     dc = GetDC(NULL);
01137     bitmap = CreateDIBSection(dc, (BITMAPINFO*) &bi, DIB_RGB_COLORS,
01138                               (void**) &target, NULL, (DWORD) 0);
01139     ReleaseDC(NULL, dc);
01140 
01141     if (!bitmap)
01142         return GL_FALSE;
01143 
01144     mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
01145     if (!mask)
01146     {
01147         DeleteObject(bitmap);
01148         return GL_FALSE;
01149     }
01150 
01151     for (i = 0;  i < image->width * image->height;  i++, target++, source += 4)
01152     {
01153         *target = (source[3] << 24) |
01154                   (source[0] << 16) |
01155                   (source[1] <<  8) |
01156                    source[2];
01157     }
01158 
01159     ZeroMemory(&ii, sizeof(ii));
01160     ii.fIcon    = FALSE;
01161     ii.xHotspot = xhot;
01162     ii.yHotspot = yhot;
01163     ii.hbmMask  = mask;
01164     ii.hbmColor = bitmap;
01165 
01166     cursor->win32.handle = (HCURSOR) CreateIconIndirect(&ii);
01167 
01168     DeleteObject(bitmap);
01169     DeleteObject(mask);
01170 
01171     if (!cursor->win32.handle)
01172         return GL_FALSE;
01173 
01174     return GL_TRUE;
01175 }
01176 
01177 int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
01178 {
01179     cursor->win32.handle =
01180         CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
01181     if (!cursor->win32.handle)
01182     {
01183         _glfwInputError(GLFW_PLATFORM_ERROR,
01184                         "Win32: Failed to create standard cursor");
01185         return GL_FALSE;
01186     }
01187 
01188     return GL_TRUE;
01189 }
01190 
01191 void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
01192 {
01193     if (cursor->win32.handle)
01194         DestroyIcon((HICON) cursor->win32.handle);
01195 }
01196 
01197 void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
01198 {
01199     POINT pos;
01200 
01201     if (_glfw.cursorWindow != window)
01202         return;
01203 
01204     if (window->cursorMode != GLFW_CURSOR_NORMAL)
01205         return;
01206 
01207     if (!GetCursorPos(&pos))
01208         return;
01209 
01210     if (WindowFromPoint(pos) != window->win32.handle)
01211         return;
01212 
01213     if (cursor)
01214         SetCursor(cursor->win32.handle);
01215     else
01216         SetCursor(LoadCursorW(NULL, IDC_ARROW));
01217 }
01218 
01219 void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
01220 {
01221     WCHAR* wideString;
01222     HANDLE stringHandle;
01223     size_t wideSize;
01224 
01225     wideString = _glfwCreateWideStringFromUTF8(string);
01226     if (!wideString)
01227     {
01228         _glfwInputError(GLFW_PLATFORM_ERROR,
01229                         "Win32: Failed to convert string to UTF-16");
01230         return;
01231     }
01232 
01233     wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR);
01234 
01235     stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize);
01236     if (!stringHandle)
01237     {
01238         free(wideString);
01239 
01240         _glfwInputError(GLFW_PLATFORM_ERROR,
01241                         "Win32: Failed to allocate global handle for clipboard");
01242         return;
01243     }
01244 
01245     memcpy(GlobalLock(stringHandle), wideString, wideSize);
01246     GlobalUnlock(stringHandle);
01247 
01248     if (!OpenClipboard(window->win32.handle))
01249     {
01250         GlobalFree(stringHandle);
01251         free(wideString);
01252 
01253         _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
01254         return;
01255     }
01256 
01257     EmptyClipboard();
01258     SetClipboardData(CF_UNICODETEXT, stringHandle);
01259     CloseClipboard();
01260 
01261     free(wideString);
01262 }
01263 
01264 const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
01265 {
01266     HANDLE stringHandle;
01267 
01268     if (!OpenClipboard(window->win32.handle))
01269     {
01270         _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
01271         return NULL;
01272     }
01273 
01274     stringHandle = GetClipboardData(CF_UNICODETEXT);
01275     if (!stringHandle)
01276     {
01277         CloseClipboard();
01278 
01279         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
01280                         "Win32: Failed to convert clipboard to string");
01281         return NULL;
01282     }
01283 
01284     free(_glfw.win32.clipboardString);
01285     _glfw.win32.clipboardString =
01286         _glfwCreateUTF8FromWideString(GlobalLock(stringHandle));
01287 
01288     GlobalUnlock(stringHandle);
01289     CloseClipboard();
01290 
01291     if (!_glfw.win32.clipboardString)
01292     {
01293         _glfwInputError(GLFW_PLATFORM_ERROR,
01294                         "Win32: Failed to convert wide string to UTF-8");
01295         return NULL;
01296     }
01297 
01298     return _glfw.win32.clipboardString;
01299 }
01300 
01301 
01305 
01306 GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
01307 {
01308     _GLFWwindow* window = (_GLFWwindow*) handle;
01309     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
01310     return window->win32.handle;
01311 }
01312 


librealsense
Author(s): Sergey Dorodnicov , Mark Horn , Reagan Lopez
autogenerated on Tue Jun 25 2019 19:54:39