1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
| | /* 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 <https://www.gnu.org/licenses/>. */
#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);
}
|