Handle XDND mouse rects synchronously
* src/xterm.c (x_dnd_send_position): Record event X and Y for consumption by the XdndStatus handler. Ignore mouse rects if waiting for status. (x_dnd_send_leave): Clear pending DND event. (handle_one_xevent): When handling XdndStatus, check if the pending event is contained in the new mouse rect.
This commit is contained in:
parent
97441f742e
commit
00501e82c7
1 changed files with 70 additions and 27 deletions
97
src/xterm.c
97
src/xterm.c
|
@ -1285,6 +1285,15 @@ static Window x_dnd_waiting_for_status_window;
|
|||
upon receiving an XdndStatus event from said window. */
|
||||
static XEvent x_dnd_pending_send_position;
|
||||
|
||||
/* Whether or not that event corresponds to a button press. */
|
||||
static bool x_dnd_pending_send_position_button;
|
||||
|
||||
/* The root-window position of that event. */
|
||||
static int x_dnd_pending_send_position_root_x;
|
||||
|
||||
/* Likewise. */
|
||||
static int x_dnd_pending_send_position_root_y;
|
||||
|
||||
/* If true, send a drop from `x_dnd_finish_frame' to the pending
|
||||
status window after receiving all pending XdndStatus events. */
|
||||
static bool x_dnd_need_send_drop;
|
||||
|
@ -4453,22 +4462,6 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
|
|||
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
|
||||
XEvent msg;
|
||||
|
||||
if (target == x_dnd_mouse_rect_target
|
||||
&& x_dnd_mouse_rect.width
|
||||
&& x_dnd_mouse_rect.height
|
||||
/* Ignore the mouse rectangle if we're supposed to be sending a
|
||||
button press instead. */
|
||||
&& (supported < 5 || !button))
|
||||
{
|
||||
if (root_x >= x_dnd_mouse_rect.x
|
||||
&& root_x < (x_dnd_mouse_rect.x
|
||||
+ x_dnd_mouse_rect.width)
|
||||
&& root_y >= x_dnd_mouse_rect.y
|
||||
&& root_y < (x_dnd_mouse_rect.y
|
||||
+ x_dnd_mouse_rect.height))
|
||||
return;
|
||||
}
|
||||
|
||||
msg.xclient.type = ClientMessage;
|
||||
msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
|
||||
msg.xclient.format = 32;
|
||||
|
@ -4502,9 +4495,30 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
|
|||
msg.xclient.data.l[4] = action;
|
||||
|
||||
if (x_dnd_waiting_for_status_window == target)
|
||||
x_dnd_pending_send_position = msg;
|
||||
{
|
||||
x_dnd_pending_send_position = msg;
|
||||
x_dnd_pending_send_position_button = button;
|
||||
x_dnd_pending_send_position_root_x = root_x;
|
||||
x_dnd_pending_send_position_root_y = root_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target == x_dnd_mouse_rect_target
|
||||
&& x_dnd_mouse_rect.width
|
||||
&& x_dnd_mouse_rect.height
|
||||
/* Ignore the mouse rectangle if we're supposed to be sending a
|
||||
button press instead. */
|
||||
&& (supported < 5 || !button))
|
||||
{
|
||||
if (root_x >= x_dnd_mouse_rect.x
|
||||
&& root_x < (x_dnd_mouse_rect.x
|
||||
+ x_dnd_mouse_rect.width)
|
||||
&& root_y >= x_dnd_mouse_rect.y
|
||||
&& root_y < (x_dnd_mouse_rect.y
|
||||
+ x_dnd_mouse_rect.height))
|
||||
return;
|
||||
}
|
||||
|
||||
x_ignore_errors_for_next_request (dpyinfo);
|
||||
XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
|
||||
x_stop_ignoring_errors (dpyinfo);
|
||||
|
@ -4530,6 +4544,7 @@ x_dnd_send_leave (struct frame *f, Window target)
|
|||
msg.xclient.data.l[4] = 0;
|
||||
|
||||
x_dnd_waiting_for_status_window = None;
|
||||
x_dnd_pending_send_position.type = 0;
|
||||
|
||||
x_ignore_errors_for_next_request (dpyinfo);
|
||||
XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
|
||||
|
@ -16372,6 +16387,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
{
|
||||
Window target;
|
||||
unsigned long r1, r2;
|
||||
int root_x, root_y;
|
||||
bool button;
|
||||
|
||||
target = event->xclient.data.l[0];
|
||||
|
||||
|
@ -16417,17 +16434,43 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
{
|
||||
if (x_dnd_pending_send_position.type != 0)
|
||||
{
|
||||
x_ignore_errors_for_next_request (dpyinfo);
|
||||
XSendEvent (dpyinfo->display, target,
|
||||
False, NoEventMask,
|
||||
&x_dnd_pending_send_position);
|
||||
x_stop_ignoring_errors (dpyinfo);
|
||||
x_dnd_pending_send_position.type = 0;
|
||||
/* If the last XdndStatus specified a mouse
|
||||
rectangle and this event falls inside, don't
|
||||
send the event, but clear
|
||||
x_dnd_waiting_for_status_window instead. */
|
||||
|
||||
/* Since we sent another XdndPosition message, we
|
||||
have to wait for another one in reply, so don't
|
||||
reset `x_dnd_waiting_for_status_window'
|
||||
here. */
|
||||
root_x = x_dnd_pending_send_position_root_x;
|
||||
root_y = x_dnd_pending_send_position_root_y;
|
||||
button = x_dnd_pending_send_position_button;
|
||||
|
||||
if (target == x_dnd_mouse_rect_target
|
||||
&& x_dnd_mouse_rect.width
|
||||
&& x_dnd_mouse_rect.height
|
||||
/* Ignore the mouse rectangle if we're
|
||||
supposed to be sending a button press
|
||||
instead. */
|
||||
&& (x_dnd_last_protocol_version < 5 || !button)
|
||||
&& (root_x >= x_dnd_mouse_rect.x
|
||||
&& root_x < (x_dnd_mouse_rect.x
|
||||
+ x_dnd_mouse_rect.width)
|
||||
&& root_y >= x_dnd_mouse_rect.y
|
||||
&& root_y < (x_dnd_mouse_rect.y
|
||||
+ x_dnd_mouse_rect.height)))
|
||||
x_dnd_waiting_for_status_window = None;
|
||||
else
|
||||
{
|
||||
x_ignore_errors_for_next_request (dpyinfo);
|
||||
XSendEvent (dpyinfo->display, target,
|
||||
False, NoEventMask,
|
||||
&x_dnd_pending_send_position);
|
||||
x_stop_ignoring_errors (dpyinfo);
|
||||
x_dnd_pending_send_position.type = 0;
|
||||
|
||||
/* Since we sent another XdndPosition message, we
|
||||
have to wait for another one in reply, so don't
|
||||
reset `x_dnd_waiting_for_status_window'
|
||||
here. */
|
||||
}
|
||||
}
|
||||
else
|
||||
x_dnd_waiting_for_status_window = None;
|
||||
|
|
Loading…
Add table
Reference in a new issue