Bug 1171712 - Implement separated InkColletor and InkCollectorEvent classes. r=smaug, r=jimm
authorMaksim Lebedev <alessarik@gmail.com>
Fri, 12 Jun 2015 08:35:00 -0400
changeset 279747 783aeb2403869787aafb2a15c57e27b5dc7bde12
parent 279746 6171ef486412108242bebe0a744e56c83ea774ee
child 279748 d16d6da34d3c5ab7a5206aa5de2d83ed7ba6152e
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, jimm
bugs1171712
milestone41.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 1171712 - Implement separated InkColletor and InkCollectorEvent classes. r=smaug, r=jimm
widget/windows/InkCollector.cpp
widget/windows/InkCollector.h
widget/windows/nsWindow.cpp
--- a/widget/windows/InkCollector.cpp
+++ b/widget/windows/InkCollector.cpp
@@ -6,79 +6,85 @@
 */
 
 #include "InkCollector.h"
 
 // Msinkaut_i.c and Msinkaut.h should both be included
 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms695519.aspx
 #include <msinkaut_i.c>
 
-StaticRefPtr<InkCollector> InkCollector::sInkCollector;
-
-InkCollector::InkCollector()
-{
-}
+StaticAutoPtr<InkCollector> InkCollector::sInkCollector;
 
 InkCollector::~InkCollector()
 {
   Shutdown();
-  MOZ_ASSERT(!mRefCount);
+  MOZ_ASSERT(!mCookie && !mEnabled && !mComInitialized
+              && !mMarshaller && !mInkCollector
+              && !mConnectionPoint && !mInkCollectorEvent);
 }
 
 void InkCollector::Initialize()
 {
   // Possibly, we can use mConnectionPoint for checking,
   // But if errors exist (perhaps COM object is unavailable),
   // Initialize() will be called more times.
   static bool sInkCollectorCreated = false;
   if (sInkCollectorCreated) {
     return;
   }
   sInkCollectorCreated = true;
 
   // COM could get uninitialized due to previous initialization.
   mComInitialized = SUCCEEDED(::CoInitialize(nullptr));
 
+  // Set up instance of InkCollectorEvent.
+  mInkCollectorEvent = new InkCollectorEvent();
+
   // Set up a free threaded marshaler.
-  if (FAILED(::CoCreateFreeThreadedMarshaler(this, getter_AddRefs(mMarshaller)))) {
+  if (FAILED(::CoCreateFreeThreadedMarshaler(mInkCollectorEvent, getter_AddRefs(mMarshaller)))) {
     return;
   }
+
   // Create the ink collector.
   if (FAILED(::CoCreateInstance(CLSID_InkCollector, NULL, CLSCTX_INPROC_SERVER,
                                 IID_IInkCollector, getter_AddRefs(mInkCollector)))) {
     return;
   }
-  NS_ADDREF(mInkCollector);
+
   // Set up connection between sink and InkCollector.
   nsRefPtr<IConnectionPointContainer> connPointContainer;
+
   // Get the connection point container.
   if (SUCCEEDED(mInkCollector->QueryInterface(IID_IConnectionPointContainer,
                                               getter_AddRefs(connPointContainer)))) {
+
     // Find the connection point for Ink Collector events.
     if (SUCCEEDED(connPointContainer->FindConnectionPoint(__uuidof(_IInkCollectorEvents),
                                                           getter_AddRefs(mConnectionPoint)))) {
-      NS_ADDREF(mConnectionPoint);
+
       // Hook up sink to connection point.
-      if (SUCCEEDED(mConnectionPoint->Advise(this, &mCookie))) {
+      if (SUCCEEDED(mConnectionPoint->Advise(mInkCollectorEvent, &mCookie))) {
         OnInitialize();
       }
     }
   }
 }
 
 void InkCollector::Shutdown()
 {
   Enable(false);
   if (mConnectionPoint) {
     // Remove the connection of the sink to the Ink Collector.
     mConnectionPoint->Unadvise(mCookie);
-    NS_RELEASE(mConnectionPoint);
+    mCookie = 0;
+    mConnectionPoint = nullptr;
   }
-  NS_IF_RELEASE(mMarshaller);
-  NS_IF_RELEASE(mInkCollector);
+  mInkCollector = nullptr;
+  mMarshaller = nullptr;
+  mInkCollectorEvent = nullptr;
 
   // Let uninitialization get handled in a place where it got inited.
   if (mComInitialized) {
     CoUninitialize();
     mComInitialized = false;
   }
 }
 
@@ -113,128 +119,120 @@ void InkCollector::OnInitialize()
 // Sets a value that specifies whether the InkCollector object collects pen input.
 // This property must be set to FALSE before setting or
 // calling specific properties and methods of the object.
 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms701721.aspx
 void InkCollector::Enable(bool aNewState)
 {
   if (aNewState != mEnabled) {
     if (mInkCollector) {
-      if (S_OK == mInkCollector->put_Enabled(aNewState ? VARIANT_TRUE : VARIANT_FALSE)) {
+      if (SUCCEEDED(mInkCollector->put_Enabled(aNewState ? VARIANT_TRUE : VARIANT_FALSE))) {
         mEnabled = aNewState;
       } else {
         NS_WARNING("InkCollector did not change status successfully");
       }
     } else {
       NS_WARNING("InkCollector should be exist");
     }
   }
 }
 
+HWND InkCollector::GetTarget()
+{
+  return mTargetWindow;
+}
+
 void InkCollector::SetTarget(HWND aTargetWindow)
 {
   NS_ASSERTION(aTargetWindow, "aTargetWindow should be exist");
   if (aTargetWindow && (aTargetWindow != mTargetWindow)) {
     Initialize();
     if (mInkCollector) {
       Enable(false);
-      if (S_OK == mInkCollector->put_hWnd((LONG_PTR)aTargetWindow)) {
+      if (SUCCEEDED(mInkCollector->put_hWnd((LONG_PTR)aTargetWindow))) {
         mTargetWindow = aTargetWindow;
       } else {
         NS_WARNING("InkCollector did not change window property successfully");
       }
       Enable(true);
     }
   }
 }
 
 void InkCollector::ClearTarget()
 {
   if (mTargetWindow && mInkCollector) {
     Enable(false);
-    if (S_OK == mInkCollector->put_hWnd(0)) {
+    if (SUCCEEDED(mInkCollector->put_hWnd(0))) {
       mTargetWindow = 0;
     } else {
       NS_WARNING("InkCollector did not clear window property successfully");
     }
   }
 }
 
 // The display and the digitizer have quite different properties.
 // The display has CursorMustTouch, the mouse pointer alway touches the display surface.
 // The digitizer lists Integrated and HardProximity.
 // When the stylus is in the proximity of the tablet its movements are also detected.
 // An external tablet will only list HardProximity.
-bool InkCollector::IsHardProximityTablet(IInkTablet* aTablet) const
+bool InkCollectorEvent::IsHardProximityTablet(IInkTablet* aTablet) const
 {
   if (aTablet) {
     TabletHardwareCapabilities caps;
     if (SUCCEEDED(aTablet->get_HardwareCapabilities(&caps))) {
       return (TabletHardwareCapabilities::THWC_HardProximity & caps);
     }
   }
   return false;
 }
 
-HRESULT __stdcall InkCollector::QueryInterface(REFIID aRiid, void **aObject)
+HRESULT __stdcall InkCollectorEvent::QueryInterface(REFIID aRiid, void **aObject)
 {
   // Validate the input
   if (!aObject) {
     return E_POINTER;
   }
   HRESULT result = E_NOINTERFACE;
   // This object supports IUnknown/IDispatch/IInkCollectorEvents
   if ((IID_IUnknown == aRiid) ||
       (IID_IDispatch == aRiid) ||
       (DIID__IInkCollectorEvents == aRiid)) {
     *aObject = this;
     // AddRef should be called when we give info about interface
     NS_ADDREF_THIS();
     result = S_OK;
-  } else if (IID_IMarshal == aRiid) {
-    // Assert that the free threaded marshaller has been initialized.
-    // It is necessary to call Initialize() before invoking this method.
-    NS_ASSERTION(mMarshaller, "Free threaded marshaller is null!");
-    // Use free threaded marshalling.
-    result = mMarshaller->QueryInterface(aRiid, aObject);
   }
   return result;
 }
 
-// To avoid a memory leak you must explicitly call the Dispose
-// method on any InkCollector object to which an event handler
-// has been attached, before the object goes out of scope.
-// https://msdn.microsoft.com/en-us/library/dd187726.aspx
-HRESULT InkCollector::Invoke(DISPID aDispIdMember, REFIID /*aRiid*/,
-                             LCID /*aId*/, WORD /*wFlags*/,
-                             DISPPARAMS* aDispParams, VARIANT* /*aVarResult*/,
-                             EXCEPINFO* /*aExcepInfo*/, UINT* /*aArgErr*/)
+HRESULT InkCollectorEvent::Invoke(DISPID aDispIdMember, REFIID /*aRiid*/,
+                                  LCID /*aId*/, WORD /*wFlags*/,
+                                  DISPPARAMS* aDispParams, VARIANT* /*aVarResult*/,
+                                  EXCEPINFO* /*aExcepInfo*/, UINT* /*aArgErr*/)
 {
   switch (aDispIdMember) {
     case DISPID_ICECursorOutOfRange: {
       if (aDispParams && aDispParams->cArgs) {
         CursorOutOfRange(static_cast<IInkCursor*>(aDispParams->rgvarg[0].pdispVal));
-        ClearTarget();
       }
       break;
     }
   };
-  // Release should be called after all usage of this method.
-  NS_RELEASE_THIS();
   return S_OK;
 }
 
-void InkCollector::CursorOutOfRange(IInkCursor* aCursor) const
+void InkCollectorEvent::CursorOutOfRange(IInkCursor* aCursor) const
 {
   IInkTablet* curTablet = nullptr;
   if (FAILED(aCursor->get_Tablet(&curTablet))) {
     return;
   }
   // All events should be suppressed except
   // from tablets with hard proximity.
   if (!IsHardProximityTablet(curTablet)) {
     return;
   }
   // Notify current target window.
-  if (mTargetWindow) {
-    ::SendMessage(mTargetWindow, MOZ_WM_PEN_LEAVES_HOVER_OF_DIGITIZER, 0, 0);
+  if (HWND targetWindow = InkCollector::sInkCollector->GetTarget()) {
+    ::SendMessage(targetWindow, MOZ_WM_PEN_LEAVES_HOVER_OF_DIGITIZER, 0, 0);
   }
 }
--- a/widget/windows/InkCollector.h
+++ b/widget/windows/InkCollector.h
@@ -4,69 +4,77 @@
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
 
 #ifndef InkCollector_h__
 #define InkCollector_h__
 
 #include <msinkaut.h>
-#include "StaticPtr.h"
+#include "mozilla/StaticPtr.h"
 
 #define MOZ_WM_PEN_LEAVES_HOVER_OF_DIGITIZER  WM_USER + 0x83
 
-class InkCollector : public _IInkCollectorEvents
+class InkCollectorEvent : public _IInkCollectorEvents
 {
 public:
-  InkCollector();
-
-  void Shutdown();
-  void SetTarget(HWND aTargetWindow);
-
-  static StaticRefPtr<InkCollector> sInkCollector;
-  friend StaticRefPtr<InkCollector>;
-
-protected:
   // IUnknown
+  HRESULT __stdcall QueryInterface(REFIID aRiid, void **aObject);
   virtual ULONG STDMETHODCALLTYPE AddRef() { return ++mRefCount; }
   virtual ULONG STDMETHODCALLTYPE Release()
   {
     MOZ_ASSERT(mRefCount);
     if (!--mRefCount) {
       delete this;
       return 0;
     }
     return mRefCount;
   }
-  HRESULT __stdcall QueryInterface(REFIID aRiid, void **aObject);
 
+protected:
   // IDispatch
   STDMETHOD(GetTypeInfoCount)(UINT* aInfo) { return E_NOTIMPL; }
   STDMETHOD(GetTypeInfo)(UINT aInfo, LCID aId, ITypeInfo** aTInfo) { return E_NOTIMPL; }
   STDMETHOD(GetIDsOfNames)(REFIID aRiid, LPOLESTR* aStrNames, UINT aNames,
                            LCID aId, DISPID* aDispId) { return E_NOTIMPL; }
   STDMETHOD(Invoke)(DISPID aDispIdMember, REFIID aRiid,
                     LCID aId, WORD wFlags,
                     DISPPARAMS* aDispParams, VARIANT* aVarResult,
                     EXCEPINFO* aExcepInfo, UINT* aArgErr);
 
-  // InkCollector
-  virtual ~InkCollector();
+  // InkCollectorEvent
+  void CursorOutOfRange(IInkCursor* aCursor) const;
+  bool IsHardProximityTablet(IInkTablet* aTablet) const;
+
+private:
+  uint32_t  mRefCount = 0;
+};
+
+class InkCollector
+{
+public:
+  ~InkCollector();
+  void Shutdown();
+
+  HWND GetTarget();
+  void SetTarget(HWND aTargetWindow);
+  void ClearTarget();
+
+  static StaticAutoPtr<InkCollector> sInkCollector;
+
+protected:
   void Initialize();
   void OnInitialize();
   void Enable(bool aNewState);
-  void ClearTarget();
-  void CursorOutOfRange(IInkCursor* aCursor) const;
-  bool IsHardProximityTablet(IInkTablet* aTablet) const;
 
 private:
   nsRefPtr<IUnknown>          mMarshaller;
   nsRefPtr<IInkCollector>     mInkCollector;
   nsRefPtr<IConnectionPoint>  mConnectionPoint;
+  nsRefPtr<InkCollectorEvent> mInkCollectorEvent;
 
   HWND                        mTargetWindow     = 0;
   DWORD                       mCookie           = 0;
-  uint32_t                    mRefCount         = 0;
   bool                        mComInitialized   = false;
   bool                        mEnabled          = false;
 };
 
-#endif // nsInkCollector_h_
+#endif // InkCollector_h__
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -4935,16 +4935,17 @@ nsWindow::ProcessMessage(UINT msg, WPARA
     break;
 
     case MOZ_WM_PEN_LEAVES_HOVER_OF_DIGITIZER:
     {
       LPARAM pos = lParamToClient(::GetMessagePos());
       DispatchMouseEvent(NS_MOUSE_EXIT_WIDGET, wParam, pos, false,
                          WidgetMouseEvent::eLeftButton,
                          nsIDOMMouseEvent::MOZ_SOURCE_PEN);
+      InkCollector::sInkCollector->ClearTarget();
     }
     break;
 
     case WM_CONTEXTMENU:
     {
       // if the context menu is brought up from the keyboard, |lParam|
       // will be -1.
       LPARAM pos;