From 1137e3502dc7e27e9db64c18436bfbc27a763820 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 10 Jan 2017 16:23:20 +0100 Subject: [PATCH] winex11: Don't update the clipboard if the X11 selection hasn't changed. Signed-off-by: Alexandre Julliard --- dlls/winex11.drv/clipboard.c | 84 +++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index 3ff8453ecbf..8afe2c2a882 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -191,6 +191,7 @@ static BOOL is_clipboard_owner; static Window selection_window; static Window import_window; static Atom current_selection; +static UINT rendered_formats; static ULONG64 last_clipboard_update; static struct clipboard_format **current_x11_formats; static unsigned int nb_current_x11_formats; @@ -1025,13 +1026,13 @@ void X11DRV_CLIPBOARD_ImportSelection( Display *display, Window win, Atom select /************************************************************************** * render_format */ -static void render_format( UINT id ) +static HANDLE render_format( UINT id ) { Display *display = thread_display(); unsigned int i; HANDLE handle = 0; - if (!current_selection) return; + if (!current_selection) return 0; for (i = 0; i < nb_current_x11_formats; i++) { @@ -1040,6 +1041,7 @@ static void render_format( UINT id ) if (handle) SetClipboardData( id, handle ); break; } + return handle; } @@ -1778,45 +1780,77 @@ static void release_selection( Display *display, Time time ) * * Retrieve the contents of the X11 selection when it's owned by an X11 app. */ -static void request_selection_contents( Display *display ) +static BOOL request_selection_contents( Display *display, BOOL changed ) { struct clipboard_format *targets = find_x11_format( x11drv_atom(TARGETS) ); struct clipboard_format *string = find_x11_format( XA_STRING ); + struct clipboard_format *format = NULL; + Window owner = 0; + unsigned char *data = NULL; + unsigned long size = 0; + Atom type = 0; + + static Atom last_selection; + static Window last_owner; + static struct clipboard_format *last_format; + static Atom last_type; + static unsigned char *last_data; + static unsigned long last_size; assert( targets ); assert( string ); current_selection = 0; - if (use_primary_selection && XGetSelectionOwner( display, XA_PRIMARY )) + if (use_primary_selection) { - if (import_selection( display, import_window, XA_PRIMARY, targets )) + if ((owner = XGetSelectionOwner( display, XA_PRIMARY ))) current_selection = XA_PRIMARY; - else - import_selection( display, import_window, XA_PRIMARY, string ); } - else if (XGetSelectionOwner( display, x11drv_atom(CLIPBOARD) )) + if (!current_selection) { - if (import_selection( display, import_window, x11drv_atom(CLIPBOARD), targets )) + if ((owner = XGetSelectionOwner( display, x11drv_atom(CLIPBOARD) ))) current_selection = x11drv_atom(CLIPBOARD); - else - import_selection( display, import_window, x11drv_atom(CLIPBOARD), string ); } -} + if (current_selection) + { + if (convert_selection( display, import_window, current_selection, targets, &type, &data, &size )) + format = targets; + else if (convert_selection( display, import_window, current_selection, string, &type, &data, &size )) + format = string; + } + + changed = (changed || + rendered_formats || + last_selection != current_selection || + last_owner != owner || + last_format != format || + last_type != type || + last_size != size || + memcmp( last_data, data, size )); + + if (!changed) + { + HeapFree( GetProcessHeap(), 0, data ); + return FALSE; + } -/************************************************************************** - * grab_win32_clipboard - * - * Grab the Win32 clipboard when an X11 app has grabbed the X11 selection, - * and fill it with the selection contents. - */ -static BOOL grab_win32_clipboard( Display *display ) -{ if (!OpenClipboard( clipboard_hwnd )) return FALSE; + TRACE( "selection changed, importing\n" ); EmptyClipboard(); is_clipboard_owner = TRUE; + rendered_formats = 0; + + if (format) format->import( type, data, size ); + + HeapFree( GetProcessHeap(), 0, last_data ); + last_selection = current_selection; + last_owner = owner; + last_format = format; + last_type = type; + last_data = data; + last_size = size; last_clipboard_update = GetTickCount64(); - request_selection_contents( display ); CloseClipboard(); return TRUE; } @@ -1832,7 +1866,7 @@ BOOL update_clipboard( HWND hwnd ) if (hwnd != clipboard_hwnd) return TRUE; if (!is_clipboard_owner) return TRUE; if (GetTickCount64() - last_clipboard_update <= SELECTION_UPDATE_DELAY) return TRUE; - return grab_win32_clipboard( thread_display() ); + return request_selection_contents( thread_display(), FALSE ); } @@ -1852,7 +1886,7 @@ static LRESULT CALLBACK clipboard_wndproc( HWND hwnd, UINT msg, WPARAM wp, LPARA acquire_selection( thread_init_display() ); break; case WM_RENDERFORMAT: - render_format( wp ); + if (render_format( wp )) rendered_formats++; break; case WM_DESTROYCLIPBOARD: TRACE( "WM_DESTROYCLIPBOARD: lost ownership\n" ); @@ -1935,7 +1969,7 @@ static DWORD WINAPI clipboard_thread( void *arg ) clipboard_thread_id = GetCurrentThreadId(); AddClipboardFormatListener( clipboard_hwnd ); register_builtin_formats(); - grab_win32_clipboard( clipboard_display ); + request_selection_contents( clipboard_display, TRUE ); TRACE( "clipboard thread %04x running\n", GetCurrentThreadId() ); while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg ); @@ -2014,7 +2048,7 @@ BOOL X11DRV_SelectionClear( HWND hwnd, XEvent *xev ) if (event->selection != x11drv_atom(CLIPBOARD)) return FALSE; release_selection( event->display, event->time ); - grab_win32_clipboard( event->display ); + request_selection_contents( event->display, TRUE ); return FALSE; } -- 2.11.4.GIT