Function to get the current system color theme

This commit is contained in:
Kovid Goyal 2024-11-07 12:47:06 +05:30
parent 239e08f268
commit b0ebd340fe
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
13 changed files with 99 additions and 29 deletions

View file

@ -952,7 +952,7 @@ - (void)mouseEntered:(NSEvent *)event
- (void)viewDidChangeEffectiveAppearance - (void)viewDidChangeEffectiveAppearance
{ {
static GLFWColorScheme appearance = GLFW_COLOR_SCHEME_NO_PREFERENCE; static GLFWColorScheme appearance = GLFW_COLOR_SCHEME_NO_PREFERENCE;
GLFWColorScheme new_appearance = glfwGetCurrentSystemColorTheme(); GLFWColorScheme new_appearance = glfwGetCurrentSystemColorTheme(true);
if (new_appearance != appearance) { if (new_appearance != appearance) {
appearance = new_appearance; appearance = new_appearance;
_glfwInputColorScheme(appearance, false); _glfwInputColorScheme(appearance, false);
@ -3091,7 +3091,8 @@ GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool us
[window->ns.object makeFirstResponder:window->ns.view]; [window->ns.object makeFirstResponder:window->ns.view];
}} }}
GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(void) { GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized) {
(void)query_if_unintialized;
int theme_type = 0; int theme_type = 0;
NSAppearance *changedAppearance = NSApp.effectiveAppearance; NSAppearance *changedAppearance = NSApp.effectiveAppearance;
NSAppearanceName newAppearance = [changedAppearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]]; NSAppearanceName newAppearance = [changedAppearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];

31
glfw/dbus_glfw.c vendored
View file

@ -234,12 +234,21 @@ method_reply_received(DBusPendingCall *pending, void *user_data) {
} }
bool bool
call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_pending_callback callback, void *user_data) { call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_pending_callback callback, void *user_data, bool block) {
bool retval = false; bool retval = false;
#define REPORT(errs) _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: node=%s path=%s interface=%s method=%s, with error: %s", dbus_message_get_destination(msg), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), errs) #define REPORT(errs) _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: node=%s path=%s interface=%s method=%s, with error: %s", dbus_message_get_destination(msg), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), errs)
if (callback) { if (callback) {
DBusPendingCall *pending = NULL; DBusPendingCall *pending = NULL;
if (dbus_connection_send_with_reply(conn, msg, &pending, timeout)) { if (block) {
DBusError error; dbus_error_init(&error);
RAII_MSG(reply, dbus_connection_send_with_reply_and_block(session_bus, msg, timeout, &error));
if (dbus_error_is_set(&error)) {
callback(reply, error.message, user_data);
return false;
} else if (reply) {
callback(reply, NULL, user_data);
} else return false;
} else if (dbus_connection_send_with_reply(conn, msg, &pending, timeout)) {
MethodResponse *res = malloc(sizeof(MethodResponse)); MethodResponse *res = malloc(sizeof(MethodResponse));
if (!res) return false; if (!res) return false;
res->callback = callback; res->callback = callback;
@ -261,7 +270,7 @@ call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_p
} }
static bool static bool
call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void *user_data, va_list ap) { call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void *user_data, bool blocking, va_list ap) {
if (!conn || !path) return false; if (!conn || !path) return false;
RAII_MSG(msg, dbus_message_new_method_call(node, path, interface, method)); RAII_MSG(msg, dbus_message_new_method_call(node, path, interface, method));
if (!msg) return false; if (!msg) return false;
@ -269,7 +278,7 @@ call_method(DBusConnection *conn, const char *node, const char *path, const char
int firstarg = va_arg(ap, int); int firstarg = va_arg(ap, int);
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) { if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) {
retval = call_method_with_msg(conn, msg, timeout, callback, user_data); retval = call_method_with_msg(conn, msg, timeout, callback, user_data, blocking);
} else { } else {
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s could not add arguments", method, node, interface); _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s could not add arguments", method, node, interface);
} }
@ -282,7 +291,17 @@ glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const c
bool retval; bool retval;
va_list ap; va_list ap;
va_start(ap, user_data); va_start(ap, user_data);
retval = call_method(conn, node, path, interface, method, timeout, callback, user_data, ap); retval = call_method(conn, node, path, interface, method, timeout, callback, user_data, false, ap);
va_end(ap);
return retval;
}
bool
glfw_dbus_call_blocking_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void* user_data, ...) {
bool retval;
va_list ap;
va_start(ap, user_data);
retval = call_method(conn, node, path, interface, method, timeout, callback, user_data, true, ap);
va_end(ap); va_end(ap);
return retval; return retval;
} }
@ -292,7 +311,7 @@ glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const cha
bool retval; bool retval;
va_list ap; va_list ap;
va_start(ap, method); va_start(ap, method);
retval = call_method(conn, node, path, interface, method, DBUS_TIMEOUT_USE_DEFAULT, NULL, NULL, ap); retval = call_method(conn, node, path, interface, method, DBUS_TIMEOUT_USE_DEFAULT, NULL, NULL, false, ap);
va_end(ap); va_end(ap);
return retval; return retval;
} }

4
glfw/dbus_glfw.h vendored
View file

@ -45,11 +45,13 @@ void glfw_dbus_terminate(_GLFWDBUSData *dbus);
DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg, const char* name, bool register_on_bus); DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg, const char* name, bool register_on_bus);
void glfw_dbus_close_connection(DBusConnection *conn); void glfw_dbus_close_connection(DBusConnection *conn);
bool bool
call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_pending_callback callback, void *user_data); call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_pending_callback callback, void *user_data, bool block);
bool bool
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...); glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
bool bool
glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout_ms, dbus_pending_callback callback, void *user_data, ...); glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout_ms, dbus_pending_callback callback, void *user_data, ...);
bool
glfw_dbus_call_blocking_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void* user_data, ...);
void glfw_dbus_dispatch(DBusConnection *); void glfw_dbus_dispatch(DBusConnection *);
void glfw_dbus_session_bus_dispatch(void); void glfw_dbus_session_bus_dispatch(void);
bool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...); bool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...);

2
glfw/glfw3.h vendored
View file

@ -3982,7 +3982,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback); GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback);
GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun callback); GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun callback);
GLFWAPI GLFWsystemcolorthemechangefun glfwSetSystemColorThemeChangeCallback(GLFWsystemcolorthemechangefun callback); GLFWAPI GLFWsystemcolorthemechangefun glfwSetSystemColorThemeChangeCallback(GLFWsystemcolorthemechangefun callback);
GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(void); GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized);
/*! @brief Sets the refresh callback for the specified window. /*! @brief Sets the refresh callback for the specified window.
* *

View file

@ -22,12 +22,7 @@ static const char* supported_namespaces[2] = {FDO_DESKTOP_NAMESPACE, GNOME_DESKT
static char theme_name[128] = {0}; static char theme_name[128] = {0};
static int theme_size = -1; static int theme_size = -1;
static GLFWColorScheme appearance = GLFW_COLOR_SCHEME_NO_PREFERENCE; static GLFWColorScheme appearance = GLFW_COLOR_SCHEME_NO_PREFERENCE;
static bool cursor_theme_changed = false; static bool cursor_theme_changed = false, appearance_initialized = false;
GLFWColorScheme
glfw_current_system_color_theme(void) {
return appearance;
}
#define HANDLER(name) static void name(DBusMessage *msg, const char* errmsg, void *data) { \ #define HANDLER(name) static void name(DBusMessage *msg, const char* errmsg, void *data) { \
(void)data; \ (void)data; \
@ -36,6 +31,34 @@ glfw_current_system_color_theme(void) {
return; \ return; \
} }
HANDLER(get_color_scheme)
uint32_t val;
DBusMessageIter iter, variant_iter;
if (!dbus_message_iter_init(msg, &iter)) return;
dbus_message_iter_recurse(&iter, &variant_iter);
int type = dbus_message_iter_get_arg_type(&variant_iter);
if (type != DBUS_TYPE_UINT32) {
_glfwInputError(GLFW_PLATFORM_ERROR, "ReadOne for color-scheme did not return a uint32"); return;
}
dbus_message_iter_get_basic(&variant_iter, &val);
if (val < 3) appearance = val;
}
GLFWColorScheme
glfw_current_system_color_theme(bool query_if_unintialized) {
if (!appearance_initialized && query_if_unintialized) {
appearance_initialized = true;
DBusConnection *session_bus = glfw_dbus_session_bus();
if (session_bus) {
const char *namespace = FDO_DESKTOP_NAMESPACE, *key = FDO_APPEARANCE_KEY;
glfw_dbus_call_blocking_method(session_bus, DESKTOP_SERVICE, DESKTOP_PATH, DESKTOP_INTERFACE, "ReadOne", DBUS_TIMEOUT_USE_DEFAULT,
get_color_scheme, NULL, DBUS_TYPE_STRING, &namespace, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID);
}
}
return appearance;
}
static void static void
process_fdo_setting(const char *key, DBusMessageIter *value) { process_fdo_setting(const char *key, DBusMessageIter *value) {
if (strcmp(key, FDO_APPEARANCE_KEY) == 0) { if (strcmp(key, FDO_APPEARANCE_KEY) == 0) {
@ -43,8 +66,13 @@ process_fdo_setting(const char *key, DBusMessageIter *value) {
uint32_t val; uint32_t val;
dbus_message_iter_get_basic(value, &val); dbus_message_iter_get_basic(value, &val);
if (val > 2) val = 0; if (val > 2) val = 0;
appearance = val; if (!appearance_initialized) {
_glfwInputColorScheme(appearance, true); appearance_initialized = true;
if (val != appearance) {
appearance = val;
_glfwInputColorScheme(appearance, true);
}
}
} }
} }
} }
@ -131,7 +159,7 @@ read_desktop_settings(DBusConnection *session_bus) {
if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &supported_namespaces[i])) return false; if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &supported_namespaces[i])) return false;
} }
if (!dbus_message_iter_close_container(&iter, &array_iter)) { return false; } if (!dbus_message_iter_close_container(&iter, &array_iter)) { return false; }
return call_method_with_msg(session_bus, msg, DBUS_TIMEOUT_USE_DEFAULT, process_desktop_settings, NULL); return call_method_with_msg(session_bus, msg, DBUS_TIMEOUT_USE_DEFAULT, process_desktop_settings, NULL, false);
} }
void void
@ -166,6 +194,7 @@ on_color_scheme_change(DBusMessage *message) {
if (val > 2) val = 0; if (val > 2) val = 0;
if (val != appearance) { if (val != appearance) {
appearance = val; appearance = val;
appearance_initialized = true;
_glfwInputColorScheme(appearance, false); _glfwInputColorScheme(appearance, false);
} }
} }

View file

@ -12,4 +12,4 @@
void glfw_initialize_desktop_settings(void); void glfw_initialize_desktop_settings(void);
void glfw_current_cursor_theme(const char **theme, int *size); void glfw_current_cursor_theme(const char **theme, int *size);
GLFWColorScheme glfw_current_system_color_theme(void); GLFWColorScheme glfw_current_system_color_theme(bool);

2
glfw/linux_notify.c vendored
View file

@ -184,7 +184,7 @@ glfw_dbus_send_user_notification(const GLFWDBUSNotificationData *n, GLFWDBusnoti
APPEND(args, DBUS_TYPE_INT32, n->timeout) APPEND(args, DBUS_TYPE_INT32, n->timeout)
#undef check_call #undef check_call
#undef APPEND #undef APPEND
if (!call_method_with_msg(session_bus, msg, 5000, notification_created, data)) return 0; if (!call_method_with_msg(session_bus, msg, 5000, notification_created, data, false)) return 0;
notification_id_type ans = data->next_id; notification_id_type ans = data->next_id;
data = NULL; data = NULL;
return ans; return ans;

View file

@ -332,7 +332,7 @@ render_title_bar(_GLFWwindow *window, bool to_front_buffer) {
const uint32_t dark_fg = is_focused ? 0xffffffff : 0xffcccccc, dark_bg = is_focused ? 0xff303030 : 0xff242424; const uint32_t dark_fg = is_focused ? 0xffffffff : 0xffcccccc, dark_bg = is_focused ? 0xff303030 : 0xff242424;
static const uint32_t hover_dark_bg = 0xff444444, hover_light_bg = 0xffbbbbbb; static const uint32_t hover_dark_bg = 0xff444444, hover_light_bg = 0xffbbbbbb;
uint32_t bg_color = light_bg, fg_color = light_fg, hover_bg = hover_light_bg; uint32_t bg_color = light_bg, fg_color = light_fg, hover_bg = hover_light_bg;
GLFWColorScheme appearance = glfwGetCurrentSystemColorTheme(); GLFWColorScheme appearance = glfwGetCurrentSystemColorTheme(false);
bool is_dark = false; bool is_dark = false;
if (decs.use_custom_titlebar_color || appearance == GLFW_COLOR_SCHEME_NO_PREFERENCE) { if (decs.use_custom_titlebar_color || appearance == GLFW_COLOR_SCHEME_NO_PREFERENCE) {
bg_color = 0xff000000 | (decs.titlebar_color & 0xffffff); bg_color = 0xff000000 | (decs.titlebar_color & 0xffffff);

4
glfw/wl_init.c vendored
View file

@ -636,8 +636,8 @@ static const struct wl_registry_listener registryListener = {
}; };
GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(void) { GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized) {
return glfw_current_system_color_theme(); return glfw_current_system_color_theme(query_if_unintialized);
} }
static pid_t static pid_t

4
glfw/x11_init.c vendored
View file

@ -615,8 +615,8 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(void) { GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized) {
return GLFW_COLOR_SCHEME_NO_PREFERENCE; return glfw_current_system_color_theme(query_if_unintialized);
} }
void _glfwPlatformInputColorScheme(GLFWColorScheme appearance UNUSED) { } void _glfwPlatformInputColorScheme(GLFWColorScheme appearance UNUSED) { }

View file

@ -1711,6 +1711,7 @@ def opengl_version_string() -> str: ...
def systemd_move_pid_into_new_scope(pid: int, scope_name: str, description: str) -> str: ... def systemd_move_pid_into_new_scope(pid: int, scope_name: str, description: str) -> str: ...
def play_desktop_sound_async(name: str, event_id: str = 'test sound', is_path: bool = False, theme_name: str = '') -> str: ... def play_desktop_sound_async(name: str, event_id: str = 'test sound', is_path: bool = False, theme_name: str = '') -> str: ...
def cocoa_play_system_sound_by_id_async(sound_id: int) -> None: ... def cocoa_play_system_sound_by_id_async(sound_id: int) -> None: ...
def glfw_get_system_color_theme(query_if_unintialized: bool = True) -> Literal['light', 'dark', 'no_preference']: ...
class MousePosition(TypedDict): class MousePosition(TypedDict):
cell_x: int cell_x: int

2
kitty/glfw-wrapper.h generated
View file

@ -2010,7 +2010,7 @@ typedef GLFWsystemcolorthemechangefun (*glfwSetSystemColorThemeChangeCallback_fu
GFW_EXTERN glfwSetSystemColorThemeChangeCallback_func glfwSetSystemColorThemeChangeCallback_impl; GFW_EXTERN glfwSetSystemColorThemeChangeCallback_func glfwSetSystemColorThemeChangeCallback_impl;
#define glfwSetSystemColorThemeChangeCallback glfwSetSystemColorThemeChangeCallback_impl #define glfwSetSystemColorThemeChangeCallback glfwSetSystemColorThemeChangeCallback_impl
typedef GLFWColorScheme (*glfwGetCurrentSystemColorTheme_func)(void); typedef GLFWColorScheme (*glfwGetCurrentSystemColorTheme_func)(bool);
GFW_EXTERN glfwGetCurrentSystemColorTheme_func glfwGetCurrentSystemColorTheme_impl; GFW_EXTERN glfwGetCurrentSystemColorTheme_func glfwGetCurrentSystemColorTheme_impl;
#define glfwGetCurrentSystemColorTheme glfwGetCurrentSystemColorTheme_impl #define glfwGetCurrentSystemColorTheme glfwGetCurrentSystemColorTheme_impl

View file

@ -46,14 +46,20 @@ get_platform_dependent_config_values(void *glfw_window) {
} }
} }
static void static const char*
on_system_color_scheme_change(GLFWColorScheme appearance, bool is_initial_value) { appearance_name(GLFWColorScheme appearance) {
const char *which = NULL; const char *which = NULL;
switch (appearance) { switch (appearance) {
case GLFW_COLOR_SCHEME_NO_PREFERENCE: which = "no_preference"; break; case GLFW_COLOR_SCHEME_NO_PREFERENCE: which = "no_preference"; break;
case GLFW_COLOR_SCHEME_DARK: which = "dark"; break; case GLFW_COLOR_SCHEME_DARK: which = "dark"; break;
case GLFW_COLOR_SCHEME_LIGHT: which = "light"; break; case GLFW_COLOR_SCHEME_LIGHT: which = "light"; break;
} }
return which;
}
static void
on_system_color_scheme_change(GLFWColorScheme appearance, bool is_initial_value) {
const char *which = appearance_name(appearance);
debug("system color-scheme changed to: %s is_initial_value: %d\n", which, is_initial_value); debug("system color-scheme changed to: %s is_initial_value: %d\n", which, is_initial_value);
call_boss(on_system_color_scheme_change, "sO", which, is_initial_value ? Py_True : Py_False); call_boss(on_system_color_scheme_change, "sO", which, is_initial_value ? Py_True : Py_False);
} }
@ -1519,6 +1525,17 @@ glfw_get_physical_dpi(PYNOARG) {
return get_physical_dpi(m); return get_physical_dpi(m);
} }
static PyObject*
glfw_get_system_color_theme(PyObject UNUSED *self, PyObject *args) {
int query_if_unintialized = 1;
if (!PyArg_ParseTuple(args, "|p", &query_if_unintialized)) return NULL;
if (!glfwGetCurrentSystemColorTheme) {
PyErr_SetString(PyExc_RuntimeError, "must initialize GFLW before calling this function"); return NULL;
}
const char *which = appearance_name(glfwGetCurrentSystemColorTheme(query_if_unintialized));
return PyUnicode_FromString(which);
}
static PyObject* static PyObject*
glfw_get_key_name(PyObject UNUSED *self, PyObject *args) { glfw_get_key_name(PyObject UNUSED *self, PyObject *args) {
int key, native_key; int key, native_key;
@ -2306,6 +2323,7 @@ static PyMethodDef module_methods[] = {
{"glfw_terminate", (PyCFunction)glfw_terminate, METH_NOARGS, ""}, {"glfw_terminate", (PyCFunction)glfw_terminate, METH_NOARGS, ""},
{"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""}, {"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""},
{"glfw_get_key_name", (PyCFunction)glfw_get_key_name, METH_VARARGS, ""}, {"glfw_get_key_name", (PyCFunction)glfw_get_key_name, METH_VARARGS, ""},
{"glfw_get_system_color_theme", (PyCFunction)glfw_get_system_color_theme, METH_VARARGS, ""},
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""}, {"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""},
{"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""}, {"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */ {NULL, NULL, 0, NULL} /* Sentinel */