Bug 516727 - Electrolysis+Fennec: forward mouse events from the chrome tiles to the content process
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 05 Nov 2009 20:21:09 +0200
changeset 36049 2856c7a71f4f79b5ea2f36abe8d092cad0d9ef8f
parent 36048 43851a1c6bc6f822186755ba151e3484de4e64df
child 36050 96c251dc41d8529ad9dfae1892389fb7ef463cd1
push idunknown
push userunknown
push dateunknown
bugs516727
milestone1.9.3a1pre
Bug 516727 - Electrolysis+Fennec: forward mouse events from the chrome tiles to the content process
content/base/public/nsIFrameLoader.idl
content/base/src/nsFrameLoader.cpp
dom/ipc/PIFrameEmbedding.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/ipc/test.xul
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -38,17 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 interface nsIDocShell;
 interface nsIURI;
 interface nsIFrame;
 
-[scriptable, uuid(897af00a-c907-4311-88dc-f9d12f05b110)]
+[scriptable, uuid(8f94788d-ec69-4220-971c-0fd68d47b80f)]
 interface nsIFrameLoader : nsISupports
 {
   /**
    * Get the docshell from the frame loader.
    */
   readonly attribute nsIDocShell docShell;
 
   /**
@@ -83,16 +83,28 @@ interface nsIFrameLoader : nsISupports
    */
   [noscript] void updatePositionAndSize(in nsIFrame aIFrame);
 
   /**
    * Activate remote frame.
    * Throws an exception with non-remote frames.
    */
   void activateRemoteFrame();
+
+  /**
+   * @see nsIDOMWindowUtils sendMouseEvent.
+   */
+  void sendCrossProcessMouseEvent(in AString aType,
+                                  in float aX,
+                                  in float aY,
+                                  in long aButton,
+                                  in long aClickCount,
+                                  in long aModifiers,
+                                  [optional] in boolean aIgnoreRootScrollFrame);
+
 };
 
 native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
 
 [scriptable, uuid(8f3b12a0-35ae-4e0d-9152-8e0d7e49d446)]
 interface nsIFrameLoaderOwner : nsISupports
 {
   /**
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -1465,8 +1465,29 @@ nsFrameLoader::ActivateRemoteFrame() {
 #ifdef MOZ_IPC
   if (mChildProcess) {
     mChildProcess->Activate();
     return NS_OK;
   }
 #endif
   return NS_ERROR_UNEXPECTED;
 }
+
+NS_IMETHODIMP
+nsFrameLoader::SendCrossProcessMouseEvent(const nsAString& aType,
+                                          float aX,
+                                          float aY,
+                                          PRInt32 aButton,
+                                          PRInt32 aClickCount,
+                                          PRInt32 aModifiers,
+                                          PRBool aIgnoreRootScrollFrame)
+{
+#ifdef MOZ_IPC
+  if (mChildProcess) {
+    mChildProcess->SendMouseEvent(aType, aX, aY, aButton,
+                                  aClickCount, aModifiers,
+                                  aIgnoreRootScrollFrame);
+    return NS_OK;
+  }
+#endif
+  return NS_ERROR_FAILURE;
+}
+
--- a/dom/ipc/PIFrameEmbedding.ipdl
+++ b/dom/ipc/PIFrameEmbedding.ipdl
@@ -70,16 +70,27 @@ child:
          PRUint32 width,
          PRUint32 height);
 
     /**
      * Sending an activate message moves focus to the child.
      */
     activate();
 
+  /**
+   * @see nsIDOMWindowUtils sendMouseEvent.
+   */
+    sendMouseEvent(nsString aType,
+                   PRInt32 aX, //XXX should be float, but ipdl doesn't seem to support that.
+                   PRInt32 aY, //XXX - " -
+                   PRInt32 aButton,
+                   PRInt32 aClickCount,
+                   PRInt32 aModifiers,
+                   bool aIgnoreRootScrollFrame);
+
     PDocumentRenderer(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, nsString bgcolor, PRUint32 flags, bool flush);
 
 parent:
 
     ~PDocumentRenderer(PRUint32 w, PRUint32 h, nsCString data);
 };
 
 }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -307,16 +307,33 @@ TabChild::Recvmove(const PRUint32& x,
 bool
 TabChild::Recvactivate()
 {
   nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(mWebNav);
   browser->Activate();
   return true;
 }
 
+bool
+TabChild::RecvsendMouseEvent(const nsString& aType,
+                             const PRInt32&  aX,
+                             const PRInt32&  aY,
+                             const PRInt32&  aButton,
+                             const PRInt32&  aClickCount,
+                             const PRInt32&  aModifiers,
+                             const bool&     aIgnoreRootScrollFrame)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mWebNav);
+  nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
+  NS_ENSURE_TRUE(utils, true);
+  utils->SendMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers,
+                        aIgnoreRootScrollFrame);
+  return true;
+}
+
 mozilla::ipc::PDocumentRendererChild*
 TabChild::AllocPDocumentRenderer(
         const PRInt32& x,
         const PRInt32& y,
         const PRInt32& w,
         const PRInt32& h,
         const nsString& bgcolor,
         const PRUint32& flags,
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -70,16 +70,23 @@ public:
     virtual bool RecvcreateWidget(const MagicWindowHandle& parentWidget);
     virtual bool RecvdestroyWidget();
     virtual bool RecvloadURL(const nsCString& uri);
     virtual bool Recvmove(const PRUint32& x,
                           const PRUint32& y,
                           const PRUint32& width,
                           const PRUint32& height);
     virtual bool Recvactivate();
+    virtual bool RecvsendMouseEvent(const nsString& aType,
+                                    const PRInt32&  aX,
+                                    const PRInt32&  aY,
+                                    const PRInt32&  aButton,
+                                    const PRInt32&  aClickCount,
+                                    const PRInt32&  aModifiers,
+                                    const bool&     aIgnoreRootScrollFrame);
     virtual mozilla::ipc::PDocumentRendererChild* AllocPDocumentRenderer(
             const PRInt32& x,
             const PRInt32& y,
             const PRInt32& w,
             const PRInt32& h,
             const nsString& bgcolor,
             const PRUint32& flags,
             const bool& flush);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -119,10 +119,19 @@ TabParent::RecvPDocumentRendererDestruct
 {
     NS_ENSURE_ARG_POINTER(__a);
     DocumentRendererParent *renderer = static_cast<DocumentRendererParent *>(__a);
     renderer->DrawToCanvas(w, h, data);
 
     return true;
 }
 
+void
+TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
+                          PRInt32 aButton, PRInt32 aClickCount,
+                          PRInt32 aModifiers, PRBool aIgnoreRootScrollFrame)
+{
+  SendsendMouseEvent(nsString(aType), aX, aY, aButton, aClickCount,
+                     aModifiers, aIgnoreRootScrollFrame);
+}
+
 } // namespace tabs
 } // namespace mozilla
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -56,16 +56,19 @@ public:
     virtual ~TabParent();
     void SetOwnerElement(nsIDOMElement* aElement) { mFrameElement = aElement; }
 
     virtual bool RecvmoveFocus(const bool& aForward);
 
     void LoadURL(nsIURI* aURI);
     void Move(PRUint32 x, PRUint32 y, PRUint32 width, PRUint32 height);
     void Activate();
