winex11: Don't update the clipboard if the X11 selection hasn't changed.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-01-10 16:23:20 +01:00
parent e4cc5bf1b9
commit 1137e3502d
1 changed files with 59 additions and 25 deletions

View File

@ -191,6 +191,7 @@ static BOOL is_clipboard_owner;
static Window selection_window; static Window selection_window;
static Window import_window; static Window import_window;
static Atom current_selection; static Atom current_selection;
static UINT rendered_formats;
static ULONG64 last_clipboard_update; static ULONG64 last_clipboard_update;
static struct clipboard_format **current_x11_formats; static struct clipboard_format **current_x11_formats;
static unsigned int nb_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 * render_format
*/ */
static void render_format( UINT id ) static HANDLE render_format( UINT id )
{ {
Display *display = thread_display(); Display *display = thread_display();
unsigned int i; unsigned int i;
HANDLE handle = 0; HANDLE handle = 0;
if (!current_selection) return; if (!current_selection) return 0;
for (i = 0; i < nb_current_x11_formats; i++) for (i = 0; i < nb_current_x11_formats; i++)
{ {
@ -1040,6 +1041,7 @@ static void render_format( UINT id )
if (handle) SetClipboardData( id, handle ); if (handle) SetClipboardData( id, handle );
break; 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. * 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 *targets = find_x11_format( x11drv_atom(TARGETS) );
struct clipboard_format *string = find_x11_format( XA_STRING ); 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( targets );
assert( string ); assert( string );
current_selection = 0; 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; 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); 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; if (!OpenClipboard( clipboard_hwnd )) return FALSE;
TRACE( "selection changed, importing\n" );
EmptyClipboard(); EmptyClipboard();
is_clipboard_owner = TRUE; 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(); last_clipboard_update = GetTickCount64();
request_selection_contents( display );
CloseClipboard(); CloseClipboard();
return TRUE; return TRUE;
} }
@ -1832,7 +1866,7 @@ BOOL update_clipboard( HWND hwnd )
if (hwnd != clipboard_hwnd) return TRUE; if (hwnd != clipboard_hwnd) return TRUE;
if (!is_clipboard_owner) return TRUE; if (!is_clipboard_owner) return TRUE;
if (GetTickCount64() - last_clipboard_update <= SELECTION_UPDATE_DELAY) 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() ); acquire_selection( thread_init_display() );
break; break;
case WM_RENDERFORMAT: case WM_RENDERFORMAT:
render_format( wp ); if (render_format( wp )) rendered_formats++;
break; break;
case WM_DESTROYCLIPBOARD: case WM_DESTROYCLIPBOARD:
TRACE( "WM_DESTROYCLIPBOARD: lost ownership\n" ); TRACE( "WM_DESTROYCLIPBOARD: lost ownership\n" );
@ -1935,7 +1969,7 @@ static DWORD WINAPI clipboard_thread( void *arg )
clipboard_thread_id = GetCurrentThreadId(); clipboard_thread_id = GetCurrentThreadId();
AddClipboardFormatListener( clipboard_hwnd ); AddClipboardFormatListener( clipboard_hwnd );
register_builtin_formats(); register_builtin_formats();
grab_win32_clipboard( clipboard_display ); request_selection_contents( clipboard_display, TRUE );
TRACE( "clipboard thread %04x running\n", GetCurrentThreadId() ); TRACE( "clipboard thread %04x running\n", GetCurrentThreadId() );
while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg ); 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; if (event->selection != x11drv_atom(CLIPBOARD)) return FALSE;
release_selection( event->display, event->time ); release_selection( event->display, event->time );
grab_win32_clipboard( event->display ); request_selection_contents( event->display, TRUE );
return FALSE; return FALSE;
} }