mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-06 09:15:57 +02:00
Implement Wayland xdg-toplevel-drag protocol for make_toplevel in _glfwPlatformChangeDragImage
Fixes #9544
This commit is contained in:
committed by
Kovid Goyal
parent
6d59469cf1
commit
accee908aa
@@ -88,6 +88,7 @@
|
||||
"staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml",
|
||||
"staging/xdg-system-bell/xdg-system-bell-v1.xml",
|
||||
"staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml",
|
||||
"staging/xdg-toplevel-drag/xdg-toplevel-drag-v1.xml",
|
||||
|
||||
"kwin-blur-v1.xml",
|
||||
"wlr-layer-shell-unstable-v1.xml",
|
||||
|
||||
4
glfw/wl_init.c
vendored
4
glfw/wl_init.c
vendored
@@ -675,6 +675,8 @@ static void registryHandleGlobal(void* data UNUSED,
|
||||
_glfw.wl.xdg_system_bell_v1 = wl_registry_bind(registry, name, &xdg_system_bell_v1_interface, 1);
|
||||
} else if (is(xdg_toplevel_tag_manager_v1)) {
|
||||
_glfw.wl.xdg_toplevel_tag_manager_v1 = wl_registry_bind(registry, name, &xdg_toplevel_tag_manager_v1_interface, 1);
|
||||
} else if (is(xdg_toplevel_drag_manager_v1)) {
|
||||
_glfw.wl.xdg_toplevel_drag_manager_v1 = wl_registry_bind(registry, name, &xdg_toplevel_drag_manager_v1_interface, 1);
|
||||
}
|
||||
#undef is
|
||||
}
|
||||
@@ -975,6 +977,8 @@ void _glfwPlatformTerminate(void)
|
||||
xdg_system_bell_v1_destroy(_glfw.wl.xdg_system_bell_v1);
|
||||
if (_glfw.wl.xdg_toplevel_tag_manager_v1)
|
||||
xdg_toplevel_tag_manager_v1_destroy(_glfw.wl.xdg_toplevel_tag_manager_v1);
|
||||
if (_glfw.wl.xdg_toplevel_drag_manager_v1)
|
||||
xdg_toplevel_drag_manager_v1_destroy(_glfw.wl.xdg_toplevel_drag_manager_v1);
|
||||
if (_glfw.wl.wp_single_pixel_buffer_manager_v1)
|
||||
wp_single_pixel_buffer_manager_v1_destroy(_glfw.wl.wp_single_pixel_buffer_manager_v1);
|
||||
if (_glfw.wl.wp_cursor_shape_manager_v1)
|
||||
|
||||
7
glfw/wl_platform.h
vendored
7
glfw/wl_platform.h
vendored
@@ -71,6 +71,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||
#include "wayland-xdg-toplevel-icon-v1-client-protocol.h"
|
||||
#include "wayland-xdg-system-bell-v1-client-protocol.h"
|
||||
#include "wayland-xdg-toplevel-tag-v1-client-protocol.h"
|
||||
#include "wayland-xdg-toplevel-drag-v1-client-protocol.h"
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
@@ -346,6 +347,7 @@ typedef struct _GLFWlibraryWayland
|
||||
struct xdg_toplevel_icon_manager_v1* xdg_toplevel_icon_manager_v1;
|
||||
struct xdg_system_bell_v1* xdg_system_bell_v1;
|
||||
struct xdg_toplevel_tag_manager_v1* xdg_toplevel_tag_manager_v1;
|
||||
struct xdg_toplevel_drag_manager_v1* xdg_toplevel_drag_manager_v1;
|
||||
struct wp_cursor_shape_manager_v1* wp_cursor_shape_manager_v1;
|
||||
struct wp_cursor_shape_device_v1* wp_cursor_shape_device_v1;
|
||||
struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1;
|
||||
@@ -415,6 +417,11 @@ typedef struct _GLFWlibraryWayland
|
||||
struct wl_data_source* source;
|
||||
struct wl_surface *drag_icon;
|
||||
struct wp_viewport *drag_viewport;
|
||||
struct xdg_toplevel_drag_v1 *toplevel_drag;
|
||||
struct wl_surface *toplevel_surface;
|
||||
struct xdg_surface *toplevel_xdg_surface;
|
||||
struct xdg_toplevel *toplevel_xdg_toplevel;
|
||||
struct wl_buffer *toplevel_buffer;
|
||||
struct {
|
||||
const char *mime_type;
|
||||
int fd;
|
||||
|
||||
69
glfw/wl_window.c
vendored
69
glfw/wl_window.c
vendored
@@ -3078,6 +3078,42 @@ GLFWAPI bool glfwWaylandBeep(GLFWwindow *handle) {
|
||||
}
|
||||
|
||||
// Drag source {{{
|
||||
|
||||
static void
|
||||
drag_toplevel_xdg_surface_configure(void *data UNUSED, struct xdg_surface *surface, uint32_t serial) {
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
if (_glfw.wl.drag.toplevel_buffer) {
|
||||
wl_surface_attach(_glfw.wl.drag.toplevel_surface, _glfw.wl.drag.toplevel_buffer, 0, 0);
|
||||
wl_surface_damage(_glfw.wl.drag.toplevel_surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_buffer_destroy(_glfw.wl.drag.toplevel_buffer);
|
||||
_glfw.wl.drag.toplevel_buffer = NULL;
|
||||
}
|
||||
if (_glfw.wl.drag.toplevel_surface) wl_surface_commit(_glfw.wl.drag.toplevel_surface);
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener drag_toplevel_xdg_surface_listener = {
|
||||
.configure = drag_toplevel_xdg_surface_configure,
|
||||
};
|
||||
|
||||
static void drag_toplevel_configure(void *data UNUSED, struct xdg_toplevel *toplevel UNUSED,
|
||||
int32_t width UNUSED, int32_t height UNUSED,
|
||||
struct wl_array *states UNUSED) {}
|
||||
static void drag_toplevel_close(void *data UNUSED, struct xdg_toplevel *toplevel UNUSED) {}
|
||||
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
|
||||
static void drag_toplevel_configure_bounds(void *data UNUSED, struct xdg_toplevel *toplevel UNUSED,
|
||||
int32_t width UNUSED, int32_t height UNUSED) {}
|
||||
static void drag_toplevel_wm_capabilities(void *data UNUSED, struct xdg_toplevel *toplevel UNUSED,
|
||||
struct wl_array *caps UNUSED) {}
|
||||
#endif
|
||||
static const struct xdg_toplevel_listener drag_toplevel_listener = {
|
||||
.configure = drag_toplevel_configure,
|
||||
.close = drag_toplevel_close,
|
||||
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
|
||||
.configure_bounds = drag_toplevel_configure_bounds,
|
||||
.wm_capabilities = drag_toplevel_wm_capabilities,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void
|
||||
cancel_drag(GLFWDragEventType type) {
|
||||
_GLFWwindow *window = _glfwWindowForId(_glfw.drag.window_id);
|
||||
@@ -3191,7 +3227,28 @@ add_drag_watch(int fd) {
|
||||
|
||||
int
|
||||
_glfwPlatformChangeDragImage(const GLFWimage *thumbnail, int make_toplevel) {
|
||||
(void)make_toplevel; // TODO: Implement me
|
||||
if (make_toplevel && _glfw.wl.drag.toplevel_drag && !_glfw.wl.drag.toplevel_surface
|
||||
&& _glfw.wl.wmBase && thumbnail && thumbnail->pixels) {
|
||||
_glfw.wl.drag.toplevel_surface = wl_compositor_create_surface(_glfw.wl.compositor);
|
||||
if (_glfw.wl.drag.toplevel_surface) {
|
||||
_glfw.wl.drag.toplevel_xdg_surface = xdg_wm_base_get_xdg_surface(
|
||||
_glfw.wl.wmBase, _glfw.wl.drag.toplevel_surface);
|
||||
if (_glfw.wl.drag.toplevel_xdg_surface) {
|
||||
xdg_surface_add_listener(_glfw.wl.drag.toplevel_xdg_surface,
|
||||
&drag_toplevel_xdg_surface_listener, NULL);
|
||||
_glfw.wl.drag.toplevel_xdg_toplevel = xdg_surface_get_toplevel(
|
||||
_glfw.wl.drag.toplevel_xdg_surface);
|
||||
if (_glfw.wl.drag.toplevel_xdg_toplevel) {
|
||||
xdg_toplevel_add_listener(_glfw.wl.drag.toplevel_xdg_toplevel,
|
||||
&drag_toplevel_listener, NULL);
|
||||
_glfw.wl.drag.toplevel_buffer = createShmBuffer(thumbnail, false, true);
|
||||
xdg_toplevel_drag_v1_attach(_glfw.wl.drag.toplevel_drag,
|
||||
_glfw.wl.drag.toplevel_xdg_toplevel, 0, 0);
|
||||
wl_surface_commit(_glfw.wl.drag.toplevel_surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_glfw.wl.drag.drag_icon || !thumbnail || !thumbnail->pixels) return 0;
|
||||
struct wl_buffer* icon_buffer = createShmBuffer(thumbnail, false, true);
|
||||
if (!icon_buffer) return ENOMEM;
|
||||
@@ -3308,6 +3365,11 @@ void
|
||||
_glfwPlatformFreeDragSourceData(void) {
|
||||
if (_glfw.wl.drag.drag_viewport) wp_viewport_destroy(_glfw.wl.drag.drag_viewport);
|
||||
if (_glfw.wl.drag.drag_icon) wl_surface_destroy(_glfw.wl.drag.drag_icon);
|
||||
if (_glfw.wl.drag.toplevel_drag) xdg_toplevel_drag_v1_destroy(_glfw.wl.drag.toplevel_drag);
|
||||
if (_glfw.wl.drag.toplevel_buffer) wl_buffer_destroy(_glfw.wl.drag.toplevel_buffer);
|
||||
if (_glfw.wl.drag.toplevel_xdg_toplevel) xdg_toplevel_destroy(_glfw.wl.drag.toplevel_xdg_toplevel);
|
||||
if (_glfw.wl.drag.toplevel_xdg_surface) xdg_surface_destroy(_glfw.wl.drag.toplevel_xdg_surface);
|
||||
if (_glfw.wl.drag.toplevel_surface) wl_surface_destroy(_glfw.wl.drag.toplevel_surface);
|
||||
if (_glfw.wl.drag.source) wl_data_source_destroy(_glfw.wl.drag.source);
|
||||
if (_glfw.wl.drag.data_requests) {
|
||||
for (size_t i = 0; i < _glfw.wl.drag.count; i++) {
|
||||
@@ -3377,6 +3439,11 @@ _glfwPlatformStartDrag(_GLFWwindow* window, const GLFWimage* thumbnail) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create xdg_toplevel_drag_v1 before starting the drag (must precede start_drag)
|
||||
if (_glfw.wl.xdg_toplevel_drag_manager_v1) {
|
||||
_glfw.wl.drag.toplevel_drag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(
|
||||
_glfw.wl.xdg_toplevel_drag_manager_v1, _glfw.wl.drag.source);
|
||||
}
|
||||
// Start the drag operation
|
||||
wl_data_device_start_drag(_glfw.wl.dataDevice, _glfw.wl.drag.source, window->wl.surface, _glfw.wl.drag.drag_icon,
|
||||
_glfw.wl.pointer_serial);
|
||||
|
||||
Reference in New Issue
Block a user