+    void SendMouseEvent(const nsAString& aType, float aX, float aY,
+                        PRInt32 aButton, PRInt32 aClickCount,
+                        PRInt32 aModifiers, PRBool aIgnoreRootScrollFrame);
 
     virtual mozilla::ipc::PDocumentRendererParent* AllocPDocumentRenderer(
             const PRInt32& x,
             const PRInt32& y,
             const PRInt32& w,
             const PRInt32& h,
             const nsString& bgcolor,
             const PRUint32& flags,
--- a/dom/ipc/test.xul
+++ b/dom/ipc/test.xul
@@ -8,20 +8,33 @@
       var p = y.parentNode;
       p.removeChild(y);
       p.appendChild(y);
     }
     
     function loadURL(url) {
       document.getElementById('page').setAttribute('src', url);
     }
+
+    function randomClick() {
+       // First focus the remote frame, then dispatch click. This way remote frame gets focus before
+       // mouse event.
+       document.getElementById('page').QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
+                                      .frameLoader.activateRemoteFrame();
+       var frameLoader = document.getElementById('page').QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
+       var x = parseInt(Math.random() * 100);
+       var y = parseInt(Math.random() * 100);
+       frameLoader.sendCrossProcessMouseEvent("mousedown", x, y, 0, 1, 0, false);
+       frameLoader.sendCrossProcessMouseEvent("mouseup", x, y, 0, 1, 0, false);
+     }
   </script>
 
   <toolbar id="controls">
     <toolbarbutton label="Back"/>
     <toolbarbutton label="Forward"/>
     <textbox onchange="loadURL(this.value)" flex="1" id="URL"/>
     <toolbarbutton onclick="restart()" label="Recover"/>
+    <toolbarbutton onclick="randomClick()" label="random click"/>
   </toolbar>
 
   <browser type="content" src="http://www.google.com/" flex="1" id="page" remote="true"
            onfocus="this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.activateRemoteFrame();"/>
 </window>