Skip to content

Commit

Permalink
First go at yakui-sdl2 bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
LPGhatguy committed Jan 5, 2025
1 parent a16421c commit 1e086f2
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 0 deletions.
8 changes: 8 additions & 0 deletions crates/yakui-sdl2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "yakui-sdl2"
version = "0.1.0"
edition = "2021"

[dependencies]
yakui-core = { path = "../yakui-core", version = "0.3.0" }
sdl2 = "0.37.0"
107 changes: 107 additions & 0 deletions crates/yakui-sdl2/src/keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use sdl2::keyboard::{Mod, Scancode};
use yakui_core::input::{KeyCode, Modifiers};

pub fn from_sdl_scancode(key: Scancode) -> Option<KeyCode> {
Some(match key {
Scancode::Space => KeyCode::Space,
Scancode::Backspace => KeyCode::Backspace,
Scancode::Delete => KeyCode::Delete,
Scancode::Return => KeyCode::Enter,
Scancode::KpEnter => KeyCode::NumpadEnter,
Scancode::Tab => KeyCode::Tab,
Scancode::Left => KeyCode::ArrowLeft,
Scancode::Right => KeyCode::ArrowRight,
Scancode::Escape => KeyCode::Escape,
Scancode::Home => KeyCode::Home,
Scancode::End => KeyCode::End,
Scancode::Up => KeyCode::ArrowUp,
Scancode::Down => KeyCode::ArrowDown,
Scancode::PageUp => KeyCode::PageUp,
Scancode::PageDown => KeyCode::PageDown,

Scancode::A => KeyCode::KeyA,
Scancode::B => KeyCode::KeyB,
Scancode::C => KeyCode::KeyC,
Scancode::D => KeyCode::KeyD,
Scancode::E => KeyCode::KeyE,
Scancode::F => KeyCode::KeyF,
Scancode::G => KeyCode::KeyG,
Scancode::H => KeyCode::KeyH,
Scancode::I => KeyCode::KeyI,
Scancode::J => KeyCode::KeyJ,
Scancode::K => KeyCode::KeyK,
Scancode::L => KeyCode::KeyL,
Scancode::M => KeyCode::KeyM,
Scancode::N => KeyCode::KeyN,
Scancode::O => KeyCode::KeyO,
Scancode::P => KeyCode::KeyP,
Scancode::Q => KeyCode::KeyQ,
Scancode::R => KeyCode::KeyR,
Scancode::S => KeyCode::KeyS,
Scancode::T => KeyCode::KeyT,
Scancode::U => KeyCode::KeyU,
Scancode::V => KeyCode::KeyV,
Scancode::W => KeyCode::KeyW,
Scancode::X => KeyCode::KeyX,
Scancode::Y => KeyCode::KeyY,
Scancode::Z => KeyCode::KeyZ,
Scancode::Num0 => KeyCode::Digit0,
Scancode::Num1 => KeyCode::Digit1,
Scancode::Num2 => KeyCode::Digit2,
Scancode::Num3 => KeyCode::Digit3,
Scancode::Num4 => KeyCode::Digit4,
Scancode::Num5 => KeyCode::Digit5,
Scancode::Num6 => KeyCode::Digit6,
Scancode::Num7 => KeyCode::Digit7,
Scancode::Num8 => KeyCode::Digit8,
Scancode::Num9 => KeyCode::Digit9,
Scancode::F1 => KeyCode::F1,
Scancode::F2 => KeyCode::F2,
Scancode::F3 => KeyCode::F3,
Scancode::F4 => KeyCode::F4,
Scancode::F5 => KeyCode::F5,
Scancode::F6 => KeyCode::F6,
Scancode::F7 => KeyCode::F7,
Scancode::F8 => KeyCode::F8,
Scancode::F9 => KeyCode::F9,
Scancode::F10 => KeyCode::F10,
Scancode::F11 => KeyCode::F11,
Scancode::F12 => KeyCode::F12,
Scancode::F13 => KeyCode::F13,
Scancode::F14 => KeyCode::F14,
Scancode::F15 => KeyCode::F15,
Scancode::F16 => KeyCode::F16,
Scancode::F17 => KeyCode::F17,
Scancode::F18 => KeyCode::F18,
Scancode::F19 => KeyCode::F19,
Scancode::F20 => KeyCode::F20,
Scancode::F21 => KeyCode::F21,
Scancode::F22 => KeyCode::F22,
Scancode::F23 => KeyCode::F23,
Scancode::F24 => KeyCode::F24,

_ => return None,
})
}

