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