Browse Source

Split parental lock into a different type

pull/149/head
Andrea Ciliberti 1 year ago
parent
commit
ab9713941c
  1. 1
      ctru-rs/src/applets/mii_selector.rs
  2. 117
      ctru-rs/src/applets/swkbd.rs

1
ctru-rs/src/applets/mii_selector.rs

@ -277,6 +277,7 @@ impl MiiSelector { @@ -277,6 +277,7 @@ impl MiiSelector {
/// # }
/// ```
#[doc(alias = "miiSelectorLaunch")]
#[allow(unused_variables)]
pub fn launch(&mut self, apt: &Apt, gfx: &Gfx) -> Result<Selection, Error> {
let mut return_val = Box::<ctru_sys::MiiSelectorReturn>::default();
unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) }

117
ctru-rs/src/applets/swkbd.rs

@ -2,14 +2,13 @@ @@ -2,14 +2,13 @@
//!
//! This applet opens a virtual keyboard on the console's bottom screen which lets the user write UTF-16 valid text.
// TODO: Implement remaining functionality (password mode, filter callbacks, etc.). Also improve "max text length" API. Improve `number of buttons` API when creating a new SoftwareKeyboard.
// TODO: Split the Parental PIN lock operations into a different type.
#![doc(alias = "keyboard")]
use crate::services::{apt::Apt, gfx::Gfx};
use ctru_sys::{
self, swkbdInit, swkbdInputText, swkbdSetButton, swkbdSetFeatures, swkbdSetHintText,
swkbdSetInitialText, SwkbdState,
};
use crate::services::{apt::Apt, gfx::Gfx};
use bitflags::bitflags;
use libc;
@ -24,6 +23,15 @@ pub struct SoftwareKeyboard { @@ -24,6 +23,15 @@ pub struct SoftwareKeyboard {
state: Box<SwkbdState>,
}
/// Configuration structure to setup the Parental Lock applet.
///
/// Internally, the Parental Lock is just a different kind of [`SoftwareKeyboard`].
#[doc(alias = "SwkbdState")]
#[derive(Clone)]
pub struct ParentalLock {
state: Box<SwkbdState>,
}
/// The type of keyboard used by the [`SoftwareKeyboard`].
///
/// Can be set with [`SoftwareKeyboard::new()`]
@ -75,15 +83,22 @@ pub enum Error { @@ -75,15 +83,22 @@ pub enum Error {
PowerPressed = ctru_sys::SWKBD_POWERPRESSED,
/// The parental lock PIN was correct.
///
/// While this variant isn't *technically* considerable an error
/// the result of a Parental PIN operation won't return a string to the program, thus it's still exceptional behaviour.
/// This variant should never be returned by normal operations made using this module,
/// and is listed here only for compatibility purposes.
/// Refer to the return value of [`ParentalLock::launch()`] to confirm the outcome
/// of the Parental Lock PIN operation.
ParentalOk = ctru_sys::SWKBD_PARENTAL_OK,
/// The parental lock PIN was incorrect.
///
/// Refer to the return value of [`ParentalLock::launch()`] to confirm the outcome
/// of the Parental Lock PIN operation.
ParentalFail = ctru_sys::SWKBD_PARENTAL_FAIL,
/// Input triggered the filter.
///
/// You can have a look at [`Filters`] to activate custom filters.
BannedInput = ctru_sys::SWKBD_BANNED_INPUT,
/// An on-screen button was pressed to exit the prompt.
ButtonPressed = ctru_sys::SWKBD_D0_CLICK,
}
/// Restrictions to enforce rules on the keyboard input.
@ -109,12 +124,6 @@ bitflags! { @@ -109,12 +124,6 @@ bitflags! {
/// Special features that can be activated via [`SoftwareKeyboard::set_features()`].
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
pub struct Features: u32 {
/// Parental PIN mode.
///
/// # Notes
///
/// Refer to [`Error::ParentalOk`] and [`Error::ParentalFail`] to check whether the Parental PIN lock was successfully opened.
const PARENTAL_PIN = ctru_sys::SWKBD_PARENTAL;
/// Darken top screen while the [`SoftwareKeyboard`] is active.
const DARKEN_TOP_SCREEN = ctru_sys::SWKBD_DARKEN_TOP_SCREEN;
/// Enable predictive input (necessary for Kanji on JPN consoles).
@ -181,7 +190,7 @@ impl SoftwareKeyboard { @@ -181,7 +190,7 @@ impl SoftwareKeyboard {
unsafe {
let mut state = Box::<SwkbdState>::default();
swkbdInit(state.as_mut(), keyboard_type.into(), num_buttons, -1);
SoftwareKeyboard { state }
Self { state }
}
}
@ -208,7 +217,12 @@ impl SoftwareKeyboard { @@ -208,7 +217,12 @@ impl SoftwareKeyboard {
/// # }
/// ```
#[doc(alias = "swkbdInputText")]
pub fn get_string(&mut self, max_bytes: usize, apt: &Apt, gfx: &Gfx) -> Result<(String, Button), Error> {
pub fn get_string(
&mut self,
max_bytes: usize,
apt: &Apt,
gfx: &Gfx,
) -> Result<(String, Button), Error> {
// Unfortunately the libctru API doesn't really provide a way to get the exact length
// of the string that it receieves from the software keyboard. Instead it expects you
// to pass in a buffer and hope that it's big enough to fit the entire string, so
@ -253,10 +267,11 @@ impl SoftwareKeyboard { @@ -253,10 +267,11 @@ impl SoftwareKeyboard {
/// # }
/// ```
#[doc(alias = "swkbdInputText")]
#[allow(unused_variables)]
pub fn write_exact(&mut self, buf: &mut [u8], apt: &Apt, gfx: &Gfx) -> Result<Button, Error> {
unsafe {
match swkbdInputText(self.state.as_mut(), buf.as_mut_ptr(), buf.len()) {
ctru_sys::SWKBD_BUTTON_NONE => Err(self.parse_swkbd_error()),
ctru_sys::SWKBD_BUTTON_NONE => Err(self.state.result.into()),
ctru_sys::SWKBD_BUTTON_LEFT => Ok(Button::Left),
ctru_sys::SWKBD_BUTTON_MIDDLE => Ok(Button::Middle),
ctru_sys::SWKBD_BUTTON_RIGHT => Ok(Button::Right),
@ -448,18 +463,49 @@ impl SoftwareKeyboard { @@ -448,18 +463,49 @@ impl SoftwareKeyboard {
pub fn set_max_text_len(&mut self, len: u16) {
self.state.max_text_len = len;
}
}
fn parse_swkbd_error(&self) -> Error {
match self.state.result {
ctru_sys::SWKBD_INVALID_INPUT => Error::InvalidParameters,
ctru_sys::SWKBD_OUTOFMEM => Error::OutOfMem,
ctru_sys::SWKBD_HOMEPRESSED => Error::HomePressed,
ctru_sys::SWKBD_RESETPRESSED => Error::ResetPressed,
ctru_sys::SWKBD_POWERPRESSED => Error::PowerPressed,
ctru_sys::SWKBD_PARENTAL_OK => Error::ParentalOk,
ctru_sys::SWKBD_PARENTAL_FAIL => Error::ParentalFail,
ctru_sys::SWKBD_BANNED_INPUT => Error::BannedInput,
_ => unreachable!(),
impl ParentalLock {
/// Initialize a new configuration for the Parental Lock applet.
///
/// # Example
///
/// ```
/// # let _runner = test_runner::GdbRunner::default();
/// # fn main() {
/// #
/// use ctru::applets::swkbd::{SoftwareKeyboard, Kind};
///
/// // Standard keyboard.
/// let keyboard = SoftwareKeyboard::new(Kind::Normal, 2);
///
/// // Numpad (with only the "confirm" button).
/// let keyboard = SoftwareKeyboard::new(Kind::Numpad, 1);
/// #
/// # }
#[doc(alias = "swkbdInit")]
pub fn new() -> Self {
unsafe {
let mut state = Box::<SwkbdState>::default();
swkbdInit(state.as_mut(), Kind::Normal.into(), 1, -1);
swkbdSetFeatures(state.as_mut(), ctru_sys::SWKBD_PARENTAL);
Self { state }
}
}
/// Launch the Parental Lock applet based on the configuration and return a result depending on whether the operation was successful or not.
#[doc(alias = "swkbdInputText")]
#[allow(unused_variables)]
pub fn launch(&mut self, apt: &Apt, gfx: &Gfx) -> Result<(), Error> {
unsafe {
let mut buf = [0; 10];
swkbdInputText(self.state.as_mut(), buf.as_mut_ptr(), 10);
let e = self.state.result.into();
match e {
Error::ParentalOk => Ok(()),
_ => Err(e),
}
}
}
}
@ -496,12 +542,35 @@ impl Display for Error { @@ -496,12 +542,35 @@ impl Display for Error {
f,
"input given to the software keyboard triggered the active filters"
),
Self::ButtonPressed => write!(f, "on-screen button was pressed to exit the prompt"),
}
}
}
impl std::error::Error for Error {}
impl From<ctru_sys::SwkbdResult> for Error {
fn from(value: ctru_sys::SwkbdResult) -> Self {
match value {
ctru_sys::SWKBD_INVALID_INPUT => Error::InvalidParameters,
ctru_sys::SWKBD_OUTOFMEM => Error::OutOfMem,
ctru_sys::SWKBD_HOMEPRESSED => Error::HomePressed,
ctru_sys::SWKBD_RESETPRESSED => Error::ResetPressed,
ctru_sys::SWKBD_POWERPRESSED => Error::PowerPressed,
ctru_sys::SWKBD_PARENTAL_OK => Error::ParentalOk,
ctru_sys::SWKBD_PARENTAL_FAIL => Error::ParentalFail,
ctru_sys::SWKBD_BANNED_INPUT => Error::BannedInput,
ctru_sys::SWKBD_D0_CLICK => Error::ButtonPressed,
ctru_sys::SWKBD_D1_CLICK0 => Error::ButtonPressed,
ctru_sys::SWKBD_D1_CLICK1 => Error::ButtonPressed,
ctru_sys::SWKBD_D2_CLICK0 => Error::ButtonPressed,
ctru_sys::SWKBD_D2_CLICK1 => Error::ButtonPressed,
ctru_sys::SWKBD_D2_CLICK2 => Error::ButtonPressed,
_ => unreachable!(),
}
}
}
from_impl!(Kind, ctru_sys::SwkbdType);
from_impl!(Button, ctru_sys::SwkbdButton);
from_impl!(Error, ctru_sys::SwkbdResult);

Loading…
Cancel
Save