예제 #1
0
bool
TopWindow::OnEvent(const SDL_Event &event)
{
  switch (event.type) {
    Window *w;

#if SDL_MAJOR_VERSION < 2
  case SDL_VIDEOEXPOSE:
    invalidated = false;
    Expose();
    return true;
#endif

  case SDL_KEYDOWN:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    if (!w->IsEnabled())
      return false;

#if SDL_MAJOR_VERSION >= 2
    return w->OnKeyDown(event.key.keysym.sym);
#else
    return w->OnKeyDown(event.key.keysym.sym) ||
      (event.key.keysym.unicode != 0 &&
       w->OnCharacter(event.key.keysym.unicode));
#endif

#if SDL_MAJOR_VERSION >= 2
  case SDL_TEXTINPUT:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    if (!w->IsEnabled())
      return false;

    if (event.text.text && *event.text.text) {
      std::pair<unsigned, const char *> next = NextUTF8(event.text.text);
      bool handled = w->OnCharacter(next.first);
      while (next.second) {
        next = NextUTF8(next.second);
        handled = w->OnCharacter(next.first) || handled;
      }
      return handled;
    } else
      return false;
#endif

  case SDL_KEYUP:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    if (!w->IsEnabled())
      return false;

    return w->OnKeyUp(event.key.keysym.sym);

#ifdef HAVE_MULTI_TOUCH
  case SDL_FINGERDOWN:
    if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 2)
      return OnMultiTouchDown();
    else
      return false;

  case SDL_FINGERUP:
    if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 1)
      return OnMultiTouchUp();
    else
      return false;
#endif

  case SDL_MOUSEMOTION:
    // XXX keys
    return OnMouseMove(event.motion.x, event.motion.y, 0);

  case SDL_MOUSEBUTTONDOWN:
#if SDL_MAJOR_VERSION < 2
    if (event.button.button == SDL_BUTTON_WHEELUP)
      return OnMouseWheel(event.button.x, event.button.y, 1);
    else if (event.button.button == SDL_BUTTON_WHEELDOWN)
      return OnMouseWheel(event.button.x, event.button.y, -1);
#endif

    return double_click.Check(RasterPoint(event.button.x, event.button.y))
      ? OnMouseDouble(event.button.x, event.button.y)
      : OnMouseDown(event.button.x, event.button.y);

  case SDL_MOUSEBUTTONUP:
#if SDL_MAJOR_VERSION < 2
    if (event.button.button == SDL_BUTTON_WHEELUP ||
        event.button.button == SDL_BUTTON_WHEELDOWN)
      /* the wheel has already been handled in SDL_MOUSEBUTTONDOWN */
      return false;
#endif

    double_click.Moved(RasterPoint(event.button.x, event.button.y));

    return OnMouseUp(event.button.x, event.button.y);

  case SDL_QUIT:
    return OnClose();

#if SDL_MAJOR_VERSION < 2
  case SDL_VIDEORESIZE:
    Resize(event.resize.w, event.resize.h);
    return true;
#endif

#if SDL_MAJOR_VERSION >= 2
  case SDL_MOUSEWHEEL:
    int x, y;
    SDL_GetMouseState(&x, &y);
    return OnMouseWheel(x, y, event.wheel.y);

  case SDL_WINDOWEVENT:
    switch (event.window.event) {

    case SDL_WINDOWEVENT_RESIZED:
      Resize(event.window.data1, event.window.data2);
      return true;

    case SDL_WINDOWEVENT_RESTORED:
    case SDL_WINDOWEVENT_MOVED:
    case SDL_WINDOWEVENT_SHOWN:
    case SDL_WINDOWEVENT_MAXIMIZED:
      {
        SDL_Window* event_window = SDL_GetWindowFromID(event.window.windowID);
        if (event_window) {
          int w, h;
          SDL_GetWindowSize(event_window, &w, &h);
          if ((w >= 0) && (h >= 0)) {
            Resize(w, h);
          }
        }
      }
      return true;

    case SDL_WINDOWEVENT_EXPOSED:
      invalidated = false;
      Expose();
      return true;
    }
