Snjezana Peco wrote:
Max Areshkau wrote:
> Snjezana Peco wrote:
>> Max Rydahl Andersen wrote:
>>>>> Doing it in a seperate thread is a different enhancement I think,
>>>>> but definitly
>>>>> also worth it. The current idea is just to not update on every
>>>>> stroke since users
>>>>> would normally write more than one letter and while he is typing
>>>>> the visual view
>>>>> does not need to be updated 100% live (especially not when its
>>>>> update seem to be
>>>>> so slow in special cases).
>>>>>
>>>>>
>>>>>
>>>> I have tried to separate of visual editor update on user input into
>>>> different thread(you can see commnets for JBIDE-675),
>>>> and I founded following problems:
>>>> 1) Modifications of nsIDOM* nodes can be done only in UI thread,
>>>> if it's
>>>> done in non UI thread it's crashes a
>>>> eclipse.
>>>> 2)If we update nodes in UI thread, the user input thread are
>>>> suspended.
>>>>
>>>
>>> Too bad ;( Do we know why there is this limitation ?
>>>
>>>
>>
>> Mozilla requires DOM modifications to be done in the UI thread. It
>> is possible to split the VPE action (notifyChanged) into the UI and
>> non-UI part.
>> This wouldn't be trivial.
>>
>> Snjeza
> Looks like we can modify DOM not only from UI thread, for it we
> should use proxy objects (nsIProxyObjectManager), according following
> documentation
>
http://developer.mozilla.org/en/docs/JavaXPCOM:Embedding_Mozilla_in_a_Jav....
>
>
The article is talking about calling XPCOM UI from another thread (in
Eclipse, you can do it using display.syncExec() or
display.asyncExec()). However, you can't execute XPCOM methods in
non-UI thread. In most of the cases, that would crash the application.
You can separate non-UI part from the UI part and call XPCOM UI using
the mentioned methods.
Snjeza
I have tried to implement creation of proxy for modification DOM nodes
and with it's eclipse doesn't crashes and user can edit source page
while visual
part is updated. I have attached my changes. If I run the some code
without proxy eclipse crashes, but with proxy objects it's works. XPCOM
methods are executed from non ui thread.
Index:
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe/src/org/jboss/tools/vpe/editor/VpeVisualDomBuilder.java
===================================================================
---
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe/src/org/jboss/tools/vpe/editor/VpeVisualDomBuilder.java (revision
6924)
+++
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe/src/org/jboss/tools/vpe/editor/VpeVisualDomBuilder.java (working
copy)
@@ -71,6 +71,7 @@
import org.jboss.tools.vpe.editor.util.TextUtil;
import org.jboss.tools.vpe.editor.util.VisualDomUtil;
import org.jboss.tools.vpe.editor.util.VpeStyleUtil;
+import org.jboss.tools.vpe.xulrunner.ProxyManager;
import org.jboss.tools.vpe.xulrunner.editor.XulRunnerEditor;
import org.jboss.tools.vpe.xulrunner.editor.XulRunnerVpeUtils;
import org.mozilla.interfaces.nsIDOMAttr;
@@ -848,8 +849,11 @@
nsIDOMNode visualContainer = visualOldNode.getParentNode();
nsIDOMNode visualNextNode = visualOldNode.getNextSibling();
if (visualContainer != null) {
+
+ //jbide-675 non ui thread added by Max Areshkau
+ visualContainer=ProxyManager.createProxyForNode(visualContainer);
visualContainer.removeChild(visualOldNode);
- addNode(sourceNode, visualNextNode, visualContainer);
+ addNode(sourceNode, ProxyManager.createProxyForNode(visualNextNode),
visualContainer);
}
} else {
// Max Areshkau Why we need update parent node when we update text
Index:
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe/src/org/jboss/tools/vpe/editor/VpeController.java
===================================================================
---
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe/src/org/jboss/tools/vpe/editor/VpeController.java (revision
6924)
+++
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe/src/org/jboss/tools/vpe/editor/VpeController.java (working
copy)
@@ -144,6 +144,7 @@
import org.jboss.tools.vpe.selbar.SelectionBar;
import org.jboss.tools.vpe.xulrunner.browser.util.DOMTreeDumper;
import org.jboss.tools.vpe.xulrunner.editor.XulRunnerEditor;
+import org.mozilla.interfaces.nsIComponentManager;
import org.mozilla.interfaces.nsIDOMDocument;
import org.mozilla.interfaces.nsIDOMElement;
import org.mozilla.interfaces.nsIDOMEvent;
@@ -151,8 +152,12 @@
import org.mozilla.interfaces.nsIDOMMouseEvent;
import org.mozilla.interfaces.nsIDOMMutationEvent;
import org.mozilla.interfaces.nsIDOMNode;
+import org.mozilla.interfaces.nsIEventQueue;
+import org.mozilla.interfaces.nsIEventQueueService;
+import org.mozilla.interfaces.nsIProxyObjectManager;
import org.mozilla.interfaces.nsISelection;
import org.mozilla.interfaces.nsISelectionListener;
+import org.mozilla.interfaces.nsIServiceManager;
import org.mozilla.interfaces.nsISupports;
import org.mozilla.xpcom.Mozilla;
import org.w3c.dom.Attr;
@@ -378,7 +383,18 @@
display= PlatformUI.getWorkbench().getDisplay();
if (display != null && (Thread.currentThread() == display.getThread()))
{
- notifyChangedInUiThread(notifier, eventType, feature, oldValue, newValue, pos);
+ Job nonUIJob = new Job("Update Job"){ //$NON-NLS-1$
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ synchronized (this) {
+ notifyChangedInUiThread(notifier, eventType, feature, oldValue, newValue, pos);
+ }
+ return Status.OK_STATUS;
+ }};
+ nonUIJob.setPriority(Job.LONG);
+ nonUIJob.schedule();
+// notifyChangedInUiThread(notifier, eventType, feature, oldValue, newValue,
pos);
return;
}
//start job when we modify file in non ui thread
Index:
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/browser/XulRunnerBrowser.java
===================================================================
---
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/browser/XulRunnerBrowser.java (revision
6924)
+++
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/browser/XulRunnerBrowser.java (working
copy)
@@ -93,7 +93,7 @@
webBrowser = (nsIWebBrowser) browser.getWebBrowser();
if (webBrowser == null) {
- throw new XulRunnerException("nsIWebBrowser is not available");
// $NON-NLS-1$
+ throw new XulRunnerException("nsIWebBrowser is not available");
//$NON-NLS-1$
}
setBoolRootPref(PREFERENCE_DISABLEOPENDURINGLOAD, true);
@@ -108,7 +108,7 @@
// nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID);
nsIServiceManager serviceManager = mozilla.getServiceManager();
nsIWebProgress webProgress = (nsIWebProgress) serviceManager
- .getServiceByContractID("(a)mozilla.org/docloaderservice;1", //
$NON-NLS-1$
+ .getServiceByContractID("(a)mozilla.org/docloaderservice;1",
//$NON-NLS-1$
nsIWebProgress.NS_IWEBPROGRESS_IID);
webProgress.addProgressListener(this, nsIWebProgress.NOTIFY_ALL);
Index:
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/browser/util/DOMTreeDumper.java
===================================================================
---
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/browser/util/DOMTreeDumper.java (revision
6924)
+++
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/browser/util/DOMTreeDumper.java (working
copy)
@@ -63,6 +63,12 @@
dumpDocument(doc);
}
+ public void dumpNodeToStream(PrintStream ps, nsIDOMNode domNode) {
+
+ this.ps=ps;
+ dumpNode(domNode);
+ }
+
private void dumpDocument(nsIDOMDocument doc) {
if (doc == null) {
return;
Index:
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/editor/XulRunnerEditor.java
===================================================================
---
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/editor/XulRunnerEditor.java (revision
6924)
+++
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/editor/XulRunnerEditor.java (working
copy)
@@ -22,6 +22,7 @@
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.jboss.tools.vpe.xulrunner.BrowserPlugin;
+import org.jboss.tools.vpe.xulrunner.ProxyManager;
import org.jboss.tools.vpe.xulrunner.XPCOM;
import org.jboss.tools.vpe.xulrunner.XulRunnerException;
import org.jboss.tools.vpe.xulrunner.browser.XulRunnerBrowser;
@@ -392,7 +393,9 @@
nsIServiceManager serviceManager = Mozilla.getInstance().getServiceManager();
iFlasher = (inIFlasher)
serviceManager.getServiceByContractID(XPCOM.IN_FLASHER_CONTRACTID,
inIFlasher.INIFLASHER_IID);
iFlasher.setThickness(2);
+// iFlasher = ProxyManager.createProxyForFlasher(iFlasher);
}
+ iFlasher = ProxyManager.createProxyForFlasher(iFlasher);
return iFlasher;
}
Index:
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/ProxyManager.java
===================================================================
---
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/ProxyManager.java (revision
0)
+++
/Users/mareshkau/develop/rhds/normal_update/org.jboss.tools.vpe.xulrunner/src/org/jboss/tools/vpe/xulrunner/ProxyManager.java (revision
0)
@@ -0,0 +1,90 @@
+/*******************************************************************************
+* Copyright (c) 2007 Red Hat, Inc.
+* Distributed under license by Red Hat, Inc. All rights reserved.
+* This program is made available under the terms of the
+* Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at
http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Red Hat, Inc. - initial API and implementation
+******************************************************************************/
+package org.jboss.tools.vpe.xulrunner;
+
+import org.mozilla.interfaces.inIFlasher;
+import org.mozilla.interfaces.nsIComponentManager;
+import org.mozilla.interfaces.nsIDOMElement;
+import org.mozilla.interfaces.nsIDOMNode;
+import org.mozilla.interfaces.nsIEventQueue;
+import org.mozilla.interfaces.nsIEventQueueService;
+import org.mozilla.interfaces.nsIProxyObjectManager;
+import org.mozilla.interfaces.nsIServiceManager;
+import org.mozilla.xpcom.Mozilla;
+
+/**
+ * @author mareshkau
+ * We can access from mozilla DOM only from proxy in non ui threads
+ */
+public class ProxyManager {
+
+ private static nsIProxyObjectManager proxyObjectManager;
+
+ private static nsIEventQueue eventQueue;
+
+ /**
+ * Creates a proxy for node
+ * @param proxy for nodes
+ * @return
+ */
+ public static nsIDOMNode createProxyForNode(nsIDOMNode node) {
+
+ nsIDOMNode proxyNode =null;
+ proxyNode = (nsIDOMNode)getProxyObjectManager().getProxyForObject(getEventQueue(),
nsIDOMNode.NS_IDOMNODE_IID,
+ node, nsIProxyObjectManager.INVOKE_SYNC);
+ return proxyNode;
+ }
+ /**
+ *
+ * @param element
+ * @return proxy for element
+ */
+ public static nsIDOMElement createProxyForElement(nsIDOMElement element) {
+
+ nsIDOMElement proxyElement =null;
+ proxyElement =
(nsIDOMElement)getProxyObjectManager().getProxyForObject(getEventQueue(),
nsIDOMElement.NS_IDOMELEMENT_IID,
+ element, nsIProxyObjectManager.INVOKE_SYNC);
+ return proxyElement;
+ }
+ /**
+ *
+ * @param element
+ * @return proxy for element
+ */
+ public static inIFlasher createProxyForFlasher(inIFlasher flasher) {
+
+ inIFlasher proxyFlasher =null;
+ proxyFlasher = (inIFlasher)getProxyObjectManager().getProxyForObject(getEventQueue(),
inIFlasher.INIFLASHER_IID,
+ flasher, nsIProxyObjectManager.INVOKE_ASYNC);
+ return proxyFlasher;
+ }
+ /**
+ * @return the proxyObjectManager
+ */
+ private static nsIProxyObjectManager getProxyObjectManager() {
+ if(proxyObjectManager==null) {
+ nsIComponentManager componentManager = Mozilla.getInstance().getComponentManager();
+ proxyObjectManager =
(nsIProxyObjectManager)componentManager.createInstanceByContractID("(a)mozilla.org/xpcomproxy;1",null,nsIProxyObjectManager.NS_IPROXYOBJECTMANAGER_IID);
//$NON-NLS-1$
+ }
+ return proxyObjectManager;
+ }
+ /**
+ * @return the eventQueue
+ */
+ private static nsIEventQueue getEventQueue() {
+ if(eventQueue==null) {
+ nsIServiceManager serviceManager = Mozilla.getInstance().getServiceManager();
+ nsIEventQueueService eventQueueServive =
(nsIEventQueueService)serviceManager.getServiceByContractID("(a)mozilla.org/event-queue-service;1",nsIEventQueueService.NS_IEVENTQUEUESERVICE_IID);
//$NON-NLS-1$
+ eventQueue =
eventQueueServive.getSpecialEventQueue(nsIEventQueueService.UI_THREAD_EVENT_QUEUE);
+ }
+ return eventQueue;
+ }
+}