Convert GLFWtheme to an opaque object.

Add creation, copying and destruction functions for theming objects.
Add setters and getters for theme objects.
This commit is contained in:
ws909 2023-01-29 21:06:42 +01:00
parent 4963e8ba94
commit 3e7ce3ac63
23 changed files with 219 additions and 100 deletions

View File

@ -5845,16 +5845,31 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
*/ */
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
typedef struct GLFWtheme typedef struct GLFWtheme GLFWtheme;
{
int baseTheme; // light/dark
int flags;
unsigned char color[4];
} GLFWtheme;
#define GLFW_BASE_THEME_DEFAULT 0 typedef struct _GLFWtheme
#define GLFW_BASE_THEME_LIGHT 1 {
#define GLFW_BASE_THEME_DARK 2 int variation; // light/dark
int flags;
unsigned char color[4]; // TODO: change to 128 bit (4 floats) to support wider gamuts.
} _GLFWtheme;
GLFWAPI GLFWtheme* glfwCreateTheme(void);
GLFWAPI void glfwDestroyTheme(GLFWtheme* theme);
GLFWAPI void glfwCopyTheme(const GLFWtheme* source, GLFWtheme* target);
GLFWAPI int glfwThemeGetVariation(const GLFWtheme* theme);
GLFWAPI void glfwThemeSetVariation(GLFWtheme* theme, int value);
GLFWAPI int glfwThemeGetFlags(const GLFWtheme* theme);
GLFWAPI void glfwThemeSetFlags(GLFWtheme* theme, int value);
GLFWAPI void glfwThemeGetColor(const GLFWtheme* theme, float* red, float* green, float* blue, float* alpha);
GLFWAPI void glfwThemeSetColor(GLFWtheme* theme, float red, float green, float blue, float alpha);
#define GLFW_THEME_DARK -1
#define GLFW_THEME_DEFAULT 0
#define GLFW_THEME_LIGHT 1
#define GLFW_THEME_FLAG_HAS_COLOR 1 #define GLFW_THEME_FLAG_HAS_COLOR 1
#define GLFW_THEME_FLAG_HIGH_CONTRAST 2 #define GLFW_THEME_FLAG_HIGH_CONTRAST 2
@ -5872,7 +5887,7 @@ GLFWAPI GLFWthemefun glfwSetSystemThemeCallback(GLFWthemefun callback);
* @param[in] window The window to set the theme for. * @param[in] window The window to set the theme for.
* @param[in] theme The theme to set. Pass `NULL` to set it to the system default. * @param[in] theme The theme to set. Pass `NULL` to set it to the system default.
*/ */
GLFWAPI void glfwSetTheme(GLFWwindow* handle, GLFWtheme* theme); GLFWAPI void glfwSetTheme(GLFWwindow* handle, const GLFWtheme* theme);
GLFWAPI GLFWtheme* glfwGetTheme(GLFWwindow* handle); GLFWAPI GLFWtheme* glfwGetTheme(GLFWwindow* handle);
GLFWAPI GLFWtheme* glfwGetSystemDefaultTheme(); GLFWAPI GLFWtheme* glfwGetSystemDefaultTheme();

View File

