Yet another workaround for Wayland's awful design

This commit is contained in:
Kovid Goyal
2026-05-04 22:53:05 +05:30
parent 7222c5aa77
commit 021377c1b6
4 changed files with 20 additions and 6 deletions

1
glfw/glfw3.h vendored
View File

@@ -1840,6 +1840,7 @@ typedef struct GLFWDragEvent {
const char *data; size_t data_sz;
int err_num; // POSIX error code indicating failure fetching data
GLFWDragOperationType action; // can be 0 indicating no action
bool drop_maybe_a_cancel; // Happens on wayland compositors that dont implement top-level drag
} GLFWDragEvent;
typedef void (* GLFWdragsourcefun)(GLFWwindow* window, GLFWDragEvent *ev);

16
glfw/wl_window.c vendored
View File

@@ -3190,15 +3190,17 @@ static const struct xdg_toplevel_listener drag_toplevel_listener = {
};
static void
cancel_drag(GLFWDragEventType type) {
cancel_drag2(GLFWDragEventType type, bool maybe_a_cancel) {
_GLFWwindow *window = _glfwWindowForId(_glfw.drag.window_id);
if (window) {
GLFWDragEvent ev = {.type=type};
GLFWDragEvent ev = {.type=type, .drop_maybe_a_cancel=maybe_a_cancel};
_glfwInputDragSourceRequest(window, &ev);
}
_glfwFreeDragSourceData();
}
static void cancel_drag(GLFWDragEventType type) { cancel_drag2(type, false); }
#define dr _glfw.wl.drag.data_requests[i]
static void
@@ -3424,9 +3426,13 @@ drag_source_cancelled(void *data UNUSED, struct wl_data_source *source UNUSED) {
// impossible to distinguish between drag cancelled and dropped but not
// accepted. https://gitlab.freedesktop.org/wayland/wayland/-/issues/140
// so we assume this is a drop unless we are in top-level mode. Sigh.
const GLFWDragEventType t = _glfw.wl.drag.toplevel_xdg_toplevel ? GLFW_DRAG_CANCELLED : GLFW_DRAG_DROPPED;
debug_input("Drag source cancelled: is_drop: %d\n", t == GLFW_DRAG_DROPPED);
cancel_drag(t);
if (_glfw.wl.drag.toplevel_xdg_toplevel) {
debug_input("Drag source cancelled\n");
cancel_drag(GLFW_DRAG_CANCELLED);
} else {
debug_input("Drag source cancelled or dropped on something that doesnt accept it\n");
cancel_drag2(GLFW_DRAG_DROPPED, true);
}
}

1
kitty/glfw-wrapper.h generated
View File

@@ -1568,6 +1568,7 @@ typedef struct GLFWDragEvent {
const char *data; size_t data_sz;
int err_num; // POSIX error code indicating failure fetching data
GLFWDragOperationType action; // can be 0 indicating no action
bool drop_maybe_a_cancel; // Happens on wayland compositors that dont implement top-level drag
} GLFWDragEvent;
typedef void (* GLFWdragsourcefun)(GLFWwindow* window, GLFWDragEvent *ev);

View File

@@ -943,8 +943,14 @@ drag_source_callback(GLFWwindow *window UNUSED, GLFWDragEvent *ev) {
if (ds.from_window && (w = window_for_window_id(ds.from_window)) && w->drag_source.state) {
is_client_drag = true;
}
// On Wayland, wen compositor doesnt support top level drag protocol we get
// a drop event for what is either a cancel or a drop on something that
// does not accept the drop. In both of these cases we need to send the
// client a drop cancel.
GLFWDragEventType t = ev->type;
if (is_client_drag && ev->drop_maybe_a_cancel) t = GLFW_DRAG_CANCELLED;
switch (ev->type) {
switch (t) {
case GLFW_DRAG_DATA_REQUEST:
if (is_client_drag) {
ev->err_num = 0;