mirror of
https://github.com/glfw/glfw.git
synced 2025-02-16 21:57:43 +00:00
Update glfwSetWindowIcon to support application icons and icon size queries
New MacOS implementation for glfwSetWindowIcon New test program: animate-icon Documentation updates for glfwSetWindowIcon
This commit is contained in:
parent
9a87635686
commit
6381d7ed20
@ -98,6 +98,7 @@ video tutorials.
|
|||||||
- IntellectualKitty
|
- IntellectualKitty
|
||||||
- Aaron Jacobs
|
- Aaron Jacobs
|
||||||
- JannikGM
|
- JannikGM
|
||||||
|
- Andreas O. Jansen
|
||||||
- Erik S. V. Jansson
|
- Erik S. V. Jansson
|
||||||
- jjYBdx4IL
|
- jjYBdx4IL
|
||||||
- Toni Jovanoski
|
- Toni Jovanoski
|
||||||
|
@ -121,6 +121,7 @@ information on what to include when reporting a bug.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
- Updated `glfwSetWindowIcon` to set the MacOS Dock icon, and query for an optimal image size (#2041)
|
||||||
- Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958)
|
- Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958)
|
||||||
- Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`,
|
- Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`,
|
||||||
`GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to
|
`GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to
|
||||||
|
@ -902,6 +902,23 @@ sequential rows, starting from the top-left corner.
|
|||||||
|
|
||||||
To revert to the default window icon, pass in an empty image array.
|
To revert to the default window icon, pass in an empty image array.
|
||||||
|
|
||||||
|
On Windows and X11, the window's title bar and taskbar icons are set with this method.
|
||||||
|
On MacOS, a `NULL` window handle may be passed to set the application's Dock icon.
|
||||||
|
|
||||||
|
Some platforms support querying an optimal size for its icons.
|
||||||
|
You can ask for this size by passing a `NULL` window handle, a count of zero,
|
||||||
|
and a valid pointer to an image with its `pixels` field set to `NULL`:
|
||||||
|
|
||||||
|
@code
|
||||||
|
GLFWimage image = { DEFAULT_WIDTH, DEFAULT_HEIGHT, NULL };
|
||||||
|
glfwSetWindowIcon(NULL, 0, &image);
|
||||||
|
|
||||||
|
image.pixels = generatePixels(image.width, image.height);
|
||||||
|
|
||||||
|
glfwSetWindowIcon(window, 1, &image);
|
||||||
|
free(image.pixels);
|
||||||
|
@endcode
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetWindowIcon(window, 0, NULL);
|
glfwSetWindowIcon(window, 0, NULL);
|
||||||
@endcode
|
@endcode
|
||||||
|
@ -3256,12 +3256,12 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
||||||
|
|
||||||
/*! @brief Sets the icon for the specified window.
|
/*! @brief Sets the icon for the specified window or application.
|
||||||
*
|
*
|
||||||
* This function sets the icon of the specified window. If passed an array of
|
* This function sets the icon of the specified window or application. If passed an
|
||||||
* candidate images, those of or closest to the sizes desired by the system are
|
* array of candidate images, those of or closest to the sizes desired by the system
|
||||||
* selected. If no images are specified, the window reverts to its default
|
* are selected. If no images are specified, the window or application reverts to its
|
||||||
* icon.
|
* default icon.
|
||||||
*
|
*
|
||||||
* The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
|
* The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
|
||||||
* bits per channel with the red channel first. They are arranged canonically
|
* bits per channel with the red channel first. They are arranged canonically
|
||||||
@ -3269,9 +3269,17 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
|||||||
*
|
*
|
||||||
* The desired image sizes varies depending on platform and system settings.
|
* The desired image sizes varies depending on platform and system settings.
|
||||||
* The selected images will be rescaled as needed. Good sizes include 16x16,
|
* The selected images will be rescaled as needed. Good sizes include 16x16,
|
||||||
* 32x32 and 48x48.
|
* 32x32, 48x48, 64x64 and 128x128.
|
||||||
*
|
*
|
||||||
* @param[in] window The window whose icon to set.
|
* If passed a `NULL` window handle, a count of zero, and a valid pointer to an
|
||||||
|
* image with its `pixels` field set to `NULL`, GLFW will set that image's
|
||||||
|
* `width` and `height` fields to the optimal icon size for the current platform,
|
||||||
|
* if these can be retrieved. If they can not be retrieved by GLFW, they are left
|
||||||
|
* untouched. Doing this requires an internal const-cast for the `images` parameter.
|
||||||
|
* This parameter remains qualified with `const` for backwards-compatability.
|
||||||
|
* See @ref window_icon for an example.
|
||||||
|
*
|
||||||
|
* @param[in] window The window whose icon to set, or `NULL` for the application's icon.
|
||||||
* @param[in] count The number of images in the specified array, or zero to
|
* @param[in] count The number of images in the specified array, or zero to
|
||||||
* revert to the default window icon.
|
* revert to the default window icon.
|
||||||
* @param[in] images The images to create the icon from. This is ignored if
|
* @param[in] images The images to create the icon from. This is ignored if
|
||||||
@ -3284,13 +3292,22 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
|||||||
* @pointer_lifetime The specified image data is copied before this function
|
* @pointer_lifetime The specified image data is copied before this function
|
||||||
* returns.
|
* returns.
|
||||||
*
|
*
|
||||||
* @remark @macos Regular windows do not have icons on macOS. This function
|
* @remark Every platform has either a window icon, or an application icon.
|
||||||
* will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as
|
* To cover all platforms, you need to set both.
|
||||||
* the application bundle's icon. For more information on bundles, see the
|
*
|
||||||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
* @remark @macos The Dock icon defaults to the application bundle's icon.
|
||||||
|
* For more information on bundles, see the [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||||
* in the Mac Developer Library.
|
* in the Mac Developer Library.
|
||||||
*
|
*
|
||||||
* @remark @wayland There is no existing protocol to change an icon, the
|
* @remark @wayland @x11 The default icon is specified in the application's
|
||||||
|
* desktop file.
|
||||||
|
*
|
||||||
|
* @remark @macos Regular windows do not have icons on macOS. This function
|
||||||
|
* will emit @ref GLFW_FEATURE_UNAVAILABLE if a valid window handle is passed.
|
||||||
|
* Pass a `NULL` window handle to set the Dock icon. Otherwise, the dock icon
|
||||||
|
* will be the same as the application bundle's icon.
|
||||||
|
*
|
||||||
|
* @remark @wayland There is no existing protocol to change an icon; the
|
||||||
* window will thus inherit the one defined in the application's desktop file.
|
* window will thus inherit the one defined in the application's desktop file.
|
||||||
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||||
*
|
*
|
||||||
|
@ -193,6 +193,35 @@ static NSUInteger translateKeyToModifierFlag(int key)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts a GLFWimage to an NSImage. The returned image must be explicitly freed.
|
||||||
|
//
|
||||||
|
static NSImage* imageToNative(const GLFWimage* image)
|
||||||
|
{
|
||||||
|
NSBitmapImageRep* representation = [[NSBitmapImageRep alloc]
|
||||||
|
initWithBitmapDataPlanes:NULL
|
||||||
|
pixelsWide:image->width
|
||||||
|
pixelsHigh:image->height
|
||||||
|
bitsPerSample:8
|
||||||
|
samplesPerPixel:4
|
||||||
|
hasAlpha:YES
|
||||||
|
isPlanar:NO
|
||||||
|
colorSpaceName:NSCalibratedRGBColorSpace
|
||||||
|
bitmapFormat:NSBitmapFormatAlphaNonpremultiplied
|
||||||
|
bytesPerRow:image->width * 4
|
||||||
|
bitsPerPixel:32];
|
||||||
|
|
||||||
|
if (representation == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
memcpy([representation bitmapData], image->pixels, image->width * image->height * 4);
|
||||||
|
|
||||||
|
NSImage* native = [[NSImage alloc] initWithSize:NSMakeSize(image->width, image->height)];
|
||||||
|
[native addRepresentation:representation];
|
||||||
|
[representation release];
|
||||||
|
|
||||||
|
return native;
|
||||||
|
}
|
||||||
|
|
||||||
// Defines a constant for empty ranges in NSTextInputClient
|
// Defines a constant for empty ranges in NSTextInputClient
|
||||||
//
|
//
|
||||||
static const NSRange kEmptyRange = { NSNotFound, 0 };
|
static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
@ -1028,8 +1057,44 @@ void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title)
|
|||||||
void _glfwSetWindowIconCocoa(_GLFWwindow* window,
|
void _glfwSetWindowIconCocoa(_GLFWwindow* window,
|
||||||
int count, const GLFWimage* images)
|
int count, const GLFWimage* images)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
if (window != NULL)
|
||||||
"Cocoa: Regular windows do not have icons on macOS");
|
{
|
||||||
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
|
"Cocoa: Regular windows do not have icons on macOS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the actual pixel storage size of the dock, which is what we're after here.
|
||||||
|
NSSize preferredSize = [NSApp dockTile].size;
|
||||||
|
|
||||||
|
if (count == 0 && images != NULL && images->pixels == NULL)
|
||||||
|
{
|
||||||
|
// Const-cast
|
||||||
|
((GLFWimage*) images)->width = preferredSize.width;
|
||||||
|
((GLFWimage*) images)->height = preferredSize.height;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
NSApp.applicationIconImage = nil;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLFWimage* image = _glfwChooseImage(count, images, preferredSize.width, preferredSize.height);
|
||||||
|
|
||||||
|
assert(image->pixels != NULL);
|
||||||
|
|
||||||
|
NSImage* native = imageToNative(image);
|
||||||
|
|
||||||
|
if (native == nil)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSApp.applicationIconImage = native;
|
||||||
|
[native release];
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos)
|
void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
@ -1710,35 +1775,15 @@ GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor,
|
|||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
NSImage* native;
|
NSImage* native = imageToNative(image);
|
||||||
NSBitmapImageRep* rep;
|
|
||||||
|
if (native == nil)
|
||||||
rep = [[NSBitmapImageRep alloc]
|
|
||||||
initWithBitmapDataPlanes:NULL
|
|
||||||
pixelsWide:image->width
|
|
||||||
pixelsHigh:image->height
|
|
||||||
bitsPerSample:8
|
|
||||||
samplesPerPixel:4
|
|
||||||
hasAlpha:YES
|
|
||||||
isPlanar:NO
|
|
||||||
colorSpaceName:NSCalibratedRGBColorSpace
|
|
||||||
bitmapFormat:NSBitmapFormatAlphaNonpremultiplied
|
|
||||||
bytesPerRow:image->width * 4
|
|
||||||
bitsPerPixel:32];
|
|
||||||
|
|
||||||
if (rep == nil)
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
memcpy([rep bitmapData], image->pixels, image->width * image->height * 4);
|
|
||||||
|
|
||||||
native = [[NSImage alloc] initWithSize:NSMakeSize(image->width, image->height)];
|
|
||||||
[native addRepresentation:rep];
|
|
||||||
|
|
||||||
cursor->ns.object = [[NSCursor alloc] initWithImage:native
|
cursor->ns.object = [[NSCursor alloc] initWithImage:native
|
||||||
hotSpot:NSMakePoint(xhot, yhot)];
|
hotSpot:NSMakePoint(xhot, yhot)];
|
||||||
|
|
||||||
[native release];
|
[native release];
|
||||||
[rep release];
|
|
||||||
|
|
||||||
if (cursor->ns.object == nil)
|
if (cursor->ns.object == nil)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
@ -1007,3 +1007,5 @@ void* _glfw_calloc(size_t count, size_t size);
|
|||||||
void* _glfw_realloc(void* pointer, size_t size);
|
void* _glfw_realloc(void* pointer, size_t size);
|
||||||
void _glfw_free(void* pointer);
|
void _glfw_free(void* pointer);
|
||||||
|
|
||||||
|
const GLFWimage* _glfwChooseImage(int count, const GLFWimage* images,
|
||||||
|
int width, int height);
|
||||||
|
@ -75,28 +75,6 @@ static DWORD getWindowExStyle(const _GLFWwindow* window)
|
|||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 i, leastDiff = INT_MAX;
|
|
||||||
const GLFWimage* closest = NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const int currDiff = abs(images[i].width * images[i].height -
|
|
||||||
width * height);
|
|
||||||
if (currDiff < leastDiff)
|
|
||||||
{
|
|
||||||
closest = images + i;
|
|
||||||
leastDiff = currDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates an RGBA icon or cursor
|
// Creates an RGBA icon or cursor
|
||||||
//
|
//
|
||||||
static HICON createIcon(const GLFWimage* image, int xhot, int yhot, GLFWbool icon)
|
static HICON createIcon(const GLFWimage* image, int xhot, int yhot, GLFWbool icon)
|
||||||
@ -1545,10 +1523,10 @@ void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* im
|
|||||||
|
|
||||||
if (count)
|
if (count)
|
||||||
{
|
{
|
||||||
const GLFWimage* bigImage = chooseImage(count, images,
|
const GLFWimage* bigImage = _glfwChooseImage(count, images,
|
||||||
GetSystemMetrics(SM_CXICON),
|
GetSystemMetrics(SM_CXICON),
|
||||||
GetSystemMetrics(SM_CYICON));
|
GetSystemMetrics(SM_CYICON));
|
||||||
const GLFWimage* smallImage = chooseImage(count, images,
|
const GLFWimage* smallImage = _glfwChooseImage(count, images,
|
||||||
GetSystemMetrics(SM_CXSMICON),
|
GetSystemMetrics(SM_CXSMICON),
|
||||||
GetSystemMetrics(SM_CYSMICON));
|
GetSystemMetrics(SM_CYSMICON));
|
||||||
|
|
||||||
|
23
src/window.c
23
src/window.c
@ -175,6 +175,28 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
|
|||||||
window->monitor = monitor;
|
window->monitor = monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the image whose area most closely matches the desired one
|
||||||
|
//
|
||||||
|
const GLFWimage* _glfwChooseImage(int count, const GLFWimage* images,
|
||||||
|
int width, int height)
|
||||||
|
{
|
||||||
|
int i, leastDiff = INT_MAX;
|
||||||
|
const GLFWimage* closest = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
const int currDiff = abs(images[i].width * images[i].height -
|
||||||
|
width * height);
|
||||||
|
if (currDiff < leastDiff)
|
||||||
|
{
|
||||||
|
closest = images + i;
|
||||||
|
leastDiff = currDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -531,7 +553,6 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
|
|||||||
int i;
|
int i;
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
|
||||||
assert(window != NULL);
|
|
||||||
assert(count >= 0);
|
assert(count >= 0);
|
||||||
assert(count == 0 || images != NULL);
|
assert(count == 0 || images != NULL);
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ add_executable(monitors monitors.c ${GETOPT} ${GLAD_GL})
|
|||||||
add_executable(reopen reopen.c ${GLAD_GL})
|
add_executable(reopen reopen.c ${GLAD_GL})
|
||||||
add_executable(cursor cursor.c ${GLAD_GL})
|
add_executable(cursor cursor.c ${GLAD_GL})
|
||||||
|
|
||||||
|
add_executable(animate-icon WIN32 MACOSX_BUNDLE animate-icon.c ${GLAD_GL})
|
||||||
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD_GL})
|
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD_GL})
|
||||||
add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL})
|
add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL})
|
||||||
add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD_GL})
|
add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD_GL})
|
||||||
@ -48,7 +49,7 @@ if (RT_LIBRARY)
|
|||||||
target_link_libraries(threads "${RT_LIBRARY}")
|
target_link_libraries(threads "${RT_LIBRARY}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks tearing threads
|
set(GUI_ONLY_BINARIES animate-icon empty gamma icon inputlag joysticks tearing threads
|
||||||
timeout title triangle-vulkan window)
|
timeout title triangle-vulkan window)
|
||||||
set(CONSOLE_BINARIES allocator clipboard events msaa glfwinfo iconify monitors
|
set(CONSOLE_BINARIES allocator clipboard events msaa glfwinfo iconify monitors
|
||||||
reopen cursor)
|
reopen cursor)
|
||||||
|
202
tests/animate-icon.c
Normal file
202
tests/animate-icon.c
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
//========================================================================
|
||||||
|
// Window icon animation test program
|
||||||
|
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
//
|
||||||
|
// This program is used to test the icon feature.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define GLAD_GL_IMPLEMENTATION
|
||||||
|
#include <glad/gl.h>
|
||||||
|
#define GLFW_INCLUDE_NONE
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define ALPHA 220
|
||||||
|
#define WIDTH 3
|
||||||
|
#define HEIGHT 3
|
||||||
|
#define SPEED 0.3
|
||||||
|
|
||||||
|
const unsigned char iconColors[5][3] =
|
||||||
|
{
|
||||||
|
{ 1, 0, 0 }, // Red
|
||||||
|
{ 0, 1, 0 }, // Green
|
||||||
|
{ 0, 0, 1 }, // Blue
|
||||||
|
{ 1, 1, 1 } // All
|
||||||
|
};
|
||||||
|
|
||||||
|
static int currentIconColor = -1;
|
||||||
|
static int animate = GLFW_FALSE;
|
||||||
|
static int smooth = GLFW_FALSE;
|
||||||
|
static int useOptimalSize = GLFW_FALSE;
|
||||||
|
static int width = WIDTH, height = HEIGHT;
|
||||||
|
|
||||||
|
static void error_callback(int error_code, const char* description)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error %i: %s\n", error_code, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_icon(GLFWwindow* window, int iconColor)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
double time = glfwGetTime();
|
||||||
|
|
||||||
|
double red = (cos(SPEED * time * M_PI ) + 1.0) / 2.0;
|
||||||
|
double green = (cos(SPEED * time * M_PI * 1.5) + 1.0) / 2.0;
|
||||||
|
double blue = (cos(SPEED * time * M_PI * 2.0) + 1.0) / 2.0;
|
||||||
|
|
||||||
|
unsigned char pixels[width * height * 4];
|
||||||
|
|
||||||
|
for (x = 0; x < width; ++x)
|
||||||
|
{
|
||||||
|
for (y = 0; y < height; ++y)
|
||||||
|
{
|
||||||
|
int offset = x * height * 4 + y * 4;
|
||||||
|
|
||||||
|
pixels[offset + 0] = iconColors[currentIconColor][0] * (char) (255.0 * red);
|
||||||
|
pixels[offset + 1] = iconColors[currentIconColor][1] * (char) (255.0 * green);
|
||||||
|
pixels[offset + 2] = iconColors[currentIconColor][2] * (char) (255.0 * blue);
|
||||||
|
pixels[offset + 3] = (char) (255.0 * ((double) (x + y) / (double) (width + height)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWimage image = { width, height, pixels };
|
||||||
|
|
||||||
|
glfwSetErrorCallback(NULL);
|
||||||
|
|
||||||
|
glfwSetWindowIcon(window, 1, &image);
|
||||||
|
glfwSetWindowIcon(0, 1, &image);
|
||||||
|
|
||||||
|
glfwSetErrorCallback(error_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
|
{
|
||||||
|
if (action != GLFW_PRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case GLFW_KEY_ESCAPE:
|
||||||
|
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||||
|
break;
|
||||||
|
case GLFW_KEY_SPACE:
|
||||||
|
currentIconColor = (currentIconColor + 1) % 4;
|
||||||
|
animate = GLFW_TRUE;
|
||||||
|
break;
|
||||||
|
case GLFW_KEY_S:
|
||||||
|
smooth = !smooth;
|
||||||
|
break;
|
||||||
|
case GLFW_KEY_O:
|
||||||
|
{
|
||||||
|
GLFWimage image = { GLFW_DONT_CARE, GLFW_DONT_CARE, NULL };
|
||||||
|
glfwSetWindowIcon(NULL, 0, &image);
|
||||||
|
printf("Optimal size: [%i, %i]\n", image.width, image.height);
|
||||||
|
useOptimalSize = !useOptimalSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GLFW_KEY_X:
|
||||||
|
glfwSetWindowIcon(window, 0, NULL);
|
||||||
|
glfwSetWindowIcon(0, 0, NULL);
|
||||||
|
currentIconColor = -1;
|
||||||
|
animate = GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
GLFWwindow* window;
|
||||||
|
|
||||||
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
|
if (!glfwInit())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to initialize GLFW\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
window = glfwCreateWindow(200, 200, "Window Icon", NULL, NULL);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
|
||||||
|
fprintf(stderr, "Failed to open GLFW window\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
gladLoadGL(glfwGetProcAddress);
|
||||||
|
glfwSwapInterval(60);
|
||||||
|
|
||||||
|
glfwSetKeyCallback(window, key_callback);
|
||||||
|
|
||||||
|
double lastTime = 0.0;
|
||||||
|
while (!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (useOptimalSize)
|
||||||
|
{
|
||||||
|
GLFWimage image = { GLFW_DONT_CARE, GLFW_DONT_CARE, NULL };
|
||||||
|
glfwSetWindowIcon(NULL, 0, &image);
|
||||||
|
|
||||||
|
if (image.width != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
assert(image.height != GLFW_DONT_CARE);
|
||||||
|
|
||||||
|
width = image.width;
|
||||||
|
height = image.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = WIDTH;
|
||||||
|
height = HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
double time = glfwGetTime();
|
||||||
|
if (animate && (time - lastTime) > (smooth ? 0.01 : 0.15))
|
||||||
|
{
|
||||||
|
set_icon(window, currentIconColor);
|
||||||
|
lastTime = time;
|
||||||
|
}
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: rollback all changes in this branch. Create a new competing branch to set-application-icon, add this file's content as a new test program (animateIcon?)
|
||||||
|
// Do not add glfwSetApplicationIcon in the new one. Rather, use glfwSetWindowIcon with NULL handle, and add support for getting an optimal max size.
|
@ -89,6 +89,7 @@ static void set_icon(GLFWwindow* window, int icon_color)
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfwSetWindowIcon(window, 1, &img);
|
glfwSetWindowIcon(window, 1, &img);
|
||||||
|
glfwSetWindowIcon(NULL, 1, &img);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
@ -107,6 +108,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
break;
|
break;
|
||||||
case GLFW_KEY_X:
|
case GLFW_KEY_X:
|
||||||
glfwSetWindowIcon(window, 0, NULL);
|
glfwSetWindowIcon(window, 0, NULL);
|
||||||
|
glfwSetWindowIcon(NULL, 0, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user