1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Steve Clark (buster@netscape.com)
24 : * Ilya Konstantinov (mozilla-code@future.shiny.co.il)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "base/basictypes.h"
41 : #include "IPC/IPCMessageUtils.h"
42 : #include "nsCOMPtr.h"
43 : #include "nsDOMUIEvent.h"
44 : #include "nsIPresShell.h"
45 : #include "nsIInterfaceRequestorUtils.h"
46 : #include "nsIDOMWindow.h"
47 : #include "nsIDOMNode.h"
48 : #include "nsIContent.h"
49 : #include "nsContentUtils.h"
50 : #include "nsEventStateManager.h"
51 : #include "nsIFrame.h"
52 : #include "nsLayoutUtils.h"
53 : #include "nsIScrollableFrame.h"
54 : #include "DictionaryHelpers.h"
55 :
56 2 : nsDOMUIEvent::nsDOMUIEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent)
57 : : nsDOMEvent(aPresContext, aEvent ?
58 : static_cast<nsEvent *>(aEvent) :
59 0 : static_cast<nsEvent *>(new nsUIEvent(false, 0, 0)))
60 2 : , mClientPoint(0, 0), mLayerPoint(0, 0), mPagePoint(0, 0)
61 : {
62 2 : if (aEvent) {
63 2 : mEventIsInternal = false;
64 : }
65 : else {
66 0 : mEventIsInternal = true;
67 0 : mEvent->time = PR_Now();
68 : }
69 :
70 : // Fill mDetail and mView according to the mEvent (widget-generated
71 : // event) we've got
72 2 : switch(mEvent->eventStructType)
73 : {
74 : case NS_UI_EVENT:
75 : {
76 0 : nsUIEvent *event = static_cast<nsUIEvent*>(mEvent);
77 0 : mDetail = event->detail;
78 0 : break;
79 : }
80 :
81 : case NS_SCROLLPORT_EVENT:
82 : {
83 0 : nsScrollPortEvent* scrollEvent = static_cast<nsScrollPortEvent*>(mEvent);
84 0 : mDetail = (PRInt32)scrollEvent->orient;
85 0 : break;
86 : }
87 :
88 : default:
89 2 : mDetail = 0;
90 2 : break;
91 : }
92 :
93 2 : mView = nsnull;
94 2 : if (mPresContext)
95 : {
96 0 : nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
97 0 : if (container)
98 : {
99 0 : nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
100 0 : if (window)
101 0 : mView = do_QueryInterface(window);
102 : }
103 : }
104 2 : }
105 :
106 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMUIEvent)
107 :
108 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMUIEvent, nsDOMEvent)
109 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mView)
110 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
111 :
112 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMUIEvent, nsDOMEvent)
113 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mView)
114 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
115 :
116 12 : NS_IMPL_ADDREF_INHERITED(nsDOMUIEvent, nsDOMEvent)
117 12 : NS_IMPL_RELEASE_INHERITED(nsDOMUIEvent, nsDOMEvent)
118 :
119 : DOMCI_DATA(UIEvent, nsDOMUIEvent)
120 :
121 30 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMUIEvent)
122 24 : NS_INTERFACE_MAP_ENTRY(nsIDOMUIEvent)
123 24 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(UIEvent)
124 24 : NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
125 :
126 : nsIntPoint
127 0 : nsDOMUIEvent::GetScreenPoint()
128 : {
129 0 : if (!mEvent ||
130 : (mEvent->eventStructType != NS_MOUSE_EVENT &&
131 : mEvent->eventStructType != NS_POPUP_EVENT &&
132 : mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
133 : mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
134 : mEvent->eventStructType != NS_DRAG_EVENT &&
135 : mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
136 0 : return nsIntPoint(0, 0);
137 : }
138 :
139 0 : if (!((nsGUIEvent*)mEvent)->widget ) {
140 0 : return mEvent->refPoint;
141 : }
142 :
143 : nsIntPoint offset = mEvent->refPoint +
144 0 : ((nsGUIEvent*)mEvent)->widget->WidgetToScreenOffset();
145 0 : nscoord factor = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
146 : return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
147 0 : nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
148 : }
149 :
150 : nsIntPoint
151 0 : nsDOMUIEvent::GetClientPoint()
152 : {
153 0 : if (!mEvent ||
154 : (mEvent->eventStructType != NS_MOUSE_EVENT &&
155 : mEvent->eventStructType != NS_POPUP_EVENT &&
156 : mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
157 : mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
158 : mEvent->eventStructType != NS_DRAG_EVENT &&
159 : mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
160 0 : !mPresContext ||
161 0 : !((nsGUIEvent*)mEvent)->widget) {
162 0 : return mClientPoint;
163 : }
164 :
165 0 : nsPoint pt(0, 0);
166 0 : nsIPresShell* shell = mPresContext->GetPresShell();
167 0 : if (!shell) {
168 0 : return nsIntPoint(0, 0);
169 : }
170 0 : nsIFrame* rootFrame = shell->GetRootFrame();
171 0 : if (rootFrame)
172 0 : pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent, rootFrame);
173 :
174 : return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
175 0 : nsPresContext::AppUnitsToIntCSSPixels(pt.y));
176 : }
177 :
178 : NS_IMETHODIMP
179 0 : nsDOMUIEvent::GetView(nsIDOMWindow** aView)
180 : {
181 0 : *aView = mView;
182 0 : NS_IF_ADDREF(*aView);
183 0 : return NS_OK;
184 : }
185 :
186 : NS_IMETHODIMP
187 0 : nsDOMUIEvent::GetDetail(PRInt32* aDetail)
188 : {
189 0 : *aDetail = mDetail;
190 0 : return NS_OK;
191 : }
192 :
193 : NS_IMETHODIMP
194 0 : nsDOMUIEvent::InitUIEvent(const nsAString& typeArg,
195 : bool canBubbleArg,
196 : bool cancelableArg,
197 : nsIDOMWindow* viewArg,
198 : PRInt32 detailArg)
199 : {
200 0 : nsresult rv = nsDOMEvent::InitEvent(typeArg, canBubbleArg, cancelableArg);
201 0 : NS_ENSURE_SUCCESS(rv, rv);
202 :
203 0 : mDetail = detailArg;
204 0 : mView = viewArg;
205 :
206 0 : return NS_OK;
207 : }
208 :
209 : nsresult
210 0 : nsDOMUIEvent::InitFromCtor(const nsAString& aType,
211 : JSContext* aCx, jsval* aVal)
212 : {
213 0 : mozilla::dom::UIEventInit d;
214 0 : nsresult rv = d.Init(aCx, aVal);
215 0 : NS_ENSURE_SUCCESS(rv, rv);
216 0 : return InitUIEvent(aType, d.bubbles, d.cancelable, d.view, d.detail);
217 : }
218 :
219 : // ---- nsDOMNSUIEvent implementation -------------------
220 : nsIntPoint
221 0 : nsDOMUIEvent::GetPagePoint()
222 : {
223 0 : if (mPrivateDataDuplicated) {
224 0 : return mPagePoint;
225 : }
226 :
227 0 : nsIntPoint pagePoint = GetClientPoint();
228 :
229 : // If there is some scrolling, add scroll info to client point.
230 0 : if (mPresContext && mPresContext->GetPresShell()) {
231 0 : nsIPresShell* shell = mPresContext->GetPresShell();
232 0 : nsIScrollableFrame* scrollframe = shell->GetRootScrollFrameAsScrollable();
233 0 : if (scrollframe) {
234 0 : nsPoint pt = scrollframe->GetScrollPosition();
235 : pagePoint += nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
236 0 : nsPresContext::AppUnitsToIntCSSPixels(pt.y));
237 : }
238 : }
239 :
240 0 : return pagePoint;
241 : }
242 :
243 : NS_IMETHODIMP
244 0 : nsDOMUIEvent::GetPageX(PRInt32* aPageX)
245 : {
246 0 : NS_ENSURE_ARG_POINTER(aPageX);
247 : #ifdef MOZ_TOUCH
248 : if (mPrivateDataDuplicated) {
249 : *aPageX = mPagePoint.x;
250 : } else {
251 : *aPageX = nsDOMEvent::GetPageCoords(mPresContext,
252 : mEvent,
253 : mEvent->refPoint,
254 : mClientPoint).x;
255 : }
256 : #else
257 0 : *aPageX = GetPagePoint().x;
258 : #endif
259 0 : return NS_OK;
260 : }
261 :
262 : NS_IMETHODIMP
263 0 : nsDOMUIEvent::GetPageY(PRInt32* aPageY)
264 : {
265 0 : NS_ENSURE_ARG_POINTER(aPageY);
266 : #ifdef MOZ_TOUCH
267 : if (mPrivateDataDuplicated) {
268 : *aPageY = mPagePoint.y;
269 : } else {
270 : *aPageY = nsDOMEvent::GetPageCoords(mPresContext,
271 : mEvent,
272 : mEvent->refPoint,
273 : mClientPoint).y;
274 : }
275 : #else
276 0 : *aPageY = GetPagePoint().y;
277 : #endif
278 0 : return NS_OK;
279 : }
280 :
281 : NS_IMETHODIMP
282 0 : nsDOMUIEvent::GetWhich(PRUint32* aWhich)
283 : {
284 0 : return Which(aWhich);
285 : }
286 :
287 : NS_IMETHODIMP
288 0 : nsDOMUIEvent::GetRangeParent(nsIDOMNode** aRangeParent)
289 : {
290 0 : NS_ENSURE_ARG_POINTER(aRangeParent);
291 0 : nsIFrame* targetFrame = nsnull;
292 :
293 0 : if (mPresContext) {
294 0 : targetFrame = mPresContext->EventStateManager()->GetEventTarget();
295 : }
296 :
297 0 : *aRangeParent = nsnull;
298 :
299 0 : if (targetFrame) {
300 : nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent,
301 0 : targetFrame);
302 0 : nsCOMPtr<nsIContent> parent = targetFrame->GetContentOffsetsFromPoint(pt).content;
303 0 : if (parent) {
304 0 : if (parent->IsInNativeAnonymousSubtree() &&
305 0 : !nsContentUtils::CanAccessNativeAnon()) {
306 0 : return NS_OK;
307 : }
308 0 : return CallQueryInterface(parent, aRangeParent);
309 : }
310 : }
311 :
312 0 : return NS_OK;
313 : }
314 :
315 : NS_IMETHODIMP
316 0 : nsDOMUIEvent::GetRangeOffset(PRInt32* aRangeOffset)
317 : {
318 0 : NS_ENSURE_ARG_POINTER(aRangeOffset);
319 0 : nsIFrame* targetFrame = nsnull;
320 :
321 0 : if (mPresContext) {
322 0 : targetFrame = mPresContext->EventStateManager()->GetEventTarget();
323 : }
324 :
325 0 : if (targetFrame) {
326 : nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent,
327 0 : targetFrame);
328 0 : *aRangeOffset = targetFrame->GetContentOffsetsFromPoint(pt).offset;
329 0 : return NS_OK;
330 : }
331 0 : *aRangeOffset = 0;
332 0 : return NS_OK;
333 : }
334 :
335 : NS_IMETHODIMP
336 0 : nsDOMUIEvent::GetCancelBubble(bool* aCancelBubble)
337 : {
338 0 : NS_ENSURE_ARG_POINTER(aCancelBubble);
339 : *aCancelBubble =
340 0 : (mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) ? true : false;
341 0 : return NS_OK;
342 : }
343 :
344 : NS_IMETHODIMP
345 0 : nsDOMUIEvent::SetCancelBubble(bool aCancelBubble)
346 : {
347 0 : if (aCancelBubble) {
348 0 : mEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
349 : } else {
350 0 : mEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH;
351 : }
352 0 : return NS_OK;
353 : }
354 :
355 : nsIntPoint
356 0 : nsDOMUIEvent::GetLayerPoint()
357 : {
358 0 : if (!mEvent ||
359 : (mEvent->eventStructType != NS_MOUSE_EVENT &&
360 : mEvent->eventStructType != NS_POPUP_EVENT &&
361 : mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
362 : mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
363 : mEvent->eventStructType != NS_TOUCH_EVENT &&
364 : mEvent->eventStructType != NS_DRAG_EVENT &&
365 : mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
366 0 : !mPresContext ||
367 : mEventIsInternal) {
368 0 : return mLayerPoint;
369 : }
370 : // XXX I'm not really sure this is correct; it's my best shot, though
371 0 : nsIFrame* targetFrame = mPresContext->EventStateManager()->GetEventTarget();
372 0 : if (!targetFrame)
373 0 : return mLayerPoint;
374 0 : nsIFrame* layer = nsLayoutUtils::GetClosestLayer(targetFrame);
375 0 : nsPoint pt(nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent, layer));
376 : return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
377 0 : nsPresContext::AppUnitsToIntCSSPixels(pt.y));
378 : }
379 :
380 : NS_IMETHODIMP
381 0 : nsDOMUIEvent::GetLayerX(PRInt32* aLayerX)
382 : {
383 0 : NS_ENSURE_ARG_POINTER(aLayerX);
384 0 : *aLayerX = GetLayerPoint().x;
385 0 : return NS_OK;
386 : }
387 :
388 : NS_IMETHODIMP
389 0 : nsDOMUIEvent::GetLayerY(PRInt32* aLayerY)
390 : {
391 0 : NS_ENSURE_ARG_POINTER(aLayerY);
392 0 : *aLayerY = GetLayerPoint().y;
393 0 : return NS_OK;
394 : }
395 :
396 : NS_IMETHODIMP
397 0 : nsDOMUIEvent::GetIsChar(bool* aIsChar)
398 : {
399 0 : switch(mEvent->eventStructType)
400 : {
401 : case NS_KEY_EVENT:
402 0 : *aIsChar = ((nsKeyEvent*)mEvent)->isChar;
403 0 : return NS_OK;
404 : case NS_TEXT_EVENT:
405 0 : *aIsChar = ((nsTextEvent*)mEvent)->isChar;
406 0 : return NS_OK;
407 : default:
408 0 : *aIsChar = false;
409 0 : return NS_OK;
410 : }
411 : }
412 :
413 : NS_METHOD
414 0 : nsDOMUIEvent::DuplicatePrivateData()
415 : {
416 : #ifdef MOZ_TOUCH
417 : mClientPoint = nsDOMEvent::GetClientCoords(mPresContext,
418 : mEvent,
419 : mEvent->refPoint,
420 : mClientPoint);
421 : mLayerPoint = GetLayerPoint();
422 : mPagePoint = nsDOMEvent::GetPageCoords(mPresContext,
423 : mEvent,
424 : mEvent->refPoint,
425 : mClientPoint);
426 : // GetScreenPoint converts mEvent->refPoint to right coordinates.
427 : nsIntPoint screenPoint = nsDOMEvent::GetScreenCoords(mPresContext,
428 : mEvent,
429 : mEvent->refPoint);
430 : #else
431 0 : mClientPoint = GetClientPoint();
432 0 : mLayerPoint = GetLayerPoint();
433 0 : mPagePoint = GetPagePoint();
434 : // GetScreenPoint converts mEvent->refPoint to right coordinates.
435 0 : nsIntPoint screenPoint = GetScreenPoint();
436 : #endif
437 0 : nsresult rv = nsDOMEvent::DuplicatePrivateData();
438 0 : if (NS_SUCCEEDED(rv)) {
439 0 : mEvent->refPoint = screenPoint;
440 : }
441 0 : return rv;
442 : }
443 :
444 : void
445 0 : nsDOMUIEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType)
446 : {
447 0 : if (aSerializeInterfaceType) {
448 0 : IPC::WriteParam(aMsg, NS_LITERAL_STRING("uievent"));
449 : }
450 :
451 0 : nsDOMEvent::Serialize(aMsg, false);
452 :
453 0 : PRInt32 detail = 0;
454 0 : GetDetail(&detail);
455 0 : IPC::WriteParam(aMsg, detail);
456 0 : }
457 :
458 : bool
459 0 : nsDOMUIEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
460 : {
461 0 : NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), false);
462 0 : NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &mDetail), false);
463 0 : return true;
464 : }
465 :
466 0 : nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult,
467 : nsPresContext* aPresContext,
468 : nsGUIEvent *aEvent)
469 : {
470 0 : nsDOMUIEvent* it = new nsDOMUIEvent(aPresContext, aEvent);
471 0 : return CallQueryInterface(it, aInstancePtrResult);
472 4392 : }
|