Bug 731878 part.3 Set modifiers and buttons of nsMouseEvent on Windows r=jimm
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 25 Apr 2012 12:00:01 +0900
changeset 96435 4d0beaad9f761118e3dbe5a9f88dc12e5ef8e9c8
parent 96434 392cb8e0876ffe17d92184b020e4e6666fa9e3ee
child 96436 a41b3d2b1c9eb6bafcf254ae92910cf30b90b1f5
push id1116
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 19:38:18 +0000
treeherdermozilla-beta@95f959a8b4dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs731878
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 731878 part.3 Set modifiers and buttons of nsMouseEvent on Windows r=jimm
widget/windows/nsNativeDragTarget.cpp
widget/windows/nsWindow.cpp
widget/windows/nsWindowDefs.h
--- a/widget/windows/nsNativeDragTarget.cpp
+++ b/widget/windows/nsNativeDragTarget.cpp
@@ -196,20 +196,19 @@ nsNativeDragTarget::DispatchDragDropEven
     ::ScreenToClient(mHWnd, &cpos);
     event.refPoint.x = cpos.x;
     event.refPoint.y = cpos.y;
   } else {
     event.refPoint.x = 0;
     event.refPoint.y = 0;
   }
 
-  event.isShift   = IsKeyDown(NS_VK_SHIFT);
-  event.isControl = IsKeyDown(NS_VK_CONTROL);
-  event.isMeta    = false;
-  event.isAlt     = IsKeyDown(NS_VK_ALT);
+  nsModifierKeyState modifierKeyState;
+  modifierKeyState.InitInputEvent(event);
+
   event.inputSource = static_cast<nsBaseDragService*>(mDragService)->GetInputSource();
 
   mWindow->DispatchEvent(&event, status);
 }
 
 void
 nsNativeDragTarget::ProcessDrag(PRUint32     aEventType,
                                 DWORD        grfKeyState,
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3790,20 +3790,18 @@ bool nsWindow::DispatchMouseEvent(PRUint
                      : nsMouseEvent::eNormal);
   if (aEventType == NS_CONTEXTMENU && aIsContextMenuKey) {
     nsIntPoint zero(0, 0);
     InitEvent(event, &zero);
   } else {
     InitEvent(event, &eventPoint);
   }
 
-  event.isShift   = IS_VK_DOWN(NS_VK_SHIFT);
-  event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
-  event.isMeta    = false;
-  event.isAlt     = IS_VK_DOWN(NS_VK_ALT);
+  nsModifierKeyState modifierKeyState;
+  modifierKeyState.InitInputEvent(event);
   event.button    = aButton;
   event.inputSource = aInputSource;
 
   nsIntPoint mpScreen = eventPoint + WidgetToScreenOffset();
 
   // Suppress mouse moves caused by widget creation
   if (aEventType == NS_MOUSE_MOVE) 
   {
@@ -5081,16 +5079,18 @@ bool nsWindow::ProcessMessage(UINT msg, 
 
         } else {
           StopFlashing();
 
           sJustGotActivate = true;
           nsMouseEvent event(true, NS_MOUSE_ACTIVATE, this,
                              nsMouseEvent::eReal);
           InitEvent(event);
+          nsModifierKeyState modifierKeyState;
+          modifierKeyState.InitInputEvent(event);
           DispatchWindowEvent(&event);
           if (sSwitchKeyboardLayout && mLastKeyboardLayout)
             ActivateKeyboardLayout(mLastKeyboardLayout, 0);
         }
       }
       break;
       
     case WM_MOUSEACTIVATE:
@@ -6148,16 +6148,18 @@ bool nsWindow::OnTouch(WPARAM wParam, LP
       }
 
       nsPointWin touchPoint;
       touchPoint.x = TOUCH_COORD_TO_PIXEL(pInputs[i].x);
       touchPoint.y = TOUCH_COORD_TO_PIXEL(pInputs[i].y);
       touchPoint.ScreenToClient(mWnd);
 
       nsMozTouchEvent touchEvent(true, msg, this, pInputs[i].dwID);
+      nsModifierKeyState modifierKeyState;
+      modifierKeyState.InitInputEvent(touchEvent);
       touchEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
       touchEvent.refPoint = touchPoint;
 
       nsEventStatus status;
       DispatchEvent(&touchEvent, status);
     }
   }
 
