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 ); }