#endif
  }

  return false;
}
예제 #2
0
bool CGenericTouchInputHandler::HandleTouchInput(TouchInput event, float x, float y, int64_t time, int32_t pointer /* = 0 */, float size /* = 0.0f */)
{
  if (time < 0 || pointer < 0 || pointer >= TOUCH_MAX_POINTERS)
    return false;

  CSingleLock lock(m_critical);

  bool result = true;

  m_pointers[pointer].current.x = x;
  m_pointers[pointer].current.y = y;
  m_pointers[pointer].current.time = time;

  switch (event)
  {
    case TouchInputAbort:
    {
      triggerDetectors(event, pointer);

      setGestureState(TouchGestureUnknown);
      for (unsigned int pIndex = 0; pIndex < TOUCH_MAX_POINTERS; pIndex++)
        m_pointers[pIndex].reset();

      OnTouchAbort();
      break;
    }

    case TouchInputDown:
    {
      m_pointers[pointer].down.x = x;
      m_pointers[pointer].down.y = y;
      m_pointers[pointer].down.time = time;
      m_pointers[pointer].moving = false;
      m_pointers[pointer].size = size;

      // If this is the down event of the primary pointer
      // we start by assuming that it's a single touch
      if (pointer == 0)
      {
        // create new gesture detectors
        m_detectors.insert(new CGenericTouchSwipeDetector(this, m_dpi));
        m_detectors.insert(new CGenericTouchPinchDetector(this, m_dpi));
        m_detectors.insert(new CGenericTouchRotateDetector(this, m_dpi));
        triggerDetectors(event, pointer);

        setGestureState(TouchGestureSingleTouch);
        result = OnSingleTouchStart(x, y);

        m_holdTimer->Start(TOUCH_HOLD_TIMEOUT);
      }
      // Otherwise it's the down event of another pointer
      else
      {
        triggerDetectors(event, pointer);

        // If we so far assumed single touch or still have the primary
        // pointer of a previous multi touch pressed down, we can update to multi touch
        if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold ||
            m_gestureState == TouchGestureMultiTouchDone)
        {
          result = OnMultiTouchDown(x, y, pointer);
          m_holdTimer->Stop(true);

          if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold)
            m_holdTimer->Start(TOUCH_HOLD_TIMEOUT);

          setGestureState(TouchGestureMultiTouchStart);
        }
        // Otherwise we should ignore this pointer
        else
        {
          m_pointers[pointer].reset();
          break;
        }
      }
      return result;
    }

    case TouchInputUp:
    {
      // unexpected event => abort
      if (!m_pointers[pointer].valid() ||
          m_gestureState == TouchGestureUnknown)
        break;

      triggerDetectors(event, pointer);

      m_holdTimer->Stop(false);

      // Just a single tap with a pointer
      if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold)
      {
        result = OnSingleTouchEnd(x, y);

        if (m_gestureState == TouchGestureSingleTouch)
          OnTap(x, y, 1);
      }
      // A pan gesture started with a single pointer (ignoring any other pointers)
      else if (m_gestureState == TouchGesturePan)
      {
        float velocityX = 0.0f; // number of pixels per second
        float velocityY = 0.0f; // number of pixels per second
        m_pointers[pointer].velocity(velocityX, velocityY, false);

        result = OnTouchGestureEnd(x, y,
                                   x - m_pointers[pointer].down.x, y - m_pointers[pointer].down.y,
                                   velocityX, velocityY);
      }
      // we are in multi-touch
      else
        result = OnMultiTouchUp(x, y, pointer);

      // If we were in multi touch mode and lifted one pointer
      // we can go into the TouchGestureMultiTouchDone state which will allow
      // the user to go back into multi touch mode without lifting the primary pointer
      if (m_gestureState == TouchGestureMultiTouchStart || m_gestureState == TouchGestureMultiTouchHold || m_gestureState == TouchGestureMultiTouch)
      {
        setGestureState(TouchGestureMultiTouchDone);

        // after lifting the primary pointer, the secondary pointer will
        // become the primary pointer in the next event
        if (pointer == 0)
        {
          m_pointers[0] = m_pointers[1];
          pointer = 1;
        }
      }
      // Otherwise abort
      else
      {
        if (m_gestureState == TouchGestureMultiTouchDone)
        {
          float velocityX = 0.0f; // number of pixels per second
          float velocityY = 0.0f; // number of pixels per second
          m_pointers[pointer].velocity(velocityX, velocityY, false);

          result = OnTouchGestureEnd(x, y,
                                     x - m_pointers[pointer].down.x, y - m_pointers[pointer].down.y,
                                     velocityX, velocityY);

          // if neither of the two pointers moved we have a single tap with multiple pointers
          if (m_gestureStateOld != TouchGestureMultiTouchHold && m_gestureStateOld != TouchGestureMultiTouch)
            OnTap(fabs((m_pointers[0].down.x + m_pointers[1].down.x) / 2),
                        fabs((m_pointers[0].down.y + m_pointers[1].down.y) / 2),
                        2);
        }

        setGestureState(TouchGestureUnknown);
        m_pointers[pointer].reset();
      }

      return result;
    }

    case TouchInputMove:
    {
      // unexpected event => abort
      if (!m_pointers[pointer].valid() ||
          m_gestureState == TouchGestureUnknown ||
          m_gestureState == TouchGestureMultiTouchDone)
        break;

      bool moving = false;
      for (unsigned int index = 0; index < TOUCH_MAX_POINTERS; index++)
      {
        if (m_pointers[index].valid() && m_pointers[index].moving)
        {
          moving = true;
          break;
        }
      }

      if (moving)
      {
        m_holdTimer->Stop();

        // the touch is moving so we start a gesture
        if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureMultiTouchStart)
          result = OnTouchGestureStart(m_pointers[pointer].down.x, m_pointers[pointer].down.y);
      }

      triggerDetectors(event, pointer);

      if (m_gestureState == TouchGestureSingleTouch)
      {
        // Check if the touch has moved far enough to count as movement
        if (!m_pointers[pointer].moving)
          break;

        m_pointers[pointer].last.copy(m_pointers[pointer].down);
        setGestureState(TouchGesturePan);
      }
      else if (m_gestureState == TouchGestureMultiTouchStart)
      {
        setGestureState(TouchGestureMultiTouch);

        // set the starting point
        saveLastTouch();
      }

      float offsetX = x - m_pointers[pointer].last.x;
      float offsetY = y - m_pointers[pointer].last.y;
      float velocityX = 0.0f; // number of pixels per second
      float velocityY = 0.0f; // number of pixels per second
      m_pointers[pointer].velocity(velocityX, velocityY);

      if (m_pointers[pointer].moving &&
         (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold || m_gestureState == TouchGesturePan))
        result = OnSingleTouchMove(x, y, offsetX, offsetY, velocityX, velocityY);

      // Let's see if we have a pan gesture (i.e. the primary and only pointer moving)
      if (m_gestureState == TouchGesturePan)
      {
        result = OnTouchGesturePan(x, y, offsetX, offsetY, velocityX, velocityY);

        m_pointers[pointer].last.x = x;
        m_pointers[pointer].last.y = y;
      }
      else if (m_gestureState == TouchGestureMultiTouch)
      {
        if (moving)
          result = OnMultiTouchMove(x, y,offsetX, offsetY, velocityX, velocityY, pointer);
      }
      else
        break;

      return result;
    }

    default:
      CLog::Log(LOGDEBUG, "CGenericTouchInputHandler: unknown TouchInput");
      break;
  }

  return false;
}
예제 #3
0
bool
TopWindow::OnEvent(const Event &event)
{
  switch (event.type) {
    Window *w;

  case Event::NOP:
  case Event::QUIT:
  case Event::TIMER:
  case Event::USER:
  case Event::CALLBACK:
    break;

  case Event::KEY_DOWN:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    return w->OnKeyDown(event.param);

  case Event::KEY_UP:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    return w->OnKeyUp(event.param);

  case Event::MOUSE_MOTION:
    // XXX keys
    return OnMouseMove(event.point.x, event.point.y, 0);

  case Event::MOUSE_DOWN:
    return double_click.Check(event.point)
      ? OnMouseDouble(event.point.x, event.point.y)
      : OnMouseDown(event.point.x, event.point.y);

  case Event::MOUSE_UP:
    double_click.Moved(event.point);

    return OnMouseUp(event.point.x, event.point.y);

  case Event::MOUSE_WHEEL:
    return OnMouseWheel(event.point.x, event.point.y, (int)event.param);

  case Event::POINTER_DOWN:
    return OnMultiTouchDown();

  case Event::POINTER_UP:
    return OnMultiTouchUp();

  case Event::RESIZE:
    if (!surface_valid)
      /* postpone the resize if we're paused; the real resize will be
         handled by TopWindow::refresh() as soon as XCSoar is
         resumed */
      return true;

    if (unsigned(event.point.x) == GetWidth() &&
        unsigned(event.point.y) == GetHeight())
      /* no-op */
      return true;

    /* it seems the first page flip after a display orientation change
       is ignored on Android (tested on a Dell Streak / Android
       2.2.2); let's do one dummy call before we really draw
       something */
    screen->Flip();

    Resize(event.point.x, event.point.y);
    return true;

  case Event::PAUSE:
    OnPause();
    return true;

  case Event::RESUME:
    OnResume();
    return true;
  }

  return false;
}
예제 #4
0
bool
TopWindow::OnEvent(const SDL_Event &event)
{
  switch (event.type) {
    Window *w;

#if SDL_MAJOR_VERSION < 2
  case SDL_VIDEOEXPOSE:
    invalidated = false;
    Expose();
    return true;
#endif

  case SDL_KEYDOWN:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    if (!w->IsEnabled())
      return false;

#if SDL_MAJOR_VERSION >= 2
    return w->OnKeyDown(event.key.keysym.sym);
#else
    return w->OnKeyDown(event.key.keysym.sym) ||
      (event.key.keysym.unicode != 0 &&
       w->OnCharacter(event.key.keysym.unicode));
#endif

#if SDL_MAJOR_VERSION >= 2
  case SDL_TEXTINPUT:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    if (!w->IsEnabled())
      return false;

    if (*event.text.text) {
      std::pair<unsigned, const char *> next = NextUTF8(event.text.text);
      bool handled = w->OnCharacter(next.first);
      while (next.second) {
        next = NextUTF8(next.second);
        handled = w->OnCharacter(next.first) || handled;
      }
      return handled;
    } else
      return false;
#endif

  case SDL_KEYUP:
    w = GetFocusedWindow();
    if (w == nullptr)
      w = this;

    if (!w->IsEnabled())
      return false;

    return w->OnKeyUp(event.key.keysym.sym);

#ifdef HAVE_MULTI_TOUCH
  case SDL_FINGERDOWN:
    if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 2)
      return OnMultiTouchDown();
    else
      return false;

  case SDL_FINGERUP:
    if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 1)
      return OnMultiTouchUp();
    else
      return false;
