Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef mozilla_EventStateManager_h_ |
michael@0 | 7 | #define mozilla_EventStateManager_h_ |
michael@0 | 8 | |
michael@0 | 9 | #include "mozilla/EventForwards.h" |
michael@0 | 10 | #include "mozilla/TypedEnum.h" |
michael@0 | 11 | |
michael@0 | 12 | #include "nsIObserver.h" |
michael@0 | 13 | #include "nsWeakReference.h" |
michael@0 | 14 | #include "nsCOMPtr.h" |
michael@0 | 15 | #include "nsCOMArray.h" |
michael@0 | 16 | #include "nsCycleCollectionParticipant.h" |
michael@0 | 17 | #include "mozilla/TimeStamp.h" |
michael@0 | 18 | #include "nsIFrame.h" |
michael@0 | 19 | #include "Units.h" |
michael@0 | 20 | |
michael@0 | 21 | class nsFrameLoader; |
michael@0 | 22 | class nsIContent; |
michael@0 | 23 | class nsIDocument; |
michael@0 | 24 | class nsIDocShell; |
michael@0 | 25 | class nsIDocShellTreeItem; |
michael@0 | 26 | class imgIContainer; |
michael@0 | 27 | class EnterLeaveDispatcher; |
michael@0 | 28 | class nsIMarkupDocumentViewer; |
michael@0 | 29 | class nsIScrollableFrame; |
michael@0 | 30 | class nsITimer; |
michael@0 | 31 | class nsPresContext; |
michael@0 | 32 | |
michael@0 | 33 | namespace mozilla { |
michael@0 | 34 | |
michael@0 | 35 | class EnterLeaveDispatcher; |
michael@0 | 36 | class EventStates; |
michael@0 | 37 | class IMEContentObserver; |
michael@0 | 38 | class ScrollbarsForWheel; |
michael@0 | 39 | class WheelTransaction; |
michael@0 | 40 | |
michael@0 | 41 | namespace dom { |
michael@0 | 42 | class DataTransfer; |
michael@0 | 43 | class TabParent; |
michael@0 | 44 | } // namespace dom |
michael@0 | 45 | |
michael@0 | 46 | class OverOutElementsWrapper MOZ_FINAL : public nsISupports |
michael@0 | 47 | { |
michael@0 | 48 | public: |
michael@0 | 49 | OverOutElementsWrapper(); |
michael@0 | 50 | ~OverOutElementsWrapper(); |
michael@0 | 51 | |
michael@0 | 52 | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
michael@0 | 53 | NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper) |
michael@0 | 54 | |
michael@0 | 55 | nsWeakFrame mLastOverFrame; |
michael@0 | 56 | |
michael@0 | 57 | nsCOMPtr<nsIContent> mLastOverElement; |
michael@0 | 58 | |
michael@0 | 59 | // The last element on which we fired a over event, or null if |
michael@0 | 60 | // the last over event we fired has finished processing. |
michael@0 | 61 | nsCOMPtr<nsIContent> mFirstOverEventElement; |
michael@0 | 62 | |
michael@0 | 63 | // The last element on which we fired a out event, or null if |
michael@0 | 64 | // the last out event we fired has finished processing. |
michael@0 | 65 | nsCOMPtr<nsIContent> mFirstOutEventElement; |
michael@0 | 66 | }; |
michael@0 | 67 | |
michael@0 | 68 | class EventStateManager : public nsSupportsWeakReference, |
michael@0 | 69 | public nsIObserver |
michael@0 | 70 | { |
michael@0 | 71 | friend class mozilla::EnterLeaveDispatcher; |
michael@0 | 72 | friend class mozilla::ScrollbarsForWheel; |
michael@0 | 73 | friend class mozilla::WheelTransaction; |
michael@0 | 74 | |
michael@0 | 75 | public: |
michael@0 | 76 | EventStateManager(); |
michael@0 | 77 | virtual ~EventStateManager(); |
michael@0 | 78 | |
michael@0 | 79 | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
michael@0 | 80 | NS_DECL_NSIOBSERVER |
michael@0 | 81 | |
michael@0 | 82 | nsresult Init(); |
michael@0 | 83 | nsresult Shutdown(); |
michael@0 | 84 | |
michael@0 | 85 | /* The PreHandleEvent method is called before event dispatch to either |
michael@0 | 86 | * the DOM or frames. Any processing which must not be prevented or |
michael@0 | 87 | * cancelled should occur here. Any processing which is intended to |
michael@0 | 88 | * be conditional based on either DOM or frame processing should occur in |
michael@0 | 89 | * PostHandleEvent. Any centralized event processing which must occur before |
michael@0 | 90 | * DOM or frame event handling should occur here as well. |
michael@0 | 91 | */ |
michael@0 | 92 | nsresult PreHandleEvent(nsPresContext* aPresContext, |
michael@0 | 93 | WidgetEvent* aEvent, |
michael@0 | 94 | nsIFrame* aTargetFrame, |
michael@0 | 95 | nsEventStatus* aStatus); |
michael@0 | 96 | |
michael@0 | 97 | /* The PostHandleEvent method should contain all system processing which |
michael@0 | 98 | * should occur conditionally based on DOM or frame processing. It should |
michael@0 | 99 | * also contain any centralized event processing which must occur after |
michael@0 | 100 | * DOM and frame processing. |
michael@0 | 101 | */ |
michael@0 | 102 | nsresult PostHandleEvent(nsPresContext* aPresContext, |
michael@0 | 103 | WidgetEvent* aEvent, |
michael@0 | 104 | nsIFrame* aTargetFrame, |
michael@0 | 105 | nsEventStatus* aStatus); |
michael@0 | 106 | |
michael@0 | 107 | /** |
michael@0 | 108 | * DispatchLegacyMouseScrollEvents() dispatches NS_MOUSE_SCROLL event and |
michael@0 | 109 | * NS_MOUSE_PIXEL_SCROLL event for compatiblity with old Gecko. |
michael@0 | 110 | */ |
michael@0 | 111 | void DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame, |
michael@0 | 112 | WidgetWheelEvent* aEvent, |
michael@0 | 113 | nsEventStatus* aStatus); |
michael@0 | 114 | |
michael@0 | 115 | void NotifyDestroyPresContext(nsPresContext* aPresContext); |
michael@0 | 116 | void SetPresContext(nsPresContext* aPresContext); |
michael@0 | 117 | void ClearFrameRefs(nsIFrame* aFrame); |
michael@0 | 118 | |
michael@0 | 119 | nsIFrame* GetEventTarget(); |
michael@0 | 120 | already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent); |
michael@0 | 121 | |
michael@0 | 122 | /** |
michael@0 | 123 | * Notify that the given NS_EVENT_STATE_* bit has changed for this content. |
michael@0 | 124 | * @param aContent Content which has changed states |
michael@0 | 125 | * @param aState Corresponding state flags such as NS_EVENT_STATE_FOCUS |
michael@0 | 126 | * @return Whether the content was able to change all states. Returns false |
michael@0 | 127 | * if a resulting DOM event causes the content node passed in |
michael@0 | 128 | * to not change states. Note, the frame for the content may |
michael@0 | 129 | * change as a result of the content state change, because of |
michael@0 | 130 | * frame reconstructions that may occur, but this does not |
michael@0 | 131 | * affect the return value. |
michael@0 | 132 | */ |
michael@0 | 133 | bool SetContentState(nsIContent* aContent, EventStates aState); |
michael@0 | 134 | void ContentRemoved(nsIDocument* aDocument, nsIContent* aContent); |
michael@0 | 135 | bool EventStatusOK(WidgetGUIEvent* aEvent); |
michael@0 | 136 | |
michael@0 | 137 | /** |
michael@0 | 138 | * EventStateManager stores IMEContentObserver while it's observing contents. |
michael@0 | 139 | * Following mehtods are called by IMEContentObserver when it starts to |
michael@0 | 140 | * observe or stops observing the content. |
michael@0 | 141 | */ |
michael@0 | 142 | void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver); |
michael@0 | 143 | void OnStopObservingContent(IMEContentObserver* aIMEContentObserver); |
michael@0 | 144 | |
michael@0 | 145 | /** |
michael@0 | 146 | * Register accesskey on the given element. When accesskey is activated then |
michael@0 | 147 | * the element will be notified via nsIContent::PerformAccesskey() method. |
michael@0 | 148 | * |
michael@0 | 149 | * @param aContent the given element |
michael@0 | 150 | * @param aKey accesskey |
michael@0 | 151 | */ |
michael@0 | 152 | void RegisterAccessKey(nsIContent* aContent, uint32_t aKey); |
michael@0 | 153 | |
michael@0 | 154 | /** |
michael@0 | 155 | * Unregister accesskey for the given element. |
michael@0 | 156 | * |
michael@0 | 157 | * @param aContent the given element |
michael@0 | 158 | * @param aKey accesskey |
michael@0 | 159 | */ |
michael@0 | 160 | void UnregisterAccessKey(nsIContent* aContent, uint32_t aKey); |
michael@0 | 161 | |
michael@0 | 162 | /** |
michael@0 | 163 | * Get accesskey registered on the given element or 0 if there is none. |
michael@0 | 164 | * |
michael@0 | 165 | * @param aContent the given element (must not be null) |
michael@0 | 166 | * @return registered accesskey |
michael@0 | 167 | */ |
michael@0 | 168 | uint32_t GetRegisteredAccessKey(nsIContent* aContent); |
michael@0 | 169 | |
michael@0 | 170 | bool GetAccessKeyLabelPrefix(nsAString& aPrefix); |
michael@0 | 171 | |
michael@0 | 172 | nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer, |
michael@0 | 173 | bool aHaveHotspot, float aHotspotX, float aHotspotY, |
michael@0 | 174 | nsIWidget* aWidget, bool aLockCursor); |
michael@0 | 175 | |
michael@0 | 176 | static void StartHandlingUserInput() |
michael@0 | 177 | { |
michael@0 | 178 | ++sUserInputEventDepth; |
michael@0 | 179 | if (sUserInputEventDepth == 1) { |
michael@0 | 180 | sHandlingInputStart = TimeStamp::Now(); |
michael@0 | 181 | } |
michael@0 | 182 | } |
michael@0 | 183 | |
michael@0 | 184 | static void StopHandlingUserInput() |
michael@0 | 185 | { |
michael@0 | 186 | --sUserInputEventDepth; |
michael@0 | 187 | if (sUserInputEventDepth == 0) { |
michael@0 | 188 | sHandlingInputStart = TimeStamp(); |
michael@0 | 189 | } |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | /** |
michael@0 | 193 | * Returns true if the current code is being executed as a result of user input. |
michael@0 | 194 | * This includes timers or anything else that is initiated from user input. |
michael@0 | 195 | * However, mouse over events are not counted as user input, nor are |
michael@0 | 196 | * page load events. If this method is called from asynchronously executed code, |
michael@0 | 197 | * such as during layout reflows, it will return false. If more time has elapsed |
michael@0 | 198 | * since the user input than is specified by the |
michael@0 | 199 | * dom.event.handling-user-input-time-limit pref (default 1 second), this |
michael@0 | 200 | * function also returns false. |
michael@0 | 201 | */ |
michael@0 | 202 | static bool IsHandlingUserInput(); |
michael@0 | 203 | |
michael@0 | 204 | nsPresContext* GetPresContext() { return mPresContext; } |
michael@0 | 205 | |
michael@0 | 206 | NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager, |
michael@0 | 207 | nsIObserver) |
michael@0 | 208 | |
michael@0 | 209 | static nsIDocument* sMouseOverDocument; |
michael@0 | 210 | |
michael@0 | 211 | static EventStateManager* GetActiveEventStateManager() { return sActiveESM; } |
michael@0 | 212 | |
michael@0 | 213 | // Sets aNewESM to be the active event state manager, and |
michael@0 | 214 | // if aContent is non-null, marks the object as active. |
michael@0 | 215 | static void SetActiveManager(EventStateManager* aNewESM, |
michael@0 | 216 | nsIContent* aContent); |
michael@0 | 217 | |
michael@0 | 218 | // Sets the full-screen event state on aElement to aIsFullScreen. |
michael@0 | 219 | static void SetFullScreenState(dom::Element* aElement, bool aIsFullScreen); |
michael@0 | 220 | |
michael@0 | 221 | static bool IsRemoteTarget(nsIContent* aTarget); |
michael@0 | 222 | static LayoutDeviceIntPoint GetChildProcessOffset(nsFrameLoader* aFrameLoader, |
michael@0 | 223 | const WidgetEvent& aEvent); |
michael@0 | 224 | |
michael@0 | 225 | // Holds the point in screen coords that a mouse event was dispatched to, |
michael@0 | 226 | // before we went into pointer lock mode. This is constantly updated while |
michael@0 | 227 | // the pointer is not locked, but we don't update it while the pointer is |
michael@0 | 228 | // locked. This is used by dom::Event::GetScreenCoords() to make mouse |
michael@0 | 229 | // events' screen coord appear frozen at the last mouse position while |
michael@0 | 230 | // the pointer is locked. |
michael@0 | 231 | static nsIntPoint sLastScreenPoint; |
michael@0 | 232 | |
michael@0 | 233 | // Holds the point in client coords of the last mouse event. Used by |
michael@0 | 234 | // dom::Event::GetClientCoords() to make mouse events' client coords appear |
michael@0 | 235 | // frozen at the last mouse position while the pointer is locked. |
michael@0 | 236 | static CSSIntPoint sLastClientPoint; |
michael@0 | 237 | |
michael@0 | 238 | static bool sIsPointerLocked; |
michael@0 | 239 | static nsWeakPtr sPointerLockedElement; |
michael@0 | 240 | static nsWeakPtr sPointerLockedDoc; |
michael@0 | 241 | |
michael@0 | 242 | protected: |
michael@0 | 243 | /** |
michael@0 | 244 | * Prefs class capsules preference management. |
michael@0 | 245 | */ |
michael@0 | 246 | class Prefs |
michael@0 | 247 | { |
michael@0 | 248 | public: |
michael@0 | 249 | static bool KeyCausesActivation() { return sKeyCausesActivation; } |
michael@0 | 250 | static bool ClickHoldContextMenu() { return sClickHoldContextMenu; } |
michael@0 | 251 | static int32_t ChromeAccessModifierMask(); |
michael@0 | 252 | static int32_t ContentAccessModifierMask(); |
michael@0 | 253 | |
michael@0 | 254 | static void Init(); |
michael@0 | 255 | static void OnChange(const char* aPrefName, void*); |
michael@0 | 256 | static void Shutdown(); |
michael@0 | 257 | |
michael@0 | 258 | private: |
michael@0 | 259 | static bool sKeyCausesActivation; |
michael@0 | 260 | static bool sClickHoldContextMenu; |
michael@0 | 261 | static int32_t sGenericAccessModifierKey; |
michael@0 | 262 | static int32_t sChromeAccessModifierMask; |
michael@0 | 263 | static int32_t sContentAccessModifierMask; |
michael@0 | 264 | |
michael@0 | 265 | static int32_t GetAccessModifierMask(int32_t aItemType); |
michael@0 | 266 | }; |
michael@0 | 267 | |
michael@0 | 268 | /** |
michael@0 | 269 | * Get appropriate access modifier mask for the aDocShell. Returns -1 if |
michael@0 | 270 | * access key isn't available. |
michael@0 | 271 | */ |
michael@0 | 272 | static int32_t GetAccessModifierMaskFor(nsISupports* aDocShell); |
michael@0 | 273 | |
michael@0 | 274 | void UpdateCursor(nsPresContext* aPresContext, |
michael@0 | 275 | WidgetEvent* aEvent, |
michael@0 | 276 | nsIFrame* aTargetFrame, |
michael@0 | 277 | nsEventStatus* aStatus); |
michael@0 | 278 | /** |
michael@0 | 279 | * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the specified |
michael@0 | 280 | * content. This returns the primary frame for the content (or null |
michael@0 | 281 | * if it goes away during the event). |
michael@0 | 282 | */ |
michael@0 | 283 | nsIFrame* DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent, |
michael@0 | 284 | uint32_t aMessage, |
michael@0 | 285 | nsIContent* aTargetContent, |
michael@0 | 286 | nsIContent* aRelatedContent); |
michael@0 | 287 | /** |
michael@0 | 288 | * Synthesize DOM and frame mouseover and mouseout events from this |
michael@0 | 289 | * MOUSE_MOVE or MOUSE_EXIT event. |
michael@0 | 290 | */ |
michael@0 | 291 | void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent); |
michael@0 | 292 | /** |
michael@0 | 293 | * Tell this ESM and ESMs in parent documents that the mouse is |
michael@0 | 294 | * over some content in this document. |
michael@0 | 295 | */ |
michael@0 | 296 | void NotifyMouseOver(WidgetMouseEvent* aMouseEvent, |
michael@0 | 297 | nsIContent* aContent); |
michael@0 | 298 | /** |
michael@0 | 299 | * Tell this ESM and ESMs in affected child documents that the mouse |
michael@0 | 300 | * has exited this document's currently hovered content. |
michael@0 | 301 | * @param aMouseEvent the event that triggered the mouseout |
michael@0 | 302 | * @param aMovingInto the content node we've moved into. This is used to set |
michael@0 | 303 | * the relatedTarget for mouseout events. Also, if it's non-null |
michael@0 | 304 | * NotifyMouseOut will NOT change the current hover content to null; |
michael@0 | 305 | * in that case the caller is responsible for updating hover state. |
michael@0 | 306 | */ |
michael@0 | 307 | void NotifyMouseOut(WidgetMouseEvent* aMouseEvent, |
michael@0 | 308 | nsIContent* aMovingInto); |
michael@0 | 309 | void GenerateDragDropEnterExit(nsPresContext* aPresContext, |
michael@0 | 310 | WidgetDragEvent* aDragEvent); |
michael@0 | 311 | |
michael@0 | 312 | /** |
michael@0 | 313 | * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper elements wrapper. |
michael@0 | 314 | * If mPointersEnterLeaveHelper does not contain wrapper for pointerId it create new one |
michael@0 | 315 | */ |
michael@0 | 316 | OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent); |
michael@0 | 317 | |
michael@0 | 318 | /** |
michael@0 | 319 | * Fire the dragenter and dragexit/dragleave events when the mouse moves to a |
michael@0 | 320 | * new target. |
michael@0 | 321 | * |
michael@0 | 322 | * @param aRelatedTarget relatedTarget to set for the event |
michael@0 | 323 | * @param aTargetContent target to set for the event |
michael@0 | 324 | * @param aTargetFrame target frame for the event |
michael@0 | 325 | */ |
michael@0 | 326 | void FireDragEnterOrExit(nsPresContext* aPresContext, |
michael@0 | 327 | WidgetDragEvent* aDragEvent, |
michael@0 | 328 | uint32_t aMsg, |
michael@0 | 329 | nsIContent* aRelatedTarget, |
michael@0 | 330 | nsIContent* aTargetContent, |
michael@0 | 331 | nsWeakFrame& aTargetFrame); |
michael@0 | 332 | /** |
michael@0 | 333 | * Update the initial drag session data transfer with any changes that occur |
michael@0 | 334 | * on cloned data transfer objects used for events. |
michael@0 | 335 | */ |
michael@0 | 336 | void UpdateDragDataTransfer(WidgetDragEvent* dragEvent); |
michael@0 | 337 | |
michael@0 | 338 | nsresult SetClickCount(nsPresContext* aPresContext, |
michael@0 | 339 | WidgetMouseEvent* aEvent, |
michael@0 | 340 | nsEventStatus* aStatus); |
michael@0 | 341 | nsresult CheckForAndDispatchClick(nsPresContext* aPresContext, |
michael@0 | 342 | WidgetMouseEvent* aEvent, |
michael@0 | 343 | nsEventStatus* aStatus); |
michael@0 | 344 | void EnsureDocument(nsPresContext* aPresContext); |
michael@0 | 345 | void FlushPendingEvents(nsPresContext* aPresContext); |
michael@0 | 346 | |
michael@0 | 347 | /** |
michael@0 | 348 | * The phases of HandleAccessKey processing. See below. |
michael@0 | 349 | */ |
michael@0 | 350 | typedef enum { |
michael@0 | 351 | eAccessKeyProcessingNormal = 0, |
michael@0 | 352 | eAccessKeyProcessingUp, |
michael@0 | 353 | eAccessKeyProcessingDown |
michael@0 | 354 | } ProcessingAccessKeyState; |
michael@0 | 355 | |
michael@0 | 356 | /** |
michael@0 | 357 | * Access key handling. If there is registered content for the accesskey |
michael@0 | 358 | * given by the key event and modifier mask then call |
michael@0 | 359 | * content.PerformAccesskey(), otherwise call HandleAccessKey() recursively, |
michael@0 | 360 | * on descendant docshells first, then on the ancestor (with |aBubbledFrom| |
michael@0 | 361 | * set to the docshell associated with |this|), until something matches. |
michael@0 | 362 | * |
michael@0 | 363 | * @param aPresContext the presentation context |
michael@0 | 364 | * @param aEvent the key event |
michael@0 | 365 | * @param aStatus the event status |
michael@0 | 366 | * @param aBubbledFrom is used by an ancestor to avoid calling HandleAccessKey() |
michael@0 | 367 | * on the child the call originally came from, i.e. this is the child |
michael@0 | 368 | * that recursively called us in its Up phase. The initial caller |
michael@0 | 369 | * passes |nullptr| here. This is to avoid an infinite loop. |
michael@0 | 370 | * @param aAccessKeyState Normal, Down or Up processing phase (see enums |
michael@0 | 371 | * above). The initial event receiver uses 'normal', then 'down' when |
michael@0 | 372 | * processing children and Up when recursively calling its ancestor. |
michael@0 | 373 | * @param aModifierMask modifier mask for the key event |
michael@0 | 374 | */ |
michael@0 | 375 | void HandleAccessKey(nsPresContext* aPresContext, |
michael@0 | 376 | WidgetKeyboardEvent* aEvent, |
michael@0 | 377 | nsEventStatus* aStatus, |
michael@0 | 378 | nsIDocShellTreeItem* aBubbledFrom, |
michael@0 | 379 | ProcessingAccessKeyState aAccessKeyState, |
michael@0 | 380 | int32_t aModifierMask); |
michael@0 | 381 | |
michael@0 | 382 | bool ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes, |
michael@0 | 383 | bool aIsTrustedEvent); |
michael@0 | 384 | |
michael@0 | 385 | //--------------------------------------------- |
michael@0 | 386 | // DocShell Focus Traversal Methods |
michael@0 | 387 | //--------------------------------------------- |
michael@0 | 388 | |
michael@0 | 389 | nsIContent* GetFocusedContent(); |
michael@0 | 390 | bool IsShellVisible(nsIDocShell* aShell); |
michael@0 | 391 | |
michael@0 | 392 | // These functions are for mousewheel and pixel scrolling |
michael@0 | 393 | |
michael@0 | 394 | class WheelPrefs |
michael@0 | 395 | { |
michael@0 | 396 | public: |
michael@0 | 397 | static WheelPrefs* GetInstance(); |
michael@0 | 398 | static void Shutdown(); |
michael@0 | 399 | |
michael@0 | 400 | /** |
michael@0 | 401 | * ApplyUserPrefsToDelta() overrides the wheel event's delta values with |
michael@0 | 402 | * user prefs. |
michael@0 | 403 | */ |
michael@0 | 404 | void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent); |
michael@0 | 405 | |
michael@0 | 406 | /** |
michael@0 | 407 | * If ApplyUserPrefsToDelta() changed the delta values with customized |
michael@0 | 408 | * prefs, the overflowDelta values would be inflated. |
michael@0 | 409 | * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation. |
michael@0 | 410 | */ |
michael@0 | 411 | void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent); |
michael@0 | 412 | |
michael@0 | 413 | /** |
michael@0 | 414 | * Computes the default action for the aEvent with the prefs. |
michael@0 | 415 | */ |
michael@0 | 416 | enum Action MOZ_ENUM_TYPE(uint8_t) |
michael@0 | 417 | { |
michael@0 | 418 | ACTION_NONE = 0, |
michael@0 | 419 | ACTION_SCROLL, |
michael@0 | 420 | ACTION_HISTORY, |
michael@0 | 421 | ACTION_ZOOM, |
michael@0 | 422 | ACTION_LAST = ACTION_ZOOM |
michael@0 | 423 | }; |
michael@0 | 424 | Action ComputeActionFor(WidgetWheelEvent* aEvent); |
michael@0 | 425 | |
michael@0 | 426 | /** |
michael@0 | 427 | * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be |
michael@0 | 428 | * computed the lineOrPageDelta values. |
michael@0 | 429 | */ |
michael@0 | 430 | bool NeedToComputeLineOrPageDelta(WidgetWheelEvent* aEvent); |
michael@0 | 431 | |
michael@0 | 432 | /** |
michael@0 | 433 | * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should |
michael@0 | 434 | * be rounded down to the page width/height (false) or not (true). |
michael@0 | 435 | */ |
michael@0 | 436 | bool IsOverOnePageScrollAllowedX(WidgetWheelEvent* aEvent); |
michael@0 | 437 | bool IsOverOnePageScrollAllowedY(WidgetWheelEvent* aEvent); |
michael@0 | 438 | |
michael@0 | 439 | private: |
michael@0 | 440 | WheelPrefs(); |
michael@0 | 441 | ~WheelPrefs(); |
michael@0 | 442 | |
michael@0 | 443 | static void OnPrefChanged(const char* aPrefName, void* aClosure); |
michael@0 | 444 | |
michael@0 | 445 | enum Index |
michael@0 | 446 | { |
michael@0 | 447 | INDEX_DEFAULT = 0, |
michael@0 | 448 | INDEX_ALT, |
michael@0 | 449 | INDEX_CONTROL, |
michael@0 | 450 | INDEX_META, |
michael@0 | 451 | INDEX_SHIFT, |
michael@0 | 452 | INDEX_OS, |
michael@0 | 453 | COUNT_OF_MULTIPLIERS |
michael@0 | 454 | }; |
michael@0 | 455 | |
michael@0 | 456 | /** |
michael@0 | 457 | * GetIndexFor() returns the index of the members which should be used for |
michael@0 | 458 | * the aEvent. When only one modifier key of MODIFIER_ALT, |
michael@0 | 459 | * MODIFIER_CONTROL, MODIFIER_META, MODIFIER_SHIFT or MODIFIER_OS is |
michael@0 | 460 | * pressed, returns the index for the modifier. Otherwise, this return the |
michael@0 | 461 | * default index which is used at either no modifier key is pressed or |
michael@0 | 462 | * two or modifier keys are pressed. |
michael@0 | 463 | */ |
michael@0 | 464 | Index GetIndexFor(WidgetWheelEvent* aEvent); |
michael@0 | 465 | |
michael@0 | 466 | /** |
michael@0 | 467 | * GetPrefNameBase() returns the base pref name for aEvent. |
michael@0 | 468 | * It's decided by GetModifierForPref() which modifier should be used for |
michael@0 | 469 | * the aEvent. |
michael@0 | 470 | * |
michael@0 | 471 | * @param aBasePrefName The result, must be "mousewheel.with_*." or |
michael@0 | 472 | * "mousewheel.default.". |
michael@0 | 473 | */ |
michael@0 | 474 | void GetBasePrefName(Index aIndex, nsACString& aBasePrefName); |
michael@0 | 475 | |
michael@0 | 476 | void Init(Index aIndex); |
michael@0 | 477 | |
michael@0 | 478 | void Reset(); |
michael@0 | 479 | |
michael@0 | 480 | /** |
michael@0 | 481 | * If the abosolute values of mMultiplierX and/or mMultiplierY are equals or |
michael@0 | 482 | * larger than this value, the computed scroll amount isn't rounded down to |
michael@0 | 483 | * the page width or height. |
michael@0 | 484 | */ |
michael@0 | 485 | enum { |
michael@0 | 486 | MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000 |
michael@0 | 487 | }; |
michael@0 | 488 | |
michael@0 | 489 | bool mInit[COUNT_OF_MULTIPLIERS]; |
michael@0 | 490 | double mMultiplierX[COUNT_OF_MULTIPLIERS]; |
michael@0 | 491 | double mMultiplierY[COUNT_OF_MULTIPLIERS]; |
michael@0 | 492 | double mMultiplierZ[COUNT_OF_MULTIPLIERS]; |
michael@0 | 493 | Action mActions[COUNT_OF_MULTIPLIERS]; |
michael@0 | 494 | /** |
michael@0 | 495 | * action values overridden by .override_x pref. |
michael@0 | 496 | * If an .override_x value is -1, same as the |
michael@0 | 497 | * corresponding mActions value. |
michael@0 | 498 | */ |
michael@0 | 499 | Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS]; |
michael@0 | 500 | |
michael@0 | 501 | static WheelPrefs* sInstance; |
michael@0 | 502 | }; |
michael@0 | 503 | |
michael@0 | 504 | /** |
michael@0 | 505 | * DeltaDirection is used for specifying whether the called method should |
michael@0 | 506 | * handle vertical delta or horizontal delta. |
michael@0 | 507 | * This is clearer than using bool. |
michael@0 | 508 | */ |
michael@0 | 509 | enum DeltaDirection |
michael@0 | 510 | { |
michael@0 | 511 | DELTA_DIRECTION_X = 0, |
michael@0 | 512 | DELTA_DIRECTION_Y |
michael@0 | 513 | }; |
michael@0 | 514 | |
michael@0 | 515 | struct MOZ_STACK_CLASS EventState |
michael@0 | 516 | { |
michael@0 | 517 | bool mDefaultPrevented; |
michael@0 | 518 | bool mDefaultPreventedByContent; |
michael@0 | 519 | |
michael@0 | 520 | EventState() : |
michael@0 | 521 | mDefaultPrevented(false), mDefaultPreventedByContent(false) |
michael@0 | 522 | { |
michael@0 | 523 | } |
michael@0 | 524 | }; |
michael@0 | 525 | |
michael@0 | 526 | /** |
michael@0 | 527 | * SendLineScrollEvent() dispatches a DOMMouseScroll event for the |
michael@0 | 528 | * WidgetWheelEvent. This method shouldn't be called for non-trusted |
michael@0 | 529 | * wheel event because it's not necessary for compatiblity. |
michael@0 | 530 | * |
michael@0 | 531 | * @param aTargetFrame The event target of wheel event. |
michael@0 | 532 | * @param aEvent The original Wheel event. |
michael@0 | 533 | * @param aState The event which should be set to the dispatching |
michael@0 | 534 | * event. This also returns the dispatched event |
michael@0 | 535 | * state. |
michael@0 | 536 | * @param aDelta The delta value of the event. |
michael@0 | 537 | * @param aDeltaDirection The X/Y direction of dispatching event. |
michael@0 | 538 | */ |
michael@0 | 539 | void SendLineScrollEvent(nsIFrame* aTargetFrame, |
michael@0 | 540 | WidgetWheelEvent* aEvent, |
michael@0 | 541 | EventState& aState, |
michael@0 | 542 | int32_t aDelta, |
michael@0 | 543 | DeltaDirection aDeltaDirection); |
michael@0 | 544 | |
michael@0 | 545 | /** |
michael@0 | 546 | * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the |
michael@0 | 547 | * WidgetWheelEvent. This method shouldn't be called for non-trusted |
michael@0 | 548 | * wheel event because it's not necessary for compatiblity. |
michael@0 | 549 | * |
michael@0 | 550 | * @param aTargetFrame The event target of wheel event. |
michael@0 | 551 | * @param aEvent The original Wheel event. |
michael@0 | 552 | * @param aState The event which should be set to the dispatching |
michael@0 | 553 | * event. This also returns the dispatched event |
michael@0 | 554 | * state. |
michael@0 | 555 | * @param aPixelDelta The delta value of the event. |
michael@0 | 556 | * @param aDeltaDirection The X/Y direction of dispatching event. |
michael@0 | 557 | */ |
michael@0 | 558 | void SendPixelScrollEvent(nsIFrame* aTargetFrame, |
michael@0 | 559 | WidgetWheelEvent* aEvent, |
michael@0 | 560 | EventState& aState, |
michael@0 | 561 | int32_t aPixelDelta, |
michael@0 | 562 | DeltaDirection aDeltaDirection); |
michael@0 | 563 | |
michael@0 | 564 | /** |
michael@0 | 565 | * ComputeScrollTarget() returns the scrollable frame which should be |
michael@0 | 566 | * scrolled. |
michael@0 | 567 | * |
michael@0 | 568 | * @param aTargetFrame The event target of the wheel event. |
michael@0 | 569 | * @param aEvent The handling mouse wheel event. |
michael@0 | 570 | * @param aOptions The options for finding the scroll target. |
michael@0 | 571 | * Callers should use COMPUTE_*. |
michael@0 | 572 | * @return The scrollable frame which should be scrolled. |
michael@0 | 573 | */ |
michael@0 | 574 | // These flags are used in ComputeScrollTarget(). Callers should use |
michael@0 | 575 | // COMPUTE_*. |
michael@0 | 576 | enum |
michael@0 | 577 | { |
michael@0 | 578 | PREFER_MOUSE_WHEEL_TRANSACTION = 1, |
michael@0 | 579 | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 2, |
michael@0 | 580 | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 4, |
michael@0 | 581 | START_FROM_PARENT = 8 |
michael@0 | 582 | }; |
michael@0 | 583 | enum ComputeScrollTargetOptions |
michael@0 | 584 | { |
michael@0 | 585 | // At computing scroll target for legacy mouse events, we should return |
michael@0 | 586 | // first scrollable element even when it's not scrollable to the direction. |
michael@0 | 587 | COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0, |
michael@0 | 588 | // Default action prefers the scrolled element immediately before if it's |
michael@0 | 589 | // still under the mouse cursor. Otherwise, it prefers the nearest |
michael@0 | 590 | // scrollable ancestor which will be scrolled actually. |
michael@0 | 591 | COMPUTE_DEFAULT_ACTION_TARGET = |
michael@0 | 592 | (PREFER_MOUSE_WHEEL_TRANSACTION | |
michael@0 | 593 | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | |
michael@0 | 594 | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS), |
michael@0 | 595 | // Look for the nearest scrollable ancestor which can be scrollable with |
michael@0 | 596 | // aEvent. |
michael@0 | 597 | COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS = |
michael@0 | 598 | (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT), |
michael@0 | 599 | COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS = |
michael@0 | 600 | (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT) |
michael@0 | 601 | }; |
michael@0 | 602 | nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame, |
michael@0 | 603 | WidgetWheelEvent* aEvent, |
michael@0 | 604 | ComputeScrollTargetOptions aOptions); |
michael@0 | 605 | |
michael@0 | 606 | nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame, |
michael@0 | 607 | double aDirectionX, |
michael@0 | 608 | double aDirectionY, |
michael@0 | 609 | WidgetWheelEvent* aEvent, |
michael@0 | 610 | ComputeScrollTargetOptions aOptions); |
michael@0 | 611 | |
michael@0 | 612 | /** |
michael@0 | 613 | * GetScrollAmount() returns the scroll amount in app uints of one line or |
michael@0 | 614 | * one page. If the wheel event scrolls a page, returns the page width and |
michael@0 | 615 | * height. Otherwise, returns line height for both its width and height. |
michael@0 | 616 | * |
michael@0 | 617 | * @param aScrollableFrame A frame which will be scrolled by the event. |
michael@0 | 618 | * The result of ComputeScrollTarget() is |
michael@0 | 619 | * expected for this value. |
michael@0 | 620 | * This can be nullptr if there is no scrollable |
michael@0 | 621 | * frame. Then, this method uses root frame's |
michael@0 | 622 | * line height or visible area's width and height. |
michael@0 | 623 | */ |
michael@0 | 624 | nsSize GetScrollAmount(nsPresContext* aPresContext, |
michael@0 | 625 | WidgetWheelEvent* aEvent, |
michael@0 | 626 | nsIScrollableFrame* aScrollableFrame); |
michael@0 | 627 | |
michael@0 | 628 | /** |
michael@0 | 629 | * DoScrollText() scrolls the scrollable frame for aEvent. |
michael@0 | 630 | */ |
michael@0 | 631 | void DoScrollText(nsIScrollableFrame* aScrollableFrame, |
michael@0 | 632 | WidgetWheelEvent* aEvent); |
michael@0 | 633 | |
michael@0 | 634 | void DoScrollHistory(int32_t direction); |
michael@0 | 635 | void DoScrollZoom(nsIFrame *aTargetFrame, int32_t adjustment); |
michael@0 | 636 | nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv); |
michael@0 | 637 | nsresult ChangeTextSize(int32_t change); |
michael@0 | 638 | nsresult ChangeFullZoom(int32_t change); |
michael@0 | 639 | |
michael@0 | 640 | /** |
michael@0 | 641 | * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll |
michael@0 | 642 | * event. If wheel events are caused by pixel scroll only devices or |
michael@0 | 643 | * the delta values are customized by prefs, this class stores the delta |
michael@0 | 644 | * values and set lineOrPageDelta values. |
michael@0 | 645 | */ |
michael@0 | 646 | class DeltaAccumulator |
michael@0 | 647 | { |
michael@0 | 648 | public: |
michael@0 | 649 | static DeltaAccumulator* GetInstance() |
michael@0 | 650 | { |
michael@0 | 651 | if (!sInstance) { |
michael@0 | 652 | sInstance = new DeltaAccumulator; |
michael@0 | 653 | } |
michael@0 | 654 | return sInstance; |
michael@0 | 655 | } |
michael@0 | 656 | |
michael@0 | 657 | static void Shutdown() |
michael@0 | 658 | { |
michael@0 | 659 | delete sInstance; |
michael@0 | 660 | sInstance = nullptr; |
michael@0 | 661 | } |
michael@0 | 662 | |
michael@0 | 663 | bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; } |
michael@0 | 664 | |
michael@0 | 665 | /** |
michael@0 | 666 | * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents |
michael@0 | 667 | * which are caused if it's needed. And if the accumulated delta becomes a |
michael@0 | 668 | * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically. |
michael@0 | 669 | */ |
michael@0 | 670 | void InitLineOrPageDelta(nsIFrame* aTargetFrame, |
michael@0 | 671 | EventStateManager* aESM, |
michael@0 | 672 | WidgetWheelEvent* aEvent); |
michael@0 | 673 | |
michael@0 | 674 | /** |
michael@0 | 675 | * Reset() resets all members. |
michael@0 | 676 | */ |
michael@0 | 677 | void Reset(); |
michael@0 | 678 | |
michael@0 | 679 | /** |
michael@0 | 680 | * ComputeScrollAmountForDefaultAction() computes the default action's |
michael@0 | 681 | * scroll amount in device pixels with mPendingScrollAmount*. |
michael@0 | 682 | */ |
michael@0 | 683 | nsIntPoint ComputeScrollAmountForDefaultAction( |
michael@0 | 684 | WidgetWheelEvent* aEvent, |
michael@0 | 685 | const nsIntSize& aScrollAmountInDevPixels); |
michael@0 | 686 | |
michael@0 | 687 | private: |
michael@0 | 688 | DeltaAccumulator() : |
michael@0 | 689 | mX(0.0), mY(0.0), mPendingScrollAmountX(0.0), mPendingScrollAmountY(0.0), |
michael@0 | 690 | mHandlingDeltaMode(UINT32_MAX), mHandlingPixelOnlyDevice(false) |
michael@0 | 691 | { |
michael@0 | 692 | } |
michael@0 | 693 | |
michael@0 | 694 | double mX; |
michael@0 | 695 | double mY; |
michael@0 | 696 | |
michael@0 | 697 | // When default action of a wheel event is scroll but some delta values |
michael@0 | 698 | // are ignored because the computed amount values are not integer, the |
michael@0 | 699 | // fractional values are saved by these members. |
michael@0 | 700 | double mPendingScrollAmountX; |
michael@0 | 701 | double mPendingScrollAmountY; |
michael@0 | 702 | |
michael@0 | 703 | TimeStamp mLastTime; |
michael@0 | 704 | |
michael@0 | 705 | uint32_t mHandlingDeltaMode; |
michael@0 | 706 | bool mHandlingPixelOnlyDevice; |
michael@0 | 707 | |
michael@0 | 708 | static DeltaAccumulator* sInstance; |
michael@0 | 709 | }; |
michael@0 | 710 | |
michael@0 | 711 | // end mousewheel functions |
michael@0 | 712 | |
michael@0 | 713 | /* |
michael@0 | 714 | * When a touch gesture is about to start, this function determines what |
michael@0 | 715 | * kind of gesture interaction we will want to use, based on what is |
michael@0 | 716 | * underneath the initial touch point. |
michael@0 | 717 | * Currently it decides between panning (finger scrolling) or dragging |
michael@0 | 718 | * the target element, as well as the orientation to trigger panning and |
michael@0 | 719 | * display visual boundary feedback. The decision is stored back in aEvent. |
michael@0 | 720 | */ |
michael@0 | 721 | void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent, |
michael@0 | 722 | nsIFrame* targetFrame); |
michael@0 | 723 | |
michael@0 | 724 | // routines for the d&d gesture tracking state machine |
michael@0 | 725 | void BeginTrackingDragGesture(nsPresContext* aPresContext, |
michael@0 | 726 | WidgetMouseEvent* aDownEvent, |
michael@0 | 727 | nsIFrame* aDownFrame); |
michael@0 | 728 | void StopTrackingDragGesture(); |
michael@0 | 729 | void GenerateDragGesture(nsPresContext* aPresContext, |
michael@0 | 730 | WidgetMouseEvent* aEvent); |
michael@0 | 731 | |
michael@0 | 732 | /** |
michael@0 | 733 | * Determine which node the drag should be targeted at. |
michael@0 | 734 | * This is either the node clicked when there is a selection, or, for HTML, |
michael@0 | 735 | * the element with a draggable property set to true. |
michael@0 | 736 | * |
michael@0 | 737 | * aSelectionTarget - target to check for selection |
michael@0 | 738 | * aDataTransfer - data transfer object that will contain the data to drag |
michael@0 | 739 | * aSelection - [out] set to the selection to be dragged |
michael@0 | 740 | * aTargetNode - [out] the draggable node, or null if there isn't one |
michael@0 | 741 | */ |
michael@0 | 742 | void DetermineDragTarget(nsPIDOMWindow* aWindow, |
michael@0 | 743 | nsIContent* aSelectionTarget, |
michael@0 | 744 | dom::DataTransfer* aDataTransfer, |
michael@0 | 745 | nsISelection** aSelection, |
michael@0 | 746 | nsIContent** aTargetNode); |
michael@0 | 747 | |
michael@0 | 748 | /* |
michael@0 | 749 | * Perform the default handling for the dragstart/draggesture event and set up a |
michael@0 | 750 | * drag for aDataTransfer if it contains any data. Returns true if a drag has |
michael@0 | 751 | * started. |
michael@0 | 752 | * |
michael@0 | 753 | * aDragEvent - the dragstart/draggesture event |
michael@0 | 754 | * aDataTransfer - the data transfer that holds the data to be dragged |
michael@0 | 755 | * aDragTarget - the target of the drag |
michael@0 | 756 | * aSelection - the selection to be dragged |
michael@0 | 757 | */ |
michael@0 | 758 | bool DoDefaultDragStart(nsPresContext* aPresContext, |
michael@0 | 759 | WidgetDragEvent* aDragEvent, |
michael@0 | 760 | dom::DataTransfer* aDataTransfer, |
michael@0 | 761 | nsIContent* aDragTarget, |
michael@0 | 762 | nsISelection* aSelection); |
michael@0 | 763 | |
michael@0 | 764 | bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nullptr; } |
michael@0 | 765 | /** |
michael@0 | 766 | * Set the fields of aEvent to reflect the mouse position and modifier keys |
michael@0 | 767 | * that were set when the user first pressed the mouse button (stored by |
michael@0 | 768 | * BeginTrackingDragGesture). aEvent->widget must be |
michael@0 | 769 | * mCurrentTarget->GetNearestWidget(). |
michael@0 | 770 | */ |
michael@0 | 771 | void FillInEventFromGestureDown(WidgetMouseEvent* aEvent); |
michael@0 | 772 | |
michael@0 | 773 | nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent); |
michael@0 | 774 | nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent); |
michael@0 | 775 | |
michael@0 | 776 | void DoQuerySelectedText(WidgetQueryContentEvent* aEvent); |
michael@0 | 777 | |
michael@0 | 778 | bool RemoteQueryContentEvent(WidgetEvent* aEvent); |
michael@0 | 779 | dom::TabParent *GetCrossProcessTarget(); |
michael@0 | 780 | bool IsTargetCrossProcess(WidgetGUIEvent* aEvent); |
michael@0 | 781 | |
michael@0 | 782 | bool DispatchCrossProcessEvent(WidgetEvent* aEvent, |
michael@0 | 783 | nsFrameLoader* aRemote, |
michael@0 | 784 | nsEventStatus *aStatus); |
michael@0 | 785 | bool HandleCrossProcessEvent(WidgetEvent* aEvent, |
michael@0 | 786 | nsIFrame* aTargetFrame, |
michael@0 | 787 | nsEventStatus* aStatus); |
michael@0 | 788 | |
michael@0 | 789 | void ReleaseCurrentIMEContentObserver(); |
michael@0 | 790 | |
michael@0 | 791 | private: |
michael@0 | 792 | static inline void DoStateChange(dom::Element* aElement, |
michael@0 | 793 | EventStates aState, bool aAddState); |
michael@0 | 794 | static inline void DoStateChange(nsIContent* aContent, EventStates aState, |
michael@0 | 795 | bool aAddState); |
michael@0 | 796 | static void UpdateAncestorState(nsIContent* aStartNode, |
michael@0 | 797 | nsIContent* aStopBefore, |
michael@0 | 798 | EventStates aState, |
michael@0 | 799 | bool aAddState); |
michael@0 | 800 | static PLDHashOperator ResetLastOverForContent(const uint32_t& aIdx, |
michael@0 | 801 | nsRefPtr<OverOutElementsWrapper>& aChunk, |
michael@0 | 802 | void* aClosure); |
michael@0 | 803 | |
michael@0 | 804 | int32_t mLockCursor; |
michael@0 | 805 | |
michael@0 | 806 | // Last mouse event refPoint (the offset from the widget's origin in |
michael@0 | 807 | // device pixels) when mouse was locked, used to restore mouse position |
michael@0 | 808 | // after unlocking. |
michael@0 | 809 | LayoutDeviceIntPoint mPreLockPoint; |
michael@0 | 810 | |
michael@0 | 811 | // Stores the refPoint of the last synthetic mouse move we dispatched |
michael@0 | 812 | // to re-center the mouse when we were pointer locked. If this is (-1,-1) it |
michael@0 | 813 | // means we've not recently dispatched a centering event. We use this to |
michael@0 | 814 | // detect when we receive the synth event, so we can cancel and not send it |
michael@0 | 815 | // to content. |
michael@0 | 816 | static LayoutDeviceIntPoint sSynthCenteringPoint; |
michael@0 | 817 | |
michael@0 | 818 | nsWeakFrame mCurrentTarget; |
michael@0 | 819 | nsCOMPtr<nsIContent> mCurrentTargetContent; |
michael@0 | 820 | static nsWeakFrame sLastDragOverFrame; |
michael@0 | 821 | |
michael@0 | 822 | // Stores the refPoint (the offset from the widget's origin in device |
michael@0 | 823 | // pixels) of the last mouse event. |
michael@0 | 824 | static LayoutDeviceIntPoint sLastRefPoint; |
michael@0 | 825 | |
michael@0 | 826 | // member variables for the d&d gesture state machine |
michael@0 | 827 | LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates |
michael@0 | 828 | // The content to use as target if we start a d&d (what we drag). |
michael@0 | 829 | nsCOMPtr<nsIContent> mGestureDownContent; |
michael@0 | 830 | // The content of the frame where the mouse-down event occurred. It's the same |
michael@0 | 831 | // as the target in most cases but not always - for example when dragging |
michael@0 | 832 | // an <area> of an image map this is the image. (bug 289667) |
michael@0 | 833 | nsCOMPtr<nsIContent> mGestureDownFrameOwner; |
michael@0 | 834 | // State of keys when the original gesture-down happened |
michael@0 | 835 | Modifiers mGestureModifiers; |
michael@0 | 836 | uint16_t mGestureDownButtons; |
michael@0 | 837 | |
michael@0 | 838 | nsCOMPtr<nsIContent> mLastLeftMouseDownContent; |
michael@0 | 839 | nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent; |
michael@0 | 840 | nsCOMPtr<nsIContent> mLastMiddleMouseDownContent; |
michael@0 | 841 | nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent; |
michael@0 | 842 | nsCOMPtr<nsIContent> mLastRightMouseDownContent; |
michael@0 | 843 | nsCOMPtr<nsIContent> mLastRightMouseDownContentParent; |
michael@0 | 844 | |
michael@0 | 845 | nsCOMPtr<nsIContent> mActiveContent; |
michael@0 | 846 | nsCOMPtr<nsIContent> mHoverContent; |
michael@0 | 847 | static nsCOMPtr<nsIContent> sDragOverContent; |
michael@0 | 848 | nsCOMPtr<nsIContent> mURLTargetContent; |
michael@0 | 849 | |
michael@0 | 850 | nsPresContext* mPresContext; // Not refcnted |
michael@0 | 851 | nsCOMPtr<nsIDocument> mDocument; // Doesn't necessarily need to be owner |
michael@0 | 852 | |
michael@0 | 853 | nsRefPtr<IMEContentObserver> mIMEContentObserver; |
michael@0 | 854 | |
michael@0 | 855 | uint32_t mLClickCount; |
michael@0 | 856 | uint32_t mMClickCount; |
michael@0 | 857 | uint32_t mRClickCount; |
michael@0 | 858 | |
michael@0 | 859 | bool m_haveShutdown; |
michael@0 | 860 | |
michael@0 | 861 | // Time at which we began handling user input. |
michael@0 | 862 | static TimeStamp sHandlingInputStart; |
michael@0 | 863 | |
michael@0 | 864 | nsRefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper; |
michael@0 | 865 | nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper> mPointersEnterLeaveHelper; |
michael@0 | 866 | |
michael@0 | 867 | public: |
michael@0 | 868 | static nsresult UpdateUserActivityTimer(void); |
michael@0 | 869 | // Array for accesskey support |
michael@0 | 870 | nsCOMArray<nsIContent> mAccessKeys; |
michael@0 | 871 | |
michael@0 | 872 | static int32_t sUserInputEventDepth; |
michael@0 | 873 | |
michael@0 | 874 | static bool sNormalLMouseEventInProcess; |
michael@0 | 875 | |
michael@0 | 876 | static EventStateManager* sActiveESM; |
michael@0 | 877 | |
michael@0 | 878 | static void ClearGlobalActiveContent(EventStateManager* aClearer); |
michael@0 | 879 | |
michael@0 | 880 | // Functions used for click hold context menus |
michael@0 | 881 | nsCOMPtr<nsITimer> mClickHoldTimer; |
michael@0 | 882 | void CreateClickHoldTimer(nsPresContext* aPresContext, |
michael@0 | 883 | nsIFrame* aDownFrame, |
michael@0 | 884 | WidgetGUIEvent* aMouseDownEvent); |
michael@0 | 885 | void KillClickHoldTimer(); |
michael@0 | 886 | void FireContextClick(); |
michael@0 | 887 | |
michael@0 | 888 | void SetPointerLock(nsIWidget* aWidget, nsIContent* aElement) ; |
michael@0 | 889 | static void sClickHoldCallback ( nsITimer* aTimer, void* aESM ) ; |
michael@0 | 890 | }; |
michael@0 | 891 | |
michael@0 | 892 | /** |
michael@0 | 893 | * This class is used while processing real user input. During this time, popups |
michael@0 | 894 | * are allowed. For mousedown events, mouse capturing is also permitted. |
michael@0 | 895 | */ |
michael@0 | 896 | class AutoHandlingUserInputStatePusher |
michael@0 | 897 | { |
michael@0 | 898 | public: |
michael@0 | 899 | AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput, |
michael@0 | 900 | WidgetEvent* aEvent, |
michael@0 | 901 | nsIDocument* aDocument); |
michael@0 | 902 | ~AutoHandlingUserInputStatePusher(); |
michael@0 | 903 | |
michael@0 | 904 | protected: |
michael@0 | 905 | bool mIsHandlingUserInput; |
michael@0 | 906 | bool mIsMouseDown; |
michael@0 | 907 | bool mResetFMMouseDownState; |
michael@0 | 908 | |
michael@0 | 909 | private: |
michael@0 | 910 | // Hide so that this class can only be stack-allocated |
michael@0 | 911 | static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nullptr; } |
michael@0 | 912 | static void operator delete(void* /*memory*/) {} |
michael@0 | 913 | }; |
michael@0 | 914 | |
michael@0 | 915 | } // namespace mozilla |
michael@0 | 916 | |
michael@0 | 917 | // Click and double-click events need to be handled even for content that |
michael@0 | 918 | // has no frame. This is required for Web compatibility. |
michael@0 | 919 | #define NS_EVENT_NEEDS_FRAME(event) \ |
michael@0 | 920 | (!(event)->HasPluginActivationEventMessage() && \ |
michael@0 | 921 | (event)->message != NS_MOUSE_CLICK && \ |
michael@0 | 922 | (event)->message != NS_MOUSE_DOUBLECLICK) |
michael@0 | 923 | |
michael@0 | 924 | #endif // mozilla_EventStateManager_h_ |