Skip to content

Commit

Permalink
Joysticks: Implement new keymap handling
Browse files Browse the repository at this point in the history
  • Loading branch information
garbear committed Jun 27, 2017
1 parent b23afee commit 9479aab
Show file tree
Hide file tree
Showing 52 changed files with 1,872 additions and 44 deletions.
1 change: 1 addition & 0 deletions cmake/treedata/common/subdirs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ xbmc/input input
xbmc/input/joysticks input/joysticks
xbmc/input/joysticks/dialogs input/joysticks/dialogs
xbmc/input/joysticks/generic input/joysticks/generic
xbmc/input/joysticks/keymaps input/joysticks/keymaps
xbmc/input/keyboard input/keyboard
xbmc/input/keyboard/generic input/keyboard/generic
xbmc/input/mouse input/mouse
Expand Down
10 changes: 10 additions & 0 deletions xbmc/games/controllers/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ void CController::GetFeatures(std::vector<std::string>& features,
}
}

JOYSTICK::FEATURE_TYPE CController::GetFeatureType(const std::string &feature) const
{
for (auto it = m_layout.Features().begin(); it != m_layout.Features().end(); ++it)
{
if (feature == it->Name())
return it->Type();
}
return JOYSTICK::FEATURE_TYPE::UNKNOWN;
}

JOYSTICK::INPUT_TYPE CController::GetInputType(const std::string& feature) const
{
for (auto it = m_layout.Features().begin(); it != m_layout.Features().end(); ++it)
Expand Down
1 change: 1 addition & 0 deletions xbmc/games/controllers/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class CController : public ADDON::CAddon
std::string Label(void);
std::string ImagePath(void) const;
void GetFeatures(std::vector<std::string>& features, FEATURE_TYPE type = FEATURE_TYPE::UNKNOWN) const;
JOYSTICK::FEATURE_TYPE GetFeatureType(const std::string &feature) const;
JOYSTICK::INPUT_TYPE GetInputType(const std::string& feature) const;

bool LoadLayout(void);
Expand Down
1 change: 1 addition & 0 deletions xbmc/games/controllers/dialogs/GUIDialogAxisDetection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ std::string CGUIDialogAxisDetection::GetDialogHeader()
}

bool CGUIDialogAxisDetection::MapPrimitiveInternal(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive)
{
if (primitive.Type() == JOYSTICK::PRIMITIVE_TYPE::SEMIAXIS)
Expand Down
1 change: 1 addition & 0 deletions xbmc/games/controllers/dialogs/GUIDialogAxisDetection.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace GAME
virtual std::string GetDialogText() override;
virtual std::string GetDialogHeader() override;
virtual bool MapPrimitiveInternal(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive) override;
virtual void OnClose(bool bAccepted) override { }

Expand Down
26 changes: 25 additions & 1 deletion xbmc/games/controllers/dialogs/GUIDialogButtonCapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "input/joysticks/IButtonMap.h"
#include "input/joysticks/IButtonMapCallback.h"
#include "input/joysticks/JoystickUtils.h"
#include "input/IKeymap.h"
#include "input/ActionIDs.h"
#include "peripherals/Peripherals.h"
#include "utils/Variant.h"
Expand Down Expand Up @@ -84,12 +85,35 @@ void CGUIDialogButtonCapture::Process()
}

bool CGUIDialogButtonCapture::MapPrimitive(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive)
{
if (m_bStop)
return false;

return MapPrimitiveInternal(buttonMap, primitive);
// First check to see if driver primitive closes the dialog
if (keymap && keymap->ControllerID() == buttonMap->ControllerID())
{
std::string feature;
if (buttonMap->GetFeature(primitive, feature))
{
const auto &actions = keymap->GetActions(JOYSTICK::CJoystickUtils::MakeKeyName(feature));
if (!actions.empty())
{
switch (actions.begin()->actionId)
{
case ACTION_SELECT_ITEM:
case ACTION_NAV_BACK:
case ACTION_PREVIOUS_MENU:
return false;
default:
break;
}
}
}
}

return MapPrimitiveInternal(buttonMap, keymap, primitive);
}

void CGUIDialogButtonCapture::InstallHooks(void)
Expand Down
2 changes: 2 additions & 0 deletions xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace GAME
virtual bool Emulation(void) const override { return false; }
virtual unsigned int ControllerNumber(void) const override { return 0; }
virtual bool MapPrimitive(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive) override;
virtual void OnEventFrame(const JOYSTICK::IButtonMap* buttonMap, bool bMotion) override { }
virtual void OnLateAxis(const JOYSTICK::IButtonMap* buttonMap, unsigned int axisIndex) override { }
Expand All @@ -65,6 +66,7 @@ namespace GAME
virtual std::string GetDialogText() = 0;
virtual std::string GetDialogHeader() = 0;
virtual bool MapPrimitiveInternal(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive) = 0;
virtual void OnClose(bool bAccepted) = 0;