pub fn from_sdl_modifiers(sdl_mods: Mod) -> Modifiers {
let mut mods = Modifiers::default();

if sdl_mods.intersects(Mod::LSHIFTMOD | Mod::RSHIFTMOD) {
mods |= Modifiers::SHIFT;
}

if sdl_mods.intersects(Mod::LCTRLMOD | Mod::RCTRLMOD) {
mods |= Modifiers::CONTROL;
}

if sdl_mods.intersects(Mod::LALTMOD) {
mods |= Modifiers::ALT;
}

if sdl_mods.intersects(Mod::LGUIMOD | Mod::RGUIMOD) {
mods |= Modifiers::META;
}

mods
}
127 changes: 127 additions & 0 deletions crates/yakui-sdl2/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
mod keys;

use sdl2::event::{Event as SdlEvent, WindowEvent};
use sdl2::mouse::MouseButton as SdlMouseButton;
use sdl2::video::Window;
use yakui_core::event::Event;
use yakui_core::geometry::{Rect, UVec2, Vec2};
use yakui_core::input::MouseButton;

use self::keys::from_sdl_scancode;

pub struct YakuiSdl2 {
init: Option<InitState>,
}

struct InitState {
size: UVec2,
scale: f32,
}

fn scale_factor(window: &Window) -> f32 {
let video = window.subsystem();
let display_index = window.display_index().unwrap();
video.display_dpi(display_index).unwrap().0 / 96.0
}

impl YakuiSdl2 {
pub fn new(window: &Window) -> Self {
let size = window.size().into();
let scale = scale_factor(window);

Self {
init: Some(InitState { size, scale }),
}
}

pub fn handle_event(&mut self, state: &mut yakui_core::Yakui, event: &SdlEvent) -> bool {
if let Some(init) = self.init.take() {
state.set_surface_size(init.size.as_vec2());
state.set_unscaled_viewport(Rect::from_pos_size(Vec2::ZERO, init.size.as_vec2()));
state.set_scale_factor(init.scale);
}

match event {
SdlEvent::Window { win_event, .. } => {
match win_event {
WindowEvent::Resized(x, y) => {
let size = Vec2::new(*x as f32, *y as f32);
state.set_surface_size(size);
state.set_unscaled_viewport(Rect::from_pos_size(Vec2::ZERO, size));

false
}

// FIXME: scale factor changed
WindowEvent::Leave => state.handle_event(Event::CursorMoved(None)),

_ => false,
}
}

SdlEvent::MouseMotion { x, y, .. } => {
let pos = Vec2::new(*x as f32, *y as f32);
state.handle_event(Event::CursorMoved(Some(pos)))
}

SdlEvent::MouseButtonDown { mouse_btn, .. } => {
let button = match mouse_btn {
SdlMouseButton::Left => MouseButton::One,
SdlMouseButton::Right => MouseButton::Two,
SdlMouseButton::Middle => MouseButton::Three,
_ => return false,
};

state.handle_event(Event::MouseButtonChanged { button, down: true })
}

SdlEvent::MouseButtonUp { mouse_btn, .. } => {
let button = match mouse_btn {
SdlMouseButton::Left => MouseButton::One,
SdlMouseButton::Right => MouseButton::Two,
SdlMouseButton::Middle => MouseButton::Three,
_ => return false,
};

state.handle_event(Event::MouseButtonChanged {
button,
down: false,
})
}

SdlEvent::MouseWheel {
precise_x,
precise_y,
..
} => state.handle_event(Event::MouseScroll {
delta: Vec2::new(*precise_x, *precise_y),
}),

SdlEvent::TextInput { text, .. } => {
for c in text.chars() {
state.handle_event(Event::TextInput(c));
}

false
}

SdlEvent::KeyDown { scancode, .. } => {
if let Some(key) = scancode.and_then(from_sdl_scancode) {
state.handle_event(Event::KeyChanged { key, down: true })
} else {
false
}
}

SdlEvent::KeyUp { scancode, .. } => {
if let Some(key) = scancode.and_then(from_sdl_scancode) {
state.handle_event(Event::KeyChanged { key, down: false })
} else {
false
}
}

_ => false,
}
}
}

0 comments on commit 1e086f2

Please sign in to comment.