Nicer error message when running panel kitten on a compositor that does not support layer shell

This commit is contained in:
Kovid Goyal 2025-04-21 13:39:16 +05:30
parent 9329850184
commit a8693e45ef
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
7 changed files with 32 additions and 0 deletions

View file

@ -323,6 +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)
bool glfwWaylandIsLayerShellSupported(void)
bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle)
bool glfwWaylandBeep(GLFWwindow *handle)
GLFWLayerShellConfig* glfwWaylandLayerShellConfig(GLFWwindow *handle)

2
glfw/wl_window.c vendored
View file

@ -2834,6 +2834,8 @@ GLFWAPI GLFWLayerShellConfig* glfwWaylandLayerShellConfig(GLFWwindow *handle) {
return &((_GLFWwindow*)handle)->wl.layer_shell.config;
}
GLFWAPI bool glfwWaylandIsLayerShellSupported(void) { return _glfw.wl.zwlr_layer_shell_v1 != NULL; }
GLFWAPI bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle) { return handle != NULL && ((_GLFWwindow*)handle)->wl.window_fully_created; }
void

View file

@ -1715,6 +1715,7 @@ def base64_decode_into(src: Union[str, ReadableBuffer], output: WriteableBuffer)
def cocoa_recreate_global_menu() -> None: ...
def cocoa_clear_global_shortcuts() -> None: ...
def update_pointer_shape(os_window_id: int) -> None: ...
def is_layer_shell_supported() -> bool: ...
def os_window_focus_counters() -> Dict[int, int]: ...
def find_in_memoryview(buf: Union[bytes, memoryview, bytearray], chr: int) -> int: ...
@overload

3
kitty/glfw-wrapper.c generated
View file

@ -485,6 +485,9 @@ load_glfw(const char* path) {
*(void **) (&glfwWaylandRedrawCSDWindowTitle_impl) = dlsym(handle, "glfwWaylandRedrawCSDWindowTitle");
if (glfwWaylandRedrawCSDWindowTitle_impl == NULL) dlerror(); // clear error indicator
*(void **) (&glfwWaylandIsLayerShellSupported_impl) = dlsym(handle, "glfwWaylandIsLayerShellSupported");
if (glfwWaylandIsLayerShellSupported_impl == NULL) dlerror(); // clear error indicator
*(void **) (&glfwWaylandIsWindowFullyCreated_impl) = dlsym(handle, "glfwWaylandIsWindowFullyCreated");
if (glfwWaylandIsWindowFullyCreated_impl == NULL) dlerror(); // clear error indicator

4
kitty/glfw-wrapper.h generated
View file

@ -2340,6 +2340,10 @@ typedef void (*glfwWaylandRedrawCSDWindowTitle_func)(GLFWwindow*);
GFW_EXTERN glfwWaylandRedrawCSDWindowTitle_func glfwWaylandRedrawCSDWindowTitle_impl;
#define glfwWaylandRedrawCSDWindowTitle glfwWaylandRedrawCSDWindowTitle_impl
typedef bool (*glfwWaylandIsLayerShellSupported_func)(void);
GFW_EXTERN glfwWaylandIsLayerShellSupported_func glfwWaylandIsLayerShellSupported_impl;
#define glfwWaylandIsLayerShellSupported glfwWaylandIsLayerShellSupported_impl
typedef bool (*glfwWaylandIsWindowFullyCreated_func)(GLFWwindow*);
GFW_EXTERN glfwWaylandIsWindowFullyCreated_func glfwWaylandIsWindowFullyCreated_impl;
#define glfwWaylandIsWindowFullyCreated glfwWaylandIsWindowFullyCreated_impl

View file

@ -1211,6 +1211,10 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
&get_window_size, &pre_show_callback, &title, &wm_class_name, &wm_class_class, &optional_window_state, &load_programs, &optional_x, &optional_y, &disallow_override_title, &layer_shell_config)) return NULL;
bool is_layer_shell = false;
if (layer_shell_config && layer_shell_config != Py_None && global_state.is_wayland) {
if (!glfwWaylandIsLayerShellSupported()) {
PyErr_SetString(PyExc_RuntimeError, "The Wayland compositor does not support the layer shell protocol.");
return NULL;
}
is_layer_shell = true;
} else {
if (optional_window_state && optional_window_state != Py_None) { if (!PyLong_Check(optional_window_state)) { PyErr_SetString(PyExc_TypeError, "window_state must be an int"); return NULL; } window_state = (int) PyLong_AsLong(optional_window_state); }
@ -2407,6 +2411,17 @@ make_x11_window_a_dock_window(PyObject *self UNUSED, PyObject *args UNUSED) {
Py_RETURN_NONE;
}
static PyObject*
is_layer_shell_supported(PyObject *self UNUSED, PyObject *args UNUSED) {
#ifdef __APPLE__
Py_RETURN_FALSE;
#else
if (!global_state.is_wayland) Py_RETURN_FALSE;
return Py_NewRef(glfwWaylandIsLayerShellSupported() ? Py_True : Py_False);
#endif
}
// Boilerplate {{{
static PyMethodDef module_methods[] = {
@ -2428,6 +2443,7 @@ static PyMethodDef module_methods[] = {
METHODB(x11_display, METH_NOARGS),
METHODB(wayland_compositor_data, METH_NOARGS),
METHODB(get_click_interval, METH_NOARGS),
METHODB(is_layer_shell_supported, METH_NOARGS),
METHODB(x11_window_id, METH_O),
METHODB(make_x11_window_a_dock_window, METH_VARARGS),
METHODB(strip_csi, METH_O),

View file

@ -39,6 +39,7 @@
free_font_data,
glfw_init,
glfw_terminate,
is_layer_shell_supported,
load_png_data,
mask_kitty_signals_process_wide,
run_at_exit_cleanup_functions,
@ -229,6 +230,10 @@ def _run_app(opts: Options, args: CLIOptions, bad_lines: Sequence[BadLine] = (),
else:
global_shortcuts = {}
set_window_icon()
if _is_panel_kitten and is_wayland() and not is_layer_shell_supported():
from .debug_config import compositor_name
raise SystemExit(
f'Cannot create panels as the layer shell protocol is not supported by the compositor: {compositor_name()}')
with cached_values_for(run_app.cached_values_name) as cached_values:
startup_sessions = tuple(create_sessions(opts, args, default_session=opts.startup_session))