@ -3,7 +3,7 @@ add_library(glfw ${GLFW_LIBRARY_TYPE}
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h" "${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h" "${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h"
internal.h platform.h mappings.h internal.h platform.h mappings.h
context.c init.c input.c monitor.c platform.c vulkan.c window.c context.c init.c input.c monitor.c platform.c theme.c vulkan.c window.c
egl_context.c osmesa_context.c null_platform.h null_joystick.h egl_context.c osmesa_context.c null_platform.h null_joystick.h
null_init.c null_monitor.c null_window.c null_joystick.c) null_init.c null_monitor.c null_window.c null_joystick.c)
@ -248,7 +248,7 @@ endif()
# Make GCC warn about declarations that VS 2010 and 2012 won't accept for all # Make GCC warn about declarations that VS 2010 and 2012 won't accept for all
# source files that VS will build (Clang ignores this because we set -std=c99) # source files that VS will build (Clang ignores this because we set -std=c99)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU") if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
set_source_files_properties(context.c init.c input.c monitor.c platform.c vulkan.c set_source_files_properties(context.c init.c input.c monitor.c platform.c theme.c vulkan.c
window.c null_init.c null_joystick.c null_monitor.c window.c null_init.c null_joystick.c null_monitor.c
null_window.c win32_init.c win32_joystick.c win32_module.c null_window.c win32_init.c win32_joystick.c win32_module.c
win32_monitor.c win32_time.c win32_thread.c win32_window.c win32_monitor.c win32_time.c win32_thread.c win32_window.c

View File

@ -175,7 +175,7 @@ static void createMenuBar(void)
[NSApp performSelector:setAppleMenuSelector withObject:appMenu]; [NSApp performSelector:setAppleMenuSelector withObject:appMenu];
} }
void nsAppearanceToGLFWTheme(NSAppearance* appearance, GLFWtheme* theme) void nsAppearanceToGLFWTheme(NSAppearance* appearance, _GLFWtheme* theme)
{ {
NSAppearanceName name; NSAppearanceName name;
@ -197,20 +197,20 @@ void nsAppearanceToGLFWTheme(NSAppearance* appearance, GLFWtheme* theme)
if ([name isEqualToString:NSAppearanceNameAqua]) if ([name isEqualToString:NSAppearanceNameAqua])
{ {
theme->baseTheme = GLFW_BASE_THEME_LIGHT; theme->variation = GLFW_THEME_LIGHT;
return; return;
} }
if (@available(macOS 10.10, *)) { if (@available(macOS 10.10, *)) {
if ([name isEqualToString:NSAppearanceNameVibrantLight]) if ([name isEqualToString:NSAppearanceNameVibrantLight])
{ {
theme->baseTheme = GLFW_BASE_THEME_LIGHT; theme->variation = GLFW_THEME_LIGHT;
theme->flags |= GLFW_THEME_FLAG_VIBRANT; theme->flags |= GLFW_THEME_FLAG_VIBRANT;
return; return;
} }
if ([name isEqualToString:NSAppearanceNameVibrantDark]) if ([name isEqualToString:NSAppearanceNameVibrantDark])
{ {
theme->baseTheme = GLFW_BASE_THEME_DARK; theme->variation = GLFW_THEME_DARK;
theme->flags |= GLFW_THEME_FLAG_VIBRANT; theme->flags |= GLFW_THEME_FLAG_VIBRANT;
return; return;
} }
@ -220,36 +220,36 @@ void nsAppearanceToGLFWTheme(NSAppearance* appearance, GLFWtheme* theme)
{ {
if ([name isEqualToString:NSAppearanceNameDarkAqua]) if ([name isEqualToString:NSAppearanceNameDarkAqua])
{ {
theme->baseTheme = GLFW_BASE_THEME_DARK; theme->variation = GLFW_THEME_DARK;
return; return;
} }
if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastAqua]) if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastAqua])
{ {
theme->baseTheme = GLFW_BASE_THEME_LIGHT; theme->variation = GLFW_THEME_LIGHT;
theme->flags |= GLFW_THEME_FLAG_HIGH_CONTRAST; theme->flags |= GLFW_THEME_FLAG_HIGH_CONTRAST;
return; return;
} }
if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastDarkAqua]) if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastDarkAqua])
{ {
theme->baseTheme = GLFW_BASE_THEME_DARK; theme->variation = GLFW_THEME_DARK;
theme->flags |= GLFW_THEME_FLAG_HIGH_CONTRAST; theme->flags |= GLFW_THEME_FLAG_HIGH_CONTRAST;
return; return;
} }
if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastVibrantLight]) if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastVibrantLight])
{ {
theme->baseTheme = GLFW_BASE_THEME_LIGHT; theme->variation = GLFW_THEME_LIGHT;
theme->flags |= GLFW_THEME_FLAG_VIBRANT | GLFW_THEME_FLAG_HIGH_CONTRAST; theme->flags |= GLFW_THEME_FLAG_VIBRANT | GLFW_THEME_FLAG_HIGH_CONTRAST;
return; return;
} }
if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastVibrantDark]) if ([name isEqualToString:NSAppearanceNameAccessibilityHighContrastVibrantDark])
{ {
theme->baseTheme = GLFW_BASE_THEME_DARK; theme->variation = GLFW_THEME_DARK;
theme->flags |= GLFW_THEME_FLAG_VIBRANT | GLFW_THEME_FLAG_HIGH_CONTRAST; theme->flags |= GLFW_THEME_FLAG_VIBRANT | GLFW_THEME_FLAG_HIGH_CONTRAST;
return; return;
} }
} }
theme->baseTheme = GLFW_BASE_THEME_LIGHT; theme->variation = GLFW_THEME_LIGHT;
} }
// Create key code translation tables // Create key code translation tables
@ -491,9 +491,12 @@ static GLFWbool initializeTIS(void)
// TODO: FIXME: this method is invoked twice when the high contrast setting is edited in the preferences. // TODO: FIXME: this method is invoked twice when the high contrast setting is edited in the preferences.
GLFWtheme theme = { GLFW_BASE_THEME_LIGHT, 0 }; _GLFWtheme theme = { GLFW_THEME_LIGHT, 0 };
if (@available(macOS 10.14, *)) { if (@available(macOS 10.14, *)) {
// effectiveAppearance is actually not the system appearance, but the application appearance.
// As long as NSApplication.appearance is never set, using the effective appearance is fine
// to get and observe the system appearance.
nsAppearanceToGLFWTheme(NSApp.effectiveAppearance, &theme); nsAppearanceToGLFWTheme(NSApp.effectiveAppearance, &theme);
NSColor* color = [[NSColor controlAccentColor] colorUsingColorSpace:NSColorSpace.genericRGBColorSpace]; NSColor* color = [[NSColor controlAccentColor] colorUsingColorSpace:NSColorSpace.genericRGBColorSpace];
@ -842,7 +845,7 @@ void _glfwTerminateCocoa(void)
} // autoreleasepool } // autoreleasepool
} }
GLFWtheme* _glfwGetSystemDefaultThemeCocoa(void) _GLFWtheme* _glfwGetSystemDefaultThemeCocoa(void)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
return NULL; // TODO: implement return NULL; // TODO: implement

