Alexandre Julliard : winex11: Don' t update the clipboard if the X11 selection hasn't changed.
Alexandre Julliard
julliard at winehq.org
Tue Jan 10 15:24:42 CST 2017
Module: wine
Branch: master
Commit: 1137e3502dc7e27e9db64c18436bfbc27a763820
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1137e3502dc7e27e9db64c18436bfbc27a763820
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue Jan 10 16:23:20 2017 +0100
winex11: Don't update the clipboard if the X11 selection hasn't changed.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 3ff8453..8afe2c2 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;
}
More information about the wine-cvs
mailing list