forked from 12to11/12to11
Fix selection timestamp handling problems
* data_device.c (XLClearForeignSelection): * primary_selection.c (XLClearForeignPrimary): Clear the local selection as well upon losing selection ownership. * xdata.c (NoticeClipboardCleared, NoticePrimaryCleared): If a local selection is in use, don't clear it upon selection clear events with a timestamp identical to the time at which their ownership was acquired. Explain why in a comment. (HandleSelectionNotify): Always use the client time.
This commit is contained in:
parent
3fe08b5c7c
commit
6e062e2e2f
3 changed files with 59 additions and 9 deletions
|
@ -1210,7 +1210,15 @@ XLClearForeignSelection (Timestamp time)
|
||||||
if (current_selection_data == &foreign_selection_key)
|
if (current_selection_data == &foreign_selection_key)
|
||||||
{
|
{
|
||||||
current_selection_data = NULL;
|
current_selection_data = NULL;
|
||||||
|
SendDataOffers ();
|
||||||
|
}
|
||||||
|
else if (current_selection_data)
|
||||||
|
{
|
||||||
|
/* The foreign selection was cleared, meaning CLIPBOARD has been
|
||||||
|
disowned after the last foreign or local selection was set,
|
||||||
|
and thus the local selection must be cleared as well. */
|
||||||
|
wl_data_source_send_cancelled (current_selection_data->resource);
|
||||||
|
current_selection_data = NULL;
|
||||||
SendDataOffers ();
|
SendDataOffers ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -756,6 +756,8 @@ XLSetForeignPrimary (Timestamp time, CreateOfferFuncs functions)
|
||||||
void
|
void
|
||||||
XLClearForeignPrimary (Timestamp time)
|
XLClearForeignPrimary (Timestamp time)
|
||||||
{
|
{
|
||||||
|
struct wl_resource *scratch;
|
||||||
|
|
||||||
if (TimestampIs (time, Earlier, foreign_selection_time))
|
if (TimestampIs (time, Earlier, foreign_selection_time))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -764,6 +766,19 @@ XLClearForeignPrimary (Timestamp time)
|
||||||
primary_selection = NULL;
|
primary_selection = NULL;
|
||||||
NoticeChanged ();
|
NoticeChanged ();
|
||||||
}
|
}
|
||||||
|
else if (primary_selection)
|
||||||
|
{
|
||||||
|
/* The foreign selection was cleared; that means PRIMARY has
|
||||||
|
been disowned after the last foreign or local selection was
|
||||||
|
set, which means the local selection must be cleared as
|
||||||
|
well. */
|
||||||
|
scratch = primary_selection->resource;
|
||||||
|
zwp_primary_selection_source_v1_send_cancelled (scratch);
|
||||||
|
|
||||||
|
/* Clear the primary selection and notice a change. */
|
||||||
|
primary_selection = NULL;
|
||||||
|
NoticeChanged ();
|
||||||
|
}
|
||||||
|
|
||||||
foreign_selection_time = time;
|
foreign_selection_time = time;
|
||||||
}
|
}
|
||||||
|
|
43
xdata.c
43
xdata.c
|
@ -1093,13 +1093,32 @@ NoticePrimaryChanged (Time time)
|
||||||
static void
|
static void
|
||||||
NoticeClipboardCleared (Time time)
|
NoticeClipboardCleared (Time time)
|
||||||
{
|
{
|
||||||
/* Ignore outdated events. */
|
/* Ignore outdated events. time cannot simply be compared against
|
||||||
if (TimeIs (time, Earlier, last_x_selection_change))
|
the selection change time, because some clients do this:
|
||||||
|
|
||||||
|
- data_device.set_selection (data_source, N)
|
||||||
|
- data_source.delete (data_source)
|
||||||
|
- data_device.set_selection (data_source, N)
|
||||||
|
|
||||||
|
Which results in the selection being disowned at the same time as
|
||||||
|
the last selection change time, but then re-owned immediately
|
||||||
|
afterwards, leading to an out-of-date SelectionNotify event with
|
||||||
|
owner None having a timestamp equal to that time.
|
||||||
|
|
||||||
|
Thus, only timestamps after last_x_selection_change are
|
||||||
|
considered as valid here if x_selection_targets is NULL. */
|
||||||
|
|
||||||
|
if (!x_selection_targets)
|
||||||
|
{
|
||||||
|
if (!TimeIs (time, Later, last_x_selection_change))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (TimeIs (time, Earlier, last_x_selection_change))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DebugPrint ("CLIPBOARD was cleared at %lu\n", time);
|
DebugPrint ("CLIPBOARD was cleared at %lu\n", time);
|
||||||
|
|
||||||
last_x_selection_change = TimestampFromServerTime (time);
|
last_x_selection_change = TimestampFromClientTime (time);
|
||||||
XLClearForeignSelection (last_x_selection_change);
|
XLClearForeignSelection (last_x_selection_change);
|
||||||
|
|
||||||
/* Free data that is no longer used. */
|
/* Free data that is no longer used. */
|
||||||
|
@ -1111,13 +1130,17 @@ NoticeClipboardCleared (Time time)
|
||||||
static void
|
static void
|
||||||
NoticePrimaryCleared (Time time)
|
NoticePrimaryCleared (Time time)
|
||||||
{
|
{
|
||||||
/* Ignore outdated events. */
|
if (!x_primary_targets)
|
||||||
if (TimeIs (time, Earlier, last_primary_time))
|
{
|
||||||
|
if (!TimeIs (time, Later, last_primary_time))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (TimeIs (time, Earlier, last_primary_time))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DebugPrint ("PRIMARY was cleared at %lu\n", time);
|
DebugPrint ("PRIMARY was cleared at %lu\n", time);
|
||||||
|
|
||||||
last_primary_time = TimestampFromServerTime (time);
|
last_primary_time = TimestampFromClientTime (time);
|
||||||
XLClearForeignPrimary (last_primary_time);
|
XLClearForeignPrimary (last_primary_time);
|
||||||
|
|
||||||
/* Free data that is no longer used. */
|
/* Free data that is no longer used. */
|
||||||
|
@ -1133,17 +1156,21 @@ HandleSelectionNotify (XFixesSelectionNotifyEvent *event)
|
||||||
/* Ignore events sent when we get selection ownership. */
|
/* Ignore events sent when we get selection ownership. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Use the server timestamp in the fixes selection notify event
|
||||||
|
to synchronize the local time counter. */
|
||||||
|
TimestampFromServerTime (event->timestamp);
|
||||||
|
|
||||||
if (event->selection == CLIPBOARD
|
if (event->selection == CLIPBOARD
|
||||||
&& TimeIs (event->selection_timestamp, Later, last_clipboard_change))
|
&& TimeIs (event->selection_timestamp, Later, last_clipboard_change))
|
||||||
/* This time is used to keep track of whether or not things like
|
/* This time is used to keep track of whether or not things like
|
||||||
disowning the selection were successful. */
|
disowning the selection were successful. */
|
||||||
last_clipboard_change
|
last_clipboard_change
|
||||||
= TimestampFromServerTime (event->selection_timestamp);
|
= TimestampFromClientTime (event->selection_timestamp);
|
||||||
|
|
||||||
if (event->selection == XA_PRIMARY
|
if (event->selection == XA_PRIMARY
|
||||||
&& TimeIs (event->selection_timestamp, Later, last_primary_time))
|
&& TimeIs (event->selection_timestamp, Later, last_primary_time))
|
||||||
last_primary_time
|
last_primary_time
|
||||||
= TimestampFromServerTime (event->selection_timestamp);
|
= TimestampFromClientTime (event->selection_timestamp);
|
||||||
|
|
||||||
if (event->owner != None
|
if (event->owner != None
|
||||||
&& event->selection == CLIPBOARD)
|
&& event->selection == CLIPBOARD)
|
||||||
|
|
Loading…
Add table
Reference in a new issue