diff --git a/glfw/glfw.py b/glfw/glfw.py index 3cef8ede9..27453c8fd 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -252,6 +252,7 @@ def generate_wrappers(glfw_header: str) -> None: const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data) void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc) + void glfwSetX11WindowAsDock(int32_t x11_window_id) '''.splitlines(): if line: functions.append(Function(line.strip(), check_fail=False)) diff --git a/glfw/x11_init.c b/glfw/x11_init.c index fc81b042f..dde569f54 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -137,6 +137,8 @@ static void detectEWMH(void) getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE"); _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL = getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL"); + _glfw.x11.NET_WM_WINDOW_TYPE_DOCK = + getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_DOCK"); _glfw.x11.NET_WORKAREA = getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA"); _glfw.x11.NET_CURRENT_DESKTOP = diff --git a/glfw/x11_platform.h b/glfw/x11_platform.h index 2a2c87826..f2a4621ac 100644 --- a/glfw/x11_platform.h +++ b/glfw/x11_platform.h @@ -253,6 +253,7 @@ typedef struct _GLFWlibraryX11 Atom NET_WM_PING; Atom NET_WM_WINDOW_TYPE; Atom NET_WM_WINDOW_TYPE_NORMAL; + Atom NET_WM_WINDOW_TYPE_DOCK; Atom NET_WM_STATE; Atom NET_WM_STATE_ABOVE; Atom NET_WM_STATE_FULLSCREEN; diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 6ce1090e8..b979296fc 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -3197,3 +3197,11 @@ GLFWAPI int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc) _GLFWwindow* window = (_GLFWwindow*) handle; return XSetCommand(_glfw.x11.display, window->x11.handle, argv, argc); } + +GLFWAPI void glfwSetX11WindowAsDock(int32_t x11_window_id) { + _GLFW_REQUIRE_INIT(); + Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_DOCK; + XChangeProperty(_glfw.x11.display, x11_window_id, + _glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32, + PropModeReplace, (unsigned char*) &type, 1); +} diff --git a/kittens/panel/main.py b/kittens/panel/main.py index 5f7fa8cb5..5cf4a8b98 100644 --- a/kittens/panel/main.py +++ b/kittens/panel/main.py @@ -11,6 +11,7 @@ from kitty.cli import parse_args from kitty.cli_stub import PanelCLIOptions from kitty.constants import appname, is_macos from kitty.os_window_size import WindowSizeData +from kitty.fast_data_types import make_x11_window_a_dock_window OPTIONS = r''' --lines @@ -111,10 +112,7 @@ window_width = window_height = 0 def setup_x11_window(win_id: int) -> None: - call_xprop( - '-id', str(win_id), '-format', '_NET_WM_WINDOW_TYPE', '32a', - '-set', '_NET_WM_WINDOW_TYPE', '_NET_WM_WINDOW_TYPE_DOCK' - ) + make_x11_window_a_dock_window(win_id) func = globals()[f'create_{args.edge}_strut'] func(win_id, window_width, window_height) diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 9d433fa03..3a76946ac 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1475,3 +1475,4 @@ def clearenv() -> None: ... def set_clipboard_data_types(ct: int, mime_types: Tuple[str, ...]) -> None: ... def get_clipboard_mime(ct: int, mime: Optional[str], callback: Callable[[bytes], None]) -> None: ... def run_with_activation_token(func: Callable[[str], None]) -> None: ... +def make_x11_window_a_dock_window(x11_window_id: int) -> None: ... diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 8c5578b68..16ec6038e 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -467,6 +467,9 @@ load_glfw(const char* path) { *(void **) (&glfwSetX11LaunchCommand_impl) = dlsym(handle, "glfwSetX11LaunchCommand"); if (glfwSetX11LaunchCommand_impl == NULL) dlerror(); // clear error indicator + *(void **) (&glfwSetX11WindowAsDock_impl) = dlsym(handle, "glfwSetX11WindowAsDock"); + if (glfwSetX11WindowAsDock_impl == NULL) dlerror(); // clear error indicator + return NULL; } diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 0dcd5db13..c3dcb1637 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -2230,4 +2230,8 @@ typedef int (*glfwSetX11LaunchCommand_func)(GLFWwindow*, char**, int); GFW_EXTERN glfwSetX11LaunchCommand_func glfwSetX11LaunchCommand_impl; #define glfwSetX11LaunchCommand glfwSetX11LaunchCommand_impl +typedef void (*glfwSetX11WindowAsDock_func)(int32_t); +GFW_EXTERN glfwSetX11WindowAsDock_func glfwSetX11WindowAsDock_impl; +#define glfwSetX11WindowAsDock glfwSetX11WindowAsDock_impl + const char* load_glfw(const char* path); diff --git a/kitty/glfw.c b/kitty/glfw.c index be1739ccd..9cf2d5af0 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1686,6 +1686,16 @@ get_clipboard_mime(PyObject *self UNUSED, PyObject *args) { if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; } + +static PyObject* +make_x11_window_a_dock_window(PyObject *self UNUSED, PyObject *args UNUSED) { + int x11_window_id; + if (!PyArg_ParseTuple(args, "i", &x11_window_id)) return NULL; + if (!glfwSetX11WindowAsDock) { PyErr_SetString(PyExc_RuntimeError, "Failed to load glfwGetX11Window"); return NULL; } + glfwSetX11WindowAsDock(x11_window_id); + Py_RETURN_NONE; +} + // Boilerplate {{{ static PyMethodDef module_methods[] = { @@ -1704,6 +1714,7 @@ static PyMethodDef module_methods[] = { METHODB(x11_display, METH_NOARGS), METHODB(get_click_interval, METH_NOARGS), METHODB(x11_window_id, METH_O), + METHODB(make_x11_window_a_dock_window, METH_VARARGS), METHODB(strip_csi, METH_O), #ifndef __APPLE__ METHODB(dbus_send_notification, METH_VARARGS),