00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
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
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
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
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
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
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
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
00193
00194 static int translateKey(WPARAM wParam, LPARAM lParam)
00195 {
00196 if (wParam == VK_CONTROL)
00197 {
00198
00199
00200 MSG next;
00201 DWORD time;
00202
00203
00204 if (lParam & 0x01000000)
00205 return GLFW_KEY_RIGHT_CONTROL;
00206
00207
00208
00209
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
00224
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
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
00256
00257 static void leaveFullscreenMode(_GLFWwindow* window)
00258 {
00259 _glfwRestoreVideoMode(window->monitor);
00260 }
00261
00262
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
00309
00310 return 0;
00311 }
00312 else
00313 break;
00314 }
00315
00316
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
00356
00357
00358 if (wParam == UNICODE_NOCHAR)
00359 {
00360
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
00380
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
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
00504
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
00549
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
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
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
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
00663
00664
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,
00695 NULL,
00696 GetModuleHandleW(NULL),
00697 window);
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
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
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;
00760 wc.cbWndExtra = sizeof(void*) + sizeof(int);
00761 wc.hInstance = GetModuleHandleW(NULL);
00762 wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
00763 wc.hbrBackground = NULL;
00764 wc.lpszMenuName = NULL;
00765 wc.lpszClassName = _GLFW_WNDCLASSNAME;
00766
00767
00768 wc.hIcon = LoadIconW(GetModuleHandleW(NULL), L"GLFW_ICON");
00769 if (!wc.hIcon)
00770 {
00771
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
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
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832 _glfwPlatformMakeContextCurrent(NULL);
00833
00834
00835
00836 destroyWindow(window);
00837
00838
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
01000
01001
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
01022
01023
01024 {
01025 const int mods = getAsyncKeyMods();
01026
01027
01028 const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
01029 const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
01030
01031
01032
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
01046
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
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