From 8acb72b9a19153d1b80c07522566f43c021d72ce Mon Sep 17 00:00:00 2001 From: GamesTrap Date: Sat, 23 Jul 2022 21:28:35 +0200 Subject: [PATCH] Win32 Added support for taskbar progress --- include/GLFW/glfw3.h | 8 ++++++++ src/cocoa_init.m | 1 + src/cocoa_platform.h | 1 + src/cocoa_window.m | 6 ++++++ src/internal.h | 1 + src/null_init.c | 1 + src/null_platform.h | 1 + src/null_window.c | 4 ++++ src/win32_init.c | 1 + src/win32_platform.h | 5 +++++ src/win32_window.c | 36 ++++++++++++++++++++++++++++++++++++ src/window.c | 30 ++++++++++++++++++++++++++++++ src/wl_init.c | 1 + src/wl_platform.h | 1 + src/wl_window.c | 6 ++++++ src/x11_init.c | 1 + src/x11_platform.h | 1 + src/x11_window.c | 5 +++++ tests/window.c | 23 ++++++++++++++++++++++- 19 files changed, 132 insertions(+), 1 deletion(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index aa6ddc33..d401fcbc 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1251,6 +1251,12 @@ extern "C" { #define GLFW_HAND_CURSOR GLFW_POINTING_HAND_CURSOR /*! @} */ +#define GLFW_TASKBAR_PROGRESS_NOPROGRESS 0x00 +#define GLFW_TASKBAR_PROGRESS_INDETERMINATE 0x01 +#define GLFW_TASKBAR_PROGRESS_NORMAL 0x02 +#define GLFW_TASKBAR_PROGRESS_ERROR 0x04 +#define GLFW_TASKBAR_PROGRESS_PAUSED 0x08 + #define GLFW_CONNECTED 0x00040001 #define GLFW_DISCONNECTED 0x00040002 @@ -3283,6 +3289,8 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); */ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); +GLFWAPI void glfwSetWindowTaskbarProgress(GLFWwindow* window, const int progressState, int completed); + /*! @brief Retrieves the position of the content area of the specified window. * * This function retrieves the position, in screen coordinates, of the diff --git a/src/cocoa_init.m b/src/cocoa_init.m index aa369f9c..07ff3fc6 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -525,6 +525,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) _glfwDestroyWindowCocoa, _glfwSetWindowTitleCocoa, _glfwSetWindowIconCocoa, + _glfwSetWindowTaskbarProgressCocoa, _glfwGetWindowPosCocoa, _glfwSetWindowPosCocoa, _glfwGetWindowSizeCocoa, diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 9f7d191d..936843ad 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -218,6 +218,7 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, const _GLFWwndconfig* wndco void _glfwDestroyWindowCocoa(_GLFWwindow* window); void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title); void _glfwSetWindowIconCocoa(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowTaskbarProgressCocoa(_GLFWwindow* window, const int taskbarState, int completed); void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos); void _glfwSetWindowPosCocoa(_GLFWwindow* window, int xpos, int ypos); void _glfwGetWindowSizeCocoa(_GLFWwindow* window, int* width, int* height); diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 5bb1289b..abb5634a 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1014,6 +1014,12 @@ void _glfwSetWindowIconCocoa(_GLFWwindow* window, "Cocoa: Regular windows do not have icons on macOS"); } +void _glfwSetWindowTaskbarProgress(_GLFWwindow* window, const int progressState, int completed) +{ + _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, + "Cocoa: Window taskbar progress is not implemented"); +} + void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos) { @autoreleasepool { diff --git a/src/internal.h b/src/internal.h index 89a18628..a25629f8 100644 --- a/src/internal.h +++ b/src/internal.h @@ -708,6 +708,7 @@ struct _GLFWplatform void (*destroyWindow)(_GLFWwindow*); void (*setWindowTitle)(_GLFWwindow*,const char*); void (*setWindowIcon)(_GLFWwindow*,int,const GLFWimage*); + void (*setWindowTaskbarProgress)(_GLFWwindow*,const int,int); void (*getWindowPos)(_GLFWwindow*,int*,int*); void (*setWindowPos)(_GLFWwindow*,int,int); void (*getWindowSize)(_GLFWwindow*,int*,int*); diff --git a/src/null_init.c b/src/null_init.c index de4b28f3..d3d8c8cb 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -73,6 +73,7 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) _glfwDestroyWindowNull, _glfwSetWindowTitleNull, _glfwSetWindowIconNull, + _glfwSetWindowTaskbarProgressNull, _glfwGetWindowPosNull, _glfwSetWindowPosNull, _glfwGetWindowSizeNull, diff --git a/src/null_platform.h b/src/null_platform.h index b646acb3..348ded2e 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -89,6 +89,7 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window, const _GLFWwndconfig* wndcon void _glfwDestroyWindowNull(_GLFWwindow* window); void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title); void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowTaskbarProgressNull(_GLFWwindow* window, const int taskbarState, int completed); void _glfwSetWindowMonitorNull(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); void _glfwGetWindowPosNull(_GLFWwindow* window, int* xpos, int* ypos); void _glfwSetWindowPosNull(_GLFWwindow* window, int xpos, int ypos); diff --git a/src/null_window.c b/src/null_window.c index 8a7cae41..128ae5a2 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -178,6 +178,10 @@ void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* ima { } +void _glfwSetWindowTaskbarProgressNull(_GLFWwindow* window, const int progressState, int completed) +{ +} + void _glfwSetWindowMonitorNull(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/win32_init.c b/src/win32_init.c index 8704150c..e8a11c99 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -636,6 +636,7 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) _glfwDestroyWindowWin32, _glfwSetWindowTitleWin32, _glfwSetWindowIconWin32, + _glfwSetWindowTaskbarProgressWin32, _glfwGetWindowPosWin32, _glfwSetWindowPosWin32, _glfwGetWindowSizeWin32, diff --git a/src/win32_platform.h b/src/win32_platform.h index c2158943..c5316149 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -69,6 +69,7 @@ #include #include #include +#include // HACK: Define macros that some windows.h variants don't #ifndef WM_MOUSEHWHEEL @@ -432,6 +433,9 @@ typedef struct _GLFWwindowWin32 int lastCursorPosX, lastCursorPosY; // The last received high surrogate when decoding pairs of UTF-16 messages WCHAR highSurrogate; + + ITaskbarList3* TaskbarList; + UINT TaskbarListMsgID; } _GLFWwindowWin32; // Win32-specific global data @@ -541,6 +545,7 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window, const _GLFWwndconfig* wndco void _glfwDestroyWindowWin32(_GLFWwindow* window); void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title); void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowTaskbarProgressWin32(_GLFWwindow* window, const int taskbarState, int completed); void _glfwGetWindowPosWin32(_GLFWwindow* window, int* xpos, int* ypos); void _glfwSetWindowPosWin32(_GLFWwindow* window, int xpos, int ypos); void _glfwGetWindowSizeWin32(_GLFWwindow* window, int* width, int* height); diff --git a/src/win32_window.c b/src/win32_window.c index 168529e2..2fda5454 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1239,6 +1239,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } } + if(uMsg == window->win32.TaskbarListMsgID) + { + HRESULT res = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskbarList3, (LPVOID*)&window->win32.TaskbarList); + if (res != S_OK && window->win32.TaskbarList) + window->win32.TaskbarList->lpVtbl->Release(window->win32.TaskbarList); + else + { + window->win32.TaskbarList->lpVtbl->AddRef(window->win32.TaskbarList); + window->win32.TaskbarList->lpVtbl->HrInit(window->win32.TaskbarList); + } + } + return DefWindowProcW(hWnd, uMsg, wParam, lParam); } @@ -1348,6 +1360,10 @@ static int createNativeWindow(_GLFWwindow* window, WM_COPYDATA, MSGFLT_ALLOW, NULL); ChangeWindowMessageFilterEx(window->win32.handle, WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL); + + window->win32.TaskbarListMsgID = RegisterWindowMessageW(L"TaskbarButtonCreated"); + if (window->win32.TaskbarListMsgID) + ChangeWindowMessageFilterEx(window->win32.handle, window->win32.TaskbarListMsgID, MSGFLT_ALLOW, NULL); } window->win32.scaleToMonitor = wndconfig->scaleToMonitor; @@ -1497,6 +1513,9 @@ void _glfwDestroyWindowWin32(_GLFWwindow* window) if (_glfw.win32.disabledCursorWindow == window) _glfw.win32.disabledCursorWindow = NULL; + if (window->win32.TaskbarList) + window->win32.TaskbarList->lpVtbl->Release(window->win32.TaskbarList); + if (window->win32.handle) { RemovePropW(window->win32.handle, L"GLFW"); @@ -1559,6 +1578,23 @@ void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* im } } +void _glfwSetWindowTaskbarProgressWin32(_GLFWwindow* window, const int progressState, int completed) +{ + if(!window->win32.TaskbarList) + return; + + HRESULT res = window->win32.TaskbarList->lpVtbl->SetProgressValue(window->win32.TaskbarList, window->win32.handle, completed, 100); + if(res != S_OK) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar progress value"); + return; + } + + res = window->win32.TaskbarList->lpVtbl->SetProgressState(window->win32.TaskbarList, window->win32.handle, progressState); + if (res != S_OK) + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar progress state"); +} + void _glfwGetWindowPosWin32(_GLFWwindow* window, int* xpos, int* ypos) { POINT pos = { 0, 0 }; diff --git a/src/window.c b/src/window.c index ebbc6dca..11406824 100644 --- a/src/window.c +++ b/src/window.c @@ -546,6 +546,36 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, _glfw.platform.setWindowIcon(window, count, images); } +GLFWAPI void glfwSetWindowTaskbarProgress(GLFWwindow* handle, const int progressState, int completed) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + + assert(window != NULL); + assert(completed >= 0); + assert(completed <= 100); + + if (completed < 0) + { + _glfwInputError(GLFW_INVALID_VALUE, "Invalid progress amount for window taskbar progress"); + return; + } + else if (completed > 100) + { + _glfwInputError(GLFW_INVALID_VALUE, "Invalid progress amount for window taskbar progress"); + return; + } + + if (progressState != GLFW_TASKBAR_PROGRESS_NOPROGRESS && progressState != GLFW_TASKBAR_PROGRESS_INDETERMINATE && + progressState != GLFW_TASKBAR_PROGRESS_NORMAL && progressState != GLFW_TASKBAR_PROGRESS_ERROR && + progressState != GLFW_TASKBAR_PROGRESS_PAUSED) + { + _glfwInputError(GLFW_INVALID_ENUM, "Invalid progress state 0x%08X", progressState); + return; + } + + _glfw.platform.setWindowTaskbarProgress(window, progressState, completed); +} + GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/wl_init.c b/src/wl_init.c index 8cbcc6e8..d4278c75 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -417,6 +417,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) _glfwDestroyWindowWayland, _glfwSetWindowTitleWayland, _glfwSetWindowIconWayland, + _glfwSetWindowTaskbarProgressWayland, _glfwGetWindowPosWayland, _glfwSetWindowPosWayland, _glfwGetWindowSizeWayland, diff --git a/src/wl_platform.h b/src/wl_platform.h index f65bcb11..1176c75c 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -446,6 +446,7 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWwndconfig* wnd void _glfwDestroyWindowWayland(_GLFWwindow* window); void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title); void _glfwSetWindowIconWayland(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowTaskbarProgressWayland(_GLFWwindow* window, const int taskbarState, int completed); void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos); void _glfwSetWindowPosWayland(_GLFWwindow* window, int xpos, int ypos); void _glfwGetWindowSizeWayland(_GLFWwindow* window, int* width, int* height); diff --git a/src/wl_window.c b/src/wl_window.c index ef935d33..9b5b4363 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1885,6 +1885,12 @@ void _glfwSetWindowIconWayland(_GLFWwindow* window, "Wayland: The platform does not support setting the window icon"); } +void _glfwSetWindowTaskbarProgress(_GLFWwindow* window, const int progressState, int completed) +{ + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Wayland: The platform does not support setting the window taskbar progress"); +} + void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos) { // A Wayland client is not aware of its position, so just warn and leave it diff --git a/src/x11_init.c b/src/x11_init.c index 11aeb9e5..29c32794 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -1207,6 +1207,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) _glfwDestroyWindowX11, _glfwSetWindowTitleX11, _glfwSetWindowIconX11, + _glfwSetWindowTaskbarProgressX11, _glfwGetWindowPosX11, _glfwSetWindowPosX11, _glfwGetWindowSizeX11, diff --git a/src/x11_platform.h b/src/x11_platform.h index ecaa0fa4..052f4534 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -906,6 +906,7 @@ GLFWbool _glfwCreateWindowX11(_GLFWwindow* window, const _GLFWwndconfig* wndconf void _glfwDestroyWindowX11(_GLFWwindow* window); void _glfwSetWindowTitleX11(_GLFWwindow* window, const char* title); void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowTaskbarProgressX11(_GLFWwindow* window, const int taskbarState, int completed); void _glfwGetWindowPosX11(_GLFWwindow* window, int* xpos, int* ypos); void _glfwSetWindowPosX11(_GLFWwindow* window, int xpos, int ypos); void _glfwGetWindowSizeX11(_GLFWwindow* window, int* width, int* height); diff --git a/src/x11_window.c b/src/x11_window.c index 98f990b2..e447a844 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2091,6 +2091,11 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag XFlush(_glfw.x11.display); } +void _glfwSetWindowTaskbarProgressX11(_GLFWwindow* window, const int taskbarState, int completed) +{ + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "X11: The platform does not support setting the window taskbar progress"); +} + void _glfwGetWindowPosX11(_GLFWwindow* window, int* xpos, int* ypos) { Window dummy; diff --git a/tests/window.c b/tests/window.c index 83baff46..53fb655f 100644 --- a/tests/window.c +++ b/tests/window.c @@ -71,7 +71,7 @@ int main(int argc, char** argv) glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - GLFWwindow* window = glfwCreateWindow(600, 600, "Window Features", NULL, NULL); + GLFWwindow* window = glfwCreateWindow(600, 700, "Window Features", NULL, NULL); if (!window) { glfwTerminate(); @@ -411,6 +411,27 @@ int main(int argc, char** argv) nk_value_bool(nk, "Visible", glfwGetWindowAttrib(window, GLFW_VISIBLE)); nk_value_bool(nk, "Iconified", glfwGetWindowAttrib(window, GLFW_ICONIFIED)); nk_value_bool(nk, "Maximized", glfwGetWindowAttrib(window, GLFW_MAXIMIZED)); + + nk_layout_row_dynamic(nk, 30, 1); + + nk_label(nk, "Taskbar Progress", NK_TEXT_CENTERED); + + nk_layout_row_dynamic(nk, 30, 5); + + static int progress = 0; + if(nk_button_label(nk, "No progress")) + glfwSetWindowTaskbarProgress(window, GLFW_TASKBAR_PROGRESS_NOPROGRESS, progress); + if (nk_button_label(nk, "Indeterminate")) + glfwSetWindowTaskbarProgress(window, GLFW_TASKBAR_PROGRESS_INDETERMINATE, progress); + if (nk_button_label(nk, "Normal")) + glfwSetWindowTaskbarProgress(window, GLFW_TASKBAR_PROGRESS_NORMAL, progress); + if (nk_button_label(nk, "Error")) + glfwSetWindowTaskbarProgress(window, GLFW_TASKBAR_PROGRESS_ERROR, progress); + if (nk_button_label(nk, "Paused")) + glfwSetWindowTaskbarProgress(window, GLFW_TASKBAR_PROGRESS_PAUSED, progress); + + nk_label(nk, "Progress: ", NK_TEXT_ALIGN_LEFT); + nk_slider_int(nk, 0, &progress, 100, 1); } nk_end(nk);