1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/events/EventStateManager.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,924 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef mozilla_EventStateManager_h_ 1.10 +#define mozilla_EventStateManager_h_ 1.11 + 1.12 +#include "mozilla/EventForwards.h" 1.13 +#include "mozilla/TypedEnum.h" 1.14 + 1.15 +#include "nsIObserver.h" 1.16 +#include "nsWeakReference.h" 1.17 +#include "nsCOMPtr.h" 1.18 +#include "nsCOMArray.h" 1.19 +#include "nsCycleCollectionParticipant.h" 1.20 +#include "mozilla/TimeStamp.h" 1.21 +#include "nsIFrame.h" 1.22 +#include "Units.h" 1.23 + 1.24 +class nsFrameLoader; 1.25 +class nsIContent; 1.26 +class nsIDocument; 1.27 +class nsIDocShell; 1.28 +class nsIDocShellTreeItem; 1.29 +class imgIContainer; 1.30 +class EnterLeaveDispatcher; 1.31 +class nsIMarkupDocumentViewer; 1.32 +class nsIScrollableFrame; 1.33 +class nsITimer; 1.34 +class nsPresContext; 1.35 + 1.36 +namespace mozilla { 1.37 + 1.38 +class EnterLeaveDispatcher; 1.39 +class EventStates; 1.40 +class IMEContentObserver; 1.41 +class ScrollbarsForWheel; 1.42 +class WheelTransaction; 1.43 + 1.44 +namespace dom { 1.45 +class DataTransfer; 1.46 +class TabParent; 1.47 +} // namespace dom 1.48 + 1.49 +class OverOutElementsWrapper MOZ_FINAL : public nsISupports 1.50 +{ 1.51 +public: 1.52 + OverOutElementsWrapper(); 1.53 + ~OverOutElementsWrapper(); 1.54 + 1.55 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.56 + NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper) 1.57 + 1.58 + nsWeakFrame mLastOverFrame; 1.59 + 1.60 + nsCOMPtr<nsIContent> mLastOverElement; 1.61 + 1.62 + // The last element on which we fired a over event, or null if 1.63 + // the last over event we fired has finished processing. 1.64 + nsCOMPtr<nsIContent> mFirstOverEventElement; 1.65 + 1.66 + // The last element on which we fired a out event, or null if 1.67 + // the last out event we fired has finished processing. 1.68 + nsCOMPtr<nsIContent> mFirstOutEventElement; 1.69 +}; 1.70 + 1.71 +class EventStateManager : public nsSupportsWeakReference, 1.72 + public nsIObserver 1.73 +{ 1.74 + friend class mozilla::EnterLeaveDispatcher; 1.75 + friend class mozilla::ScrollbarsForWheel; 1.76 + friend class mozilla::WheelTransaction; 1.77 + 1.78 +public: 1.79 + EventStateManager(); 1.80 + virtual ~EventStateManager(); 1.81 + 1.82 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.83 + NS_DECL_NSIOBSERVER 1.84 + 1.85 + nsresult Init(); 1.86 + nsresult Shutdown(); 1.87 + 1.88 + /* The PreHandleEvent method is called before event dispatch to either 1.89 + * the DOM or frames. Any processing which must not be prevented or 1.90 + * cancelled should occur here. Any processing which is intended to 1.91 + * be conditional based on either DOM or frame processing should occur in 1.92 + * PostHandleEvent. Any centralized event processing which must occur before 1.93 + * DOM or frame event handling should occur here as well. 1.94 + */ 1.95 + nsresult PreHandleEvent(nsPresContext* aPresContext, 1.96 + WidgetEvent* aEvent, 1.97 + nsIFrame* aTargetFrame, 1.98 + nsEventStatus* aStatus); 1.99 + 1.100 + /* The PostHandleEvent method should contain all system processing which 1.101 + * should occur conditionally based on DOM or frame processing. It should 1.102 + * also contain any centralized event processing which must occur after 1.103 + * DOM and frame processing. 1.104 + */ 1.105 + nsresult PostHandleEvent(nsPresContext* aPresContext, 1.106 + WidgetEvent* aEvent, 1.107 + nsIFrame* aTargetFrame, 1.108 + nsEventStatus* aStatus); 1.109 + 1.110 + /** 1.111 + * DispatchLegacyMouseScrollEvents() dispatches NS_MOUSE_SCROLL event and 1.112 + * NS_MOUSE_PIXEL_SCROLL event for compatiblity with old Gecko. 1.113 + */ 1.114 + void DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame, 1.115 + WidgetWheelEvent* aEvent, 1.116 + nsEventStatus* aStatus); 1.117 + 1.118 + void NotifyDestroyPresContext(nsPresContext* aPresContext); 1.119 + void SetPresContext(nsPresContext* aPresContext); 1.120 + void ClearFrameRefs(nsIFrame* aFrame); 1.121 + 1.122 + nsIFrame* GetEventTarget(); 1.123 + already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent); 1.124 + 1.125 + /** 1.126 + * Notify that the given NS_EVENT_STATE_* bit has changed for this content. 1.127 + * @param aContent Content which has changed states 1.128 + * @param aState Corresponding state flags such as NS_EVENT_STATE_FOCUS 1.129 + * @return Whether the content was able to change all states. Returns false 1.130 + * if a resulting DOM event causes the content node passed in 1.131 + * to not change states. Note, the frame for the content may 1.132 + * change as a result of the content state change, because of 1.133 + * frame reconstructions that may occur, but this does not 1.134 + * affect the return value. 1.135 + */ 1.136 + bool SetContentState(nsIContent* aContent, EventStates aState); 1.137 + void ContentRemoved(nsIDocument* aDocument, nsIContent* aContent); 1.138 + bool EventStatusOK(WidgetGUIEvent* aEvent); 1.139 + 1.140 + /** 1.141 + * EventStateManager stores IMEContentObserver while it's observing contents. 1.142 + * Following mehtods are called by IMEContentObserver when it starts to 1.143 + * observe or stops observing the content. 1.144 + */ 1.145 + void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver); 1.146 + void OnStopObservingContent(IMEContentObserver* aIMEContentObserver); 1.147 + 1.148 + /** 1.149 + * Register accesskey on the given element. When accesskey is activated then 1.150 + * the element will be notified via nsIContent::PerformAccesskey() method. 1.151 + * 1.152 + * @param aContent the given element 1.153 + * @param aKey accesskey 1.154 + */ 1.155 + void RegisterAccessKey(nsIContent* aContent, uint32_t aKey); 1.156 + 1.157 + /** 1.158 + * Unregister accesskey for the given element. 1.159 + * 1.160 + * @param aContent the given element 1.161 + * @param aKey accesskey 1.162 + */ 1.163 + void UnregisterAccessKey(nsIContent* aContent, uint32_t aKey); 1.164 + 1.165 + /** 1.166 + * Get accesskey registered on the given element or 0 if there is none. 1.167 + * 1.168 + * @param aContent the given element (must not be null) 1.169 + * @return registered accesskey 1.170 + */ 1.171 + uint32_t GetRegisteredAccessKey(nsIContent* aContent); 1.172 + 1.173 + bool GetAccessKeyLabelPrefix(nsAString& aPrefix); 1.174 + 1.175 + nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer, 1.176 + bool aHaveHotspot, float aHotspotX, float aHotspotY, 1.177 + nsIWidget* aWidget, bool aLockCursor); 1.178 + 1.179 + static void StartHandlingUserInput() 1.180 + { 1.181 + ++sUserInputEventDepth; 1.182 + if (sUserInputEventDepth == 1) { 1.183 + sHandlingInputStart = TimeStamp::Now(); 1.184 + } 1.185 + } 1.186 + 1.187 + static void StopHandlingUserInput() 1.188 + { 1.189 + --sUserInputEventDepth; 1.190 + if (sUserInputEventDepth == 0) { 1.191 + sHandlingInputStart = TimeStamp(); 1.192 + } 1.193 + } 1.194 + 1.195 + /** 1.196 + * Returns true if the current code is being executed as a result of user input. 1.197 + * This includes timers or anything else that is initiated from user input. 1.198 + * However, mouse over events are not counted as user input, nor are 1.199 + * page load events. If this method is called from asynchronously executed code, 1.200 + * such as during layout reflows, it will return false. If more time has elapsed 1.201 + * since the user input than is specified by the 1.202 + * dom.event.handling-user-input-time-limit pref (default 1 second), this 1.203 + * function also returns false. 1.204 + */ 1.205 + static bool IsHandlingUserInput(); 1.206 + 1.207 + nsPresContext* GetPresContext() { return mPresContext; } 1.208 + 1.209 + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager, 1.210 + nsIObserver) 1.211 + 1.212 + static nsIDocument* sMouseOverDocument; 1.213 + 1.214 + static EventStateManager* GetActiveEventStateManager() { return sActiveESM; } 1.215 + 1.216 + // Sets aNewESM to be the active event state manager, and 1.217 + // if aContent is non-null, marks the object as active. 1.218 + static void SetActiveManager(EventStateManager* aNewESM, 1.219 + nsIContent* aContent); 1.220 + 1.221 + // Sets the full-screen event state on aElement to aIsFullScreen. 1.222 + static void SetFullScreenState(dom::Element* aElement, bool aIsFullScreen); 1.223 + 1.224 + static bool IsRemoteTarget(nsIContent* aTarget); 1.225 + static LayoutDeviceIntPoint GetChildProcessOffset(nsFrameLoader* aFrameLoader, 1.226 + const WidgetEvent& aEvent); 1.227 + 1.228 + // Holds the point in screen coords that a mouse event was dispatched to, 1.229 + // before we went into pointer lock mode. This is constantly updated while 1.230 + // the pointer is not locked, but we don't update it while the pointer is 1.231 + // locked. This is used by dom::Event::GetScreenCoords() to make mouse 1.232 + // events' screen coord appear frozen at the last mouse position while 1.233 + // the pointer is locked. 1.234 + static nsIntPoint sLastScreenPoint; 1.235 + 1.236 + // Holds the point in client coords of the last mouse event. Used by 1.237 + // dom::Event::GetClientCoords() to make mouse events' client coords appear 1.238 + // frozen at the last mouse position while the pointer is locked. 1.239 + static CSSIntPoint sLastClientPoint; 1.240 + 1.241 + static bool sIsPointerLocked; 1.242 + static nsWeakPtr sPointerLockedElement; 1.243 + static nsWeakPtr sPointerLockedDoc; 1.244 + 1.245 +protected: 1.246 + /** 1.247 + * Prefs class capsules preference management. 1.248 + */ 1.249 + class Prefs 1.250 + { 1.251 + public: 1.252 + static bool KeyCausesActivation() { return sKeyCausesActivation; } 1.253 + static bool ClickHoldContextMenu() { return sClickHoldContextMenu; } 1.254 + static int32_t ChromeAccessModifierMask(); 1.255 + static int32_t ContentAccessModifierMask(); 1.256 + 1.257 + static void Init(); 1.258 + static void OnChange(const char* aPrefName, void*); 1.259 + static void Shutdown(); 1.260 + 1.261 + private: 1.262 + static bool sKeyCausesActivation; 1.263 + static bool sClickHoldContextMenu; 1.264 + static int32_t sGenericAccessModifierKey; 1.265 + static int32_t sChromeAccessModifierMask; 1.266 + static int32_t sContentAccessModifierMask; 1.267 + 1.268 + static int32_t GetAccessModifierMask(int32_t aItemType); 1.269 + }; 1.270 + 1.271 + /** 1.272 + * Get appropriate access modifier mask for the aDocShell. Returns -1 if 1.273 + * access key isn't available. 1.274 + */ 1.275 + static int32_t GetAccessModifierMaskFor(nsISupports* aDocShell); 1.276 + 1.277 + void UpdateCursor(nsPresContext* aPresContext, 1.278 + WidgetEvent* aEvent, 1.279 + nsIFrame* aTargetFrame, 1.280 + nsEventStatus* aStatus); 1.281 + /** 1.282 + * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the specified 1.283 + * content. This returns the primary frame for the content (or null 1.284 + * if it goes away during the event). 1.285 + */ 1.286 + nsIFrame* DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent, 1.287 + uint32_t aMessage, 1.288 + nsIContent* aTargetContent, 1.289 + nsIContent* aRelatedContent); 1.290 + /** 1.291 + * Synthesize DOM and frame mouseover and mouseout events from this 1.292 + * MOUSE_MOVE or MOUSE_EXIT event. 1.293 + */ 1.294 + void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent); 1.295 + /** 1.296 + * Tell this ESM and ESMs in parent documents that the mouse is 1.297 + * over some content in this document. 1.298 + */ 1.299 + void NotifyMouseOver(WidgetMouseEvent* aMouseEvent, 1.300 + nsIContent* aContent); 1.301 + /** 1.302 + * Tell this ESM and ESMs in affected child documents that the mouse 1.303 + * has exited this document's currently hovered content. 1.304 + * @param aMouseEvent the event that triggered the mouseout 1.305 + * @param aMovingInto the content node we've moved into. This is used to set 1.306 + * the relatedTarget for mouseout events. Also, if it's non-null 1.307 + * NotifyMouseOut will NOT change the current hover content to null; 1.308 + * in that case the caller is responsible for updating hover state. 1.309 + */ 1.310 + void NotifyMouseOut(WidgetMouseEvent* aMouseEvent, 1.311 + nsIContent* aMovingInto); 1.312 + void GenerateDragDropEnterExit(nsPresContext* aPresContext, 1.313 + WidgetDragEvent* aDragEvent); 1.314 + 1.315 + /** 1.316 + * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper elements wrapper. 1.317 + * If mPointersEnterLeaveHelper does not contain wrapper for pointerId it create new one 1.318 + */ 1.319 + OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent); 1.320 + 1.321 + /** 1.322 + * Fire the dragenter and dragexit/dragleave events when the mouse moves to a 1.323 + * new target. 1.324 + * 1.325 + * @param aRelatedTarget relatedTarget to set for the event 1.326 + * @param aTargetContent target to set for the event 1.327 + * @param aTargetFrame target frame for the event 1.328 + */ 1.329 + void FireDragEnterOrExit(nsPresContext* aPresContext, 1.330 + WidgetDragEvent* aDragEvent, 1.331 + uint32_t aMsg, 1.332 + nsIContent* aRelatedTarget, 1.333 + nsIContent* aTargetContent, 1.334 + nsWeakFrame& aTargetFrame); 1.335 + /** 1.336 + * Update the initial drag session data transfer with any changes that occur 1.337 + * on cloned data transfer objects used for events. 1.338 + */ 1.339 + void UpdateDragDataTransfer(WidgetDragEvent* dragEvent); 1.340 + 1.341 + nsresult SetClickCount(nsPresContext* aPresContext, 1.342 + WidgetMouseEvent* aEvent, 1.343 + nsEventStatus* aStatus); 1.344 + nsresult CheckForAndDispatchClick(nsPresContext* aPresContext, 1.345 + WidgetMouseEvent* aEvent, 1.346 + nsEventStatus* aStatus); 1.347 + void EnsureDocument(nsPresContext* aPresContext); 1.348 + void FlushPendingEvents(nsPresContext* aPresContext); 1.349 + 1.350 + /** 1.351 + * The phases of HandleAccessKey processing. See below. 1.352 + */ 1.353 + typedef enum { 1.354 + eAccessKeyProcessingNormal = 0, 1.355 + eAccessKeyProcessingUp, 1.356 + eAccessKeyProcessingDown 1.357 + } ProcessingAccessKeyState; 1.358 + 1.359 + /** 1.360 + * Access key handling. If there is registered content for the accesskey 1.361 + * given by the key event and modifier mask then call 1.362 + * content.PerformAccesskey(), otherwise call HandleAccessKey() recursively, 1.363 + * on descendant docshells first, then on the ancestor (with |aBubbledFrom| 1.364 + * set to the docshell associated with |this|), until something matches. 1.365 + * 1.366 + * @param aPresContext the presentation context 1.367 + * @param aEvent the key event 1.368 + * @param aStatus the event status 1.369 + * @param aBubbledFrom is used by an ancestor to avoid calling HandleAccessKey() 1.370 + * on the child the call originally came from, i.e. this is the child 1.371 + * that recursively called us in its Up phase. The initial caller 1.372 + * passes |nullptr| here. This is to avoid an infinite loop. 1.373 + * @param aAccessKeyState Normal, Down or Up processing phase (see enums 1.374 + * above). The initial event receiver uses 'normal', then 'down' when 1.375 + * processing children and Up when recursively calling its ancestor. 1.376 + * @param aModifierMask modifier mask for the key event 1.377 + */ 1.378 + void HandleAccessKey(nsPresContext* aPresContext, 1.379 + WidgetKeyboardEvent* aEvent, 1.380 + nsEventStatus* aStatus, 1.381 + nsIDocShellTreeItem* aBubbledFrom, 1.382 + ProcessingAccessKeyState aAccessKeyState, 1.383 + int32_t aModifierMask); 1.384 + 1.385 + bool ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes, 1.386 + bool aIsTrustedEvent); 1.387 + 1.388 + //--------------------------------------------- 1.389 + // DocShell Focus Traversal Methods 1.390 + //--------------------------------------------- 1.391 + 1.392 + nsIContent* GetFocusedContent(); 1.393 + bool IsShellVisible(nsIDocShell* aShell); 1.394 + 1.395 + // These functions are for mousewheel and pixel scrolling 1.396 + 1.397 + class WheelPrefs 1.398 + { 1.399 + public: 1.400 + static WheelPrefs* GetInstance(); 1.401 + static void Shutdown(); 1.402 + 1.403 + /** 1.404 + * ApplyUserPrefsToDelta() overrides the wheel event's delta values with 1.405 + * user prefs. 1.406 + */ 1.407 + void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent); 1.408 + 1.409 + /** 1.410 + * If ApplyUserPrefsToDelta() changed the delta values with customized 1.411 + * prefs, the overflowDelta values would be inflated. 1.412 + * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation. 1.413 + */ 1.414 + void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent); 1.415 + 1.416 + /** 1.417 + * Computes the default action for the aEvent with the prefs. 1.418 + */ 1.419 + enum Action MOZ_ENUM_TYPE(uint8_t) 1.420 + { 1.421 + ACTION_NONE = 0, 1.422 + ACTION_SCROLL, 1.423 + ACTION_HISTORY, 1.424 + ACTION_ZOOM, 1.425 + ACTION_LAST = ACTION_ZOOM 1.426 + }; 1.427 + Action ComputeActionFor(WidgetWheelEvent* aEvent); 1.428 + 1.429 + /** 1.430 + * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be 1.431 + * computed the lineOrPageDelta values. 1.432 + */ 1.433 + bool NeedToComputeLineOrPageDelta(WidgetWheelEvent* aEvent); 1.434 + 1.435 + /** 1.436 + * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should 1.437 + * be rounded down to the page width/height (false) or not (true). 1.438 + */ 1.439 + bool IsOverOnePageScrollAllowedX(WidgetWheelEvent* aEvent); 1.440 + bool IsOverOnePageScrollAllowedY(WidgetWheelEvent* aEvent); 1.441 + 1.442 + private: 1.443 + WheelPrefs(); 1.444 + ~WheelPrefs(); 1.445 + 1.446 + static void OnPrefChanged(const char* aPrefName, void* aClosure); 1.447 + 1.448 + enum Index 1.449 + { 1.450 + INDEX_DEFAULT = 0, 1.451 + INDEX_ALT, 1.452 + INDEX_CONTROL, 1.453 + INDEX_META, 1.454 + INDEX_SHIFT, 1.455 + INDEX_OS, 1.456 + COUNT_OF_MULTIPLIERS 1.457 + }; 1.458 + 1.459 + /** 1.460 + * GetIndexFor() returns the index of the members which should be used for 1.461 + * the aEvent. When only one modifier key of MODIFIER_ALT, 1.462 + * MODIFIER_CONTROL, MODIFIER_META, MODIFIER_SHIFT or MODIFIER_OS is 1.463 + * pressed, returns the index for the modifier. Otherwise, this return the 1.464 + * default index which is used at either no modifier key is pressed or 1.465 + * two or modifier keys are pressed. 1.466 + */ 1.467 + Index GetIndexFor(WidgetWheelEvent* aEvent); 1.468 + 1.469 + /** 1.470 + * GetPrefNameBase() returns the base pref name for aEvent. 1.471 + * It's decided by GetModifierForPref() which modifier should be used for 1.472 + * the aEvent. 1.473 + * 1.474 + * @param aBasePrefName The result, must be "mousewheel.with_*." or 1.475 + * "mousewheel.default.". 1.476 + */ 1.477 + void GetBasePrefName(Index aIndex, nsACString& aBasePrefName); 1.478 + 1.479 + void Init(Index aIndex); 1.480 + 1.481 + void Reset(); 1.482 + 1.483 + /** 1.484 + * If the abosolute values of mMultiplierX and/or mMultiplierY are equals or 1.485 + * larger than this value, the computed scroll amount isn't rounded down to 1.486 + * the page width or height. 1.487 + */ 1.488 + enum { 1.489 + MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000 1.490 + }; 1.491 + 1.492 + bool mInit[COUNT_OF_MULTIPLIERS]; 1.493 + double mMultiplierX[COUNT_OF_MULTIPLIERS]; 1.494 + double mMultiplierY[COUNT_OF_MULTIPLIERS]; 1.495 + double mMultiplierZ[COUNT_OF_MULTIPLIERS]; 1.496 + Action mActions[COUNT_OF_MULTIPLIERS]; 1.497 + /** 1.498 + * action values overridden by .override_x pref. 1.499 + * If an .override_x value is -1, same as the 1.500 + * corresponding mActions value. 1.501 + */ 1.502 + Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS]; 1.503 + 1.504 + static WheelPrefs* sInstance; 1.505 + }; 1.506 + 1.507 + /** 1.508 + * DeltaDirection is used for specifying whether the called method should 1.509 + * handle vertical delta or horizontal delta. 1.510 + * This is clearer than using bool. 1.511 + */ 1.512 + enum DeltaDirection 1.513 + { 1.514 + DELTA_DIRECTION_X = 0, 1.515 + DELTA_DIRECTION_Y 1.516 + }; 1.517 + 1.518 + struct MOZ_STACK_CLASS EventState 1.519 + { 1.520 + bool mDefaultPrevented; 1.521 + bool mDefaultPreventedByContent; 1.522 + 1.523 + EventState() : 1.524 + mDefaultPrevented(false), mDefaultPreventedByContent(false) 1.525 + { 1.526 + } 1.527 + }; 1.528 + 1.529 + /** 1.530 + * SendLineScrollEvent() dispatches a DOMMouseScroll event for the 1.531 + * WidgetWheelEvent. This method shouldn't be called for non-trusted 1.532 + * wheel event because it's not necessary for compatiblity. 1.533 + * 1.534 + * @param aTargetFrame The event target of wheel event. 1.535 + * @param aEvent The original Wheel event. 1.536 + * @param aState The event which should be set to the dispatching 1.537 + * event. This also returns the dispatched event 1.538 + * state. 1.539 + * @param aDelta The delta value of the event. 1.540 + * @param aDeltaDirection The X/Y direction of dispatching event. 1.541 + */ 1.542 + void SendLineScrollEvent(nsIFrame* aTargetFrame, 1.543 + WidgetWheelEvent* aEvent, 1.544 + EventState& aState, 1.545 + int32_t aDelta, 1.546 + DeltaDirection aDeltaDirection); 1.547 + 1.548 + /** 1.549 + * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the 1.550 + * WidgetWheelEvent. This method shouldn't be called for non-trusted 1.551 + * wheel event because it's not necessary for compatiblity. 1.552 + * 1.553 + * @param aTargetFrame The event target of wheel event. 1.554 + * @param aEvent The original Wheel event. 1.555 + * @param aState The event which should be set to the dispatching 1.556 + * event. This also returns the dispatched event 1.557 + * state. 1.558 + * @param aPixelDelta The delta value of the event. 1.559 + * @param aDeltaDirection The X/Y direction of dispatching event. 1.560 + */ 1.561 + void SendPixelScrollEvent(nsIFrame* aTargetFrame, 1.562 + WidgetWheelEvent* aEvent, 1.563 + EventState& aState, 1.564 + int32_t aPixelDelta, 1.565 + DeltaDirection aDeltaDirection); 1.566 + 1.567 + /** 1.568 + * ComputeScrollTarget() returns the scrollable frame which should be 1.569 + * scrolled. 1.570 + * 1.571 + * @param aTargetFrame The event target of the wheel event. 1.572 + * @param aEvent The handling mouse wheel event. 1.573 + * @param aOptions The options for finding the scroll target. 1.574 + * Callers should use COMPUTE_*. 1.575 + * @return The scrollable frame which should be scrolled. 1.576 + */ 1.577 + // These flags are used in ComputeScrollTarget(). Callers should use 1.578 + // COMPUTE_*. 1.579 + enum 1.580 + { 1.581 + PREFER_MOUSE_WHEEL_TRANSACTION = 1, 1.582 + PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 2, 1.583 + PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 4, 1.584 + START_FROM_PARENT = 8 1.585 + }; 1.586 + enum ComputeScrollTargetOptions 1.587 + { 1.588 + // At computing scroll target for legacy mouse events, we should return 1.589 + // first scrollable element even when it's not scrollable to the direction. 1.590 + COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0, 1.591 + // Default action prefers the scrolled element immediately before if it's 1.592 + // still under the mouse cursor. Otherwise, it prefers the nearest 1.593 + // scrollable ancestor which will be scrolled actually. 1.594 + COMPUTE_DEFAULT_ACTION_TARGET = 1.595 + (PREFER_MOUSE_WHEEL_TRANSACTION | 1.596 + PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | 1.597 + PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS), 1.598 + // Look for the nearest scrollable ancestor which can be scrollable with 1.599 + // aEvent. 1.600 + COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS = 1.601 + (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT), 1.602 + COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS = 1.603 + (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT) 1.604 + }; 1.605 + nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame, 1.606 + WidgetWheelEvent* aEvent, 1.607 + ComputeScrollTargetOptions aOptions); 1.608 + 1.609 + nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame, 1.610 + double aDirectionX, 1.611 + double aDirectionY, 1.612 + WidgetWheelEvent* aEvent, 1.613 + ComputeScrollTargetOptions aOptions); 1.614 + 1.615 + /** 1.616 + * GetScrollAmount() returns the scroll amount in app uints of one line or 1.617 + * one page. If the wheel event scrolls a page, returns the page width and 1.618 + * height. Otherwise, returns line height for both its width and height. 1.619 + * 1.620 + * @param aScrollableFrame A frame which will be scrolled by the event. 1.621 + * The result of ComputeScrollTarget() is 1.622 + * expected for this value. 1.623 + * This can be nullptr if there is no scrollable 1.624 + * frame. Then, this method uses root frame's 1.625 + * line height or visible area's width and height. 1.626 + */ 1.627 + nsSize GetScrollAmount(nsPresContext* aPresContext, 1.628 + WidgetWheelEvent* aEvent, 1.629 + nsIScrollableFrame* aScrollableFrame); 1.630 + 1.631 + /** 1.632 + * DoScrollText() scrolls the scrollable frame for aEvent. 1.633 + */ 1.634 + void DoScrollText(nsIScrollableFrame* aScrollableFrame, 1.635 + WidgetWheelEvent* aEvent); 1.636 + 1.637 + void DoScrollHistory(int32_t direction); 1.638 + void DoScrollZoom(nsIFrame *aTargetFrame, int32_t adjustment); 1.639 + nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv); 1.640 + nsresult ChangeTextSize(int32_t change); 1.641 + nsresult ChangeFullZoom(int32_t change); 1.642 + 1.643 + /** 1.644 + * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll 1.645 + * event. If wheel events are caused by pixel scroll only devices or 1.646 + * the delta values are customized by prefs, this class stores the delta 1.647 + * values and set lineOrPageDelta values. 1.648 + */ 1.649 + class DeltaAccumulator 1.650 + { 1.651 + public: 1.652 + static DeltaAccumulator* GetInstance() 1.653 + { 1.654 + if (!sInstance) { 1.655 + sInstance = new DeltaAccumulator; 1.656 + } 1.657 + return sInstance; 1.658 + } 1.659 + 1.660 + static void Shutdown() 1.661 + { 1.662 + delete sInstance; 1.663 + sInstance = nullptr; 1.664 + } 1.665 + 1.666 + bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; } 1.667 + 1.668 + /** 1.669 + * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents 1.670 + * which are caused if it's needed. And if the accumulated delta becomes a 1.671 + * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically. 1.672 + */ 1.673 + void InitLineOrPageDelta(nsIFrame* aTargetFrame, 1.674 + EventStateManager* aESM, 1.675 + WidgetWheelEvent* aEvent); 1.676 + 1.677 + /** 1.678 + * Reset() resets all members. 1.679 + */ 1.680 + void Reset(); 1.681 + 1.682 + /** 1.683 + * ComputeScrollAmountForDefaultAction() computes the default action's 1.684 + * scroll amount in device pixels with mPendingScrollAmount*. 1.685 + */ 1.686 + nsIntPoint ComputeScrollAmountForDefaultAction( 1.687 + WidgetWheelEvent* aEvent, 1.688 + const nsIntSize& aScrollAmountInDevPixels); 1.689 + 1.690 + private: 1.691 + DeltaAccumulator() : 1.692 + mX(0.0), mY(0.0), mPendingScrollAmountX(0.0), mPendingScrollAmountY(0.0), 1.693 + mHandlingDeltaMode(UINT32_MAX), mHandlingPixelOnlyDevice(false) 1.694 + { 1.695 + } 1.696 + 1.697 + double mX; 1.698 + double mY; 1.699 + 1.700 + // When default action of a wheel event is scroll but some delta values 1.701 + // are ignored because the computed amount values are not integer, the 1.702 + // fractional values are saved by these members. 1.703 + double mPendingScrollAmountX; 1.704 + double mPendingScrollAmountY; 1.705 + 1.706 + TimeStamp mLastTime; 1.707 + 1.708 + uint32_t mHandlingDeltaMode; 1.709 + bool mHandlingPixelOnlyDevice; 1.710 + 1.711 + static DeltaAccumulator* sInstance; 1.712 + }; 1.713 + 1.714 + // end mousewheel functions 1.715 + 1.716 + /* 1.717 + * When a touch gesture is about to start, this function determines what 1.718 + * kind of gesture interaction we will want to use, based on what is 1.719 + * underneath the initial touch point. 1.720 + * Currently it decides between panning (finger scrolling) or dragging 1.721 + * the target element, as well as the orientation to trigger panning and 1.722 + * display visual boundary feedback. The decision is stored back in aEvent. 1.723 + */ 1.724 + void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent, 1.725 + nsIFrame* targetFrame); 1.726 + 1.727 + // routines for the d&d gesture tracking state machine 1.728 + void BeginTrackingDragGesture(nsPresContext* aPresContext, 1.729 + WidgetMouseEvent* aDownEvent, 1.730 + nsIFrame* aDownFrame); 1.731 + void StopTrackingDragGesture(); 1.732 + void GenerateDragGesture(nsPresContext* aPresContext, 1.733 + WidgetMouseEvent* aEvent); 1.734 + 1.735 + /** 1.736 + * Determine which node the drag should be targeted at. 1.737 + * This is either the node clicked when there is a selection, or, for HTML, 1.738 + * the element with a draggable property set to true. 1.739 + * 1.740 + * aSelectionTarget - target to check for selection 1.741 + * aDataTransfer - data transfer object that will contain the data to drag 1.742 + * aSelection - [out] set to the selection to be dragged 1.743 + * aTargetNode - [out] the draggable node, or null if there isn't one 1.744 + */ 1.745 + void DetermineDragTarget(nsPIDOMWindow* aWindow, 1.746 + nsIContent* aSelectionTarget, 1.747 + dom::DataTransfer* aDataTransfer, 1.748 + nsISelection** aSelection, 1.749 + nsIContent** aTargetNode); 1.750 + 1.751 + /* 1.752 + * Perform the default handling for the dragstart/draggesture event and set up a 1.753 + * drag for aDataTransfer if it contains any data. Returns true if a drag has 1.754 + * started. 1.755 + * 1.756 + * aDragEvent - the dragstart/draggesture event 1.757 + * aDataTransfer - the data transfer that holds the data to be dragged 1.758 + * aDragTarget - the target of the drag 1.759 + * aSelection - the selection to be dragged 1.760 + */ 1.761 + bool DoDefaultDragStart(nsPresContext* aPresContext, 1.762 + WidgetDragEvent* aDragEvent, 1.763 + dom::DataTransfer* aDataTransfer, 1.764 + nsIContent* aDragTarget, 1.765 + nsISelection* aSelection); 1.766 + 1.767 + bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nullptr; } 1.768 + /** 1.769 + * Set the fields of aEvent to reflect the mouse position and modifier keys 1.770 + * that were set when the user first pressed the mouse button (stored by 1.771 + * BeginTrackingDragGesture). aEvent->widget must be 1.772 + * mCurrentTarget->GetNearestWidget(). 1.773 + */ 1.774 + void FillInEventFromGestureDown(WidgetMouseEvent* aEvent); 1.775 + 1.776 + nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent); 1.777 + nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent); 1.778 + 1.779 + void DoQuerySelectedText(WidgetQueryContentEvent* aEvent); 1.780 + 1.781 + bool RemoteQueryContentEvent(WidgetEvent* aEvent); 1.782 + dom::TabParent *GetCrossProcessTarget(); 1.783 + bool IsTargetCrossProcess(WidgetGUIEvent* aEvent); 1.784 + 1.785 + bool DispatchCrossProcessEvent(WidgetEvent* aEvent, 1.786 + nsFrameLoader* aRemote, 1.787 + nsEventStatus *aStatus); 1.788 + bool HandleCrossProcessEvent(WidgetEvent* aEvent, 1.789 + nsIFrame* aTargetFrame, 1.790 + nsEventStatus* aStatus); 1.791 + 1.792 + void ReleaseCurrentIMEContentObserver(); 1.793 + 1.794 +private: 1.795 + static inline void DoStateChange(dom::Element* aElement, 1.796 + EventStates aState, bool aAddState); 1.797 + static inline void DoStateChange(nsIContent* aContent, EventStates aState, 1.798 + bool aAddState); 1.799 + static void UpdateAncestorState(nsIContent* aStartNode, 1.800 + nsIContent* aStopBefore, 1.801 + EventStates aState, 1.802 + bool aAddState); 1.803 + static PLDHashOperator ResetLastOverForContent(const uint32_t& aIdx, 1.804 + nsRefPtr<OverOutElementsWrapper>& aChunk, 1.805 + void* aClosure); 1.806 + 1.807 + int32_t mLockCursor; 1.808 + 1.809 + // Last mouse event refPoint (the offset from the widget's origin in 1.810 + // device pixels) when mouse was locked, used to restore mouse position 1.811 + // after unlocking. 1.812 + LayoutDeviceIntPoint mPreLockPoint; 1.813 + 1.814 + // Stores the refPoint of the last synthetic mouse move we dispatched 1.815 + // to re-center the mouse when we were pointer locked. If this is (-1,-1) it 1.816 + // means we've not recently dispatched a centering event. We use this to 1.817 + // detect when we receive the synth event, so we can cancel and not send it 1.818 + // to content. 1.819 + static LayoutDeviceIntPoint sSynthCenteringPoint; 1.820 + 1.821 + nsWeakFrame mCurrentTarget; 1.822 + nsCOMPtr<nsIContent> mCurrentTargetContent; 1.823 + static nsWeakFrame sLastDragOverFrame; 1.824 + 1.825 + // Stores the refPoint (the offset from the widget's origin in device 1.826 + // pixels) of the last mouse event. 1.827 + static LayoutDeviceIntPoint sLastRefPoint; 1.828 + 1.829 + // member variables for the d&d gesture state machine 1.830 + LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates 1.831 + // The content to use as target if we start a d&d (what we drag). 1.832 + nsCOMPtr<nsIContent> mGestureDownContent; 1.833 + // The content of the frame where the mouse-down event occurred. It's the same 1.834 + // as the target in most cases but not always - for example when dragging 1.835 + // an <area> of an image map this is the image. (bug 289667) 1.836 + nsCOMPtr<nsIContent> mGestureDownFrameOwner; 1.837 + // State of keys when the original gesture-down happened 1.838 + Modifiers mGestureModifiers; 1.839 + uint16_t mGestureDownButtons; 1.840 + 1.841 + nsCOMPtr<nsIContent> mLastLeftMouseDownContent; 1.842 + nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent; 1.843 + nsCOMPtr<nsIContent> mLastMiddleMouseDownContent; 1.844 + nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent; 1.845 + nsCOMPtr<nsIContent> mLastRightMouseDownContent; 1.846 + nsCOMPtr<nsIContent> mLastRightMouseDownContentParent; 1.847 + 1.848 + nsCOMPtr<nsIContent> mActiveContent; 1.849 + nsCOMPtr<nsIContent> mHoverContent; 1.850 + static nsCOMPtr<nsIContent> sDragOverContent; 1.851 + nsCOMPtr<nsIContent> mURLTargetContent; 1.852 + 1.853 + nsPresContext* mPresContext; // Not refcnted 1.854 + nsCOMPtr<nsIDocument> mDocument; // Doesn't necessarily need to be owner 1.855 + 1.856 + nsRefPtr<IMEContentObserver> mIMEContentObserver; 1.857 + 1.858 + uint32_t mLClickCount; 1.859 + uint32_t mMClickCount; 1.860 + uint32_t mRClickCount; 1.861 + 1.862 + bool m_haveShutdown; 1.863 + 1.864 + // Time at which we began handling user input. 1.865 + static TimeStamp sHandlingInputStart; 1.866 + 1.867 + nsRefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper; 1.868 + nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper> mPointersEnterLeaveHelper; 1.869 + 1.870 +public: 1.871 + static nsresult UpdateUserActivityTimer(void); 1.872 + // Array for accesskey support 1.873 + nsCOMArray<nsIContent> mAccessKeys; 1.874 + 1.875 + static int32_t sUserInputEventDepth; 1.876 + 1.877 + static bool sNormalLMouseEventInProcess; 1.878 + 1.879 + static EventStateManager* sActiveESM; 1.880 + 1.881 + static void ClearGlobalActiveContent(EventStateManager* aClearer); 1.882 + 1.883 + // Functions used for click hold context menus 1.884 + nsCOMPtr<nsITimer> mClickHoldTimer; 1.885 + void CreateClickHoldTimer(nsPresContext* aPresContext, 1.886 + nsIFrame* aDownFrame, 1.887 + WidgetGUIEvent* aMouseDownEvent); 1.888 + void KillClickHoldTimer(); 1.889 + void FireContextClick(); 1.890 + 1.891 + void SetPointerLock(nsIWidget* aWidget, nsIContent* aElement) ; 1.892 + static void sClickHoldCallback ( nsITimer* aTimer, void* aESM ) ; 1.893 +}; 1.894 + 1.895 +/** 1.896 + * This class is used while processing real user input. During this time, popups 1.897 + * are allowed. For mousedown events, mouse capturing is also permitted. 1.898 + */ 1.899 +class AutoHandlingUserInputStatePusher 1.900 +{ 1.901 +public: 1.902 + AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput, 1.903 + WidgetEvent* aEvent, 1.904 + nsIDocument* aDocument); 1.905 + ~AutoHandlingUserInputStatePusher(); 1.906 + 1.907 +protected: 1.908 + bool mIsHandlingUserInput; 1.909 + bool mIsMouseDown; 1.910 + bool mResetFMMouseDownState; 1.911 + 1.912 +private: 1.913 + // Hide so that this class can only be stack-allocated 1.914 + static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nullptr; } 1.915 + static void operator delete(void* /*memory*/) {} 1.916 +}; 1.917 + 1.918 +} // namespace mozilla 1.919 + 1.920 +// Click and double-click events need to be handled even for content that 1.921 +// has no frame. This is required for Web compatibility. 1.922 +#define NS_EVENT_NEEDS_FRAME(event) \ 1.923 + (!(event)->HasPluginActivationEventMessage() && \ 1.924 + (event)->message != NS_MOUSE_CLICK && \ 1.925 + (event)->message != NS_MOUSE_DOUBLECLICK) 1.926 + 1.927 +#endif // mozilla_EventStateManager_h_