Bug 1243268 - Support ImmSetCandidateWindow(CFS_EXCLUDE) on plugin process. r=masayuki
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Tue, 02 Feb 2016 17:05:56 +0900
changeset 320948 661ff05ff47ac082265325511cc81264cc616a15
parent 320947 950702b82f19c5327efab387bdbdbac80700c80d
child 320949 b436fe906468bdc56d8f3969fc91dcb0939cabb1
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1243268
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1243268 - Support ImmSetCandidateWindow(CFS_EXCLUDE) on plugin process. r=masayuki
dom/ipc/PBrowser.ipdl
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/plugins/ipc/PPluginInstance.ipdl
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
widget/IMEData.h
widget/PuppetWidget.cpp
widget/PuppetWidget.h
widget/nsBaseWidget.h
widget/nsGUIEventIPC.h
widget/nsIWidget.h
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -65,16 +65,17 @@ using mozilla::WritingMode from "mozilla
 using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
 using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
 using nsIWidget::TouchPointerState from "nsIWidget.h";
 using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
 using class mozilla::dom::ipc::StructuredCloneData from "ipc/IPCMessageUtils.h";
 using mozilla::EventMessage from "mozilla/EventForwards.h";
 using nsEventStatus from "mozilla/EventForwards.h";
 using nsSizeMode from "nsIWidgetListener.h";
