diff --git a/.gitattributes b/.gitattributes index 64a3446f6..96200d248 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -*.m linguist-language=Objective-C +*.m linguist-language=Objective-C diff --git a/.gitignore b/.gitignore index f6103c222..9fc9bef05 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,4 @@ tests/title tests/vulkan tests/windows +/build diff --git a/examples/glfw.rc b/examples/glfw.rc index f2b62f6c4..ab88e4ea4 100644 --- a/examples/glfw.rc +++ b/examples/glfw.rc @@ -1,3 +1,3 @@ - -GLFW_ICON ICON "glfw.ico" - + +GLFW_ICON ICON "glfw.ico" + diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 237dd55ef..d7521458e 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1318,6 +1318,24 @@ typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float); */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); +/*! @brief The function signature for pen callbacks. +* +* This is the function signature for pen callback functions. +* +* @param[in] window The window that received the event. +* @param[in] pressure The [pen pressure](@ref pressure) that was pressed or +* released. +* @param[in] the x (horizontal point) coordinate of the point location of the pen. +* @param[in] the y (vertical point) coordinate of the point location of the pen. +* * +* @sa @ref input_pen_pressure +* @sa @ref glfwSetPenPressureCallback +* +* @ingroup input +*/ + +typedef void(*GLFWpenpressurefun)(GLFWwindow*, double, int, int); + /*! @brief The function signature for cursor position callbacks. * * This is the function signature for cursor position callback functions. @@ -1390,6 +1408,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); * * @ingroup input */ + typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); /*! @brief The function signature for Unicode character callbacks. @@ -4014,7 +4033,32 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key); * * @ingroup input */ -GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button); +GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button); + +/*! @brief Returns the last reported state of a pen button for the specified +* window. +* +* This function returns the last state reported for the specified pen button +* to the specified window. The returned state is one of `GLFW_PRESS` or +* `GLFW_RELEASE`. +* +* @param[in] window The desired window. +* @param[in] button The desired [pen button](@ref pen buttons). +* @return One of `GLFW_PRESS` or `GLFW_RELEASE`. +* +* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref +* GLFW_INVALID_ENUM. +* +* @thread_safety This function must only be called from the main thread. +* +* @sa @ref input_pen_button +* +* @since Added in version 1.0. +* @glfw3 Added window handle parameter. +* +* @ingroup input +*/ +GLFWAPI double glfwGetPenPressure(GLFWwindow* handle); /*! @brief Retrieves the position of the cursor relative to the client area of * the window. @@ -4354,6 +4398,27 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmods * @ingroup input */ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun); +/*! @brief Sets the pen callback. +* +* This function sets the pen callback of the specified window, which +* is called when a pen is pressed or released. +** +* @param[in] window The window whose callback to set. +* @param[in] cbfun The new callback, or `NULL` to remove the currently set +* callback. +* @return The previously set callback, or `NULL` if no callback was set or the +* library had not been [initialized](@ref intro_init). +* +* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. +* +* @thread_safety This function must only be called from the main thread. +* +* @sa @ref input_pen_pressure +* +* +* @ingroup input +*/ +GLFWAPI GLFWpenpressurefun glfwSetPenPressureCallback(GLFWwindow* window, GLFWpenpressurefun cbfun); /*! @brief Sets the cursor position callback. * diff --git a/src/input.c b/src/input.c index 7d81cd57f..870f979f4 100644 --- a/src/input.c +++ b/src/input.c @@ -293,6 +293,16 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); } +void _glfwInputPenPressure(_GLFWwindow* window, double pressure, int x, int y) +{ + window->penPressure = pressure; + window->penXposition = x; + window->penYposition = y; + + if (window->callbacks.penPressure) + window->callbacks.penPressure((GLFWwindow*)window, pressure, x, y); +} + void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) { if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) @@ -578,6 +588,19 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) return (int) window->mouseButtons[button]; } + +/***************************PEN**************************************************/ +GLFWAPI double glfwGetPenPressure(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*)handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(0); + + return window->penPressure; +} +/**************************PEN***************************************************/ + GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; @@ -773,6 +796,17 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, return cbfun; } +GLFWAPI GLFWpenpressurefun glfwSetPenPressureCallback(GLFWwindow* handle, + GLFWpenpressurefun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*)handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(window->callbacks.penPressure, cbfun); + return cbfun; +} + GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle, GLFWcursorposfun cbfun) { diff --git a/src/internal.h b/src/internal.h index ea9c4ed1a..1405f82eb 100644 --- a/src/internal.h +++ b/src/internal.h @@ -84,8 +84,8 @@ typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*); typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*); #define GL_VERSION 0x1f02 -#define GL_NONE 0 -#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_NONE 0 +#define GL_COLOR_BUFFER_BIT 0x00004000 #define GL_UNSIGNED_BYTE 0x1401 #define GL_EXTENSIONS 0x1f03 #define GL_NUM_EXTENSIONS 0x821d @@ -102,7 +102,7 @@ typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*); #define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc #define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008 -typedef int GLint; +typedef int GLint; typedef unsigned int GLuint; typedef unsigned int GLenum; typedef unsigned int GLbitfield; @@ -419,7 +419,13 @@ struct _GLFWwindow GLFWbool stickyKeys; GLFWbool stickyMouseButtons; + + double penPressure; + int penXposition; + int penYposition; + GLFWbool lockKeyMods; + int cursorMode; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char keys[GLFW_KEY_LAST + 1]; @@ -439,6 +445,7 @@ struct _GLFWwindow GLFWframebuffersizefun fbsize; GLFWwindowcontentscalefun scale; GLFWmousebuttonfun mouseButton; + GLFWpenpressurefun penPressure; GLFWcursorposfun cursorPos; GLFWcursorenterfun cursorEnter; GLFWscrollfun scroll; @@ -835,6 +842,15 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); */ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); +/*! @brief Notifies shared code of a pen click event. +* @param[in] window The window that received the event. +* @param[in] pressure when the pen was pressed. +* @param[in] x (horizontal point) coordinate of the point location of the pen. +* @param[in] y (vertical point) coordinate of the point location of the pen. +* @ingroup event +*/ +void _glfwInputPenPressure(_GLFWwindow* window, double pressure, int x, int y); + /*! @brief Notifies shared code of a cursor motion event. * @param[in] window The window that received the event. * @param[in] xpos The new x-coordinate of the cursor, relative to the left diff --git a/src/win32_platform.h b/src/win32_platform.h index 958a31375..49c68480a 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -104,6 +104,89 @@ #define _WIN32_WINNT_WINBLUE 0x0602 #endif +#if WINVER < 0x0604 +#define WM_POINTERUPDATE 0x0245 +#define WM_POINTERDOWN 0x0246 +#define WM_POINTERUP 0x0247 +#define POINTER_MESSAGE_FLAG_INCONTACT 0x00000004 // Pointer is in contact + +#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam)) +#define IS_POINTER_INCONTACT_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_INCONTACT) +#define IS_POINTER_FLAG_SET_WPARAM(wParam, flag) (((DWORD)HIWORD(wParam) & (flag)) == (flag)) + +typedef enum +{ + POINTER_CHANGE_NONE, + POINTER_CHANGE_FIRSTBUTTON_DOWN, + POINTER_CHANGE_FIRSTBUTTON_UP, + POINTER_CHANGE_SECONDBUTTON_DOWN, + POINTER_CHANGE_SECONDBUTTON_UP, + POINTER_CHANGE_THIRDBUTTON_DOWN, + POINTER_CHANGE_THIRDBUTTON_UP, + POINTER_CHANGE_FOURTHBUTTON_DOWN, + POINTER_CHANGE_FOURTHBUTTON_UP, + POINTER_CHANGE_FIFTHBUTTON_DOWN, + POINTER_CHANGE_FIFTHBUTTON_UP, +} POINTER_BUTTON_CHANGE_TYPE; + +typedef struct +{ + DWORD pointerType; + UINT32 pointerId; + UINT32 frameId; + UINT32 pointerFlags; + HANDLE sourceDevice; + HWND hwndTarget; + POINT ptPixelLocation; + POINT ptHimetricLocation; + POINT ptPixelLocationRaw; + POINT ptHimetricLocationRaw; + DWORD dwTime; + UINT32 historyCount; + INT32 InputData; + DWORD dwKeyStates; + UINT64 PerformanceCount; + POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; +} POINTER_INFO; + +typedef struct +{ + POINTER_INFO pointerInfo; + UINT32 penFlags; + UINT32 penMask; + UINT32 pressure; + UINT32 rotation; + INT32 tiltX; + INT32 tiltY; +} POINTER_PEN_INFO; + +typedef struct +{ + POINTER_INFO pointerInfo; + UINT32 touchFlags; + UINT32 touchMask; + RECT rcContact; + RECT rcContactRaw; + UINT32 orientation; + UINT32 pressure; +} POINTER_TOUCH_INFO; + +enum { + PT_POINTER = 0x00000001, // Generic pointer + PT_TOUCH = 0x00000002, // Touch + PT_PEN = 0x00000003, // Pen + PT_MOUSE = 0x00000004, // Mouse +#if WINVER >= 0x0603 + PT_TOUCHPAD = 0x00000005, // Touchpad +#endif /* WINVER >= 0x0603 */ +}; + +WINUSERAPI BOOL WINAPI GetPointerType(UINT32,DWORD*); +WINUSERAPI BOOL WINAPI GetPointerPenInfo(UINT32,POINTER_PEN_INFO*); +WINUSERAPI BOOL WINAPI GetPointerInfo(UINT32,POINTER_INFO*); + +#endif /*Windows 8 and above*/ + #if WINVER < 0x0601 typedef struct { @@ -189,7 +272,7 @@ BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp); // HACK: Define macros that some dinput.h variants don't #ifndef DIDFT_OPTIONAL - #define DIDFT_OPTIONAL 0x80000000 + #define DIDFT_OPTIONAL 0x80000000 #endif // winmm.dll function pointer typedefs diff --git a/src/win32_window.c b/src/win32_window.c index d6959d07a..f0c1ce268 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include #define _GLFW_KEY_INVALID -2 @@ -77,15 +79,15 @@ static DWORD getWindowExStyle(const _GLFWwindow* window) // Returns the image whose area most closely matches the desired one // static const GLFWimage* chooseImage(int count, const GLFWimage* images, - int width, int height) + int width, int height) { int i, leastDiff = INT_MAX; const GLFWimage* closest = NULL; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { const int currDiff = abs(images[i].width * images[i].height - - width * height); + width * height); if (currDiff < leastDiff) { closest = images + i; @@ -99,7 +101,7 @@ static const GLFWimage* chooseImage(int count, const GLFWimage* images, // Creates an RGBA icon or cursor // static HICON createIcon(const GLFWimage* image, - int xhot, int yhot, GLFWbool icon) + int xhot, int yhot, GLFWbool icon) { int i; HDC dc; @@ -111,30 +113,30 @@ static HICON createIcon(const GLFWimage* image, unsigned char* source = image->pixels; ZeroMemory(&bi, sizeof(bi)); - bi.bV5Size = sizeof(bi); - bi.bV5Width = image->width; - bi.bV5Height = -image->height; - bi.bV5Planes = 1; - bi.bV5BitCount = 32; + bi.bV5Size = sizeof(bi); + bi.bV5Width = image->width; + bi.bV5Height = -image->height; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; bi.bV5Compression = BI_BITFIELDS; - bi.bV5RedMask = 0x00ff0000; - bi.bV5GreenMask = 0x0000ff00; - bi.bV5BlueMask = 0x000000ff; - bi.bV5AlphaMask = 0xff000000; + bi.bV5RedMask = 0x00ff0000; + bi.bV5GreenMask = 0x0000ff00; + bi.bV5BlueMask = 0x000000ff; + bi.bV5AlphaMask = 0xff000000; dc = GetDC(NULL); color = CreateDIBSection(dc, - (BITMAPINFO*) &bi, - DIB_RGB_COLORS, - (void**) &target, - NULL, - (DWORD) 0); + (BITMAPINFO*)&bi, + DIB_RGB_COLORS, + (void**)&target, + NULL, + (DWORD)0); ReleaseDC(NULL, dc); if (!color) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to create RGBA bitmap"); + "Win32: Failed to create RGBA bitmap"); return NULL; } @@ -142,12 +144,12 @@ static HICON createIcon(const GLFWimage* image, if (!mask) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to create mask bitmap"); + "Win32: Failed to create mask bitmap"); DeleteObject(color); return NULL; } - for (i = 0; i < image->width * image->height; i++) + for (i = 0; i < image->width * image->height; i++) { target[0] = source[2]; target[1] = source[1]; @@ -158,10 +160,10 @@ static HICON createIcon(const GLFWimage* image, } ZeroMemory(&ii, sizeof(ii)); - ii.fIcon = icon; + ii.fIcon = icon; ii.xHotspot = xhot; ii.yHotspot = yhot; - ii.hbmMask = mask; + ii.hbmMask = mask; ii.hbmColor = color; handle = CreateIconIndirect(&ii); @@ -174,12 +176,12 @@ static HICON createIcon(const GLFWimage* image, if (icon) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to create icon"); + "Win32: Failed to create icon"); } else { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to create cursor"); + "Win32: Failed to create cursor"); } } @@ -189,8 +191,8 @@ static HICON createIcon(const GLFWimage* image, // Translate client window size to full window size according to styles // static void getFullWindowSize(DWORD style, DWORD exStyle, - int clientWidth, int clientHeight, - int* fullWidth, int* fullHeight) + int clientWidth, int clientHeight, + int* fullWidth, int* fullHeight) { RECT rect = { 0, 0, clientWidth, clientHeight }; AdjustWindowRectEx(&rect, style, FALSE, exStyle); @@ -203,26 +205,26 @@ static void getFullWindowSize(DWORD style, DWORD exStyle, static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area) { int xoff, yoff; - const float ratio = (float) window->numer / (float) window->denom; + const float ratio = (float)window->numer / (float)window->denom; getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), - 0, 0, &xoff, &yoff); + 0, 0, &xoff, &yoff); - if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT || + if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT || edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT) { area->bottom = area->top + yoff + - (int) ((area->right - area->left - xoff) / ratio); + (int)((area->right - area->left - xoff) / ratio); } else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT) { area->top = area->bottom - yoff - - (int) ((area->right - area->left - xoff) / ratio); + (int)((area->right - area->left - xoff) / ratio); } else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM) { area->right = area->left + xoff + - (int) ((area->bottom - area->top - yoff) * ratio); + (int)((area->bottom - area->top - yoff) * ratio); } } @@ -249,8 +251,8 @@ static GLFWbool cursorInClientArea(_GLFWwindow* window) return GLFW_FALSE; GetClientRect(window->win32.handle, &area); - ClientToScreen(window->win32.handle, (POINT*) &area.left); - ClientToScreen(window->win32.handle, (POINT*) &area.right); + ClientToScreen(window->win32.handle, (POINT*)&area.left); + ClientToScreen(window->win32.handle, (POINT*)&area.right); return PtInRect(&area, pos); } @@ -278,8 +280,8 @@ static void updateClipRect(_GLFWwindow* window) { RECT clipRect; GetClientRect(window->win32.handle, &clipRect); - ClientToScreen(window->win32.handle, (POINT*) &clipRect.left); - ClientToScreen(window->win32.handle, (POINT*) &clipRect.right); + ClientToScreen(window->win32.handle, (POINT*)&clipRect.left); + ClientToScreen(window->win32.handle, (POINT*)&clipRect.right); ClipCursor(&clipRect); } else @@ -297,13 +299,13 @@ static void updateWindowStyles(const _GLFWwindow* window) GetClientRect(window->win32.handle, &rect); AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window)); - ClientToScreen(window->win32.handle, (POINT*) &rect.left); - ClientToScreen(window->win32.handle, (POINT*) &rect.right); + ClientToScreen(window->win32.handle, (POINT*)&rect.left); + ClientToScreen(window->win32.handle, (POINT*)&rect.right); SetWindowLongW(window->win32.handle, GWL_STYLE, style); SetWindowPos(window->win32.handle, HWND_TOP, - rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, - SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER); + rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER); } // Update window framebuffer transparency @@ -316,7 +318,7 @@ static void updateFramebufferTransparency(const _GLFWwindow* window) if (_glfwIsCompositionEnabledWin32()) { HRGN region = CreateRectRgn(0, 0, -1, -1); - DWM_BLURBEHIND bb = {0}; + DWM_BLURBEHIND bb = { 0 }; bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; bb.hRgnBlur = region; bb.fEnable = TRUE; @@ -340,7 +342,7 @@ static void updateFramebufferTransparency(const _GLFWwindow* window) // issue. When set to black, something is making the hit test // not resize with the window frame. SetLayeredWindowAttributes(window->win32.handle, - RGB(0, 193, 48), 255, LWA_COLORKEY); + RGB(0, 193, 48), 255, LWA_COLORKEY); } DeleteObject(region); @@ -351,7 +353,7 @@ static void updateFramebufferTransparency(const _GLFWwindow* window) exStyle &= ~WS_EX_LAYERED; SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle); RedrawWindow(window->win32.handle, NULL, NULL, - RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); } } @@ -361,18 +363,18 @@ static LPWSTR translateCursorShape(int shape) { switch (shape) { - case GLFW_ARROW_CURSOR: - return IDC_ARROW; - case GLFW_IBEAM_CURSOR: - return IDC_IBEAM; - case GLFW_CROSSHAIR_CURSOR: - return IDC_CROSS; - case GLFW_HAND_CURSOR: - return IDC_HAND; - case GLFW_HRESIZE_CURSOR: - return IDC_SIZEWE; - case GLFW_VRESIZE_CURSOR: - return IDC_SIZENS; + case GLFW_ARROW_CURSOR: + return IDC_ARROW; + case GLFW_IBEAM_CURSOR: + return IDC_IBEAM; + case GLFW_CROSSHAIR_CURSOR: + return IDC_CROSS; + case GLFW_HAND_CURSOR: + return IDC_HAND; + case GLFW_HRESIZE_CURSOR: + return IDC_SIZEWE; + case GLFW_VRESIZE_CURSOR: + return IDC_SIZENS; } return NULL; @@ -490,8 +492,8 @@ static GLFWbool acquireMonitor(_GLFWwindow* window) _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); SetWindowPos(window->win32.handle, HWND_TOPMOST, - xpos, ypos, mode.width, mode.height, - SWP_NOACTIVATE | SWP_NOCOPYBITS); + xpos, ypos, mode.width, mode.height, + SWP_NOACTIVATE | SWP_NOCOPYBITS); _glfwInputMonitorWindow(window->monitor, window); return status; @@ -515,7 +517,7 @@ static void releaseMonitor(_GLFWwindow* window) // Window callback function (handles window messages) // static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam) + WPARAM wParam, LPARAM lParam) { _GLFWwindow* window = GetPropW(hWnd, L"GLFW"); if (!window) @@ -524,27 +526,27 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, switch (uMsg) { - case WM_DISPLAYCHANGE: - _glfwPollMonitorsWin32(); - break; + case WM_DISPLAYCHANGE: + _glfwPollMonitorsWin32(); + break; - case WM_DEVICECHANGE: + case WM_DEVICECHANGE: + { + if (wParam == DBT_DEVICEARRIVAL) { - if (wParam == DBT_DEVICEARRIVAL) - { - DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; - if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - _glfwDetectJoystickConnectionWin32(); - } - else if (wParam == DBT_DEVICEREMOVECOMPLETE) - { - DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; - if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - _glfwDetectJoystickDisconnectionWin32(); - } - - break; + DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam; + if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + _glfwDetectJoystickConnectionWin32(); } + else if (wParam == DBT_DEVICEREMOVECOMPLETE) + { + DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam; + if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + _glfwDetectJoystickDisconnectionWin32(); + } + + break; + } } return DefWindowProcW(hWnd, uMsg, wParam, lParam); @@ -552,502 +554,563 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, switch (uMsg) { - case WM_MOUSEACTIVATE: + case WM_MOUSEACTIVATE: + { + // HACK: Postpone cursor disabling when the window was activated by + // clicking a caption button + if (HIWORD(lParam) == WM_LBUTTONDOWN) { - // HACK: Postpone cursor disabling when the window was activated by - // clicking a caption button - if (HIWORD(lParam) == WM_LBUTTONDOWN) + if (LOWORD(lParam) == HTCLOSE || + LOWORD(lParam) == HTMINBUTTON || + LOWORD(lParam) == HTMAXBUTTON) { - if (LOWORD(lParam) == HTCLOSE || - LOWORD(lParam) == HTMINBUTTON || - LOWORD(lParam) == HTMAXBUTTON) + window->win32.frameAction = GLFW_TRUE; + } + } + + break; + } + + case WM_POINTERDOWN: + case WM_POINTERUPDATE: + case WM_POINTERUP: + { + POINTER_PEN_INFO penInfo; + POINTER_INFO pointerInfo; + UINT32 pointerId = GET_POINTERID_WPARAM(wParam); + DWORD pointerType = PT_POINTER; + + // default to unhandled to enable call to DefWindowProc + BOOL fHandled = FALSE; + + // Retrieve common pointer information + if (!GetPointerType(pointerId, &pointerType)) + { + // failure, call + GetLastError(); + // set PT_POINTER to fall to default case below + pointerType = PT_POINTER; + } + + switch (pointerType) + { + case (PT_PEN): + //Retrieve pen information + if (!GetPointerPenInfo(pointerId, &penInfo)) + { + // failure, call + GetLastError(); + } + else + { + // success, process penInfo + // We change the pen pressure which is given normalized to a range between 0 and 1024 + // to a normalized value in [0..1] + double pressure = (double)penInfo.pressure /(double) 1024; + int xPos = GET_X_LPARAM(lParam); + int yPos = GET_Y_LPARAM(lParam); + if (IS_POINTER_INCONTACT_WPARAM(wParam)) { - window->win32.frameAction = GLFW_TRUE; + _glfwInputPenPressure(window, pressure, xPos, yPos); } + // mark as handled to skip call to DefWindowProc + fHandled = TRUE; } - break; } - - case WM_CAPTURECHANGED: + default: + if (!GetPointerInfo(pointerId, &pointerInfo)) { - // HACK: Disable the cursor once the caption button action has been - // completed or cancelled - if (lParam == 0 && window->win32.frameAction) - { - if (window->cursorMode == GLFW_CURSOR_DISABLED) - _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); - - window->win32.frameAction = GLFW_FALSE; - } - - break; + // failure. + GetLastError(); } - - case WM_SETFOCUS: + else { - _glfwInputWindowFocus(window, GLFW_TRUE); - - // HACK: Do not disable cursor while the user is interacting with - // a caption button - if (window->win32.frameAction) - break; + // success, proceed with pointerInfo. + // fHandled = HandleGenericPointerMessage(&pointerInfo); + } + break; + } + case WM_CAPTURECHANGED: + { + // HACK: Disable the cursor once the caption button action has been + // completed or cancelled + if (lParam == 0 && window->win32.frameAction) + { if (window->cursorMode == GLFW_CURSOR_DISABLED) _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); - return 0; + window->win32.frameAction = GLFW_FALSE; } - case WM_KILLFOCUS: - { - if (window->cursorMode == GLFW_CURSOR_DISABLED) - _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); + break; + } - if (window->monitor && window->autoIconify) - _glfwPlatformIconifyWindow(window); + case WM_SETFOCUS: + { + _glfwInputWindowFocus(window, GLFW_TRUE); - _glfwInputWindowFocus(window, GLFW_FALSE); - return 0; - } - - case WM_SYSCOMMAND: - { - switch (wParam & 0xfff0) - { - case SC_SCREENSAVE: - case SC_MONITORPOWER: - { - if (window->monitor) - { - // We are running in full screen mode, so disallow - // screen saver and screen blanking - return 0; - } - else - break; - } - - // User trying to access application menu using ALT? - case SC_KEYMENU: - return 0; - } + // HACK: Do not disable cursor while the user is interacting with + // a caption button + if (window->win32.frameAction) break; - } - case WM_CLOSE: + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); + + return 0; + } + + case WM_KILLFOCUS: + { + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); + + if (window->monitor && window->autoIconify) + _glfwPlatformIconifyWindow(window); + + _glfwInputWindowFocus(window, GLFW_FALSE); + return 0; + } + + case WM_SYSCOMMAND: + { + switch (wParam & 0xfff0) { - _glfwInputWindowCloseRequest(window); - return 0; - } - - case WM_INPUTLANGCHANGE: + case SC_SCREENSAVE: + case SC_MONITORPOWER: { - _glfwUpdateKeyNamesWin32(); - break; - } - - case WM_CHAR: - case WM_SYSCHAR: - case WM_UNICHAR: - { - const GLFWbool plain = (uMsg != WM_SYSCHAR); - - if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) - { - // WM_UNICHAR is not sent by Windows, but is sent by some - // third-party input method engine - // Returning TRUE here announces support for this message - return TRUE; - } - - _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain); - return 0; - } - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_KEYUP: - case WM_SYSKEYUP: - { - const int key = translateKey(wParam, lParam); - const int scancode = (lParam >> 16) & 0x1ff; - const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS; - const int mods = getKeyMods(); - - if (key == _GLFW_KEY_INVALID) - break; - - if (action == GLFW_RELEASE && wParam == VK_SHIFT) - { - // HACK: Release both Shift keys on Shift up event, as when both - // are pressed the first release does not emit any event - // NOTE: The other half of this is in _glfwPlatformPollEvents - _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods); - _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods); - } - else if (wParam == VK_SNAPSHOT) - { - // HACK: Key down is not reported for the Print Screen key - _glfwInputKey(window, key, scancode, GLFW_PRESS, mods); - _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods); - } - else - _glfwInputKey(window, key, scancode, action, mods); - - break; - } - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_XBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - case WM_XBUTTONUP: - { - int i, button, action; - - if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) - button = GLFW_MOUSE_BUTTON_LEFT; - else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) - button = GLFW_MOUSE_BUTTON_RIGHT; - else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) - button = GLFW_MOUSE_BUTTON_MIDDLE; - else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) - button = GLFW_MOUSE_BUTTON_4; - else - button = GLFW_MOUSE_BUTTON_5; - - if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || - uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN) - { - action = GLFW_PRESS; - } - else - action = GLFW_RELEASE; - - for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) - { - if (window->mouseButtons[i] == GLFW_PRESS) - break; - } - - if (i > GLFW_MOUSE_BUTTON_LAST) - SetCapture(hWnd); - - _glfwInputMouseClick(window, button, action, getKeyMods()); - - for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) - { - if (window->mouseButtons[i] == GLFW_PRESS) - break; - } - - if (i > GLFW_MOUSE_BUTTON_LAST) - ReleaseCapture(); - - if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) - return TRUE; - - return 0; - } - - case WM_MOUSEMOVE: - { - const int x = GET_X_LPARAM(lParam); - const int y = GET_Y_LPARAM(lParam); - - // Disabled cursor motion input is provided by WM_INPUT - if (window->cursorMode == GLFW_CURSOR_DISABLED) - break; - - _glfwInputCursorPos(window, x, y); - - window->win32.lastCursorPosX = x; - window->win32.lastCursorPosY = y; - - if (!window->win32.cursorTracked) - { - TRACKMOUSEEVENT tme; - ZeroMemory(&tme, sizeof(tme)); - tme.cbSize = sizeof(tme); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = window->win32.handle; - TrackMouseEvent(&tme); - - window->win32.cursorTracked = GLFW_TRUE; - _glfwInputCursorEnter(window, GLFW_TRUE); - } - - return 0; - } - - case WM_INPUT: - { - UINT size; - HRAWINPUT ri = (HRAWINPUT) lParam; - RAWINPUT* data; - int dx, dy; - - // Only process input when disabled cursor mode is applied - if (_glfw.win32.disabledCursorWindow != window) - break; - - GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); - if (size > (UINT) _glfw.win32.rawInputSize) - { - free(_glfw.win32.rawInput); - _glfw.win32.rawInput = calloc(size, 1); - _glfw.win32.rawInputSize = size; - } - - size = _glfw.win32.rawInputSize; - if (GetRawInputData(ri, RID_INPUT, - _glfw.win32.rawInput, &size, - sizeof(RAWINPUTHEADER)) == (UINT) -1) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to retrieve raw input data"); - break; - } - - data = _glfw.win32.rawInput; - if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) - { - dx = data->data.mouse.lLastX - window->win32.lastCursorPosX; - dy = data->data.mouse.lLastY - window->win32.lastCursorPosY; - } - else - { - dx = data->data.mouse.lLastX; - dy = data->data.mouse.lLastY; - } - - _glfwInputCursorPos(window, - window->virtualCursorPosX + dx, - window->virtualCursorPosY + dy); - - window->win32.lastCursorPosX += dx; - window->win32.lastCursorPosY += dy; - break; - } - - case WM_MOUSELEAVE: - { - window->win32.cursorTracked = GLFW_FALSE; - _glfwInputCursorEnter(window, GLFW_FALSE); - return 0; - } - - case WM_MOUSEWHEEL: - { - _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA); - return 0; - } - - case WM_MOUSEHWHEEL: - { - // This message is only sent on Windows Vista and later - // NOTE: The X-axis is inverted for consistency with macOS and X11 - _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0); - return 0; - } - - case WM_ENTERSIZEMOVE: - case WM_ENTERMENULOOP: - { - // HACK: Postpone cursor disabling while the user is moving or - // resizing the window or using the menu - if (window->cursorMode == GLFW_CURSOR_DISABLED) - _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); - - break; - } - - case WM_EXITSIZEMOVE: - case WM_EXITMENULOOP: - { - // HACK: Disable the cursor once the user is done moving or - // resizing the window or using the menu - if (window->cursorMode == GLFW_CURSOR_DISABLED) - _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); - - break; - } - - case WM_SIZE: - { - const GLFWbool iconified = wParam == SIZE_MINIMIZED; - const GLFWbool maximized = wParam == SIZE_MAXIMIZED || - (window->win32.maximized && - wParam != SIZE_RESTORED); - - if (_glfw.win32.disabledCursorWindow == window) - updateClipRect(window); - - if (window->win32.iconified != iconified) - _glfwInputWindowIconify(window, iconified); - - if (window->win32.maximized != maximized) - _glfwInputWindowMaximize(window, maximized); - - _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam)); - _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam)); - - if (window->monitor && window->win32.iconified != iconified) - { - if (iconified) - releaseMonitor(window); - else - acquireMonitor(window); - } - - window->win32.iconified = iconified; - window->win32.maximized = maximized; - return 0; - } - - case WM_MOVE: - { - if (_glfw.win32.disabledCursorWindow == window) - updateClipRect(window); - - // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as - // those macros do not handle negative window positions correctly - _glfwInputWindowPos(window, - GET_X_LPARAM(lParam), - GET_Y_LPARAM(lParam)); - return 0; - } - - case WM_SIZING: - { - if (window->numer == GLFW_DONT_CARE || - window->denom == GLFW_DONT_CARE) - { - break; - } - - applyAspectRatio(window, (int) wParam, (RECT*) lParam); - return TRUE; - } - - case WM_GETMINMAXINFO: - { - int xoff, yoff; - MINMAXINFO* mmi = (MINMAXINFO*) lParam; - if (window->monitor) + { + // We are running in full screen mode, so disallow + // screen saver and screen blanking + return 0; + } + else break; + } - getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), - 0, 0, &xoff, &yoff); - - if (window->minwidth != GLFW_DONT_CARE && - window->minheight != GLFW_DONT_CARE) - { - mmi->ptMinTrackSize.x = window->minwidth + xoff; - mmi->ptMinTrackSize.y = window->minheight + yoff; - } - - if (window->maxwidth != GLFW_DONT_CARE && - window->maxheight != GLFW_DONT_CARE) - { - mmi->ptMaxTrackSize.x = window->maxwidth + xoff; - mmi->ptMaxTrackSize.y = window->maxheight + yoff; - } - - if (!window->decorated) - { - MONITORINFO mi; - const HMONITOR mh = MonitorFromWindow(window->win32.handle, - MONITOR_DEFAULTTONEAREST); - - ZeroMemory(&mi, sizeof(mi)); - mi.cbSize = sizeof(mi); - GetMonitorInfo(mh, &mi); - - mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left; - mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top; - mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left; - mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top; - } - + // User trying to access application menu using ALT? + case SC_KEYMENU: return 0; } + break; + } - case WM_PAINT: - { - _glfwInputWindowDamage(window); - break; - } + case WM_CLOSE: + { + _glfwInputWindowCloseRequest(window); + return 0; + } - case WM_ERASEBKGND: + case WM_INPUTLANGCHANGE: + { + _glfwUpdateKeyNamesWin32(); + break; + } + + case WM_CHAR: + case WM_SYSCHAR: + case WM_UNICHAR: + { + const GLFWbool plain = (uMsg != WM_SYSCHAR); + + if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) { + // WM_UNICHAR is not sent by Windows, but is sent by some + // third-party input method engine + // Returning TRUE here announces support for this message return TRUE; } - case WM_DWMCOMPOSITIONCHANGED: + _glfwInputChar(window, (unsigned int)wParam, getKeyMods(), plain); + return 0; + } + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + { + const int key = translateKey(wParam, lParam); + const int scancode = (lParam >> 16) & 0x1ff; + const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS; + const int mods = getKeyMods(); + + if (key == _GLFW_KEY_INVALID) + break; + + if (action == GLFW_RELEASE && wParam == VK_SHIFT) { - if (window->win32.transparent) - updateFramebufferTransparency(window); - return 0; + // HACK: Release both Shift keys on Shift up event, as when both + // are pressed the first release does not emit any event + // NOTE: The other half of this is in _glfwPlatformPollEvents + _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods); + _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods); + } + else if (wParam == VK_SNAPSHOT) + { + // HACK: Key down is not reported for the Print Screen key + _glfwInputKey(window, key, scancode, GLFW_PRESS, mods); + _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods); + } + else + _glfwInputKey(window, key, scancode, action, mods); + + break; + } + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_XBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + case WM_XBUTTONUP: + { + int i, button, action; + + if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) + button = GLFW_MOUSE_BUTTON_LEFT; + else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) + button = GLFW_MOUSE_BUTTON_RIGHT; + else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) + button = GLFW_MOUSE_BUTTON_MIDDLE; + else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) + button = GLFW_MOUSE_BUTTON_4; + else + button = GLFW_MOUSE_BUTTON_5; + + if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || + uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN) + { + action = GLFW_PRESS; + } + else + action = GLFW_RELEASE; + + for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) + { + if (window->mouseButtons[i] == GLFW_PRESS) + break; } - case WM_DPICHANGED: + if (i > GLFW_MOUSE_BUTTON_LAST) + SetCapture(hWnd); + + _glfwInputMouseClick(window, button, action, getKeyMods()); + + for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) { - const float xscale = HIWORD(wParam) / 96.f; - const float yscale = LOWORD(wParam) / 96.f; - _glfwInputWindowContentScale(window, xscale, yscale); + if (window->mouseButtons[i] == GLFW_PRESS) + break; + } + + if (i > GLFW_MOUSE_BUTTON_LAST) + ReleaseCapture(); + + if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) + return TRUE; + + return 0; + } + + case WM_MOUSEMOVE: + { + const int x = GET_X_LPARAM(lParam); + const int y = GET_Y_LPARAM(lParam); + + // Disabled cursor motion input is provided by WM_INPUT + if (window->cursorMode == GLFW_CURSOR_DISABLED) + break; + + _glfwInputCursorPos(window, x, y); + + window->win32.lastCursorPosX = x; + window->win32.lastCursorPosY = y; + + if (!window->win32.cursorTracked) + { + TRACKMOUSEEVENT tme; + ZeroMemory(&tme, sizeof(tme)); + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = window->win32.handle; + TrackMouseEvent(&tme); + + window->win32.cursorTracked = GLFW_TRUE; + _glfwInputCursorEnter(window, GLFW_TRUE); + } + + return 0; + } + + case WM_INPUT: + { + UINT size; + HRAWINPUT ri = (HRAWINPUT)lParam; + RAWINPUT* data; + int dx, dy; + + // Only process input when disabled cursor mode is applied + if (_glfw.win32.disabledCursorWindow != window) + break; + + GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); + if (size > (UINT)_glfw.win32.rawInputSize) + { + free(_glfw.win32.rawInput); + _glfw.win32.rawInput = calloc(size, 1); + _glfw.win32.rawInputSize = size; + } + + size = _glfw.win32.rawInputSize; + if (GetRawInputData(ri, RID_INPUT, + _glfw.win32.rawInput, &size, + sizeof(RAWINPUTHEADER)) == (UINT)-1) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Win32: Failed to retrieve raw input data"); break; } - case WM_SETCURSOR: + data = _glfw.win32.rawInput; + if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { - if (LOWORD(lParam) == HTCLIENT) - { - updateCursorImage(window); - return TRUE; - } + dx = data->data.mouse.lLastX - window->win32.lastCursorPosX; + dy = data->data.mouse.lLastY - window->win32.lastCursorPosY; + } + else + { + dx = data->data.mouse.lLastX; + dy = data->data.mouse.lLastY; + } + _glfwInputCursorPos(window, + window->virtualCursorPosX + dx, + window->virtualCursorPosY + dy); + + window->win32.lastCursorPosX += dx; + window->win32.lastCursorPosY += dy; + break; + } + + case WM_MOUSELEAVE: + { + window->win32.cursorTracked = GLFW_FALSE; + _glfwInputCursorEnter(window, GLFW_FALSE); + return 0; + } + + case WM_MOUSEWHEEL: + { + _glfwInputScroll(window, 0.0, (SHORT)HIWORD(wParam) / (double)WHEEL_DELTA); + return 0; + } + + case WM_MOUSEHWHEEL: + { + // This message is only sent on Windows Vista and later + // NOTE: The X-axis is inverted for consistency with macOS and X11 + _glfwInputScroll(window, -((SHORT)HIWORD(wParam) / (double)WHEEL_DELTA), 0.0); + return 0; + } + + case WM_ENTERSIZEMOVE: + case WM_ENTERMENULOOP: + { + // HACK: Postpone cursor disabling while the user is moving or + // resizing the window or using the menu + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); + + break; + } + + case WM_EXITSIZEMOVE: + case WM_EXITMENULOOP: + { + // HACK: Disable the cursor once the user is done moving or + // resizing the window or using the menu + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); + + break; + } + + case WM_SIZE: + { + const GLFWbool iconified = wParam == SIZE_MINIMIZED; + const GLFWbool maximized = wParam == SIZE_MAXIMIZED || + (window->win32.maximized && + wParam != SIZE_RESTORED); + + if (_glfw.win32.disabledCursorWindow == window) + updateClipRect(window); + + if (window->win32.iconified != iconified) + _glfwInputWindowIconify(window, iconified); + + if (window->win32.maximized != maximized) + _glfwInputWindowMaximize(window, maximized); + + _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam)); + _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam)); + + if (window->monitor && window->win32.iconified != iconified) + { + if (iconified) + releaseMonitor(window); + else + acquireMonitor(window); + } + + window->win32.iconified = iconified; + window->win32.maximized = maximized; + return 0; + } + + case WM_MOVE: + { + if (_glfw.win32.disabledCursorWindow == window) + updateClipRect(window); + + // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as + // those macros do not handle negative window positions correctly + _glfwInputWindowPos(window, + GET_X_LPARAM(lParam), + GET_Y_LPARAM(lParam)); + return 0; + } + + case WM_SIZING: + { + if (window->numer == GLFW_DONT_CARE || + window->denom == GLFW_DONT_CARE) + { break; } - case WM_DROPFILES: + applyAspectRatio(window, (int)wParam, (RECT*)lParam); + return TRUE; + } + + case WM_GETMINMAXINFO: + { + int xoff, yoff; + MINMAXINFO* mmi = (MINMAXINFO*)lParam; + + if (window->monitor) + break; + + getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), + 0, 0, &xoff, &yoff); + + if (window->minwidth != GLFW_DONT_CARE && + window->minheight != GLFW_DONT_CARE) { - HDROP drop = (HDROP) wParam; - POINT pt; - int i; - - const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0); - char** paths = calloc(count, sizeof(char*)); - - // Move the mouse to the position of the drop - DragQueryPoint(drop, &pt); - _glfwInputCursorPos(window, pt.x, pt.y); - - for (i = 0; i < count; i++) - { - const UINT length = DragQueryFileW(drop, i, NULL, 0); - WCHAR* buffer = calloc(length + 1, sizeof(WCHAR)); - - DragQueryFileW(drop, i, buffer, length + 1); - paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer); - - free(buffer); - } - - _glfwInputDrop(window, count, (const char**) paths); - - for (i = 0; i < count; i++) - free(paths[i]); - free(paths); - - DragFinish(drop); - return 0; + mmi->ptMinTrackSize.x = window->minwidth + xoff; + mmi->ptMinTrackSize.y = window->minheight + yoff; } + + if (window->maxwidth != GLFW_DONT_CARE && + window->maxheight != GLFW_DONT_CARE) + { + mmi->ptMaxTrackSize.x = window->maxwidth + xoff; + mmi->ptMaxTrackSize.y = window->maxheight + yoff; + } + + if (!window->decorated) + { + MONITORINFO mi; + const HMONITOR mh = MonitorFromWindow(window->win32.handle, + MONITOR_DEFAULTTONEAREST); + + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + GetMonitorInfo(mh, &mi); + + mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left; + mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top; + mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left; + mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top; + } + + return 0; + } + + case WM_PAINT: + { + _glfwInputWindowDamage(window); + break; + } + + case WM_ERASEBKGND: + { + return TRUE; + } + + case WM_DWMCOMPOSITIONCHANGED: + { + if (window->win32.transparent) + updateFramebufferTransparency(window); + return 0; + } + + case WM_DPICHANGED: + { + const float xscale = HIWORD(wParam) / 96.f; + const float yscale = LOWORD(wParam) / 96.f; + _glfwInputWindowContentScale(window, xscale, yscale); + break; + } + + case WM_SETCURSOR: + { + if (LOWORD(lParam) == HTCLIENT) + { + updateCursorImage(window); + return TRUE; + } + + break; + } + + case WM_DROPFILES: + { + HDROP drop = (HDROP)wParam; + POINT pt; + int i; + + const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0); + char** paths = calloc(count, sizeof(char*)); + + // Move the mouse to the position of the drop + DragQueryPoint(drop, &pt); + _glfwInputCursorPos(window, pt.x, pt.y); + + for (i = 0; i < count; i++) + { + const UINT length = DragQueryFileW(drop, i, NULL, 0); + WCHAR* buffer = calloc(length + 1, sizeof(WCHAR)); + + DragQueryFileW(drop, i, buffer, length + 1); + paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer); + + free(buffer); + } + + _glfwInputDrop(window, count, (const char**)paths); + + for (i = 0; i < count; i++) + free(paths[i]); + free(paths); + + DragFinish(drop); + return 0; + } } return DefWindowProcW(hWnd, uMsg, wParam, lParam); @@ -1056,8 +1119,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // Creates the GLFW window // static int createNativeWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { int xpos, ypos, fullWidth, fullHeight; WCHAR* wideTitle; @@ -1073,7 +1136,7 @@ static int createNativeWindow(_GLFWwindow* window, // video mode has been picked in _glfwSetVideoModeWin32 _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); _glfwPlatformGetVideoMode(window->monitor, &mode); - fullWidth = mode.width; + fullWidth = mode.width; fullHeight = mode.height; } else @@ -1085,8 +1148,8 @@ static int createNativeWindow(_GLFWwindow* window, style |= WS_MAXIMIZE; getFullWindowSize(style, exStyle, - wndconfig->width, wndconfig->height, - &fullWidth, &fullHeight); + wndconfig->width, wndconfig->height, + &fullWidth, &fullHeight); } wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); @@ -1094,22 +1157,22 @@ static int createNativeWindow(_GLFWwindow* window, return GLFW_FALSE; window->win32.handle = CreateWindowExW(exStyle, - _GLFW_WNDCLASSNAME, - wideTitle, - style, - xpos, ypos, - fullWidth, fullHeight, - NULL, // No parent window - NULL, // No window menu - GetModuleHandleW(NULL), - NULL); + _GLFW_WNDCLASSNAME, + wideTitle, + style, + xpos, ypos, + fullWidth, fullHeight, + NULL, // No parent window + NULL, // No window menu + GetModuleHandleW(NULL), + NULL); free(wideTitle); if (!window->win32.handle) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to create window"); + "Win32: Failed to create window"); return GLFW_FALSE; } @@ -1118,11 +1181,11 @@ static int createNativeWindow(_GLFWwindow* window, if (IsWindows7OrGreater()) { ChangeWindowMessageFilterEx(window->win32.handle, - WM_DROPFILES, MSGFLT_ALLOW, NULL); + WM_DROPFILES, MSGFLT_ALLOW, NULL); ChangeWindowMessageFilterEx(window->win32.handle, - WM_COPYDATA, MSGFLT_ALLOW, NULL); + WM_COPYDATA, MSGFLT_ALLOW, NULL); ChangeWindowMessageFilterEx(window->win32.handle, - WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL); + WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL); } DragAcceptFiles(window->win32.handle, TRUE); @@ -1148,29 +1211,29 @@ GLFWbool _glfwRegisterWindowClassWin32(void) WNDCLASSEXW wc; ZeroMemory(&wc, sizeof(wc)); - wc.cbSize = sizeof(wc); - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wc.lpfnWndProc = (WNDPROC) windowProc; - wc.hInstance = GetModuleHandleW(NULL); - wc.hCursor = LoadCursorW(NULL, IDC_ARROW); + wc.cbSize = sizeof(wc); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)windowProc; + wc.hInstance = GetModuleHandleW(NULL); + wc.hCursor = LoadCursorW(NULL, IDC_ARROW); wc.lpszClassName = _GLFW_WNDCLASSNAME; // Load user-provided icon if available wc.hIcon = LoadImageW(GetModuleHandleW(NULL), - L"GLFW_ICON", IMAGE_ICON, - 0, 0, LR_DEFAULTSIZE | LR_SHARED); + L"GLFW_ICON", IMAGE_ICON, + 0, 0, LR_DEFAULTSIZE | LR_SHARED); if (!wc.hIcon) { // No user-provided icon found, load default icon wc.hIcon = LoadImageW(NULL, - IDI_APPLICATION, IMAGE_ICON, - 0, 0, LR_DEFAULTSIZE | LR_SHARED); + IDI_APPLICATION, IMAGE_ICON, + 0, 0, LR_DEFAULTSIZE | LR_SHARED); } if (!RegisterClassExW(&wc)) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to register window class"); + "Win32: Failed to register window class"); return GLFW_FALSE; } @@ -1204,9 +1267,9 @@ GLFWbool _glfwIsCompositionEnabledWin32(void) ////////////////////////////////////////////////////////////////////////// int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) { if (!createNativeWindow(window, wndconfig, fbconfig)) return GLFW_FALSE; @@ -1286,30 +1349,30 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) } void _glfwPlatformSetWindowIcon(_GLFWwindow* window, - int count, const GLFWimage* images) + int count, const GLFWimage* images) { HICON bigIcon = NULL, smallIcon = NULL; if (count) { const GLFWimage* bigImage = chooseImage(count, images, - GetSystemMetrics(SM_CXICON), - GetSystemMetrics(SM_CYICON)); + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON)); const GLFWimage* smallImage = chooseImage(count, images, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON)); + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON)); bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE); smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE); } else { - bigIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICON); - smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM); + bigIcon = (HICON)GetClassLongPtrW(window->win32.handle, GCLP_HICON); + smallIcon = (HICON)GetClassLongPtrW(window->win32.handle, GCLP_HICONSM); } - SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon); - SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon); + SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM)bigIcon); + SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM)smallIcon); if (window->win32.bigIcon) DestroyIcon(window->win32.bigIcon); @@ -1339,9 +1402,9 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) { RECT rect = { xpos, ypos, xpos, ypos }; AdjustWindowRectEx(&rect, getWindowStyle(window), - FALSE, getWindowExStyle(window)); + FALSE, getWindowExStyle(window)); SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); } void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) @@ -1366,16 +1429,16 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { RECT rect = { 0, 0, width, height }; AdjustWindowRectEx(&rect, getWindowStyle(window), - FALSE, getWindowExStyle(window)); + FALSE, getWindowExStyle(window)); SetWindowPos(window->win32.handle, HWND_TOP, - 0, 0, rect.right - rect.left, rect.bottom - rect.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER); + 0, 0, rect.right - rect.left, rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER); } } void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight) + int minwidth, int minheight, + int maxwidth, int maxheight) { RECT area; @@ -1387,9 +1450,9 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, GetWindowRect(window->win32.handle, &area); MoveWindow(window->win32.handle, - area.left, area.top, - area.right - area.left, - area.bottom - area.top, TRUE); + area.left, area.top, + area.right - area.left, + area.bottom - area.top, TRUE); } void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) @@ -1402,9 +1465,9 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom GetWindowRect(window->win32.handle, &area); applyAspectRatio(window, WMSZ_BOTTOMRIGHT, &area); MoveWindow(window->win32.handle, - area.left, area.top, - area.right - area.left, - area.bottom - area.top, TRUE); + area.left, area.top, + area.right - area.left, + area.bottom - area.top, TRUE); } void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) @@ -1413,8 +1476,8 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh } void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom) + int* left, int* top, + int* right, int* bottom) { RECT rect; int width, height; @@ -1422,7 +1485,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, _glfwPlatformGetWindowSize(window, &width, &height); SetRect(&rect, 0, 0, width, height); AdjustWindowRectEx(&rect, getWindowStyle(window), - FALSE, getWindowExStyle(window)); + FALSE, getWindowExStyle(window)); if (left) *left = -rect.left; @@ -1435,10 +1498,10 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, } void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale) + float* xscale, float* yscale) { const HANDLE handle = MonitorFromWindow(window->win32.handle, - MONITOR_DEFAULTTONEAREST); + MONITOR_DEFAULTTONEAREST); _glfwGetMonitorContentScaleWin32(handle, xscale, yscale); } @@ -1480,10 +1543,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) } void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, - _GLFWmonitor* monitor, - int xpos, int ypos, - int width, int height, - int refreshRate) + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) { if (window->monitor == monitor) { @@ -1496,11 +1559,11 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, { RECT rect = { xpos, ypos, xpos + width, ypos + height }; AdjustWindowRectEx(&rect, getWindowStyle(window), - FALSE, getWindowExStyle(window)); + FALSE, getWindowExStyle(window)); SetWindowPos(window->win32.handle, HWND_TOP, - rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, - SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER); + rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER); } return; @@ -1517,8 +1580,8 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, { DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE); UINT flags = SWP_FRAMECHANGED | SWP_SHOWWINDOW | - SWP_NOACTIVATE | SWP_NOCOPYBITS | - SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE; + SWP_NOACTIVATE | SWP_NOCOPYBITS | + SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE; style &= ~WS_OVERLAPPEDWINDOW; style |= getWindowStyle(window); @@ -1550,11 +1613,11 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, after = HWND_NOTOPMOST; AdjustWindowRectEx(&rect, getWindowStyle(window), - FALSE, getWindowExStyle(window)); + FALSE, getWindowExStyle(window)); SetWindowPos(window->win32.handle, after, - rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, - flags); + rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + flags); } } @@ -1602,7 +1665,7 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) { const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST; SetWindowPos(window->win32.handle, after, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) @@ -1624,7 +1687,7 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) { if (opacity < 1.f) { - const BYTE alpha = (BYTE) (255 * opacity); + const BYTE alpha = (BYTE)(255 * opacity); DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); style |= WS_EX_LAYERED; SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style); @@ -1719,7 +1782,7 @@ void _glfwPlatformWaitEvents(void) void _glfwPlatformWaitEventsTimeout(double timeout) { - MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS); + MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD)(timeout * 1e3), QS_ALLEVENTS); _glfwPlatformPollEvents(); } @@ -1746,7 +1809,7 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) { - POINT pos = { (int) xpos, (int) ypos }; + POINT pos = { (int)xpos, (int)ypos }; // Store the new position so it can be recognized later window->win32.lastCursorPosX = pos.x; @@ -1764,15 +1827,15 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) _glfw.win32.disabledCursorWindow = window; _glfwPlatformGetCursorPos(window, - &_glfw.win32.restoreCursorPosX, - &_glfw.win32.restoreCursorPosY); + &_glfw.win32.restoreCursorPosX, + &_glfw.win32.restoreCursorPosY); centerCursor(window); updateClipRect(window); if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to register raw input device"); + "Win32: Failed to register raw input device"); } } else if (_glfw.win32.disabledCursorWindow == window) @@ -1782,13 +1845,13 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) _glfw.win32.disabledCursorWindow = NULL; updateClipRect(NULL); _glfwPlatformSetCursorPos(window, - _glfw.win32.restoreCursorPosX, - _glfw.win32.restoreCursorPosY); + _glfw.win32.restoreCursorPosX, + _glfw.win32.restoreCursorPosY); if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to remove raw input device"); + "Win32: Failed to remove raw input device"); } } @@ -1807,10 +1870,10 @@ int _glfwPlatformGetKeyScancode(int key) } int _glfwPlatformCreateCursor(_GLFWcursor* cursor, - const GLFWimage* image, - int xhot, int yhot) + const GLFWimage* image, + int xhot, int yhot) { - cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE); + cursor->win32.handle = (HCURSOR)createIcon(image, xhot, yhot, GLFW_FALSE); if (!cursor->win32.handle) return GLFW_FALSE; @@ -1824,7 +1887,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) if (!cursor->win32.handle) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to create standard cursor"); + "Win32: Failed to create standard cursor"); return GLFW_FALSE; } @@ -1834,7 +1897,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) { if (cursor->win32.handle) - DestroyIcon((HICON) cursor->win32.handle); + DestroyIcon((HICON)cursor->win32.handle); } void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) @@ -1857,7 +1920,7 @@ void _glfwPlatformSetClipboardString(const char* string) if (!object) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to allocate global handle for clipboard"); + "Win32: Failed to allocate global handle for clipboard"); return; } @@ -1865,7 +1928,7 @@ void _glfwPlatformSetClipboardString(const char* string) if (!buffer) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to lock global handle"); + "Win32: Failed to lock global handle"); GlobalFree(object); return; } @@ -1876,7 +1939,7 @@ void _glfwPlatformSetClipboardString(const char* string) if (!OpenClipboard(_glfw.win32.helperWindowHandle)) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to open clipboard"); + "Win32: Failed to open clipboard"); GlobalFree(object); return; } @@ -1894,7 +1957,7 @@ const char* _glfwPlatformGetClipboardString(void) if (!OpenClipboard(_glfw.win32.helperWindowHandle)) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to open clipboard"); + "Win32: Failed to open clipboard"); return NULL; } @@ -1902,7 +1965,7 @@ const char* _glfwPlatformGetClipboardString(void) if (!object) { _glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE, - "Win32: Failed to convert clipboard to string"); + "Win32: Failed to convert clipboard to string"); CloseClipboard(); return NULL; } @@ -1911,7 +1974,7 @@ const char* _glfwPlatformGetClipboardString(void) if (!buffer) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to lock global handle"); + "Win32: Failed to lock global handle"); CloseClipboard(); return NULL; } @@ -1935,8 +1998,8 @@ void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) } int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, - VkPhysicalDevice device, - uint32_t queuefamily) + VkPhysicalDevice device, + uint32_t queuefamily) { PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR = @@ -1945,7 +2008,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, if (!vkGetPhysicalDeviceWin32PresentationSupportKHR) { _glfwInputError(GLFW_API_UNAVAILABLE, - "Win32: Vulkan instance missing VK_KHR_win32_surface extension"); + "Win32: Vulkan instance missing VK_KHR_win32_surface extension"); return GLFW_FALSE; } @@ -1953,9 +2016,9 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, } VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface) + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) { VkResult err; VkWin32SurfaceCreateInfoKHR sci; @@ -1966,7 +2029,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, if (!vkCreateWin32SurfaceKHR) { _glfwInputError(GLFW_API_UNAVAILABLE, - "Win32: Vulkan instance missing VK_KHR_win32_surface extension"); + "Win32: Vulkan instance missing VK_KHR_win32_surface extension"); return VK_ERROR_EXTENSION_NOT_PRESENT; } @@ -1979,8 +2042,8 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, if (err) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to create Vulkan surface: %s", - _glfwGetVulkanResultString(err)); + "Win32: Failed to create Vulkan surface: %s", + _glfwGetVulkanResultString(err)); } return err; @@ -1993,7 +2056,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow* window = (_GLFWwindow*)handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return window->win32.handle; } diff --git a/src/window.c b/src/window.c index e7352f472..5949c37fd 100644 --- a/src/window.c +++ b/src/window.c @@ -27,7 +27,6 @@ //======================================================================== #include "internal.h" - #include #include #include diff --git a/tests/events.c b/tests/events.c index 094ea5f9b..d12d9a8ae 100644 --- a/tests/events.c +++ b/tests/events.c @@ -354,6 +354,17 @@ static void mouse_button_callback(GLFWwindow* window, int button, int action, in get_action_name(action)); } +static void pen_callback(GLFWwindow* window, double pressure, int x, int y) +{ + Slot* slot = glfwGetWindowUserPointer(window); + printf("%08x to %i at %0.3f: Pen position: %i %i Pressure: %f\n", + counter++, slot->number, glfwGetTime(), x, y, pressure); + /* + fprintf(stderr, "pressure -- %f --\n", pressure); + fprintf(stderr, "xPosition -- %d --\n", x); + fprintf(stderr, "yPosition -- %d --\n", y);*/ +} + static void cursor_position_callback(GLFWwindow* window, double x, double y) { Slot* slot = glfwGetWindowUserPointer(window); @@ -613,6 +624,7 @@ int main(int argc, char** argv) glfwSetWindowIconifyCallback(slots[i].window, window_iconify_callback); glfwSetWindowMaximizeCallback(slots[i].window, window_maximize_callback); glfwSetMouseButtonCallback(slots[i].window, mouse_button_callback); + glfwSetPenPressureCallback(slots[i].window, pen_callback); glfwSetCursorPosCallback(slots[i].window, cursor_position_callback); glfwSetCursorEnterCallback(slots[i].window, cursor_enter_callback); glfwSetScrollCallback(slots[i].window, scroll_callback); diff --git a/tests/opacity.c b/tests/opacity.c index 4a615ae6a..3176c9ff9 100644 --- a/tests/opacity.c +++ b/tests/opacity.c @@ -1,106 +1,106 @@ -//======================================================================== -// Window opacity test program -// Copyright (c) Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#include -#include - -#define NK_IMPLEMENTATION -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_STANDARD_VARARGS -#include - -#define NK_GLFW_GL2_IMPLEMENTATION -#include - -#include -#include - -static void error_callback(int error, const char* description) -{ - fprintf(stderr, "Error: %s\n", description); -} - -int main(int argc, char** argv) -{ - GLFWmonitor* monitor = NULL; - GLFWwindow* window; - struct nk_context* nk; - struct nk_font_atlas* atlas; - - glfwSetErrorCallback(error_callback); - - if (!glfwInit()) - exit(EXIT_FAILURE); - - window = glfwCreateWindow(400, 400, "Opacity", NULL, NULL); - if (!window) - { - glfwTerminate(); - exit(EXIT_FAILURE); - } - - glfwMakeContextCurrent(window); - gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); - glfwSwapInterval(1); - - nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS); - nk_glfw3_font_stash_begin(&atlas); - nk_glfw3_font_stash_end(); - - while (!glfwWindowShouldClose(window)) - { - int width, height; - struct nk_rect area; - - glfwGetWindowSize(window, &width, &height); - area = nk_rect(0.f, 0.f, (float) width, (float) height); - - glClear(GL_COLOR_BUFFER_BIT); - nk_glfw3_new_frame(); - if (nk_begin(nk, "", area, 0)) - { - float opacity = glfwGetWindowOpacity(window); - nk_layout_row_dynamic(nk, 30, 2); - if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f)) - glfwSetWindowOpacity(window, opacity); - nk_labelf(nk, NK_TEXT_LEFT, "%0.3f", opacity); - } - - nk_end(nk); - nk_glfw3_render(NK_ANTI_ALIASING_ON); - - glfwSwapBuffers(window); - glfwWaitEventsTimeout(1.0); - } - - nk_glfw3_shutdown(); - glfwTerminate(); - exit(EXIT_SUCCESS); -} - +//======================================================================== +// Window opacity test program +// Copyright (c) Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include +#include + +#define NK_IMPLEMENTATION +#define NK_INCLUDE_FIXED_TYPES +#define NK_INCLUDE_FONT_BAKING +#define NK_INCLUDE_DEFAULT_FONT +#define NK_INCLUDE_DEFAULT_ALLOCATOR +#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT +#define NK_INCLUDE_STANDARD_VARARGS +#include + +#define NK_GLFW_GL2_IMPLEMENTATION +#include + +#include +#include + +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + +int main(int argc, char** argv) +{ + GLFWmonitor* monitor = NULL; + GLFWwindow* window; + struct nk_context* nk; + struct nk_font_atlas* atlas; + + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + exit(EXIT_FAILURE); + + window = glfwCreateWindow(400, 400, "Opacity", NULL, NULL); + if (!window) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + + glfwMakeContextCurrent(window); + gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); + glfwSwapInterval(1); + + nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS); + nk_glfw3_font_stash_begin(&atlas); + nk_glfw3_font_stash_end(); + + while (!glfwWindowShouldClose(window)) + { + int width, height; + struct nk_rect area; + + glfwGetWindowSize(window, &width, &height); + area = nk_rect(0.f, 0.f, (float) width, (float) height); + + glClear(GL_COLOR_BUFFER_BIT); + nk_glfw3_new_frame(); + if (nk_begin(nk, "", area, 0)) + { + float opacity = glfwGetWindowOpacity(window); + nk_layout_row_dynamic(nk, 30, 2); + if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f)) + glfwSetWindowOpacity(window, opacity); + nk_labelf(nk, NK_TEXT_LEFT, "%0.3f", opacity); + } + + nk_end(nk); + nk_glfw3_render(NK_ANTI_ALIASING_ON); + + glfwSwapBuffers(window); + glfwWaitEventsTimeout(1.0); + } + + nk_glfw3_shutdown(); + glfwTerminate(); + exit(EXIT_SUCCESS); +} +