Expand Down
1 change: 1 addition & 0 deletions xbmc/games/controllers/dialogs/GUIDialogIgnoreInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ std::string CGUIDialogIgnoreInput::GetDialogHeader()
}

bool CGUIDialogIgnoreInput::MapPrimitiveInternal(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive)
{
// Check if we have already started capturing primitives for a device
Expand Down
1 change: 1 addition & 0 deletions xbmc/games/controllers/dialogs/GUIDialogIgnoreInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace GAME
virtual std::string GetDialogText() override;
virtual std::string GetDialogHeader() override;
virtual bool MapPrimitiveInternal(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive) override;
void OnClose(bool bAccepted) override;

Expand Down
44 changes: 44 additions & 0 deletions xbmc/games/controllers/windows/GUIConfigurationWizard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#include "games/controllers/ControllerFeature.h"
#include "input/joysticks/IButtonMap.h"
#include "input/joysticks/IButtonMapCallback.h"
#include "input/joysticks/JoystickUtils.h"
#include "input/keyboard/KeymapActionMap.h"
#include "input/InputManager.h"
#include "input/IKeymap.h"
#include "peripherals/Peripherals.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
Expand Down Expand Up @@ -188,6 +190,7 @@ void CGUIConfigurationWizard::Process(void)
}

bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive)
{
using namespace JOYSTICK;
Expand All @@ -198,6 +201,47 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap,
if (primitive.Type() == PRIMITIVE_TYPE::BUTTON &&
primitive.Index() == ESC_KEY_CODE)
{
bool bIsCancelAction = false;

//! @todo This only succeeds for game.controller.default; no actions are
// currently defined for other controllers
if (keymap)
{
std::string feature;
if (buttonMap->GetFeature(primitive, feature))
{
const auto &actions = keymap->GetActions(CJoystickUtils::MakeKeyName(feature));
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;
}
}
}
}

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;
}
else if (primitive.Type() == PRIMITIVE_TYPE::BUTTON &&
primitive.Index() == ESC_KEY_CODE)
{
// Handle esc key
bHandled = Abort(false);
}
else if (m_history.find(primitive) != m_history.end())
Expand Down
1 change: 1 addition & 0 deletions xbmc/games/controllers/windows/GUIConfigurationWizard.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ namespace GAME
virtual bool Emulation(void) const override { return m_bEmulation; }
virtual unsigned int ControllerNumber(void) const override { return m_controllerNumber; }
virtual bool MapPrimitive(JOYSTICK::IButtonMap* buttonMap,
IKeymap* keymap,
const JOYSTICK::CDriverPrimitive& primitive) override;
virtual void OnEventFrame(const JOYSTICK::IButtonMap* buttonMap, bool bMotion) override;
virtual void OnLateAxis(const JOYSTICK::IButtonMap* buttonMap, unsigned int axisIndex) override;
Expand Down
20 changes: 20 additions & 0 deletions xbmc/games/ports/InputSink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,23 @@ bool CInputSink::AcceptsInput(const std::string& feature) const
{
return m_gameClient.AcceptsInput();
}

bool CInputSink::OnButtonPress(const std::string& feature, bool bPressed)
{
return true;
}

bool CInputSink::OnButtonMotion(const std::string& feature, float magnitude, unsigned int motionTimeMs)
{
return true;
}

bool CInputSink::OnAnalogStickMotion(const std::string& feature, float x, float y, unsigned int motionTimeMs)
{
return true;
}

bool CInputSink::OnAccelerometerMotion(const std::string& feature, float x, float y, float z)
{
return true;
}
8 changes: 4 additions & 4 deletions xbmc/games/ports/InputSink.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ namespace GAME
virtual std::string ControllerID(void) const override;
virtual bool HasFeature(const std::string& feature) const override { return true; }
virtual bool AcceptsInput(const std::string& feature) const override;
virtual bool OnButtonPress(const std::string& feature, bool bPressed) override { return true; }
virtual bool OnButtonPress(const std::string& feature, bool bPressed) override;
virtual void OnButtonHold(const std::string& feature, unsigned int holdTimeMs) override { }
virtual bool OnButtonMotion(const std::string& feature, float magnitude, unsigned int motionTimeMs) override { return true; }
virtual bool OnAnalogStickMotion(const std::string& feature, float x, float y, unsigned int motionTimeMs) override { return true; }
virtual bool OnAccelerometerMotion(const std::string& feature, float x, float y, float z) override { return true; }
virtual bool OnButtonMotion(const std::string& feature, float magnitude, unsigned int motionTimeMs) override;
virtual bool OnAnalogStickMotion(const std::string& feature, float x, float y, unsigned int motionTimeMs) override;
virtual bool OnAccelerometerMotion(const std::string& feature, float x, float y, float z) override;

private:
const CGameClient &m_gameClient;
Expand Down
66 changes: 63 additions & 3 deletions xbmc/games/ports/Port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@