+using mozilla::widget::CandidateWindowPosition from "ipc/nsGUIEventIPC.h";
 
 namespace mozilla {
 namespace dom {
 
 struct NativeKeyBinding
 {
   CommandInt[] singleLineCommands;
   CommandInt[] multiLineCommands;
@@ -279,17 +280,17 @@ parent:
      *
      * aFocused  Whether or not a plugin is focused
      */
     prio(urgent) async SetPluginFocused(bool aFocused);
 
     /**
      * Set IME candidate window by windowless plugin if plugin has focus.
      */
-    async SetCandidateWindowForPlugin(int32_t aX, int32_t aY);
+    async SetCandidateWindowForPlugin(CandidateWindowPosition aPosition);
 
     /**
      *  When plugin event isn't consumed, call this
      */
     async DefaultProcOfPluginEvent(WidgetPluginEvent aEvent);
 
     /**
      * Request that the parent process move focus to the browser's frame. If
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2387,25 +2387,25 @@ TabParent::RecvSetPluginFocused(const bo
   if (!widget) {
     return true;
   }
   widget->SetPluginFocused((bool&)aFocused);
   return true;
 }
 
  bool
-TabParent::RecvSetCandidateWindowForPlugin(const int32_t& aX,
-                                           const int32_t& aY)
+TabParent::RecvSetCandidateWindowForPlugin(
+             const CandidateWindowPosition& aPosition)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return true;
   }
 
-  widget->SetCandidateWindowForPlugin(aX, aY);
+  widget->SetCandidateWindowForPlugin(aPosition);
   return true;
 }
 
 bool
 TabParent::RecvDefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -233,18 +233,18 @@ public:
   virtual bool
   RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent,
                      const int32_t& aPanelX,
                      const int32_t& aPanelY,
                      nsString* aCommitted) override;
 
   virtual bool RecvSetPluginFocused(const bool& aFocused) override;
 
-  virtual bool RecvSetCandidateWindowForPlugin(const int32_t& aX,
-                                               const int32_t& aY) override;
+  virtual bool RecvSetCandidateWindowForPlugin(
+                 const widget::CandidateWindowPosition& aPosition) override;
 
   virtual bool
   RecvDefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent) override;
 
   virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
                                    int32_t* aIMEOpen) override;
 
   virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -936,31 +936,32 @@ nsPluginInstanceOwner::GetCompositionStr
                         aType).get());
       break;
   }
 
   return false;
 }
 
 bool
-nsPluginInstanceOwner::SetCandidateWindow(int32_t aX, int32_t aY)
+nsPluginInstanceOwner::SetCandidateWindow(
+    const widget::CandidateWindowPosition& aPosition)
 {
   if (NS_WARN_IF(!mPluginFrame)) {
     return false;
   }
 
   nsCOMPtr<nsIWidget> widget = GetContainingWidgetIfOffset();
   if (!widget) {
     widget = GetRootWidgetForPluginFrame(mPluginFrame);
     if (NS_WARN_IF(!widget)) {
       return false;
     }
   }
 
-  widget->SetCandidateWindowForPlugin(aX, aY);
+  widget->SetCandidateWindowForPlugin(aPosition);
   return true;
 }
 
 bool
 nsPluginInstanceOwner::RequestCommitOrCancel(bool aCommitted)
 {
   nsCOMPtr<nsIWidget> widget = GetContainingWidgetIfOffset();
   if (!widget) {
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -264,17 +264,18 @@ public:
 #endif
 
   void NotifyHostAsyncInitFailed();
   void NotifyHostCreateWidget();
   void NotifyDestroyPending();
 
   bool GetCompositionString(uint32_t aIndex, nsTArray<uint8_t>* aString,
                             int32_t* aLength);
-  bool SetCandidateWindow(int32_t aX, int32_t aY);
+  bool SetCandidateWindow(
+           const mozilla::widget::CandidateWindowPosition& aPosition);
   bool RequestCommitOrCancel(bool aCommitted);
 
 private:
   virtual ~nsPluginInstanceOwner();
 
   // return FALSE if LayerSurface dirty (newly created and don't have valid plugin content yet)
   bool IsUpToDate()
   {
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -26,16 +26,17 @@ using mozilla::gfx::IntSize from "mozill
 using mozilla::gfx::IntRect from "mozilla/gfx/2D.h";
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
 using mozilla::plugins::WindowsSharedMemoryHandle from "mozilla/plugins/PluginMessageUtils.h";
 using mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
 using nsIntRect from "nsRect.h";
 using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
 using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
+using struct mozilla::widget::CandidateWindowPosition from "ipc/nsGUIEventIPC.h";
 
 namespace mozilla {
 namespace plugins {
 
 struct IOSurfaceDescriptor {
   uint32_t surfaceId;
   double contentsScaleFactor;
 };
@@ -259,19 +260,18 @@ parent:
   // Sends a native window to be adopted by the native window that would be
   // returned by NPN_GetValue_NPNVnetscapeWindow. Only used on Windows.
   async SetNetscapeWindowAsParent(NativeWindowHandle childWindow);
 
   sync GetCompositionString(uint32_t aType)
                             returns (uint8_t[] aDist, int32_t aLength);
   // Set candidate window position.
   //
-  // @param aX  x position of candidate window
-  // @param aY  y position of candidate window
-  async SetCandidateWindow(int32_t aX, int32_t aY);
+  // @param aPosition  position information of candidate window
+  async SetCandidateWindow(CandidateWindowPosition aPosition);
   async RequestCommitOrCancel(bool aCommitted);
 
 both:
   async PPluginScriptableObject();
 
 child:
   /* NPP_NewStream */
   async PBrowserStream(nsCString url,
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -2060,24 +2060,32 @@ PluginInstanceChild::ImmGetCompositionSt
 BOOL
 PluginInstanceChild::ImmSetCandidateWindowProc(HIMC aIMC, LPCANDIDATEFORM aForm)
 {
     if (aIMC != sHookIMC) {
         return sImm32ImmSetCandidateWindowStub(aIMC, aForm);
     }
 
     if (!sCurrentPluginInstance ||
-        aForm->dwIndex != 0 ||
-        !(aForm->dwStyle & CFS_CANDIDATEPOS)) {
-        // Flash only uses CFS_CANDIDATEPOS with index == 0.
+        aForm->dwIndex != 0) {
         return FALSE;
     }
 
-    sCurrentPluginInstance->SendSetCandidateWindow(
-        aForm->ptCurrentPos.x, aForm->ptCurrentPos.y);
+    CandidateWindowPosition position;
+    position.mPoint.x = aForm->ptCurrentPos.x;
+    position.mPoint.y = aForm->ptCurrentPos.y;
+    position.mExcludeRect = !!(aForm->dwStyle & CFS_EXCLUDE);
+    if (position.mExcludeRect) {
+      position.mRect.x = aForm->rcArea.left;
+      position.mRect.y = aForm->rcArea.top;
+      position.mRect.width = aForm->rcArea.right - aForm->rcArea.left;
+      position.mRect.height = aForm->rcArea.bottom - aForm->rcArea.top;
+    }
+
+    sCurrentPluginInstance->SendSetCandidateWindow(position);
     return TRUE;
 }
 
 // static
 BOOL
 PluginInstanceChild::ImmNotifyIME(HIMC aIMC, DWORD aAction, DWORD aIndex,
                                   DWORD aValue)
 {
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -2391,23 +2391,23 @@ PluginInstanceParent::RecvGetComposition
     if (!owner->GetCompositionString(aIndex, aDist, aLength)) {
         *aLength = IMM_ERROR_NODATA;
     }
 #endif
     return true;
 }
 
 bool
-PluginInstanceParent::RecvSetCandidateWindow(const int32_t& aX,
-                                             const int32_t& aY)
+PluginInstanceParent::RecvSetCandidateWindow(
+    const mozilla::widget::CandidateWindowPosition& aPosition)
 {
 #if defined(OS_WIN)
     nsPluginInstanceOwner* owner = GetOwner();
     if (owner) {
-        owner->SetCandidateWindow(aX, aY);
+        owner->SetCandidateWindow(aPosition);
     }
 #endif
     return true;
 }
 
 bool
 PluginInstanceParent::RecvRequestCommitOrCancel(const bool& aCommitted)
 {
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -354,17 +354,18 @@ public:
                                       PluginAsyncSurrogate** aSurrogate = nullptr);
 
     // for IME hook
     virtual bool
     RecvGetCompositionString(const uint32_t& aIndex,
                              nsTArray<uint8_t>* aBuffer,
                              int32_t* aLength) override;
     virtual bool
-    RecvSetCandidateWindow(const int32_t& aX, const int32_t& aY) override;
+    RecvSetCandidateWindow(
+        const mozilla::widget::CandidateWindowPosition& aPosition) override;
     virtual bool
     RecvRequestCommitOrCancel(const bool& aCommitted) override;
 
 private:
     // Create an appropriate platform surface for a background of size
     // |aSize|.  Return true if successful.
     bool CreateBackground(const nsIntSize& aSize);
     void DestroyBackground();
--- a/widget/IMEData.h
+++ b/widget/IMEData.h
@@ -854,12 +854,24 @@ struct IMENotification final
 
   void SetData(const TextChangeDataBase& aTextChangeData)
   {
     MOZ_RELEASE_ASSERT(mMessage == NOTIFY_IME_OF_TEXT_CHANGE);
     mTextChangeData = aTextChangeData;
   }
 };
 
+struct CandidateWindowPosition
+{
+  // Upper left corner of the candidate window if mExcludeRect is false.
+  // Otherwise, the position currently interested.  E.g., caret position.
+  LayoutDeviceIntPoint mPoint;
+  // Rect which shouldn't be overlapped with the candidate window.
+  // This is valid only when mExcludeRect is true.
+  LayoutDeviceIntRect mRect;
+  // See explanation of mPoint and mRect.
+  bool mExcludeRect;
+};
+
 } // namespace widget
 } // namespace mozilla
 
 #endif // #ifndef mozilla_widget_IMEData_h_
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -1409,23 +1409,24 @@ PuppetWidget::GetCurrentWidgetListener()
   if (mAttachedWidgetListener->GetView()->IsPrimaryFramePaintSuppressed()) {
     return mPreviouslyAttachedWidgetListener;
   }
 
   return mAttachedWidgetListener;
 }
 
 void
