Apache OpenOffice (AOO) Bugzilla – Issue 82879
Freeze on drag'n'drop in document opened via loadComponentFromUrl()
Last modified: 2007-12-20 09:56:08 UTC
This problem has been giving us a lot of grief for some time now. Finally we've managed to extract a testcase. Steps to reproduce 1. Open the attached document test_FreezeOnDragAndDropOnWindows.odt 2. Tools/Macros/Organize Macros/Beanshell... 3. Select test_FreezeOnDragAndDropOnWindows.odt/Library1/FreezeOnDragAndDropOnWindows.bsh 4. Click "Edit" 5. Switch to the Beanshell Debug Window 6. Click "Run" 7. The macro opens a new Untitled1 document. Switch to that document and enter the text "foobar" 8. Select the letters "foo" with the mouse. 9. Now (try to) drag the selected letters to the end of the word. 10. The Untitled1 window is frozen and does not react to user interaction anymore. Notes: - Opening the data source browser (View/Data Sources F4) and attempting to drag a column heading into the document (which would result in a mailmerge field) also works to trigger the freeze, so it seems to be some general drag'n'drop problem. - The problem is not Writer-specific. You can change "swriter" to "scalc" in the macro and then attempt drag'n'drop in the Calc window and it will freeze, too. - If, after step 3., you click "Run" right away, to start the macro without going to the Beanshell window first, the freeze does not happen. We have spent a lot of time examining this issue. We've put loadComponentFromUrl() calls in lots of different places inside our custom Java component and it seems that there are a few "blessed" contexts in which the call will work without creating the freeze-situation. Simple situations seem to work, such as 1. register an event handler on the GlobalEventBroadcaster that calls loadComponentFromUrl() right away when an OnUnload event occurs 2. Close a window manually More complex situations fail, such as performing 2. above via UNO api from inside the component. The following works, too: 1. Write a small Basic macro that calls loadComponentFromUrl() 2. Run this macro manually via Tools/Macros/Run Macro The following doesn't work 1. Write a small Basic macro that calls loadComponentFromUrl() 2. Call this macro via the scripting framework from inside our component Somewhere I've read that all Basic scripts run in the same thread, so this experiment seems to show that the freeze does not depend on which thread is calling loadComponentFromUrl(). - We've tested the problem with different Java versions (up to Java 1.6) with no change in the symptoms, so it seems unrelated to the Java version. - The problem does not occur on Linux. - There are ways to unfreeze the window, such as right-clicking on its button in the Windows task bar. Once you do that, all the clicks you performed on the Window while frozen will be executed. So events are not lost, they're just not processed. To summarize: In all but the most trivial cases it seems to be impossible to use loadComponentFromUrl() from within a Java component without triggering the freeze condition. No tricks that we've attempted (such as the ways described above of calling a Basic macro via SFW or triggering a global event via API) have worked. Impact: This is our number 1 OOo issue at the moment. We've migrated a couple 1000(!!) desktops to OOo (under Windows) so far that all need our custom component (an important part of whose job unfortunately happens to be the opening of templates). We're telling people that they can't use drag'n'drop on text (a feature some people are very fond of) and that they have to use the cumbersome Insert/Fields/Other/Database dialog for inserting mailmerge fields rather than drag'n'drop (If you know how comfortable mail merge is in Word, you can imagine how happy people are with that). People are losing data (Not everyone is aware of the tricks to unfreeze the window). People are pissed. Management is pissed. Everyone's pissed. We're desperately looking for a workaround, but as stated above, nothing has worked so far. The only option I can see is to execute an external program to load the document, but that workaround is a big mess, because our component does not just load a template and then forget about it. It needs to do further processing on the new document, so it needs the handle returned by loadComponentFromUrl(). Just waiting for an OnLoad event or something like that doesn't work reliably, because there's no guarantee that the next event of that kind belongs to our load request. This means that the external program needs to pass the handle to our component (which has to block until the handle has been passed). This carries with it timing and deadlock issues(not to speak of the overhead) and needs user configuration (since the location of the external program can not be known). It's therefore a last-resort option only. A better solution would be very much appreciated.
Created attachment 49088 [details] Run macro from Beanshell edit window, then d'n'd in Untitled1 => Freeze
@ jsk: Something for you or is something for the API guys?
confirming the issue. Exactly as described.
Currently evaluating - i'm lacking a Windows machine currently (need to wait for the machines to complete testing cycle) so i gave it a quick look on Linux where i wasn't even able to start the bsh Editor.
What happens here is that the window created by the beanshell script does not work as a drop target which i believe is more likely VCL related -> to pl. Note that this is no regression - tested this back to PU 7 but it is well worth to get fixed for 2.4, i set the prio to 2 because the office frequently ends up in a frozen state (not always)
pl->jl: tra mentioned you as the new owner of the windows clipboard ? This would seem to be a deadlock in the service. I doubt that the document isn't registered as drop target.
jl->hro: Please take care of this.
.
Accepted.
Changed target to 2.3.1. We must not only create a seperate STA thread for a requested call to RegisterDragDrop if the calling thread is an MTA but also if the calling thread and the thread that created the Window are not identical. Usually the calling thread is the main thread, the same in which all windows are created and is STA or the threads differ and the calling thread is an MTA. Here we have a new scenario where the request for RegisterDragDrop is called from the thread that runs the BeanShell and this thread is STA or uninitialized and differs from the windows thread. ->Fixed.
Just to make sure, does your fix work for any Java thread, i.e. also threads from inside a Java component (not Beanshell)?
The defect had nothing to do with Java itself. It was just the Apartment Model the Thread used when a call to RegisterDragDrop was requested. Actually when the thread was from a MTA the call was dispatched in a different thread that attached the input queue to the thread that created the window. When it was from a STA there was the assumption that RegisterDragDrop worked (as the Documentation says) but this assumption was wrong. A dispatch to a new thread with attached input queue also has to be done if the threads just differ. Now this case is correctly handled. So the fix covers all scenarios where a thread from a STA (or unitialized apartment) tries to register drag and drop for a window that was not created in the same thread...or to give a short answer: Yes ;-)
CCed
Seen good on Windows / en_US / Full installation. Waiting for other builds.
set verified.
closing