/* GTK drag'n'drop support for Emacs Copyright (C) 2020 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see . */ #include "pgtkdnd.h" #include "config.h" #include "pgtkterm.h" #include "buffer.h" static GdkContentFormats *formats; void pgtk_dnd_global_init (void) { formats = gdk_content_formats_new ((const char *[]) {"text/plain", NULL}, 1); } static void drag_callback (GtkDropTarget *dest, GValue *drop, gdouble x, gdouble y, gpointer userptr) { struct frame *target_frame = userptr; gchar *c = g_strdup (g_value_get_string (drop)); size_t idx; size_t idz = 0; for (idx = 0; idz < strlen (c);) { if (c[idz] != '\xd') { c[idx] = c[idz]; ++idx; ++idz; } else { ++idz; } } c[idx] = 0; Lisp_Object str = build_string_from_utf8 (c); union buffered_input_event inev; EVENT_INIT (inev.ie); inev.ie.kind = DRAG_N_DROP_EVENT; inev.ie.arg = list2 (Qstring, str); inev.ie.modifiers = 0; XSETINT (inev.ie.x, (int) round (x)); XSETINT (inev.ie.y, (int) round (y)); XSETFRAME (inev.ie.frame_or_window, target_frame); inev.ie.timestamp = time (NULL); evq_enqueue (&inev); } static GdkDragAction drag_move_cb (GtkDropTarget *dest, gdouble x, gdouble y, gpointer userptr) { struct frame *f = userptr; enum window_part part; Lisp_Object window = window_from_coordinates (f, (int) x, (int) y, &part, 1, 1); if (part != ON_TEXT) return false; if (NILP (window)) return false; Fselect_window (window, Qnil); Lisp_Object frame; XSETFRAME (frame, f); Lisp_Object posn = Fposn_at_x_y (make_fixnum (x), make_fixnum (y), frame, Qnil); Lisp_Object posn_point = call1 (intern_c_string ("posn-point"), posn); Fset_window_point (window, posn_point); redisplay (); return GDK_ACTION_COPY; } void pgtk_dnd_init (struct frame *f) { FRAME_X_OUTPUT (f)->di.target = gtk_drop_target_new (G_TYPE_STRING, GDK_ACTION_COPY | GDK_ACTION_MOVE); gtk_widget_add_controller (FRAME_GTK_WIDGET (f), GTK_EVENT_CONTROLLER (FRAME_X_OUTPUT (f)->di.target)); g_signal_connect (G_OBJECT (FRAME_X_OUTPUT (f)->di.target), "drop", G_CALLBACK (drag_callback), f); g_signal_connect (G_OBJECT (FRAME_X_OUTPUT (f)->di.target), "motion", G_CALLBACK (drag_move_cb), f); }