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 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)viewDidChangeEffectiveAppearance
{
static GLFWColorScheme appearance = GLFW_COLOR_SCHEME_NO_PREFERENCE;
GLFWColorScheme new_appearance = glfwGetCurrentSystemColorTheme();
GLFWColorScheme new_appearance = glfwGetCurrentSystemColorTheme(true);
if (new_appearance != appearance) {
appearance = new_appearance;
_glfwInputColorScheme(appearance, false);
@ -3091,7 +3091,8 @@ GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool us
[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;
NSAppearance *changedAppearance = NSApp.effectiveAppearance;
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
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;
#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) {
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));
if (!res) return false;
res->callback = callback;
@ -261,7 +270,7 @@ call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_p
}
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;
RAII_MSG(msg, dbus_message_new_method_call(node, path, interface, method));
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);
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 {
_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;
va_list ap;
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);
return retval;
}
@ -292,7 +311,7 @@ glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const cha
bool retval;
va_list ap;
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);
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);
void glfw_dbus_close_connection(DBusConnection *conn);
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
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
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, ...);
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_session_bus_dispatch(void);
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 GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun 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.
*

View file

@ -22,12 +22,7 @@ static const char* supported_namespaces[2] = {FDO_DESKTOP_NAMESPACE, GNOME_DESKT
static char theme_name[128] = {0};
static int theme_size = -1;
static GLFWColorScheme appearance = GLFW_COLOR_SCHEME_NO_PREFERENCE;
static bool cursor_theme_changed = false;
GLFWColorScheme
glfw_current_system_color_theme(void) {
return appearance;
}
static bool cursor_theme_changed = false, appearance_initialized = false;
#define HANDLER(name) static void name(DBusMessage *msg, const char* errmsg, void *data) { \
(void)data; \
@ -36,6 +31,34 @@ glfw_current_system_color_theme(void) {
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
process_fdo_setting(const char *key, DBusMessageIter *value) {
if (strcmp(key, FDO_APPEARANCE_KEY) == 0) {
@ -43,8 +66,13 @@ process_fdo_setting(const char *key, DBusMessageIter *value) {
uint32_t val;
dbus_message_iter_get_basic(value, &val);
if (val > 2) val = 0;
appearance = val;
_glfwInputColorScheme(appearance, true);
if (!appearance_initialized) {
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_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
@ -166,6 +194,7 @@ on_color_scheme_change(DBusMessage *message) {
if (val > 2) val = 0;
if (val != appearance) {
appearance = val;
appearance_initialized = true;
_glfwInputColorScheme(appearance, false);
}
}

View file

@ -12,4 +12,4 @@
void glfw_initialize_desktop_settings(void);
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)
#undef check_call
#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;
data = NULL;
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;
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;
GLFWColorScheme appearance = glfwGetCurrentSystemColorTheme();
GLFWColorScheme appearance = glfwGetCurrentSystemColorTheme(false);
bool is_dark = false;
if (decs.use_custom_titlebar_color || appearance == GLFW_COLOR_SCHEME_NO_PREFERENCE) {
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) {
return glfw_current_system_color_theme();
GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized) {
return glfw_current_system_color_theme(query_if_unintialized);
}
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 //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(void) {
return GLFW_COLOR_SCHEME_NO_PREFERENCE;
GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized) {
return glfw_current_system_color_theme(query_if_unintialized);
}
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 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 glfw_get_system_color_theme(query_if_unintialized: bool = True) -> Literal['light', 'dark', 'no_preference']: ...
class MousePosition(TypedDict):
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;
#define glfwSetSystemColorThemeChangeCallback glfwSetSystemColorThemeChangeCallback_impl
typedef GLFWColorScheme (*glfwGetCurrentSystemColorTheme_func)(void);
typedef GLFWColorScheme (*glfwGetCurrentSystemColorTheme_func)(bool);
GFW_EXTERN glfwGetCurrentSystemColorTheme_func glfwGetCurrentSystemColorTheme_impl;
#define glfwGetCurrentSystemColorTheme glfwGetCurrentSystemColorTheme_impl

View file

@ -46,14 +46,20 @@ get_platform_dependent_config_values(void *glfw_window) {
}
}
static void
on_system_color_scheme_change(GLFWColorScheme appearance, bool is_initial_value) {
static const char*
appearance_name(GLFWColorScheme appearance) {
const char *which = NULL;
switch (appearance) {
case GLFW_COLOR_SCHEME_NO_PREFERENCE: which = "no_preference"; break;
case GLFW_COLOR_SCHEME_DARK: which = "dark"; 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);
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);
}
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*
glfw_get_key_name(PyObject UNUSED *self, PyObject *args) {
int key, native_key;
@ -2306,6 +2323,7 @@ static PyMethodDef module_methods[] = {
{"glfw_terminate", (PyCFunction)glfw_terminate, 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_system_color_theme", (PyCFunction)glfw_get_system_color_theme, METH_VARARGS, ""},
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""},
{"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */