Bumping manifests a=b2g-bump
[gecko.git] / widget / windows / WinMouseScrollHandler.h
blobd828f115b2f1b7b181036b34380121f7b956ac56
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_widget_WinMouseScrollHandler_h__
8 #define mozilla_widget_WinMouseScrollHandler_h__
10 #include "nscore.h"
11 #include "nsDebug.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/EventForwards.h"
14 #include "mozilla/TimeStamp.h"
15 #include <windows.h>
17 class nsWindowBase;
18 struct nsIntPoint;
20 namespace mozilla {
21 namespace widget {
23 class ModifierKeyState;
25 struct MSGResult;
27 class MouseScrollHandler {
28 public:
29 static MouseScrollHandler* GetInstance();
31 static void Initialize();
32 static void Shutdown();
34 static bool NeedsMessage(UINT aMsg);
35 static bool ProcessMessage(nsWindowBase* aWidget,
36 UINT msg,
37 WPARAM wParam,
38 LPARAM lParam,
39 MSGResult& aResult);
41 /**
42 * See nsIWidget::SynthesizeNativeMouseScrollEvent() for the detail about
43 * this method.
45 static nsresult SynthesizeNativeMouseScrollEvent(nsWindowBase* aWidget,
46 const nsIntPoint& aPoint,
47 uint32_t aNativeMessage,
48 int32_t aDelta,
49 uint32_t aModifierFlags,
50 uint32_t aAdditionalFlags);
52 /**
53 * IsWaitingInternalMessage() returns true if MouseScrollHandler posted
54 * an internal message for a native mouse wheel message and has not
55 * received it. Otherwise, false.
57 static bool IsWaitingInternalMessage()
59 return sInstance && sInstance->mIsWaitingInternalMessage;
62 private:
63 MouseScrollHandler();
64 ~MouseScrollHandler();
66 bool mIsWaitingInternalMessage;
68 static MouseScrollHandler* sInstance;
70 /**
71 * DispatchEvent() dispatches aEvent on aWidget.
73 * @return TRUE if the event was consumed. Otherwise, FALSE.
75 static bool DispatchEvent(nsWindowBase* aWidget, WidgetGUIEvent& aEvent);
77 /**
78 * InitEvent() initializes the aEvent. If aPoint is null, the result of
79 * GetCurrentMessagePos() will be used.
81 static void InitEvent(nsWindowBase* aWidget,
82 WidgetGUIEvent& aEvent,
83 nsIntPoint* aPoint = nullptr);
85 /**
86 * GetModifierKeyState() returns current modifier key state.
87 * Note that some devices need some hack for the modifier key state.
88 * This method does it automatically.
90 * @param aMessage Handling message.
92 static ModifierKeyState GetModifierKeyState(UINT aMessage);
94 /**
95 * MozGetMessagePos() returns the mouse cursor position when GetMessage()
96 * was called last time. However, if we're sending a native message,
97 * this returns the specified cursor position by
98 * SynthesizeNativeMouseScrollEvent().
100 static POINTS GetCurrentMessagePos();
103 * ProcessNativeMouseWheelMessage() processes WM_MOUSEWHEEL and
104 * WM_MOUSEHWHEEL. Additionally, processes WM_VSCROLL and WM_HSCROLL if they
105 * should be processed as mouse wheel message.
106 * This method posts MOZ_WM_MOUSEVWHEEL, MOZ_WM_MOUSEHWHEEL,
107 * MOZ_WM_VSCROLL or MOZ_WM_HSCROLL if we need to dispatch mouse scroll
108 * events. That avoids deadlock with plugin process.
110 * @param aWidget A window which receives the message.
111 * @param aMessage WM_MOUSEWHEEL, WM_MOUSEHWHEEL, WM_VSCROLL or
112 * WM_HSCROLL.
113 * @param aWParam The wParam value of the message.
114 * @param aLParam The lParam value of the message.
116 void ProcessNativeMouseWheelMessage(nsWindowBase* aWidget,
117 UINT aMessage,
118 WPARAM aWParam,
119 LPARAM aLParam);
122 * ProcessNativeScrollMessage() processes WM_VSCROLL and WM_HSCROLL.
123 * This method just call ProcessMouseWheelMessage() if the message should be
124 * processed as mouse wheel message. Otherwise, dispatches a content
125 * command event.
127 * @param aWidget A window which receives the message.
128 * @param aMessage WM_VSCROLL or WM_HSCROLL.
129 * @param aWParam The wParam value of the message.
130 * @param aLParam The lParam value of the message.
131 * @return TRUE if the message is processed. Otherwise, FALSE.
133 bool ProcessNativeScrollMessage(nsWindowBase* aWidget,
134 UINT aMessage,
135 WPARAM aWParam,
136 LPARAM aLParam);
139 * HandleMouseWheelMessage() processes MOZ_WM_MOUSEVWHEEL and
140 * MOZ_WM_MOUSEHWHEEL which are posted when one of our windows received
141 * WM_MOUSEWHEEL or WM_MOUSEHWHEEL for avoiding deadlock with OOPP.
143 * @param aWidget A window which receives the wheel message.
144 * @param aMessage MOZ_WM_MOUSEWHEEL or MOZ_WM_MOUSEHWHEEL.
145 * @param aWParam The wParam value of the original message.
146 * @param aLParam The lParam value of the original message.
148 void HandleMouseWheelMessage(nsWindowBase* aWidget,
149 UINT aMessage,
150 WPARAM aWParam,
151 LPARAM aLParam);
154 * HandleScrollMessageAsMouseWheelMessage() processes the MOZ_WM_VSCROLL and
155 * MOZ_WM_HSCROLL which are posted when one of mouse windows received
156 * WM_VSCROLL or WM_HSCROLL and user wants them to emulate mouse wheel
157 * message's behavior.
159 * @param aWidget A window which receives the scroll message.
160 * @param aMessage MOZ_WM_VSCROLL or MOZ_WM_HSCROLL.
161 * @param aWParam The wParam value of the original message.
162 * @param aLParam The lParam value of the original message.
164 void HandleScrollMessageAsMouseWheelMessage(nsWindowBase* aWidget,
165 UINT aMessage,
166 WPARAM aWParam,
167 LPARAM aLParam);
170 * ComputeMessagePos() computes the cursor position when the message was
171 * added to the queue.
173 * @param aMessage Handling message.
174 * @param aWParam Handling message's wParam.
175 * @param aLParam Handling message's lParam.
176 * @return Mouse cursor position when the message is added to
177 * the queue or current cursor position if the result of
178 * ::GetMessagePos() is broken.
180 POINT ComputeMessagePos(UINT aMessage,
181 WPARAM aWParam,
182 LPARAM aLParam);
184 class EventInfo {
185 public:
187 * @param aWidget An nsWindow which is handling the event.
188 * @param aMessage Must be WM_MOUSEWHEEL or WM_MOUSEHWHEEL.
190 EventInfo(nsWindowBase* aWidget, UINT aMessage, WPARAM aWParam, LPARAM aLParam);
192 bool CanDispatchWheelEvent() const;
194 int32_t GetNativeDelta() const { return mDelta; }
195 HWND GetWindowHandle() const { return mWnd; }
196 const TimeStamp& GetTimeStamp() const { return mTimeStamp; }
197 bool IsVertical() const { return mIsVertical; }
198 bool IsPositive() const { return (mDelta > 0); }
199 bool IsPage() const { return mIsPage; }
202 * @return Number of lines or pages scrolled per WHEEL_DELTA.
204 int32_t GetScrollAmount() const;
206 protected:
207 EventInfo() :
208 mIsVertical(false), mIsPage(false), mDelta(0), mWnd(nullptr)
212 // TRUE if event is for vertical scroll. Otherwise, FALSE.
213 bool mIsVertical;
214 // TRUE if event scrolls per page, otherwise, FALSE.
215 bool mIsPage;
216 // The native delta value.
217 int32_t mDelta;
218 // The window handle which is handling the event.
219 HWND mWnd;
220 // Timestamp of the event.
221 TimeStamp mTimeStamp;
224 class LastEventInfo : public EventInfo {
225 public:
226 LastEventInfo() :
227 EventInfo(), mAccumulatedDelta(0)
232 * CanContinueTransaction() checks whether the new event can continue the
233 * last transaction or not. Note that if there is no transaction, this
234 * returns true.
236 bool CanContinueTransaction(const EventInfo& aNewEvent);
239 * ResetTransaction() resets the transaction, i.e., the instance forgets
240 * the last event information.
242 void ResetTransaction();
245 * RecordEvent() saves the information of new event.
247 void RecordEvent(const EventInfo& aEvent);
250 * InitWheelEvent() initializes NS_WHEEL_WHEEL event and
251 * recomputes the remaning detla for the event.
252 * This must be called only once during handling a message and after
253 * RecordEvent() is called.
255 * @param aWidget A window which will dispatch the event.
256 * @param aWheelEvent An NS_WHEEL_WHEEL event, this will be
257 * initialized.
258 * @param aModKeyState Current modifier key state.
259 * @return TRUE if the event is ready to dispatch.
260 * Otherwise, FALSE.
262 bool InitWheelEvent(nsWindowBase* aWidget,
263 WidgetWheelEvent& aWheelEvent,
264 const ModifierKeyState& aModKeyState);
266 private:
267 static int32_t RoundDelta(double aDelta);
269 int32_t mAccumulatedDelta;
272 LastEventInfo mLastEventInfo;
274 class SystemSettings {
275 public:
276 SystemSettings() : mInitialized(false) {}
278 void Init();
279 void MarkDirty();
280 void NotifyUserPrefsMayOverrideSystemSettings();
282 int32_t GetScrollAmount(bool aForVertical) const
284 MOZ_ASSERT(mInitialized, "SystemSettings must be initialized");
285 return aForVertical ? mScrollLines : mScrollChars;
288 bool IsPageScroll(bool aForVertical) const
290 MOZ_ASSERT(mInitialized, "SystemSettings must be initialized");
291 return aForVertical ? (mScrollLines == WHEEL_PAGESCROLL) :
292 (mScrollChars == WHEEL_PAGESCROLL);
295 private:
296 bool mInitialized;
297 int32_t mScrollLines;
298 int32_t mScrollChars;
301 SystemSettings mSystemSettings;
303 class UserPrefs {
304 public:
305 UserPrefs();
306 ~UserPrefs();
308 void MarkDirty();
310 bool IsScrollMessageHandledAsWheelMessage()
312 Init();
313 return mScrollMessageHandledAsWheelMessage;
316 int32_t GetOverriddenVerticalScrollAmout()
318 Init();
319 return mOverriddenVerticalScrollAmount;
322 int32_t GetOverriddenHorizontalScrollAmout()
324 Init();
325 return mOverriddenHorizontalScrollAmount;
328 int32_t GetMouseScrollTransactionTimeout()
330 Init();
331 return mMouseScrollTransactionTimeout;
334 private:
335 void Init();
337 static void OnChange(const char* aPrefName, void* aClosure)
339 static_cast<UserPrefs*>(aClosure)->MarkDirty();
342 bool mInitialized;
343 bool mScrollMessageHandledAsWheelMessage;
344 int32_t mOverriddenVerticalScrollAmount;
345 int32_t mOverriddenHorizontalScrollAmount;
346 int32_t mMouseScrollTransactionTimeout;
349 UserPrefs mUserPrefs;
351 class SynthesizingEvent {
352 public:
353 SynthesizingEvent() :
354 mWnd(nullptr), mMessage(0), mWParam(0), mLParam(0),
355 mStatus(NOT_SYNTHESIZING)
359 ~SynthesizingEvent() {}
361 static bool IsSynthesizing();
363 nsresult Synthesize(const POINTS& aCursorPoint, HWND aWnd,
364 UINT aMessage, WPARAM aWParam, LPARAM aLParam,
365 const BYTE (&aKeyStates)[256]);
367 void NativeMessageReceived(nsWindowBase* aWidget, UINT aMessage,
368 WPARAM aWParam, LPARAM aLParam);
370 void NotifyNativeMessageHandlingFinished();
371 void NotifyInternalMessageHandlingFinished();
373 const POINTS& GetCursorPoint() const { return mCursorPoint; }
375 private:
376 POINTS mCursorPoint;
377 HWND mWnd;
378 UINT mMessage;
379 WPARAM mWParam;
380 LPARAM mLParam;
381 BYTE mKeyState[256];
382 BYTE mOriginalKeyState[256];
384 enum Status {
385 NOT_SYNTHESIZING,
386 SENDING_MESSAGE,
387 NATIVE_MESSAGE_RECEIVED,
388 INTERNAL_MESSAGE_POSTED,
390 Status mStatus;
392 #ifdef PR_LOGGING
393 const char* GetStatusName()
395 switch (mStatus) {
396 case NOT_SYNTHESIZING:
397 return "NOT_SYNTHESIZING";
398 case SENDING_MESSAGE:
399 return "SENDING_MESSAGE";
400 case NATIVE_MESSAGE_RECEIVED:
401 return "NATIVE_MESSAGE_RECEIVED";
402 case INTERNAL_MESSAGE_POSTED:
403 return "INTERNAL_MESSAGE_POSTED";
404 default:
405 return "Unknown";
408 #endif
410 void Finish();
411 }; // SynthesizingEvent
413 SynthesizingEvent* mSynthesizingEvent;
415 public:
417 class Device {
418 public:
419 class Elantech {
420 public:
422 * GetDriverMajorVersion() returns the installed driver's major version.
423 * If Elantech's driver was installed, returns 0.
425 static int32_t GetDriverMajorVersion();
428 * IsHelperWindow() checks whether aWnd is a helper window of Elantech's
429 * touchpad. Returns TRUE if so. Otherwise, FALSE.
431 static bool IsHelperWindow(HWND aWnd);
434 * Key message handler for Elantech's hack. Returns TRUE if the message
435 * is consumed by this handler. Otherwise, FALSE.
437 static bool HandleKeyMessage(nsWindowBase* aWidget,
438 UINT aMsg,
439 WPARAM aWParam);
441 static void UpdateZoomUntil();
442 static bool IsZooming();
444 static void Init();
446 static bool IsPinchHackNeeded() { return sUsePinchHack; }
449 private:
450 // Whether to enable the Elantech swipe gesture hack.
451 static bool sUseSwipeHack;
452 // Whether to enable the Elantech pinch-to-zoom gesture hack.
453 static bool sUsePinchHack;
454 static DWORD sZoomUntil;
455 }; // class Elantech
457 class TrackPoint {
458 public:
460 * IsDriverInstalled() returns TRUE if TrackPoint's driver is installed.
461 * Otherwise, returns FALSE.
463 static bool IsDriverInstalled();
464 }; // class TrackPoint
466 class UltraNav {
467 public:
469 * IsObsoleteDriverInstalled() checks whether obsoleted UltraNav
470 * is installed on the environment.
471 * Returns TRUE if it was installed. Otherwise, FALSE.
473 static bool IsObsoleteDriverInstalled();
474 }; // class UltraNav
476 class SetPoint {
477 public:
479 * SetPoint, Logitech's mouse driver, may report wrong cursor position
480 * for WM_MOUSEHWHEEL message. See comment in the implementation for
481 * the detail.
483 static bool IsGetMessagePosResponseValid(UINT aMessage,
484 WPARAM aWParam,
485 LPARAM aLParam);
486 private:
487 static bool sMightBeUsing;
490 static void Init();
492 static bool IsFakeScrollableWindowNeeded()
494 return sFakeScrollableWindowNeeded;
497 private:
499 * Gets the bool value of aPrefName used to enable or disable an input
500 * workaround (like the Trackpoint hack). The pref can take values 0 (for
501 * disabled), 1 (for enabled) or -1 (to automatically detect whether to
502 * enable the workaround).
504 * @param aPrefName The name of the pref.
505 * @param aValueIfAutomatic Whether the given input workaround should be
506 * enabled by default.
508 static bool GetWorkaroundPref(const char* aPrefName,
509 bool aValueIfAutomatic);
511 static bool sFakeScrollableWindowNeeded;
512 }; // class Device
515 } // namespace widget
516 } // namespace mozilla
518 #endif // mozilla_widget_WinMouseScrollHandler_h__