-PuppetWidget::SetCandidateWindowForPlugin(int32_t aX, int32_t aY)
+PuppetWidget::SetCandidateWindowForPlugin(
+                const CandidateWindowPosition& aPosition)
 {
   if (!mTabChild) {
     return;
   }
 
-  mTabChild->SendSetCandidateWindowForPlugin(aX, aY);
+  mTabChild->SendSetCandidateWindowForPlugin(aPosition);
 }
 
 void
 PuppetWidget::ZoomToRect(const uint32_t& aPresShellId,
                          const FrameMetrics::ViewID& aViewId,
                          const CSSRect& aRect,
                          const uint32_t& aFlags)
 {
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -248,17 +248,18 @@ public:
   virtual nsresult SynthesizeNativeTouchTap(ScreenIntPoint aPointerScreenPoint,
                                             bool aLongTap,
                                             nsIObserver* aObserver) override;
   virtual nsresult ClearNativeTouchSequence(nsIObserver* aObserver) override;
   virtual uint32_t GetMaxTouchPoints() const override;
 
   virtual void StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
 
-  virtual void SetCandidateWindowForPlugin(int32_t aX, int32_t aY) override;
+  virtual void SetCandidateWindowForPlugin(
+                 const CandidateWindowPosition& aPosition) override;
 
   virtual void ZoomToRect(const uint32_t& aPresShellId,
                           const FrameMetrics::ViewID& aViewId,
                           const CSSRect& aRect,
                           const uint32_t& aFlags) override;
 protected:
   virtual nsresult NotifyIMEInternal(
                      const IMENotification& aIMENotification) override;
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -218,18 +218,19 @@ public:
   virtual nsresult        ForceUpdateNativeMenuAt(const nsAString& indexString) override { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              NotifyIME(const IMENotification& aIMENotification) override final;
   NS_IMETHOD              StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent,
                                          int32_t aPanelX, int32_t aPanelY,
                                          nsString& aCommitted) override
                           { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              SetPluginFocused(bool& aFocused) override
                           { return NS_ERROR_NOT_IMPLEMENTED; }
-  virtual void            SetCandidateWindowForPlugin(int32_t aX,
-                                                      int32_t aY) override
+  virtual void            SetCandidateWindowForPlugin(
+                            const mozilla::widget::CandidateWindowPosition&
+                              aPosition) override
                           { }
   virtual void            DefaultProcOfPluginEvent(
                             const mozilla::WidgetPluginEvent& aEvent) override
                           { }
   NS_IMETHOD              AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) override { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD_(bool)       ExecuteNativeKeyBinding(
                             NativeKeyBindingsType aType,
                             const mozilla::WidgetKeyboardEvent& aEvent,
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -945,12 +945,32 @@ struct ParamTraits<mozilla::ContentCache
            ReadParam(aMsg, aIter, &aResult->mCaret.mOffset) &&
            ReadParam(aMsg, aIter, &aResult->mCaret.mRect) &&
            ReadParam(aMsg, aIter, &aResult->mTextRectArray.mStart) &&
            ReadParam(aMsg, aIter, &aResult->mTextRectArray.mRects) &&
            ReadParam(aMsg, aIter, &aResult->mEditorRect);
   }
 };
 
+template<>
+struct ParamTraits<mozilla::widget::CandidateWindowPosition>
+{
+  typedef mozilla::widget::CandidateWindowPosition paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mPoint);
+    WriteParam(aMsg, aParam.mRect);
+    WriteParam(aMsg, aParam.mExcludeRect);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->mPoint) &&
+           ReadParam(aMsg, aIter, &aResult->mRect) &&
+           ReadParam(aMsg, aIter, &aResult->mExcludeRect);
+  }
+};
+
 } // namespace IPC
 
 #endif // nsGUIEventIPC_h__
 
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1830,17 +1830,18 @@ public:
     bool PluginHasFocus() 
     {
       return GetInputContext().mIMEState.mEnabled == IMEState::PLUGIN;
     }
 
     /**
      * Set IME candidate window position by windowless plugin.
      */