#endif

  case SDL_MOUSEMOTION:
    // XXX keys
#ifdef HAVE_HIGHDPI_SUPPORT
    {
      auto x = event.motion.x;
      auto y = event.motion.y;
      PointToReal(x, y);
      return OnMouseMove(x, y, 0);
    }
#else
    return OnMouseMove(event.motion.x, event.motion.y, 0);
#endif

  case SDL_MOUSEBUTTONDOWN:
    {
#if SDL_MAJOR_VERSION < 2
      if (event.button.button == SDL_BUTTON_WHEELUP)
        return OnMouseWheel(event.button.x, event.button.y, 1);
      else if (event.button.button == SDL_BUTTON_WHEELDOWN)
        return OnMouseWheel(event.button.x, event.button.y, -1);
#endif

#ifdef HAVE_HIGHDPI_SUPPORT
      auto x = event.button.x;
      auto y = event.button.y;
      PointToReal(x, y);

      return double_click.Check(RasterPoint(x, y))
        ? OnMouseDouble(x, y)
        : OnMouseDown(x, y);
#else
      return double_click.Check(RasterPoint(event.button.x, event.button.y))
        ? OnMouseDouble(event.button.x, event.button.y)
        : OnMouseDown(event.button.x, event.button.y);
#endif
    }

  case SDL_MOUSEBUTTONUP:
    {
#if SDL_MAJOR_VERSION < 2
      if (event.button.button == SDL_BUTTON_WHEELUP ||
          event.button.button == SDL_BUTTON_WHEELDOWN)
        /* the wheel has already been handled in SDL_MOUSEBUTTONDOWN */
        return false;
#endif

#ifdef HAVE_HIGHDPI_SUPPORT
      auto x = event.button.x;
      auto y = event.button.y;
      PointToReal(x, y);

      double_click.Moved(RasterPoint(x, y));

      return OnMouseUp(x, y);
#else
      double_click.Moved(RasterPoint(event.button.x, event.button.y));

      return OnMouseUp(event.button.x, event.button.y);
#endif
    }

  case SDL_QUIT:
    return OnClose();

