view src/state.rs @ 17:0bce7fe96937

Add a client, copy of the GTK interface.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 26 Aug 2021 22:00:55 +0200
parents 478cf2a7d577
children
line wrap: on
line source

// Tablet emulator, for people who don’t own one
// Copyright © 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use crate::uinput::{
    create_uinput_device, input_axis_new, input_key_new, input_misc_new, input_synchronize_new,
};
use crate::{DEFAULT_HEIGHT, DEFAULT_WIDTH, MAX_X, MAX_Y};
use input_linux::{AbsoluteAxis, Key, MiscKind, SynchronizeKind, UInputHandle};
use std::fs::File;

pub struct State {
    dev: UInputHandle<File>,
    width: f64,
    height: f64,
    selected_tool: Key,
    pressed: bool,
}

impl State {
    pub fn new() -> std::io::Result<State> {
        let dev = create_uinput_device()?;
        println!(
            "New device at {:?} ({:?})",
            dev.evdev_path()?,
            dev.sys_path()?
        );

        Ok(State {
            dev,
            width: DEFAULT_WIDTH as f64,
            height: DEFAULT_HEIGHT as f64,
            selected_tool: Key::ButtonToolPen,
            pressed: false,
        })
    }

    pub fn set_size(&mut self, width: i32, height: i32) {
        self.width = width as f64;
        self.height = height as f64;
    }

    pub fn select_tool(&mut self, tool: Key) {
        self.selected_tool = tool;
    }

    pub fn press(&mut self, x: f64, y: f64) -> std::io::Result<()> {
        self.pressed = true;
        self.dev.write(&[
            input_axis_new(AbsoluteAxis::X, (x * MAX_X as f64 / self.width) as i32),
            input_axis_new(AbsoluteAxis::Y, (y * MAX_Y as f64 / self.height) as i32),
            input_axis_new(AbsoluteAxis::Z, 0),
            input_axis_new(AbsoluteAxis::Wheel, 0),
            input_axis_new(AbsoluteAxis::Pressure, 1024),
            input_axis_new(AbsoluteAxis::Distance, 0),
            input_axis_new(AbsoluteAxis::TiltX, 16),
            input_axis_new(AbsoluteAxis::TiltY, 0),
            input_misc_new(MiscKind::Serial, 0),
            input_key_new(self.selected_tool, 1),
            input_synchronize_new(SynchronizeKind::Report, 0),
        ])?;
        Ok(())
    }

    pub fn release(&mut self, x: f64, y: f64) -> std::io::Result<()> {
        self.pressed = false;
        self.dev.write(&[
            input_axis_new(AbsoluteAxis::X, (x * MAX_X as f64 / self.width) as i32),
            input_axis_new(AbsoluteAxis::Y, (y * MAX_Y as f64 / self.height) as i32),
            input_axis_new(AbsoluteAxis::Z, 0),
            input_axis_new(AbsoluteAxis::Wheel, 0),
            input_axis_new(AbsoluteAxis::Pressure, 0),
            input_axis_new(AbsoluteAxis::Distance, 16),
            input_axis_new(AbsoluteAxis::TiltX, 16),
            input_axis_new(AbsoluteAxis::TiltY, 0),
            input_misc_new(MiscKind::Serial, 0),
            input_key_new(self.selected_tool, 1),
            input_synchronize_new(SynchronizeKind::Report, 0),
        ])?;
        Ok(())
    }

    pub fn motion(&mut self, x: f64, y: f64) -> std::io::Result<()> {
        self.dev.write(&[
            input_axis_new(AbsoluteAxis::X, (x * MAX_X as f64 / self.width) as i32),
            input_axis_new(AbsoluteAxis::Y, (y * MAX_Y as f64 / self.height) as i32),
            input_axis_new(AbsoluteAxis::Z, 0),
            input_axis_new(AbsoluteAxis::Wheel, 0),
            input_axis_new(AbsoluteAxis::Pressure, if self.pressed { 2048 } else { 0 }),
            input_axis_new(AbsoluteAxis::Distance, if self.pressed { 0 } else { 32 }),
            input_axis_new(AbsoluteAxis::TiltX, 16),
            input_axis_new(AbsoluteAxis::TiltY, 0),
            input_misc_new(MiscKind::Serial, 0),
            input_key_new(self.selected_tool, 1),
            input_synchronize_new(SynchronizeKind::Report, 0),
        ])?;
        Ok(())
    }
}

pub struct FakeState {
    width: f64,
    height: f64,
    selected_tool: Key,
    pressed: bool,
}

impl FakeState {
    pub fn new() -> FakeState {
        FakeState {
            width: DEFAULT_WIDTH as f64,
            height: DEFAULT_HEIGHT as f64,
            selected_tool: Key::ButtonToolPen,
            pressed: false,
        }
    }

    pub fn is_pressed(&self) -> bool {
        self.pressed
    }

    pub fn set_size(&mut self, width: i32, height: i32) {
        self.width = width as f64;
        self.height = height as f64;
    }

    pub fn select_tool(&mut self, tool: Key) {
        self.selected_tool = tool;
    }

    pub fn press(&mut self, _x: f64, _y: f64) -> std::io::Result<()> {
        self.pressed = true;
        Ok(())
    }

    pub fn release(&mut self, _x: f64, _y: f64) -> std::io::Result<()> {
        self.pressed = false;
        Ok(())
    }

    pub fn motion(&mut self, _x: f64, _y: f64) -> std::io::Result<()> {
        Ok(())
    }
}