mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-23 06:19:16 +01:00
Fix Joy-Con Pair Crash + Implement More HID Service Functions
This fixes a Joy-Con Pair bug which caused a crash when a partner device was set to none while being set as a partner. In addition, the following HID service functions were implemented: * GetSupportedNpadStyleSet * ActivateNpadWithRevision * GetNpadJoyHoldType * AcquireNpadStyleSetUpdateEventHandle
This commit is contained in:
parent
6a931b95b0
commit
ee2fdbdf6a
@ -23,9 +23,6 @@ namespace skyline::input {
|
|||||||
if (!activated)
|
if (!activated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto &npad : npads)
|
|
||||||
npad.Disconnect();
|
|
||||||
|
|
||||||
for (auto &controller : controllers)
|
for (auto &controller : controllers)
|
||||||
controller.device = nullptr;
|
controller.device = nullptr;
|
||||||
|
|
||||||
@ -75,6 +72,19 @@ namespace skyline::input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do this to prevent triggering the event unless there's a real change in a device's style, which would be caused if we disconnected all controllers then reconnected them
|
||||||
|
for (auto &device : npads) {
|
||||||
|
bool connected = false;
|
||||||
|
for (auto &controller : controllers) {
|
||||||
|
if (controller.device == &device) {
|
||||||
|
connected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!connected)
|
||||||
|
device.Disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpadManager::Activate() {
|
void NpadManager::Activate() {
|
||||||
|
@ -22,6 +22,8 @@ namespace skyline::input {
|
|||||||
bool activated{false}; //!< If this NpadManager is activated or not
|
bool activated{false}; //!< If this NpadManager is activated or not
|
||||||
std::atomic<bool> updated{false}; //!< If this NpadManager has been updated by the guest
|
std::atomic<bool> updated{false}; //!< If this NpadManager has been updated by the guest
|
||||||
|
|
||||||
|
friend NpadDevice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This translates an NPad's ID into it's index in the array
|
* @brief This translates an NPad's ID into it's index in the array
|
||||||
* @param id The ID of the NPad to translate
|
* @param id The ID of the NPad to translate
|
||||||
|
@ -5,9 +5,12 @@
|
|||||||
#include "npad.h"
|
#include "npad.h"
|
||||||
|
|
||||||
namespace skyline::input {
|
namespace skyline::input {
|
||||||
NpadDevice::NpadDevice(NpadManager &manager, NpadSection §ion, NpadId id) : manager(manager), section(section), id(id) {}
|
NpadDevice::NpadDevice(NpadManager &manager, NpadSection §ion, NpadId id) : manager(manager), section(section), id(id), updateEvent(std::make_shared<kernel::type::KEvent>(manager.state)) {}
|
||||||
|
|
||||||
|
void NpadDevice::Connect(NpadControllerType newType) {
|
||||||
|
if (type == newType)
|
||||||
|
return;
|
||||||
|
|
||||||
void NpadDevice::Connect(NpadControllerType type) {
|
|
||||||
section.header.type = NpadControllerType::None;
|
section.header.type = NpadControllerType::None;
|
||||||
section.deviceType.raw = 0;
|
section.deviceType.raw = 0;
|
||||||
section.buttonProperties.raw = 0;
|
section.buttonProperties.raw = 0;
|
||||||
@ -15,7 +18,7 @@ namespace skyline::input {
|
|||||||
connectionState.raw = 0;
|
connectionState.raw = 0;
|
||||||
connectionState.connected = true;
|
connectionState.connected = true;
|
||||||
|
|
||||||
switch (type) {
|
switch (newType) {
|
||||||
case NpadControllerType::ProController:
|
case NpadControllerType::ProController:
|
||||||
section.header.type = NpadControllerType::ProController;
|
section.header.type = NpadControllerType::ProController;
|
||||||
section.deviceType.fullKey = true;
|
section.deviceType.fullKey = true;
|
||||||
@ -86,10 +89,10 @@ namespace skyline::input {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw exception("Unsupported controller type: {}", type);
|
throw exception("Unsupported controller type: {}", newType);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (newType) {
|
||||||
case NpadControllerType::ProController:
|
case NpadControllerType::ProController:
|
||||||
case NpadControllerType::JoyconLeft:
|
case NpadControllerType::JoyconLeft:
|
||||||
case NpadControllerType::JoyconRight:
|
case NpadControllerType::JoyconRight:
|
||||||
@ -114,19 +117,24 @@ namespace skyline::input {
|
|||||||
section.leftBatteryLevel = NpadBatteryLevel::Full;
|
section.leftBatteryLevel = NpadBatteryLevel::Full;
|
||||||
section.rightBatteryLevel = NpadBatteryLevel::Full;
|
section.rightBatteryLevel = NpadBatteryLevel::Full;
|
||||||
|
|
||||||
this->type = type;
|
type = newType;
|
||||||
controllerInfo = &GetControllerInfo();
|
controllerInfo = &GetControllerInfo();
|
||||||
|
|
||||||
SetButtonState(NpadButton{}, NpadButtonState::Released);
|
updateEvent->Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpadDevice::Disconnect() {
|
void NpadDevice::Disconnect() {
|
||||||
|
if (type == NpadControllerType::None)
|
||||||
|
return;
|
||||||
|
|
||||||
section = {};
|
section = {};
|
||||||
explicitAssignment = false;
|
explicitAssignment = false;
|
||||||
globalTimestamp = 0;
|
globalTimestamp = 0;
|
||||||
|
|
||||||
type = NpadControllerType::None;
|
type = NpadControllerType::None;
|
||||||
controllerInfo = nullptr;
|
controllerInfo = nullptr;
|
||||||
|
|
||||||
|
updateEvent->Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
NpadControllerInfo &NpadDevice::GetControllerInfo() {
|
NpadControllerInfo &NpadDevice::GetControllerInfo() {
|
||||||
@ -149,8 +157,9 @@ namespace skyline::input {
|
|||||||
NpadControllerState &NpadDevice::GetNextEntry(NpadControllerInfo &info) {
|
NpadControllerState &NpadDevice::GetNextEntry(NpadControllerInfo &info) {
|
||||||
auto &lastEntry = info.state.at(info.header.currentEntry);
|
auto &lastEntry = info.state.at(info.header.currentEntry);
|
||||||
|
|
||||||
info.header.currentEntry = (info.header.currentEntry != constant::HidEntryCount - 1) ? info.header.currentEntry + 1 : 0;
|
|
||||||
info.header.timestamp = util::GetTimeTicks();
|
info.header.timestamp = util::GetTimeTicks();
|
||||||
|
info.header.entryCount = std::min(static_cast<u8>(info.header.entryCount + 1), constant::HidEntryCount);
|
||||||
|
info.header.currentEntry = (info.header.currentEntry != constant::HidEntryCount - 1) ? info.header.currentEntry + 1 : 0;
|
||||||
|
|
||||||
auto &entry = info.state.at(info.header.currentEntry);
|
auto &entry = info.state.at(info.header.currentEntry);
|
||||||
|
|
||||||
@ -210,7 +219,7 @@ namespace skyline::input {
|
|||||||
mask = orientedMask;
|
mask = orientedMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NpadControllerState& controllerEntry : {std::ref(GetNextEntry(section.defaultController)), std::ref(GetNextEntry(section.digitalController))})
|
for (NpadControllerState &controllerEntry : {std::ref(GetNextEntry(section.defaultController)), std::ref(GetNextEntry(section.digitalController))})
|
||||||
if (state == NpadButtonState::Pressed)
|
if (state == NpadButtonState::Pressed)
|
||||||
controllerEntry.buttons.raw |= mask.raw;
|
controllerEntry.buttons.raw |= mask.raw;
|
||||||
else
|
else
|
||||||
@ -224,7 +233,7 @@ namespace skyline::input {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto &controllerEntry = GetNextEntry(*controllerInfo);
|
auto &controllerEntry = GetNextEntry(*controllerInfo);
|
||||||
auto& defaultEntry = GetNextEntry(section.defaultController);
|
auto &defaultEntry = GetNextEntry(section.defaultController);
|
||||||
|
|
||||||
if (manager.orientation == NpadJoyOrientation::Vertical && (type != NpadControllerType::JoyconLeft && type != NpadControllerType::JoyconRight)) {
|
if (manager.orientation == NpadJoyOrientation::Vertical && (type != NpadControllerType::JoyconLeft && type != NpadControllerType::JoyconRight)) {
|
||||||
switch (axis) {
|
switch (axis) {
|
||||||
@ -266,7 +275,7 @@ namespace skyline::input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& digitalEntry = GetNextEntry(section.digitalController);
|
auto &digitalEntry = GetNextEntry(section.digitalController);
|
||||||
constexpr i16 threshold = 3276; // A 10% deadzone for the stick
|
constexpr i16 threshold = 3276; // A 10% deadzone for the stick
|
||||||
|
|
||||||
digitalEntry.buttons.leftStickUp = defaultEntry.leftY >= threshold;
|
digitalEntry.buttons.leftStickUp = defaultEntry.leftY >= threshold;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/types/KEvent.h>
|
||||||
#include "shared_mem.h"
|
#include "shared_mem.h"
|
||||||
|
|
||||||
namespace skyline::input {
|
namespace skyline::input {
|
||||||
@ -96,6 +97,7 @@ namespace skyline::input {
|
|||||||
NpadId id; //!< The ID of this controller
|
NpadId id; //!< The ID of this controller
|
||||||
NpadControllerType type{}; //!< The type of this controller
|
NpadControllerType type{}; //!< The type of this controller
|
||||||
NpadConnectionState connectionState{}; //!< The state of the connection
|
NpadConnectionState connectionState{}; //!< The state of the connection
|
||||||
|
std::shared_ptr<kernel::type::KEvent> updateEvent; //!< This event is triggered on the controller's style changing
|
||||||
bool explicitAssignment{false}; //!< If an assignment has explicitly been set or is the default for this controller
|
bool explicitAssignment{false}; //!< If an assignment has explicitly been set or is the default for this controller
|
||||||
|
|
||||||
NpadDevice(NpadManager &manager, NpadSection §ion, NpadId id);
|
NpadDevice(NpadManager &manager, NpadSection §ion, NpadId id);
|
||||||
@ -123,9 +125,9 @@ namespace skyline::input {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This connects this controller to the guest
|
* @brief This connects this controller to the guest
|
||||||
* @param type The type of controller to connect as
|
* @param newType The type of controller to connect as
|
||||||
*/
|
*/
|
||||||
void Connect(NpadControllerType type);
|
void Connect(NpadControllerType newType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This disconnects this controller from the guest
|
* @brief This disconnects this controller from the guest
|
||||||
|
@ -20,7 +20,7 @@ namespace skyline {
|
|||||||
*/
|
*/
|
||||||
struct CommonHeader {
|
struct CommonHeader {
|
||||||
u64 timestamp; //!< The timestamp of the latest entry in ticks
|
u64 timestamp; //!< The timestamp of the latest entry in ticks
|
||||||
u64 entryCount{constant::HidEntryCount}; //!< The number of entries (17)
|
u64 entryCount; //!< The number of written entries
|
||||||
u64 currentEntry; //!< The index of the latest entry
|
u64 currentEntry; //!< The index of the latest entry
|
||||||
u64 maxEntry{constant::HidEntryCount - 1}; //!< The maximum entry index (16)
|
u64 maxEntry{constant::HidEntryCount - 1}; //!< The maximum entry index (16)
|
||||||
};
|
};
|
||||||
|
@ -10,10 +10,14 @@ namespace skyline::service::hid {
|
|||||||
IHidServer::IHidServer(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::hid_IHidServer, "hid:IHidServer", {
|
IHidServer::IHidServer(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::hid_IHidServer, "hid:IHidServer", {
|
||||||
{0x0, SFUNC(IHidServer::CreateAppletResource)},
|
{0x0, SFUNC(IHidServer::CreateAppletResource)},
|
||||||
{0x64, SFUNC(IHidServer::SetSupportedNpadStyleSet)},
|
{0x64, SFUNC(IHidServer::SetSupportedNpadStyleSet)},
|
||||||
|
{0x64, SFUNC(IHidServer::GetSupportedNpadStyleSet)},
|
||||||
{0x66, SFUNC(IHidServer::SetSupportedNpadIdType)},
|
{0x66, SFUNC(IHidServer::SetSupportedNpadIdType)},
|
||||||
{0x67, SFUNC(IHidServer::ActivateNpad)},
|
{0x67, SFUNC(IHidServer::ActivateNpad)},
|
||||||
{0x68, SFUNC(IHidServer::DeactivateNpad)},
|
{0x68, SFUNC(IHidServer::DeactivateNpad)},
|
||||||
|
{0x6A, SFUNC(IHidServer::AcquireNpadStyleSetUpdateEventHandle)},
|
||||||
|
{0x6D, SFUNC(IHidServer::ActivateNpadWithRevision)},
|
||||||
{0x78, SFUNC(IHidServer::SetNpadJoyHoldType)},
|
{0x78, SFUNC(IHidServer::SetNpadJoyHoldType)},
|
||||||
|
{0x79, SFUNC(IHidServer::GetNpadJoyHoldType)},
|
||||||
{0x7A, SFUNC(IHidServer::SetNpadJoyAssignmentModeSingleByDefault)},
|
{0x7A, SFUNC(IHidServer::SetNpadJoyAssignmentModeSingleByDefault)},
|
||||||
{0x7B, SFUNC(IHidServer::SetNpadJoyAssignmentModeSingle)},
|
{0x7B, SFUNC(IHidServer::SetNpadJoyAssignmentModeSingle)},
|
||||||
{0x7C, SFUNC(IHidServer::SetNpadJoyAssignmentModeDual)}
|
{0x7C, SFUNC(IHidServer::SetNpadJoyAssignmentModeDual)}
|
||||||
@ -25,11 +29,17 @@ namespace skyline::service::hid {
|
|||||||
|
|
||||||
void IHidServer::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto styleSet = request.Pop<NpadStyleSet>();
|
auto styleSet = request.Pop<NpadStyleSet>();
|
||||||
|
state.input->npad.styles = styleSet;
|
||||||
|
state.input->npad.Update();
|
||||||
|
|
||||||
state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast<bool>(styleSet.proController), static_cast<bool>(styleSet.joyconHandheld), static_cast<bool>(styleSet.joyconDual), static_cast<bool>(styleSet.joyconLeft), static_cast<bool>
|
state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast<bool>(styleSet.proController), static_cast<bool>(styleSet.joyconHandheld), static_cast<bool>(styleSet.joyconDual), static_cast<bool>(styleSet.joyconLeft), static_cast<bool>
|
||||||
(styleSet.joyconRight), static_cast<bool>(styleSet.gamecube), static_cast<bool>(styleSet.palma), static_cast<bool>(styleSet.nes), static_cast<bool>(styleSet.nesHandheld), static_cast<bool>(styleSet.snes));
|
(styleSet.joyconRight), static_cast<bool>(styleSet.gamecube), static_cast<bool>(styleSet.palma), static_cast<bool>(styleSet.nes), static_cast<bool>(styleSet.nesHandheld), static_cast<bool>(styleSet.snes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IHidServer::GetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
response.Push(state.input->npad.styles);
|
||||||
|
}
|
||||||
|
|
||||||
void IHidServer::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
const auto &buffer = request.inputBuf.at(0);
|
const auto &buffer = request.inputBuf.at(0);
|
||||||
u64 address = buffer.address;
|
u64 address = buffer.address;
|
||||||
@ -53,11 +63,23 @@ namespace skyline::service::hid {
|
|||||||
state.input->npad.Deactivate();
|
state.input->npad.Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IHidServer::AcquireNpadStyleSetUpdateEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
auto id = request.Pop<NpadId>();
|
||||||
|
request.copyHandles.push_back(state.process->InsertItem(state.input->npad.at(id).updateEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHidServer::ActivateNpadWithRevision(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
state.input->npad.Activate();
|
||||||
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto appletResourceUID = request.Pop<u64>();
|
|
||||||
state.input->npad.orientation = request.Pop<NpadJoyOrientation>();
|
state.input->npad.orientation = request.Pop<NpadJoyOrientation>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IHidServer::GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
response.Push(state.input->npad.orientation);
|
||||||
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single, true);
|
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single, true);
|
||||||
|
@ -25,6 +25,11 @@ namespace skyline::service::hid {
|
|||||||
*/
|
*/
|
||||||
void SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
void SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This gets the style of controllers supported (https://switchbrew.org/wiki/HID_services#GetSupportedNpadStyleSet)
|
||||||
|
*/
|
||||||
|
void GetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the NpadIds which are supported (https://switchbrew.org/wiki/HID_services#SetSupportedNpadIdType)
|
* @brief This sets the NpadIds which are supported (https://switchbrew.org/wiki/HID_services#SetSupportedNpadIdType)
|
||||||
*/
|
*/
|
||||||
@ -40,11 +45,26 @@ namespace skyline::service::hid {
|
|||||||
*/
|
*/
|
||||||
void DeactivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
void DeactivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This requests an event that's signalled on a specific NpadId changing (https://switchbrew.org/wiki/HID_services#AcquireNpadStyleSetUpdateEventHandle)
|
||||||
|
*/
|
||||||
|
void AcquireNpadStyleSetUpdateEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This requests the activation of controllers with a specific HID revision (https://switchbrew.org/wiki/HID_services#ActivateNpadWithRevision)
|
||||||
|
*/
|
||||||
|
void ActivateNpadWithRevision(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the Joy-Con hold mode (https://switchbrew.org/wiki/HID_services#SetNpadJoyHoldType)
|
* @brief Sets the Joy-Con hold mode (https://switchbrew.org/wiki/HID_services#SetNpadJoyHoldType)
|
||||||
*/
|
*/
|
||||||
void SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
void SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the Joy-Con hold mode (https://switchbrew.org/wiki/HID_services#GetNpadJoyHoldType)
|
||||||
|
*/
|
||||||
|
void GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the Joy-Con assignment mode to Single by default (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeSingleByDefault)
|
* @brief Sets the Joy-Con assignment mode to Single by default (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeSingleByDefault)
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +19,7 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
/**
|
/**
|
||||||
* This is the instance of [PreferenceFragment] that is shown inside [R.id.settings]
|
* This is the instance of [PreferenceFragment] that is shown inside [R.id.settings]
|
||||||
*/
|
*/
|
||||||
private val preferenceFragment : PreferenceFragment = PreferenceFragment()
|
private val preferenceFragment = PreferenceFragment()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an instance of [InputManager] used by [ControllerPreference]
|
* This is an instance of [InputManager] used by [ControllerPreference]
|
||||||
|
@ -148,11 +148,6 @@ class ControllerActivity : AppCompatActivity(), View.OnClickListener {
|
|||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
window.decorView.findViewById<View>(android.R.id.content).viewTreeObserver.addOnTouchModeChangeListener {
|
|
||||||
if (!it)
|
|
||||||
toolbar_layout.setExpanded(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
controller_list.layoutManager = LinearLayoutManager(this)
|
controller_list.layoutManager = LinearLayoutManager(this)
|
||||||
controller_list.adapter = adapter
|
controller_list.adapter = adapter
|
||||||
|
|
||||||
@ -173,15 +168,22 @@ class ControllerActivity : AppCompatActivity(), View.OnClickListener {
|
|||||||
override fun onClick(v : View?) {
|
override fun onClick(v : View?) {
|
||||||
when (val tag = v!!.tag) {
|
when (val tag = v!!.tag) {
|
||||||
is ControllerTypeItem -> {
|
is ControllerTypeItem -> {
|
||||||
val type = manager.controllers[id]!!.type
|
val controller = manager.controllers[id]!!
|
||||||
|
|
||||||
val types = ControllerType.values().filter { !it.firstController || id == 0 }
|
val types = ControllerType.values().filter { !it.firstController || id == 0 }
|
||||||
val typeNames = types.map { getString(it.stringRes) }.toTypedArray()
|
val typeNames = types.map { getString(it.stringRes) }.toTypedArray()
|
||||||
|
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
.setTitle(tag.content)
|
.setTitle(tag.content)
|
||||||
.setSingleChoiceItems(typeNames, types.indexOf(type)) { dialog, typeIndex ->
|
.setSingleChoiceItems(typeNames, types.indexOf(controller.type)) { dialog, typeIndex ->
|
||||||
manager.controllers[id] = when (types[typeIndex]) {
|
val selectedType = types[typeIndex]
|
||||||
|
if (controller.type != selectedType) {
|
||||||
|
if (controller is JoyConLeftController)
|
||||||
|
controller.partnerId?.let { (manager.controllers[it] as JoyConRightController).partnerId = null }
|
||||||
|
else if (controller is JoyConRightController)
|
||||||
|
controller.partnerId?.let { (manager.controllers[it] as JoyConLeftController).partnerId = null }
|
||||||
|
|
||||||
|
manager.controllers[id] = when (selectedType) {
|
||||||
ControllerType.None -> Controller(id, ControllerType.None)
|
ControllerType.None -> Controller(id, ControllerType.None)
|
||||||
ControllerType.HandheldProController -> HandheldController(id)
|
ControllerType.HandheldProController -> HandheldController(id)
|
||||||
ControllerType.ProController -> ProController(id)
|
ControllerType.ProController -> ProController(id)
|
||||||
@ -190,6 +192,7 @@ class ControllerActivity : AppCompatActivity(), View.OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update()
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".MainActivity">
|
tools:context=".input.ControllerActivity">
|
||||||
|
|
||||||
<include layout="@layout/titlebar" />
|
<include layout="@layout/titlebar" />
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<include layout="@layout/titlebar" />
|
<include layout="@layout/titlebar" />
|
||||||
@ -8,5 +9,6 @@
|
|||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/settings"
|
android:id="@+id/settings"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent"
|
||||||
</LinearLayout>
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
android:id="@+id/toolbar_layout"
|
android:id="@+id/toolbar_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:descendantFocusability="afterDescendants"
|
android:fitsSystemWindows="true"
|
||||||
|
app:layout_scrollFlags="scroll|exitUntilCollapsed"
|
||||||
app:liftOnScroll="true">
|
app:liftOnScroll="true">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
Loading…
Reference in New Issue
Block a user