diff options
| author | Po Lu | 2022-06-21 22:03:42 +0800 |
|---|---|---|
| committer | Po Lu | 2022-06-21 22:05:21 +0800 |
| commit | be35c92c90d455739a6ff9d4beefa2b35d044852 (patch) | |
| tree | 19c5be6b9e09ccb45c58a5008f8f956f3ad92d57 /src/pgtkterm.c | |
| parent | b1af8c2c00aefe6aa554a468e65b6e07c9f14722 (diff) | |
| download | emacs-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.c | 129 |
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 | |||
| 290 | evq_enqueue (union buffered_input_event *ev) | 289 | evq_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 | ||
| 5870 | static gboolean | 5893 | static gboolean |
| 5871 | button_event (GtkWidget *widget, | 5894 | button_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 | ||
| 6199 | static gboolean pgtk_selection_event (GtkWidget *, GdkEvent *, gpointer); | ||
| 6200 | |||
| 6177 | void | 6201 | void |
| 6178 | pgtk_set_event_handler (struct frame *f) | 6202 | pgtk_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 | ||
| 6325 | static struct frame * | ||
| 6326 | pgtk_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 | |||
| 6343 | static gboolean | ||
| 6344 | pgtk_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", |