dom/events/EventStateManager.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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_

mercurial