emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 22d3f0e95a: Make responding to selection requests work inside pop


From: Po Lu
Subject: master 22d3f0e95a: Make responding to selection requests work inside popups
Date: Wed, 8 Jun 2022 03:10:04 -0400 (EDT)

branch: master
commit 22d3f0e95a5602b2bde763cff185f5b4fed6e53e
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Make responding to selection requests work inside popups
    
    * src/xfns.c (Fx_file_dialog):
    * src/xmenu.c (x_menu_wait_for_event, create_and_show_popup_menu)
    (create_and_show_dialog, x_menu_show): Defer selection requests.
    * src/xselect.c (x_get_foreign_selection)
    (x_handle_selection_notify): Add some more info to selection
    trace.
    
    * src/xterm.c (x_defer_selection_requests): Make non-static.
    (x_release_selection_requests_and_flush): New function.
    (x_dnd_begin_drag_and_drop): Use DEFER_SELECTIONS instead.
    (x_wait_for_cell_change): Fix initial value of rc for pushed
    back events.
    (handle_one_xevent): Allow GTK to respond to selections in its
    windows too.
    
    * src/xterm.h (DEFER_SELECTIONS): New slug of code.
---
 src/xfns.c    |  3 +++
 src/xmenu.c   | 24 ++++++++++++++++++-----
 src/xselect.c |  8 ++++++--
 src/xterm.c   | 63 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
 src/xterm.h   |  6 ++++++
 5 files changed, 86 insertions(+), 18 deletions(-)

diff --git a/src/xfns.c b/src/xfns.c
index cffb4a5d96..f0a2ec666c 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -8885,6 +8885,9 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 
2, 5, 0,
   /* Prevent redisplay.  */
   specbind (Qinhibit_redisplay, Qt);
 
+  /* Defer selection requests.  */
+  DEFER_SELECTIONS;
+
   block_input ();
 
   /* Create the dialog with PROMPT as title, using DIR as initial
diff --git a/src/xmenu.c b/src/xmenu.c
index e9601981ed..7134bf22c8 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -198,6 +198,10 @@ x_menu_wait_for_event (void *data)
       struct x_display_info *dpyinfo;
       int n = 0;
 
+      /* ISTM that if timer_check is okay, this should be too, since
+        both can run random Lisp.  */
+      x_handle_pending_selection_requests ();
+
       FD_ZERO (&read_fds);
       for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
         {
@@ -1579,6 +1583,8 @@ create_and_show_popup_menu (struct frame *f, widget_value 
*first_wv,
     }
 #endif
 
+  DEFER_SELECTIONS;
+
   /* Display the menu.  */
   gtk_widget_show_all (menu);
 
@@ -1868,6 +1874,8 @@ create_and_show_popup_menu (struct frame *f, widget_value 
*first_wv,
   {
     specpdl_ref specpdl_count = SPECPDL_INDEX ();
 
+    DEFER_SELECTIONS;
+
     record_unwind_protect_int (pop_down_menu, (int) menu_id);
 #ifdef HAVE_XINPUT2
     record_unwind_protect_ptr (leave_toolkit_menu, f);
@@ -2199,6 +2207,8 @@ create_and_show_dialog (struct frame *f, widget_value 
*first_wv)
   if (menu)
     {
       specpdl_ref specpdl_count = SPECPDL_INDEX ();
+
+      DEFER_SELECTIONS;
       record_unwind_protect_ptr (pop_down_menu, menu);
 
       /* Display the menu.  */
@@ -2255,6 +2265,8 @@ create_and_show_dialog (struct frame *f, widget_value 
*first_wv)
   {
     specpdl_ref count = SPECPDL_INDEX ();
 
+    DEFER_SELECTIONS;
+
     /* xdialog_show_unwind is responsible for popping the dialog box down.  */
 
     record_unwind_protect_int (pop_down_menu, (int) dialog_id);
@@ -2715,18 +2727,18 @@ x_menu_show (struct frame *f, int x, int y, int 
menuflags,
   y = max (y, 1);
   XMenuLocate (FRAME_X_DISPLAY (f), menu, 0, 0, x, y,
               &ulx, &uly, &width, &height);
-  if (ulx+width > dispwidth)
+  if (ulx + width > dispwidth)
     {
       x -= (ulx + width) - dispwidth;
       ulx = dispwidth - width;
     }
-  if (uly+height > dispheight)
+  if (uly + height > dispheight)
     {
       y -= (uly + height) - dispheight;
       uly = dispheight - height;
     }
 #ifndef HAVE_X_WINDOWS
-  if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1)
+  if (FRAME_HAS_MINIBUF_P (f) && uly + height > dispheight - 1)
     {
       /* Move the menu away of the echo area, to avoid overwriting the
         menu with help echo messages or vice versa.  */
@@ -2750,8 +2762,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
       /* If position was not given by a mouse click, adjust so upper left
          corner of the menu as a whole ends up at given coordinates.  This
          is what x-popup-menu says in its documentation.  */
-      x += width/2;
-      y += 1.5*height/(maxlines+2);
+      x += width / 2;
+      y += 1.5 * height/ (maxlines + 2);
     }
 
   XMenuSetAEQ (menu, true);
@@ -2759,6 +2771,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
   pane = selidx = 0;
 
 #ifndef MSDOS
+  DEFER_SELECTIONS;
+
   XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
 #ifdef HAVE_XINPUT2
   XMenuActivateSetTranslateFunction (x_menu_translate_generic_event);
diff --git a/src/xselect.c b/src/xselect.c
index d184489cbd..40b6571e0a 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1252,7 +1252,11 @@ x_get_foreign_selection (Lisp_Object selection_symbol, 
Lisp_Object target_type,
   else
     x_wait_for_cell_change (reading_selection_reply,
                            make_timespec (secs, nsecs));
-  TRACE1 ("  Got event = %d", !NILP (XCAR (reading_selection_reply)));
+  TRACE1 ("  Got event = %s", (!NILP (XCAR (reading_selection_reply))
+                              ? (SYMBOLP (XCAR (reading_selection_reply))
+                                 ? SSDATA (SYMBOL_NAME (XCAR 
(reading_selection_reply)))
+                                 : "YES")
+                              : "NO"));
 
   if (NILP (XCAR (reading_selection_reply)))
     error ("Timed out waiting for reply from selection owner");
@@ -1947,7 +1951,7 @@ x_handle_selection_notify (const XSelectionEvent *event)
   if (event->selection != reading_which_selection)
     return;
 
-  TRACE0 ("Received SelectionNotify");
+  TRACE1 ("Received SelectionNotify: %d", (int) event->property);
   XSETCAR (reading_selection_reply,
           (event->property != 0 ? Qt : Qlambda));
 }
diff --git a/src/xterm.c b/src/xterm.c
index 444adcf94f..1f4d301e6a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -793,10 +793,43 @@ static struct input_event *current_hold_quit;
    than 0.  */
 static int x_use_pending_selection_requests;
 
-static void
+static void x_push_selection_request (struct selection_input_event *);
+
+/* Defer selection requests.  Any selection requests generated after
+   this can then be processed by calling
+   `x_handle_pending_selection_requests'.
+
+   Also run through and queue all the selection events already in the
+   keyboard buffer.  */
+void
 x_defer_selection_requests (void)
 {
+  union buffered_input_event *event;
+
+  block_input ();
   x_use_pending_selection_requests++;
+
+  if (!x_use_pending_selection_requests)
+    {
+      event = kbd_fetch_ptr;
+
+      while (event != kbd_store_ptr)
+       {
+         if (event->ie.kind == SELECTION_REQUEST_EVENT
+             || event->ie.kind == SELECTION_CLEAR_EVENT)
+           {
+             x_push_selection_request (&event->sie);
+
+             /* Mark this selection event as invalid.   */
+             SELECTION_EVENT_DPYINFO (&event->sie) = NULL;
+           }
+
+         event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1
+                  ? kbd_buffer : event + 1);
+       }
+    }
+
+  unblock_input ();
 }
 
 static void
@@ -805,6 +838,15 @@ x_release_selection_requests (void)
   x_use_pending_selection_requests--;
 }
 
+void
+x_release_selection_requests_and_flush (void)
+{
+  x_release_selection_requests ();
+
+  if (!x_use_pending_selection_requests)
+    x_handle_pending_selection_requests ();
+}
+
 struct x_selection_request_event
 {
   /* The selection request event.  */
@@ -10764,8 +10806,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, 
Atom xaction,
   if (x_dnd_in_progress || x_dnd_waiting_for_finish)
     error ("A drag-and-drop session is already in progress");
 
-  x_defer_selection_requests ();
-  record_unwind_protect_void (x_release_selection_requests);
+  DEFER_SELECTIONS;
 
   /* If local_value is nil, then we lost ownership of XdndSelection.
      Signal a more informative error than args-out-of-range.  */
@@ -10781,8 +10822,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, 
Atom xaction,
   if (popup_activated ())
     error ("Trying to drag-and-drop from within a menu-entry");
 
-  record_unwind_protect_void (x_free_dnd_targets);
   x_set_dnd_targets (target_atoms, ntargets);
+  record_unwind_protect_void (x_free_dnd_targets);
 
   ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f),
                                          QXdndSelection);
@@ -15306,7 +15347,7 @@ x_wait_for_cell_change (Lisp_Object cell, struct 
timespec timeout)
 
 #ifndef USE_GTK
   FD_ZERO (&rfds);
-  rc = 0;
+  rc = -1;
 #endif
 
   while (true)
@@ -15892,18 +15933,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       break;
 
     case SelectionNotify:
-#ifdef USE_X_TOOLKIT
-      if (! x_window_to_frame (dpyinfo, event->xselection.requestor))
+#if defined USE_X_TOOLKIT || defined USE_GTK
+      if (!x_window_to_frame (dpyinfo, event->xselection.requestor))
         goto OTHER;
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT and not USE_GTK */
       x_handle_selection_notify (&event->xselection);
       break;
 
     case SelectionClear:       /* Someone has grabbed ownership.  */
-#ifdef USE_X_TOOLKIT
-      if (! x_window_to_frame (dpyinfo, event->xselectionclear.window))
+#if defined USE_X_TOOLKIT || defined USE_GTK
+      if (!x_window_to_frame (dpyinfo, event->xselectionclear.window))
         goto OTHER;
-#endif /* USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT and not USE_GTK */
       {
         const XSelectionClearEvent *eventp = &event->xselectionclear;
 
diff --git a/src/xterm.h b/src/xterm.h
index 1ab65f15d1..7e91e28ed1 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1456,6 +1456,12 @@ extern void x_xr_reset_ext_clip (struct frame *f);
 extern void x_scroll_bar_configure (GdkEvent *);
 #endif
 
+#define DEFER_SELECTIONS                                               \
+  x_defer_selection_requests ();                                       \
+  record_unwind_protect_void (x_release_selection_requests_and_flush)
+
+extern void x_defer_selection_requests (void);
+extern void x_release_selection_requests_and_flush (void);
 extern void x_handle_pending_selection_requests (void);
 extern bool x_detect_pending_selection_requests (void);
 extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,



reply via email to

[Prev in Thread] Current Thread [Next in Thread]