@@ -6214,20 +6216,18 @@ bool nsWindow::OnGesture(WPARAM wParam, 
 
   // Other gestures translate into simple gesture events:
   nsSimpleGestureEvent event(true, 0, this, 0, 0.0);
   if ( !mGesture.ProcessGestureMessage(mWnd, wParam, lParam, event) ) {
     return false; // fall through to DefWndProc
   }
   
   // Polish up and send off the new event
-  event.isShift   = IS_VK_DOWN(NS_VK_SHIFT);
-  event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
-  event.isMeta    = false;
-  event.isAlt     = IS_VK_DOWN(NS_VK_ALT);
+  nsModifierKeyState modifierKeyState;
+  modifierKeyState.InitInputEvent(event);
   event.button    = 0;
   event.time      = ::GetMessageTime();
   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
 
   nsEventStatus status;
   DispatchEvent(&event, status);
   if (status == nsEventStatus_eIgnore) {
     return false; // Ignored, fall through
@@ -7922,30 +7922,95 @@ nsWindow::DealWithPopups(HWND inWnd, UIN
  ** BLOCK: Misc. utility methods and functions.
  **
  ** General use.
  **
  **************************************************************
  **************************************************************/
 
 // nsModifierKeyState used in various character processing. 
-nsModifierKeyState::nsModifierKeyState()
-{
-  mIsShiftDown   = IS_VK_DOWN(NS_VK_SHIFT);
-  mIsControlDown = IS_VK_DOWN(NS_VK_CONTROL);
-  mIsAltDown     = IS_VK_DOWN(NS_VK_ALT);
+void
+nsModifierKeyState::Update()
+{
+  mIsShiftDown   = IS_VK_DOWN(VK_SHIFT);
+  mIsControlDown = IS_VK_DOWN(VK_CONTROL);
+  mIsAltDown     = IS_VK_DOWN(VK_MENU);
+  mIsWinDown     = IS_VK_DOWN(VK_LWIN) || IS_VK_DOWN(VK_RWIN);
+
+  mIsCapsLocked   = (::GetKeyState(VK_CAPITAL) & 1);
+  mIsNumLocked    = (::GetKeyState(VK_NUMLOCK) & 1);
+  mIsScrollLocked = (::GetKeyState(VK_SCROLL) & 1);
 }
 
 void
 nsModifierKeyState::InitInputEvent(nsInputEvent& aInputEvent) const
 {
   aInputEvent.isShift   = mIsShiftDown;
   aInputEvent.isControl = mIsControlDown;
   aInputEvent.isMeta    = false;
   aInputEvent.isAlt     = mIsAltDown;
+
+  switch(aInputEvent.eventStructType) {
+    case NS_MOUSE_EVENT:
+    case NS_MOUSE_SCROLL_EVENT:
+    case NS_DRAG_EVENT:
+    case NS_SIMPLE_GESTURE_EVENT:
+    case NS_MOZTOUCH_EVENT:
+      break;
+    default:
+      return;
+  }
+
+  nsMouseEvent_base& mouseEvent = static_cast<nsMouseEvent_base&>(aInputEvent);
+  mouseEvent.modifiers = 0;
+  if (mIsShiftDown) {
+    mouseEvent.modifiers |= MODIFIER_SHIFT;
+  }
+  if (mIsControlDown) {
+    mouseEvent.modifiers |= MODIFIER_CONTROL;
+  }
+  if (mIsAltDown) {
+    mouseEvent.modifiers |= MODIFIER_ALT;
+  }
+  if (mIsWinDown) {
+    mouseEvent.modifiers |= MODIFIER_WIN;
+  }
+  if (mIsCapsLocked) {
+    mouseEvent.modifiers |= MODIFIER_CAPSLOCK;
+  }
+  if (mIsNumLocked) {
+    mouseEvent.modifiers |= MODIFIER_NUMLOCK;
+  }
+  if (mIsScrollLocked) {
+    mouseEvent.modifiers |= MODIFIER_SCROLL;
+  }
+  // If both Control key and Alt key are pressed, it means AltGr is pressed.
+  // Ideally, we should check whether the current keyboard layout has AltGr
+  // or not.  However, setting AltGr flags for keyboard which doesn't have
+  // AltGr must not be serious bug.  So, it should be OK for now.
+  if (mIsControlDown && mIsAltDown) {
+    mouseEvent.modifiers |= MODIFIER_ALTGRAPH;
+  }
+
+  mouseEvent.buttons = 0;
+  if (::GetKeyState(VK_LBUTTON) < 0) {
+    mouseEvent.buttons |= nsMouseEvent::eLeftButtonFlag;
+  }
+  if (::GetKeyState(VK_RBUTTON) < 0) {
+    mouseEvent.buttons |= nsMouseEvent::eRightButtonFlag;
+  }
+  if (::GetKeyState(VK_MBUTTON) < 0) {
+    mouseEvent.buttons |= nsMouseEvent::eMiddleButtonFlag;
+  }
+  if (::GetKeyState(VK_XBUTTON1) < 0) {
+    mouseEvent.buttons |= nsMouseEvent::e4thButtonFlag;
+  }
+  if (::GetKeyState(VK_XBUTTON2) < 0) {
+    mouseEvent.buttons |= nsMouseEvent::e5thButtonFlag;
+  }
 }
 
 // Note that the result of GetTopLevelWindow method can be different from the
 // result of WinUtils::GetTopLevelHWND().  The result can be non-floating
 // window.  Because our top level window may be contained in another window
 // which is not managed by us.
 nsWindow* nsWindow::GetTopLevelWindow(bool aStopOnDialogOrPopup)
 {
--- a/widget/windows/nsWindowDefs.h
+++ b/widget/windows/nsWindowDefs.h
@@ -256,25 +256,37 @@ struct nsFakeCharMessage {
   }
 };
 
 // Used in char processing
 struct nsModifierKeyState {
   bool mIsShiftDown;
   bool mIsControlDown;
   bool mIsAltDown;
+  bool mIsWinDown;
 
-  nsModifierKeyState();
+  bool mIsCapsLocked;
+  bool mIsNumLocked;
+  bool mIsScrollLocked;
+
+  nsModifierKeyState()
+  {
+    Update();
+  }
   nsModifierKeyState(bool aIsShiftDown, bool aIsControlDown,
-                     bool aIsAltDown) :
-    mIsShiftDown(aIsShiftDown), mIsControlDown(aIsControlDown),
-    mIsAltDown(aIsAltDown)
+                     bool aIsAltDown)
   {
+    Update();
+    mIsShiftDown = aIsShiftDown;
+    mIsControlDown = aIsControlDown;
+    mIsAltDown = aIsAltDown;
   }
 
+  void Update();
+
   void InitInputEvent(nsInputEvent& aInputEvent) const;
 };
 
 // Used for synthesizing events
 struct KeyPair {
   PRUint8 mGeneral;
   PRUint8 mSpecific;
   KeyPair(PRUint32 aGeneral, PRUint32 aSpecific)