mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-06-27 11:21:32 +00:00
parent
fa6c76d3e3
commit
6744183027
8 changed files with 118 additions and 36 deletions
|
|
@ -39,6 +39,10 @@
|
|||
|
||||
#define debug debug_rendering
|
||||
|
||||
// Macro and forward declaration needed before draggingEntered: (uti_to_mime is defined in Clipboard section)
|
||||
#define UTI_ROUNDTRIP_PREFIX @"uti-is-typical-apple-nih."
|
||||
static const char* uti_to_mime(NSString *uti);
|
||||
|
||||
static const char*
|
||||
polymorphic_string_as_utf8(id string) {
|
||||
if (string == nil) return "(nil)";
|
||||
|
|
@ -1346,8 +1350,58 @@ is_modifier_pressed(NSUInteger flags, NSUInteger target_mask, NSUInteger other_m
|
|||
double xpos = pos.x;
|
||||
double ypos = contentRect.size.height - pos.y;
|
||||
|
||||
// Call drag enter callback and check if accepted
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, xpos, ypos);
|
||||
// Get MIME types from the dragging pasteboard
|
||||
NSPasteboard* pasteboard = [sender draggingPasteboard];
|
||||
|
||||
// Count total types across all pasteboard items plus 2 for uri-list and text/plain
|
||||
size_t max_types = 2;
|
||||
for (NSPasteboardItem* item in pasteboard.pasteboardItems) {
|
||||
max_types += [item.types count];
|
||||
}
|
||||
|
||||
// Pre-allocate C array for MIME types
|
||||
const char** mime_array = (const char**)calloc(max_types, sizeof(const char*));
|
||||
if (!mime_array) {
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, xpos, ypos, NULL, 0);
|
||||
return accepted ? NSDragOperationGeneric : NSDragOperationNone;
|
||||
}
|
||||
|
||||
int mime_count = 0;
|
||||
|
||||
// Check for common types first
|
||||
NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES};
|
||||
if ([pasteboard canReadObjectForClasses:@[[NSURL class]] options:options]) {
|
||||
mime_array[mime_count++] = "text/uri-list";
|
||||
}
|
||||
if ([pasteboard canReadObjectForClasses:@[[NSString class]] options:nil]) {
|
||||
mime_array[mime_count++] = "text/plain";
|
||||
}
|
||||
|
||||
// Get additional types from pasteboard items
|
||||
for (NSPasteboardItem* item in pasteboard.pasteboardItems) {
|
||||
for (NSPasteboardType type in item.types) {
|
||||
const char* mime = uti_to_mime(type);
|
||||
if (mime && mime[0]) {
|
||||
// Check for duplicates
|
||||
bool duplicate = false;
|
||||
for (int i = 0; i < mime_count; i++) {
|
||||
if (strcmp(mime_array[i], mime) == 0) {
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!duplicate) {
|
||||
mime_array[mime_count++] = mime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call drag enter callback with MIME types
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, xpos, ypos, mime_array, mime_count);
|
||||
|
||||
free(mime_array);
|
||||
|
||||
if (accepted)
|
||||
return NSDragOperationGeneric;
|
||||
return NSDragOperationNone;
|
||||
|
|
@ -1361,7 +1415,7 @@ is_modifier_pressed(NSUInteger flags, NSUInteger target_mask, NSUInteger other_m
|
|||
double ypos = contentRect.size.height - pos.y;
|
||||
|
||||
// Call drag move callback
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_MOVE, xpos, ypos);
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_MOVE, xpos, ypos, NULL, 0);
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
|
|
@ -1369,7 +1423,7 @@ is_modifier_pressed(NSUInteger flags, NSUInteger target_mask, NSUInteger other_m
|
|||
{
|
||||
(void)sender;
|
||||
// Call drag leave callback
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_LEAVE, 0, 0);
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_LEAVE, 0, 0, NULL, 0);
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
|
|
@ -3025,8 +3079,6 @@ bool _glfwPlatformToggleFullscreen(_GLFWwindow* w, unsigned int flags) {
|
|||
|
||||
// Clipboard {{{
|
||||
|
||||
#define UTI_ROUNDTRIP_PREFIX @"uti-is-typical-apple-nih."
|
||||
|
||||
static NSString*
|
||||
mime_to_uti(const char *mime) {
|
||||
if (strcmp(mime, "text/plain") == 0) return NSPasteboardTypeString;
|
||||
|
|
|
|||
16
glfw/glfw3.h
vendored
16
glfw/glfw3.h
vendored
|
|
@ -1838,7 +1838,7 @@ typedef struct GLFWdragitem {
|
|||
* This is the function pointer type for drag event callbacks. A drag event
|
||||
* callback function has the following signature:
|
||||
* @code
|
||||
* int function_name(GLFWwindow* window, int event, double xpos, double ypos)
|
||||
* int function_name(GLFWwindow* window, int event, double xpos, double ypos, const char** mime_types, int mime_count)
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] window The window that received the drag event.
|
||||
|
|
@ -1846,6 +1846,12 @@ typedef struct GLFWdragitem {
|
|||
* or @ref GLFW_DRAG_LEAVE.
|
||||
* @param[in] xpos The x-coordinate of the drag position in window coordinates.
|
||||
* @param[in] ypos The y-coordinate of the drag position in window coordinates.
|
||||
* @param[in] mime_types Array of MIME type strings available from the drag source.
|
||||
* For @ref GLFW_DRAG_ENTER events this contains all available MIME types.
|
||||
* For other events this may be `NULL`. The strings are only valid for the
|
||||
* duration of the callback; if you need to store them, make copies.
|
||||
* @param[in] mime_count Number of MIME types in the array. Zero if no MIME types
|
||||
* are available or for non-enter events.
|
||||
* @return For @ref GLFW_DRAG_ENTER events, return non-zero to accept the drag
|
||||
* or zero to reject it. Return value is ignored for other event types.
|
||||
*
|
||||
|
|
@ -1856,7 +1862,7 @@ typedef struct GLFWdragitem {
|
|||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
typedef int (* GLFWdragfun)(GLFWwindow*, GLFWDragEventType event, double xpos, double ypos);
|
||||
typedef int (* GLFWdragfun)(GLFWwindow*, GLFWDragEventType event, double xpos, double ypos, const char** mime_types, int mime_count);
|
||||
|
||||
typedef void (* GLFWliveresizefun)(GLFWwindow*, bool);
|
||||
|
||||
|
|
@ -4995,6 +5001,10 @@ GLFWAPI GLFWliveresizefun glfwSetLiveResizeCallback(GLFWwindow* window, GLFWlive
|
|||
* callback to accept or reject incoming drag operations and track drag
|
||||
* position.
|
||||
*
|
||||
* For @ref GLFW_DRAG_ENTER events, the callback receives an array of MIME types
|
||||
* available from the drag source. The application can use this information to
|
||||
* decide whether to accept or reject the drag operation.
|
||||
*
|
||||
* @param[in] window The window whose callback to set.
|
||||
* @param[in] callback The new callback, or `NULL` to remove the currently set
|
||||
* callback.
|
||||
|
|
@ -5003,7 +5013,7 @@ GLFWAPI GLFWliveresizefun glfwSetLiveResizeCallback(GLFWwindow* window, GLFWlive
|
|||
*
|
||||
* @callback_signature
|
||||
* @code
|
||||
* int function_name(GLFWwindow* window, int event, double xpos, double ypos)
|
||||
* int function_name(GLFWwindow* window, int event, double xpos, double ypos, const char** mime_types, int mime_count)
|
||||
* @endcode
|
||||
* For more information about the callback parameters, see the
|
||||
* [function pointer type](@ref GLFWdragfun).
|
||||
|
|
|
|||
4
glfw/input.c
vendored
4
glfw/input.c
vendored
|
|
@ -412,10 +412,10 @@ int _glfwInputDrop(_GLFWwindow* window, const char *mime, const char *text, size
|
|||
|
||||
// Notifies shared code of a drag event
|
||||
//
|
||||
int _glfwInputDragEvent(_GLFWwindow* window, int event, double xpos, double ypos)
|
||||
int _glfwInputDragEvent(_GLFWwindow* window, int event, double xpos, double ypos, const char** mime_types, int mime_count)
|
||||
{
|
||||
if (window->callbacks.drag)
|
||||
return window->callbacks.drag((GLFWwindow*) window, event, xpos, ypos);
|
||||
return window->callbacks.drag((GLFWwindow*) window, event, xpos, ypos, mime_types, mime_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
2
glfw/internal.h
vendored
2
glfw/internal.h
vendored
|
|
@ -822,7 +822,7 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
|||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||
void _glfwInputCursorEnter(_GLFWwindow* window, bool entered);
|
||||
int _glfwInputDrop(_GLFWwindow* window, const char *mime, const char *text, size_t sz);
|
||||
int _glfwInputDragEvent(_GLFWwindow* window, int event, double xpos, double ypos);
|
||||
int _glfwInputDragEvent(_GLFWwindow* window, int event, double xpos, double ypos, const char** mime_types, int mime_count);
|
||||
void _glfwInputColorScheme(GLFWColorScheme, bool);
|
||||
void _glfwPlatformInputColorScheme(GLFWColorScheme);
|
||||
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
||||
|
|
|
|||
8
glfw/wl_window.c
vendored
8
glfw/wl_window.c
vendored
|
|
@ -2497,10 +2497,10 @@ static void drag_enter(void *data UNUSED, struct wl_data_device *wl_data_device
|
|||
while (window)
|
||||
{
|
||||
if (window->wl.surface == surface) {
|
||||
// Call drag enter callback
|
||||
// Call drag enter callback with MIME types
|
||||
double xpos = wl_fixed_to_double(x);
|
||||
double ypos = wl_fixed_to_double(y);
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, xpos, ypos);
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, xpos, ypos, d->mimes, (int)d->mimes_count);
|
||||
|
||||
// If accepted, check MIME type priorities
|
||||
if (accepted) {
|
||||
|
|
@ -2531,7 +2531,7 @@ static void drag_leave(void *data UNUSED, struct wl_data_device *wl_data_device
|
|||
_GLFWwindow* window = _glfw.windowListHead;
|
||||
while (window) {
|
||||
if (window->wl.surface == _glfw.wl.dataOffers[i].surface) {
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_LEAVE, 0, 0);
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_LEAVE, 0, 0, NULL, 0);
|
||||
break;
|
||||
}
|
||||
window = window->next;
|
||||
|
|
@ -2578,7 +2578,7 @@ static void motion(void *data UNUSED, struct wl_data_device *wl_data_device UNUS
|
|||
if (window->wl.surface == _glfw.wl.dataOffers[i].surface) {
|
||||
double xpos = wl_fixed_to_double(x);
|
||||
double ypos = wl_fixed_to_double(y);
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_MOVE, xpos, ypos);
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_MOVE, xpos, ypos, NULL, 0);
|
||||
break;
|
||||
}
|
||||
window = window->next;
|
||||
|
|
|
|||
27
glfw/x11_window.c
vendored
27
glfw/x11_window.c
vendored
|
|
@ -1840,10 +1840,7 @@ static void processEvent(XEvent *event)
|
|||
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||
return;
|
||||
|
||||
// Call the drag enter callback first
|
||||
// Position is not known yet at enter time, will be updated with XdndPosition
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, 0, 0);
|
||||
|
||||
// Get the MIME types before calling the callback
|
||||
if (list)
|
||||
{
|
||||
count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source,
|
||||
|
|
@ -1856,10 +1853,22 @@ static void processEvent(XEvent *event)
|
|||
count = 3;
|
||||
formats = (Atom*) event->xclient.data.l + 2;
|
||||
}
|
||||
char **atom_names = calloc(count, sizeof(char*));
|
||||
if (atom_names && accepted) {
|
||||
get_atom_names(formats, count, atom_names);
|
||||
|
||||
char **atom_names = calloc(count, sizeof(char*));
|
||||
int valid_mime_count = 0;
|
||||
if (atom_names) {
|
||||
get_atom_names(formats, count, atom_names);
|
||||
// Count valid MIME types
|
||||
for (i = 0; i < count; i++) {
|
||||
if (atom_names[i]) valid_mime_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Call the drag enter callback with the MIME types
|
||||
// Position is not known yet at enter time, will be updated with XdndPosition
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, 0, 0, (const char**)atom_names, valid_mime_count);
|
||||
|
||||
if (atom_names && accepted) {
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (atom_names[i]) {
|
||||
|
|
@ -1920,7 +1929,7 @@ static void processEvent(XEvent *event)
|
|||
else if (event->xclient.message_type == _glfw.x11.XdndLeave)
|
||||
{
|
||||
// The drag operation has left the window
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_LEAVE, 0, 0);
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_LEAVE, 0, 0, NULL, 0);
|
||||
_glfw.x11.xdnd.source = None;
|
||||
_glfw.x11.xdnd.target_window = None;
|
||||
}
|
||||
|
|
@ -1949,7 +1958,7 @@ static void processEvent(XEvent *event)
|
|||
_glfwInputCursorPos(window, xpos, ypos);
|
||||
|
||||
// Call the drag move callback
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_MOVE, xpos, ypos);
|
||||
_glfwInputDragEvent(window, GLFW_DRAG_MOVE, xpos, ypos, NULL, 0);
|
||||
|
||||
XEvent reply = { ClientMessage };
|
||||
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||
|
|
|
|||
10
kitty/glfw-wrapper.h
generated
10
kitty/glfw-wrapper.h
generated
|
|
@ -1576,7 +1576,7 @@ typedef struct GLFWdragitem {
|
|||
* This is the function pointer type for drag event callbacks. A drag event
|
||||
* callback function has the following signature:
|
||||
* @code
|
||||
* int function_name(GLFWwindow* window, int event, double xpos, double ypos)
|
||||
* int function_name(GLFWwindow* window, int event, double xpos, double ypos, const char** mime_types, int mime_count)
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] window The window that received the drag event.
|
||||
|
|
@ -1584,6 +1584,12 @@ typedef struct GLFWdragitem {
|
|||
* or @ref GLFW_DRAG_LEAVE.
|
||||
* @param[in] xpos The x-coordinate of the drag position in window coordinates.
|
||||
* @param[in] ypos The y-coordinate of the drag position in window coordinates.
|
||||
* @param[in] mime_types Array of MIME type strings available from the drag source.
|
||||
* For @ref GLFW_DRAG_ENTER events this contains all available MIME types.
|
||||
* For other events this may be `NULL`. The strings are only valid for the
|
||||
* duration of the callback; if you need to store them, make copies.
|
||||
* @param[in] mime_count Number of MIME types in the array. Zero if no MIME types
|
||||
* are available or for non-enter events.
|
||||
* @return For @ref GLFW_DRAG_ENTER events, return non-zero to accept the drag
|
||||
* or zero to reject it. Return value is ignored for other event types.
|
||||
*
|
||||
|
|
@ -1594,7 +1600,7 @@ typedef struct GLFWdragitem {
|
|||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
typedef int (* GLFWdragfun)(GLFWwindow*, GLFWDragEventType event, double xpos, double ypos);
|
||||
typedef int (* GLFWdragfun)(GLFWwindow*, GLFWDragEventType event, double xpos, double ypos, const char** mime_types, int mime_count);
|
||||
|
||||
typedef void (* GLFWliveresizefun)(GLFWwindow*, bool);
|
||||
|
||||
|
|
|
|||
23
kitty/glfw.c
23
kitty/glfw.c
|
|
@ -642,11 +642,21 @@ window_focus_callback(GLFWwindow *w, int focused) {
|
|||
}
|
||||
|
||||
static int
|
||||
drag_callback(GLFWwindow *w, GLFWDragEventType event, double xpos, double ypos) {
|
||||
(void)event; (void)xpos; (void)ypos;
|
||||
is_droppable_mime(const char *mime) {
|
||||
if (strcmp(mime, "text/uri-list") == 0) return 3;
|
||||
if (strcmp(mime, "text/plain;charset=utf-8") == 0) return 2;
|
||||
if (strcmp(mime, "text/plain") == 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
drag_callback(GLFWwindow *w, GLFWDragEventType event, double xpos, double ypos, const char** mime_types, int mime_count) {
|
||||
(void)xpos; (void)ypos;
|
||||
if (!set_callback_window(w)) return 0;
|
||||
if (event == GLFW_DRAG_ENTER) {
|
||||
return 1;
|
||||
for (int i = 0; i < mime_count; i++) {
|
||||
if (is_droppable_mime(mime_types[i])) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -655,12 +665,7 @@ static int
|
|||
drop_callback(GLFWwindow *w, const char *mime, const char *data, size_t sz) {
|
||||
if (!set_callback_window(w)) return 0;
|
||||
#define RETURN(x) { global_state.callback_os_window = NULL; return x; }
|
||||
if (!data) {
|
||||
if (strcmp(mime, "text/uri-list") == 0) RETURN(3);
|
||||
if (strcmp(mime, "text/plain;charset=utf-8") == 0) RETURN(2);
|
||||
if (strcmp(mime, "text/plain") == 0) RETURN(1);
|
||||
RETURN(0);
|
||||
}
|
||||
if (!data) return is_droppable_mime(mime);
|
||||
WINDOW_CALLBACK(on_drop, "sy#", mime, data, (Py_ssize_t)sz);
|
||||
request_tick_callback();
|
||||
RETURN(0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue