aboutsummaryrefslogtreecommitdiffstats
path: root/src/pgtkterm.c
diff options
context:
space:
mode:
authorPo Lu2022-06-23 13:38:30 +0800
committerPo Lu2022-06-23 13:58:38 +0800
commit0b4db66a9deae682dc7d444f4ab8d0e49f15c3b9 (patch)
tree6f08101c3b9697085153e3babe29dc379d031b9c /src/pgtkterm.c
parent00034ad2e635adc93cd1d6dcb1b500c10d990c74 (diff)
downloademacs-0b4db66a9deae682dc7d444f4ab8d0e49f15c3b9.tar.gz
emacs-0b4db66a9deae682dc7d444f4ab8d0e49f15c3b9.zip
Allow dropping more data types on PGTK
* lisp/loadup.el (featurep): Load `pgtk-dnd'. * lisp/pgtk-dnd.el: New file. (pgtk-dnd-test-function, pgtk-dnd-types-alist) (pgtk-dnd-known-types, pgtk-dnd-use-offix-drop) (pgtk-dnd-current-state, pgtk-get-selection-internal) (pgtk-register-dnd-targets, pgtk-dnd-empty-state) (pgtk-dnd-init-frame, pgtk-dnd-get-state-cons-for-frame) (pgtk-dnd-get-state-for-frame, pgtk-dnd-default-test-function) (pgtk-dnd-current-type, pgtk-dnd-forget-drop) (pgtk-dnd-maybe-call-test-function, pgtk-dnd-save-state) (pgtk-dnd-handle-moz-url, pgtk-dnd-insert-utf8-text) (pgtk-dnd-insert-utf16-text, pgtk-dnd-insert-ctext) (pgtk-dnd-handle-uri-list, pgtk-dnd-handle-file-name) (pgtk-dnd-choose-type, pgtk-dnd-drop-data) (pgtk-dnd-handle-drag-n-drop-event, pgtk-update-drop-status) (pgtk-drop-finish, pgtk-dnd-handle-gdk, pgtk-dnd): New variables and functions and library. * lisp/term/pgtk-win.el (special-event-map): Load `drag-n-drop-event'. (after-make-frame-functions): Register DND after make frame functions. * src/emacs.c (main): Stop calling empty init_pgtkterm function. * src/pgtkselect.c (Fpgtk_register_dnd_targets, Fpgtk_drop_finish) (Fpgtk_update_drop_status): New functions. (syms_of_pgtkselect): Register new functions. * src/pgtkterm.c (struct event_queue_t): Fix coding style of definition. (symbol_to_drag_action, drag_action_to_symbol) (pgtk_update_drop_status, pgtk_finish_drop): New functions. (drag_data_received): Delete function. (pgtk_set_event_handler): Register for DND correctly. (syms_of_pgtkterm): New defsyms for DND types. (init_pgtkterm): Delete function. * src/pgtkterm.h: Update prototypes, fix prototype coding style.
Diffstat (limited to 'src/pgtkterm.c')
-rw-r--r--src/pgtkterm.c276
1 files changed, 234 insertions, 42 deletions
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 91874ff58a5..a123311366a 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -76,25 +76,36 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
76 76
77static bool any_help_event_p; 77static bool any_help_event_p;
78 78
79struct pgtk_display_info *x_display_list; /* Chain of existing displays */ 79/* Chain of existing displays */
80extern Lisp_Object tip_frame; 80struct pgtk_display_info *x_display_list;
81 81
82static struct event_queue_t 82struct event_queue_t
83{ 83{
84 union buffered_input_event *q; 84 union buffered_input_event *q;
85 int nr, cap; 85 int nr, cap;
86} event_q = {
87 NULL, 0, 0,
88}; 86};
89 87
88/* A queue of events that will be read by the read_socket_hook. */
89static struct event_queue_t event_q;
90
90/* Non-zero timeout value means ignore next mouse click if it arrives 91/* Non-zero timeout value means ignore next mouse click if it arrives
91 before that timeout elapses (i.e. as part of the same sequence of 92 before that timeout elapses (i.e. as part of the same sequence of
92 events resulting from clicking on a frame to select it). */ 93 events resulting from clicking on a frame to select it). */
93
94static Time ignore_next_mouse_click_timeout; 94static Time ignore_next_mouse_click_timeout;
95 95
96/* The default Emacs icon . */
96static Lisp_Object xg_default_icon_file; 97static Lisp_Object xg_default_icon_file;
97 98
99/* The current GdkDragContext of a drop. */
100static GdkDragContext *current_drop_context;
101
102/* Whether or not current_drop_context was set from a drop
103 handler. */
104static bool current_drop_context_drop;
105
106/* The time of the last drop. */
107static guint32 current_drop_time;
108
98static void pgtk_delete_display (struct pgtk_display_info *); 109static void pgtk_delete_display (struct pgtk_display_info *);
99static void pgtk_clear_frame_area (struct frame *, int, int, int, int); 110static void pgtk_clear_frame_area (struct frame *, int, int, int, int);
100static void pgtk_fill_rectangle (struct frame *, unsigned long, int, int, 111static void pgtk_fill_rectangle (struct frame *, unsigned long, int, int,
@@ -6146,40 +6157,217 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
6146 return TRUE; 6157 return TRUE;
6147} 6158}
6148 6159
6160
6161
6162/* C part of drop handling code.
6163 The Lisp part is in pgtk-dnd.el. */
6164
6165static GdkDragAction
6166symbol_to_drag_action (Lisp_Object act)
6167{
6168 if (EQ (act, Qcopy))
6169 return GDK_ACTION_COPY;
6170
6171 if (EQ (act, Qmove))
6172 return GDK_ACTION_MOVE;
6173
6174 if (EQ (act, Qlink))
6175 return GDK_ACTION_LINK;
6176
6177 if (EQ (act, Qprivate))
6178 return GDK_ACTION_PRIVATE;
6179
6180 if (NILP (act))
6181 return GDK_ACTION_DEFAULT;
6182
6183 signal_error ("Invalid drag acction", act);
6184}
6185
6186static Lisp_Object
6187drag_action_to_symbol (GdkDragAction action)
6188{
6189 switch (action)
6190 {
6191 case GDK_ACTION_COPY:
6192 return Qcopy;
6193
6194 case GDK_ACTION_MOVE:
6195 return Qmove;
6196
6197 case GDK_ACTION_LINK:
6198 return Qlink;
6199
6200 case GDK_ACTION_PRIVATE:
6201 return Qprivate;
6202
6203 case GDK_ACTION_DEFAULT:
6204 default:
6205 return Qnil;
6206 }
6207}
6208
6209void
6210pgtk_update_drop_status (Lisp_Object action, Lisp_Object event_time)
6211{
6212 guint32 time;
6213
6214 CONS_TO_INTEGER (event_time, guint32, time);
6215
6216 if (!current_drop_context || time < current_drop_time)
6217 return;
6218
6219 gdk_drag_status (current_drop_context,
6220 symbol_to_drag_action (action),
6221 time);
6222}
6223
6224void
6225pgtk_finish_drop (Lisp_Object success, Lisp_Object event_time,
6226 Lisp_Object del)
6227{
6228 guint32 time;
6229
6230 CONS_TO_INTEGER (event_time, guint32, time);
6231
6232 if (!current_drop_context || time < current_drop_time)
6233 return;
6234
6235 gtk_drag_finish (current_drop_context, !NILP (success),
6236 !NILP (del), time);
6237
6238 if (current_drop_context_drop)
6239 g_clear_pointer (&current_drop_context,
6240 g_object_unref);
6241}
6242
6149static void 6243static void
6150drag_data_received (GtkWidget *widget, GdkDragContext *context, 6244drag_leave (GtkWidget *widget, GdkDragContext *context,
6151 gint x, gint y, GtkSelectionData *data, 6245 guint time, gpointer user_data)
6152 guint info, guint time, gpointer user_data)
6153{ 6246{
6154 struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); 6247 struct frame *f;
6155 gchar **uris = gtk_selection_data_get_uris (data); 6248 union buffered_input_event inev;
6249
6250 f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
6156 6251
6157 if (uris != NULL) 6252 if (current_drop_context)
6158 { 6253 {
6159 for (int i = 0; uris[i] != NULL; i++) 6254 if (current_drop_context_drop)
6160 { 6255 gtk_drag_finish (current_drop_context,
6161 union buffered_input_event inev; 6256 FALSE, FALSE, current_drop_time);
6162 Lisp_Object arg = Qnil;
6163 6257
6164 EVENT_INIT (inev.ie); 6258 g_clear_pointer (&current_drop_context,
6165 inev.ie.kind = NO_EVENT; 6259 g_object_unref);
6166 inev.ie.arg = Qnil; 6260 }
6167 6261
6168 arg = list2 (Qurl, build_string (uris[i])); 6262 inev.ie.kind = DRAG_N_DROP_EVENT;
6263 inev.ie.modifiers = 0;
6264 inev.ie.arg = Qnil;
6265 inev.ie.timestamp = time;
6169 6266
6170 inev.ie.kind = DRAG_N_DROP_EVENT; 6267 XSETINT (inev.ie.x, 0);
6171 inev.ie.modifiers = 0; 6268 XSETINT (inev.ie.y, 0);
6172 XSETINT (inev.ie.x, x); 6269 XSETFRAME (inev.ie.frame_or_window, f);
6173 XSETINT (inev.ie.y, y);
6174 XSETFRAME (inev.ie.frame_or_window, f);
6175 inev.ie.arg = arg;
6176 inev.ie.timestamp = 0;
6177 6270
6178 evq_enqueue (&inev); 6271 evq_enqueue (&inev);
6179 } 6272}
6273
6274static gboolean
6275drag_motion (GtkWidget *widget, GdkDragContext *context,
6276 gint x, gint y, guint time)
6277
6278{
6279 struct frame *f;
6280 union buffered_input_event inev;
6281 GdkAtom name;
6282 GdkDragAction suggestion;
6283
6284 f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
6285
6286 if (!f)
6287 return FALSE;
6288
6289 if (current_drop_context)
6290 {
6291 if (current_drop_context_drop)
6292 gtk_drag_finish (current_drop_context,
6293 FALSE, FALSE, current_drop_time);
6294
6295 g_clear_pointer (&current_drop_context,
6296 g_object_unref);
6180 } 6297 }
6181 6298
6182 gtk_drag_finish (context, TRUE, FALSE, time); 6299 current_drop_context = g_object_ref (context);
6300 current_drop_time = time;
6301 current_drop_context_drop = false;
6302
6303 name = gdk_drag_get_selection (context);
6304 suggestion = gdk_drag_context_get_suggested_action (context);
6305
6306 EVENT_INIT (inev.ie);
6307
6308 inev.ie.kind = DRAG_N_DROP_EVENT;
6309 inev.ie.modifiers = 0;
6310 inev.ie.arg = list4 (Qlambda, intern (gdk_atom_name (name)),
6311 make_uint (time),
6312 drag_action_to_symbol (suggestion));
6313 inev.ie.timestamp = time;
6314
6315 XSETINT (inev.ie.x, x);
6316 XSETINT (inev.ie.y, y);
6317 XSETFRAME (inev.ie.frame_or_window, f);
6318
6319 evq_enqueue (&inev);
6320
6321 return TRUE;
6322}
6323
6324static gboolean
6325drag_drop (GtkWidget *widget, GdkDragContext *context,
6326 int x, int y, guint time, gpointer user_data)
6327{
6328 struct frame *f;
6329 union buffered_input_event inev;
6330 GdkAtom name;
6331 GdkDragAction selected_action;
6332
6333 f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
6334
6335 if (!f)
6336 return FALSE;
6337
6338 if (current_drop_context)
6339 {
6340 if (current_drop_context_drop)
6341 gtk_drag_finish (current_drop_context,
6342 FALSE, FALSE, current_drop_time);
6343
6344 g_clear_pointer (&current_drop_context,
6345 g_object_unref);
6346 }
6347
6348 current_drop_context = g_object_ref (context);
6349 current_drop_time = time;
6350 current_drop_context_drop = true;
6351
6352 name = gdk_drag_get_selection (context);
6353 selected_action = gdk_drag_context_get_selected_action (context);
6354
6355 EVENT_INIT (inev.ie);
6356
6357 inev.ie.kind = DRAG_N_DROP_EVENT;
6358 inev.ie.modifiers = 0;
6359 inev.ie.arg = list4 (Qquote, intern (gdk_atom_name (name)),
6360 make_uint (time),
6361 drag_action_to_symbol (selected_action));
6362 inev.ie.timestamp = time;
6363
6364 XSETINT (inev.ie.x, x);
6365 XSETINT (inev.ie.y, y);
6366 XSETFRAME (inev.ie.frame_or_window, f);
6367
6368 evq_enqueue (&inev);
6369
6370 return TRUE;
6183} 6371}
6184 6372
6185static void 6373static void
@@ -6208,9 +6396,9 @@ pgtk_set_event_handler (struct frame *f)
6208 return; 6396 return;
6209 } 6397 }
6210 6398
6211 gtk_drag_dest_set (FRAME_GTK_WIDGET (f), GTK_DEST_DEFAULT_ALL, NULL, 0, 6399 gtk_drag_dest_set (FRAME_GTK_WIDGET (f), 0, NULL, 0,
6212 GDK_ACTION_COPY); 6400 (GDK_ACTION_MOVE | GDK_ACTION_COPY
6213 gtk_drag_dest_add_uri_targets (FRAME_GTK_WIDGET (f)); 6401 | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
6214 6402
6215 if (FRAME_GTK_OUTER_WIDGET (f)) 6403 if (FRAME_GTK_OUTER_WIDGET (f))
6216 { 6404 {
@@ -6251,8 +6439,12 @@ pgtk_set_event_handler (struct frame *f)
6251 G_CALLBACK (scroll_event), NULL); 6439 G_CALLBACK (scroll_event), NULL);
6252 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event", 6440 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event",
6253 G_CALLBACK (configure_event), NULL); 6441 G_CALLBACK (configure_event), NULL);
6254 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received", 6442 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-leave",
6255 G_CALLBACK (drag_data_received), NULL); 6443 G_CALLBACK (drag_leave), NULL);
6444 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-motion",
6445 G_CALLBACK (drag_motion), NULL);
6446 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop",
6447 G_CALLBACK (drag_drop), NULL);
6256 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw", 6448 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
6257 G_CALLBACK (pgtk_handle_draw), NULL); 6449 G_CALLBACK (pgtk_handle_draw), NULL);
6258 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event", 6450 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event",
@@ -6803,12 +6995,17 @@ syms_of_pgtkterm (void)
6803 6995
6804 DEFSYM (Qlatin_1, "latin-1"); 6996 DEFSYM (Qlatin_1, "latin-1");
6805 6997
6806 xg_default_icon_file = 6998 xg_default_icon_file
6807 build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); 6999 = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
6808 staticpro (&xg_default_icon_file); 7000 staticpro (&xg_default_icon_file);
6809 7001
6810 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); 7002 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
6811 7003
7004 DEFSYM (Qcopy, "copy");
7005 DEFSYM (Qmove, "move");
7006 DEFSYM (Qlink, "link");
7007 DEFSYM (Qprivate, "private");
7008
6812 7009
6813 Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); 7010 Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
6814 Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); 7011 Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
@@ -7093,8 +7290,3 @@ pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
7093 7290
7094 return CALLN (Fapply, intern ("concat"), Fnreverse (acc)); 7291 return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
7095} 7292}
7096
7097void
7098init_pgtkterm (void)
7099{
7100}