summaryrefslogtreecommitdiff
path: root/src/pgtkterm.c
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-06-23 13:38:30 +0800
committerPo Lu <luangruo@yahoo.com>2022-06-23 13:58:38 +0800
commit0b4db66a9deae682dc7d444f4ab8d0e49f15c3b9 (patch)
tree6f08101c3b9697085153e3babe29dc379d031b9c /src/pgtkterm.c
parent00034ad2e635adc93cd1d6dcb1b500c10d990c74 (diff)
downloademacs-0b4db66a9deae682dc7d444f4ab8d0e49f15c3b9.tar.gz
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/>. */
static bool any_help_event_p;
-struct pgtk_display_info *x_display_list; /* Chain of existing displays */
-extern Lisp_Object tip_frame;
+/* Chain of existing displays */
+struct pgtk_display_info *x_display_list;
-static struct event_queue_t
+struct event_queue_t
{
union buffered_input_event *q;
int nr, cap;
-} event_q = {
- NULL, 0, 0,
};
+/* A queue of events that will be read by the read_socket_hook. */
+static struct event_queue_t event_q;
+
/* Non-zero timeout value means ignore next mouse click if it arrives
before that timeout elapses (i.e. as part of the same sequence of
events resulting from clicking on a frame to select it). */
-
static Time ignore_next_mouse_click_timeout;
+/* The default Emacs icon . */
static Lisp_Object xg_default_icon_file;
+/* The current GdkDragContext of a drop. */
+static GdkDragContext *current_drop_context;
+
+/* Whether or not current_drop_context was set from a drop
+ handler. */
+static bool current_drop_context_drop;
+
+/* The time of the last drop. */
+static guint32 current_drop_time;
+
static void pgtk_delete_display (struct pgtk_display_info *);
static void pgtk_clear_frame_area (struct frame *, int, int, int, int);
static void pgtk_fill_rectangle (struct frame *, unsigned long, int, int,
@@ -6146,40 +6157,217 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
return TRUE;
}
+
+
+/* C part of drop handling code.
+ The Lisp part is in pgtk-dnd.el. */
+
+static GdkDragAction
+symbol_to_drag_action (Lisp_Object act)
+{
+ if (EQ (act, Qcopy))
+ return GDK_ACTION_COPY;
+
+ if (EQ (act, Qmove))
+ return GDK_ACTION_MOVE;
+
+ if (EQ (act, Qlink))
+ return GDK_ACTION_LINK;
+
+ if (EQ (act, Qprivate))
+ return GDK_ACTION_PRIVATE;
+
+ if (NILP (act))
+ return GDK_ACTION_DEFAULT;
+
+ signal_error ("Invalid drag acction", act);
+}
+
+static Lisp_Object
+drag_action_to_symbol (GdkDragAction action)
+{
+ switch (action)
+ {
+ case GDK_ACTION_COPY:
+ return Qcopy;
+
+ case GDK_ACTION_MOVE:
+ return Qmove;
+
+ case GDK_ACTION_LINK:
+ return Qlink;
+
+ case GDK_ACTION_PRIVATE:
+ return Qprivate;
+
+ case GDK_ACTION_DEFAULT:
+ default:
+ return Qnil;
+ }
+}
+
+void
+pgtk_update_drop_status (Lisp_Object action, Lisp_Object event_time)
+{
+ guint32 time;
+
+ CONS_TO_INTEGER (event_time, guint32, time);
+
+ if (!current_drop_context || time < current_drop_time)
+ return;
+
+ gdk_drag_status (current_drop_context,
+ symbol_to_drag_action (action),
+ time);
+}
+
+void
+pgtk_finish_drop (Lisp_Object success, Lisp_Object event_time,
+ Lisp_Object del)
+{
+ guint32 time;
+
+ CONS_TO_INTEGER (event_time, guint32, time);
+
+ if (!current_drop_context || time < current_drop_time)
+ return;
+
+ gtk_drag_finish (current_drop_context, !NILP (success),
+ !NILP (del), time);
+
+ if (current_drop_context_drop)
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
+}
+
static void
-drag_data_received (GtkWidget *widget, GdkDragContext *context,
- gint x, gint y, GtkSelectionData *data,
- guint info, guint time, gpointer user_data)
+drag_leave (GtkWidget *widget, GdkDragContext *context,
+ guint time, gpointer user_data)
{
- struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
- gchar **uris = gtk_selection_data_get_uris (data);
+ struct frame *f;
+ union buffered_input_event inev;
+
+ f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
- if (uris != NULL)
+ if (current_drop_context)
{
- for (int i = 0; uris[i] != NULL; i++)
- {
- union buffered_input_event inev;
- Lisp_Object arg = Qnil;
+ if (current_drop_context_drop)
+ gtk_drag_finish (current_drop_context,
+ FALSE, FALSE, current_drop_time);
- EVENT_INIT (inev.ie);
- inev.ie.kind = NO_EVENT;
- inev.ie.arg = Qnil;
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
+ }
- arg = list2 (Qurl, build_string (uris[i]));
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ inev.ie.modifiers = 0;
+ inev.ie.arg = Qnil;
+ inev.ie.timestamp = time;
- inev.ie.kind = DRAG_N_DROP_EVENT;
- inev.ie.modifiers = 0;
- XSETINT (inev.ie.x, x);
- XSETINT (inev.ie.y, y);
- XSETFRAME (inev.ie.frame_or_window, f);
- inev.ie.arg = arg;
- inev.ie.timestamp = 0;
+ XSETINT (inev.ie.x, 0);
+ XSETINT (inev.ie.y, 0);
+ XSETFRAME (inev.ie.frame_or_window, f);
- evq_enqueue (&inev);
- }
+ evq_enqueue (&inev);
+}
+
+static gboolean
+drag_motion (GtkWidget *widget, GdkDragContext *context,
+ gint x, gint y, guint time)
+
+{
+ struct frame *f;
+ union buffered_input_event inev;
+ GdkAtom name;
+ GdkDragAction suggestion;
+
+ f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+
+ if (!f)
+ return FALSE;
+
+ if (current_drop_context)
+ {
+ if (current_drop_context_drop)
+ gtk_drag_finish (current_drop_context,
+ FALSE, FALSE, current_drop_time);
+
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
}
- gtk_drag_finish (context, TRUE, FALSE, time);
+ current_drop_context = g_object_ref (context);
+ current_drop_time = time;
+ current_drop_context_drop = false;
+
+ name = gdk_drag_get_selection (context);
+ suggestion = gdk_drag_context_get_suggested_action (context);
+
+ EVENT_INIT (inev.ie);
+
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ inev.ie.modifiers = 0;
+ inev.ie.arg = list4 (Qlambda, intern (gdk_atom_name (name)),
+ make_uint (time),
+ drag_action_to_symbol (suggestion));
+ inev.ie.timestamp = time;
+
+ XSETINT (inev.ie.x, x);
+ XSETINT (inev.ie.y, y);
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ evq_enqueue (&inev);
+
+ return TRUE;
+}
+
+static gboolean
+drag_drop (GtkWidget *widget, GdkDragContext *context,
+ int x, int y, guint time, gpointer user_data)
+{
+ struct frame *f;
+ union buffered_input_event inev;
+ GdkAtom name;
+ GdkDragAction selected_action;
+
+ f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+
+ if (!f)
+ return FALSE;
+
+ if (current_drop_context)
+ {
+ if (current_drop_context_drop)
+ gtk_drag_finish (current_drop_context,
+ FALSE, FALSE, current_drop_time);
+
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
+ }
+
+ current_drop_context = g_object_ref (context);
+ current_drop_time = time;
+ current_drop_context_drop = true;
+
+ name = gdk_drag_get_selection (context);
+ selected_action = gdk_drag_context_get_selected_action (context);
+
+ EVENT_INIT (inev.ie);
+
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ inev.ie.modifiers = 0;
+ inev.ie.arg = list4 (Qquote, intern (gdk_atom_name (name)),
+ make_uint (time),
+ drag_action_to_symbol (selected_action));
+ inev.ie.timestamp = time;
+
+ XSETINT (inev.ie.x, x);
+ XSETINT (inev.ie.y, y);
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ evq_enqueue (&inev);
+
+ return TRUE;
}
static void
@@ -6208,9 +6396,9 @@ pgtk_set_event_handler (struct frame *f)
return;
}
- gtk_drag_dest_set (FRAME_GTK_WIDGET (f), GTK_DEST_DEFAULT_ALL, NULL, 0,
- GDK_ACTION_COPY);
- gtk_drag_dest_add_uri_targets (FRAME_GTK_WIDGET (f));
+ gtk_drag_dest_set (FRAME_GTK_WIDGET (f), 0, NULL, 0,
+ (GDK_ACTION_MOVE | GDK_ACTION_COPY
+ | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
if (FRAME_GTK_OUTER_WIDGET (f))
{
@@ -6251,8 +6439,12 @@ pgtk_set_event_handler (struct frame *f)
G_CALLBACK (scroll_event), NULL);
g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event",
G_CALLBACK (configure_event), NULL);
- g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received",
- G_CALLBACK (drag_data_received), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-leave",
+ G_CALLBACK (drag_leave), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-motion",
+ G_CALLBACK (drag_motion), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop",
+ G_CALLBACK (drag_drop), NULL);
g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
G_CALLBACK (pgtk_handle_draw), NULL);
g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event",
@@ -6803,12 +6995,17 @@ syms_of_pgtkterm (void)
DEFSYM (Qlatin_1, "latin-1");
- xg_default_icon_file =
- build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
+ xg_default_icon_file
+ = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
staticpro (&xg_default_icon_file);
DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
+ DEFSYM (Qcopy, "copy");
+ DEFSYM (Qmove, "move");
+ DEFSYM (Qlink, "link");
+ DEFSYM (Qprivate, "private");
+
Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
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)
return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
}
-
-void
-init_pgtkterm (void)
-{
-}