#if SDL_MAJOR_VERSION < 2
  case SDL_VIDEORESIZE:
    Resize(event.resize.w, event.resize.h);
    return true;
#endif

#if SDL_MAJOR_VERSION >= 2
  case SDL_MOUSEWHEEL:
    {
      int x, y;
      SDL_GetMouseState(&x, &y);
#ifdef HAVE_HIGHDPI_SUPPORT
      PointToReal(x, y);
#endif
      return OnMouseWheel(x, y, event.wheel.y);
    }

  case SDL_WINDOWEVENT:
    switch (event.window.event) {

    case SDL_WINDOWEVENT_RESIZED:
#ifndef HAVE_HIGHDPI_SUPPORT
      Resize(event.window.data1, event.window.data2);
      return true;
#endif
    case SDL_WINDOWEVENT_RESTORED:
    case SDL_WINDOWEVENT_MOVED:
    case SDL_WINDOWEVENT_SHOWN:
    case SDL_WINDOWEVENT_MAXIMIZED:
      {
        SDL_Window* event_window = SDL_GetWindowFromID(event.window.windowID);
        if (event_window) {
          int w, h;
          SDL_GetWindowSize(event_window, &w, &h);
          if ((w >= 0) && (h >= 0)) {
#ifdef HAVE_HIGHDPI_SUPPORT
            int real_w, real_h;
            SDL_GL_GetDrawableSize(event_window, &real_w, &real_h);
            point_to_real_x = static_cast<float>(real_w) /
                              static_cast<float>(w);
            point_to_real_y = static_cast<float>(real_h) /
                              static_cast<float>(h);
            Resize(real_w, real_h);
#else
            Resize(w, h);
#endif
          }

#if defined(__MACOSX__) && __MACOSX__
          SDL_SysWMinfo *wm_info =
              reinterpret_cast<SDL_SysWMinfo *>(alloca(sizeof(SDL_SysWMinfo)));
          SDL_VERSION(&wm_info->version);
          if ((SDL_GetWindowWMInfo(event_window, wm_info)) &&
              (wm_info->subsystem == SDL_SYSWM_COCOA)) {
            [wm_info->info.cocoa.window
                setCollectionBehavior:
                    NSWindowCollectionBehaviorFullScreenPrimary];
          }
          Invalidate();
#endif
        }
      }
      return true;

    case SDL_WINDOWEVENT_EXPOSED:
      invalidated = false;
      Expose();
      return true;
    }
#endif
  }