View File

@ -297,7 +297,7 @@ void _glfwRestoreVideoModeCocoa(_GLFWmonitor* monitor);
float _glfwTransformYCocoa(float y); float _glfwTransformYCocoa(float y);
void nsAppearanceToGLFWTheme(NSAppearance* appearance, GLFWtheme* theme); void nsAppearanceToGLFWTheme(NSAppearance* appearance, _GLFWtheme* theme);
void* _glfwLoadLocalVulkanLoaderCocoa(void); void* _glfwLoadLocalVulkanLoaderCocoa(void);
@ -309,6 +309,6 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
void _glfwDestroyContextNSGL(_GLFWwindow* window); void _glfwDestroyContextNSGL(_GLFWwindow* window);
GLFWtheme* _glfwGetSystemDefaultThemeCocoa(void); _GLFWtheme* _glfwGetSystemDefaultThemeCocoa(void);
void _glfwSetThemeCocoa(_GLFWwindow* window, GLFWtheme* theme); void _glfwSetThemeCocoa(_GLFWwindow* window, _GLFWtheme* theme);
GLFWtheme* _glfwGetThemeCocoa(_GLFWwindow* window); _GLFWtheme* _glfwGetThemeCocoa(_GLFWwindow* window);

View File

@ -1876,9 +1876,9 @@ const char* _glfwGetClipboardStringCocoa(void)
} // autoreleasepool } // autoreleasepool
} }
void _glfwSetThemeCocoa(_GLFWwindow* window, GLFWtheme* theme) void _glfwSetThemeCocoa(_GLFWwindow* window, _GLFWtheme* theme)
{ {
if (!theme || theme->baseTheme == GLFW_BASE_THEME_DEFAULT) if (!theme || theme->variation == GLFW_THEME_DEFAULT)
{ {
[(NSWindow*)window->ns.object setAppearance:nil]; [(NSWindow*)window->ns.object setAppearance:nil];
return; return;
@ -1896,7 +1896,7 @@ void _glfwSetThemeCocoa(_GLFWwindow* window, GLFWtheme* theme)
// appearanceNamed: will result in nil, so these can not be used. // appearanceNamed: will result in nil, so these can not be used.
NSAppearanceName name; NSAppearanceName name;
if (theme->baseTheme == GLFW_BASE_THEME_LIGHT) if (theme->variation == GLFW_THEME_LIGHT)
{ {
if (theme->flags & GLFW_THEME_FLAG_VIBRANT) if (theme->flags & GLFW_THEME_FLAG_VIBRANT)
{ {
@ -1926,11 +1926,11 @@ void _glfwSetThemeCocoa(_GLFWwindow* window, GLFWtheme* theme)
[(NSWindow*)window->ns.object setAppearance:appearance]; [(NSWindow*)window->ns.object setAppearance:appearance];
} }
GLFWtheme* _glfwGetThemeCocoa(_GLFWwindow* window) _GLFWtheme* _glfwGetThemeCocoa(_GLFWwindow* window)
{ {
GLFWtheme* theme = &window->theme; _GLFWtheme* theme = &window->theme;
theme->baseTheme = GLFW_BASE_THEME_LIGHT; theme->variation = GLFW_THEME_LIGHT;
theme->flags = 0; theme->flags = 0;
if (@available(macOS 10.09, *)) if (@available(macOS 10.09, *))

View File

@ -546,7 +546,11 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
GLFWAPI GLFWtheme* glfwGetSystemDefaultTheme() GLFWAPI GLFWtheme* glfwGetSystemDefaultTheme()
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfw.platform.getSystemDefaultTheme();
_GLFWtheme* theme = _glfw.platform.getSystemDefaultTheme();
assert(theme->variation != GLFW_THEME_DEFAULT);
return (GLFWtheme*) theme;
} }
GLFWAPI GLFWthemefun glfwSetSystemThemeCallback(GLFWthemefun callback) GLFWAPI GLFWthemefun glfwSetSystemThemeCallback(GLFWthemefun callback)

View File

@ -477,12 +477,12 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
js->hats[hat] = value; js->hats[hat] = value;
} }
void _glfwInputSystemTheme(GLFWtheme* theme) void _glfwInputSystemTheme(_GLFWtheme* theme)
{ {
assert(theme != NULL); assert(theme != NULL);
if (_glfw.callbacks.theme) if (_glfw.callbacks.theme)
_glfw.callbacks.theme(theme); _glfw.callbacks.theme((GLFWtheme*) theme);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -571,7 +571,7 @@ struct _GLFWwindow
GLFWdropfun drop; GLFWdropfun drop;
} callbacks; } callbacks;
GLFWtheme theme; _GLFWtheme theme; // TODO: This data is mutable by clients, so remove it.
// This is defined in platform.h // This is defined in platform.h
GLFW_PLATFORM_WINDOW_STATE GLFW_PLATFORM_WINDOW_STATE
@ -675,7 +675,7 @@ struct _GLFWplatform
// Init // Init
GLFWbool (*init)(void); GLFWbool (*init)(void);
void (*terminate)(void); void (*terminate)(void);
GLFWtheme* (*getSystemDefaultTheme)(void); _GLFWtheme* (*getSystemDefaultTheme)(void);
// Input // Input
void (*getCursorPos)(_GLFWwindow*,double*,double*); void (*getCursorPos)(_GLFWwindow*,double*,double*);
void (*setCursorPos)(_GLFWwindow*,double,double); void (*setCursorPos)(_GLFWwindow*,double,double);
@ -738,8 +738,8 @@ struct _GLFWplatform
void (*setWindowFloating)(_GLFWwindow*,GLFWbool); void (*setWindowFloating)(_GLFWwindow*,GLFWbool);
void (*setWindowOpacity)(_GLFWwindow*,float); void (*setWindowOpacity)(_GLFWwindow*,float);
void (*setWindowMousePassthrough)(_GLFWwindow*,GLFWbool); void (*setWindowMousePassthrough)(_GLFWwindow*,GLFWbool);
GLFWtheme* (*getTheme)(_GLFWwindow*); _GLFWtheme* (*getTheme)(_GLFWwindow*);
void (*setTheme)(_GLFWwindow*,GLFWtheme*); void (*setTheme)(_GLFWwindow*,_GLFWtheme*);
// Events // Events
void (*pollEvents)(void); void (*pollEvents)(void);
void (*waitEvents)(void); void (*waitEvents)(void);
@ -936,7 +936,7 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value); void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value); void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
void _glfwInputSystemTheme(GLFWtheme* theme); void _glfwInputSystemTheme(_GLFWtheme* theme);
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement); void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window); void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);

