diff options
author | Garrett Brown <themagnificentmrb@gmail.com> | 2018-02-07 21:36:33 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-07 21:36:33 -0800 |
commit | 61febe46913c120ba796243134b2514cbfb5603f (patch) | |
tree | 46346c2ccad2a53e3b662a7c4f2805312dd84512 | |
parent | 42594024405891635ba2001944881e71364c651b (diff) | |
parent | 413167c4f6acacc974cbd9c292b021a607d4d977 (diff) |
Merge pull request #13482 from garbear/mouse-mapping
Games: Mouse remapping support
90 files changed, 2025 insertions, 637 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 184f64e309..bccb29802f 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -17412,7 +17412,13 @@ msgctxt "#35170" msgid "Press a key ({1:d})" msgstr "" -#empty strings from id 35171 to 35199 +#. Name of mouse connected to the computer +#: xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp +msgctxt "#35171" +msgid "Mouse" +msgstr "" + +#empty strings from id 35172 to 35199 #. This string is an early meme from the late 1990's that made fun of the poor translation in the 16-bit game Zero Wing from the late 1980's. DO NOT TRANSLATE! #: system/settings/settings.xml diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h index b50c300a12..75be27eb3a 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h @@ -34,6 +34,10 @@ extern "C" /// @name Peripheral types ///{ + + /*! + * @brief API error codes + */ typedef enum PERIPHERAL_ERROR { PERIPHERAL_NO_ERROR = 0, // no error occurred @@ -45,6 +49,9 @@ extern "C" PERIPHERAL_ERROR_CONNECTION_FAILED = -6, // peripherals are connected, but command was interrupted } PERIPHERAL_ERROR; + /*! + * @brief Peripheral types + */ typedef enum PERIPHERAL_TYPE { PERIPHERAL_TYPE_UNKNOWN, @@ -52,6 +59,9 @@ extern "C" PERIPHERAL_TYPE_KEYBOARD, } PERIPHERAL_TYPE; + /*! + * @brief Information shared between peripherals + */ typedef struct PERIPHERAL_INFO { PERIPHERAL_TYPE type; /*!< @brief type of peripheral */ @@ -63,8 +73,6 @@ extern "C" /*! * @brief Peripheral add-on capabilities. - * If a capability is set to true, then the corresponding methods from - * kodi_peripheral_dll.h need to be implemented. */ typedef struct PERIPHERAL_CAPABILITIES { @@ -77,6 +85,10 @@ extern "C" /// @name Event types ///{ + + /*! + * @brief Types of events that can be sent and received + */ typedef enum PERIPHERAL_EVENT_TYPE { PERIPHERAL_EVENT_TYPE_NONE, /*!< @brief unknown event */ @@ -86,12 +98,18 @@ extern "C" PERIPHERAL_EVENT_TYPE_SET_MOTOR, /*!< @brief set the state for joystick rumble motor */ } PERIPHERAL_EVENT_TYPE; + /*! + * @brief States a button can have + */ typedef enum JOYSTICK_STATE_BUTTON { JOYSTICK_STATE_BUTTON_UNPRESSED = 0x0, /*!< @brief button is released */ JOYSTICK_STATE_BUTTON_PRESSED = 0x1, /*!< @brief button is pressed */ } JOYSTICK_STATE_BUTTON; + /*! + * @brief States a D-pad (also called a hat) can have + */ typedef enum JOYSTICK_STATE_HAT { JOYSTICK_STATE_HAT_UNPRESSED = 0x0, /*!< @brief no directions are pressed */ @@ -106,7 +124,7 @@ extern "C" } JOYSTICK_STATE_HAT; /*! - * @brief value in the closed interval [-1.0, 1.0] + * @brief Axis value in the closed interval [-1.0, 1.0] * * The axis state uses the XInput coordinate system: * - Negative values signify down or to the left @@ -114,13 +132,25 @@ extern "C" */ typedef float JOYSTICK_STATE_AXIS; + /*! + * @brief Motor value in the closed interval [0.0, 1.0] + */ typedef float JOYSTICK_STATE_MOTOR; + /*! + * @brief Event information + */ typedef struct PERIPHERAL_EVENT { - unsigned int peripheral_index; - PERIPHERAL_EVENT_TYPE type; - unsigned int driver_index; + /*! @brief Index of the peripheral handling/receiving the event */ + unsigned int peripheral_index; + + /*! @brief Type of the event used to determine which enum field to access below */ + PERIPHERAL_EVENT_TYPE type; + + /*! @brief The index of the event source */ + unsigned int driver_index; + JOYSTICK_STATE_BUTTON driver_button_state; JOYSTICK_STATE_HAT driver_hat_state; JOYSTICK_STATE_AXIS driver_axis_state; @@ -130,6 +160,10 @@ extern "C" /// @name Joystick types ///{ + + /*! + * @brief Info specific to joystick peripherals + */ typedef struct JOYSTICK_INFO { PERIPHERAL_INFO peripheral; /*!< @brief peripheral info for this joystick */ @@ -142,6 +176,15 @@ extern "C" bool supports_poweroff; /*!< @brief whether the joystick supports being powered off */ } ATTRIBUTE_PACKED JOYSTICK_INFO; + /*! + * @brief Driver input primitives + * + * Mapping lower-level driver values to higher-level controller features is + * non-injective; two triggers can share a single axis. + * + * To handle this, driver values are subdivided into "primitives" that map + * injectively to higher-level features. + */ typedef enum JOYSTICK_DRIVER_PRIMITIVE_TYPE { JOYSTICK_DRIVER_PRIMITIVE_TYPE_UNKNOWN, @@ -150,13 +193,21 @@ extern "C" JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS, JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR, JOYSTICK_DRIVER_PRIMITIVE_TYPE_KEY, + JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOUSE_BUTTON, + JOYSTICK_DRIVER_PRIMITIVE_TYPE_RELPOINTER_DIRECTION, } JOYSTICK_DRIVER_PRIMITIVE_TYPE; + /*! + * @brief Button primitive + */ typedef struct JOYSTICK_DRIVER_BUTTON { int index; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_BUTTON; + /*! + * @brief Hat direction + */ typedef enum JOYSTICK_DRIVER_HAT_DIRECTION { JOYSTICK_DRIVER_HAT_UNKNOWN, @@ -166,12 +217,18 @@ extern "C" JOYSTICK_DRIVER_HAT_DOWN, } JOYSTICK_DRIVER_HAT_DIRECTION; + /*! + * @brief Hat direction primitive + */ typedef struct JOYSTICK_DRIVER_HAT { int index; JOYSTICK_DRIVER_HAT_DIRECTION direction; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_HAT; + /*! + * @brief Semiaxis direction + */ typedef enum JOYSTICK_DRIVER_SEMIAXIS_DIRECTION { JOYSTICK_DRIVER_SEMIAXIS_NEGATIVE = -1, /*!< @brief negative half of the axis */ @@ -179,6 +236,9 @@ extern "C" JOYSTICK_DRIVER_SEMIAXIS_POSITIVE = 1, /*!< @brief positive half of the axis */ } JOYSTICK_DRIVER_SEMIAXIS_DIRECTION; + /*! + * @brief Semiaxis primitive + */ typedef struct JOYSTICK_DRIVER_SEMIAXIS { int index; @@ -187,16 +247,70 @@ extern "C" unsigned int range; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_SEMIAXIS; + /*! + * @brief Motor primitive + */ typedef struct JOYSTICK_DRIVER_MOTOR { int index; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_MOTOR; + /*! + * @brief Keyboard key primitive + */ typedef struct JOYSTICK_DRIVER_KEY { char keycode[16]; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_KEY; + /*! + * @brief Mouse buttons + */ + typedef enum JOYSTICK_DRIVER_MOUSE_INDEX + { + JOYSTICK_DRIVER_MOUSE_INDEX_UNKNOWN, + JOYSTICK_DRIVER_MOUSE_INDEX_LEFT, + JOYSTICK_DRIVER_MOUSE_INDEX_RIGHT, + JOYSTICK_DRIVER_MOUSE_INDEX_MIDDLE, + JOYSTICK_DRIVER_MOUSE_INDEX_BUTTON4, + JOYSTICK_DRIVER_MOUSE_INDEX_BUTTON5, + JOYSTICK_DRIVER_MOUSE_INDEX_WHEEL_UP, + JOYSTICK_DRIVER_MOUSE_INDEX_WHEEL_DOWN, + JOYSTICK_DRIVER_MOUSE_INDEX_HORIZ_WHEEL_LEFT, + JOYSTICK_DRIVER_MOUSE_INDEX_HORIZ_WHEEL_RIGHT, + } JOYSTICK_DRIVER_MOUSE_INDEX; + + /*! + * @brief Mouse button primitive + */ + typedef struct JOYSTICK_DRIVER_MOUSE_BUTTON + { + JOYSTICK_DRIVER_MOUSE_INDEX button; + } ATTRIBUTE_PACKED JOYSTICK_DRIVER_MOUSE_BUTTON; + + /*! + * @brief Relative pointer direction + */ + typedef enum JOYSTICK_DRIVER_RELPOINTER_DIRECTION + { + JOYSTICK_DRIVER_RELPOINTER_UNKNOWN, + JOYSTICK_DRIVER_RELPOINTER_LEFT, + JOYSTICK_DRIVER_RELPOINTER_RIGHT, + JOYSTICK_DRIVER_RELPOINTER_UP, + JOYSTICK_DRIVER_RELPOINTER_DOWN, + } JOYSTICK_DRIVER_RELPOINTER_DIRECTION; + + /*! + * @brief Relative pointer direction primitive + */ + typedef struct JOYSTICK_DRIVER_RELPOINTER + { + JOYSTICK_DRIVER_RELPOINTER_DIRECTION direction; + } ATTRIBUTE_PACKED JOYSTICK_DRIVER_RELPOINTER; + + /*! + * @brief Driver primitive struct + */ typedef struct JOYSTICK_DRIVER_PRIMITIVE { JOYSTICK_DRIVER_PRIMITIVE_TYPE type; @@ -207,9 +321,17 @@ extern "C" struct JOYSTICK_DRIVER_SEMIAXIS semiaxis; struct JOYSTICK_DRIVER_MOTOR motor; struct JOYSTICK_DRIVER_KEY key; + struct JOYSTICK_DRIVER_MOUSE_BUTTON mouse; + struct JOYSTICK_DRIVER_RELPOINTER relpointer; }; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_PRIMITIVE; + /*! + * @brief Controller feature + * + * Controller features are an abstraction over driver values. Each feature + * maps to one or more driver primitives. + */ typedef enum JOYSTICK_FEATURE_TYPE { JOYSTICK_FEATURE_TYPE_UNKNOWN, @@ -224,9 +346,12 @@ extern "C" JOYSTICK_FEATURE_TYPE_KEY, } JOYSTICK_FEATURE_TYPE; + /*! + * @brief Indices used to access a feature's driver primitives + */ typedef enum JOYSTICK_FEATURE_PRIMITIVE { - // Scalar feature + // Scalar feature (a button, hat direction or semiaxis) JOYSTICK_SCALAR_PRIMITIVE = 0, // Analog stick @@ -254,10 +379,22 @@ extern "C" // Key JOYSTICK_KEY_PRIMITIVE = 0, + // Mouse button + JOYSTICK_MOUSE_BUTTON = 0, + + // Relative pointer direction + JOYSTICK_RELPOINTER_UP = 0, + JOYSTICK_RELPOINTER_DOWN = 1, + JOYSTICK_RELPOINTER_RIGHT = 2, + JOYSTICK_RELPOINTER_LEFT = 3, + // Maximum number of primitives JOYSTICK_PRIMITIVE_MAX = 4, } JOYSTICK_FEATURE_PRIMITIVE; + /*! + * @brief Mapping between higher-level controller feature and its driver primitives + */ typedef struct JOYSTICK_FEATURE { char* name; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h index 98f3e0074b..c2efc05701 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h @@ -164,62 +164,70 @@ namespace addon class PeripheralEvent { public: - PeripheralEvent(void) : - m_event() + PeripheralEvent(void) { } PeripheralEvent(unsigned int peripheralIndex, unsigned int buttonIndex, JOYSTICK_STATE_BUTTON state) : - m_event() + m_type(PERIPHERAL_EVENT_TYPE_DRIVER_BUTTON), + m_peripheralIndex(peripheralIndex), + m_driverIndex(buttonIndex), + m_buttonState(state) { - SetType(PERIPHERAL_EVENT_TYPE_DRIVER_BUTTON); - SetPeripheralIndex(peripheralIndex); - SetDriverIndex(buttonIndex); - SetButtonState(state); } PeripheralEvent(unsigned int peripheralIndex, unsigned int hatIndex, JOYSTICK_STATE_HAT state) : - m_event() + m_type(PERIPHERAL_EVENT_TYPE_DRIVER_HAT), + m_peripheralIndex(peripheralIndex), + m_driverIndex(hatIndex), + m_hatState(state) { - SetType(PERIPHERAL_EVENT_TYPE_DRIVER_HAT); - SetPeripheralIndex(peripheralIndex); - SetDriverIndex(hatIndex); - SetHatState(state); } PeripheralEvent(unsigned int peripheralIndex, unsigned int axisIndex, JOYSTICK_STATE_AXIS state) : - m_event() + m_type(PERIPHERAL_EVENT_TYPE_DRIVER_AXIS), + m_peripheralIndex(peripheralIndex), + m_driverIndex(axisIndex), + m_axisState(state) { - SetType(PERIPHERAL_EVENT_TYPE_DRIVER_AXIS); - SetPeripheralIndex(peripheralIndex); - SetDriverIndex(axisIndex); - SetAxisState(state); } explicit PeripheralEvent(const PERIPHERAL_EVENT& event) : - m_event(event) - { - } - - PERIPHERAL_EVENT_TYPE Type(void) const { return m_event.type; } - unsigned int PeripheralIndex(void) const { return m_event.peripheral_index; } - unsigned int DriverIndex(void) const { return m_event.driver_index; } - JOYSTICK_STATE_BUTTON ButtonState(void) const { return m_event.driver_button_state; } - JOYSTICK_STATE_HAT HatState(void) const { return m_event.driver_hat_state; } - JOYSTICK_STATE_AXIS AxisState(void) const { return m_event.driver_axis_state; } - JOYSTICK_STATE_MOTOR MotorState(void) const { return m_event.motor_state; } - - void SetType(PERIPHERAL_EVENT_TYPE type) { m_event.type = type; } - void SetPeripheralIndex(unsigned int index) { m_event.peripheral_index = index; } - void SetDriverIndex(unsigned int index) { m_event.driver_index = index; } - void SetButtonState(JOYSTICK_STATE_BUTTON state) { m_event.driver_button_state = state; } - void SetHatState(JOYSTICK_STATE_HAT state) { m_event.driver_hat_state = state; } - void SetAxisState(JOYSTICK_STATE_AXIS state) { m_event.driver_axis_state = state; } - void SetMotorState(JOYSTICK_STATE_MOTOR state) { m_event.motor_state = state; } + m_type(event.type), + m_peripheralIndex(event.peripheral_index), + m_driverIndex(event.driver_index), + m_buttonState(event.driver_button_state), + m_hatState(event.driver_hat_state), + m_axisState(event.driver_axis_state), + m_motorState(event.motor_state) + { + } + + PERIPHERAL_EVENT_TYPE Type(void) const { return m_type; } + unsigned int PeripheralIndex(void) const { return m_peripheralIndex; } + unsigned int DriverIndex(void) const { return m_driverIndex; } + JOYSTICK_STATE_BUTTON ButtonState(void) const { return m_buttonState; } + JOYSTICK_STATE_HAT HatState(void) const { return m_hatState; } + JOYSTICK_STATE_AXIS AxisState(void) const { return m_axisState; } + JOYSTICK_STATE_MOTOR MotorState(void) const { return m_motorState; } + + void SetType(PERIPHERAL_EVENT_TYPE type) { m_type = type; } + void SetPeripheralIndex(unsigned int index) { m_peripheralIndex = index; } + void SetDriverIndex(unsigned int index) { m_driverIndex = index; } + void SetButtonState(JOYSTICK_STATE_BUTTON state) { m_buttonState = state; } + void SetHatState(JOYSTICK_STATE_HAT state) { m_hatState = state; } + void SetAxisState(JOYSTICK_STATE_AXIS state) { m_axisState = state; } + void SetMotorState(JOYSTICK_STATE_MOTOR state) { m_motorState = state; } void ToStruct(PERIPHERAL_EVENT& event) const { - event = m_event; + event.type = m_type; + event.peripheral_index = m_peripheralIndex; + event.driver_index = m_driverIndex; + event.driver_button_state = m_buttonState; + event.driver_hat_state = m_hatState; + event.driver_axis_state = m_axisState; + event.motor_state = m_motorState; } static void FreeStruct(PERIPHERAL_EVENT& event) @@ -228,7 +236,13 @@ namespace addon } private: - PERIPHERAL_EVENT m_event; + PERIPHERAL_EVENT_TYPE m_type = PERIPHERAL_EVENT_TYPE_NONE; + unsigned int m_peripheralIndex = 0; + unsigned int m_driverIndex = 0; + JOYSTICK_STATE_BUTTON m_buttonState = JOYSTICK_STATE_BUTTON_UNPRESSED; + JOYSTICK_STATE_HAT m_hatState = JOYSTICK_STATE_HAT_UNPRESSED; + JOYSTICK_STATE_AXIS m_axisState = 0.0f; + JOYSTICK_STATE_MOTOR m_motorState = 0.0f; }; typedef PeripheralVector<PeripheralEvent, PERIPHERAL_EVENT> PeripheralEvents; @@ -298,9 +312,6 @@ namespace addon unsigned int MotorCount(void) const { return m_motorCount; } bool SupportsPowerOff(void) const { return m_supportsPowerOff; } - // Derived property: Counts are unknown if all are zero - bool AreElementCountsKnown(void) const { return m_buttonCount != 0 || m_hatCount != 0 || m_axisCount != 0; } - void SetProvider(const std::string& provider) { m_provider = provider; } void SetRequestedPort(int requestedPort) { m_requestedPort = requestedPort; } void SetButtonCount(unsigned int buttonCount) { m_buttonCount = buttonCount; } @@ -352,6 +363,9 @@ namespace addon * 2) a hat direction * 3) a semiaxis (either the positive or negative half of an axis) * 4) a motor + * 5) a keyboard key + * 6) a mouse button + * 7) a relative pointer direction * * The type determines the fields in use: * @@ -370,6 +384,15 @@ namespace addon * * Motor: * - driver index + * + * Key: + * - key code + * + * Mouse button: + * - driver index + * + * Relative pointer direction: + * - relative pointer direction */ struct DriverPrimitive { @@ -383,7 +406,8 @@ namespace addon m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), m_center(0), m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN), - m_range(1) + m_range(1), + m_relPointerDirection(JOYSTICK_DRIVER_RELPOINTER_UNKNOWN) { } @@ -397,12 +421,13 @@ namespace addon m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), m_center(0), m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN), - m_range(1) + m_range(1), + m_relPointerDirection(JOYSTICK_DRIVER_RELPOINTER_UNKNOWN) { } /*! - * \brief Construct a driver primitive representing a button + * \brief Construct a driver primitive representing a joystick button */ static DriverPrimitive CreateButton(unsigned int buttonIndex) { @@ -419,7 +444,8 @@ namespace addon m_hatDirection(direction), m_center(0), m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN), - m_range(1) + m_range(1), + m_relPointerDirection(JOYSTICK_DRIVER_RELPOINTER_UNKNOWN) { } @@ -433,7 +459,8 @@ namespace addon m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), m_center(center), m_semiAxisDirection(direction), - m_range(range) + m_range(range), + m_relPointerDirection(JOYSTICK_DRIVER_RELPOINTER_UNKNOWN) { } @@ -455,7 +482,31 @@ namespace addon m_center(0), m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN), m_range(1), - m_keycode(std::move(keycode)) + m_keycode(std::move(keycode)), + m_relPointerDirection(JOYSTICK_DRIVER_RELPOINTER_UNKNOWN) + { + } + + /*! + * \brief Construct a driver primitive representing a mouse button + */ + static DriverPrimitive CreateMouseButton(JOYSTICK_DRIVER_MOUSE_INDEX buttonIndex) + { + return DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOUSE_BUTTON, static_cast<unsigned int>(buttonIndex)); + } + + /*! + * \brief Construct a driver primitive representing one of the four + * direction in which a relative pointer can move + */ + DriverPrimitive(JOYSTICK_DRIVER_RELPOINTER_DIRECTION direction) : + m_type(JOYSTICK_DRIVER_PRIMITIVE_TYPE_RELPOINTER_DIRECTION), + m_driverIndex(0), + m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), + m_center(0), + m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN), + m_range(1), + m_relPointerDirection(direction) { } @@ -465,7 +516,8 @@ namespace addon m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), m_center(0), m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN), - m_range(1) + m_range(1), + m_relPointerDirection(JOYSTICK_DRIVER_RELPOINTER_UNKNOWN) { switch (m_type) { @@ -498,6 +550,16 @@ namespace addon m_keycode = primitive.key.keycode; break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOUSE_BUTTON: + { + m_driverIndex = primitive.mouse.button; + break; + } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_RELPOINTER_DIRECTION: + { + m_relPointerDirection = primitive.relpointer.direction; + break; + } default: break; } @@ -510,6 +572,8 @@ namespace addon JOYSTICK_DRIVER_SEMIAXIS_DIRECTION SemiAxisDirection(void) const { return m_semiAxisDirection; } unsigned int Range(void) const { return m_range; } const std::string& Keycode(void) const { return m_keycode; } + JOYSTICK_DRIVER_MOUSE_INDEX MouseIndex(void) const { return static_cast<JOYSTICK_DRIVER_MOUSE_INDEX>(m_driverIndex); } + JOYSTICK_DRIVER_RELPOINTER_DIRECTION RelPointerDirection(void) const { return m_relPointerDirection; } bool operator==(const DriverPrimitive& other) const { @@ -518,7 +582,6 @@ namespace addon switch (m_type) { case JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON: - case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR: { return m_driverIndex == other.m_driverIndex; } @@ -538,6 +601,18 @@ namespace addon { return m_keycode == other.m_keycode; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR: + { + return m_driverIndex == other.m_driverIndex; + } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOUSE_BUTTON: + { + return m_driverIndex == other.m_driverIndex; + } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_RELPOINTER_DIRECTION: + { + return m_relPointerDirection == other.m_relPointerDirection; + } default: break; } @@ -581,6 +656,16 @@ namespace addon driver_primitive.key.keycode[size - 1] = '\0'; break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOUSE_BUTTON: + { + driver_primitive.mouse.button = static_cast<JOYSTICK_DRIVER_MOUSE_INDEX>(m_driverIndex); + break; + } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_RELPOINTER_DIRECTION: + { + driver_primitive.relpointer.direction = m_relPointerDirection; + break; + } default: break; } @@ -599,6 +684,7 @@ namespace addon JOYSTICK_DRIVER_SEMIAXIS_DIRECTION m_semiAxisDirection; unsigned int m_range; std::string m_keycode; + JOYSTICK_DRIVER_RELPOINTER_DIRECTION m_relPointerDirection; }; typedef PeripheralVector<DriverPrimitive, JOYSTICK_DRIVER_PRIMITIVE> DriverPrimitives; @@ -705,4 +791,3 @@ namespace addon } /* namespace addon */ } /* namespace kodi */ - diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h index 6501b43458..691dd5ee43 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h @@ -166,6 +166,16 @@ bool HasFeature(const char* controller_id, const char* feature_name); bool EnableKeyboard(bool enable, const game_controller* controller); /*! + * \brief Enable/disable mouse input using the specified controller + * + * \param enable True to enable input, false otherwise + * \param controller The controller info if enabling, or unused if disabling + * + * \return True if mouse input was enabled, false otherwise + */ +bool EnableMouse(bool enable, const game_controller* controller); + +/*! * \brief Notify the add-on of an input event * * \param event The input event @@ -260,6 +270,7 @@ void __declspec(dllexport) get_addon(void* ptr) pClient->toAddon.UpdatePort = UpdatePort; pClient->toAddon.HasFeature = HasFeature; pClient->toAddon.EnableKeyboard = EnableKeyboard; + pClient->toAddon.EnableMouse = EnableMouse; pClient->toAddon.InputEvent = InputEvent; pClient->toAddon.SerializeSize = SerializeSize; pClient->toAddon.Serialize = Serialize; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h index d54ee22b0c..54196afa01 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h @@ -162,7 +162,6 @@ typedef enum GAME_HW_CONTEXT_TYPE typedef enum GAME_INPUT_PORT { GAME_INPUT_PORT_JOYSTICK_START = 0, // Non-negative values are for joystick ports - GAME_INPUT_PORT_MOUSE = -2, } GAME_INPUT_PORT; typedef enum GAME_INPUT_EVENT_SOURCE @@ -502,6 +501,7 @@ typedef struct KodiToAddonFuncTable_Game void (__cdecl* UpdatePort)(int, bool, const game_controller*); bool (__cdecl* HasFeature)(const char* controller_id, const char* feature_name); bool (__cdecl* EnableKeyboard)(bool, const game_controller*); + bool (__cdecl* EnableMouse)(bool, const game_controller*); bool (__cdecl* InputEvent)(const game_input_event*); size_t (__cdecl* SerializeSize)(void); GAME_ERROR (__cdecl* Serialize)(uint8_t*, size_t); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h index f547ff72c9..0e3c9e31a4 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h @@ -91,8 +91,8 @@ #define ADDON_INSTANCE_VERSION_AUDIOENCODER_XML_ID "kodi.binary.instance.audioencoder" #define ADDON_INSTANCE_VERSION_AUDIOENCODER_DEPENDS "addon-instance/AudioEncoder.h" -#define ADDON_INSTANCE_VERSION_GAME "1.0.34" -#define ADDON_INSTANCE_VERSION_GAME_MIN "1.0.34" +#define ADDON_INSTANCE_VERSION_GAME "1.0.35" +#define ADDON_INSTANCE_VERSION_GAME_MIN "1.0.35" #define ADDON_INSTANCE_VERSION_GAME_XML_ID "kodi.binary.instance.game" #define ADDON_INSTANCE_VERSION_GAME_DEPENDS "kodi_game_dll.h" \ "kodi_game_types.h" \ @@ -108,7 +108,7 @@ #define ADDON_INSTANCE_VERSION_INPUTSTREAM_XML_ID "kodi.binary.instance.inputstream" #define ADDON_INSTANCE_VERSION_INPUTSTREAM_DEPENDS "addon-instance/Inputstream.h" -#define ADDON_INSTANCE_VERSION_PERIPHERAL "1.3.6" +#define ADDON_INSTANCE_VERSION_PERIPHERAL "1.3.7" #define ADDON_INSTANCE_VERSION_PERIPHERAL_MIN "1.3.4" #define ADDON_INSTANCE_VERSION_PERIPHERAL_XML_ID "kodi.binary.instance.peripheral" #define ADDON_INSTANCE_VERSION_PERIPHERAL_DEPENDS "addon-instance/Peripheral.h" \ diff --git a/xbmc/games/GameServices.cpp b/xbmc/games/GameServices.cpp index e6a4d5c90c..b58a620b6f 100644 --- a/xbmc/games/GameServices.cpp +++ b/xbmc/games/GameServices.cpp @@ -58,6 +58,11 @@ ControllerPtr CGameServices::GetDefaultKeyboard() return m_controllerManager.GetDefaultKeyboard(); } +ControllerPtr CGameServices::GetDefaultMouse() +{ + return m_controllerManager.GetDefaultMouse(); +} + ControllerVector CGameServices::GetControllers() { return m_controllerManager.GetControllers(); diff --git a/xbmc/games/GameServices.h b/xbmc/games/GameServices.h index 300cbec644..466c3f0e88 100644 --- a/xbmc/games/GameServices.h +++ b/xbmc/games/GameServices.h @@ -58,6 +58,7 @@ namespace GAME ControllerPtr GetController(const std::string& controllerId); ControllerPtr GetDefaultController(); ControllerPtr GetDefaultKeyboard(); + ControllerPtr GetDefaultMouse(); ControllerVector GetControllers(); std::string GetSavestatesFolder() const; diff --git a/xbmc/games/addons/input/GameClientInput.cpp b/xbmc/games/addons/input/GameClientInput.cpp index 6b95c719fc..a1809ae73a 100644 --- a/xbmc/games/addons/input/GameClientInput.cpp +++ b/xbmc/games/addons/input/GameClientInput.cpp @@ -31,7 +31,6 @@ #include "guilib/GUIWindowManager.h" #include "guilib/WindowIDs.h" #include "input/joysticks/JoystickTypes.h" -#include "input/InputManager.h" #include "peripherals/Peripherals.h" #include "peripherals/PeripheralTypes.h" //! @todo //#include "threads/SingleLock.h" @@ -251,34 +250,74 @@ void CGameClientInput::CloseKeyboard() void CGameClientInput::OpenMouse() { - m_mouse.reset(new CGameClientMouse(m_gameClient, m_struct.toAddon, &CServiceBroker::GetInputManager())); + using namespace JOYSTICK; - CSingleLock lock(m_clientAccess); + //! @todo Move to player manager + PERIPHERALS::PeripheralVector mice; + CServiceBroker::GetPeripherals().GetPeripheralsWithFeature(mice, PERIPHERALS::FEATURE_MOUSE); - if (m_gameClient.Initialized()) - { - std::string strId = m_mouse->ControllerID(); + if (mice.empty()) + return; - game_controller controllerStruct = { strId.c_str() }; + CGameServices& gameServices = CServiceBroker::GetGameServices(); - try { m_struct.toAddon.UpdatePort(GAME_INPUT_PORT_MOUSE, true, &controllerStruct); } - catch (...) { m_gameClient.LogException("UpdatePort()"); } + ControllerPtr controller = gameServices.GetDefaultMouse(); //! @todo + + std::string controllerId = controller->ID(); + + game_controller controllerStruct{}; + + controllerStruct.controller_id = controllerId.c_str(); + controllerStruct.digital_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::DIGITAL); + controllerStruct.analog_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::ANALOG); + controllerStruct.analog_stick_count = controller->FeatureCount(FEATURE_TYPE::ANALOG_STICK); + controllerStruct.accelerometer_count = controller->FeatureCount(FEATURE_TYPE::ACCELEROMETER); + controllerStruct.key_count = controller->FeatureCount(FEATURE_TYPE::KEY); + controllerStruct.rel_pointer_count = controller->FeatureCount(FEATURE_TYPE::RELPOINTER); + controllerStruct.abs_pointer_count = controller->FeatureCount(FEATURE_TYPE::ABSPOINTER); + controllerStruct.motor_count = controller->FeatureCount(FEATURE_TYPE::MOTOR); + + bool bSuccess = false; + + { + CSingleLock lock(m_clientAccess); + + if (m_gameClient.Initialized()) + { + try + { + bSuccess = m_struct.toAddon.EnableMouse(true, &controllerStruct); + } + catch (...) + { + m_gameClient.LogException("EnableMouse()"); + } + } } + + if (bSuccess) + m_mouse.reset(new CGameClientMouse(m_gameClient, controllerId, m_struct.toAddon, mice.at(0).get())); } void CGameClientInput::CloseMouse() { + m_mouse.reset(); + { CSingleLock lock(m_clientAccess); if (m_gameClient.Initialized()) { - try { m_struct.toAddon.UpdatePort(GAME_INPUT_PORT_MOUSE, false, nullptr); } - catch (...) { m_gameClient.LogException("UpdatePort()"); } + try + { + m_struct.toAddon.EnableMouse(false, nullptr); + } + catch (...) + { + m_gameClient.LogException("EnableMouse()"); + } } } - - m_mouse.reset(); } bool CGameClientInput::SetRumble(unsigned int port, const std::string& feature, float magnitude) diff --git a/xbmc/games/addons/input/GameClientMouse.cpp b/xbmc/games/addons/input/GameClientMouse.cpp index 98adb6ca18..1a37d8995a 100644 --- a/xbmc/games/addons/input/GameClientMouse.cpp +++ b/xbmc/games/addons/input/GameClientMouse.cpp @@ -26,17 +26,21 @@ #include "input/Key.h" #include "utils/log.h" +#include <utility> + using namespace KODI; using namespace GAME; CGameClientMouse::CGameClientMouse(const CGameClient &gameClient, + std::string controllerId, const KodiToAddonFuncTable_Game &dllStruct, MOUSE::IMouseInputProvider *inputProvider) : m_gameClient(gameClient), + m_controllerId(std::move(controllerId)), m_dllStruct(dllStruct), - m_inputProvider(inputProvider), - m_controllerId(inputProvider->RegisterMouseHandler(this)) + m_inputProvider(inputProvider) { + inputProvider->RegisterMouseHandler(this, false); } CGameClientMouse::~CGameClientMouse() @@ -59,10 +63,12 @@ bool CGameClientMouse::OnMotion(const std::string& relpointer, int dx, int dy) bool bHandled = false; + const std::string controllerId = ControllerID(); + game_input_event event; event.type = GAME_INPUT_EVENT_RELATIVE_POINTER; - event.port = GAME_INPUT_PORT_MOUSE; + event.port = -1; //! @todo Remove in port refactor event.controller_id = m_controllerId.c_str(); event.feature_name = relpointer.c_str(); event.rel_pointer.x = dx; @@ -93,7 +99,7 @@ bool CGameClientMouse::OnButtonPress(const std::string& button) game_input_event event; event.type = GAME_INPUT_EVENT_DIGITAL_BUTTON; - event.port = GAME_INPUT_PORT_MOUSE; + event.port = -1; //! @todo Remove in port refactor event.controller_id = m_controllerId.c_str(); event.feature_name = button.c_str(); event.digital_button.pressed = true; @@ -115,7 +121,7 @@ void CGameClientMouse::OnButtonRelease(const std::string& button) game_input_event event; event.type = GAME_INPUT_EVENT_DIGITAL_BUTTON; - event.port = GAME_INPUT_PORT_MOUSE; + event.port = -1; //! @todo Remove in port refactor event.controller_id = m_controllerId.c_str(); event.feature_name = button.c_str(); event.digital_button.pressed = false; diff --git a/xbmc/games/addons/input/GameClientMouse.h b/xbmc/games/addons/input/GameClientMouse.h index c5d253ea37..39043371ec 100644 --- a/xbmc/games/addons/input/GameClientMouse.h +++ b/xbmc/games/addons/input/GameClientMouse.h @@ -46,10 +46,12 @@ namespace GAME /*! * \brief Constructor registers for mouse events at CInputManager. * \param gameClient The game client implementation. + * \param controllerId The controller profile used for input * \param dllStruct The emulator or game to which the events are sent. * \param inputProvider The interface providing us with mouse input. */ CGameClientMouse(const CGameClient &gameClient, + std::string controllerId, const KodiToAddonFuncTable_Game &dllStruct, MOUSE::IMouseInputProvider *inputProvider); @@ -67,9 +69,9 @@ namespace GAME private: // Construction parameters const CGameClient &m_gameClient; + const std::string m_controllerId; const KodiToAddonFuncTable_Game &m_dllStruct; MOUSE::IMouseInputProvider *const m_inputProvider; - const std::string m_controllerId; }; } } diff --git a/xbmc/games/controllers/ControllerIDs.h b/xbmc/games/controllers/ControllerIDs.h index 427c14f12a..98eb7fd47c 100644 --- a/xbmc/games/controllers/ControllerIDs.h +++ b/xbmc/games/controllers/ControllerIDs.h @@ -22,4 +22,5 @@ // Default controller IDs #define DEFAULT_CONTROLLER_ID "game.controller.default" #define DEFAULT_KEYBOARD_ID "game.controller.keyboard" +#define DEFAULT_MOUSE_ID "game.controller.mouse" #define DEFAULT_REMOTE_ID "game.controller.remote" diff --git a/xbmc/games/controllers/ControllerManager.cpp b/xbmc/games/controllers/ControllerManager.cpp index feffa5c7d6..1199aff385 100644 --- a/xbmc/games/controllers/ControllerManager.cpp +++ b/xbmc/games/controllers/ControllerManager.cpp @@ -53,6 +53,11 @@ ControllerPtr CControllerManager::GetDefaultKeyboard() return GetController(DEFAULT_KEYBOARD_ID); } +ControllerPtr CControllerManager::GetDefaultMouse() +{ + return GetController(DEFAULT_MOUSE_ID); +} + ControllerVector CControllerManager::GetControllers() { using namespace ADDON; diff --git a/xbmc/games/controllers/ControllerManager.h b/xbmc/games/controllers/ControllerManager.h index 540ef59fef..63765b90b8 100644 --- a/xbmc/games/controllers/ControllerManager.h +++ b/xbmc/games/controllers/ControllerManager.h @@ -64,6 +64,13 @@ namespace GAME ControllerPtr GetDefaultKeyboard(); /*! + * \brief Get the default mouse + * + * \return The mouse controller, or empty if the controller failed to load + */ + ControllerPtr GetDefaultMouse(); + + /*! * \brief Get installed controllers * * \return The installed controllers that loaded successfully diff --git a/xbmc/games/controllers/guicontrols/CMakeLists.txt b/xbmc/games/controllers/guicontrols/CMakeLists.txt index bbec218bbf..e6babcc9e5 100644 --- a/xbmc/games/controllers/guicontrols/CMakeLists.txt +++ b/xbmc/games/controllers/guicontrols/CMakeLists.txt @@ -1,4 +1,4 @@ -set(SOURCES GUIAnalogStickButton.cpp +set(SOURCES GUICardinalFeatureButton.cpp GUIControllerButton.cpp GUIFeatureButton.cpp GUIFeatureControls.cpp @@ -11,7 +11,7 @@ set(SOURCES GUIAnalogStickButton.cpp GUIWheelButton.cpp ) -set(HEADERS GUIAnalogStickButton.h +set(HEADERS GUICardinalFeatureButton.h GUIControllerButton.h GUIControlTypes.h GUIFeatureButton.h diff --git a/xbmc/games/controllers/guicontrols/GUIAnalogStickButton.cpp b/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.cpp index 661a6f4884..73a5819988 100644 --- a/xbmc/games/controllers/guicontrols/GUIAnalogStickButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.cpp @@ -18,7 +18,7 @@ * */ -#include "GUIAnalogStickButton.h" +#include "GUICardinalFeatureButton.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" @@ -27,16 +27,16 @@ using namespace KODI; using namespace GAME; -CGUIAnalogStickButton::CGUIAnalogStickButton(const CGUIButtonControl& buttonTemplate, - IConfigurationWizard* wizard, - const CControllerFeature& feature, - unsigned int index) : +CGUICardinalFeatureButton::CGUICardinalFeatureButton(const CGUIButtonControl& buttonTemplate, + IConfigurationWizard* wizard, + const CControllerFeature& feature, + unsigned int index) : CGUIFeatureButton(buttonTemplate, wizard, feature, index) { Reset(); } -bool CGUIAnalogStickButton::PromptForInput(CEvent& waitEvent) +bool CGUICardinalFeatureButton::PromptForInput(CEvent& waitEvent) { using namespace JOYSTICK; @@ -47,19 +47,19 @@ bool CGUIAnalogStickButton::PromptForInput(CEvent& waitEvent) std::string strWarn; switch (m_state) { - case STATE::ANALOG_STICK_UP: + case STATE::CARDINAL_DIRECTION_UP: strPrompt = g_localizeStrings.Get(35092); // "Move %s up" strWarn = g_localizeStrings.Get(35093); // "Move %s up (%d)" break; - case STATE::ANALOG_STICK_RIGHT: + case STATE::CARDINAL_DIRECTION_RIGHT: strPrompt = g_localizeStrings.Get(35096); // "Move %s right" strWarn = g_localizeStrings.Get(35097); // "Move %s right (%d)" break; - case STATE::ANALOG_STICK_DOWN: + case STATE::CARDINAL_DIRECTION_DOWN: strPrompt = g_localizeStrings.Get(35094); // "Move %s down" strWarn = g_localizeStrings.Get(35095); // "Move %s down (%d)" break; - case STATE::ANALOG_STICK_LEFT: + case STATE::CARDINAL_DIRECTION_LEFT: strPrompt = g_localizeStrings.Get(35098); // "Move %s left" strWarn = g_localizeStrings.Get(35099); // "Move %s left (%d)" break; @@ -80,29 +80,29 @@ bool CGUIAnalogStickButton::PromptForInput(CEvent& waitEvent) return bInterrupted; } -bool CGUIAnalogStickButton::IsFinished(void) const +bool CGUICardinalFeatureButton::IsFinished(void) const { return m_state >= STATE::FINISHED; } -JOYSTICK::ANALOG_STICK_DIRECTION CGUIAnalogStickButton::GetAnalogStickDirection(void) const +KODI::INPUT::CARDINAL_DIRECTION CGUICardinalFeatureButton::GetCardinalDirection(void) const { - using namespace JOYSTICK; + using namespace INPUT; switch (m_state) { - case STATE::ANALOG_STICK_UP: return ANALOG_STICK_DIRECTION::UP; - case STATE::ANALOG_STICK_RIGHT: return ANALOG_STICK_DIRECTION::RIGHT; - case STATE::ANALOG_STICK_DOWN: return ANALOG_STICK_DIRECTION::DOWN; - case STATE::ANALOG_STICK_LEFT: return ANALOG_STICK_DIRECTION::LEFT; + case STATE::CARDINAL_DIRECTION_UP: return CARDINAL_DIRECTION::UP; + case STATE::CARDINAL_DIRECTION_RIGHT: return CARDINAL_DIRECTION::RIGHT; + case STATE::CARDINAL_DIRECTION_DOWN: return CARDINAL_DIRECTION::DOWN; + case STATE::CARDINAL_DIRECTION_LEFT: return CARDINAL_DIRECTION::LEFT; default: break; } - return ANALOG_STICK_DIRECTION::UNKNOWN; + return CARDINAL_DIRECTION::NONE; } -void CGUIAnalogStickButton::Reset(void) +void CGUICardinalFeatureButton::Reset(void) { - m_state = STATE::ANALOG_STICK_UP; + m_state = STATE::CARDINAL_DIRECTION_UP; } diff --git a/xbmc/games/controllers/guicontrols/GUIAnalogStickButton.h b/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.h index 6b918e525e..f8180c877d 100644 --- a/xbmc/games/controllers/guicontrols/GUIAnalogStickButton.h +++ b/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.h @@ -25,33 +25,36 @@ namespace KODI { namespace GAME { - class CGUIAnalogStickButton : public CGUIFeatureButton + class CGUICardinalFeatureButton : public CGUIFeatureButton { public: - CGUIAnalogStickButton(const CGUIButtonControl& buttonTemplate, - IConfigurationWizard* wizard, - const CControllerFeature& feature, - unsigned int index); + CGUICardinalFeatureButton(const CGUIButtonControl& buttonTemplate, + IConfigurationWizard* wizard, + const CControllerFeature& feature, + unsigned int index); - virtual ~CGUIAnalogStickButton() = default; + virtual ~CGUICardinalFeatureButton() = default; // implementation of IFeatureButton virtual bool PromptForInput(CEvent& waitEvent) override; virtual bool IsFinished(void) const override; - virtual JOYSTICK::ANALOG_STICK_DIRECTION GetAnalogStickDirection(void) const override; + virtual INPUT::CARDINAL_DIRECTION GetCardinalDirection(void) const override; virtual void Reset(void) override; private: enum class STATE { - ANALOG_STICK_UP, - ANALOG_STICK_RIGHT, - ANALOG_STICK_DOWN, - ANALOG_STICK_LEFT, + CARDINAL_DIRECTION_UP, + CARDINAL_DIRECTION_RIGHT, + CARDINAL_DIRECTION_DOWN, + CARDINAL_DIRECTION_LEFT, FINISHED, }; STATE m_state; }; + + using CGUIAnalogStickButton = CGUICardinalFeatureButton; + using CGUIRelativePointerButton = CGUICardinalFeatureButton; } } diff --git a/xbmc/games/controllers/guicontrols/GUIControlTypes.h b/xbmc/games/controllers/guicontrols/GUIControlTypes.h index ef32908a5a..b4feae8955 100644 --- a/xbmc/games/controllers/guicontrols/GUIControlTypes.h +++ b/xbmc/games/controllers/guicontrols/GUIControlTypes.h @@ -31,6 +31,7 @@ namespace GAME UNKNOWN, BUTTON, ANALOG_STICK, + RELATIVE_POINTER, WHEEL, THROTTLE, SELECT_KEY, diff --git a/xbmc/games/controllers/guicontrols/GUIFeatureButton.h b/xbmc/games/controllers/guicontrols/GUIFeatureButton.h index 990a831887..b71642529a 100644 --- a/xbmc/games/controllers/guicontrols/GUIFeatureButton.h +++ b/xbmc/games/controllers/guicontrols/GUIFeatureButton.h @@ -45,9 +45,9 @@ namespace GAME // partial implementation of IFeatureButton virtual const CControllerFeature& Feature(void) const override { return m_feature; } - virtual JOYSTICK::ANALOG_STICK_DIRECTION GetAnalogStickDirection(void) const override { return JOYSTICK::ANALOG_STICK_DIRECTION::UNKNOWN; } - virtual JOYSTICK::WHEEL_DIRECTION GetWheelDirection(void) const override { return JOYSTICK::WHEEL_DIRECTION::UNKNOWN; } - virtual JOYSTICK::THROTTLE_DIRECTION GetThrottleDirection(void) const override { return JOYSTICK::THROTTLE_DIRECTION::UNKNOWN; } + virtual INPUT::CARDINAL_DIRECTION GetCardinalDirection(void) const override { return INPUT::CARDINAL_DIRECTION::NONE; } + virtual JOYSTICK::WHEEL_DIRECTION GetWheelDirection(void) const override { return JOYSTICK::WHEEL_DIRECTION::NONE; } + virtual JOYSTICK::THROTTLE_DIRECTION GetThrottleDirection(void) const override { return JOYSTICK::THROTTLE_DIRECTION::NONE; } protected: bool DoPrompt(const std::string& strPrompt, const std::string& strWarn, const std::string& strFeature, CEvent& waitEvent); diff --git a/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp b/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp index ce445465c7..642543aa62 100644 --- a/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp +++ b/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp @@ -19,7 +19,7 @@ */ #include "GUIFeatureFactory.h" -#include "GUIAnalogStickButton.h" +#include "GUICardinalFeatureButton.h" #include "GUIScalarFeatureButton.h" #include "GUISelectKeyButton.h" #include "GUIThrottleButton.h" @@ -51,6 +51,9 @@ CGUIButtonControl* CGUIFeatureFactory::CreateButton(BUTTON_TYPE type, case BUTTON_TYPE::SELECT_KEY: return new CGUISelectKeyButton(buttonTemplate, wizard, index); + case BUTTON_TYPE::RELATIVE_POINTER: + return new CGUIRelativePointerButton(buttonTemplate, wizard, feature, index); + default: break; } diff --git a/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp b/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp index 9a7a67b1c9..92a09e342a 100644 --- a/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp +++ b/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp @@ -34,10 +34,8 @@ BUTTON_TYPE CGUIFeatureTranslator::GetButtonType(JOYSTICK::FEATURE_TYPE featureT case JOYSTICK::FEATURE_TYPE::ANALOG_STICK: return BUTTON_TYPE::ANALOG_STICK; - //! @todo Create button control for relative pointers. Use analog sticks for - // now, as four directions are sufficient for relative pointers. case JOYSTICK::FEATURE_TYPE::RELPOINTER: - return BUTTON_TYPE::ANALOG_STICK; + return BUTTON_TYPE::RELATIVE_POINTER; case JOYSTICK::FEATURE_TYPE::WHEEL: return BUTTON_TYPE::WHEEL; diff --git a/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp b/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp index 210d7bd115..34c0f0155e 100644 --- a/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp @@ -89,7 +89,7 @@ JOYSTICK::THROTTLE_DIRECTION CGUIThrottleButton::GetThrottleDirection(void) cons break; } - return THROTTLE_DIRECTION::UNKNOWN; + return THROTTLE_DIRECTION::NONE; } void CGUIThrottleButton::Reset(void) diff --git a/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp b/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp index 3c85f32e61..382b7dd550 100644 --- a/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp @@ -89,7 +89,7 @@ JOYSTICK::WHEEL_DIRECTION CGUIWheelButton::GetWheelDirection(void) const break; } - return WHEEL_DIRECTION::UNKNOWN; + return WHEEL_DIRECTION::NONE; } void CGUIWheelButton::Reset(void) diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp index f89aa44880..d09941e14a 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp @@ -56,9 +56,9 @@ CGUIConfigurationWizard::~CGUIConfigurationWizard(void) = default; void CGUIConfigurationWizard::InitializeState(void) { m_currentButton = nullptr; - m_analogStickDirection = JOYSTICK::ANALOG_STICK_DIRECTION::UNKNOWN; - m_wheelDirection = JOYSTICK::WHEEL_DIRECTION::UNKNOWN; - m_throttleDirection = JOYSTICK::THROTTLE_DIRECTION::UNKNOWN; + m_cardinalDirection = INPUT::CARDINAL_DIRECTION::NONE; + m_wheelDirection = JOYSTICK::WHEEL_DIRECTION::NONE; + m_throttleDirection = JOYSTICK::THROTTLE_DIRECTION::NONE; m_history.clear(); m_lateAxisDetected = false; m_deviceName.clear(); @@ -139,7 +139,7 @@ void CGUIConfigurationWizard::Process(void) while (!button->IsFinished()) { // Allow other threads to access which direction the prompt is on - m_analogStickDirection = button->GetAnalogStickDirection(); + m_cardinalDirection = button->GetCardinalDirection(); m_wheelDirection = button->GetWheelDirection(); m_throttleDirection = button->GetThrottleDirection(); @@ -209,6 +209,7 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, IKeymap* keymap, const JOYSTICK::CDriverPrimitive& primitive) { + using namespace INPUT; using namespace JOYSTICK; bool bHandled = false; @@ -216,8 +217,6 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, // Abort if another controller cancels the prompt if (IsMapping() && !IsMapping(buttonMap->DeviceName())) { - bool bIsCancelAction = false; - //! @todo This only succeeds for game.controller.default; no actions are // currently defined for other controllers if (keymap) @@ -229,27 +228,11 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, if (!actions.empty()) { //! @todo Handle multiple actions mapped to the same key - switch (actions.begin()->actionId) - { - case ACTION_NAV_BACK: - case ACTION_PREVIOUS_MENU: - bIsCancelAction = true; - break; - default: - break; - } + OnAction(actions.begin()->actionId); } } } - if (bIsCancelAction) - { - CLog::Log(LOGDEBUG, "%s: device \"%s\" is cancelling prompt", buttonMap->ControllerID().c_str(), buttonMap->DeviceName().c_str()); - Abort(false); - } - else - CLog::Log(LOGDEBUG, "%s: ignoring input for device \"%s\"", buttonMap->ControllerID().c_str(), buttonMap->DeviceName().c_str()); - // Discard input bHandled = true; } @@ -266,13 +249,13 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, { // Get the current state of the thread IFeatureButton* currentButton; - ANALOG_STICK_DIRECTION analogStickDirection; + CARDINAL_DIRECTION cardinalDirection; WHEEL_DIRECTION wheelDirection; THROTTLE_DIRECTION throttleDirection; { CSingleLock lock(m_stateMutex); currentButton = m_currentButton; - analogStickDirection = m_analogStickDirection; + cardinalDirection = m_cardinalDirection; wheelDirection = m_wheelDirection; throttleDirection = m_throttleDirection; } @@ -302,56 +285,67 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, { const CControllerFeature& feature = currentButton->Feature(); - CLog::Log(LOGDEBUG, "%s: mapping feature \"%s\" for device %s", - m_strControllerId.c_str(), feature.Name().c_str(), buttonMap->DeviceName().c_str()); - - switch (feature.Type()) + if (primitive.Type() == PRIMITIVE_TYPE::RELATIVE_POINTER && + feature.Type() != FEATURE_TYPE::RELPOINTER) { - case FEATURE_TYPE::SCALAR: - { - buttonMap->AddScalar(feature.Name(), primitive); - bHandled = true; - break; - } - case FEATURE_TYPE::ANALOG_STICK: - { - buttonMap->AddAnalogStick(feature.Name(), analogStickDirection, primitive); - bHandled = true; - break; - } - case FEATURE_TYPE::RELPOINTER: - { - buttonMap->AddRelativePointer(feature.Name(), analogStickDirection, primitive); - bHandled = true; - break; - } - case FEATURE_TYPE::WHEEL: - { - buttonMap->AddWheel(feature.Name(), wheelDirection, primitive); - bHandled = true; - break; - } - case FEATURE_TYPE::THROTTLE: - { - buttonMap->AddThrottle(feature.Name(), throttleDirection, primitive); - bHandled = true; - break; - } - case FEATURE_TYPE::KEY: + // Don't allow relative pointers to map to other features + } + else + { + CLog::Log(LOGDEBUG, "%s: mapping feature \"%s\" for device %s", + m_strControllerId.c_str(), feature.Name().c_str(), buttonMap->DeviceName().c_str()); + + switch (feature.Type()) { - buttonMap->AddKey(feature.Name(), primitive); - bHandled = true; - break; + case FEATURE_TYPE::SCALAR: + { + buttonMap->AddScalar(feature.Name(), primitive); + bHandled = true; + break; + } + case FEATURE_TYPE::ANALOG_STICK: + { + buttonMap->AddAnalogStick(feature.Name(), cardinalDirection, primitive); + bHandled = true; + break; + } + case FEATURE_TYPE::RELPOINTER: + { + buttonMap->AddRelativePointer(feature.Name(), cardinalDirection, primitive); + bHandled = true; + break; + } + case FEATURE_TYPE::WHEEL: + { + buttonMap->AddWheel(feature.Name(), wheelDirection, primitive); + bHandled = true; + break; + } + case FEATURE_TYPE::THROTTLE: + { + buttonMap->AddThrottle(feature.Name(), throttleDirection, primitive); + bHandled = true; + break; + } + case FEATURE_TYPE::KEY: + { + buttonMap->AddKey(feature.Name(), primitive); + bHandled = true; + break; + } + default: + break; } - default: - break; } if (bHandled) { m_history.insert(primitive); - OnMotion(buttonMap); + // Don't record motion for relative pointers + if (primitive.Type() != PRIMITIVE_TYPE::RELATIVE_POINTER) + OnMotion(buttonMap); + m_inputEvent.Set(); if (m_deviceName.empty()) @@ -410,7 +404,7 @@ bool CGUIConfigurationWizard::OnKeyPress(const CKey& key) if (bIsMappingController) { - bHandled = OnKeyAction(m_actionMap->GetActionID(key)); + bHandled = OnAction(m_actionMap->GetActionID(key)); } else { @@ -421,7 +415,7 @@ bool CGUIConfigurationWizard::OnKeyPress(const CKey& key) return bHandled; } -bool CGUIConfigurationWizard::OnKeyAction(unsigned int actionId) +bool CGUIConfigurationWizard::OnAction(unsigned int actionId) { bool bHandled = false; @@ -441,6 +435,7 @@ bool CGUIConfigurationWizard::OnKeyAction(unsigned int actionId) case ACTION_PARENT_DIR: case ACTION_PREVIOUS_MENU: case ACTION_STOP: + case ACTION_NAV_BACK: // Abort and prevent action Abort(false); bHandled = true; @@ -455,11 +450,6 @@ bool CGUIConfigurationWizard::OnKeyAction(unsigned int actionId) return bHandled; } -bool CGUIConfigurationWizard::OnButtonPress(const std::string& button) -{ - return Abort(false); -} - bool CGUIConfigurationWizard::IsMapping() const { return !m_deviceName.empty(); @@ -472,15 +462,18 @@ bool CGUIConfigurationWizard::IsMapping(const std::string &deviceName) const void CGUIConfigurationWizard::InstallHooks(void) { + // Install button mapper with lowest priority CServiceBroker::GetPeripherals().RegisterJoystickButtonMapper(this); + + // Install hook to reattach button mapper when peripherals change CServiceBroker::GetPeripherals().RegisterObserver(this); + + // Install hook to cancel the button mapper CServiceBroker::GetInputManager().RegisterKeyboardDriverHandler(this); - CServiceBroker::GetInputManager().RegisterMouseHandler(this); } void CGUIConfigurationWizard::RemoveHooks(void) { - CServiceBroker::GetInputManager().UnregisterMouseHandler(this); CServiceBroker::GetInputManager().UnregisterKeyboardDriverHandler(this); CServiceBroker::GetPeripherals().UnregisterObserver(this); CServiceBroker::GetPeripherals().UnregisterJoystickButtonMapper(this); diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.h b/xbmc/games/controllers/windows/GUIConfigurationWizard.h index b980bc5ae7..4ae26bf54c 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.h +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.h @@ -24,7 +24,6 @@ #include "input/joysticks/DriverPrimitive.h" #include "input/joysticks/interfaces/IButtonMapper.h" #include "input/keyboard/interfaces/IKeyboardDriverHandler.h" -#include "input/mouse/interfaces/IMouseInputHandler.h" #include "input/XBMC_keysym.h" #include "threads/CriticalSection.h" #include "threads/Event.h" @@ -49,7 +48,6 @@ namespace GAME class CGUIConfigurationWizard : public IConfigurationWizard, public JOYSTICK::IButtonMapper, public KEYBOARD::IKeyboardDriverHandler, - public MOUSE::IMouseInputHandler, public Observer, protected CThread { @@ -78,11 +76,6 @@ namespace GAME virtual bool OnKeyPress(const CKey& key) override; virtual void OnKeyRelease(const CKey& key) override { } - // implementation of IMouseInputHandler - virtual bool OnMotion(const std::string& relpointer, int dx, int dy) override { return false; } - virtual bool OnButtonPress(const std::string& button) override; - virtual void OnButtonRelease(const std::string& button) override { } - // implementation of Observer virtual void Notify(const Observable& obs, const ObservableMessage msg) override; @@ -102,7 +95,7 @@ namespace GAME void OnMotion(const JOYSTICK::IButtonMap* buttonMap); void OnMotionless(const JOYSTICK::IButtonMap* buttonMap); - bool OnKeyAction(unsigned int actionId); + bool OnAction(unsigned int actionId); // Run() parameters std::string m_strControllerId; @@ -110,7 +103,7 @@ namespace GAME // State variables and mutex IFeatureButton* m_currentButton; - JOYSTICK::ANALOG_STICK_DIRECTION m_analogStickDirection; + INPUT::CARDINAL_DIRECTION m_cardinalDirection; JOYSTICK::WHEEL_DIRECTION m_wheelDirection; JOYSTICK::THROTTLE_DIRECTION m_throttleDirection; std::set<JOYSTICK::CDriverPrimitive> m_history; // History to avoid repeated features diff --git a/xbmc/games/controllers/windows/IConfigurationWindow.h b/xbmc/games/controllers/windows/IConfigurationWindow.h index 870a773165..72c0cf60e9 100644 --- a/xbmc/games/controllers/windows/IConfigurationWindow.h +++ b/xbmc/games/controllers/windows/IConfigurationWindow.h @@ -21,6 +21,7 @@ #include "games/controllers/ControllerTypes.h" #include "input/joysticks/JoystickTypes.h" +#include "input/InputTypes.h" #include <string> #include <vector> @@ -187,11 +188,12 @@ namespace GAME virtual bool IsFinished(void) const = 0; /*! - * \brief Get the direction of the next analog stick prompt - * \return The next direction to be prompted, or UNKNOWN if this isn't an - * analog stick or the prompt is finished + * \brief Get the direction of the next analog stick or relative pointer + * prompt + * \return The next direction to be prompted, or UNKNOWN if this isn't a + * cardinal feature or the prompt is finished */ - virtual JOYSTICK::ANALOG_STICK_DIRECTION GetAnalogStickDirection(void) const = 0; + virtual INPUT::CARDINAL_DIRECTION GetCardinalDirection(void) const = 0; /*! * \brief Get the direction of the next wheel prompt diff --git a/xbmc/guilib/GUIControl.cpp b/xbmc/guilib/GUIControl.cpp index 7837ff674a..8f57681305 100644 --- a/xbmc/guilib/GUIControl.cpp +++ b/xbmc/guilib/GUIControl.cpp @@ -25,7 +25,7 @@ #include "GUIWindowManager.h" #include "GUIControlProfiler.h" #include "GUITexture.h" -#include "input/MouseStat.h" +#include "input/mouse/MouseStat.h" #include "input/InputManager.h" #include "input/Key.h" #include "ServiceBroker.h" diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp index 90e94e13e9..bbdc7dbec8 100644 --- a/xbmc/input/ButtonTranslator.cpp +++ b/xbmc/input/ButtonTranslator.cpp @@ -32,14 +32,14 @@ #include "IButtonMapper.h" #include "Key.h" #include "KeyboardTranslator.h" -#include "MouseTranslator.h" #include "WindowTranslator.h" -#include "FileItem.h" #include "filesystem/Directory.h" #include "guilib/WindowIDs.h" -#include "Util.h" +#include "input/mouse/MouseTranslator.h" #include "utils/log.h" #include "utils/XBMCTinyXML.h" +#include "FileItem.h" +#include "Util.h" using namespace KODI; diff --git a/xbmc/input/CMakeLists.txt b/xbmc/input/CMakeLists.txt index c2cb7a0825..2c4e3feb04 100644 --- a/xbmc/input/CMakeLists.txt +++ b/xbmc/input/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES Action.cpp InputCodingTableFactory.cpp InputCodingTableKorean.cpp InputManager.cpp + InputTranslator.cpp IRTranslator.cpp JoystickMapper.cpp Key.cpp @@ -19,18 +20,12 @@ set(SOURCES Action.cpp KeyboardTranslator.cpp Keymap.cpp KeymapEnvironment.cpp - MouseStat.cpp - MouseTranslator.cpp TouchTranslator.cpp WindowKeymap.cpp WindowTranslator.cpp XBMC_keytable.cpp) set(HEADERS hardware/IHardwareInput.h - mouse/interfaces/IMouseButtonMap.h - mouse/interfaces/IMouseDriverHandler.h - mouse/interfaces/IMouseInputHandler.h - mouse/interfaces/IMouseInputProvider.h Action.h ActionIDs.h ActionTranslator.h @@ -48,6 +43,8 @@ set(HEADERS hardware/IHardwareInput.h InputCodingTableFactory.h InputCodingTableKorean.h InputManager.h + InputTranslator.h + InputTypes.h IRTranslator.h JoystickMapper.h Key.h @@ -57,8 +54,6 @@ set(HEADERS hardware/IHardwareInput.h KeyboardTranslator.h Keymap.h KeymapEnvironment.h - MouseStat.h - MouseTranslator.h TouchTranslator.h WindowTranslator.h WindowKeymap.h diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp index fcaee017f9..6adf6ac512 100644 --- a/xbmc/input/InputManager.cpp +++ b/xbmc/input/InputManager.cpp @@ -29,10 +29,9 @@ #include "KeymapEnvironment.h" #include "TouchTranslator.h" #include "input/keyboard/interfaces/IKeyboardDriverHandler.h" -#include "input/mouse/generic/MouseInputHandling.h" -#include "input/mouse/interfaces/IMouseDriverHandler.h" -#include "input/mouse/MouseWindowingButtonMap.h" #include "input/keyboard/KeyboardEasterEgg.h" +#include "input/mouse/interfaces/IMouseDriverHandler.h" +#include "input/mouse/MouseTranslator.h" #include "input/Key.h" #include "input/WindowTranslator.h" #include "messaging/ApplicationMessenger.h" @@ -78,7 +77,6 @@ CInputManager::CInputManager(const CAppParamParser ¶ms, m_customControllerTranslator(new CCustomControllerTranslator), m_touchTranslator(new CTouchTranslator), m_joystickTranslator(new CJoystickMapper), - m_mouseButtonMap(new MOUSE::CMouseWindowingButtonMap), m_keyboardEasterEgg(new KEYBOARD::CKeyboardEasterEgg) { m_buttonTranslator->RegisterMapper("touch", m_touchTranslator.get()); @@ -397,24 +395,35 @@ bool CInputManager::OnEvent(XBMC_Event& newEvent) { bool handled = false; - for (auto it = m_mouseHandlers.begin(); it != m_mouseHandlers.end(); ++it) + for (auto driverHandler : m_mouseHandlers) { - if (newEvent.type == XBMC_MOUSEMOTION) + switch (newEvent.type) + { + case XBMC_MOUSEMOTION: { - if (it->driverHandler->OnPosition(newEvent.motion.x, newEvent.motion.y)) + if (driverHandler->OnPosition(newEvent.motion.x, newEvent.motion.y)) handled = true; + break; } - else + case XBMC_MOUSEBUTTONDOWN: { - if (newEvent.type == XBMC_MOUSEBUTTONDOWN) + MOUSE::BUTTON_ID buttonId; + if (CMouseTranslator::TranslateEventID(newEvent.button.button, buttonId)) { - if (it->driverHandler->OnButtonPress(newEvent.button.button)) + if (driverHandler->OnButtonPress(buttonId)) handled = true; } - else if (newEvent.type == XBMC_MOUSEBUTTONUP) - { - it->driverHandler->OnButtonRelease(newEvent.button.button); - } + break; + } + case XBMC_MOUSEBUTTONUP: + { + MOUSE::BUTTON_ID buttonId; + if (CMouseTranslator::TranslateEventID(newEvent.button.button, buttonId)) + driverHandler->OnButtonRelease(buttonId); + break; + } + default: + break; } if (handled) @@ -1006,29 +1015,13 @@ void CInputManager::UnregisterKeyboardDriverHandler(KEYBOARD::IKeyboardDriverHan m_keyboardHandlers.erase(std::remove(m_keyboardHandlers.begin(), m_keyboardHandlers.end(), handler), m_keyboardHandlers.end()); } -std::string CInputManager::RegisterMouseHandler(MOUSE::IMouseInputHandler* handler) +void CInputManager::RegisterMouseDriverHandler(MOUSE::IMouseDriverHandler* handler) { - auto it = std::find_if(m_mouseHandlers.begin(), m_mouseHandlers.end(), - [handler](const MouseHandlerHandle& element) - { - return element.inputHandler == handler; - }); - - if (it == m_mouseHandlers.end()) - { - std::unique_ptr<MOUSE::IMouseDriverHandler> driverHandler(new MOUSE::CMouseInputHandling(handler, m_mouseButtonMap.get())); - MouseHandlerHandle handle = { handler, std::move(driverHandler) }; - m_mouseHandlers.insert(m_mouseHandlers.begin(), std::move(handle)); - } - - return m_mouseButtonMap->ControllerID(); + if (std::find(m_mouseHandlers.begin(), m_mouseHandlers.end(), handler) == m_mouseHandlers.end()) + m_mouseHandlers.insert(m_mouseHandlers.begin(), handler); } -void CInputManager::UnregisterMouseHandler(MOUSE::IMouseInputHandler* handler) +void CInputManager::UnregisterMouseDriverHandler(MOUSE::IMouseDriverHandler* handler) { - m_mouseHandlers.erase(std::remove_if(m_mouseHandlers.begin(), m_mouseHandlers.end(), - [handler](const MouseHandlerHandle& handle) - { - return handle.inputHandler == handler; - }), m_mouseHandlers.end()); + m_mouseHandlers.erase(std::remove(m_mouseHandlers.begin(), m_mouseHandlers.end(), handler), m_mouseHandlers.end()); } diff --git a/xbmc/input/InputManager.h b/xbmc/input/InputManager.h index 97266c45ae..2d623b39a1 100644 --- a/xbmc/input/InputManager.h +++ b/xbmc/input/InputManager.h @@ -34,8 +34,8 @@ #include "Action.h" #include "windowing/XBMC_events.h" #include "input/mouse/interfaces/IMouseInputProvider.h" +#include "input/mouse/MouseStat.h" #include "input/KeyboardStat.h" -#include "input/MouseStat.h" #include "interfaces/IActionListener.h" #include "settings/lib/ISettingCallback.h" #include "threads/CriticalSection.h" @@ -61,9 +61,7 @@ namespace KEYBOARD namespace MOUSE { - class IMouseButtonMap; class IMouseDriverHandler; - class IMouseInputHandler; } } @@ -82,7 +80,6 @@ namespace MOUSE */ class CInputManager : public ISettingCallback, public IActionListener, - public KODI::MOUSE::IMouseInputProvider, public Observable { public: @@ -288,9 +285,8 @@ public: void RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler); void UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler); - // implementation of IMouseInputProvider - virtual std::string RegisterMouseHandler(KODI::MOUSE::IMouseInputHandler* handler) override; - virtual void UnregisterMouseHandler(KODI::MOUSE::IMouseInputHandler* handler) override; + virtual void RegisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler); + virtual void UnregisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler); private: @@ -364,15 +360,7 @@ private: std::unique_ptr<CJoystickMapper> m_joystickTranslator; std::vector<KODI::KEYBOARD::IKeyboardDriverHandler*> m_keyboardHandlers; - - struct MouseHandlerHandle - { - KODI::MOUSE::IMouseInputHandler* inputHandler; - std::unique_ptr<KODI::MOUSE::IMouseDriverHandler> driverHandler; - }; - - std::vector<MouseHandlerHandle> m_mouseHandlers; - std::unique_ptr<KODI::MOUSE::IMouseButtonMap> m_mouseButtonMap; + std::vector<KODI::MOUSE::IMouseDriverHandler*> m_mouseHandlers; std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler> m_keyboardEasterEgg; }; diff --git a/xbmc/input/InputTranslator.cpp b/xbmc/input/InputTranslator.cpp new file mode 100644 index 0000000000..e3b1747f2c --- /dev/null +++ b/xbmc/input/InputTranslator.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "InputTranslator.h" + +using namespace KODI; +using namespace INPUT; + +#define TAN_1_8_PI 0.4142136f // tan(1/8*PI) +#define TAN_3_8_PI 2.4142136f // tan(3/8*PI) + +CARDINAL_DIRECTION CInputTranslator::VectorToCardinalDirection(float x, float y) +{ + if (y >= -x && y > x) return CARDINAL_DIRECTION::UP; + else if (y <= x && y > -x) return CARDINAL_DIRECTION::RIGHT; + else if (y <= -x && y < x) return CARDINAL_DIRECTION::DOWN; + else if (y >= x && y < -x) return CARDINAL_DIRECTION::LEFT; + + return CARDINAL_DIRECTION::NONE; +} + +INTERCARDINAL_DIRECTION CInputTranslator::VectorToIntercardinalDirection(float x, float y) +{ + if (y >= TAN_3_8_PI * -x && y > TAN_3_8_PI * x) return INTERCARDINAL_DIRECTION::UP; + else if (y <= TAN_3_8_PI * x && y > TAN_1_8_PI * x) return INTERCARDINAL_DIRECTION::RIGHTUP; + else if (y <= TAN_1_8_PI * x && y > TAN_1_8_PI * -x) return INTERCARDINAL_DIRECTION::RIGHT; + else if (y <= TAN_1_8_PI * -x && y > TAN_3_8_PI * -x) return INTERCARDINAL_DIRECTION::RIGHTDOWN; + else if (y <= TAN_3_8_PI * -x && y < TAN_3_8_PI * x) return INTERCARDINAL_DIRECTION::DOWN; + else if (y >= TAN_3_8_PI * x && y < TAN_1_8_PI * x) return INTERCARDINAL_DIRECTION::LEFTDOWN; + else if (y >= TAN_1_8_PI * x && y < TAN_1_8_PI * -x) return INTERCARDINAL_DIRECTION::LEFT; + else if (y >= TAN_1_8_PI * -x && y < TAN_3_8_PI * -x) return INTERCARDINAL_DIRECTION::LEFTUP; + + return INTERCARDINAL_DIRECTION::NONE; +} diff --git a/xbmc/input/InputTranslator.h b/xbmc/input/InputTranslator.h new file mode 100644 index 0000000000..d3e02a984a --- /dev/null +++ b/xbmc/input/InputTranslator.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#pragma once + +#include "InputTypes.h" + +namespace KODI +{ +namespace INPUT +{ + class CInputTranslator + { + public: + /*! + * \brief Get the closest cardinal direction to the given vector + * + * This function assumes a right-handed cartesian coordinate system; postive + * X is right, positive Y is up. + * + * Ties are resolved in the clockwise direction: (0.5, 0.5) will resolve to + * RIGHT. + * + * \param x The x component of the vector + * \param y The y component of the vector + * + * \return The closest cardinal direction (up, down, right or left), or + * CARDINAL_DIRECTION::NONE if x and y are both 0 + */ + static CARDINAL_DIRECTION VectorToCardinalDirection(float x, float y); + + /*! + * \brief Get the closest cardinal or intercardinal direction to the given + * vector + * + * This function assumes a right-handed cartesian coordinate system; postive + * X is right, positive Y is up. + * + * Ties are resolved in the clockwise direction. + * + * \param x The x component of the vector + * \param y The y component of the vector + * + * \return The closest intercardinal direction, or + * INTERCARDINAL_DIRECTION::NONE if x and y are both 0 + */ + static INTERCARDINAL_DIRECTION VectorToIntercardinalDirection(float x, float y); + }; +} +} diff --git a/xbmc/input/InputTypes.h b/xbmc/input/InputTypes.h new file mode 100644 index 0000000000..adf36cbac2 --- /dev/null +++ b/xbmc/input/InputTypes.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#pragma once + +namespace KODI +{ +namespace INPUT +{ + /*! + * \brief Cardinal directions, used for input device motions + */ + enum class CARDINAL_DIRECTION + { + NONE = 0x0, + UP = 0x1, + DOWN = 0x2, + RIGHT = 0x4, + LEFT = 0x8, + }; + + /*! + * \brief Cardinal and intercardinal directions, used for input device motions + */ + enum class INTERCARDINAL_DIRECTION + { + NONE = static_cast<unsigned int>(CARDINAL_DIRECTION::NONE), + UP = static_cast<unsigned int>(CARDINAL_DIRECTION::UP), + DOWN = static_cast<unsigned int>(CARDINAL_DIRECTION::DOWN), + RIGHT = static_cast<unsigned int>(CARDINAL_DIRECTION::RIGHT), + LEFT = static_cast<unsigned int>(CARDINAL_DIRECTION::LEFT), + RIGHTUP = RIGHT | UP, + RIGHTDOWN = RIGHT | DOWN, + LEFTUP = LEFT | UP, + LEFTDOWN = LEFT | DOWN, + }; +} +} diff --git a/xbmc/input/JoystickMapper.cpp b/xbmc/input/JoystickMapper.cpp index fcc37df37a..c1a1bfbf74 100644 --- a/xbmc/input/JoystickMapper.cpp +++ b/xbmc/input/JoystickMapper.cpp @@ -134,7 +134,7 @@ bool CJoystickMapper::DeserializeButton(const TiXmlElement *pButton, std::string if (!feature.empty() && !actionStr.empty()) { // Handle direction - dir = JOYSTICK::ANALOG_STICK_DIRECTION::UNKNOWN; + dir = JOYSTICK::ANALOG_STICK_DIRECTION::NONE; const char *szDirection = pButton->Attribute(JOYSTICK_XML_ATTR_DIRECTION); if (szDirection != nullptr) dir = JOYSTICK::CJoystickTranslator::TranslateAnalogStickDirection(szDirection); diff --git a/xbmc/input/joysticks/DriverPrimitive.cpp b/xbmc/input/joysticks/DriverPrimitive.cpp index 66cc47c9ea..10f3e52474 100644 --- a/xbmc/input/joysticks/DriverPrimitive.cpp +++ b/xbmc/input/joysticks/DriverPrimitive.cpp @@ -55,6 +55,18 @@ CDriverPrimitive::CDriverPrimitive(XBMCKey keycode) : { } +CDriverPrimitive::CDriverPrimitive(MOUSE::BUTTON_ID index) : + m_type(PRIMITIVE_TYPE::MOUSE_BUTTON), + m_driverIndex(static_cast<unsigned int>(index)) +{ +} + +CDriverPrimitive::CDriverPrimitive(RELATIVE_POINTER_DIRECTION direction) : + m_type(PRIMITIVE_TYPE::RELATIVE_POINTER), + m_pointerDirection(direction) +{ +} + bool CDriverPrimitive::operator==(const CDriverPrimitive& rhs) const { if (m_type == rhs.m_type) @@ -63,6 +75,7 @@ bool CDriverPrimitive::operator==(const CDriverPrimitive& rhs) const { case PRIMITIVE_TYPE::BUTTON: case PRIMITIVE_TYPE::MOTOR: + case PRIMITIVE_TYPE::MOUSE_BUTTON: return m_driverIndex == rhs.m_driverIndex; case PRIMITIVE_TYPE::HAT: return m_driverIndex == rhs.m_driverIndex && m_hatDirection == rhs.m_hatDirection; @@ -73,6 +86,8 @@ bool CDriverPrimitive::operator==(const CDriverPrimitive& rhs) const m_range == rhs.m_range; case PRIMITIVE_TYPE::KEY: return m_keycode == rhs.m_keycode; + case PRIMITIVE_TYPE::RELATIVE_POINTER: + return m_pointerDirection == rhs.m_pointerDirection; default: return true; } @@ -88,7 +103,8 @@ bool CDriverPrimitive::operator<(const CDriverPrimitive& rhs) const if (m_type == PRIMITIVE_TYPE::BUTTON || m_type == PRIMITIVE_TYPE::HAT || m_type == PRIMITIVE_TYPE::SEMIAXIS || - m_type == PRIMITIVE_TYPE::MOTOR) + m_type == PRIMITIVE_TYPE::MOTOR || + m_type == PRIMITIVE_TYPE::MOUSE_BUTTON) { if (m_driverIndex < rhs.m_driverIndex) return true; if (m_driverIndex > rhs.m_driverIndex) return false; @@ -118,13 +134,20 @@ bool CDriverPrimitive::operator<(const CDriverPrimitive& rhs) const if (m_keycode > rhs.m_keycode) return false; } + if (m_type == PRIMITIVE_TYPE::RELATIVE_POINTER) + { + if (m_pointerDirection < rhs.m_pointerDirection) return true; + if (m_pointerDirection > rhs.m_pointerDirection) return false; + } + return false; } bool CDriverPrimitive::IsValid(void) const { if (m_type == PRIMITIVE_TYPE::BUTTON || - m_type == PRIMITIVE_TYPE::MOTOR) + m_type == PRIMITIVE_TYPE::MOTOR || + m_type == PRIMITIVE_TYPE::MOUSE_BUTTON) return true; if (m_type == PRIMITIVE_TYPE::HAT) @@ -172,5 +195,13 @@ bool CDriverPrimitive::IsValid(void) const if (m_type == PRIMITIVE_TYPE::KEY) return m_keycode != XBMCK_UNKNOWN; + if (m_type == PRIMITIVE_TYPE::RELATIVE_POINTER) + { + return m_pointerDirection == RELATIVE_POINTER_DIRECTION::UP || + m_pointerDirection == RELATIVE_POINTER_DIRECTION::DOWN || + m_pointerDirection == RELATIVE_POINTER_DIRECTION::RIGHT || + m_pointerDirection == RELATIVE_POINTER_DIRECTION::LEFT; + } + return false; } diff --git a/xbmc/input/joysticks/DriverPrimitive.h b/xbmc/input/joysticks/DriverPrimitive.h index 32be317992..65eca9b831 100644 --- a/xbmc/input/joysticks/DriverPrimitive.h +++ b/xbmc/input/joysticks/DriverPrimitive.h @@ -20,6 +20,7 @@ #pragma once #include "JoystickTypes.h" +#include "input/mouse/MouseTypes.h" #include "input/XBMC_keysym.h" #include <stdint.h> @@ -67,6 +68,12 @@ namespace JOYSTICK * Key: * - keycode * + * Mouse button: + * - driver index + * + * Relative pointer: + * - pointer direction + * * For more info, see "Chapter 2. Joystick drivers" in the documentation * thread: http://forum.kodi.tv/showthread.php?tid=257764 */ @@ -100,6 +107,16 @@ namespace JOYSTICK */ CDriverPrimitive(XBMCKey keycode); + /*! + * \brief Construct a driver primitive representing a mouse button + */ + CDriverPrimitive(MOUSE::BUTTON_ID index); + + /*! + * \brief Construct a driver primitive representing a relative pointer + */ + CDriverPrimitive(RELATIVE_POINTER_DIRECTION direction); + bool operator==(const CDriverPrimitive& rhs) const; bool operator<(const CDriverPrimitive& rhs) const; @@ -150,6 +167,16 @@ namespace JOYSTICK XBMCKey Keycode() const { return m_keycode; } /*! + * \brief The mouse button ID (valid for mouse buttons) + */ + MOUSE::BUTTON_ID MouseButton() const { return static_cast<MOUSE::BUTTON_ID>(m_driverIndex); } + + /*! + * \brief The relative pointer direction (valid for relative pointers) + */ + RELATIVE_POINTER_DIRECTION PointerDirection() const { return m_pointerDirection; } + + /*! * \brief Test if an driver primitive is valid * * A driver primitive is valid if it has a known type and: @@ -163,11 +190,12 @@ namespace JOYSTICK private: PRIMITIVE_TYPE m_type = PRIMITIVE_TYPE::UNKNOWN; unsigned int m_driverIndex = 0; - HAT_DIRECTION m_hatDirection = HAT_DIRECTION::UNKNOWN; + HAT_DIRECTION m_hatDirection = HAT_DIRECTION::NONE; int m_center = 0; SEMIAXIS_DIRECTION m_semiAxisDirection = SEMIAXIS_DIRECTION::ZERO; unsigned int m_range = 1; XBMCKey m_keycode = XBMCK_UNKNOWN; + RELATIVE_POINTER_DIRECTION m_pointerDirection = RELATIVE_POINTER_DIRECTION::NONE; }; } } diff --git a/xbmc/input/joysticks/JoystickTranslator.cpp b/xbmc/input/joysticks/JoystickTranslator.cpp index 07e049e801..0312fb3ef8 100644 --- a/xbmc/input/joysticks/JoystickTranslator.cpp +++ b/xbmc/input/joysticks/JoystickTranslator.cpp @@ -21,6 +21,7 @@ #include "JoystickTranslator.h" #include "guilib/LocalizeStrings.h" #include "input/joysticks/DriverPrimitive.h" +#include "input/mouse/MouseStat.h" #include "utils/StringUtils.h" using namespace KODI; @@ -38,7 +39,6 @@ const char* CJoystickTranslator::HatStateToString(HAT_STATE state) case HAT_STATE::RIGHTDOWN: return "DOWN RIGHT"; case HAT_STATE::LEFTUP: return "UP LEFT"; case HAT_STATE::LEFTDOWN: return "DOWN LEFT"; - case HAT_STATE::UNPRESSED: default: break; } @@ -68,7 +68,7 @@ ANALOG_STICK_DIRECTION CJoystickTranslator::TranslateAnalogStickDirection(const if (dir == "right") return ANALOG_STICK_DIRECTION::RIGHT; if (dir == "left") return ANALOG_STICK_DIRECTION::LEFT; - return ANALOG_STICK_DIRECTION::UNKNOWN; + return ANALOG_STICK_DIRECTION::NONE; } const char* CJoystickTranslator::TranslateWheelDirection(WHEEL_DIRECTION dir) @@ -89,7 +89,7 @@ WHEEL_DIRECTION CJoystickTranslator::TranslateWheelDirection(const std::string & if (dir == "right") return WHEEL_DIRECTION::RIGHT; if (dir == "left") return WHEEL_DIRECTION::LEFT; - return WHEEL_DIRECTION::UNKNOWN; + return WHEEL_DIRECTION::NONE; } const char* CJoystickTranslator::TranslateThrottleDirection(THROTTLE_DIRECTION dir) @@ -110,7 +110,7 @@ THROTTLE_DIRECTION CJoystickTranslator::TranslateThrottleDirection(const std::st if (dir == "up") return THROTTLE_DIRECTION::UP; if (dir == "down") return THROTTLE_DIRECTION::DOWN; - return THROTTLE_DIRECTION::UNKNOWN; + return THROTTLE_DIRECTION::NONE; } SEMIAXIS_DIRECTION CJoystickTranslator::PositionToSemiAxisDirection(float position) @@ -126,7 +126,7 @@ WHEEL_DIRECTION CJoystickTranslator::PositionToWheelDirection(float position) if (position > 0.0f) return WHEEL_DIRECTION::RIGHT; else if (position < 0.0f) return WHEEL_DIRECTION::LEFT; - return WHEEL_DIRECTION::UNKNOWN; + return WHEEL_DIRECTION::NONE; } THROTTLE_DIRECTION CJoystickTranslator::PositionToThrottleDirection(float position) @@ -134,17 +134,7 @@ THROTTLE_DIRECTION CJoystickTranslator::PositionToThrottleDirection(float positi if (position > 0.0f) return THROTTLE_DIRECTION::UP; else if (position < 0.0f) return THROTTLE_DIRECTION::DOWN; - return THROTTLE_DIRECTION::UNKNOWN; -} - -ANALOG_STICK_DIRECTION CJoystickTranslator::VectorToAnalogStickDirection(float x, float y) -{ - if (y >= x && y > -x) return ANALOG_STICK_DIRECTION::UP; - else if (y < x && y >= -x) return ANALOG_STICK_DIRECTION::RIGHT; - else if (y <= x && y < -x) return ANALOG_STICK_DIRECTION::DOWN; - else if (y > x && y <= -x) return ANALOG_STICK_DIRECTION::LEFT; - - return ANALOG_STICK_DIRECTION::UNKNOWN; + return THROTTLE_DIRECTION::NONE; } std::string CJoystickTranslator::GetPrimitiveName(const CDriverPrimitive& primitive) diff --git a/xbmc/input/joysticks/JoystickTranslator.h b/xbmc/input/joysticks/JoystickTranslator.h index 6ff92f54f4..41a4b1c5fd 100644 --- a/xbmc/input/joysticks/JoystickTranslator.h +++ b/xbmc/input/joysticks/JoystickTranslator.h @@ -20,6 +20,7 @@ #pragma once #include "JoystickTypes.h" +#include "input/mouse/MouseTypes.h" namespace KODI { @@ -124,20 +125,6 @@ namespace JOYSTICK static THROTTLE_DIRECTION PositionToThrottleDirection(float position); /*! - * \brief Get the closest cardinal direction to the given vector - * - * Ties are resolved in the clockwise direction: (0.5, 0.5) will resolve to - * RIGHT. - * - * \param x The x component of the vector - * \param y The y component of the vector - * - * \return The closest analog stick direction (up, down, right or left), or - * ANALOG_STICK_DIRECTION::UNKNOWN if x and y are both 0 - */ - static ANALOG_STICK_DIRECTION VectorToAnalogStickDirection(float x, float y); - - /*! * \brief Get the localized name of the primitive * * \param primitive The primitive, currently only buttons and axes are supported diff --git a/xbmc/input/joysticks/JoystickTypes.h b/xbmc/input/joysticks/JoystickTypes.h index 44f0214bc3..86311372ae 100644 --- a/xbmc/input/joysticks/JoystickTypes.h +++ b/xbmc/input/joysticks/JoystickTypes.h @@ -24,6 +24,8 @@ \ingroup joystick */ +#include "input/InputTypes.h" + #include <set> #include <string> @@ -96,35 +98,22 @@ namespace JOYSTICK /*! * \brief Direction arrows on the hat (directional pad) */ - enum class HAT_DIRECTION - { - UNKNOWN = 0x0, - UP = 0x1, - DOWN = 0x2, - RIGHT = 0x4, - LEFT = 0x8, - }; + using HAT_DIRECTION = INPUT::CARDINAL_DIRECTION; + + /*! + * \brief States in which a hat can be + */ + using HAT_STATE = INPUT::INTERCARDINAL_DIRECTION; /*! * \brief Typedef for analog stick directions */ - using ANALOG_STICK_DIRECTION = HAT_DIRECTION; + using ANALOG_STICK_DIRECTION = INPUT::CARDINAL_DIRECTION; /*! - * \brief States in which a hat can be + * \brief Directions of motion for a relative pointer */ - enum class HAT_STATE - { - UNPRESSED = 0x0, /*!< @brief no directions are pressed */ - UP = 0x1, /*!< @brief only up is pressed */ - DOWN = 0x2, /*!< @brief only down is pressed */ - RIGHT = 0x4, /*!< @brief only right is pressed */ - LEFT = 0x8, /*!< @brief only left is pressed */ - RIGHTUP = RIGHT | UP, - RIGHTDOWN = RIGHT | DOWN, - LEFTUP = LEFT | UP, - LEFTDOWN = LEFT | DOWN, - }; + using RELATIVE_POINTER_DIRECTION = INPUT::CARDINAL_DIRECTION; /*! * \brief Directions in which a semiaxis can point @@ -141,7 +130,7 @@ namespace JOYSTICK */ enum class WHEEL_DIRECTION { - UNKNOWN, + NONE, RIGHT, LEFT, }; @@ -151,7 +140,7 @@ namespace JOYSTICK */ enum class THROTTLE_DIRECTION { - UNKNOWN, + NONE, UP, DOWN, }; @@ -176,9 +165,11 @@ namespace JOYSTICK HAT, // one of the four direction arrows on a D-pad SEMIAXIS, // the positive or negative half of an axis MOTOR, // a rumble motor - KEY // a keyboard key + KEY, // a keyboard key + MOUSE_BUTTON, // a mouse button + RELATIVE_POINTER, // a relative pointer, such as on a mouse }; - + /*! * \ingroup joystick * \brief Action entry in joystick.xml diff --git a/xbmc/input/joysticks/JoystickUtils.cpp b/xbmc/input/joysticks/JoystickUtils.cpp index e2bbd5cabb..cf115dabab 100644 --- a/xbmc/input/joysticks/JoystickUtils.cpp +++ b/xbmc/input/joysticks/JoystickUtils.cpp @@ -34,7 +34,7 @@ std::string CJoystickUtils::MakeKeyName(const FeatureName &feature, ANALOG_STICK { std::string keyName = feature; - if (dir != ANALOG_STICK_DIRECTION::UNKNOWN) + if (dir != ANALOG_STICK_DIRECTION::NONE) keyName += CJoystickTranslator::TranslateAnalogStickDirection(dir); return keyName; @@ -42,7 +42,7 @@ std::string CJoystickUtils::MakeKeyName(const FeatureName &feature, ANALOG_STICK std::string CJoystickUtils::MakeKeyName(const FeatureName &feature, WHEEL_DIRECTION dir) { - ANALOG_STICK_DIRECTION stickDir = ANALOG_STICK_DIRECTION::UNKNOWN; + ANALOG_STICK_DIRECTION stickDir = ANALOG_STICK_DIRECTION::NONE; switch (dir) { @@ -61,7 +61,7 @@ std::string CJoystickUtils::MakeKeyName(const FeatureName &feature, WHEEL_DIRECT std::string CJoystickUtils::MakeKeyName(const FeatureName &feature, THROTTLE_DIRECTION dir) { - ANALOG_STICK_DIRECTION stickDir = ANALOG_STICK_DIRECTION::UNKNOWN; + ANALOG_STICK_DIRECTION stickDir = ANALOG_STICK_DIRECTION::NONE; switch (dir) { diff --git a/xbmc/input/joysticks/generic/ButtonMapping.cpp b/xbmc/input/joysticks/generic/ButtonMapping.cpp index 4c7c7c2194..3f5af89d60 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.cpp +++ b/xbmc/input/joysticks/generic/ButtonMapping.cpp @@ -27,6 +27,7 @@ #include "input/joysticks/DriverPrimitive.h" #include "input/joysticks/JoystickTranslator.h" #include "input/joysticks/JoystickUtils.h" +#include "input/InputTranslator.h" #include "input/IKeymap.h" #include "input/Key.h" #include "threads/SystemClock.h" @@ -261,6 +262,67 @@ bool CKeyDetector::OnMotion(bool bPressed) return false; } +// --- CMouseButtonDetector ---------------------------------------------------- + +CMouseButtonDetector::CMouseButtonDetector(CButtonMapping* buttonMapping, MOUSE::BUTTON_ID buttonIndex) : + CPrimitiveDetector(buttonMapping), + m_buttonIndex(buttonIndex) +{ +} + +bool CMouseButtonDetector::OnMotion(bool bPressed) +{ + if (bPressed) + return MapPrimitive(CDriverPrimitive(m_buttonIndex)); + + return false; +} + +// --- CPointerDetector -------------------------------------------------------- + +CPointerDetector::CPointerDetector(CButtonMapping* buttonMapping) : + CPrimitiveDetector(buttonMapping) +{ +} + +bool CPointerDetector::OnMotion(int x, int y) +{ + if (!m_bStarted) + { + m_bStarted = true; + m_startX = x; + m_startY = y; + m_frameCount = 0; + } + + if (m_frameCount++ >= MIN_FRAME_COUNT) + { + int dx = x - m_startX; + int dy = y - m_startY; + + INPUT::INTERCARDINAL_DIRECTION dir = GetPointerDirection(dx, dy); + + CDriverPrimitive primitive(static_cast<RELATIVE_POINTER_DIRECTION>(dir)); + if (primitive.IsValid()) + { + if (MapPrimitive(primitive)) + m_bStarted = false; + } + } + + return true; +} + +KODI::INPUT::INTERCARDINAL_DIRECTION CPointerDetector::GetPointerDirection(int x, int y) +{ + using namespace INPUT; + + // Translate from left-handed coordinate system to right-handed coordinate system + y *= -1; + + return CInputTranslator::VectorToIntercardinalDirection(static_cast<float>(x), static_cast<float>(y)); +} + // --- CButtonMapping ---------------------------------------------------------- CButtonMapping::CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMap, IKeymap* keymap) : @@ -342,6 +404,21 @@ bool CButtonMapping::OnKeyPress(const CKey& key) return GetKey(static_cast<XBMCKey>(key.GetKeycode())).OnMotion(true); } +bool CButtonMapping::OnPosition(int x, int y) +{ + return GetPointer().OnMotion(x, y); +} + +bool CButtonMapping::OnButtonPress(MOUSE::BUTTON_ID button) +{ + return GetMouseButton(button).OnMotion(true); +} + +void CButtonMapping::OnButtonRelease(MOUSE::BUTTON_ID button) +{ + GetMouseButton(button).OnMotion(false); +} + void CButtonMapping::SaveButtonMap() { m_buttonMap->SaveButtonMap(); @@ -468,6 +545,27 @@ CKeyDetector& CButtonMapping::GetKey(XBMCKey keycode) return itKey->second; } +CMouseButtonDetector& CButtonMapping::GetMouseButton(MOUSE::BUTTON_ID buttonIndex) +{ + auto itButton = m_mouseButtons.find(buttonIndex); + + if (itButton == m_mouseButtons.end()) + { + m_mouseButtons.insert(std::make_pair(buttonIndex, CMouseButtonDetector(this, buttonIndex))); + itButton = m_mouseButtons.find(buttonIndex); + } + + return itButton->second; +} + +CPointerDetector &CButtonMapping::GetPointer() +{ + if (!m_pointer) + m_pointer.reset(new CPointerDetector(this)); + + return *m_pointer; +} + void CButtonMapping::OnLateDiscovery(unsigned int axisIndex) { m_buttonMapper->OnLateAxis(m_buttonMap, axisIndex); diff --git a/xbmc/input/joysticks/generic/ButtonMapping.h b/xbmc/input/joysticks/generic/ButtonMapping.h index 22f124271c..e0eebd00dc 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.h +++ b/xbmc/input/joysticks/generic/ButtonMapping.h @@ -23,8 +23,11 @@ #include "input/joysticks/interfaces/IDriverHandler.h" #include "input/joysticks/DriverPrimitive.h" #include "input/keyboard/interfaces/IKeyboardDriverHandler.h" +#include "input/mouse/interfaces/IMouseDriverHandler.h" +#include "input/mouse/MouseTypes.h" #include <map> +#include <memory> #include <stdint.h> class IKeymap; @@ -248,6 +251,61 @@ namespace JOYSTICK }; /*! + * \brief Detects when a mouse button should be mapped + */ + class CMouseButtonDetector : public CPrimitiveDetector + { + public: + CMouseButtonDetector(CButtonMapping* buttonMapping, MOUSE::BUTTON_ID buttonIndex); + + /*! + * \brief Button state has been updated + * + * \param bPressed The new state + * + * \return True if this press was handled, false if it should fall through + * to the next driver handler + */ + bool OnMotion(bool bPressed); + + private: + // Construction parameters + const MOUSE::BUTTON_ID m_buttonIndex; + }; + + /*! + * \brief Detects when a mouse button should be mapped + */ + class CPointerDetector : public CPrimitiveDetector + { + public: + CPointerDetector(CButtonMapping* buttonMapping); + + /*! + * \brief Pointer position has been updated + * + * \param x The new x coordinate + * \param y The new y coordinate + * + * \return Always true - pointer motion events are always absorbed while + * button mapping + */ + bool OnMotion(int x, int y); + + private: + // Utility function + static INPUT::INTERCARDINAL_DIRECTION GetPointerDirection(int x, int y); + + static const unsigned int MIN_FRAME_COUNT = 10; + + // State variables + bool m_bStarted = false; + int m_startX = 0; + int m_startY = 0; + unsigned int m_frameCount = 0; + }; + + /*! * \ingroup joystick * \brief Generic implementation of a class that provides button mapping by * translating driver events to button mapping commands @@ -260,6 +318,7 @@ namespace JOYSTICK */ class CButtonMapping : public IDriverHandler, public KEYBOARD::IKeyboardDriverHandler, + public MOUSE::IMouseDriverHandler, public IButtonMapCallback { public: @@ -283,6 +342,11 @@ namespace JOYSTICK bool OnKeyPress(const CKey& key) override; void OnKeyRelease(const CKey& key) override { } + // implementation of IMouseDriverHandler + bool OnPosition(int x, int y) override; + bool OnButtonPress(MOUSE::BUTTON_ID button) override; + void OnButtonRelease(MOUSE::BUTTON_ID button) override; + // implementation of IButtonMapCallback virtual void SaveButtonMap() override; virtual void ResetIgnoredPrimitives() override; @@ -310,6 +374,8 @@ namespace JOYSTICK CHatDetector& GetHat(unsigned int hatIndex); CAxisDetector& GetAxis(unsigned int axisIndex, float position, const AxisConfiguration& initialConfig = AxisConfiguration()); CKeyDetector& GetKey(XBMCKey keycode); + CMouseButtonDetector& GetMouseButton(MOUSE::BUTTON_ID buttonIndex); + CPointerDetector &GetPointer(); // Construction parameters IButtonMapper* const m_buttonMapper; @@ -320,6 +386,8 @@ namespace JOYSTICK std::map<unsigned int, CHatDetector> m_hats; std::map<unsigned int, CAxisDetector> m_axes; std::map<XBMCKey, CKeyDetector> m_keys; + std::map<MOUSE::BUTTON_ID, CMouseButtonDetector> m_mouseButtons; + std::unique_ptr<CPointerDetector> m_pointer; unsigned int m_lastAction; uint64_t m_frameCount; }; diff --git a/xbmc/input/joysticks/generic/FeatureHandling.cpp b/xbmc/input/joysticks/generic/FeatureHandling.cpp index 7e186c9472..d35d585efb 100644 --- a/xbmc/input/joysticks/generic/FeatureHandling.cpp +++ b/xbmc/input/joysticks/generic/FeatureHandling.cpp @@ -300,7 +300,7 @@ CWheel::CWheel(const FeatureName& name, IInputHandler* handler, IButtonMap* butt bool CWheel::OnAnalogMotion(const CDriverPrimitive& source, float magnitude) { - WHEEL_DIRECTION direction = WHEEL_DIRECTION::UNKNOWN; + WHEEL_DIRECTION direction = WHEEL_DIRECTION::NONE; std::vector<WHEEL_DIRECTION> dirs = { WHEEL_DIRECTION::RIGHT, @@ -346,7 +346,7 @@ CThrottle::CThrottle(const FeatureName& name, IInputHandler* handler, IButtonMap bool CThrottle::OnAnalogMotion(const CDriverPrimitive& source, float magnitude) { - THROTTLE_DIRECTION direction = THROTTLE_DIRECTION::UNKNOWN; + THROTTLE_DIRECTION direction = THROTTLE_DIRECTION::NONE; std::vector<THROTTLE_DIRECTION> dirs = { THROTTLE_DIRECTION::UP, @@ -399,7 +399,7 @@ bool CAnalogStick::OnDigitalMotion(const CDriverPrimitive& source, bool bPressed bool CAnalogStick::OnAnalogMotion(const CDriverPrimitive& source, float magnitude) { - ANALOG_STICK_DIRECTION direction = ANALOG_STICK_DIRECTION::UNKNOWN; + ANALOG_STICK_DIRECTION direction = ANALOG_STICK_DIRECTION::NONE; std::vector<ANALOG_STICK_DIRECTION> dirs = { ANALOG_STICK_DIRECTION::UP, diff --git a/xbmc/input/joysticks/interfaces/IButtonMap.h b/xbmc/input/joysticks/interfaces/IButtonMap.h index ed76f2835b..766d266654 100644 --- a/xbmc/input/joysticks/interfaces/IButtonMap.h +++ b/xbmc/input/joysticks/interfaces/IButtonMap.h @@ -83,7 +83,7 @@ namespace JOYSTICK * Multiple primitives can be mapped to the same feature. For example, * analog sticks use one primitive for each direction. * - * \param primitive The driver primitive (a button, hat direction or semi-axis) + * \param primitive The driver primitive * \param feature The name of the resolved joystick feature, or * invalid if false is returned * @@ -182,7 +182,7 @@ namespace JOYSTICK */ virtual bool GetRelativePointer( const FeatureName& feature, - ANALOG_STICK_DIRECTION direction, + RELATIVE_POINTER_DIRECTION direction, CDriverPrimitive& primitive ) = 0; @@ -197,7 +197,7 @@ namespace JOYSTICK */ virtual void AddRelativePointer( const FeatureName& feature, - ANALOG_STICK_DIRECTION direction, + RELATIVE_POINTER_DIRECTION direction, const CDriverPrimitive& primitive ) = 0; diff --git a/xbmc/input/joysticks/keymaps/KeymapHandler.cpp b/xbmc/input/joysticks/keymaps/KeymapHandler.cpp index 8b5e455e44..c0fcee5e73 100644 --- a/xbmc/input/joysticks/keymaps/KeymapHandler.cpp +++ b/xbmc/input/joysticks/keymaps/KeymapHandler.cpp @@ -28,6 +28,7 @@ #include "input/joysticks/JoystickUtils.h" #include "input/IKeymap.h" #include "input/IKeymapEnvironment.h" +#include "input/InputTranslator.h" #include <algorithm> #include <assert.h> @@ -113,10 +114,12 @@ bool CKeymapHandler::OnButtonMotion(const FeatureName& feature, float magnitude, bool CKeymapHandler::OnAnalogStickMotion(const FeatureName& feature, float x, float y, unsigned int motionTimeMs) { + using namespace INPUT; + bool bHandled = false; // Calculate the direction of the stick's position - const ANALOG_STICK_DIRECTION analogStickDir = CJoystickTranslator::VectorToAnalogStickDirection(x, y); + const ANALOG_STICK_DIRECTION analogStickDir = CInputTranslator::VectorToCardinalDirection(x, y); // Calculate the magnitude projected onto that direction const float magnitude = std::max(std::fabs(x), std::fabs(y)); @@ -129,7 +132,7 @@ bool CKeymapHandler::OnAnalogStickMotion(const FeatureName& feature, float x, fl } // Now activate direction the analog stick is pointing - if (analogStickDir != ANALOG_STICK_DIRECTION::UNKNOWN) + if (analogStickDir != ANALOG_STICK_DIRECTION::NONE) bHandled = ActivateDirection(feature, magnitude, analogStickDir, motionTimeMs); return bHandled; @@ -153,7 +156,7 @@ bool CKeymapHandler::OnWheelMotion(const FeatureName& feature, float position, u } // Now activate direction in which the wheel is positioned - if (direction != WHEEL_DIRECTION::UNKNOWN) + if (direction != WHEEL_DIRECTION::NONE) bHandled = ActivateDirection(feature, magnitude, direction, motionTimeMs); return bHandled; @@ -177,7 +180,7 @@ bool CKeymapHandler::OnThrottleMotion(const FeatureName& feature, float position } // Now activate direction in which the throttle is positioned - if (direction != THROTTLE_DIRECTION::UNKNOWN) + if (direction != THROTTLE_DIRECTION::NONE) bHandled = ActivateDirection(feature, magnitude, direction, motionTimeMs); return bHandled; diff --git a/xbmc/input/mouse/CMakeLists.txt b/xbmc/input/mouse/CMakeLists.txt index bebe854d7a..214adf01e8 100644 --- a/xbmc/input/mouse/CMakeLists.txt +++ b/xbmc/input/mouse/CMakeLists.txt @@ -1,9 +1,13 @@ -set(SOURCES MouseWindowingButtonMap.cpp) +set(SOURCES MouseStat.cpp + MouseTranslator.cpp +) -set(HEADERS interfaces/IMouseButtonMap.h - interfaces/IMouseDriverHandler.h +set(HEADERS interfaces/IMouseDriverHandler.h interfaces/IMouseInputHandler.h interfaces/IMouseInputProvider.h - MouseWindowingButtonMap.h) + MouseStat.h + MouseTranslator.h + MouseTypes.h +) core_add_library(input_mouse) diff --git a/xbmc/input/MouseStat.cpp b/xbmc/input/mouse/MouseStat.cpp index 606b233995..606b233995 100644 --- a/xbmc/input/MouseStat.cpp +++ b/xbmc/input/mouse/MouseStat.cpp diff --git a/xbmc/input/MouseStat.h b/xbmc/input/mouse/MouseStat.h index 4eab9ae6fe..4eab9ae6fe 100644 --- a/xbmc/input/MouseStat.h +++ b/xbmc/input/mouse/MouseStat.h diff --git a/xbmc/input/MouseTranslator.cpp b/xbmc/input/mouse/MouseTranslator.cpp index 26c486bb49..baf7771a89 100644 --- a/xbmc/input/MouseTranslator.cpp +++ b/xbmc/input/mouse/MouseTranslator.cpp @@ -19,14 +19,17 @@ */ #include "MouseTranslator.h" -#include "Key.h" #include "MouseStat.h" +#include "input/Key.h" #include "utils/log.h" #include "utils/StringUtils.h" #include "utils/XBMCTinyXML.h" #include <string> +using namespace KODI; +using namespace MOUSE; + namespace { @@ -87,3 +90,59 @@ uint32_t CMouseTranslator::TranslateCommand(const TiXmlElement *pButton) return buttonId; } + +bool CMouseTranslator::TranslateEventID(unsigned int eventId, BUTTON_ID &buttonId) +{ + switch (eventId) + { + case XBMC_BUTTON_LEFT: + { + buttonId = BUTTON_ID::LEFT; + return true; + } + case XBMC_BUTTON_MIDDLE: + { + buttonId = BUTTON_ID::MIDDLE; + return true; + } + case XBMC_BUTTON_RIGHT: + { + buttonId = BUTTON_ID::RIGHT; + return true; + } + case XBMC_BUTTON_WHEELUP: + { + buttonId = BUTTON_ID::WHEEL_UP; + return true; + } + case XBMC_BUTTON_WHEELDOWN: + { + buttonId = BUTTON_ID::WHEEL_DOWN; + return true; + } + case XBMC_BUTTON_X1: + { + buttonId = BUTTON_ID::BUTTON4; + return true; + } + case XBMC_BUTTON_X2: + { + buttonId = BUTTON_ID::BUTTON5; + return true; + } + case XBMC_BUTTON_X3: + { + buttonId = BUTTON_ID::HORIZ_WHEEL_LEFT; + return true; + } + case XBMC_BUTTON_X4: + { + buttonId = BUTTON_ID::HORIZ_WHEEL_RIGHT; + return true; + } + default: + break; + } + + return false; +} diff --git a/xbmc/input/MouseTranslator.h b/xbmc/input/mouse/MouseTranslator.h index 0381d57e4d..085af845f2 100644 --- a/xbmc/input/MouseTranslator.h +++ b/xbmc/input/mouse/MouseTranslator.h @@ -19,6 +19,8 @@ */ #pragma once +#include "MouseTypes.h" + #include <stdint.h> class TiXmlElement; @@ -26,5 +28,18 @@ class TiXmlElement; class CMouseTranslator { public: + /*! + * \brief Translate a keymap element to a key ID + */ static uint32_t TranslateCommand(const TiXmlElement *pButton); + + /*! + * \brief Translate a mouse event ID to a mouse button index + * + * \param eventId The event ID from MouseStat.h + * \param[out] buttonId The button ID from MouseTypes.h, or unmodified if unsuccessful + * + * \return True if successful, false otherwise + */ + static bool TranslateEventID(unsigned int eventId, KODI::MOUSE::BUTTON_ID &buttonId); }; diff --git a/xbmc/input/mouse/MouseTypes.h b/xbmc/input/mouse/MouseTypes.h new file mode 100644 index 0000000000..da00b3eda8 --- /dev/null +++ b/xbmc/input/mouse/MouseTypes.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#pragma once + +#include "input/InputTypes.h" + +#include <string> + +namespace KODI +{ +namespace MOUSE +{ + /*! + * \brief Buttons on a mouse + */ + enum class BUTTON_ID + { + UNKNOWN, + LEFT, + RIGHT, + MIDDLE, + BUTTON4, + BUTTON5, + WHEEL_UP, + WHEEL_DOWN, + HORIZ_WHEEL_LEFT, + HORIZ_WHEEL_RIGHT, + }; + + /*! + * \brief Name of a mouse button + * + * Names are defined in the mouse's controller profile. + */ + using ButtonName = std::string; + + /*! + * \brief Directions of motion for a mouse pointer + */ + using POINTER_DIRECTION = INPUT::CARDINAL_DIRECTION; + + /*! + * \brief Name of the mouse pointer + * + * Names are defined in the mouse's controller profile. + */ + using PointerName = std::string; +} +} diff --git a/xbmc/input/mouse/MouseWindowingButtonMap.cpp b/xbmc/input/mouse/MouseWindowingButtonMap.cpp deleted file mode 100644 index 328a2f59bb..0000000000 --- a/xbmc/input/mouse/MouseWindowingButtonMap.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016-2017 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this Program; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -#include "MouseWindowingButtonMap.h" -#include "input/MouseStat.h" - -#include <algorithm> - -using namespace KODI; -using namespace MOUSE; - -#define CONTROLLER_PROFILE "game.controller.mouse" - -std::vector<std::pair<unsigned int, std::string>> CMouseWindowingButtonMap::m_buttonMap = { - { XBMC_BUTTON_LEFT, "left" }, - { XBMC_BUTTON_MIDDLE, "middle" }, - { XBMC_BUTTON_RIGHT, "right" }, - { XBMC_BUTTON_WHEELUP, "wheelup" }, - { XBMC_BUTTON_WHEELDOWN, "wheeldown" }, -}; - -std::string CMouseWindowingButtonMap::m_pointerName = "pointer"; - -std::string CMouseWindowingButtonMap::ControllerID(void) const -{ - return CONTROLLER_PROFILE; -} - -bool CMouseWindowingButtonMap::GetButton(unsigned int buttonIndex, std::string& feature) -{ - auto it = std::find_if(m_buttonMap.begin(), m_buttonMap.end(), - [buttonIndex](const std::pair<unsigned int, std::string>& entry) - { - return entry.first == buttonIndex; - }); - - if (it != m_buttonMap.end()) - { - feature = it->second; - return true; - } - - return false; -} - -bool CMouseWindowingButtonMap::GetRelativePointer(std::string& feature) -{ - feature = m_pointerName; - return true; -} - -bool CMouseWindowingButtonMap::GetButtonIndex(const std::string& feature, unsigned int& buttonIndex) -{ - auto it = std::find_if(m_buttonMap.begin(), m_buttonMap.end(), - [&feature](const std::pair<unsigned int, std::string>& entry) - { - return entry.second == feature; - }); - - if (it != m_buttonMap.end()) - { - buttonIndex = it->first; - return true; - } - - return false; -} diff --git a/xbmc/input/mouse/MouseWindowingButtonMap.h b/xbmc/input/mouse/MouseWindowingButtonMap.h deleted file mode 100644 index 55262178ac..0000000000 --- a/xbmc/input/mouse/MouseWindowingButtonMap.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2016-2017 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this Program; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/>. - * - */ -#pragma once - -#include "input/mouse/interfaces/IMouseButtonMap.h" - -#include <string> -#include <utility> -#include <vector> - -namespace KODI -{ -namespace MOUSE -{ - /*! - * \ingroup mouse - * \brief Maps mouse windowing events to higher-level features understood by IMouseInputHandler implementations. - */ - class CMouseWindowingButtonMap : public IMouseButtonMap - { - public: - ~CMouseWindowingButtonMap(void) override = default; - - // implementation of IMouseButtonMap - std::string ControllerID(void) const override; - bool GetButton(unsigned int buttonIndex, std::string& feature) override; - bool GetRelativePointer(std::string& feature) override; - bool GetButtonIndex(const std::string& feature, unsigned int& buttonIndex) override; - - private: - static std::vector<std::pair<unsigned int, std::string>> m_buttonMap; - static std::string m_pointerName; - }; -} -} diff --git a/xbmc/input/mouse/generic/MouseInputHandling.cpp b/xbmc/input/mouse/generic/MouseInputHandling.cpp index a4e55e63c1..ce95bd663f 100644 --- a/xbmc/input/mouse/generic/MouseInputHandling.cpp +++ b/xbmc/input/mouse/generic/MouseInputHandling.cpp @@ -19,30 +19,92 @@ */ #include "MouseInputHandling.h" -#include "input/mouse/interfaces/IMouseButtonMap.h" +#include "input/joysticks/interfaces/IButtonMap.h" #include "input/mouse/interfaces/IMouseInputHandler.h" +#include "input/InputTranslator.h" using namespace KODI; using namespace MOUSE; -CMouseInputHandling::CMouseInputHandling(IMouseInputHandler* handler, IMouseButtonMap* buttonMap) : +CMouseInputHandling::CMouseInputHandling(IMouseInputHandler* handler, JOYSTICK::IButtonMap* buttonMap) : m_handler(handler), - m_buttonMap(buttonMap), - m_x(0), - m_y(0) + m_buttonMap(buttonMap) { } bool CMouseInputHandling::OnPosition(int x, int y) { + using namespace JOYSTICK; + + if (!m_bHasPosition) + { + m_bHasPosition = true; + m_x = x; + m_y = y; + return true; + } + int dx = x - m_x; int dy = y - m_y; bool bHandled = false; - std::string featureName; - if (m_buttonMap->GetRelativePointer(featureName)) - bHandled = m_handler->OnMotion(featureName, dx, dy); + // Get direction of motion + POINTER_DIRECTION dir = GetPointerDirection(dx, dy); + + CDriverPrimitive source(dir); + if (source.IsValid()) + { + // Get pointer in direction of motion + PointerName pointerName; + if (m_buttonMap->GetFeature(source, pointerName)) + { + // Get orthogonal direction of motion + POINTER_DIRECTION dirCCW = GetOrthogonalDirectionCCW(dir); + + // Get mapped directions of motion for rotation and reflection + CDriverPrimitive target; + CDriverPrimitive targetCCW; + + if (m_buttonMap->GetRelativePointer(pointerName, dir, target)) + m_buttonMap->GetRelativePointer(pointerName, dirCCW, targetCCW); + + if (target.IsValid()) + { + // Invert y to right-handed cartesian system + dy *= -1; + + // Perform rotation + int rotation[2][2] = { {1, 0}, {0, 1} }; + + GetRotation(dir, target.PointerDirection(), rotation); + + dx = rotation[0][0] * dx + rotation[0][1] * dy; + dy = rotation[1][0] * dx + rotation[1][1] * dy; + + if (targetCCW.IsValid()) + { + // Perform reflection + int reflection[2][2] = { {1, 0}, {0, 1} }; + + GetReflectionCCW(target.PointerDirection(), targetCCW.PointerDirection(), reflection); + + dx = reflection[0][0] * dx + reflection[0][1] * dy; + dy = reflection[1][0] * dx + reflection[1][1] * dy; + } + + // Invert y back to left-handed coordinate system + dy *= -1; + } + + bHandled = m_handler->OnMotion(pointerName, dx, dy); + } + } + else + { + // Don't fall through - might disrupt the game + bHandled = true; + } m_x = x; m_y = y; @@ -50,20 +112,244 @@ bool CMouseInputHandling::OnPosition(int x, int y) return bHandled; } -bool CMouseInputHandling::OnButtonPress(unsigned int button) +bool CMouseInputHandling::OnButtonPress(BUTTON_ID button) { bool bHandled = false; - std::string featureName; - if (m_buttonMap->GetButton(button, featureName)) - bHandled = m_handler->OnButtonPress(featureName); + JOYSTICK::CDriverPrimitive source(button); + + ButtonName buttonName; + if (m_buttonMap->GetFeature(source, buttonName)) + bHandled = m_handler->OnButtonPress(buttonName); return bHandled; } -void CMouseInputHandling::OnButtonRelease(unsigned int button) +void CMouseInputHandling::OnButtonRelease(BUTTON_ID button) +{ + JOYSTICK::CDriverPrimitive source(button); + + ButtonName buttonName; + if (m_buttonMap->GetFeature(source, buttonName)) + m_handler->OnButtonRelease(buttonName); +} + +POINTER_DIRECTION CMouseInputHandling::GetPointerDirection(int x, int y) +{ + using namespace INPUT; + + return CInputTranslator::VectorToCardinalDirection(static_cast<float>(x), static_cast<float>(-y)); +} + +POINTER_DIRECTION CMouseInputHandling::GetOrthogonalDirectionCCW(POINTER_DIRECTION direction) +{ + switch (direction) + { + case POINTER_DIRECTION::RIGHT: return POINTER_DIRECTION::UP; + case POINTER_DIRECTION::UP: return POINTER_DIRECTION::LEFT; + case POINTER_DIRECTION::LEFT: return POINTER_DIRECTION::DOWN; + case POINTER_DIRECTION::DOWN: return POINTER_DIRECTION::RIGHT; + default: + break; + } + + return POINTER_DIRECTION::NONE; +} + +void CMouseInputHandling::GetRotation(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&rotation)[2][2]) +{ + switch (source) + { + case POINTER_DIRECTION::RIGHT: + { + switch (target) + { + case POINTER_DIRECTION::UP: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::LEFT: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::DOWN: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::UP: + { + switch (target) + { + case POINTER_DIRECTION::LEFT: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::DOWN: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::RIGHT: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::LEFT: + { + switch (target) + { + case POINTER_DIRECTION::DOWN: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::RIGHT: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::UP: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::DOWN: + { + switch (target) + { + case POINTER_DIRECTION::RIGHT: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::UP: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::LEFT: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + default: + break; + } +} + +void CMouseInputHandling::GetRotation(int deg, int (&rotation)[2][2]) +{ + switch (deg) + { + case 90: + { + rotation[0][0] = 0; + rotation[0][1] = -1; + rotation[1][0] = 1; + rotation[1][1] = 0; + break; + } + case 180: + { + rotation[0][0] = -1; + rotation[0][1] = 0; + rotation[1][0] = 0; + rotation[1][1] = -1; + break; + } + case 270: + { + rotation[0][0] = 0; + rotation[0][1] = 1; + rotation[1][0] = -1; + rotation[1][1] = 0; + break; + } + default: + break; + } +} + +void CMouseInputHandling::GetReflectionCCW(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&rotation)[2][2]) +{ + switch (source) + { + case POINTER_DIRECTION::RIGHT: + { + switch (target) + { + case POINTER_DIRECTION::DOWN: + GetReflection(0, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::UP: + { + switch (target) + { + case POINTER_DIRECTION::RIGHT: + GetReflection(90, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::LEFT: + { + switch (target) + { + case POINTER_DIRECTION::UP: + GetReflection(180, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::DOWN: + { + switch (target) + { + case POINTER_DIRECTION::LEFT: + GetReflection(270, rotation); + break; + default: + break; + } + break; + } + default: + break; + } +} + +void CMouseInputHandling::GetReflection(int deg, int (&reflection)[2][2]) { - std::string featureName; - if (m_buttonMap->GetButton(button, featureName)) - m_handler->OnButtonRelease(featureName); + switch (deg) + { + case 0: + case 180: + { + reflection[0][0] = 1; + reflection[0][1] = 0; + reflection[1][0] = 0; + reflection[1][1] = -1; + break; + } + case 90: + case 270: + { + reflection[0][0] = -1; + reflection[0][1] = 0; + reflection[1][0] = 0; + reflection[1][1] = 1; + break; + } + default: + break; + } } diff --git a/xbmc/input/mouse/generic/MouseInputHandling.h b/xbmc/input/mouse/generic/MouseInputHandling.h index e41973534c..6d84261641 100644 --- a/xbmc/input/mouse/generic/MouseInputHandling.h +++ b/xbmc/input/mouse/generic/MouseInputHandling.h @@ -20,14 +20,18 @@ #pragma once #include "input/mouse/interfaces/IMouseDriverHandler.h" +#include "input/mouse/MouseTypes.h" namespace KODI { +namespace JOYSTICK +{ + class IButtonMap; +} + namespace MOUSE { class IMouseInputHandler; - class IMouseButtonMap; - class CRelativePointer; /*! * \ingroup mouse @@ -36,23 +40,34 @@ namespace MOUSE class CMouseInputHandling : public IMouseDriverHandler { public: - CMouseInputHandling(IMouseInputHandler* handler, IMouseButtonMap* buttonMap); + CMouseInputHandling(IMouseInputHandler* handler, JOYSTICK::IButtonMap* buttonMap); ~CMouseInputHandling(void) override = default; // implementation of IMouseDriverHandler bool OnPosition(int x, int y) override; - bool OnButtonPress(unsigned int button) override; - void OnButtonRelease(unsigned int button) override; + bool OnButtonPress(BUTTON_ID button) override; + void OnButtonRelease(BUTTON_ID button) override; private: + // Utility functions + static POINTER_DIRECTION GetPointerDirection(int x, int y); + static POINTER_DIRECTION GetOrthogonalDirectionCCW(POINTER_DIRECTION direction); + + static void GetRotation(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&rotation)[2][2]); + static void GetRotation(int deg, int (&rotation)[2][2]); + + static void GetReflectionCCW(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&reflection)[2][2]); + static void GetReflection(int deg, int (&reflection)[2][2]); + // Construction parameters IMouseInputHandler* const m_handler; - IMouseButtonMap* const m_buttonMap; + JOYSTICK::IButtonMap* const m_buttonMap; // Mouse parameters - int m_x; - int m_y; + bool m_bHasPosition = false; + int m_x = 0; + int m_y = 0; }; } } diff --git a/xbmc/input/mouse/interfaces/IMouseButtonMap.h b/xbmc/input/mouse/interfaces/IMouseButtonMap.h deleted file mode 100644 index b237f483ad..0000000000 --- a/xbmc/input/mouse/interfaces/IMouseButtonMap.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2016-2017 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this Program; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/>. - * - */ -#pragma once - -#include <string> - -namespace KODI -{ -namespace MOUSE -{ - /*! - * \ingroup mouse - * \brief Button map interface to translate between the mouse's driver data - * and its higher-level features. - */ - class IMouseButtonMap - { - public: - virtual ~IMouseButtonMap(void) = default; - - /*! - * \brief The ID of the controller profile associated with this button map - * - * The controller ID provided by the implementation serves as the context - * for the feature names below. - * - * \return The ID of this button map's controller profile - */ - virtual std::string ControllerID(void) const = 0; - - /*! - * \brief Get the name of a button by its index - * - * \param buttonIndex The index of the button - * \param[out] feature The name of the feature with the specified button index - * - * \return True if the button index is associated with a feature, false otherwise - */ - virtual bool GetButton(unsigned int buttonIndex, std::string& feature) = 0; - - /*! - * \brief Get the name of the mouse's relative pointer - * - * \param[out] feature The name of the relative pointer - * - * \return True if the mouse has a relative pointer, false otherwise - */ - virtual bool GetRelativePointer(std::string& feature) = 0; - - /*! - * \brief Get the button index for a button - * - * \param feature The name of the button - * \param buttonIndex The resolved button index - * - * \return True if the feature resolved to a button index, or false otherwise - */ - virtual bool GetButtonIndex(const std::string& feature, unsigned int& buttonIndex) = 0; - }; -} -} diff --git a/xbmc/input/mouse/interfaces/IMouseDriverHandler.h b/xbmc/input/mouse/interfaces/IMouseDriverHandler.h index 41f7096d57..2ca0c103cc 100644 --- a/xbmc/input/mouse/interfaces/IMouseDriverHandler.h +++ b/xbmc/input/mouse/interfaces/IMouseDriverHandler.h @@ -19,6 +19,8 @@ */ #pragma once +#include "input/mouse/MouseTypes.h" + namespace KODI { namespace MOUSE @@ -38,6 +40,9 @@ namespace MOUSE * \param x The new x coordinate of the pointer * \param y The new y coordinate of the pointer * + * The mouse uses a left-handed (graphics) cartesian coordinate system. + * Positive X is right, positive Y is down. + * * \return True if the event was handled, false otherwise */ virtual bool OnPosition(int x, int y) = 0; @@ -49,14 +54,14 @@ namespace MOUSE * * \return True if the event was handled, otherwise false */ - virtual bool OnButtonPress(unsigned int button) = 0; + virtual bool OnButtonPress(BUTTON_ID button) = 0; /*! * \brief A mouse button has been released * * \param button The index of the released button */ - virtual void OnButtonRelease(unsigned int button) = 0; + virtual void OnButtonRelease(BUTTON_ID button) = 0; }; } } diff --git a/xbmc/input/mouse/interfaces/IMouseInputHandler.h b/xbmc/input/mouse/interfaces/IMouseInputHandler.h index 1e9e093cc2..82c820f83a 100644 --- a/xbmc/input/mouse/interfaces/IMouseInputHandler.h +++ b/xbmc/input/mouse/interfaces/IMouseInputHandler.h @@ -19,6 +19,8 @@ */ #pragma once +#include "input/mouse/MouseTypes.h" + #include <string> namespace KODI @@ -48,9 +50,12 @@ namespace MOUSE * \param dx The relative x coordinate of motion * \param dy The relative y coordinate of motion * + * The mouse uses a left-handed (graphics) cartesian coordinate system. + * Positive X is right, positive Y is down. + * * \return True if the event was handled, otherwise false */ - virtual bool OnMotion(const std::string& relpointer, int dx, int dy) = 0; + virtual bool OnMotion(const PointerName& relpointer, int dx, int dy) = 0; /*! * \brief A mouse button has been pressed @@ -59,14 +64,14 @@ namespace MOUSE * * \return True if the event was handled, otherwise false */ - virtual bool OnButtonPress(const std::string& button) = 0; + virtual bool OnButtonPress(const ButtonName& button) = 0; /*! * \brief A mouse button has been released * * \param button The name of the feature being released */ - virtual void OnButtonRelease(const std::string& button) = 0; + virtual void OnButtonRelease(const ButtonName& button) = 0; }; } } diff --git a/xbmc/input/mouse/interfaces/IMouseInputProvider.h b/xbmc/input/mouse/interfaces/IMouseInputProvider.h index b2069aa1e6..5a6fbad156 100644 --- a/xbmc/input/mouse/interfaces/IMouseInputProvider.h +++ b/xbmc/input/mouse/interfaces/IMouseInputProvider.h @@ -38,17 +38,15 @@ namespace MOUSE * \brief Registers a handler to be called on mouse input * * \param handler The handler to receive mouse input provided by this class - * - * \return The controller ID that serves as a context for incoming mouse events - * - * \sa IMouseButtonMap + * \param bPromiscuous True to observe all events without affecting + * subsequent handlers */ - virtual std::string RegisterMouseHandler(IMouseInputHandler* handler) = 0; + virtual void RegisterMouseHandler(IMouseInputHandler* handler, bool bPromiscuous) = 0; /*! * \brief Unregisters handler from mouse input * - * \param[in] handler The handler that was receiving mouse input + * \param handler The handler that was receiving mouse input */ virtual void UnregisterMouseHandler(IMouseInputHandler* handler) = 0; }; diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h index acde742d3e..984a08d9dd 100644 --- a/xbmc/peripherals/PeripheralTypes.h +++ b/xbmc/peripherals/PeripheralTypes.h @@ -63,6 +63,7 @@ namespace PERIPHERALS FEATURE_RUMBLE, FEATURE_POWER_OFF, FEATURE_KEYBOARD, + FEATURE_MOUSE, }; enum PeripheralType @@ -78,6 +79,7 @@ namespace PERIPHERALS PERIPHERAL_IMON, PERIPHERAL_JOYSTICK, PERIPHERAL_KEYBOARD, + PERIPHERAL_MOUSE, }; class CPeripheral; @@ -140,6 +142,8 @@ namespace PERIPHERALS return "joystick"; case PERIPHERAL_KEYBOARD: return "keyboard"; + case PERIPHERAL_MOUSE: + return "mouse"; default: return "unknown"; } @@ -170,6 +174,8 @@ namespace PERIPHERALS return PERIPHERAL_JOYSTICK; else if (strTypeLowerCase == "keyboard") return PERIPHERAL_KEYBOARD; + else if (strTypeLowerCase == "mouse") + return PERIPHERAL_MOUSE; return PERIPHERAL_UNKNOWN; }; @@ -252,6 +258,8 @@ namespace PERIPHERALS return "poweroff"; case FEATURE_KEYBOARD: return "keyboard"; + case FEATURE_MOUSE: + return "mouse"; case FEATURE_UNKNOWN: default: return "unknown"; @@ -285,6 +293,8 @@ namespace PERIPHERALS return FEATURE_POWER_OFF; else if (strTypeLowerCase == "keyboard") return FEATURE_KEYBOARD; + else if (strTypeLowerCase == "mouse") + return FEATURE_MOUSE; return FEATURE_UNKNOWN; }; diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp index 68b0f74cc1..ffcac0d839 100644 --- a/xbmc/peripherals/Peripherals.cpp +++ b/xbmc/peripherals/Peripherals.cpp @@ -40,6 +40,7 @@ #include "devices/PeripheralImon.h" #include "devices/PeripheralJoystick.h" #include "devices/PeripheralKeyboard.h" +#include "devices/PeripheralMouse.h" #include "devices/PeripheralNIC.h" #include "devices/PeripheralNyxboard.h" #include "devices/PeripheralTuner.h" @@ -358,6 +359,10 @@ void CPeripherals::CreatePeripheral(CPeripheralBus &bus, const PeripheralScanRes peripheral = PeripheralPtr(new CPeripheralKeyboard(*this, mappedResult, &bus)); break; + case PERIPHERAL_MOUSE: + peripheral = PeripheralPtr(new CPeripheralMouse(*this, mappedResult, &bus)); + break; + default: break; } @@ -870,6 +875,7 @@ void CPeripherals::RegisterJoystickButtonMapper(IButtonMapper* mapper) PeripheralVector peripherals; GetPeripheralsWithFeature(peripherals, FEATURE_JOYSTICK); GetPeripheralsWithFeature(peripherals, FEATURE_KEYBOARD); + GetPeripheralsWithFeature(peripherals, FEATURE_MOUSE); for (auto& peripheral : peripherals) peripheral->RegisterJoystickButtonMapper(mapper); @@ -882,6 +888,7 @@ void CPeripherals::UnregisterJoystickButtonMapper(IButtonMapper* mapper) PeripheralVector peripherals; GetPeripheralsWithFeature(peripherals, FEATURE_JOYSTICK); GetPeripheralsWithFeature(peripherals, FEATURE_KEYBOARD); + GetPeripheralsWithFeature(peripherals, FEATURE_MOUSE); for (auto& peripheral : peripherals) peripheral->UnregisterJoystickButtonMapper(mapper); diff --git a/xbmc/peripherals/addons/AddonButtonMap.cpp b/xbmc/peripherals/addons/AddonButtonMap.cpp index f6cd1a8d36..5e2d805c99 100644 --- a/xbmc/peripherals/addons/AddonButtonMap.cpp +++ b/xbmc/peripherals/addons/AddonButtonMap.cpp @@ -176,7 +176,7 @@ bool CAddonButtonMap::GetAnalogStick(const FeatureName& feature, if (addonFeature.Type() == JOYSTICK_FEATURE_TYPE_ANALOG_STICK) { - primitive = CPeripheralAddonTranslator::TranslatePrimitive(addonFeature.Primitive(GetPrimitiveIndex(direction))); + primitive = CPeripheralAddonTranslator::TranslatePrimitive(addonFeature.Primitive(GetAnalogStickIndex(direction))); retVal = primitive.IsValid(); } } @@ -190,7 +190,7 @@ void CAddonButtonMap::AddAnalogStick(const FeatureName& feature, { using namespace JOYSTICK; - JOYSTICK_FEATURE_PRIMITIVE primitiveIndex = GetPrimitiveIndex(direction); + JOYSTICK_FEATURE_PRIMITIVE primitiveIndex = GetAnalogStickIndex(direction); kodi::addon::DriverPrimitive addonPrimitive = CPeripheralAddonTranslator::TranslatePrimitive(primitive); kodi::addon::JoystickFeature analogStick(feature, JOYSTICK_FEATURE_TYPE_ANALOG_STICK); @@ -216,7 +216,7 @@ void CAddonButtonMap::AddAnalogStick(const FeatureName& feature, } bool CAddonButtonMap::GetRelativePointer(const FeatureName& feature, - JOYSTICK::ANALOG_STICK_DIRECTION direction, + JOYSTICK::RELATIVE_POINTER_DIRECTION direction, JOYSTICK::CDriverPrimitive& primitive) { bool retVal(false); @@ -230,7 +230,7 @@ bool CAddonButtonMap::GetRelativePointer(const FeatureName& feature, if (addonFeature.Type() == JOYSTICK_FEATURE_TYPE_RELPOINTER) { - primitive = CPeripheralAddonTranslator::TranslatePrimitive(addonFeature.Primitive(GetPrimitiveIndex(direction))); + primitive = CPeripheralAddonTranslator::TranslatePrimitive(addonFeature.Primitive(GetRelativePointerIndex(direction))); retVal = primitive.IsValid(); } } @@ -239,12 +239,12 @@ bool CAddonButtonMap::GetRelativePointer(const FeatureName& feature, } void CAddonButtonMap::AddRelativePointer(const FeatureName& feature, - JOYSTICK::ANALOG_STICK_DIRECTION direction, + JOYSTICK::RELATIVE_POINTER_DIRECTION direction, const JOYSTICK::CDriverPrimitive& primitive) { using namespace JOYSTICK; - JOYSTICK_FEATURE_PRIMITIVE primitiveIndex = GetPrimitiveIndex(direction); + JOYSTICK_FEATURE_PRIMITIVE primitiveIndex = GetRelativePointerIndex(direction); kodi::addon::DriverPrimitive addonPrimitive = CPeripheralAddonTranslator::TranslatePrimitive(primitive); kodi::addon::JoystickFeature relPointer(feature, JOYSTICK_FEATURE_TYPE_RELPOINTER); @@ -515,7 +515,6 @@ CAddonButtonMap::DriverMap CAddonButtonMap::CreateLookupTable(const FeatureMap& } case JOYSTICK_FEATURE_TYPE_ANALOG_STICK: - case JOYSTICK_FEATURE_TYPE_RELPOINTER: { std::vector<JOYSTICK_FEATURE_PRIMITIVE> primitives = { JOYSTICK_ANALOG_STICK_UP, @@ -573,6 +572,20 @@ CAddonButtonMap::DriverMap CAddonButtonMap::CreateLookupTable(const FeatureMap& break; } + case JOYSTICK_FEATURE_TYPE_RELPOINTER: + { + std::vector<JOYSTICK_FEATURE_PRIMITIVE> primitives = { + JOYSTICK_RELPOINTER_UP, + JOYSTICK_RELPOINTER_DOWN, + JOYSTICK_RELPOINTER_RIGHT, + JOYSTICK_RELPOINTER_LEFT, + }; + + for (auto primitive : primitives) + driverMap[CPeripheralAddonTranslator::TranslatePrimitive(feature.Primitive(primitive))] = it->first; + break; + } + default: break; } @@ -581,7 +594,7 @@ CAddonButtonMap::DriverMap CAddonButtonMap::CreateLookupTable(const FeatureMap& return driverMap; } -JOYSTICK_FEATURE_PRIMITIVE CAddonButtonMap::GetPrimitiveIndex(JOYSTICK::ANALOG_STICK_DIRECTION dir) +JOYSTICK_FEATURE_PRIMITIVE CAddonButtonMap::GetAnalogStickIndex(JOYSTICK::ANALOG_STICK_DIRECTION dir) { using namespace JOYSTICK; @@ -597,6 +610,22 @@ JOYSTICK_FEATURE_PRIMITIVE CAddonButtonMap::GetPrimitiveIndex(JOYSTICK::ANALOG_S return static_cast<JOYSTICK_FEATURE_PRIMITIVE>(0); } +JOYSTICK_FEATURE_PRIMITIVE CAddonButtonMap::GetRelativePointerIndex(JOYSTICK::RELATIVE_POINTER_DIRECTION dir) +{ + using namespace JOYSTICK; + + switch (dir) + { + case RELATIVE_POINTER_DIRECTION::UP: return JOYSTICK_RELPOINTER_UP; + case RELATIVE_POINTER_DIRECTION::DOWN: return JOYSTICK_RELPOINTER_DOWN; + case RELATIVE_POINTER_DIRECTION::RIGHT: return JOYSTICK_RELPOINTER_RIGHT; + case RELATIVE_POINTER_DIRECTION::LEFT: return JOYSTICK_RELPOINTER_LEFT; + default: break; + } + + return static_cast<JOYSTICK_FEATURE_PRIMITIVE>(0); +} + JOYSTICK_FEATURE_PRIMITIVE CAddonButtonMap::GetPrimitiveIndex(JOYSTICK::WHEEL_DIRECTION dir) { using namespace JOYSTICK; diff --git a/xbmc/peripherals/addons/AddonButtonMap.h b/xbmc/peripherals/addons/AddonButtonMap.h index 628cb0d194..2a920cd527 100644 --- a/xbmc/peripherals/addons/AddonButtonMap.h +++ b/xbmc/peripherals/addons/AddonButtonMap.h @@ -82,13 +82,13 @@ namespace PERIPHERALS bool GetRelativePointer( const KODI::JOYSTICK::FeatureName& feature, - KODI::JOYSTICK::ANALOG_STICK_DIRECTION direction, + KODI::JOYSTICK::RELATIVE_POINTER_DIRECTION direction, KODI::JOYSTICK::CDriverPrimitive& primitive ) override; void AddRelativePointer( const KODI::JOYSTICK::FeatureName& feature, - KODI::JOYSTICK::ANALOG_STICK_DIRECTION direction, + KODI::JOYSTICK::RELATIVE_POINTER_DIRECTION direction, const KODI::JOYSTICK::CDriverPrimitive& primitive ) override; @@ -157,7 +157,8 @@ namespace PERIPHERALS // Utility functions static DriverMap CreateLookupTable(const FeatureMap& features); - static JOYSTICK_FEATURE_PRIMITIVE GetPrimitiveIndex(KODI::JOYSTICK::ANALOG_STICK_DIRECTION dir); + static JOYSTICK_FEATURE_PRIMITIVE GetAnalogStickIndex(KODI::JOYSTICK::ANALOG_STICK_DIRECTION dir); + static JOYSTICK_FEATURE_PRIMITIVE GetRelativePointerIndex(KODI::JOYSTICK::RELATIVE_POINTER_DIRECTION dir); static JOYSTICK_FEATURE_PRIMITIVE GetPrimitiveIndex(KODI::JOYSTICK::WHEEL_DIRECTION dir); static JOYSTICK_FEATURE_PRIMITIVE GetPrimitiveIndex(KODI::JOYSTICK::THROTTLE_DIRECTION dir); diff --git a/xbmc/peripherals/addons/AddonButtonMapping.cpp b/xbmc/peripherals/addons/AddonButtonMapping.cpp index 03e47efe7e..6ba9fa2a3a 100644 --- a/xbmc/peripherals/addons/AddonButtonMapping.cpp +++ b/xbmc/peripherals/addons/AddonButtonMapping.cpp @@ -104,6 +104,28 @@ void CAddonButtonMapping::OnKeyRelease(const CKey& key) m_buttonMapping->OnKeyRelease(key); } +bool CAddonButtonMapping::OnPosition(int x, int y) +{ + if (m_buttonMapping) + return m_buttonMapping->OnPosition(x, y); + + return false; +} + +bool CAddonButtonMapping::OnButtonPress(MOUSE::BUTTON_ID button) +{ + if (m_buttonMapping) + return m_buttonMapping->OnButtonPress(button); + + return false; +} + +void CAddonButtonMapping::OnButtonRelease(MOUSE::BUTTON_ID button) +{ + if (m_buttonMapping) + m_buttonMapping->OnButtonRelease(button); +} + void CAddonButtonMapping::SaveButtonMap() { if (m_buttonMapping) diff --git a/xbmc/peripherals/addons/AddonButtonMapping.h b/xbmc/peripherals/addons/AddonButtonMapping.h index e19a174b19..d5c9446e4c 100644 --- a/xbmc/peripherals/addons/AddonButtonMapping.h +++ b/xbmc/peripherals/addons/AddonButtonMapping.h @@ -22,6 +22,7 @@ #include "input/joysticks/interfaces/IButtonMapCallback.h" #include "input/joysticks/interfaces/IDriverHandler.h" #include "input/keyboard/interfaces/IKeyboardDriverHandler.h" +#include "input/mouse/interfaces/IMouseDriverHandler.h" #include <memory> @@ -42,6 +43,7 @@ namespace PERIPHERALS class CAddonButtonMapping : public KODI::JOYSTICK::IDriverHandler, public KODI::KEYBOARD::IKeyboardDriverHandler, + public KODI::MOUSE::IMouseDriverHandler, public KODI::JOYSTICK::IButtonMapCallback { public: @@ -59,6 +61,11 @@ namespace PERIPHERALS bool OnKeyPress(const CKey& key) override; void OnKeyRelease(const CKey& key) override; + // implementation of IMouseDriverHandler + bool OnPosition(int x, int y) override; + bool OnButtonPress(KODI::MOUSE::BUTTON_ID button) override; + void OnButtonRelease(KODI::MOUSE::BUTTON_ID button) override; + // implementation of IButtonMapCallback void SaveButtonMap() override; void ResetIgnoredPrimitives() override; diff --git a/xbmc/peripherals/addons/AddonInputHandling.cpp b/xbmc/peripherals/addons/AddonInputHandling.cpp index add2ebdaa7..378e6f8f8f 100644 --- a/xbmc/peripherals/addons/AddonInputHandling.cpp +++ b/xbmc/peripherals/addons/AddonInputHandling.cpp @@ -25,6 +25,8 @@ #include "input/joysticks/interfaces/IDriverReceiver.h" #include "input/keyboard/generic/KeyboardInputHandling.h" #include "input/keyboard/interfaces/IKeyboardInputHandler.h" +#include "input/mouse/generic/MouseInputHandling.h" +#include "input/mouse/interfaces/IMouseInputHandler.h" #include "peripherals/addons/AddonButtonMap.h" #include "peripherals/devices/PeripheralJoystick.h" #include "peripherals/Peripherals.h" @@ -86,6 +88,28 @@ CAddonInputHandling::CAddonInputHandling(CPeripherals& manager, CPeripheral* per } } +CAddonInputHandling::CAddonInputHandling(CPeripherals& manager, CPeripheral* peripheral, MOUSE::IMouseInputHandler* handler) +{ + PeripheralAddonPtr addon = manager.GetAddonWithButtonMap(peripheral); + + if (!addon) + { + CLog::Log(LOGDEBUG, "Failed to locate add-on for \"%s\"", peripheral->DeviceName().c_str()); + } + else + { + m_buttonMap.reset(new CAddonButtonMap(peripheral, addon, handler->ControllerID())); + if (m_buttonMap->Load()) + { + m_mouseHandler.reset(new MOUSE::CMouseInputHandling(handler, m_buttonMap.get())); + } + else + { + m_buttonMap.reset(); + } + } +} + CAddonInputHandling::~CAddonInputHandling(void) { m_driverHandler.reset(); @@ -138,6 +162,29 @@ void CAddonInputHandling::OnKeyRelease(const CKey& key) m_keyboardHandler->OnKeyRelease(key); } + +bool CAddonInputHandling::OnPosition(int x, int y) +{ + if (m_mouseHandler) + return m_mouseHandler->OnPosition(x, y); + + return false; +} + +bool CAddonInputHandling::OnButtonPress(MOUSE::BUTTON_ID button) +{ + if (m_mouseHandler) + return m_mouseHandler->OnButtonPress(button); + + return false; +} + +void CAddonInputHandling::OnButtonRelease(MOUSE::BUTTON_ID button) +{ + if (m_mouseHandler) + m_mouseHandler->OnButtonRelease(button); +} + bool CAddonInputHandling::SetRumbleState(const JOYSTICK::FeatureName& feature, float magnitude) { if (m_inputReceiver) diff --git a/xbmc/peripherals/addons/AddonInputHandling.h b/xbmc/peripherals/addons/AddonInputHandling.h index 3a3a87390c..2ab93fe582 100644 --- a/xbmc/peripherals/addons/AddonInputHandling.h +++ b/xbmc/peripherals/addons/AddonInputHandling.h @@ -22,6 +22,7 @@ #include "input/joysticks/interfaces/IDriverHandler.h" #include "input/joysticks/interfaces/IInputReceiver.h" #include "input/keyboard/interfaces/IKeyboardDriverHandler.h" +#include "input/mouse/interfaces/IMouseDriverHandler.h" #include <memory> @@ -38,6 +39,11 @@ namespace KEYBOARD { class IKeyboardInputHandler; } + +namespace MOUSE +{ + class IMouseInputHandler; +} } namespace PERIPHERALS @@ -47,7 +53,8 @@ namespace PERIPHERALS class CAddonInputHandling : public KODI::JOYSTICK::IDriverHandler, public KODI::JOYSTICK::IInputReceiver, - public KODI::KEYBOARD::IKeyboardDriverHandler + public KODI::KEYBOARD::IKeyboardDriverHandler, + public KODI::MOUSE::IMouseDriverHandler { public: CAddonInputHandling(CPeripherals& manager, @@ -59,6 +66,10 @@ namespace PERIPHERALS CPeripheral* peripheral, KODI::KEYBOARD::IKeyboardInputHandler* handler); + CAddonInputHandling(CPeripherals& manager, + CPeripheral* peripheral, + KODI::MOUSE::IMouseInputHandler* handler); + ~CAddonInputHandling(void) override; // implementation of IDriverHandler @@ -71,6 +82,11 @@ namespace PERIPHERALS bool OnKeyPress(const CKey& key) override; void OnKeyRelease(const CKey& key) override; + // implementation of IMouseDriverHandler + bool OnPosition(int x, int y) override; + bool OnButtonPress(KODI::MOUSE::BUTTON_ID button) override; + void OnButtonRelease(KODI::MOUSE::BUTTON_ID button) override; + // implementation of IInputReceiver bool SetRumbleState(const KODI::JOYSTICK::FeatureName& feature, float magnitude) override; @@ -78,6 +94,7 @@ namespace PERIPHERALS std::unique_ptr<KODI::JOYSTICK::IDriverHandler> m_driverHandler; std::unique_ptr<KODI::JOYSTICK::IInputReceiver> m_inputReceiver; std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler> m_keyboardHandler; + std::unique_ptr<KODI::MOUSE::IMouseDriverHandler> m_mouseHandler; std::unique_ptr<KODI::JOYSTICK::IButtonMap> m_buttonMap; }; } diff --git a/xbmc/peripherals/addons/PeripheralAddon.cpp b/xbmc/peripherals/addons/PeripheralAddon.cpp index df90468cb1..f9be30d623 100644 --- a/xbmc/peripherals/addons/PeripheralAddon.cpp +++ b/xbmc/peripherals/addons/PeripheralAddon.cpp @@ -52,6 +52,9 @@ using namespace XFILE; #define KEYBOARD_BUTTON_MAP_NAME "Keyboard" #define KEYBOARD_PROVIDER "application" +#define MOUSE_BUTTON_MAP_NAME "Mouse" +#define MOUSE_PROVIDER "application" + #ifndef SAFE_DELETE #define SAFE_DELETE(p) do { delete (p); (p) = NULL; } while (0) #endif @@ -828,10 +831,11 @@ void CPeripheralAddon::GetJoystickInfo(const CPeripheral* device, kodi::addon::J joystickInfo.SetMotorCount(joystick->MotorCount()); joystickInfo.SetSupportsPowerOff(joystick->SupportsPowerOff()); } - else if (device->Type() == PERIPHERAL_KEYBOARD) + else if (device->Type() == PERIPHERAL_KEYBOARD || + device->Type() == PERIPHERAL_MOUSE) { - joystickInfo.SetName(GetDeviceName(PERIPHERAL_KEYBOARD)); // Override name with non-localized version - joystickInfo.SetProvider(GetProvider(PERIPHERAL_KEYBOARD)); + joystickInfo.SetName(GetDeviceName(device->Type())); // Override name with non-localized version + joystickInfo.SetProvider(GetProvider(device->Type())); } } @@ -863,6 +867,8 @@ std::string CPeripheralAddon::GetDeviceName(PeripheralType type) { case PERIPHERAL_KEYBOARD: return KEYBOARD_BUTTON_MAP_NAME; + case PERIPHERAL_MOUSE: + return MOUSE_BUTTON_MAP_NAME; default: break; } @@ -876,6 +882,8 @@ std::string CPeripheralAddon::GetProvider(PeripheralType type) { case PERIPHERAL_KEYBOARD: return KEYBOARD_PROVIDER; + case PERIPHERAL_MOUSE: + return MOUSE_PROVIDER; default: break; } diff --git a/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp b/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp index 5c0b659322..5e7ceedcee 100644 --- a/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp +++ b/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp @@ -116,6 +116,16 @@ CDriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const kodi::addo retVal = CDriverPrimitive(keycode); break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOUSE_BUTTON: + { + retVal = CDriverPrimitive(TranslateMouseButton(primitive.MouseIndex())); + break; + } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_RELPOINTER_DIRECTION: + { + retVal = CDriverPrimitive(TranslateRelPointerDirection(primitive.RelPointerDirection())); + break; + } default: break; } @@ -155,6 +165,16 @@ kodi::addon::DriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(cons retVal = kodi::addon::DriverPrimitive(keysym); break; } + case PRIMITIVE_TYPE::MOUSE_BUTTON: + { + retVal = kodi::addon::DriverPrimitive::CreateMouseButton(TranslateMouseButton(primitive.MouseButton())); + break; + } + case PRIMITIVE_TYPE::RELATIVE_POINTER: + { + retVal = kodi::addon::DriverPrimitive(TranslateRelPointerDirection(primitive.PointerDirection())); + break; + } default: break; } @@ -195,7 +215,7 @@ HAT_DIRECTION CPeripheralAddonTranslator::TranslateHatDirection(JOYSTICK_DRIVER_ default: break; } - return HAT_DIRECTION::UNKNOWN; + return HAT_DIRECTION::NONE; } JOYSTICK_DRIVER_HAT_DIRECTION CPeripheralAddonTranslator::TranslateHatDirection(HAT_DIRECTION dir) @@ -214,7 +234,7 @@ JOYSTICK_DRIVER_HAT_DIRECTION CPeripheralAddonTranslator::TranslateHatDirection( HAT_STATE CPeripheralAddonTranslator::TranslateHatState(JOYSTICK_STATE_HAT state) { - HAT_STATE translatedState = HAT_STATE::UNPRESSED; + HAT_STATE translatedState = HAT_STATE::NONE; if (state & JOYSTICK_STATE_HAT_UP) translatedState |= HAT_STATE::UP; if (state & JOYSTICK_STATE_HAT_DOWN) translatedState |= HAT_STATE::DOWN; @@ -248,6 +268,75 @@ JOYSTICK_DRIVER_SEMIAXIS_DIRECTION CPeripheralAddonTranslator::TranslateSemiAxis return JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN; } +MOUSE::BUTTON_ID CPeripheralAddonTranslator::TranslateMouseButton(JOYSTICK_DRIVER_MOUSE_INDEX button) +{ + switch (button) + { + case JOYSTICK_DRIVER_MOUSE_INDEX_LEFT: return MOUSE::BUTTON_ID::LEFT; + case JOYSTICK_DRIVER_MOUSE_INDEX_RIGHT: return MOUSE::BUTTON_ID::RIGHT; + case JOYSTICK_DRIVER_MOUSE_INDEX_MIDDLE: return MOUSE::BUTTON_ID::MIDDLE; + case JOYSTICK_DRIVER_MOUSE_INDEX_BUTTON4: return MOUSE::BUTTON_ID::BUTTON4; + case JOYSTICK_DRIVER_MOUSE_INDEX_BUTTON5: return MOUSE::BUTTON_ID::BUTTON5; + case JOYSTICK_DRIVER_MOUSE_INDEX_WHEEL_UP: return MOUSE::BUTTON_ID::WHEEL_UP; + case JOYSTICK_DRIVER_MOUSE_INDEX_WHEEL_DOWN: return MOUSE::BUTTON_ID::WHEEL_DOWN; + case JOYSTICK_DRIVER_MOUSE_INDEX_HORIZ_WHEEL_LEFT: return MOUSE::BUTTON_ID::HORIZ_WHEEL_LEFT; + case JOYSTICK_DRIVER_MOUSE_INDEX_HORIZ_WHEEL_RIGHT: return MOUSE::BUTTON_ID::HORIZ_WHEEL_RIGHT; + default: + break; + } + + return MOUSE::BUTTON_ID::UNKNOWN; +} + +JOYSTICK_DRIVER_MOUSE_INDEX CPeripheralAddonTranslator::TranslateMouseButton(MOUSE::BUTTON_ID button) +{ + switch (button) + { + case MOUSE::BUTTON_ID::LEFT: return JOYSTICK_DRIVER_MOUSE_INDEX_LEFT; + case MOUSE::BUTTON_ID::RIGHT: return JOYSTICK_DRIVER_MOUSE_INDEX_RIGHT; + case MOUSE::BUTTON_ID::MIDDLE: return JOYSTICK_DRIVER_MOUSE_INDEX_MIDDLE; + case MOUSE::BUTTON_ID::BUTTON4: return JOYSTICK_DRIVER_MOUSE_INDEX_BUTTON4; + case MOUSE::BUTTON_ID::BUTTON5: return JOYSTICK_DRIVER_MOUSE_INDEX_BUTTON5; + case MOUSE::BUTTON_ID::WHEEL_UP: return JOYSTICK_DRIVER_MOUSE_INDEX_WHEEL_UP; + case MOUSE::BUTTON_ID::WHEEL_DOWN: return JOYSTICK_DRIVER_MOUSE_INDEX_WHEEL_DOWN; + case MOUSE::BUTTON_ID::HORIZ_WHEEL_LEFT: return JOYSTICK_DRIVER_MOUSE_INDEX_HORIZ_WHEEL_LEFT; + case MOUSE::BUTTON_ID::HORIZ_WHEEL_RIGHT: return JOYSTICK_DRIVER_MOUSE_INDEX_HORIZ_WHEEL_RIGHT; + default: + break; + } + + return JOYSTICK_DRIVER_MOUSE_INDEX_UNKNOWN; +} + +RELATIVE_POINTER_DIRECTION CPeripheralAddonTranslator::TranslateRelPointerDirection(JOYSTICK_DRIVER_RELPOINTER_DIRECTION dir) +{ + switch (dir) + { + case JOYSTICK_DRIVER_RELPOINTER_LEFT: return RELATIVE_POINTER_DIRECTION::LEFT; + case JOYSTICK_DRIVER_RELPOINTER_RIGHT: return RELATIVE_POINTER_DIRECTION::RIGHT; + case JOYSTICK_DRIVER_RELPOINTER_UP: return RELATIVE_POINTER_DIRECTION::UP; + case JOYSTICK_DRIVER_RELPOINTER_DOWN: return RELATIVE_POINTER_DIRECTION::DOWN; + default: + break; + } + + return RELATIVE_POINTER_DIRECTION::NONE; +} + +JOYSTICK_DRIVER_RELPOINTER_DIRECTION CPeripheralAddonTranslator::TranslateRelPointerDirection(RELATIVE_POINTER_DIRECTION dir) +{ + switch (dir) + { + case RELATIVE_POINTER_DIRECTION::UP: return JOYSTICK_DRIVER_RELPOINTER_UP; + case RELATIVE_POINTER_DIRECTION::DOWN: return JOYSTICK_DRIVER_RELPOINTER_DOWN; + case RELATIVE_POINTER_DIRECTION::RIGHT: return JOYSTICK_DRIVER_RELPOINTER_RIGHT; + case RELATIVE_POINTER_DIRECTION::LEFT: return JOYSTICK_DRIVER_RELPOINTER_LEFT; + default: + break; + } + return JOYSTICK_DRIVER_RELPOINTER_UNKNOWN; +} + JOYSTICK::FEATURE_TYPE CPeripheralAddonTranslator::TranslateFeatureType(JOYSTICK_FEATURE_TYPE type) { switch (type) diff --git a/xbmc/peripherals/addons/PeripheralAddonTranslator.h b/xbmc/peripherals/addons/PeripheralAddonTranslator.h index 35c40791e1..683b9e9177 100644 --- a/xbmc/peripherals/addons/PeripheralAddonTranslator.h +++ b/xbmc/peripherals/addons/PeripheralAddonTranslator.h @@ -23,6 +23,7 @@ #include "addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h" #include "input/joysticks/DriverPrimitive.h" #include "input/joysticks/JoystickTypes.h" +#include "input/mouse/MouseTypes.h" #include "peripherals/PeripheralTypes.h" #include <vector> @@ -51,6 +52,12 @@ namespace PERIPHERALS static KODI::JOYSTICK::SEMIAXIS_DIRECTION TranslateSemiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_DIRECTION dir); static JOYSTICK_DRIVER_SEMIAXIS_DIRECTION TranslateSemiAxisDirection(KODI::JOYSTICK::SEMIAXIS_DIRECTION dir); + static KODI::MOUSE::BUTTON_ID TranslateMouseButton(JOYSTICK_DRIVER_MOUSE_INDEX button); + static JOYSTICK_DRIVER_MOUSE_INDEX TranslateMouseButton(KODI::MOUSE::BUTTON_ID button); + + static KODI::JOYSTICK::RELATIVE_POINTER_DIRECTION TranslateRelPointerDirection(JOYSTICK_DRIVER_RELPOINTER_DIRECTION dir); + static JOYSTICK_DRIVER_RELPOINTER_DIRECTION TranslateRelPointerDirection(KODI::JOYSTICK::RELATIVE_POINTER_DIRECTION dir); + static KODI::JOYSTICK::FEATURE_TYPE TranslateFeatureType(JOYSTICK_FEATURE_TYPE type); static JOYSTICK_FEATURE_TYPE TranslateFeatureType(KODI::JOYSTICK::FEATURE_TYPE type); diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp index 51e1df8835..4603dd90a8 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp +++ b/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp @@ -56,6 +56,28 @@ bool CPeripheralBusApplication::PerformDeviceScan(PeripheralScanResults& results results.m_results.push_back(result); } + bool bHasMouse = CServiceBroker::GetSettings().GetBool(CSettings::SETTING_INPUT_ENABLEMOUSE); + + //! @todo Fix game clients to handle mouse disconnecting + //! For now mouse is always connected + bHasMouse = true; + + if (bHasMouse) + { + PeripheralScanResult result(Type()); + result.m_type = PERIPHERAL_MOUSE; + result.m_strDeviceName = g_localizeStrings.Get(35171); // "Mouse" + result.m_strLocation = PeripheralTypeTranslator::TypeToString(PERIPHERAL_MOUSE); + result.m_iVendorId = 0; + result.m_iProductId = 0; + result.m_mappedType = PERIPHERAL_MOUSE; + result.m_mappedBusType = Type(); + result.m_iSequence = 0; + + if (!results.ContainsResult(result)) + results.m_results.push_back(result); + } + return true; } diff --git a/xbmc/peripherals/devices/CMakeLists.txt b/xbmc/peripherals/devices/CMakeLists.txt index bd967340b9..57795f5ffd 100644 --- a/xbmc/peripherals/devices/CMakeLists.txt +++ b/xbmc/peripherals/devices/CMakeLists.txt @@ -5,6 +5,7 @@ set(SOURCES Peripheral.cpp PeripheralImon.cpp PeripheralJoystick.cpp PeripheralKeyboard.cpp + PeripheralMouse.cpp PeripheralNIC.cpp PeripheralNyxboard.cpp PeripheralTuner.cpp) @@ -16,6 +17,7 @@ set(HEADERS Peripheral.h PeripheralImon.h PeripheralJoystick.h PeripheralKeyboard.h + PeripheralMouse.h PeripheralNIC.h PeripheralNyxboard.h PeripheralTuner.h) diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp index 9e0ca5c9e7..d8d2e5f8d6 100644 --- a/xbmc/peripherals/devices/Peripheral.cpp +++ b/xbmc/peripherals/devices/Peripheral.cpp @@ -605,6 +605,27 @@ void CPeripheral::UnregisterKeyboardHandler(KEYBOARD::IKeyboardInputHandler* han } } +void CPeripheral::RegisterMouseHandler(MOUSE::IMouseInputHandler* handler, bool bPromiscuous) +{ + auto it = m_mouseHandlers.find(handler); + if (it == m_mouseHandlers.end()) + { + std::unique_ptr<CAddonInputHandling> addonInput(new CAddonInputHandling(m_manager, this, handler)); + RegisterMouseDriverHandler(addonInput.get(), bPromiscuous); + m_mouseHandlers[handler] = std::move(addonInput); + } +} + +void CPeripheral::UnregisterMouseHandler(MOUSE::IMouseInputHandler* handler) +{ + auto it = m_mouseHandlers.find(handler); + if (it != m_mouseHandlers.end()) + { + UnregisterMouseDriverHandler(it->second.get()); + m_mouseHandlers.erase(it); + } +} + void CPeripheral::RegisterJoystickButtonMapper(IButtonMapper* mapper) { auto it = m_buttonMappers.find(mapper); @@ -614,6 +635,7 @@ void CPeripheral::RegisterJoystickButtonMapper(IButtonMapper* mapper) RegisterJoystickDriverHandler(addonMapping.get(), false); RegisterKeyboardDriverHandler(addonMapping.get(), false); + RegisterMouseDriverHandler(addonMapping.get(), false); m_buttonMappers[mapper] = std::move(addonMapping); } @@ -624,6 +646,7 @@ void CPeripheral::UnregisterJoystickButtonMapper(IButtonMapper* mapper) auto it = m_buttonMappers.find(mapper); if (it != m_buttonMappers.end()) { + UnregisterMouseDriverHandler(it->second.get()); UnregisterKeyboardDriverHandler(it->second.get()); UnregisterJoystickDriverHandler(it->second.get()); diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h index 9dd5aaf562..a746948477 100644 --- a/xbmc/peripherals/devices/Peripheral.h +++ b/xbmc/peripherals/devices/Peripheral.h @@ -26,6 +26,7 @@ #include "input/joysticks/interfaces/IInputProvider.h" #include "input/keyboard/interfaces/IKeyboardInputProvider.h" +#include "input/mouse/interfaces/IMouseInputProvider.h" #include "peripherals/PeripheralTypes.h" class TiXmlDocument; @@ -46,6 +47,11 @@ namespace KEYBOARD { class IKeyboardDriverHandler; } + +namespace MOUSE +{ + class IMouseDriverHandler; +} } namespace PERIPHERALS @@ -63,7 +69,8 @@ namespace PERIPHERALS } CecStateChange; class CPeripheral : public KODI::JOYSTICK::IInputProvider, - public KODI::KEYBOARD::IKeyboardInputProvider + public KODI::KEYBOARD::IKeyboardInputProvider, + public KODI::MOUSE::IMouseInputProvider { friend class CGUIDialogPeripheralSettings; @@ -212,6 +219,9 @@ namespace PERIPHERALS virtual void RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler, bool bPromiscuous) { } virtual void UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler) { } + virtual void RegisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler, bool bPromiscuous) { } + virtual void UnregisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler) { } + // implementation of IInputProvider void RegisterInputHandler(KODI::JOYSTICK::IInputHandler* handler, bool bPromiscuous) override; void UnregisterInputHandler(KODI::JOYSTICK::IInputHandler* handler) override; @@ -220,6 +230,10 @@ namespace PERIPHERALS void RegisterKeyboardHandler(KODI::KEYBOARD::IKeyboardInputHandler* handler, bool bPromiscuous) override; void UnregisterKeyboardHandler(KODI::KEYBOARD::IKeyboardInputHandler* handler) override; + // implementation of IMouseInputProvider + void RegisterMouseHandler(KODI::MOUSE::IMouseInputHandler* handler, bool bPromiscuous) override; + void UnregisterMouseHandler(KODI::MOUSE::IMouseInputHandler* handler) override; + virtual void RegisterJoystickButtonMapper(KODI::JOYSTICK::IButtonMapper* mapper); virtual void UnregisterJoystickButtonMapper(KODI::JOYSTICK::IButtonMapper* mapper); @@ -253,6 +267,7 @@ namespace PERIPHERALS CPeripheralBus* m_bus; std::map<KODI::JOYSTICK::IInputHandler*, std::unique_ptr<KODI::JOYSTICK::IDriverHandler>> m_inputHandlers; std::map<KODI::KEYBOARD::IKeyboardInputHandler*, std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler>> m_keyboardHandlers; + std::map<KODI::MOUSE::IMouseInputHandler*, std::unique_ptr<KODI::MOUSE::IMouseDriverHandler>> m_mouseHandlers; std::map<KODI::JOYSTICK::IButtonMapper*, std::unique_ptr<CAddonButtonMapping>> m_buttonMappers; }; } diff --git a/xbmc/peripherals/devices/PeripheralJoystick.cpp b/xbmc/peripherals/devices/PeripheralJoystick.cpp index c8db2a6019..d5cb661089 100644 --- a/xbmc/peripherals/devices/PeripheralJoystick.cpp +++ b/xbmc/peripherals/devices/PeripheralJoystick.cpp @@ -241,7 +241,7 @@ bool CPeripheralJoystick::OnHatMotion(unsigned int hatIndex, HAT_STATE state) DeviceName().c_str(), CJoystickTranslator::HatStateToString(state)); // Avoid sending activated input if the app is in the background - if (state != HAT_STATE::UNPRESSED && !g_application.IsAppFocused()) + if (state != HAT_STATE::NONE && !g_application.IsAppFocused()) return false; CSingleLock lock(m_handlerMutex); @@ -264,7 +264,7 @@ bool CPeripheralJoystick::OnHatMotion(unsigned int hatIndex, HAT_STATE state) // If hat is centered, force bHandled to false to notify all handlers. // This avoids "sticking". - if (state == HAT_STATE::UNPRESSED) + if (state == HAT_STATE::NONE) bHandled = false; // Once a hat is handled, we're done diff --git a/xbmc/peripherals/devices/PeripheralMouse.cpp b/xbmc/peripherals/devices/PeripheralMouse.cpp new file mode 100644 index 0000000000..884bab22d3 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralMouse.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "PeripheralMouse.h" +#include "input/InputManager.h" +#include "peripherals/Peripherals.h" +#include "threads/SingleLock.h" + +#include <sstream> + +using namespace KODI; +using namespace PERIPHERALS; + +CPeripheralMouse::CPeripheralMouse(CPeripherals& manager, const PeripheralScanResult& scanResult, CPeripheralBus* bus) : + CPeripheral(manager, scanResult, bus) +{ + // Initialize CPeripheral + m_features.push_back(FEATURE_MOUSE); +} + +CPeripheralMouse::~CPeripheralMouse(void) +{ + m_manager.GetInputManager().UnregisterMouseDriverHandler(this); +} + +bool CPeripheralMouse::InitialiseFeature(const PeripheralFeature feature) +{ + bool bSuccess = false; + + if (CPeripheral::InitialiseFeature(feature)) + { + if (feature == FEATURE_MOUSE) + { + m_manager.GetInputManager().RegisterMouseDriverHandler(this); + } + + bSuccess = true; + } + + return bSuccess; +} + +void CPeripheralMouse::RegisterMouseDriverHandler(MOUSE::IMouseDriverHandler* handler, bool bPromiscuous) +{ + using namespace KEYBOARD; + + CSingleLock lock(m_mutex); + + MouseHandle handle{ handler, bPromiscuous }; + m_mouseHandlers.insert(m_mouseHandlers.begin(), handle); +} + +void CPeripheralMouse::UnregisterMouseDriverHandler(MOUSE::IMouseDriverHandler* handler) +{ + CSingleLock lock(m_mutex); + + auto it = std::find_if(m_mouseHandlers.begin(), m_mouseHandlers.end(), + [handler](const MouseHandle &handle) + { + return handle.handler == handler; + }); + + if (it != m_mouseHandlers.end()) + m_mouseHandlers.erase(it); +} + +bool CPeripheralMouse::OnPosition(int x, int y) +{ + CSingleLock lock(m_mutex); + + bool bHandled = false; + + // Process promiscuous handlers + for (const MouseHandle &handle : m_mouseHandlers) + { + if (handle.bPromiscuous) + handle.handler->OnPosition(x, y); + } + + // Process handlers until one is handled + for (const MouseHandle &handle : m_mouseHandlers) + { + if (!handle.bPromiscuous) + { + bHandled = handle.handler->OnPosition(x, y); + if (bHandled) + break; + } + } + + return bHandled; +} + +bool CPeripheralMouse::OnButtonPress(MOUSE::BUTTON_ID button) +{ + CSingleLock lock(m_mutex); + + bool bHandled = false; + + // Process promiscuous handlers + for (const MouseHandle &handle : m_mouseHandlers) + { + if (handle.bPromiscuous) + handle.handler->OnButtonPress(button); + } + + // Process handlers until one is handled + for (const MouseHandle &handle : m_mouseHandlers) + { + if (!handle.bPromiscuous) + { + bHandled = handle.handler->OnButtonPress(button); + if (bHandled) + break; + } + } + + return bHandled; +} + +void CPeripheralMouse::OnButtonRelease(MOUSE::BUTTON_ID button) +{ + CSingleLock lock(m_mutex); + + for (const MouseHandle &handle : m_mouseHandlers) + handle.handler->OnButtonRelease(button); +} diff --git a/xbmc/peripherals/devices/PeripheralMouse.h b/xbmc/peripherals/devices/PeripheralMouse.h new file mode 100644 index 0000000000..ff152055cc --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralMouse.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#pragma once + +#include "Peripheral.h" +#include "input/mouse/interfaces/IMouseDriverHandler.h" +#include "threads/CriticalSection.h" + +#include <vector> + +namespace PERIPHERALS +{ + class CPeripheralMouse : public CPeripheral, + public KODI::MOUSE::IMouseDriverHandler + { + public: + CPeripheralMouse(CPeripherals& manager, const PeripheralScanResult& scanResult, CPeripheralBus* bus); + + ~CPeripheralMouse(void) override; + + // implementation of CPeripheral + bool InitialiseFeature(const PeripheralFeature feature) override; + void RegisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler, bool bPromiscuous) override; + void UnregisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler) override; + + // implementation of IMouseDriverHandler + bool OnPosition(int x, int y) override; + bool OnButtonPress(KODI::MOUSE::BUTTON_ID button) override; + void OnButtonRelease(KODI::MOUSE::BUTTON_ID button) override; + + private: + struct MouseHandle + { + KODI::MOUSE::IMouseDriverHandler* handler; + bool bPromiscuous; + }; + + std::vector<MouseHandle> m_mouseHandlers; + CCriticalSection m_mutex; + }; +} diff --git a/xbmc/platform/android/activity/AndroidMouse.cpp b/xbmc/platform/android/activity/AndroidMouse.cpp index 3c771a90db..4973af3e89 100644 --- a/xbmc/platform/android/activity/AndroidMouse.cpp +++ b/xbmc/platform/android/activity/AndroidMouse.cpp @@ -23,7 +23,7 @@ #include "XBMCApp.h" #include "Application.h" #include "guilib/GUIWindowManager.h" -#include "input/MouseStat.h" +#include "input/mouse/MouseStat.h" #include "ServiceBroker.h" #include "windowing/android/WinSystemAndroid.h" diff --git a/xbmc/platform/android/activity/XBMCApp.cpp b/xbmc/platform/android/activity/XBMCApp.cpp index b6caf1a773..e9408eda50 100644 --- a/xbmc/platform/android/activity/XBMCApp.cpp +++ b/xbmc/platform/android/activity/XBMCApp.cpp @@ -82,9 +82,9 @@ #include "guiinfo/GUIInfoLabels.h" #include "platform/android/activity/IInputDeviceCallbacks.h" #include "platform/android/activity/IInputDeviceEventHandler.h" +#include "input/mouse/MouseStat.h" #include "input/Key.h" #include "utils/log.h" -#include "input/MouseStat.h" #include "network/android/NetworkAndroid.h" #include "cores/VideoPlayer/VideoRenderers/RenderManager.h" #include "filesystem/SpecialProtocol.h" diff --git a/xbmc/platform/darwin/ios/IOSExternalTouchController.mm b/xbmc/platform/darwin/ios/IOSExternalTouchController.mm index 459b6d26b8..85f2330b28 100644 --- a/xbmc/platform/darwin/ios/IOSExternalTouchController.mm +++ b/xbmc/platform/darwin/ios/IOSExternalTouchController.mm @@ -18,9 +18,9 @@ * */ -#include "input/MouseStat.h" #include "filesystem/SpecialProtocol.h" #include "guilib/LocalizeStrings.h" +#include "input/mouse/MouseStat.h" #include "Util.h" #import "IOSExternalTouchController.h" diff --git a/xbmc/platform/linux/input/LinuxInputDevices.cpp b/xbmc/platform/linux/input/LinuxInputDevices.cpp index 7791af3418..9afb5b72e8 100644 --- a/xbmc/platform/linux/input/LinuxInputDevices.cpp +++ b/xbmc/platform/linux/input/LinuxInputDevices.cpp @@ -90,11 +90,11 @@ typedef unsigned long kernel_ulong_t; #include <stdio.h> #include "guilib/GraphicContext.h" +#include "input/mouse/MouseStat.h" +#include "input/touch/generic/GenericTouchActionHandler.h" #include "input/XBMC_keysym.h" #include "LinuxInputDevices.h" -#include "input/MouseStat.h" #include "utils/log.h" -#include "input/touch/generic/GenericTouchActionHandler.h" #include "settings/AdvancedSettings.h" #ifndef BITS_PER_LONG diff --git a/xbmc/windowing/WinEventsLinux.cpp b/xbmc/windowing/WinEventsLinux.cpp index a29d2deac1..a76130308f 100644 --- a/xbmc/windowing/WinEventsLinux.cpp +++ b/xbmc/windowing/WinEventsLinux.cpp @@ -23,7 +23,7 @@ #include "XBMC_events.h" #include "input/XBMC_keysym.h" #include "Application.h" -#include "input/MouseStat.h" +#include "input/mouse/MouseStat.h" #include "utils/log.h" #include "powermanagement/PowerManager.h" #include "peripherals/Peripherals.h" diff --git a/xbmc/windowing/X11/WinEventsX11.cpp b/xbmc/windowing/X11/WinEventsX11.cpp index 858b15a24f..4f949153ae 100644 --- a/xbmc/windowing/X11/WinEventsX11.cpp +++ b/xbmc/windowing/X11/WinEventsX11.cpp @@ -33,7 +33,7 @@ #include "utils/log.h" #include "utils/CharsetConverter.h" #include "guilib/GUIWindowManager.h" -#include "input/MouseStat.h" +#include "input/mouse/MouseStat.h" #include "input/InputManager.h" #include "ServiceBroker.h" diff --git a/xbmc/windowing/mir/WinEventsMir.cpp b/xbmc/windowing/mir/WinEventsMir.cpp index ab8b31ef73..195f7bd2bd 100644 --- a/xbmc/windowing/mir/WinEventsMir.cpp +++ b/xbmc/windowing/mir/WinEventsMir.cpp @@ -26,8 +26,8 @@ #include <xkbcommon/xkbcommon-keysyms.h> #include "Application.h" +#include "input/mouse/MouseStat.h" #include "input/Key.h" -#include "input/MouseStat.h" namespace { diff --git a/xbmc/windowing/osx/WinEventsSDL.cpp b/xbmc/windowing/osx/WinEventsSDL.cpp index 8c33b017c9..9742f9a5c4 100644 --- a/xbmc/windowing/osx/WinEventsSDL.cpp +++ b/xbmc/windowing/osx/WinEventsSDL.cpp @@ -27,9 +27,9 @@ #include "GUIUserMessages.h" #include "settings/DisplaySettings.h" #include "guilib/GUIWindowManager.h" +#include "input/mouse/MouseStat.h" #include "input/Key.h" #include "input/InputManager.h" -#include "input/MouseStat.h" #include "windowing/WinSystem.h" #include "platform/darwin/osx/CocoaInterface.h" #include "ServiceBroker.h" diff --git a/xbmc/windowing/wayland/InputProcessorPointer.cpp b/xbmc/windowing/wayland/InputProcessorPointer.cpp index b21758eaaf..f6a9f021af 100644 --- a/xbmc/windowing/wayland/InputProcessorPointer.cpp +++ b/xbmc/windowing/wayland/InputProcessorPointer.cpp @@ -24,7 +24,7 @@ #include <linux/input-event-codes.h> -#include "input/MouseStat.h" +#include "input/mouse/MouseStat.h" using namespace KODI::WINDOWING::WAYLAND; diff --git a/xbmc/windowing/win10/WinEventsWin10.cpp b/xbmc/windowing/win10/WinEventsWin10.cpp index 0abebb1ed7..1010e9218b 100644 --- a/xbmc/windowing/win10/WinEventsWin10.cpp +++ b/xbmc/windowing/win10/WinEventsWin10.cpp @@ -20,11 +20,11 @@ #include "Application.h" #include "guilib/GUIWindowManager.h" -#include "input/Action.h" -#include "input/ActionIDs.h" -#include "input/MouseStat.h" +#include "input/mouse/MouseStat.h" #include "input/touch/generic/GenericTouchActionHandler.h" #include "input/touch/generic/GenericTouchInputHandler.h" +#include "input/Action.h" +#include "input/ActionIDs.h" #include "messaging/ApplicationMessenger.h" #include "rendering/dx/DeviceResources.h" #include "rendering/dx/RenderContext.h" diff --git a/xbmc/windowing/windows/WinEventsWin32.cpp b/xbmc/windowing/windows/WinEventsWin32.cpp index 9428f45bff..b1e4c846d7 100644 --- a/xbmc/windowing/windows/WinEventsWin32.cpp +++ b/xbmc/windowing/windows/WinEventsWin32.cpp @@ -29,10 +29,10 @@ #include "Application.h" #include "guilib/GUIControl.h" // for EVENT_RESULT #include "guilib/GUIWindowManager.h" -#include "input/MouseStat.h" -#include "input/InputManager.h" +#include "input/mouse/MouseStat.h" #include "input/touch/generic/GenericTouchActionHandler.h" #include "input/touch/generic/GenericTouchSwipeDetector.h" +#include "input/InputManager.h" #include "messaging/ApplicationMessenger.h" #include "network/Zeroconf.h" #include "network/ZeroconfBrowser.h" diff --git a/xbmc/windows/GUIWindowPointer.cpp b/xbmc/windows/GUIWindowPointer.cpp index 6b4521e328..1488f81583 100644 --- a/xbmc/windows/GUIWindowPointer.cpp +++ b/xbmc/windows/GUIWindowPointer.cpp @@ -19,7 +19,7 @@ */ #include "GUIWindowPointer.h" -#include "input/MouseStat.h" +#include "input/mouse/MouseStat.h" #include "input/InputManager.h" #include "ServiceBroker.h" #include "windowing/WinSystem.h" |