diff options
| author | Po Lu | 2022-06-23 13:38:30 +0800 |
|---|---|---|
| committer | Po Lu | 2022-06-23 13:58:38 +0800 |
| commit | 0b4db66a9deae682dc7d444f4ab8d0e49f15c3b9 (patch) | |
| tree | 6f08101c3b9697085153e3babe29dc379d031b9c /src/pgtkterm.c | |
| parent | 00034ad2e635adc93cd1d6dcb1b500c10d990c74 (diff) | |
| download | emacs-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.c | 276 |
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 | ||
| 77 | static bool any_help_event_p; | 77 | static bool any_help_event_p; |
| 78 | 78 | ||
| 79 | struct pgtk_display_info *x_display_list; /* Chain of existing displays */ | 79 | /* Chain of existing displays */ |
| 80 | extern Lisp_Object tip_frame; | 80 | struct pgtk_display_info *x_display_list; |
| 81 | 81 | ||
| 82 | static struct event_queue_t | 82 | struct 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. */ | ||
| 89 | static 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 | |||
| 94 | static Time ignore_next_mouse_click_timeout; | 94 | static Time ignore_next_mouse_click_timeout; |
| 95 | 95 | ||
| 96 | /* The default Emacs icon . */ | ||
| 96 | static Lisp_Object xg_default_icon_file; | 97 | static Lisp_Object xg_default_icon_file; |
| 97 | 98 | ||
| 99 | /* The current GdkDragContext of a drop. */ | ||
| 100 | static GdkDragContext *current_drop_context; | ||
| 101 | |||
| 102 | /* Whether or not current_drop_context was set from a drop | ||
| 103 | handler. */ | ||
| 104 | static bool current_drop_context_drop; | ||
| 105 | |||
| 106 | /* The time of the last drop. */ | ||
| 107 | static guint32 current_drop_time; | ||
| 108 | |||
| 98 | static void pgtk_delete_display (struct pgtk_display_info *); | 109 | static void pgtk_delete_display (struct pgtk_display_info *); |
| 99 | static void pgtk_clear_frame_area (struct frame *, int, int, int, int); | 110 | static void pgtk_clear_frame_area (struct frame *, int, int, int, int); |
| 100 | static void pgtk_fill_rectangle (struct frame *, unsigned long, int, int, | 111 | static 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 | |||
| 6165 | static GdkDragAction | ||
| 6166 | symbol_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 | |||
| 6186 | static Lisp_Object | ||
| 6187 | drag_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 | |||
| 6209 | void | ||
| 6210 | pgtk_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 | |||
| 6224 | void | ||
| 6225 | pgtk_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 (¤t_drop_context, | ||
| 6240 | g_object_unref); | ||
| 6241 | } | ||
| 6242 | |||
| 6149 | static void | 6243 | static void |
| 6150 | drag_data_received (GtkWidget *widget, GdkDragContext *context, | 6244 | drag_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 (¤t_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 | |||
| 6274 | static gboolean | ||
| 6275 | drag_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 (¤t_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 | |||
| 6324 | static gboolean | ||
| 6325 | drag_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 (¤t_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 | ||
| 6185 | static void | 6373 | static 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 | |||
| 7097 | void | ||
| 7098 | init_pgtkterm (void) | ||
| 7099 | { | ||
| 7100 | } | ||