View File

@ -140,7 +140,7 @@ void _glfwTerminateNull(void)
_glfwTerminateEGL(); _glfwTerminateEGL();
} }
GLFWtheme* _glfwGetSystemDefaultThemeNull(void) _GLFWtheme* _glfwGetSystemDefaultThemeNull(void)
{ {
return NULL; // TODO: should probably return a colorless GLFWtheme with baseTheme set to GLFW_BASE_THEME_LIGHT return NULL; // TODO: should probably return a colorless GLFWtheme with baseTheme set to GLFW_THEME_LIGHT
} }

View File

@ -147,6 +147,6 @@ VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, _GLFWwindow* window,
void _glfwPollMonitorsNull(void); void _glfwPollMonitorsNull(void);
GLFWtheme* _glfwGetSystemDefaultThemeNull(void); _GLFWtheme* _glfwGetSystemDefaultThemeNull(void);
void _glfwSetThemeNull(_GLFWwindow* window, GLFWtheme* theme); void _glfwSetThemeNull(_GLFWwindow* window, _GLFWtheme* theme);
GLFWtheme* _glfwGetThemeNull(_GLFWwindow* window); _GLFWtheme* _glfwGetThemeNull(_GLFWwindow* window);

View File

@ -551,11 +551,11 @@ const char* _glfwGetClipboardStringNull(void)
return _glfw.null.clipboardString; return _glfw.null.clipboardString;
} }
void _glfwSetThemeNull(_GLFWwindow* window, GLFWtheme* theme) void _glfwSetThemeNull(_GLFWwindow* window, _GLFWtheme* theme)
{ {
} }
GLFWtheme* _glfwGetThemeNull(_GLFWwindow* window) _GLFWtheme* _glfwGetThemeNull(_GLFWwindow* window)
{ {
return NULL; // TODO: see to-do in _glfwGetSystemDefaultThemeNull return NULL; // TODO: see to-do in _glfwGetSystemDefaultThemeNull
} }