-    virtual void SetCandidateWindowForPlugin(int32_t aX, int32_t aY) = 0;
+    virtual void SetCandidateWindowForPlugin(
+      const mozilla::widget::CandidateWindowPosition& aPosition) = 0;
 
     /**
      * Handle default action when PluginEvent isn't handled
      */
     virtual void DefaultProcOfPluginEvent(
                    const mozilla::WidgetPluginEvent& aEvent) = 0;
 
     /*
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -7838,23 +7838,31 @@ nsWindow::ComputeShouldAccelerate()
       (IsPopup() && gfxWindowsPlatform::GetPlatform()->IsWARP()))
   {
     return false;
   }
   return nsBaseWidget::ComputeShouldAccelerate();
 }
 
 void
-nsWindow::SetCandidateWindowForPlugin(int32_t aX, int32_t aY)
+nsWindow::SetCandidateWindowForPlugin(const CandidateWindowPosition& aPosition)
 {
   CANDIDATEFORM form;
   form.dwIndex = 0;
-  form.dwStyle = CFS_CANDIDATEPOS;
-  form.ptCurrentPos.x = aX;
-  form.ptCurrentPos.y = aY;
+  if (aPosition.mExcludeRect) {
+    form.dwStyle = CFS_EXCLUDE;
+    form.rcArea.left = aPosition.mRect.x;
+    form.rcArea.top = aPosition.mRect.y;
+    form.rcArea.right = aPosition.mRect.x + aPosition.mRect.width;
+    form.rcArea.bottom = aPosition.mRect.y + aPosition.mRect.height;
+  } else {
+    form.dwStyle = CFS_CANDIDATEPOS;
+  }
+  form.ptCurrentPos.x = aPosition.mPoint.x;
+  form.ptCurrentPos.y = aPosition.mPoint.y;
 
   IMEHandler::SetCandidateWindow(this, &form);
 }
 
 void
 nsWindow::DefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent)
 {
   const NPEvent* pPluginEvent =
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -300,18 +300,19 @@ public:
 
   bool IsPopup();
   virtual bool ShouldUseOffMainThreadCompositing() override;
 
   bool CaptureWidgetOnScreen(RefPtr<mozilla::gfx::DrawTarget> aDT) override;
 
   const IMEContext& DefaultIMC() const { return mDefaultIMC; }
 
-  virtual void SetCandidateWindowForPlugin(int32_t aX,
-                                           int32_t aY) override;
+  virtual void SetCandidateWindowForPlugin(
+                 const mozilla::widget::CandidateWindowPosition&
+                   aPosition) override;
   virtual void DefaultProcOfPluginEvent(
                  const mozilla::WidgetPluginEvent& aEvent) override;
 
 protected:
   virtual ~nsWindow();
 
   virtual void WindowUsesOMTC() override;
   virtual void RegisterTouchWindow() override;