From 190566be8e0cf9afd7cd5b3fa9ee1c0d03b8d875 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Jun 2024 12:53:37 +0530 Subject: [PATCH] Wayland: Fix specifying the output name for the panel kitten not working Fixes #7573 --- docs/changelog.rst | 2 ++ glfw/glfw.py | 2 +- glfw/glfw3.h | 2 +- glfw/wl_monitor.c | 21 ++++++++++++++++++--- glfw/wl_platform.h | 1 + glfw/wl_window.c | 20 ++++++-------------- kitty/glfw-wrapper.h | 4 ++-- kitty/glfw.c | 27 ++++++++++++++++++++------- 8 files changed, 51 insertions(+), 28 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 90dec67f3..7a61533e1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -74,6 +74,8 @@ Detailed list of changes - Wayland: Allow fractional scales less than one (:pull:`7549`) +- Wayland: Fix specifying the output name for the panel kitten not working (:iss:`7573`) + 0.35.2 [2024-06-22] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/glfw.py b/glfw/glfw.py index 8733983c6..afe47ed86 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -323,7 +323,7 @@ def generate_wrappers(glfw_header: str) -> None: void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data) bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color) void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) - void glfwWaylandSetupLayerShellForNextWindow(GLFWLayerShellConfig c) + void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig *c) pid_t glfwWaylandCompositorPID(void) unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \ const char *action_text, int32_t timeout, int urgency, GLFWDBusnotificationcreatedfun callback, void *data) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index c12979a6c..1bba46b61 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1309,7 +1309,7 @@ typedef enum { GLFW_FOCUS_NOT_ALLOWED, GLFW_FOCUS_EXCLUSIVE, GLFW_FOCUS_ON_DEMAN typedef struct GLFWLayerShellConfig { GLFWLayerShellType type; GLFWEdge edge; - const char *output_name; + char output_name[64]; GLFWFocusPolicy focus_policy; unsigned size_in_cells; void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height); diff --git a/glfw/wl_monitor.c b/glfw/wl_monitor.c index 15cc0bc14..6d96e1333 100644 --- a/glfw/wl_monitor.c +++ b/glfw/wl_monitor.c @@ -31,7 +31,6 @@ #include #include #include -#include #include @@ -90,7 +89,6 @@ static void outputHandleDone(void* data, struct wl_output* output UNUSED) for (int i = 0; i < _glfw.monitorCount; i++) { if (_glfw.monitors[i] == monitor) return; } - _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); } @@ -103,11 +101,28 @@ static void outputHandleScale(void* data, monitor->wl.scale = factor; } +static void outputHandleName(void* data, + struct wl_output* output UNUSED, + const char* name) { + struct _GLFWmonitor *monitor = data; + if (name) strncpy(monitor->wl.friendly_name, name, sizeof(monitor->wl.friendly_name)-1); +} + +static void outputHandleDescription(void* data, + struct wl_output* output UNUSED, + const char* description) { + struct _GLFWmonitor *monitor = data; + if (description) strncpy(monitor->wl.description, description, sizeof(monitor->wl.description)-1); + +} + static const struct wl_output_listener outputListener = { outputHandleGeometry, outputHandleMode, outputHandleDone, outputHandleScale, + outputHandleName, + outputHandleDescription, }; @@ -133,7 +148,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version) output = wl_registry_bind(_glfw.wl.registry, name, &wl_output_interface, - 2); + MIN(version, (unsigned)WL_OUTPUT_NAME_SINCE_VERSION)); if (!output) { _glfwFreeMonitor(monitor); diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index 4e52d7828..f3904b88c 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -395,6 +395,7 @@ typedef struct _GLFWmonitorWayland { struct wl_output* output; uint32_t name; + char friendly_name[64], description[64]; int currentMode; int x; diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 948d662a3..8af8299ab 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -953,14 +953,10 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled UNUSED) { static struct wl_output* find_output_by_name(const char* name) { - if (!name) return NULL; - int count; - GLFWmonitor** monitors = glfwGetMonitors(&count); - for (int i = 0; i < count; ++i) { - _GLFWmonitor *m = (_GLFWmonitor*)monitors + i; - if (strcmp(m->name, name) == 0) { - return m->wl.output; - } + if (!name || !name[0]) return NULL; + for (int i = 0; i < _glfw.monitorCount; i++) { + _GLFWmonitor *m = _glfw.monitors[i]; + if (strcmp(m->wl.friendly_name, name) == 0) return m->wl.output; } return NULL; } @@ -1399,7 +1395,6 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) wp_viewport_destroy(window->wl.wp_viewport); if (window->wl.org_kde_kwin_blur) org_kde_kwin_blur_release(window->wl.org_kde_kwin_blur); - if (window->wl.layer_shell.config.output_name) free((void*)window->wl.layer_shell.config.output_name); if (window->context.destroy) window->context.destroy(window); @@ -2747,11 +2742,8 @@ GLFWAPI void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) { if (csd_change_title(window)) commit_window_surface_if_safe(window); } -GLFWAPI void glfwWaylandSetupLayerShellForNextWindow(GLFWLayerShellConfig c) { - if (layer_shell_config_for_next_window.output_name) free((void*)layer_shell_config_for_next_window.output_name); - layer_shell_config_for_next_window = c; - if (layer_shell_config_for_next_window.output_name && !layer_shell_config_for_next_window.output_name[0]) layer_shell_config_for_next_window.output_name = NULL; - if (layer_shell_config_for_next_window.output_name) layer_shell_config_for_next_window.output_name = strdup(layer_shell_config_for_next_window.output_name); +GLFWAPI void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig *c) { + layer_shell_config_for_next_window = *c; } void diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 3e9b34dff..35d6adba2 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1047,7 +1047,7 @@ typedef enum { GLFW_FOCUS_NOT_ALLOWED, GLFW_FOCUS_EXCLUSIVE, GLFW_FOCUS_ON_DEMAN typedef struct GLFWLayerShellConfig { GLFWLayerShellType type; GLFWEdge edge; - const char *output_name; + char output_name[64]; GLFWFocusPolicy focus_policy; unsigned size_in_cells; void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height); @@ -2320,7 +2320,7 @@ typedef void (*glfwWaylandRedrawCSDWindowTitle_func)(GLFWwindow*); GFW_EXTERN glfwWaylandRedrawCSDWindowTitle_func glfwWaylandRedrawCSDWindowTitle_impl; #define glfwWaylandRedrawCSDWindowTitle glfwWaylandRedrawCSDWindowTitle_impl -typedef void (*glfwWaylandSetupLayerShellForNextWindow_func)(GLFWLayerShellConfig); +typedef void (*glfwWaylandSetupLayerShellForNextWindow_func)(const GLFWLayerShellConfig*); GFW_EXTERN glfwWaylandSetupLayerShellForNextWindow_func glfwWaylandSetupLayerShellForNextWindow_impl; #define glfwWaylandSetupLayerShellForNextWindow glfwWaylandSetupLayerShellForNextWindow_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 6fd4f4b4f..23ed84da0 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1090,17 +1090,26 @@ calculate_layer_shell_window_size( } } -static GLFWLayerShellConfig -translate_layer_shell_config(PyObject *p) { - GLFWLayerShellConfig ans = {.size_callback=calculate_layer_shell_window_size}; -#define A(attr, type_check, convert) RAII_PyObject(attr, PyObject_GetAttrString(p, #attr)); if (attr == NULL) return ans; if (!type_check(attr)) { PyErr_SetString(PyExc_TypeError, #attr " not of the correct type"); return ans; }; ans.attr = convert(attr); - A(output_name, PyUnicode_Check, PyUnicode_AsUTF8); +static bool +translate_layer_shell_config(PyObject *p, GLFWLayerShellConfig *ans) { + memset(ans, 0, sizeof(GLFWLayerShellConfig)); + ans->size_callback = calculate_layer_shell_window_size; +#define A(attr, type_check, convert) RAII_PyObject(attr, PyObject_GetAttrString(p, #attr)); if (attr == NULL) return false; if (!type_check(attr)) { PyErr_SetString(PyExc_TypeError, #attr " not of the correct type"); return false; }; ans->attr = convert(attr); A(type, PyLong_Check, PyLong_AsLong); A(edge, PyLong_Check, PyLong_AsLong); A(focus_policy, PyLong_Check, PyLong_AsLong); A(size_in_cells, PyLong_Check, PyLong_AsLong); #undef A - return ans; +#define A(attr) { \ + RAII_PyObject(attr, PyObject_GetAttrString(p, #attr)); if (attr == NULL) return false; \ + if (!PyUnicode_Check(attr)) { PyErr_SetString(PyExc_TypeError, #attr " not a string"); return false; };\ + Py_ssize_t sz; const char *t = PyUnicode_AsUTF8AndSize(attr, &sz); \ + if (sz > (ssize_t)sizeof(ans->attr)-1) { PyErr_Format(PyExc_ValueError, "%s: %s is too long", #attr, t); return false; } \ + memcpy(ans->attr, t, sz); } + + A(output_name); + return true; +#undef A } static PyObject* @@ -1204,7 +1213,11 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { if (ret == NULL) return NULL; int width = PyLong_AsLong(PyTuple_GET_ITEM(ret, 0)), height = PyLong_AsLong(PyTuple_GET_ITEM(ret, 1)); Py_CLEAR(ret); - if (is_layer_shell) glfwWaylandSetupLayerShellForNextWindow(translate_layer_shell_config(layer_shell_config)); + if (is_layer_shell) { + GLFWLayerShellConfig lsc = {0}; + if (!translate_layer_shell_config(layer_shell_config, &lsc)) return NULL; + glfwWaylandSetupLayerShellForNextWindow(&lsc); + } GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, temp_window ? temp_window : common_context); if (temp_window) { glfwDestroyWindow(temp_window); temp_window = NULL; } if (glfw_window == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; }