88
src/theme.c Normal file
View File

@ -0,0 +1,88 @@
//
// theme.c
// glfw
//
// Created by Andreas Ormevik Jansen on 28/01/2023.
//
#include "internal.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
GLFWAPI GLFWtheme* glfwCreateTheme(void)
{
_GLFWtheme* theme = _glfw_calloc(1, sizeof(_GLFWtheme));
theme->variation = GLFW_THEME_DEFAULT;
theme->flags = 0;
return (GLFWtheme*) theme;
}
GLFWAPI void glfwDestroyTheme(GLFWtheme* theme)
{
_glfw_free((_GLFWtheme*) theme);
}
GLFWAPI void glfwCopyTheme(const GLFWtheme* source, GLFWtheme* target)
{
memcpy(target, source, sizeof(_GLFWtheme));
}
GLFWAPI int glfwThemeGetVariation(const GLFWtheme* theme)
{
assert(theme != NULL);
return ((_GLFWtheme*) theme)->variation;
}
GLFWAPI void glfwThemeSetVariation(GLFWtheme* theme, int value)
{
assert(theme != NULL);
assert(value == GLFW_THEME_DARK || value == GLFW_THEME_DEFAULT || value == GLFW_THEME_LIGHT);
((_GLFWtheme*) theme)->variation = value;
}
GLFWAPI int glfwThemeGetFlags(const GLFWtheme* theme)
{
assert(theme != NULL);
return ((_GLFWtheme*) theme)->flags;
}
GLFWAPI void glfwThemeSetFlags(GLFWtheme* theme, int value)
{
assert(theme != NULL);
assert((value & ~(GLFW_THEME_FLAG_HAS_COLOR | GLFW_THEME_FLAG_HIGH_CONTRAST | GLFW_THEME_FLAG_VIBRANT)) == 0);
((_GLFWtheme*) theme)->flags = value;
}
GLFWAPI void glfwThemeGetColor(const GLFWtheme* theme, float* red, float* green, float* blue, float* alpha)
{
assert(theme != NULL);
assert(red != NULL && green != NULL && blue != NULL && alpha != NULL);
const _GLFWtheme* iTheme = ((_GLFWtheme*) theme);
*red = iTheme->color[0] / 255.0f;
*green = iTheme->color[1] / 255.0f;
*blue = iTheme->color[2] / 255.0f;
*alpha = iTheme->color[3] / 255.0f;
}
GLFWAPI void glfwThemeSetColor(GLFWtheme* theme, float red, float green, float blue, float alpha)
{
assert(theme != NULL);
_GLFWtheme* iTheme = ((_GLFWtheme*) theme);
iTheme->color[0] = red * 255.0f;
iTheme->color[1] = green * 255.0f;
iTheme->color[2] = blue * 255.0f;
iTheme->color[3] = alpha * 255.0f;
}

