text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "ppapi/cpp/input_event.h"
  
  #include "ppapi/cpp/instance_handle.h"
  #include "ppapi/cpp/module.h"
  #include "ppapi/cpp/module_impl.h"
  #include "ppapi/cpp/point.h"
  #include "ppapi/cpp/touch_point.h"
  #include "ppapi/cpp/var.h"
  
  namespace pp {
  
  namespace {
  
  template <> const char* interface_name<PPB_InputEvent_1_0>() {
    return PPB_INPUT_EVENT_INTERFACE_1_0;
  }
  
  template <> const char* interface_name<PPB_KeyboardInputEvent_1_2>() {
    return PPB_KEYBOARD_INPUT_EVENT_INTERFACE_1_2;
  }
  
  template <> const char* interface_name<PPB_KeyboardInputEvent_1_0>() {
    return PPB_KEYBOARD_INPUT_EVENT_INTERFACE_1_0;
  }
  
  template <> const char* interface_name<PPB_MouseInputEvent_1_1>() {
    return PPB_MOUSE_INPUT_EVENT_INTERFACE_1_1;
  }
  
  template <> const char* interface_name<PPB_WheelInputEvent_1_0>() {
    return PPB_WHEEL_INPUT_EVENT_INTERFACE_1_0;
  }
  
  template <> const char* interface_name<PPB_TouchInputEvent_1_0>() {
    return PPB_TOUCH_INPUT_EVENT_INTERFACE_1_0;
  }
  
  template <> const char* interface_name<PPB_IMEInputEvent_1_0>() {
    return PPB_IME_INPUT_EVENT_INTERFACE_1_0;
  }
  
  }  // namespace
  
  // InputEvent ------------------------------------------------------------------
  
  InputEvent::InputEvent() : Resource() {
  }
  
  InputEvent::InputEvent(PP_Resource input_event_resource) : Resource() {
    // Type check the input event before setting it.
    if (!has_interface<PPB_InputEvent_1_0>())
      return;
    if (get_interface<PPB_InputEvent_1_0>()->IsInputEvent(input_event_resource)) {
      Module::Get()->core()->AddRefResource(input_event_resource);
      PassRefFromConstructor(input_event_resource);
    }
  }
  
  InputEvent::~InputEvent() {
  }
  
  PP_InputEvent_Type InputEvent::GetType() const {
    if (!has_interface<PPB_InputEvent_1_0>())
      return PP_INPUTEVENT_TYPE_UNDEFINED;
    return get_interface<PPB_InputEvent_1_0>()->GetType(pp_resource());
  }
  
  PP_TimeTicks InputEvent::GetTimeStamp() const {
    if (!has_interface<PPB_InputEvent_1_0>())
      return 0.0f;
    return get_interface<PPB_InputEvent_1_0>()->GetTimeStamp(pp_resource());
  }
  
  uint32_t InputEvent::GetModifiers() const {
    if (!has_interface<PPB_InputEvent_1_0>())
      return 0;
    return get_interface<PPB_InputEvent_1_0>()->GetModifiers(pp_resource());
  }
  
  // MouseInputEvent -------------------------------------------------------------
  
  MouseInputEvent::MouseInputEvent() : InputEvent() {
  }
  
  MouseInputEvent::MouseInputEvent(const InputEvent& event) : InputEvent() {
    // Type check the input event before setting it.
    if (!has_interface<PPB_MouseInputEvent_1_1>())
      return;
    if (get_interface<PPB_MouseInputEvent_1_1>()->IsMouseInputEvent(
            event.pp_resource())) {
      Module::Get()->core()->AddRefResource(event.pp_resource());
      PassRefFromConstructor(event.pp_resource());
    }
  }
  
  MouseInputEvent::MouseInputEvent(const InstanceHandle& instance,
                                   PP_InputEvent_Type type,
                                   PP_TimeTicks time_stamp,
                                   uint32_t modifiers,
                                   PP_InputEvent_MouseButton mouse_button,
                                   const Point& mouse_position,
                                   int32_t click_count,
                                   const Point& mouse_movement) {
    // Type check the input event before setting it.
    if (!has_interface<PPB_MouseInputEvent_1_1>())
      return;
    PassRefFromConstructor(get_interface<PPB_MouseInputEvent_1_1>()->Create(
        instance.pp_instance(), type, time_stamp, modifiers, mouse_button,
        &mouse_position.pp_point(), click_count, &mouse_movement.pp_point()));
  }
  
  PP_InputEvent_MouseButton MouseInputEvent::GetButton() const {
    if (!has_interface<PPB_MouseInputEvent_1_1>())
      return PP_INPUTEVENT_MOUSEBUTTON_NONE;
    return get_interface<PPB_MouseInputEvent_1_1>()->GetButton(pp_resource());
  }
  
  Point MouseInputEvent::GetPosition() const {
    if (!has_interface<PPB_MouseInputEvent_1_1>())
      return Point();
    return get_interface<PPB_MouseInputEvent_1_1>()->GetPosition(pp_resource());
  }
  
  int32_t MouseInputEvent::GetClickCount() const {
    if (!has_interface<PPB_MouseInputEvent_1_1>())
      return 0;
    return get_interface<PPB_MouseInputEvent_1_1>()->GetClickCount(pp_resource());
  }
  
  Point MouseInputEvent::GetMovement() const {
    if (!has_interface<PPB_MouseInputEvent_1_1>())
      return Point();
    return get_interface<PPB_MouseInputEvent_1_1>()->GetMovement(pp_resource());
  }
  
  // WheelInputEvent -------------------------------------------------------------
  
  WheelInputEvent::WheelInputEvent() : InputEvent() {
  }
  
  WheelInputEvent::WheelInputEvent(const InputEvent& event) : InputEvent() {
    // Type check the input event before setting it.
    if (!has_interface<PPB_WheelInputEvent_1_0>())
      return;
    if (get_interface<PPB_WheelInputEvent_1_0>()->IsWheelInputEvent(
            event.pp_resource())) {
      Module::Get()->core()->AddRefResource(event.pp_resource());
      PassRefFromConstructor(event.pp_resource());
    }
  }
  
  WheelInputEvent::WheelInputEvent(const InstanceHandle& instance,
                                   PP_TimeTicks time_stamp,
                                   uint32_t modifiers,
                                   const FloatPoint& wheel_delta,
                                   const FloatPoint& wheel_ticks,
                                   bool scroll_by_page) {
    // Type check the input event before setting it.
    if (!has_interface<PPB_WheelInputEvent_1_0>())
      return;
    PassRefFromConstructor(get_interface<PPB_WheelInputEvent_1_0>()->Create(
        instance.pp_instance(), time_stamp, modifiers,
        &wheel_delta.pp_float_point(), &wheel_ticks.pp_float_point(),
        PP_FromBool(scroll_by_page)));
  }
  
  FloatPoint WheelInputEvent::GetDelta() const {
    if (!has_interface<PPB_WheelInputEvent_1_0>())
      return FloatPoint();
    return get_interface<PPB_WheelInputEvent_1_0>()->GetDelta(pp_resource());
  }
  
  FloatPoint WheelInputEvent::GetTicks() const {
    if (!has_interface<PPB_WheelInputEvent_1_0>())
      return FloatPoint();
    return get_interface<PPB_WheelInputEvent_1_0>()->GetTicks(pp_resource());
  }
  
  bool WheelInputEvent::GetScrollByPage() const {
    if (!has_interface<PPB_WheelInputEvent_1_0>())
      return false;
    return PP_ToBool(
        get_interface<PPB_WheelInputEvent_1_0>()->GetScrollByPage(pp_resource()));
  }
  
  // KeyboardInputEvent ----------------------------------------------------------
  
  KeyboardInputEvent::KeyboardInputEvent() : InputEvent() {
  }
  
  KeyboardInputEvent::KeyboardInputEvent(const InputEvent& event) : InputEvent() {
    PP_Bool is_keyboard_event = PP_FALSE;
  
    if (has_interface<PPB_KeyboardInputEvent_1_2>()) {
      is_keyboard_event =
          get_interface<PPB_KeyboardInputEvent_1_2>()->IsKeyboardInputEvent(
              event.pp_resource());
    } else if (has_interface<PPB_KeyboardInputEvent_1_0>()) {
      is_keyboard_event =
          get_interface<PPB_KeyboardInputEvent_1_0>()->IsKeyboardInputEvent(
              event.pp_resource());
    }
  
    if (PP_ToBool(is_keyboard_event)) {
      Module::Get()->core()->AddRefResource(event.pp_resource());
      PassRefFromConstructor(event.pp_resource());
    }
  }
  
  KeyboardInputEvent::KeyboardInputEvent(const InstanceHandle& instance,
                                         PP_InputEvent_Type type,
                                         PP_TimeTicks time_stamp,
                                         uint32_t modifiers,
                                         uint32_t key_code,
                                         const Var& character_text) {
    if (has_interface<PPB_KeyboardInputEvent_1_2>()) {
      PassRefFromConstructor(get_interface<PPB_KeyboardInputEvent_1_2>()->Create(
          instance.pp_instance(), type, time_stamp, modifiers, key_code,
          character_text.pp_var(), Var().pp_var()));
    } else if (has_interface<PPB_KeyboardInputEvent_1_0>()) {
      PassRefFromConstructor(get_interface<PPB_KeyboardInputEvent_1_0>()->Create(
          instance.pp_instance(), type, time_stamp, modifiers, key_code,
          character_text.pp_var()));
    }
  }
  
  KeyboardInputEvent::KeyboardInputEvent(const InstanceHandle& instance,
                                         PP_InputEvent_Type type,
                                         PP_TimeTicks time_stamp,
                                         uint32_t modifiers,
                                         uint32_t key_code,
                                         const Var& character_text,
                                         const Var& code) {
    if (has_interface<PPB_KeyboardInputEvent_1_2>()) {
      PassRefFromConstructor(get_interface<PPB_KeyboardInputEvent_1_2>()->Create(
          instance.pp_instance(), type, time_stamp, modifiers, key_code,
          character_text.pp_var(), code.pp_var()));
    } else if (has_interface<PPB_KeyboardInputEvent_1_0>()) {
      PassRefFromConstructor(get_interface<PPB_KeyboardInputEvent_1_0>()->Create(
          instance.pp_instance(), type, time_stamp, modifiers, key_code,
          character_text.pp_var()));
    }
  }
  
  uint32_t KeyboardInputEvent::GetKeyCode() const {
    if (has_interface<PPB_KeyboardInputEvent_1_2>()) {
      return get_interface<PPB_KeyboardInputEvent_1_2>()->GetKeyCode(
          pp_resource());
    } else if (has_interface<PPB_KeyboardInputEvent_1_0>()) {
      return get_interface<PPB_KeyboardInputEvent_1_0>()->GetKeyCode(
          pp_resource());
    }
    return 0;
  }
  
  Var KeyboardInputEvent::GetCharacterText() const {
    if (has_interface<PPB_KeyboardInputEvent_1_2>()) {
      return Var(PASS_REF,
                 get_interface<PPB_KeyboardInputEvent_1_2>()->GetCharacterText(
                     pp_resource()));
    } else if (has_interface<PPB_KeyboardInputEvent_1_0>()) {
      return Var(PASS_REF,
                 get_interface<PPB_KeyboardInputEvent_1_0>()->GetCharacterText(
                   pp_resource()));
    }
    return Var();
  }
  
  Var KeyboardInputEvent::GetCode() const {
    if (has_interface<PPB_KeyboardInputEvent_1_2>()) {
      return Var(PASS_REF,
                 get_interface<PPB_KeyboardInputEvent_1_2>()->GetCode(
                     pp_resource()));
    }
    return Var();
  }
  
  // TouchInputEvent ------------------------------------------------------------
  TouchInputEvent::TouchInputEvent() : InputEvent() {
  }
  
  TouchInputEvent::TouchInputEvent(const InputEvent& event) : InputEvent() {
    if (!has_interface<PPB_TouchInputEvent_1_0>())
      return;
    // Type check the input event before setting it.
    if (get_interface<PPB_TouchInputEvent_1_0>()->IsTouchInputEvent(
        event.pp_resource())) {
      Module::Get()->core()->AddRefResource(event.pp_resource());
      PassRefFromConstructor(event.pp_resource());
    }
  }
  
  TouchInputEvent::TouchInputEvent(const InstanceHandle& instance,
                                   PP_InputEvent_Type type,
                                   PP_TimeTicks time_stamp,
                                   uint32_t modifiers) {
    // Type check the input event before setting it.
    if (!has_interface<PPB_TouchInputEvent_1_0>())
      return;
    PassRefFromConstructor(get_interface<PPB_TouchInputEvent_1_0>()->Create(
        instance.pp_instance(), type, time_stamp, modifiers));
  }
  
  void TouchInputEvent::AddTouchPoint(PP_TouchListType list,
                                      PP_TouchPoint point) {
    if (!has_interface<PPB_TouchInputEvent_1_0>())
      return;
    get_interface<PPB_TouchInputEvent_1_0>()->AddTouchPoint(pp_resource(), list,
                                                            &point);
  }
  
  uint32_t TouchInputEvent::GetTouchCount(PP_TouchListType list) const {
    if (!has_interface<PPB_TouchInputEvent_1_0>())
      return 0;
    return get_interface<PPB_TouchInputEvent_1_0>()->GetTouchCount(pp_resource(),
                                                                   list);
  }
  
  TouchPoint TouchInputEvent::GetTouchById(PP_TouchListType list,
                                               uint32_t id) const {
    if (!has_interface<PPB_TouchInputEvent_1_0>())
      return TouchPoint();
    return TouchPoint(get_interface<PPB_TouchInputEvent_1_0>()->
                          GetTouchById(pp_resource(), list, id));
  }
  
  TouchPoint TouchInputEvent::GetTouchByIndex(PP_TouchListType list,
                                                  uint32_t index) const {
    if (!has_interface<PPB_TouchInputEvent_1_0>())
      return TouchPoint();
    return TouchPoint(get_interface<PPB_TouchInputEvent_1_0>()->
                          GetTouchByIndex(pp_resource(), list, index));
  }
  
  // IMEInputEvent -------------------------------------------------------
  
  IMEInputEvent::IMEInputEvent() : InputEvent() {
  }
  
  IMEInputEvent::IMEInputEvent(const InputEvent& event) : InputEvent() {
    if (has_interface<PPB_IMEInputEvent_1_0>()) {
      if (get_interface<PPB_IMEInputEvent_1_0>()->IsIMEInputEvent(
              event.pp_resource())) {
        Module::Get()->core()->AddRefResource(event.pp_resource());
        PassRefFromConstructor(event.pp_resource());
      }
    }
  }
  
  IMEInputEvent::IMEInputEvent(
      const InstanceHandle& instance,
      PP_InputEvent_Type type,
      PP_TimeTicks time_stamp,
      const Var& text,
      const std::vector<uint32_t>& segment_offsets,
      int32_t target_segment,
      const std::pair<uint32_t, uint32_t>& selection) : InputEvent() {
    if (!has_interface<PPB_IMEInputEvent_1_0>())
      return;
    uint32_t dummy = 0;
    PassRefFromConstructor(get_interface<PPB_IMEInputEvent_1_0>()->Create(
        instance.pp_instance(), type, time_stamp, text.pp_var(),
        segment_offsets.empty() ? 0 : segment_offsets.size() - 1,
        segment_offsets.empty() ? &dummy : &segment_offsets[0],
        target_segment, selection.first, selection.second));
  }
  
  
  Var IMEInputEvent::GetText() const {
    if (has_interface<PPB_IMEInputEvent_1_0>()) {
      return Var(PASS_REF,
                 get_interface<PPB_IMEInputEvent_1_0>()->GetText(
                     pp_resource()));
    }
    return Var();
  }
  
  uint32_t IMEInputEvent::GetSegmentNumber() const {
    if (has_interface<PPB_IMEInputEvent_1_0>()) {
      return get_interface<PPB_IMEInputEvent_1_0>()->GetSegmentNumber(
          pp_resource());
    }
    return 0;
  }
  
  uint32_t IMEInputEvent::GetSegmentOffset(uint32_t index) const {
    if (has_interface<PPB_IMEInputEvent_1_0>()) {
      return get_interface<PPB_IMEInputEvent_1_0>()->GetSegmentOffset(
          pp_resource(), index);
    }
    return 0;
  }
  
  int32_t IMEInputEvent::GetTargetSegment() const {
    if (has_interface<PPB_IMEInputEvent_1_0>()) {
      return get_interface<PPB_IMEInputEvent_1_0>()->GetTargetSegment(
          pp_resource());
    }
    return 0;
  }
  
  void IMEInputEvent::GetSelection(uint32_t* start, uint32_t* end) const {
    if (has_interface<PPB_IMEInputEvent_1_0>()) {
      get_interface<PPB_IMEInputEvent_1_0>()->GetSelection(pp_resource(),
                                                           start,
                                                           end);
    }
  }
  
  }  // namespace pp
  