aboutsummaryrefslogtreecommitdiffstats
path: root/src/pgtkterm.c
diff options
context:
space:
mode:
authorPo Lu2022-06-21 22:03:42 +0800
committerPo Lu2022-06-21 22:05:21 +0800
commitbe35c92c90d455739a6ff9d4beefa2b35d044852 (patch)
tree19c5be6b9e09ccb45c58a5008f8f956f3ad92d57 /src/pgtkterm.c
parentb1af8c2c00aefe6aa554a468e65b6e07c9f14722 (diff)
downloademacs-be35c92c90d455739a6ff9d4beefa2b35d044852.tar.gz
emacs-be35c92c90d455739a6ff9d4beefa2b35d044852.zip
Rewrite PGTK selection code from scratch
* src/frame.c (delete_frame): Clear selections and swallow special events. * src/keyboard.c (kbd_buffer_get_event, process_special_events): Also handle selection events on PGTK. * src/keyboard.h (union buffered_input_event): Include selection events on PGTK. * src/pgtkselect.c (symbol_to_gtk_clipboard, LOCAL_SELECTION): New functions and macros. (selection_type_to_quarks, get_func, clear_func): Delete functions. (pgtk_selection_init, pgtk_selection_lost): (pgtk_selection_usable): New functions. (Fpgtk_own_selection_internal, Fpgtk_disown_selection_internal) (Fpgtk_selection_exists_p, Fpgtk_selection_owner_p) (Fpgtk_get_selection_internal): Complete rewrite. (syms_of_pgtkselect): Update defsyms and add more hooks. * src/pgtkselect.h: Delete file. * src/pgtkterm.c (evq_enqueue): Set last user time based on the event. (pgtk_any_window_to_frame, button_event): Fix coding style. (pgtk_set_event_handler): Add selection events. (pgtk_find_selection_owner, pgtk_selection_event): New functions. (pgtk_term_init): Remove call to `pgtk_selection_init'. * src/pgtkterm.h (struct pgtk_display_info): New field `display'. (enum selection_input_event): New struct. New macros for accessing its fields.
Diffstat (limited to 'src/pgtkterm.c')
-rw-r--r--src/pgtkterm.c129
1 files changed, 112 insertions, 17 deletions
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index da958a6664a..91874ff58a5 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -61,7 +61,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
61#include "buffer.h" 61#include "buffer.h"
62#include "font.h" 62#include "font.h"
63#include "xsettings.h" 63#include "xsettings.h"
64#include "pgtkselect.h"
65#include "emacsgtkfixed.h" 64#include "emacsgtkfixed.h"
66 65
67#ifdef GDK_WINDOWING_WAYLAND 66#ifdef GDK_WINDOWING_WAYLAND
@@ -290,6 +289,9 @@ static void
290evq_enqueue (union buffered_input_event *ev) 289evq_enqueue (union buffered_input_event *ev)
291{ 290{
292 struct event_queue_t *evq = &event_q; 291 struct event_queue_t *evq = &event_q;
292 struct frame *frame;
293 struct pgtk_display_info *dpyinfo;
294
293 if (evq->cap == 0) 295 if (evq->cap == 0)
294 { 296 {
295 evq->cap = 4; 297 evq->cap = 4;
@@ -303,6 +305,27 @@ evq_enqueue (union buffered_input_event *ev)
303 } 305 }
304 306
305 evq->q[evq->nr++] = *ev; 307 evq->q[evq->nr++] = *ev;
308
309 if (ev->ie.kind != SELECTION_REQUEST_EVENT
310 && ev->ie.kind != SELECTION_CLEAR_EVENT)
311 {
312 frame = NULL;
313
314 if (WINDOWP (ev->ie.frame_or_window))
315 frame = WINDOW_XFRAME (XWINDOW (ev->ie.frame_or_window));
316
317 if (FRAMEP (ev->ie.frame_or_window))
318 frame = XFRAME (ev->ie.frame_or_window);
319
320 if (frame)
321 {
322 dpyinfo = FRAME_DISPLAY_INFO (frame);
323
324 if (dpyinfo->last_user_time < ev->ie.timestamp)
325 dpyinfo->last_user_time = ev->ie.timestamp;
326 }
327 }
328
306 raise (SIGIO); 329 raise (SIGIO);
307} 330}
308 331
@@ -4809,16 +4832,16 @@ pgtk_any_window_to_frame (GdkWindow *window)
4809 return NULL; 4832 return NULL;
4810 4833
4811 FOR_EACH_FRAME (tail, frame) 4834 FOR_EACH_FRAME (tail, frame)
4812 { 4835 {
4813 if (found) 4836 if (found)
4814 break; 4837 break;
4815 f = XFRAME (frame); 4838 f = XFRAME (frame);
4816 if (FRAME_PGTK_P (f)) 4839 if (FRAME_PGTK_P (f))
4817 { 4840 {
4818 if (pgtk_window_is_of_frame (f, window)) 4841 if (pgtk_window_is_of_frame (f, window))
4819 found = f; 4842 found = f;
4820 } 4843 }
4821 } 4844 }
4822 4845
4823 return found; 4846 return found;
4824} 4847}
@@ -5868,8 +5891,7 @@ construct_mouse_click (struct input_event *result,
5868} 5891}
5869 5892
5870static gboolean 5893static gboolean
5871button_event (GtkWidget *widget, 5894button_event (GtkWidget *widget, GdkEvent *event,
5872 GdkEvent *event,
5873 gpointer *user_data) 5895 gpointer *user_data)
5874{ 5896{
5875 union buffered_input_event inev; 5897 union buffered_input_event inev;
@@ -6174,6 +6196,8 @@ pgtk_monitors_changed_cb (GdkScreen *screen, gpointer user_data)
6174 evq_enqueue (&inev); 6196 evq_enqueue (&inev);
6175} 6197}
6176 6198
6199static gboolean pgtk_selection_event (GtkWidget *, GdkEvent *, gpointer);
6200
6177void 6201void
6178pgtk_set_event_handler (struct frame *f) 6202pgtk_set_event_handler (struct frame *f)
6179{ 6203{
@@ -6225,14 +6249,20 @@ pgtk_set_event_handler (struct frame *f)
6225 G_CALLBACK (button_event), NULL); 6249 G_CALLBACK (button_event), NULL);
6226 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "scroll-event", 6250 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "scroll-event",
6227 G_CALLBACK (scroll_event), NULL); 6251 G_CALLBACK (scroll_event), NULL);
6228 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event",
6229 G_CALLBACK (pgtk_selection_lost), NULL);
6230 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event", 6252 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event",
6231 G_CALLBACK (configure_event), NULL); 6253 G_CALLBACK (configure_event), NULL);
6232 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received", 6254 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received",
6233 G_CALLBACK (drag_data_received), NULL); 6255 G_CALLBACK (drag_data_received), NULL);
6234 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw", 6256 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
6235 G_CALLBACK (pgtk_handle_draw), NULL); 6257 G_CALLBACK (pgtk_handle_draw), NULL);
6258 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event",
6259 G_CALLBACK (pgtk_selection_event), NULL);
6260 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event",
6261 G_CALLBACK (pgtk_selection_event), NULL);
6262 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-request-event",
6263 G_CALLBACK (pgtk_selection_event), NULL);
6264 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-notify-event",
6265 G_CALLBACK (pgtk_selection_event), NULL);
6236 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "event", 6266 g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "event",
6237 G_CALLBACK (pgtk_handle_event), NULL); 6267 G_CALLBACK (pgtk_handle_event), NULL);
6238} 6268}
@@ -6292,6 +6322,73 @@ same_x_server (const char *name1, const char *name2)
6292 && (*name2 == '.' || *name2 == '\0')); 6322 && (*name2 == '.' || *name2 == '\0'));
6293} 6323}
6294 6324
6325static struct frame *
6326pgtk_find_selection_owner (GdkWindow *window)
6327{
6328 Lisp_Object tail, tem;
6329 struct frame *f;
6330
6331 FOR_EACH_FRAME (tail, tem)
6332 {
6333 f = XFRAME (tem);
6334
6335 if (FRAME_PGTK_P (f)
6336 && (FRAME_GDK_WINDOW (f) == window))
6337 return f;
6338 }
6339
6340 return NULL;
6341}
6342
6343static gboolean
6344pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
6345 gpointer user_data)
6346{
6347 struct frame *f;
6348 union buffered_input_event inev;
6349
6350 if (event->type == GDK_PROPERTY_NOTIFY)
6351 pgtk_handle_property_notify (&event->property);
6352 else if (event->type == GDK_SELECTION_CLEAR
6353 || event->type == GDK_SELECTION_REQUEST)
6354 {
6355 f = pgtk_find_selection_owner (event->selection.window);
6356
6357 if (f)
6358 {
6359 EVENT_INIT (inev.ie);
6360
6361 inev.sie.kind = (event->type == GDK_SELECTION_CLEAR
6362 ? SELECTION_CLEAR_EVENT
6363 : SELECTION_REQUEST_EVENT);
6364
6365 SELECTION_EVENT_DPYINFO (&inev.sie) = FRAME_DISPLAY_INFO (f);
6366 SELECTION_EVENT_SELECTION (&inev.sie) = event->selection.selection;
6367 SELECTION_EVENT_TIME (&inev.sie) = event->selection.time;
6368
6369 if (event->type == GDK_SELECTION_REQUEST)
6370 {
6371 /* FIXME: when does GDK destroy the requestor GdkWindow
6372 object?
6373
6374 It would make sense to wait for the transfer to
6375 complete. But I don't know if GDK actually does
6376 that. */
6377 SELECTION_EVENT_REQUESTOR (&inev.sie) = event->selection.requestor;
6378 SELECTION_EVENT_TARGET (&inev.sie) = event->selection.target;
6379 SELECTION_EVENT_PROPERTY (&inev.sie) = event->selection.property;
6380 }
6381
6382 evq_enqueue (&inev);
6383 return TRUE;
6384 }
6385 }
6386 else if (event->type == GDK_SELECTION_NOTIFY)
6387 pgtk_handle_selection_notify (&event->selection);
6388
6389 return FALSE;
6390}
6391
6295/* Open a connection to X display DISPLAY_NAME, and return 6392/* Open a connection to X display DISPLAY_NAME, and return
6296 the structure that describes the open display. 6393 the structure that describes the open display.
6297 If we cannot contact the display, return null. */ 6394 If we cannot contact the display, return null. */
@@ -6525,8 +6622,6 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
6525 6622
6526 xsettings_initialize (dpyinfo); 6623 xsettings_initialize (dpyinfo);
6527 6624
6528 pgtk_selection_init ();
6529
6530 pgtk_im_init (dpyinfo); 6625 pgtk_im_init (dpyinfo);
6531 6626
6532 g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-added", 6627 g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-added",