DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (5b81998bb7ab)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef InputData_h__
#define InputData_h__

#include "nsGUIEvent.h"
#include "nsDOMTouchEvent.h"
#include "nsDebug.h"

namespace mozilla {


enum InputType
{
  MULTITOUCH_INPUT,
  PINCHGESTURE_INPUT,
  TAPGESTURE_INPUT
};

class MultiTouchInput;
class PinchGestureInput;
class TapGestureInput;

// This looks unnecessary now, but as we add more and more classes that derive
// from InputType (eventually probably almost as many as nsGUIEvent.h has), it
// will be more and more clear what's going on with a macro that shortens the
// definition of the RTTI functions.
#define INPUTDATA_AS_CHILD_TYPE(type, enumID) \
  const type& As##type() const \
  { \
    NS_ABORT_IF_FALSE(mInputType == enumID, "Invalid cast of InputData."); \
    return (const type&) *this; \
  }

/** Base input data class. Should never be instantiated. */
class InputData
{
public:
  InputType mInputType;
  // Time in milliseconds that this data is relevant to. This only really
  // matters when this data is used as an event. We use uint32_t instead of
  // TimeStamp because it is easier to convert from nsInputEvent. The time is
  // platform-specific but it in the case of B2G and Fennec it is since startup.
  uint32_t mTime;

  INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT)
  INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT)
  INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT)

protected:
  InputData(InputType aInputType, uint32_t aTime)
    : mInputType(aInputType),
      mTime(aTime)
  {


  }
};

/**
 * Data container for a single touch input. Similar to nsDOMTouch, but used in
 * off-main-thread situations. This is more for just storing touch data, whereas
 * nsDOMTouch derives from nsIDOMTouch so it is more useful for dispatching
 * through the DOM (which can only happen on the main thread). nsDOMTouch also
 * bears the problem of storing pointers to nsIWidget instances which can only
 * be used on the main thread, so if instead we used nsDOMTouch and ever set
 * these pointers off-main-thread, Bad Things Can Happen(tm).
 *
 * Note that this doesn't inherit from InputData because this itself is not an
 * event. It is only a container/struct that should have any number of instances
 * within a MultiTouchInput.
 *
 * fixme/bug 775746: Make nsDOMTouch inherit from this class.
 */
class SingleTouchData
{
public:
  SingleTouchData(int32_t aIdentifier,
                  nsIntPoint aScreenPoint,
                  nsIntPoint aRadius,
                  float aRotationAngle,
                  float aForce)
    : mIdentifier(aIdentifier),
      mScreenPoint(aScreenPoint),
      mRadius(aRadius),
      mRotationAngle(aRotationAngle),
      mForce(aForce)
  {


  }

  // A unique number assigned to each SingleTouchData within a MultiTouchInput so
  // that they can be easily distinguished when handling a touch start/move/end.
  int32_t mIdentifier;

  // Point on the screen that the touch hit, in device pixels. They are
  // coordinates on the screen.
  nsIntPoint mScreenPoint;

  // Radius that the touch covers, i.e. if you're using your thumb it will
  // probably be larger than using your pinky, even with the same force.
  // Radius can be different along x and y. For example, if you press down with
  // your entire finger vertically, the y radius will be much larger than the x
  // radius.
  nsIntPoint mRadius;

  float mRotationAngle;

  // How hard the screen is being pressed.
  float mForce;
};

/**
 * Similar to nsTouchEvent, but for use off-main-thread. Also only stores a
 * screen touch point instead of the many different coordinate spaces nsTouchEvent
 * stores its touch point in. This includes a way to initialize itself from an
 * nsTouchEvent by copying all relevant data over. Note that this copying from
 * nsTouchEvent functionality can only be used on the main thread.
 *
 * Stores an array of SingleTouchData.
 */
class MultiTouchInput : public InputData
{
public:
  enum MultiTouchType
  {
    MULTITOUCH_START,
    MULTITOUCH_MOVE,
    MULTITOUCH_END,
    MULTITOUCH_ENTER,
    MULTITOUCH_LEAVE,
    MULTITOUCH_CANCEL
  };

  MultiTouchInput(MultiTouchType aType, uint32_t aTime)
    : InputData(MULTITOUCH_INPUT, aTime),
      mType(aType)
  {


  }

