diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index cd733bf10..ebbd54088 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1844,6 +1844,26 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); */ GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); +/*! @brief Sets the icons representing the specified window. + * + * This function sets the icons, as an array of GLFWimage, of the specified + * window. + * + * If count is 0, it removes any icon previously set that way. + * + * @param[in] window The window whose icons to change. + * @param[in] images Array with the icons to set. + * @param[in] count Number of images in the array. + * + * @par Thread Safety + * TODO + * + * @since Added in GLFW TODO. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcons(GLFWwindow* window, const GLFWimage* images, int count); + /*! @brief Retrieves the size of the framebuffer of the specified window. * * This function retrieves the size, in pixels, of the framebuffer of the diff --git a/src/cocoa_window.m b/src/cocoa_window.m index b5bb4662a..6514fffb3 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -996,6 +996,13 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) [window->ns.object setContentSize:NSMakeSize(width, height)]; } +void _glfwPlatformSetWindowIcons(_GLFWwindow* window, const GLFWimage* images, int count) +{ + // TODO + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Set window icons not implemented yet"); +} + void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) { const NSRect contentRect = [window->ns.view frame]; diff --git a/src/internal.h b/src/internal.h index 38749a1bf..620589317 100644 --- a/src/internal.h +++ b/src/internal.h @@ -544,6 +544,11 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height); */ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height); +/*! @copydoc glfwSetWindowIcons + * @ingroup platform + */ +void _glfwPlatformSetWindowIcons(_GLFWwindow* window, const GLFWimage* images, int count); + /*! @copydoc glfwGetFramebufferSize * @ingroup platform */ diff --git a/src/mir_window.c b/src/mir_window.c index 566a5a110..c22e79956 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -531,6 +531,12 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } +void _glfwPlatformSetWindowIcons(_GLFWwindow* window, const GLFWimage* images, int count) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) { if (width) diff --git a/src/win32_window.c b/src/win32_window.c index da652e8a8..1de5cc51a 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -916,6 +916,13 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) } } +void _glfwPlatformSetWindowIcons(_GLFWwindow* window, const GLFWimage* images, int count) +{ + // TODO + _glfwInputError(GLFW_PLATFORM_ERROR, + "Win32: Set window icons not implemented yet"); +} + void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) { _glfwPlatformGetWindowSize(window, width, height); diff --git a/src/window.c b/src/window.c index 3acd48c48..153417d9a 100644 --- a/src/window.c +++ b/src/window.c @@ -514,6 +514,15 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) _glfwPlatformSetWindowSize(window, width, height); } +GLFWAPI void glfwSetWindowIcons(GLFWwindow* handle, const GLFWimage* images, int count) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + + _GLFW_REQUIRE_INIT(); + + _glfwPlatformSetWindowIcons(window, images, count); +} + GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/wl_window.c b/src/wl_window.c index bb2da4734..1a61c9904 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -265,6 +265,16 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) window->wl.height = height; } +void _glfwPlatformSetWindowIcons(_GLFWwindow* window, const GLFWimage* images, int count) +{ + // There is currently no standard way to set the icon at runtime on + // Wayland, the closest thing is xdg_surface.set_app_id combined with a + // .desktop file containing the icon. + + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Set window icons not supported"); +} + void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) { _glfwPlatformGetWindowSize(window, width, height); diff --git a/src/x11_init.c b/src/x11_init.c index 19b5ab9dc..d95d4a8ba 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -443,6 +443,8 @@ static void detectEWMH(void) getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS"); _glfw.x11.NET_WM_NAME = getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_NAME"); + _glfw.x11.NET_WM_ICON = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_ICON"); _glfw.x11.NET_WM_ICON_NAME = getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_ICON_NAME"); _glfw.x11.NET_WM_PID = diff --git a/src/x11_platform.h b/src/x11_platform.h index 22bb7e0d5..6f0bd39e1 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -130,6 +130,7 @@ typedef struct _GLFWlibraryX11 Atom WM_STATE; Atom WM_DELETE_WINDOW; Atom NET_WM_NAME; + Atom NET_WM_ICON; Atom NET_WM_ICON_NAME; Atom NET_WM_PID; Atom NET_WM_PING; diff --git a/src/x11_window.c b/src/x11_window.c index d89f7236c..f97153baa 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1572,6 +1572,42 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) XFlush(_glfw.x11.display); } +void _glfwPlatformSetWindowIcons(_GLFWwindow* window, const GLFWimage* images, int count) +{ + if (count > 0) + { + int propsize = 2 * count; + int i; + for (i = 0; i < count; ++i) + propsize += images[i].width * images[i].height * 4; + + long* propdata = calloc(propsize, sizeof(long)); + long index = 0; + for (i = 0; i < count; ++i) + { + int width = images[i].width; + int height = images[i].height; + propdata[index++] = width; + propdata[index++] = height; + + // As Xlib specifies its properties in terms of long, we can’t blindly + // memcpy the provided data, since sizeof(long) can be different from 4. + const uint32_t* pixels = (const uint32_t*) images[i].pixels; + int j; + for (j = 0; j < width * height; ++j) + propdata[index++] = *pixels++; + } + + XChangeProperty(_glfw.x11.display, window->x11.handle, + _glfw.x11.NET_WM_ICON, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*) propdata, propsize); + free(propdata); + } + else + XDeleteProperty(_glfw.x11.display, window->x11.handle, + _glfw.x11.NET_WM_ICON); +} + void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) { _glfwPlatformGetWindowSize(window, width, height);