1. Replace CurrentTime with actual server timestamp in clipboard selection ownership 2. Add get_server_time function to retrieve current X11 server timestamp by generating PropertyNotify event 3. Store selection timestamp globally for use in export_timestamp function 4. Maintain original window event mask when getting server time
The previous implementation used CurrentTime (0) which can cause issues with X11 clipboard handling. Using a proper server timestamp ensures correct synchronization and prevents potential race conditions in clipboard ownership transfers.
Signed-off-by: Jiajin Cui cuijiajin@uniontech.com
From: Jiajin Cui cuijiajin@uniontech.com
1. Replace CurrentTime with actual server timestamp in clipboard selection ownership 2. Add get_server_time function to retrieve current X11 server timestamp by generating PropertyNotify event 3. Store selection timestamp globally for use in export_timestamp function 4. Maintain original window event mask when getting server time
The previous implementation used CurrentTime (0) which can cause issues with X11 clipboard handling. Using a proper server timestamp ensures correct synchronization and prevents potential race conditions in clipboard ownership transfers.
Signed-off-by: Jiajin Cui cuijiajin@uniontech.com --- dlls/winex11.drv/clipboard.c | 50 +++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index ee0015639b8..99731a9126e 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -193,6 +193,7 @@ static DWORD clipboard_thread_id; static HWND clipboard_hwnd; static BOOL is_clipboard_owner; static Window selection_window; +static Time selection_timestamp; static Window import_window; static Atom current_selection; static UINT rendered_formats; @@ -1733,7 +1734,7 @@ static BOOL export_multiple( Display *display, Window win, Atom prop, Atom targe */ static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size ) { - Time time = CurrentTime; /* FIXME */ + Time time = selection_timestamp; put_property( display, win, prop, XA_INTEGER, 32, &time, 1 ); return TRUE; } @@ -1906,6 +1907,44 @@ static BOOL read_property( Display *display, Window w, Atom prop, return TRUE; }
+/************************************************************************** + * get_server_time + * + * Get the current X11 server timestamp by generating a PropertyNotify event + */ +static Time get_server_time( Display *display, Window win ) +{ + static Atom timestamp_prop = 0; + XEvent event; + Time timestamp = CurrentTime; + XWindowAttributes attrs; + + if (!timestamp_prop) + timestamp_prop = XInternAtom( display, "__wine_timestamp", False ); + + /* Ensure window can receive PropertyNotify events */ + XGetWindowAttributes( display, win, &attrs ); + XSelectInput( display, win, attrs.your_event_mask | PropertyChangeMask ); + + /* Generate a PropertyNotify event to get server time */ + XChangeProperty( display, win, timestamp_prop, XA_INTEGER, 8, PropModeReplace, NULL, 0 ); + XSync( display, False ); + + /* Wait for the PropertyNotify event */ + while (XCheckTypedWindowEvent( display, win, PropertyNotify, &event )) + { + if (event.xproperty.atom == timestamp_prop) + { + timestamp = event.xproperty.time; + break; + } + } + + /* Restore original event mask */ + XSelectInput( display, win, attrs.your_event_mask ); + + return timestamp; +}
/************************************************************************** * acquire_selection @@ -1920,9 +1959,12 @@ static void acquire_selection( Display *display ) InputOutput, CopyFromParent, 0, NULL ); if (!selection_window) return;
- XSetSelectionOwner( display, x11drv_atom(CLIPBOARD), selection_window, CurrentTime ); - if (use_primary_selection) XSetSelectionOwner( display, XA_PRIMARY, selection_window, CurrentTime ); - TRACE( "win %lx\n", selection_window ); + /* Get the current server timestamp for selection ownership */ + selection_timestamp = get_server_time( display, selection_window ); + + XSetSelectionOwner( display, x11drv_atom(CLIPBOARD), selection_window, selection_timestamp ); + if (use_primary_selection) XSetSelectionOwner( display, XA_PRIMARY, selection_window, selection_timestamp ); + TRACE( "win %lx timestamp %lu\n", selection_window, selection_timestamp ); }
We can use a VMware virtual machine to test this issue. The VMware virtual machine determines whether the clipboard data has been updated by checking the timestamp.
Esme Povirk (@madewokherd) commented about dlls/winex11.drv/clipboard.c:
- XGetWindowAttributes( display, win, &attrs );
- XSelectInput( display, win, attrs.your_event_mask | PropertyChangeMask );
- /* Generate a PropertyNotify event to get server time */
- XChangeProperty( display, win, timestamp_prop, XA_INTEGER, 8, PropModeReplace, NULL, 0 );
- XSync( display, False );
- /* Wait for the PropertyNotify event */
- while (XCheckTypedWindowEvent( display, win, PropertyNotify, &event ))
- {
if (event.xproperty.atom == timestamp_prop){timestamp = event.xproperty.time;break;}- }
This might remove unrelated events from the queue, though that won't matter for its current use case.
Esme Povirk (@madewokherd) commented about dlls/winex11.drv/clipboard.c:
}
+/**************************************************************************
get_server_time
- Get the current X11 server timestamp by generating a PropertyNotify event
- */
+static Time get_server_time( Display *display, Window win ) +{
- static Atom timestamp_prop = 0;
- XEvent event;
- Time timestamp = CurrentTime;
- XWindowAttributes attrs;
- if (!timestamp_prop)
timestamp_prop = XInternAtom( display, "__wine_timestamp", False );
This should probably use X11DRV_Atoms.