#include "Port.h"
#include "InputSink.h"
#include "games/addons/GameClient.h"
#include "guilib/WindowIDs.h"
#include "input/joysticks/keymaps/KeymapHandling.h"
#include "peripherals/devices/Peripheral.h"

using namespace KODI;
using namespace GAME;

CPort::CPort(JOYSTICK::IInputHandler *gameInput, CGameClient &gameClient) :
m_gameInput(gameInput),
m_gameClient(gameClient),
m_inputSink(new CInputSink(gameClient))
{
}
Expand All @@ -38,16 +42,72 @@ CPort::~CPort()
void CPort::RegisterInput(JOYSTICK::IInputProvider *provider)
{
// Give input sink the lowest priority by registering it before the other
// non-promiscuous input handlers
// input handlers
provider->RegisterInputHandler(m_inputSink.get(), false);

// Register input handler
provider->RegisterInputHandler(m_gameInput, false);
provider->RegisterInputHandler(this, false);

// Register GUI input
m_appInput.reset(new JOYSTICK::CKeymapHandling(provider, false, this));
}

void CPort::UnregisterInput(JOYSTICK::IInputProvider *provider)
{
// Unregister in reverse order
provider->UnregisterInputHandler(m_gameInput);
m_appInput.reset();
provider->UnregisterInputHandler(this);
provider->UnregisterInputHandler(m_inputSink.get());
}

std::string CPort::ControllerID() const
{
return m_gameInput->ControllerID();
}

bool CPort::AcceptsInput(const std::string& feature) const
{
return m_gameClient.AcceptsInput();
}

bool CPort::OnButtonPress(const std::string& feature, bool bPressed)
{
if (bPressed && !m_gameClient.AcceptsInput())
return false;

return m_gameInput->OnButtonPress(feature, bPressed);
}

void CPort::OnButtonHold(const std::string& feature, unsigned int holdTimeMs)
{
m_gameInput->OnButtonHold(feature, holdTimeMs);
}

bool CPort::OnButtonMotion(const std::string& feature, float magnitude, unsigned int motionTimeMs)
{
if (magnitude > 0.0f && !m_gameClient.AcceptsInput())
return false;

return m_gameInput->OnButtonMotion(feature, magnitude, motionTimeMs);
}

bool CPort::OnAnalogStickMotion(const std::string& feature, float x, float y, unsigned int motionTimeMs)
{
if ((x != 0.0f || y != 0.0f) && !m_gameClient.AcceptsInput())
return false;

return m_gameInput->OnAnalogStickMotion(feature, x, y, motionTimeMs);
}

bool CPort::OnAccelerometerMotion(const std::string& feature, float x, float y, float z)
{
if (!m_gameClient.AcceptsInput())
return false;

return m_gameInput->OnAccelerometerMotion(feature, x, y, z);
}

int CPort::GetWindowID() const
{
return WINDOW_FULLSCREEN_GAME;
}
34 changes: 27 additions & 7 deletions xbmc/games/ports/Port.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,25 @@
*/
#pragma once

#include <memory>
#include "input/joysticks/IInputHandler.h"
#include "input/KeymapEnvironment.h"

namespace PERIPHERALS
{
class CPeripheral;
}
#include <memory>

namespace KODI
{
namespace JOYSTICK
{
class IInputHandler;
class CKeymapHandling;
class IInputProvider;
}

namespace GAME
{
class CGameClient;

class CPort
class CPort : public JOYSTICK::IInputHandler,
public IKeymapEnvironment
{
public:
CPort(JOYSTICK::IInputHandler* gameInput, CGameClient& gameClient);
Expand All @@ -49,9 +48,30 @@ namespace GAME

JOYSTICK::IInputHandler *InputHandler() { return m_gameInput; }

// Implementation of IInputHandler
virtual std::string ControllerID() const override;
virtual bool HasFeature(const std::string& feature) const override { return true; }
virtual bool AcceptsInput(const std::string& feature) const override;
virtual bool OnButtonPress(const std::string& feature, bool bPressed) override;
virtual void OnButtonHold(const std::string& feature, unsigned int holdTimeMs) override;
virtual bool OnButtonMotion(const std::string& feature, float magnitude, unsigned int motionTimeMs) override;
virtual bool OnAnalogStickMotion(const std::string& feature, float x, float y, unsigned int motionTimeMs) override;
virtual bool OnAccelerometerMotion(const std::string& feature, float x, float y, float z) override;

// Implementation of IKeymapEnvironment
virtual int GetWindowID() const override;
virtual int GetFallthrough(int windowId) const override { return -1; }
virtual bool UseGlobalFallthrough() const override { return false; }

private:
// Construction parameters
JOYSTICK::IInputHandler* const m_gameInput;
CGameClient& m_gameClient;

// Handles input to Kodi
std::unique_ptr<JOYSTICK::CKeymapHandling> m_appInput;

// Prevents input falling through to Kodi when not handled by the game
std::unique_ptr<JOYSTICK::IInputHandler> m_inputSink;
};
}
Expand Down

0 comments on commit 9479aab

Please sign in to comment.