Bug 140813

Summary: Use GetUpdatedClipboardFormats Vista API to minimize clipboard-related overhead
Product: LibreOffice Reporter: Mike Kaganski <mikekaganski>
Component: LibreOfficeAssignee: Mike Kaganski <mikekaganski>
Status: RESOLVED FIXED    
Severity: normal CC: glogow, himajin100000
Priority: medium    
Version: unspecified   
Hardware: All   
OS: Windows (All)   
See Also: https://bugs.documentfoundation.org/show_bug.cgi?id=116983
https://bugs.documentfoundation.org/show_bug.cgi?id=142104
https://bugs.documentfoundation.org/show_bug.cgi?id=136762
https://bugs.documentfoundation.org/show_bug.cgi?id=143565
https://bugs.documentfoundation.org/show_bug.cgi?id=62196
Whiteboard: target:7.2.0 target:7.1.3
Crash report or crash signature: Regression By:
Bug Depends on:    
Bug Blocks: 108843    

Description Mike Kaganski 2021-03-05 08:22:35 UTC
Currently LibreOffice uses a dedicated thread to respond to clipboard change notifications (see CMtaOleClipboard in vcl/win/dtrans/MtaOleClipb.cxx), which obtains an IDataObject (using OleGetClipboard) for the updated clipboard data, and stores it for possible further use. The object is wrapped into an appartment-neutral object in CWinClipboard::getContents (vcl/win/dtrans/WinClipboard.cxx). This object is later queried for available formats when deciding if Paste should be enabled, and which paste options to provide. Often, this is the only information needed, because not every data in clipboard ends up in LibreOffice.

This is (a) rather expensive (obtaining a COM object, creating an appartment-neutral wrapper over it, having to properly release it at the next clipboard update - for each clipboard event, regardless if we will use the data or not), and (b) prone to errors (see e.g. tdf#136175; also there are hangs sometimes in unit testing, caused by deadlocking of released COM object waiting for a thread that is waiting for its release).

Since Windows Vista, there's GetUpdatedClipboardFormats function [1] created to list available formats in the system clipboard without opening it, and so without race conditions [2] [3]. We could possibly reimplement the thread to only get the list of available formats using this function, and only obtain the COM object when actually pasting something. That would require that the XTransferable returned from CWinClipboard::getContents would be able to ask for the IDataObject only when needed.

[1] https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getupdatedclipboardformats
[2] https://techcommunity.microsoft.com/t5/microsoft-security-and/why-does-my-shared-clipboard-not-work-part-2/ba-p/246465
[3] https://support.citrix.com/article/CTX216506
Comment 1 Commit Notification 2021-03-06 06:13:17 UTC
Mike Kaganski committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/7b6c0e63e64eb2ad1e83bd744a0d20f78c7a6b84

tdf#140813: Use GetUpdatedClipboardFormats to enumerate clipboard formats

It will be available in 7.2.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 2 Timur 2021-03-06 07:40:09 UTC
I guess Win only. 
BTW, congrats for fixing the most annoying bug of clipboard paste :)
Comment 3 Mike Kaganski 2021-03-06 08:24:17 UTC
(In reply to Timur from comment #2)
> I guess Win only. 

Definitely; thanks.

> BTW, congrats for fixing the most annoying bug of clipboard paste :)

Thank you; that was mainly work of others who created a reproducer and outlined the solution :-)
Comment 4 Mike Kaganski 2021-03-25 14:22:30 UTC
Backport to 7-1 is at https://gerrit.libreoffice.org/c/core/+/112971, needed to fix the problem seen in bug 116983 comment 92.
Comment 5 Telesto 2021-03-30 12:24:36 UTC
Also thanks solving this and bug 136175. Those where nasty hard to catch bugs.. It's really a relieve knowing those are gone now :-)
Comment 6 Commit Notification 2021-03-31 03:50:38 UTC
Mike Kaganski committed a patch related to this issue.
It has been pushed to "libreoffice-7-1":

https://git.libreoffice.org/core/commit/5be35c2b1fe127f69223a92965cbbc92dab15c3b

tdf#140813: Use GetUpdatedClipboardFormats to enumerate clipboard formats

It will be available in 7.1.3.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 7 Mike Kaganski 2021-03-31 13:20:15 UTC
(In reply to Telesto from comment #5)

Thank you for the reliable way to repro - that is the one most important bit that was missing from the original bug.