pass modifier keys to click events (e.g. control | shift etc.)
Review URL: https://codereview.appspot.com/7062054

git-svn-id: http://skia.googlecode.com/svn/trunk@7082 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/views/SkView.cpp b/src/views/SkView.cpp
index 94eb490..0c6c0de 100644
--- a/src/views/SkView.cpp
+++ b/src/views/SkView.cpp
@@ -372,13 +372,12 @@
     }
 }
 
-SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y)
-{
+SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) {
     if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) {
         return NULL;
     }
 
-    if (this->onSendClickToChildren(x, y)) {
+    if (this->onSendClickToChildren(x, y, modi)) {
         F2BIter    iter(this);
         SkView*    child;
 
@@ -389,7 +388,7 @@
                 continue;
             }
 
-            Click* click = child->findClickHandler(p.fX, p.fY);
+            Click* click = child->findClickHandler(p.fX, p.fY, modi);
 
             if (click) {
                 return click;
@@ -397,10 +396,10 @@
         }
     }
 
-    return this->onFindClickHandler(x, y);
+    return this->onFindClickHandler(x, y, modi);
 }
 
-void SkView::DoClickDown(Click* click, int x, int y)
+void SkView::DoClickDown(Click* click, int x, int y, unsigned modi)
 {
     SkASSERT(click);
 
@@ -420,10 +419,11 @@
     click->fPrev = click->fCurr = click->fOrig;
 
     click->fState = Click::kDown_State;
+    click->fModifierKeys = modi;
     target->onClick(click);
 }
 
-void SkView::DoClickMoved(Click* click, int x, int y)
+void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi)
 {
     SkASSERT(click);
 
@@ -443,10 +443,11 @@
     }
 
     click->fState = Click::kMoved_State;
+    click->fModifierKeys = modi;
     target->onClick(click);
 }
 
-void SkView::DoClickUp(Click* click, int x, int y)
+void SkView::DoClickUp(Click* click, int x, int y, unsigned modi)
 {
     SkASSERT(click);
 
@@ -466,6 +467,7 @@
     }
 
     click->fState = Click::kUp_State;
+    click->fModifierKeys = modi;
     target->onClick(click);
 }
 
@@ -489,11 +491,11 @@
 
 void SkView::onSizeChange() {}
 
-bool SkView::onSendClickToChildren(SkScalar x, SkScalar y) {
+bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) {
     return true;
 }
 
-SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y) {
+SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
     return NULL;
 }
 
diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp
index b02631d..0f0d9c1 100644
--- a/src/views/SkWindow.cpp
+++ b/src/views/SkWindow.cpp
@@ -358,12 +358,13 @@
     return false;
 }
 
-bool SkWindow::handleClick(int x, int y, Click::State state, void *owner) {
-    return this->onDispatchClick(x, y, state, owner);
+bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
+                           unsigned modifierKeys) {
+    return this->onDispatchClick(x, y, state, owner, modifierKeys);
 }
 
 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
-        void* owner) {
+                               void* owner, unsigned modifierKeys) {
     bool handled = false;
 
     // First, attempt to find an existing click with this owner.
@@ -382,25 +383,25 @@
                 fClicks.remove(index);
             }
             Click* click = this->findClickHandler(SkIntToScalar(x),
-                    SkIntToScalar(y));
+                                                  SkIntToScalar(y), modifierKeys);
 
             if (click) {
                 click->fOwner = owner;
                 *fClicks.append() = click;
-                SkView::DoClickDown(click, x, y);
+                SkView::DoClickDown(click, x, y, modifierKeys);
                 handled = true;
             }
             break;
         }
         case Click::kMoved_State:
             if (index != -1) {
-                SkView::DoClickMoved(fClicks[index], x, y);
+                SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
                 handled = true;
             }
             break;
         case Click::kUp_State:
             if (index != -1) {
-                SkView::DoClickUp(fClicks[index], x, y);
+                SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
                 delete fClicks[index];
                 fClicks.remove(index);
                 handled = true;
diff --git a/src/views/mac/SkNSView.mm b/src/views/mac/SkNSView.mm
index ffa9d7c..fc82ac4 100644
--- a/src/views/mac/SkNSView.mm
+++ b/src/views/mac/SkNSView.mm
@@ -192,35 +192,68 @@
  //     unichar c = [[event characters] characterAtIndex:0];
 }
 
