Bug 1794292 - [ANGLE] cherry-pick init-gl-point-size. r=gfx-reviewers,bradwerth
[gecko.git] / widget / windows / InkCollector.cpp
blob4c2dfbf3871abcb2a20e0a9a367388e0606997e9
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=2 sw=2 et tw=78:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
8 #include "InkCollector.h"
10 // Msinkaut_i.c and Msinkaut.h should both be included
11 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms695519.aspx
12 #include <msinkaut_i.c>
14 StaticAutoPtr<InkCollector> InkCollector::sInkCollector;
16 InkCollector::~InkCollector() {
17 Shutdown();
18 MOZ_ASSERT(!mCookie && !mEnabled && !mComInitialized && !mMarshaller &&
19 !mInkCollector && !mConnectionPoint && !mInkCollectorEvent);
22 void InkCollector::Initialize() {
23 // Possibly, we can use mConnectionPoint for checking,
24 // But if errors exist (perhaps COM object is unavailable),
25 // Initialize() will be called more times.
26 static bool sInkCollectorCreated = false;
27 if (sInkCollectorCreated) {
28 return;
30 sInkCollectorCreated = true;
32 // COM could get uninitialized due to previous initialization.
33 mComInitialized = SUCCEEDED(::CoInitialize(nullptr));
35 // Set up instance of InkCollectorEvent.
36 mInkCollectorEvent = new InkCollectorEvent();
38 // Set up a free threaded marshaler.
39 if (FAILED(::CoCreateFreeThreadedMarshaler(mInkCollectorEvent,
40 getter_AddRefs(mMarshaller)))) {
41 return;
44 // Create the ink collector.
45 if (FAILED(::CoCreateInstance(CLSID_InkCollector, NULL, CLSCTX_INPROC_SERVER,
46 IID_IInkCollector,
47 getter_AddRefs(mInkCollector)))) {
48 return;
51 // Set up connection between sink and InkCollector.
52 RefPtr<IConnectionPointContainer> connPointContainer;
54 // Get the connection point container.
55 if (SUCCEEDED(mInkCollector->QueryInterface(
56 IID_IConnectionPointContainer, getter_AddRefs(connPointContainer)))) {
57 // Find the connection point for Ink Collector events.
58 if (SUCCEEDED(connPointContainer->FindConnectionPoint(
59 __uuidof(_IInkCollectorEvents),
60 getter_AddRefs(mConnectionPoint)))) {
61 // Hook up sink to connection point.
62 if (SUCCEEDED(mConnectionPoint->Advise(mInkCollectorEvent, &mCookie))) {
63 OnInitialize();
69 void InkCollector::Shutdown() {
70 Enable(false);
71 if (mConnectionPoint) {
72 // Remove the connection of the sink to the Ink Collector.
73 mConnectionPoint->Unadvise(mCookie);
74 mCookie = 0;
75 mConnectionPoint = nullptr;
77 mInkCollector = nullptr;
78 mMarshaller = nullptr;
79 mInkCollectorEvent = nullptr;
81 // Let uninitialization get handled in a place where it got inited.
82 if (mComInitialized) {
83 CoUninitialize();
84 mComInitialized = false;
88 void InkCollector::OnInitialize() {
89 // Suppress all events to do not allow performance decreasing.
90 // https://msdn.microsoft.com/en-us/library/ms820347.aspx
91 mInkCollector->SetEventInterest(InkCollectorEventInterest::ICEI_AllEvents,
92 VARIANT_FALSE);
94 // Sets a value that indicates whether an object or control has interest in a
95 // specified event.
96 mInkCollector->SetEventInterest(
97 InkCollectorEventInterest::ICEI_CursorOutOfRange, VARIANT_TRUE);
99 // If the MousePointer property is set to IMP_Custom and the MouseIcon
100 // property is NULL, Then the ink collector no longer handles mouse cursor
101 // settings.
102 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms700686.aspx
103 mInkCollector->put_MouseIcon(nullptr);
104 mInkCollector->put_MousePointer(InkMousePointer::IMP_Custom);
106 // This mode allows an ink collector to collect ink from any tablet attached
107 // to the Tablet PC. The Boolean value that indicates whether to use the mouse
108 // as an input device. If TRUE, the mouse is used for input.
109 // https://msdn.microsoft.com/en-us/library/ms820346.aspx
110 mInkCollector->SetAllTabletsMode(VARIANT_FALSE);
112 // Sets the value that specifies whether ink is rendered as it is drawn.
113 // VARIANT_TRUE to render ink as it is drawn on the display.
114 // VARIANT_FALSE to not have the ink appear on the display as strokes are
115 // made.
116 // https://msdn.microsoft.com/en-us/library/windows/desktop/dd314598.aspx
117 mInkCollector->put_DynamicRendering(VARIANT_FALSE);
119 // Set AutoRedraw to false to prevent repainting the ink when the window is
120 // invalidated.
121 mInkCollector->put_AutoRedraw(VARIANT_FALSE);
124 // Sets a value that specifies whether the InkCollector object collects pen
125 // input. This property must be set to FALSE before setting or calling specific
126 // properties and methods of the object.
127 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms701721.aspx
128 void InkCollector::Enable(bool aNewState) {
129 if (aNewState != mEnabled) {
130 if (mInkCollector) {
131 if (SUCCEEDED(mInkCollector->put_Enabled(aNewState ? VARIANT_TRUE
132 : VARIANT_FALSE))) {
133 mEnabled = aNewState;
134 } else {
135 NS_WARNING("InkCollector did not change status successfully");
137 } else {
138 NS_WARNING("InkCollector should be exist");
143 HWND InkCollector::GetTarget() { return mTargetWindow; }
145 void InkCollector::SetTarget(HWND aTargetWindow) {
146 NS_ASSERTION(aTargetWindow, "aTargetWindow should be exist");
147 if (aTargetWindow && (aTargetWindow != mTargetWindow)) {
148 Initialize();
149 if (mInkCollector) {
150 Enable(false);
151 if (SUCCEEDED(mInkCollector->put_hWnd((LONG_PTR)aTargetWindow))) {
152 mTargetWindow = aTargetWindow;
153 } else {
154 NS_WARNING("InkCollector did not change window property successfully");
156 Enable(true);
161 void InkCollector::ClearTarget() {
162 if (mTargetWindow && mInkCollector) {
163 Enable(false);
164 if (SUCCEEDED(mInkCollector->put_hWnd(0))) {
165 mTargetWindow = 0;
166 } else {
167 NS_WARNING("InkCollector did not clear window property successfully");
172 uint16_t InkCollector::GetPointerId() { return mPointerId; }
174 void InkCollector::SetPointerId(uint16_t aPointerId) {
175 mPointerId = aPointerId;
178 void InkCollector::ClearPointerId() { mPointerId = 0; }
180 // The display and the digitizer have quite different properties.
181 // The display has CursorMustTouch, the mouse pointer alway touches the display
182 // surface. The digitizer lists Integrated and HardProximity. When the stylus is
183 // in the proximity of the tablet its movements are also detected. An external
184 // tablet will only list HardProximity.
185 bool InkCollectorEvent::IsHardProximityTablet(IInkTablet* aTablet) const {
186 if (aTablet) {
187 TabletHardwareCapabilities caps;
188 if (SUCCEEDED(aTablet->get_HardwareCapabilities(&caps))) {
189 return (TabletHardwareCapabilities::THWC_HardProximity & caps);
192 return false;
195 HRESULT __stdcall InkCollectorEvent::QueryInterface(REFIID aRiid,
196 void** aObject) {
197 // Validate the input
198 if (!aObject) {
199 return E_POINTER;
201 HRESULT result = E_NOINTERFACE;
202 // This object supports IUnknown/IDispatch/IInkCollectorEvents
203 if ((IID_IUnknown == aRiid) || (IID_IDispatch == aRiid) ||
204 (DIID__IInkCollectorEvents == aRiid)) {
205 *aObject = this;
206 // AddRef should be called when we give info about interface
207 NS_ADDREF_THIS();
208 result = S_OK;
210 return result;
213 HRESULT InkCollectorEvent::Invoke(DISPID aDispIdMember, REFIID /*aRiid*/,
214 LCID /*aId*/, WORD /*wFlags*/,
215 DISPPARAMS* aDispParams,
216 VARIANT* /*aVarResult*/,
217 EXCEPINFO* /*aExcepInfo*/,
218 UINT* /*aArgErr*/) {
219 switch (aDispIdMember) {
220 case DISPID_ICECursorOutOfRange: {
221 if (aDispParams && aDispParams->cArgs) {
222 CursorOutOfRange(
223 static_cast<IInkCursor*>(aDispParams->rgvarg[0].pdispVal));
225 break;
228 return S_OK;
231 void InkCollectorEvent::CursorOutOfRange(IInkCursor* aCursor) const {
232 IInkTablet* curTablet = nullptr;
233 if (FAILED(aCursor->get_Tablet(&curTablet))) {
234 return;
236 // All events should be suppressed except
237 // from tablets with hard proximity.
238 if (!IsHardProximityTablet(curTablet)) {
239 return;
241 // Notify current target window.
242 if (HWND targetWindow = InkCollector::sInkCollector->GetTarget()) {
243 ::SendMessage(targetWindow, MOZ_WM_PEN_LEAVES_HOVER_OF_DIGITIZER, 0, 0);