  MultiTouchInput(const nsTouchEvent& aTouchEvent)
    : InputData(MULTITOUCH_INPUT, aTouchEvent.time)
  {
    NS_ABORT_IF_FALSE(NS_IsMainThread(),
                      "Can only copy from nsTouchEvent on main thread");

    switch (aTouchEvent.message) {
      case NS_TOUCH_START:
        mType = MULTITOUCH_START;
        break;
      case NS_TOUCH_MOVE:
        mType = MULTITOUCH_MOVE;
        break;
      case NS_TOUCH_END:
        mType = MULTITOUCH_END;
        break;
      case NS_TOUCH_ENTER:
        mType = MULTITOUCH_ENTER;
        break;
      case NS_TOUCH_LEAVE:
        mType = MULTITOUCH_LEAVE;
        break;
      case NS_TOUCH_CANCEL:
        mType = MULTITOUCH_CANCEL;
        break;
      default:
        NS_WARNING("Did not assign a type to a MultiTouchInput");
        break;
    }

    for (size_t i = 0; i < aTouchEvent.touches.Length(); i++) {
      nsDOMTouch* domTouch = (nsDOMTouch*)(aTouchEvent.touches[i].get());

      // Extract data from weird interfaces.
      int32_t identifier, radiusX, radiusY;
      float rotationAngle, force;
      domTouch->GetIdentifier(&identifier);
      domTouch->GetRadiusX(&radiusX);
      domTouch->GetRadiusY(&radiusY);
      domTouch->GetRotationAngle(&rotationAngle);
      domTouch->GetForce(&force);

      SingleTouchData data(identifier,
                           domTouch->mRefPoint,
                           nsIntPoint(radiusX, radiusY),
                           rotationAngle,
                           force);

      mTouches.AppendElement(data);
    }
  }

  // This conversion from nsMouseEvent to MultiTouchInput is needed because on
  // the B2G emulator we can only receive mouse events, but we need to be able
  // to pan correctly. To do this, we convert the events into a format that the
  // panning code can handle. This code is very limited and only supports
  // SingleTouchData. It also sends garbage for the identifier, radius, force
  // and rotation angle.
  MultiTouchInput(const nsMouseEvent& aMouseEvent)
    : InputData(MULTITOUCH_INPUT, aMouseEvent.time)
  {
    NS_ABORT_IF_FALSE(NS_IsMainThread(),
                      "Can only copy from nsMouseEvent on main thread");
    switch (aMouseEvent.message) {
    case NS_MOUSE_BUTTON_DOWN:
      mType = MULTITOUCH_START;
      break;
    case NS_MOUSE_MOVE:
      mType = MULTITOUCH_MOVE;
      break;
    case NS_MOUSE_BUTTON_UP:
      mType = MULTITOUCH_END;
      break;
    // The mouse pointer has been interrupted in an implementation-specific
    // manner, such as a synchronous event or action cancelling the touch, or a
    // touch point leaving the document window and going into a non-document
    // area capable of handling user interactions.
    case NS_MOUSE_EXIT:
      mType = MULTITOUCH_CANCEL;
      break;
    default:
      NS_WARNING("Did not assign a type to a MultiTouchInput");
      break;
    }

    mTouches.AppendElement(SingleTouchData(0,
                                           aMouseEvent.refPoint,
                                           nsIntPoint(1, 1),
                                           180.0f,
                                           1.0f));
  }

  MultiTouchType mType;
  nsTArray<SingleTouchData> mTouches;
};

/**
 * Encapsulation class for pinch events. In general, these will be generated by
 * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
 * determining whether or not the user was trying to do a gesture.
 */
class PinchGestureInput : public InputData
{
public:
  enum PinchGestureType
  {
    PINCHGESTURE_START,
    PINCHGESTURE_SCALE,
    PINCHGESTURE_END
  };

  PinchGestureInput(PinchGestureType aType,
                    uint32_t aTime,
                    const nsIntPoint& aFocusPoint,
                    float aCurrentSpan,
                    float aPreviousSpan)
    : InputData(PINCHGESTURE_INPUT, aTime),
      mType(aType),
      mFocusPoint(aFocusPoint),
      mCurrentSpan(aCurrentSpan),
      mPreviousSpan(aPreviousSpan)
  {


  }

  PinchGestureType mType;

  // Center point of the pinch gesture. That is, if there are two fingers on the
  // screen, it is their midpoint. In the case of more than two fingers, the
  // point is implementation-specific, but can for example be the midpoint
  // between the very first and very last touch. This is in device pixels and
  // are the coordinates on the screen of this midpoint.
  nsIntPoint mFocusPoint;

  // The distance in device pixels (though as a float for increased precision
  // and because it is the distance along both the x and y axis) between the
  // touches responsible for the pinch gesture.
  float mCurrentSpan;

  // The previous |mCurrentSpan| in the PinchGestureInput preceding this one.
  // This is only really relevant during a PINCHGESTURE_SCALE because when it is
  // of this type then there must have been a history of spans.
  float mPreviousSpan;
};

/**
 * Encapsulation class for tap events. In general, these will be generated by
 * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
 * determining whether or not the user was trying to do a gesture.
 */
class TapGestureInput : public InputData
{
public:
  enum TapGestureType
  {
    TAPGESTURE_LONG,
    TAPGESTURE_UP,
    TAPGESTURE_CONFIRMED,
    TAPGESTURE_DOUBLE,
    TAPGESTURE_CANCEL
  };

  TapGestureInput(TapGestureType aType, uint32_t aTime, const nsIntPoint& aPoint)
    : InputData(TAPGESTURE_INPUT, aTime),
      mType(aType),
      mPoint(aPoint)
  {


  }

  TapGestureType mType;
  nsIntPoint mPoint;
};

}

#endif // InputData_h__