/* Prevent redisplay. */
specbind (Qinhibit_redisplay, Qt);
+ /* Defer selection requests. */
+ DEFER_SELECTIONS;
+
block_input ();
/* Create the dialog with PROMPT as title, using DIR as initial
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)
{
}
#endif
+ DEFER_SELECTIONS;
+
/* Display the menu. */
gtk_widget_show_all (menu);
{
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);
if (menu)
{
specpdl_ref specpdl_count = SPECPDL_INDEX ();
+
+ DEFER_SELECTIONS;
record_unwind_protect_ptr (pop_down_menu, menu);
/* Display the menu. */
{
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);
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. */
/* 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);
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);
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");
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));
}
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
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. */
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. */
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);
#ifndef USE_GTK
FD_ZERO (&rfds);
- rc = 0;
+ rc = -1;
#endif
while (true)
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;
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,