View File

@ -737,7 +737,7 @@ void _glfwTerminateWin32(void)
freeLibraries(); freeLibraries();
} }
GLFWtheme* _glfwGetSystemDefaultThemeWin32(void) _GLFWtheme* _glfwGetSystemDefaultThemeWin32(void)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
return NULL; // TODO: implement return NULL; // TODO: implement

View File

@ -622,6 +622,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
GLFWtheme* _glfwGetSystemDefaultThemeWin32(void); _GLFWtheme* _glfwGetSystemDefaultThemeWin32(void);
void _glfwSetThemeWin32(_GLFWwindow* window, GLFWtheme* theme); void _glfwSetThemeWin32(_GLFWwindow* window, _GLFWtheme* theme);
GLFWtheme* _glfwGetThemeWin32(_GLFWwindow* window); _GLFWtheme* _glfwGetThemeWin32(_GLFWwindow* window);

View File

@ -2373,12 +2373,12 @@ const char* _glfwGetClipboardStringWin32(void)
return _glfw.win32.clipboardString; return _glfw.win32.clipboardString;
} }
void _glfwSetThemeWin32(_GLFWwindow* window, GLFWtheme* theme) void _glfwSetThemeWin32(_GLFWwindow* window, _GLFWtheme* theme)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
} }
GLFWtheme* _glfwGetThemeWin32(_GLFWwindow* window) _GLFWtheme* _glfwGetThemeWin32(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
return NULL; // TODO: implement return NULL; // TODO: implement

View File

@ -1160,7 +1160,7 @@ GLFWAPI void glfwSetTheme(GLFWwindow* handle, GLFWtheme* theme)
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfw.platform.setTheme(window, theme); _glfw.platform.setTheme(window, (_GLFWtheme*) theme);
} }
GLFWAPI GLFWtheme* glfwGetTheme(GLFWwindow* handle) GLFWAPI GLFWtheme* glfwGetTheme(GLFWwindow* handle)
@ -1169,5 +1169,5 @@ GLFWAPI GLFWtheme* glfwGetTheme(GLFWwindow* handle)
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfw.platform.getTheme(window); return (GLFWtheme*) _glfw.platform.getTheme(window);
} }

View File

@ -803,7 +803,7 @@ void _glfwTerminateWayland(void)
_glfw_free(_glfw.wl.clipboardString); _glfw_free(_glfw.wl.clipboardString);
} }
GLFWtheme* _glfwGetSystemDefaultThemeWayland(void) _GLFWtheme* _glfwGetSystemDefaultThemeWayland(void)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
return NULL; // TODO: implement return NULL; // TODO: implement

View File

@ -519,6 +519,6 @@ void _glfwUpdateContentScaleWayland(_GLFWwindow* window);
void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddSeatListenerWayland(struct wl_seat* seat);
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);
GLFWtheme* _glfwGetSystemDefaultThemeWayland(void); _GLFWtheme* _glfwGetSystemDefaultThemeWayland(void);
void _glfwSetThemeWayland(_GLFWwindow* window, GLFWtheme* theme); void _glfwSetThemeWayland(_GLFWwindow* window, _GLFWtheme* theme);
GLFWtheme* _glfwGetThemeWayland(_GLFWwindow* window); _GLFWtheme* _glfwGetThemeWayland(_GLFWwindow* window);

View File

@ -2775,12 +2775,12 @@ const char* _glfwGetClipboardStringWayland(void)
return _glfw.wl.clipboardString; return _glfw.wl.clipboardString;
} }
void _glfwSetThemeWayland(_GLFWwindow* window, GLFWtheme* theme) void _glfwSetThemeWayland(_GLFWwindow* window, _GLFWtheme* theme)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
} }
GLFWtheme* _glfwGetThemeWayland(_GLFWwindow* window) _GLFWtheme* _glfwGetThemeWayland(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
return NULL; // TODO: implement return NULL; // TODO: implement

View File

@ -1664,7 +1664,7 @@ void _glfwTerminateX11(void)
} }
} }
GLFWtheme* _glfwGetSystemDefaultThemeX11(void) _GLFWtheme* _glfwGetSystemDefaultThemeX11(void)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
return NULL; // TODO: implement return NULL; // TODO: implement