+static const struct {
+    unsigned    fNSModifierMask;
+    unsigned    fSkModifierMask;
+} gModifierMasks[] = {
+    { NSAlphaShiftKeyMask,  kShift_SkModifierKey },
+    { NSShiftKeyMask,       kShift_SkModifierKey },
+    { NSControlKeyMask,     kControl_SkModifierKey },
+    { NSAlternateKeyMask,   kOption_SkModifierKey },
+    { NSCommandKeyMask,     kCommand_SkModifierKey },
+};
+
+static unsigned convertNSModifiersToSk(NSUInteger nsModi) {
+    unsigned skModi = 0;
+    for (size_t i = 0; i < SK_ARRAY_COUNT(gModifierMasks); ++i) {
+        if (nsModi & gModifierMasks[i].fNSModifierMask) {
+            skModi |= gModifierMasks[i].fSkModifierMask;
+        }
+    }
+    return skModi;
+}
+
 - (void)mouseDown:(NSEvent *)event {
     NSPoint p = [event locationInWindow];
+    unsigned modi = convertNSModifiersToSk([event modifierFlags]);
+
     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
         NSPoint loc = [self convertPoint:p fromView:nil];
-        fWind->handleClick((int) loc.x, (int) loc.y, SkView::Click::kDown_State, self);
+        fWind->handleClick((int) loc.x, (int) loc.y,
+                           SkView::Click::kDown_State, self, modi);
     }
 }
 
 - (void)mouseDragged:(NSEvent *)event {
     NSPoint p = [event locationInWindow];
+    unsigned modi = convertNSModifiersToSk([event modifierFlags]);
+
     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
         NSPoint loc = [self convertPoint:p fromView:nil];
-        fWind->handleClick((int) loc.x, (int) loc.y, SkView::Click::kMoved_State, self);
+        fWind->handleClick((int) loc.x, (int) loc.y,
+                           SkView::Click::kMoved_State, self, modi);
     }
 }
 
 - (void)mouseMoved:(NSEvent *)event {
     NSPoint p = [event locationInWindow];
+    unsigned modi = convertNSModifiersToSk([event modifierFlags]);
+    
     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
         NSPoint loc = [self convertPoint:p fromView:nil];
-        fWind->handleClick((int) loc.x, (int) loc.y, SkView::Click::kMoved_State, self);
+        fWind->handleClick((int) loc.x, (int) loc.y,
+                           SkView::Click::kMoved_State, self, modi);
     }
 }
 
 - (void)mouseUp:(NSEvent *)event {
     NSPoint p = [event locationInWindow];
+    unsigned modi = convertNSModifiersToSk([event modifierFlags]);
+    
     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
         NSPoint loc = [self convertPoint:p fromView:nil];
-        fWind->handleClick((int) loc.x, (int) loc.y, SkView::Click::kUp_State, self);
+        fWind->handleClick((int) loc.x, (int) loc.y,
+                           SkView::Click::kUp_State, self, modi);
     }
 }
 
diff --git a/src/views/mac/SkOSWindow_Mac.mm b/src/views/mac/SkOSWindow_Mac.mm
index a288ae3..01c8677 100644
--- a/src/views/mac/SkOSWindow_Mac.mm
+++ b/src/views/mac/SkOSWindow_Mac.mm
@@ -48,8 +48,9 @@
     return this->INHERITED::onEvent(evt);
 }
 
-bool SkOSWindow::onDispatchClick(int x, int y, Click::State state, void* owner) {
-    return this->INHERITED::onDispatchClick(x, y, state, owner);
+bool SkOSWindow::onDispatchClick(int x, int y, Click::State state, void* owner,
+                                 unsigned modi) {
+    return this->INHERITED::onDispatchClick(x, y, state, owner, modi);
 }
 
 void SkOSWindow::onSetTitle(const char title[]) {
diff --git a/src/views/unix/SkOSWindow_Unix.cpp b/src/views/unix/SkOSWindow_Unix.cpp
index 46a2b3d..6c973e0 100644
--- a/src/views/unix/SkOSWindow_Unix.cpp
+++ b/src/views/unix/SkOSWindow_Unix.cpp
@@ -150,6 +150,11 @@
     XFlush(fUnixWindow.fDisplay);
 }
 
+static unsigned getModifierKeys(const XEvent& evt) {
+//    unsigned xmod = evt.xkey.state;
+    return 0;   // TODO
+}
+
 void SkOSWindow::loop() {
     Display* dsp = fUnixWindow.fDisplay;
     if (NULL == dsp) {
@@ -171,14 +176,17 @@
                 break;
             case ButtonPress:
                 if (evt.xbutton.button == Button1)
-                    this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kDown_State);
+                    this->handleClick(evt.xbutton.x, evt.xbutton.y,
+                              SkView::Click::kDown_State, getModifierKeys(evt));
                 break;
             case ButtonRelease:
                 if (evt.xbutton.button == Button1)
-                    this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kUp_State);
+                    this->handleClick(evt.xbutton.x, evt.xbutton.y,
+                                  SkView::Click::kUp_State, getModifierKeys(evt));
                 break;
             case MotionNotify:
-                this->handleClick(evt.xmotion.x, evt.xmotion.y, SkView::Click::kMoved_State);
+                this->handleClick(evt.xmotion.x, evt.xmotion.y,
+                              SkView::Click::kMoved_State, getModifierKeys(evt));
                 break;
             case KeyPress: {
                 KeySym keysym = XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0);
diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp
index 150be6a..5ae00cb 100644
--- a/src/views/win/SkOSWindow_win.cpp
+++ b/src/views/win/SkOSWindow_win.cpp
@@ -103,6 +103,10 @@
     return kNONE_SkKey;
 }
 
+static unsigned getModifiers(UINT message) {
+    return 0;   // TODO
+}
+
 bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
     switch (message) {
         case WM_KEYDOWN: {
@@ -146,15 +150,18 @@
         } break;
 
         case WM_LBUTTONDOWN:
-            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
+                              Click::kDown_State, getModifiers(message));
             return true;
 
         case WM_MOUSEMOVE:
-            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
+                              Click::kMoved_State, getModifiers(message));
             return true;
 
         case WM_LBUTTONUP:
-            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
+                              Click::kUp_State, getModifiers(message));
             return true;
 
         case WM_EVENT_CALLBACK: