diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index dac116b7..6553e60d 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3395,9 +3395,11 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i */ GLFWAPI void glfwSetWindowTaskbarProgress(GLFWwindow* window, int progressState, double value); -//Use count = GLFW_DONT_CARE to disable overlay/badge icon +//Use count = 0 to disable overlay/badge icon GLFWAPI void glfwSetWindowTaskbarBadge(GLFWwindow* window, int count); +GLFWAPI void glfwSetWindowTaskbarBadgeString(GLFWwindow* window, const char* string); + /*! @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 1c82f3ce..31dd703c 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -530,6 +530,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) _glfwSetWindowIconCocoa, _glfwSetWindowTaskbarProgressCocoa, _glfwSetWindowTaskbarBadgeCocoa, + _glfwSetWindowTaskbarBadgeStringCocoa, _glfwGetWindowPosCocoa, _glfwSetWindowPosCocoa, _glfwGetWindowSizeCocoa, diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 3ec55489..ebd06003 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -232,6 +232,7 @@ void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title); void _glfwSetWindowIconCocoa(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowTaskbarProgressCocoa(_GLFWwindow* window, int progressState, double value); void _glfwSetWindowTaskbarBadgeCocoa(_GLFWwindow* window, int count); +void _glfwSetWindowTaskbarBadgeStringCocoa(_GLFWwindow* window, const char* count); 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 98029041..8f8d947c 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1169,8 +1169,47 @@ void _glfwSetWindowTaskbarProgressCocoa(_GLFWwindow* window, int progressState, void _glfwSetWindowTaskbarBadgeCocoa(_GLFWwindow* window, int count) { - _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, - "Cocoa: Setting the taskbar progress badge is not implemented"); + if (window != NULL) + { + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Cocoa: Cannot set a badge for a window. Pass NULL to set the Dock badge."); + return; + } + + if (count == 0) + { + [NSApp dockTile].badgeLabel = nil; + return; + } + + NSString* string; + + if (count <= 9999) + string = [@(count) stringValue]; + else + string = [[@(9999) stringValue] stringByAppendingString:@"+"]; + + [NSApp dockTile].badgeLabel = string; +} + +void _glfwSetWindowTaskbarBadgeStringCocoa(_GLFWwindow* window, const char* string) +{ + if (window != NULL) + { + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Cocoa: Cannot set a badge for a window. Pass NULL to set for the application."); + } + + if (string == NULL) + { + [NSApp dockTile].badgeLabel = nil; + return; + } + + NSString* nsString = [NSString stringWithCString:string + encoding:[NSString defaultCStringEncoding]]; + + [NSApp dockTile].badgeLabel = nsString; } void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos) diff --git a/src/internal.h b/src/internal.h index 5c7e3e5e..c37c89dc 100644 --- a/src/internal.h +++ b/src/internal.h @@ -708,6 +708,7 @@ struct _GLFWplatform void (*setWindowIcon)(_GLFWwindow*,int,const GLFWimage*); void (*setWindowTaskbarProgress)(_GLFWwindow*,const int,double); void (*setWindowTaskbarBadge)(_GLFWwindow*,int); + void (*setWindowTaskbarBadgeString)(_GLFWwindow*,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 cef34bcd..c60a54d9 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -75,6 +75,7 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) _glfwSetWindowIconNull, _glfwSetWindowTaskbarProgressNull, _glfwSetWindowTaskbarBadgeNull, + _glfwSetWindowTaskbarBadgeStringNull, _glfwGetWindowPosNull, _glfwSetWindowPosNull, _glfwGetWindowSizeNull, diff --git a/src/null_platform.h b/src/null_platform.h index 529ae48d..271d9f73 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -91,6 +91,7 @@ void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title); void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowTaskbarProgressNull(_GLFWwindow* window, int progressState, double value); void _glfwSetWindowTaskbarBadgeNull(_GLFWwindow* window, int count); +void _glfwSetWindowTaskbarBadgeStringNull(_GLFWwindow* window, int count); 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 97cd92cc..5e221cea 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -195,6 +195,10 @@ void _glfwSetWindowTaskbarBadgeNull(_GLFWwindow* window, int count) { } +void _glfwSetWindowTaskbarBadgeStringNull(_GLFWwindow* window, int count) +{ +} + void _glfwSetWindowMonitorNull(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/win32_init.c b/src/win32_init.c index a3dc0168..c24def07 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -640,6 +640,7 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) _glfwSetWindowIconWin32, _glfwSetWindowTaskbarProgressWin32, _glfwSetWindowTaskbarBadgeWin32, + _glfwSetWindowTaskbarBadgeStringWin32, _glfwGetWindowPosWin32, _glfwSetWindowPosWin32, _glfwGetWindowSizeWin32, diff --git a/src/win32_platform.h b/src/win32_platform.h index 30c943f8..7eb7381d 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -620,6 +620,7 @@ void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title); void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowTaskbarProgressWin32(_GLFWwindow* window, int progressState, double value); void _glfwSetWindowTaskbarBadgeWin32(_GLFWwindow* window, int count); +void _glfwSetWindowTaskbarBadgeStringWin32(_GLFWwindow* window, const char* count); 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 73443fce..8e46cb07 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1605,7 +1605,7 @@ void _glfwSetWindowTaskbarProgressWin32(_GLFWwindow* window, int progressState, if(!IsWindows7OrGreater()) { - _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Win32: Taskbar progress is only supported on Windows 7 or newer"); + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Win32: Taskbar progress is only supported on Windows 7 and newer"); return; } @@ -1644,7 +1644,7 @@ void _glfwSetWindowTaskbarProgressWin32(_GLFWwindow* window, int progressState, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar progress state"); } -HICON GenerateBadgeIcon(HWND hWnd, int count) +static HICON GenerateBadgeIcon(HWND hWnd, int count) { HDC hdc = NULL, hdcMem = NULL; HBITMAP hBitmap = NULL, hOldBitmap = NULL; @@ -1727,17 +1727,25 @@ void _glfwSetWindowTaskbarBadgeWin32(_GLFWwindow* window, int count) { HRESULT res = S_OK; HICON icon = NULL; + + if (window == NULL) + { + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Win32: Taskbar badge requires a valid window handle"); + return; + } if (!IsWindows7OrGreater()) { - _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Win32: Taskbar badge is only supported on Windows 7 or newer"); + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Win32: Taskbar badge is only supported on Windows 7 and newer"); return; } if (!window->win32.taskbarList) return; + + count = min(count, 999); - if (count != GLFW_DONT_CARE) + if (count > 0) { icon = GenerateBadgeIcon(window->win32.handle, count); if (!icon) @@ -1747,7 +1755,8 @@ void _glfwSetWindowTaskbarBadgeWin32(_GLFWwindow* window, int count) } } - res = window->win32.taskbarList->lpVtbl->SetOverlayIcon(window->win32.taskbarList, window->win32.handle, icon, TEXT("")); + // TODO: should probably set the alt text too. Integer as text is better than nothing. Use the same string for the icon and alt text in the string version. + res = window->win32.taskbarList->lpVtbl-> (window->win32.taskbarList, window->win32.handle, icon, TEXT("")); if(icon) DestroyIcon(icon); @@ -1759,6 +1768,12 @@ void _glfwSetWindowTaskbarBadgeWin32(_GLFWwindow* window, int count) } } +void _glfwSetWindowTaskbarBadgeStringWin32(_GLFWwindow* window, const char* string) +{ + _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, + "Win32: I'm sure GamesTrap will find a way to write non-integer strings with GDI too. :)"); +} + void _glfwGetWindowPosWin32(_GLFWwindow* window, int* xpos, int* ypos) { POINT pos = { 0, 0 }; diff --git a/src/window.c b/src/window.c index 6bba41e2..366531ac 100644 --- a/src/window.c +++ b/src/window.c @@ -587,11 +587,9 @@ GLFWAPI void glfwSetWindowTaskbarBadge(GLFWwindow* handle, int count) { _GLFWwindow* window = (_GLFWwindow*)handle; - assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (count != GLFW_DONT_CARE && (count < 0 || count > 999)) + if (count < 0) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid badge count %d", count); return; @@ -600,6 +598,15 @@ GLFWAPI void glfwSetWindowTaskbarBadge(GLFWwindow* handle, int count) _glfw.platform.setWindowTaskbarBadge(window, count); } +GLFWAPI void glfwSetWindowTaskbarBadgeString(GLFWwindow* handle, const char* string) +{ + _GLFWwindow* window = (_GLFWwindow*)handle; + + _GLFW_REQUIRE_INIT(); + + _glfw.platform.setWindowTaskbarBadgeString(window, string); +} + 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 985a42a0..71887d34 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -421,6 +421,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) _glfwSetWindowIconWayland, _glfwSetWindowTaskbarProgressWayland, _glfwSetWindowTaskbarBadgeWayland, + _glfwSetWindowTaskbarBadgeStringWayland, _glfwGetWindowPosWayland, _glfwSetWindowPosWayland, _glfwGetWindowSizeWayland, diff --git a/src/wl_platform.h b/src/wl_platform.h index 49cb36e0..ad365d50 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -448,6 +448,7 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title); void _glfwSetWindowIconWayland(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowTaskbarProgressWayland(_GLFWwindow* window, int progressState, double value); void _glfwSetWindowTaskbarBadgeWayland(_GLFWwindow* window, int count); +void _glfwSetWindowTaskbarBadgeStringWayland(_GLFWwindow* window, const char* count); 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 246e392e..80a12c96 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1913,13 +1913,24 @@ void _glfwSetWindowTaskbarProgressWayland(_GLFWwindow* window, const int progres void _glfwSetWindowTaskbarBadgeWayland(_GLFWwindow* window, int count) { - (void)window; - - const dbus_bool_t badgeVisible = (count != GLFW_DONT_CARE); + if (window != NULL) + { + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Wayland: Cannot set a badge for a window. Pass NULL to set the application's shared badge."); + return; + } + + const dbus_bool_t badgeVisible = (count > 0); _glfwUpdateTaskbarBadgeDBusPOSIX(badgeVisible, count); } +void _glfwSetWindowTaskbarBadgeStringWayland(_GLFWwindow* window, const char* string) +{ + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Wayland: Unable to set a string badge. Only integer badges are supported."); +} + 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 66c9d54c..166b80bc 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -1211,6 +1211,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) _glfwSetWindowIconX11, _glfwSetWindowTaskbarProgressX11, _glfwSetWindowTaskbarBadgeX11, + _glfwSetWindowTaskbarBadgeStringX11, _glfwGetWindowPosX11, _glfwSetWindowPosX11, _glfwGetWindowSizeX11, diff --git a/src/x11_platform.h b/src/x11_platform.h index 7c17ed08..73ff4af3 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -907,6 +907,7 @@ void _glfwSetWindowTitleX11(_GLFWwindow* window, const char* title); void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowTaskbarProgressX11(_GLFWwindow* window, int progressState, double value); void _glfwSetWindowTaskbarBadgeX11(_GLFWwindow* window, int count); +void _glfwSetWindowTaskbarBadgeStringX11(_GLFWwindow* window, const char* count); 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 7ee61612..7b76a167 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2163,13 +2163,24 @@ void _glfwSetWindowTaskbarProgressX11(_GLFWwindow* window, int progressState, do void _glfwSetWindowTaskbarBadgeX11(_GLFWwindow* window, int count) { - (void)window; + if (window != NULL) + { + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "X11: Cannot set a badge for a window. Pass NULL to set the application's shared badge."); + return; + } - const dbus_bool_t badgeVisible = (count != GLFW_DONT_CARE); + const dbus_bool_t badgeVisible = (count > 0); _glfwUpdateTaskbarBadgeDBusPOSIX(badgeVisible, count); } +void _glfwSetWindowTaskbarBadgeStringX11(_GLFWwindow* window, const char* string) +{ + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "X11: Unable to set a string badge. Only integer badges are supported."); +} + void _glfwGetWindowPosX11(_GLFWwindow* window, int* xpos, int* ypos) { Window dummy; diff --git a/tests/window.c b/tests/window.c index 51b4198d..0fd1aef9 100644 --- a/tests/window.c +++ b/tests/window.c @@ -443,17 +443,16 @@ int main(int argc, char** argv) nk_label(nk, "Taskbar Badge", NK_TEXT_CENTERED); - static int enableBadge = false; static int badgeCount = 0; nk_layout_row_begin(nk, NK_DYNAMIC, 30, 3); nk_layout_row_push(nk, 1.0f / 3.f); - if (nk_checkbox_label(nk, "Enable Badge", &enableBadge)) - glfwSetWindowTaskbarBadge(window, enableBadge ? badgeCount : GLFW_DONT_CARE); - nk_layout_row_push(nk, 1.0f / 3.f); nk_labelf(nk, NK_TEXT_LEFT, "Badge count: %d", badgeCount); nk_layout_row_push(nk, 2.f / 3.f); - if (nk_slider_int(nk, 0, &badgeCount, 99, 1)) - glfwSetWindowTaskbarBadge(window, enableBadge ? badgeCount : GLFW_DONT_CARE); + if (nk_slider_int(nk, 0, &badgeCount, 10000, 1)) + { + glfwSetWindowTaskbarBadge(window, badgeCount); + glfwSetWindowTaskbarBadge(NULL, badgeCount); + } nk_layout_row_end(nk); } nk_end(nk);