View File

@ -1002,6 +1002,6 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth); Visual** visual, int* depth);
GLFWtheme* _glfwGetSystemDefaultThemeX11(void); _GLFWtheme* _glfwGetSystemDefaultThemeX11(void);
void _glfwSetThemeX11(_GLFWwindow* window, GLFWtheme* theme); void _glfwSetThemeX11(_GLFWwindow* window, _GLFWtheme* theme);
GLFWtheme* _glfwGetThemeX11(_GLFWwindow* window); _GLFWtheme* _glfwGetThemeX11(_GLFWwindow* window);

View File

@ -3082,12 +3082,12 @@ const char* _glfwGetClipboardStringX11(void)
return getSelectionString(_glfw.x11.CLIPBOARD); return getSelectionString(_glfw.x11.CLIPBOARD);
} }
void _glfwSetThemeX11(_GLFWwindow* window, GLFWtheme* theme) void _glfwSetThemeX11(_GLFWwindow* window, _GLFWtheme* theme)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
} }
GLFWtheme* _glfwGetThemeX11(_GLFWwindow* window) _GLFWtheme* _glfwGetThemeX11(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL); _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, NULL);
return NULL; // TODO: implement return NULL; // TODO: implement

View File

@ -36,75 +36,84 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
const unsigned char theme_colors[6][4] = const float theme_colors[6][4] =
{ {
{ 0, 0, 0, 255 }, // black { 0, 0, 0, 1.0 }, // black
{ 255, 0, 0, 255 }, // red { 1.0, 0, 0, 1.0 }, // red
{ 0, 255, 0, 255 }, // green { 0, 1.0, 0, 1.0 }, // green
{ 0, 0, 255, 255 }, // blue { 0, 0, 1.0, 1.0 }, // blue
{ 255, 255, 255, 255 }, // white { 1.0, 1.0, 1.0, 1.0 }, // white
{ 128, 128, 128, 255 } // gray (no theme color) { 0.5, 0.5, 0.5, 1.0 } // gray (no theme color)
}; };
static int cur_theme_color = 0; static int cur_theme_color = 0;
static GLFWtheme theme; static GLFWtheme* theme;
static void print_theme(GLFWtheme* theme, const char* title) static void print_theme(GLFWtheme* theme, const char* title)
{ {
const int flags = glfwThemeGetFlags(theme);
int n = 0; int n = 0;
printf("%s: {\n", title); printf("%s: {\n", title);
printf(" Base: %s\n", theme->baseTheme == GLFW_BASE_THEME_LIGHT ? "light" : "dark"); printf(" Base: %s\n", glfwThemeGetVariation(theme) == GLFW_THEME_LIGHT ? "light" : "dark");
printf(" Flags: ["); printf(" Flags: [");
if (theme->flags & GLFW_THEME_FLAG_HAS_COLOR) if (flags & GLFW_THEME_FLAG_HAS_COLOR)
{ {
printf(n++ > 0 ? ", %s" : "%s", "HAS_COLOR"); printf(n++ > 0 ? ", %s" : "%s", "HAS_COLOR");
} }
if (theme->flags & GLFW_THEME_FLAG_VIBRANT) if (flags & GLFW_THEME_FLAG_VIBRANT)
{ {
printf(n++ > 0 ? ", %s" : "%s", "VIBRANT"); printf(n++ > 0 ? ", %s" : "%s", "VIBRANT");
} }
if (theme->flags & GLFW_THEME_FLAG_HIGH_CONTRAST) if (flags & GLFW_THEME_FLAG_HIGH_CONTRAST)
{ {
printf(n++ > 0 ? ", %s" : "%s", "HIGH_CONTRAST"); printf(n++ > 0 ? ", %s" : "%s", "HIGH_CONTRAST");
} }
printf("]\n"); printf("]\n");
if (theme->flags & GLFW_THEME_FLAG_HAS_COLOR) if (flags & GLFW_THEME_FLAG_HAS_COLOR)
{ {
printf(" Color: [%i, %i, %i, %i]\n", theme->color[0], theme->color[1], theme->color[2], theme->color[3]); float r, g, b, a;
glfwThemeGetColor(theme, &r, &g, &b, &a);
printf(" Color: [%f, %f, %f, %f]\n", r, g, b, a);
} }
printf("}\n"); printf("}\n");
} }
static void set_theme(GLFWwindow* window, int theme_color) static void set_theme(GLFWwindow* window, int theme_color)
{ {
memcpy(theme.color, theme_colors[theme_color], 4); glfwThemeSetColor(
theme,
theme_colors[theme_color][0],
theme_colors[theme_color][1],
theme_colors[theme_color][2],
theme_colors[theme_color][3]
);
if (theme_color == 6) if (theme_color == 6)
{ {
theme.flags &= ~GLFW_THEME_FLAG_HAS_COLOR; glfwThemeSetFlags(theme, glfwThemeGetFlags(theme) & ~GLFW_THEME_FLAG_HAS_COLOR);
} else } else
{ {
theme.flags |= GLFW_THEME_FLAG_HAS_COLOR; glfwThemeSetFlags(theme, glfwThemeGetFlags(theme) | GLFW_THEME_FLAG_HAS_COLOR);
} }
const char* title; const char* title;
switch (theme.baseTheme) { switch (glfwThemeGetVariation(theme)) {
case GLFW_BASE_THEME_DEFAULT: case GLFW_THEME_DEFAULT:
title = "Default theme"; title = "Default theme";
break; break;
case GLFW_BASE_THEME_LIGHT: case GLFW_THEME_LIGHT:
title = "Light theme"; title = "Light theme";
break; break;
case GLFW_BASE_THEME_DARK: case GLFW_THEME_DARK:
title = "Dark theme"; title = "Dark theme";
break; break;
} }
glfwSetWindowTitle(window, title); glfwSetWindowTitle(window, title);
glfwSetTheme(window, &theme); glfwSetTheme(window, theme);
} }
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)
@ -119,15 +128,15 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
glfwSetTheme(window, NULL); glfwSetTheme(window, NULL);
break; break;
case GLFW_KEY_1: case GLFW_KEY_1:
theme.baseTheme = GLFW_BASE_THEME_DEFAULT; glfwThemeSetVariation(theme, GLFW_THEME_DEFAULT);
set_theme(window, cur_theme_color); set_theme(window, cur_theme_color);
break; break;
case GLFW_KEY_2: case GLFW_KEY_2:
theme.baseTheme = GLFW_BASE_THEME_LIGHT; glfwThemeSetVariation(theme, GLFW_THEME_LIGHT);
set_theme(window, cur_theme_color); set_theme(window, cur_theme_color);
break; break;
case GLFW_KEY_3: case GLFW_KEY_3:
theme.baseTheme = GLFW_BASE_THEME_DARK; glfwThemeSetVariation(theme, GLFW_THEME_DARK);
set_theme(window, cur_theme_color); set_theme(window, cur_theme_color);
break; break;
case GLFW_KEY_ESCAPE: case GLFW_KEY_ESCAPE:
@ -172,12 +181,11 @@ int main(int argc, char** argv)
glfwSetKeyCallback(window, key_callback); glfwSetKeyCallback(window, key_callback);
theme.baseTheme = GLFW_BASE_THEME_DEFAULT; theme = glfwCreateTheme();
theme.flags = 0;
theme.color[0] = 0; glfwThemeSetVariation(theme, GLFW_THEME_DEFAULT);
theme.color[1] = 0; glfwThemeSetFlags(theme, 0);
theme.color[2] = 0; glfwThemeSetColor(theme, 0, 0, 0, 0);
theme.color[3] = 0;
set_theme(window, cur_theme_color); set_theme(window, cur_theme_color);
glfwSetSystemThemeCallback(theme_callback); glfwSetSystemThemeCallback(theme_callback);
@ -195,6 +203,7 @@ int main(int argc, char** argv)
glfwWaitEvents(); glfwWaitEvents();
} }
glfwDestroyTheme(theme);
glfwDestroyWindow(window); glfwDestroyWindow(window);
glfwTerminate(); glfwTerminate();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);