Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=8 et :
3 : */
4 : /* This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #include "mozilla/layers/RemoteContentController.h"
9 :
10 : #include "base/message_loop.h"
11 : #include "base/task.h"
12 : #include "MainThreadUtils.h"
13 : #include "mozilla/dom/ContentParent.h"
14 : #include "mozilla/dom/TabParent.h"
15 : #include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
16 : #include "mozilla/layers/APZThreadUtils.h"
17 : #include "mozilla/layout/RenderFrameParent.h"
18 : #include "mozilla/gfx/GPUProcessManager.h"
19 : #include "mozilla/Unused.h"
20 : #include "Units.h"
21 :
22 : namespace mozilla {
23 : namespace layers {
24 :
25 : using namespace mozilla::gfx;
26 :
27 1 : RemoteContentController::RemoteContentController()
28 1 : : mCompositorThread(MessageLoop::current())
29 2 : , mCanSend(true)
30 : {
31 1 : }
32 :
33 0 : RemoteContentController::~RemoteContentController()
34 : {
35 0 : }
36 :
37 : void
38 0 : RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
39 : {
40 0 : MOZ_ASSERT(IsRepaintThread());
41 :
42 0 : if (mCanSend) {
43 0 : Unused << SendRequestContentRepaint(aFrameMetrics);
44 : }
45 0 : }
46 :
47 : void
48 0 : RemoteContentController::HandleTapOnMainThread(TapType aTapType,
49 : LayoutDevicePoint aPoint,
50 : Modifiers aModifiers,
51 : ScrollableLayerGuid aGuid,
52 : uint64_t aInputBlockId)
53 : {
54 0 : MOZ_ASSERT(NS_IsMainThread());
55 :
56 0 : dom::TabParent* tab = dom::TabParent::GetTabParentFromLayersId(aGuid.mLayersId);
57 0 : if (tab) {
58 0 : tab->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
59 : }
60 0 : }
61 :
62 : void
63 0 : RemoteContentController::HandleTap(TapType aTapType,
64 : const LayoutDevicePoint& aPoint,
65 : Modifiers aModifiers,
66 : const ScrollableLayerGuid& aGuid,
67 : uint64_t aInputBlockId)
68 : {
69 0 : APZThreadUtils::AssertOnControllerThread();
70 :
71 0 : if (XRE_GetProcessType() == GeckoProcessType_GPU) {
72 0 : MOZ_ASSERT(MessageLoop::current() == mCompositorThread);
73 :
74 : // The raw pointer to APZCTreeManagerParent is ok here because we are on the
75 : // compositor thread.
76 : APZCTreeManagerParent* apzctmp =
77 0 : CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId);
78 0 : if (apzctmp) {
79 0 : Unused << apzctmp->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
80 : }
81 :
82 0 : return;
83 : }
84 :
85 0 : MOZ_ASSERT(XRE_IsParentProcess());
86 :
87 0 : if (NS_IsMainThread()) {
88 0 : HandleTapOnMainThread(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
89 : } else {
90 : // We don't want to get the TabParent or call TabParent::SendHandleTap() from a non-main thread (this might happen
91 : // on Android, where this is called from the Java UI thread)
92 0 : NS_DispatchToMainThread(NewRunnableMethod<TapType,
93 : LayoutDevicePoint,
94 : Modifiers,
95 : ScrollableLayerGuid,
96 0 : uint64_t>(
97 : "layers::RemoteContentController::HandleTapOnMainThread",
98 : this,
99 : &RemoteContentController::HandleTapOnMainThread,
100 : aTapType,
101 : aPoint,
102 : aModifiers,
103 : aGuid,
104 0 : aInputBlockId));
105 : }
106 : }
107 :
108 : void
109 0 : RemoteContentController::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
110 : const ScrollableLayerGuid& aGuid,
111 : LayoutDeviceCoord aSpanChange,
112 : Modifiers aModifiers)
113 : {
114 0 : APZThreadUtils::AssertOnControllerThread();
115 :
116 : // For now we only ever want to handle this NotifyPinchGesture message in
117 : // the parent process, even if the APZ is sending it to a content process.
118 :
119 : // If we're in the GPU process, try to find a handle to the parent process
120 : // and send it there.
121 0 : if (XRE_IsGPUProcess()) {
122 0 : MOZ_ASSERT(MessageLoop::current() == mCompositorThread);
123 :
124 : // The raw pointer to APZCTreeManagerParent is ok here because we are on the
125 : // compositor thread.
126 : APZCTreeManagerParent* apzctmp =
127 0 : CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId);
128 0 : if (apzctmp) {
129 0 : Unused << apzctmp->SendNotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
130 0 : return;
131 : }
132 : }
133 :
134 : // If we're in the parent process, handle it directly. We don't have a handle
135 : // to the widget though, so we fish out the ChromeProcessController and
136 : // delegate to that instead.
137 0 : if (XRE_IsParentProcess()) {
138 0 : MOZ_ASSERT(NS_IsMainThread());
139 : RefPtr<GeckoContentController> rootController =
140 0 : CompositorBridgeParent::GetGeckoContentControllerForRoot(aGuid.mLayersId);
141 0 : if (rootController) {
142 0 : rootController->NotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
143 : }
144 : }
145 : }
146 :
147 : void
148 0 : RemoteContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
149 : {
150 0 : (MessageLoop::current() ? MessageLoop::current() : mCompositorThread)->
151 0 : PostDelayedTask(Move(aTask), aDelayMs);
152 0 : }
153 :
154 : bool
155 0 : RemoteContentController::IsRepaintThread()
156 : {
157 0 : return MessageLoop::current() == mCompositorThread;
158 : }
159 :
160 : void
161 0 : RemoteContentController::DispatchToRepaintThread(already_AddRefed<Runnable> aTask)
162 : {
163 0 : mCompositorThread->PostTask(Move(aTask));
164 0 : }
165 :
166 : void
167 0 : RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
168 : APZStateChange aChange,
169 : int aArg)
170 : {
171 0 : if (MessageLoop::current() != mCompositorThread) {
172 : // We have to send messages from the compositor thread
173 0 : mCompositorThread->PostTask(
174 0 : NewRunnableMethod<ScrollableLayerGuid, APZStateChange, int>(
175 : "layers::RemoteContentController::NotifyAPZStateChange",
176 : this,
177 : &RemoteContentController::NotifyAPZStateChange,
178 : aGuid,
179 : aChange,
180 0 : aArg));
181 0 : return;
182 : }
183 :
184 0 : if (mCanSend) {
185 0 : Unused << SendNotifyAPZStateChange(aGuid, aChange, aArg);
186 : }
187 : }
188 :
189 : void
190 0 : RemoteContentController::UpdateOverscrollVelocity(float aX, float aY, bool aIsRootContent)
191 : {
192 0 : if (MessageLoop::current() != mCompositorThread) {
193 0 : mCompositorThread->PostTask(NewRunnableMethod<float, float, bool>(
194 : "layers::RemoteContentController::UpdateOverscrollVelocity",
195 : this,
196 : &RemoteContentController::UpdateOverscrollVelocity,
197 : aX,
198 : aY,
199 0 : aIsRootContent));
200 0 : return;
201 : }
202 0 : if (mCanSend) {
203 0 : Unused << SendUpdateOverscrollVelocity(aX, aY, aIsRootContent);
204 : }
205 : }
206 :
207 : void
208 0 : RemoteContentController::UpdateOverscrollOffset(float aX, float aY, bool aIsRootContent)
209 : {
210 0 : if (MessageLoop::current() != mCompositorThread) {
211 0 : mCompositorThread->PostTask(NewRunnableMethod<float, float, bool>(
212 : "layers::RemoteContentController::UpdateOverscrollOffset",
213 : this,
214 : &RemoteContentController::UpdateOverscrollOffset,
215 : aX,
216 : aY,
217 0 : aIsRootContent));
218 0 : return;
219 : }
220 0 : if (mCanSend) {
221 0 : Unused << SendUpdateOverscrollOffset(aX, aY, aIsRootContent);
222 : }
223 : }
224 :
225 : void
226 0 : RemoteContentController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
227 : const nsString& aEvent)
228 : {
229 0 : if (MessageLoop::current() != mCompositorThread) {
230 : // We have to send messages from the compositor thread
231 0 : mCompositorThread->PostTask(
232 0 : NewRunnableMethod<FrameMetrics::ViewID, nsString>(
233 : "layers::RemoteContentController::NotifyMozMouseScrollEvent",
234 : this,
235 : &RemoteContentController::NotifyMozMouseScrollEvent,
236 : aScrollId,
237 0 : aEvent));
238 0 : return;
239 : }
240 :
241 0 : if (mCanSend) {
242 0 : Unused << SendNotifyMozMouseScrollEvent(aScrollId, aEvent);
243 : }
244 : }
245 :
246 : void
247 0 : RemoteContentController::NotifyFlushComplete()
248 : {
249 0 : MOZ_ASSERT(IsRepaintThread());
250 :
251 0 : if (mCanSend) {
252 0 : Unused << SendNotifyFlushComplete();
253 : }
254 0 : }
255 :
256 : void
257 0 : RemoteContentController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
258 : {
259 0 : if (MessageLoop::current() != mCompositorThread) {
260 : // We have to send messages from the compositor thread
261 0 : mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(
262 : "layers::RemoteContentController::NotifyAsyncScrollbarDragRejected",
263 : this,
264 : &RemoteContentController::NotifyAsyncScrollbarDragRejected,
265 0 : aScrollId));
266 0 : return;
267 : }
268 :
269 0 : if (mCanSend) {
270 0 : Unused << SendNotifyAsyncScrollbarDragRejected(aScrollId);
271 : }
272 : }
273 :
274 : void
275 0 : RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
276 : {
277 : // This controller could possibly be kept alive longer after this
278 : // by a RefPtr, but it is no longer valid to send messages.
279 0 : mCanSend = false;
280 0 : }
281 :
282 : void
283 0 : RemoteContentController::Destroy()
284 : {
285 0 : if (mCanSend) {
286 0 : mCanSend = false;
287 0 : Unused << SendDestroy();
288 : }
289 0 : }
290 :
291 : } // namespace layers
292 : } // namespace mozilla
|