Слияние кода завершено, страница обновится автоматически
// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
use crate::{
client::ClientIoHandler,
console::console_select,
pixman::{get_image_height, get_image_width},
vnc::BIT_PER_BYTE,
};
use anyhow::Result;
use log::error;
use once_cell::sync::Lazy;
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use util::bitmap::Bitmap;
// Logical window size for mouse.
const ABS_MAX: u64 = 0x7fff;
// Event type of Point.
const INPUT_POINT_LEFT: u8 = 0x01;
const INPUT_POINT_MIDDLE: u8 = 0x02;
const INPUT_POINT_RIGHT: u8 = 0x04;
// ASCII value.
const ASCII_A: i32 = 65;
const ASCII_Z: i32 = 90;
const UPPERCASE_TO_LOWERCASE: i32 = 32;
// Keycode.
const KEYCODE_1: u16 = 2;
const KEYCODE_9: u16 = 10;
const KEYCODE_CTRL: u16 = 29;
const KEYCODE_SHIFT: u16 = 42;
const KEYCODE_SHIFT_R: u16 = 54;
const KEYCODE_ALT: u16 = 56;
const KEYCODE_CAPS_LOCK: u16 = 58;
const KEYCODE_NUM_LOCK: u16 = 69;
const KEYCODE_CTRL_R: u16 = 157;
const KEYCODE_ALT_R: u16 = 184;
// Keyboard Modifier State
pub enum KeyboardModifier {
KeyModNone = 0,
KeyModShift = 1,
KeyModCtrl = 2,
KeyModAlt = 3,
KeyModAltgr = 4,
KeyModNumlock = 5,
KeyModCapslock = 6,
KeyModMax = 7,
}
/// Record the keyboard status,
/// Including the press information of keys,
/// and some status information.
pub struct KeyBoardState {
/// Keyboard state.
pub keystate: Bitmap<u8>,
/// Key Modifier states.
pub keymods: Bitmap<u8>,
}
impl KeyBoardState {
pub fn new(key_num: usize) -> Self {
Self {
keystate: Bitmap::new(key_num / (BIT_PER_BYTE as usize) + 1),
keymods: Bitmap::new(
KeyboardModifier::KeyModMax as usize / (BIT_PER_BYTE as usize) + 1,
),
}
}
/// Get the corresponding keyboard modifier.
fn keyboard_modifier_get(&self, key_mod: KeyboardModifier) -> bool {
match self.keymods.contain(key_mod as usize) {
Ok(res) => res,
Err(_e) => false,
}
}
/// Reset all keyboard modifier state.
fn keyboard_state_reset(&mut self) {
self.keymods.clear_all();
}
/// Record the press and up state in the keyboard.
fn keyboard_state_update(&mut self, keycode: u16, down: bool) -> Result<()> {
// Key is not pressed and the incoming key action is up.
if !down && !self.keystate.contain(keycode as usize)? {
return Ok(());
}
// Update Keyboard key modifier state.
if down {
self.keystate.set(keycode as usize)?;
} else {
self.keystate.clear(keycode as usize)?;
}
// Update Keyboard modifier state.
match keycode {
KEYCODE_SHIFT | KEYCODE_SHIFT_R => {
self.keyboard_modstate_update(
KEYCODE_SHIFT,
KEYCODE_SHIFT,
KeyboardModifier::KeyModShift,
)?;
}
KEYCODE_CTRL | KEYCODE_CTRL_R => {
self.keyboard_modstate_update(
KEYCODE_CTRL,
KEYCODE_CTRL_R,
KeyboardModifier::KeyModCtrl,
)?;
}
KEYCODE_ALT => {
self.keyboard_modstate_update(
KEYCODE_ALT,
KEYCODE_ALT,
KeyboardModifier::KeyModAlt,
)?;
}
KEYCODE_ALT_R => {
self.keyboard_modstate_update(
KEYCODE_ALT_R,
KEYCODE_ALT_R,
KeyboardModifier::KeyModAltgr,
)?;
}
KEYCODE_CAPS_LOCK => {
if down {
self.keymods
.change(KeyboardModifier::KeyModCapslock as usize)?;
}
}
KEYCODE_NUM_LOCK => {
if down {
self.keymods
.change(KeyboardModifier::KeyModNumlock as usize)?;
}
}
_ => {}
}
Ok(())
}
/// If one of the keys keycode_1 and keycode_2 is pressed,
/// Then the corresponding keyboard modifier state will be set.
/// Otherwise, it will be clear.
fn keyboard_modstate_update(
&mut self,
keycode_1: u16,
keycode_2: u16,
mod_state: KeyboardModifier,
) -> Result<()> {
let mut res = self.keystate.contain(keycode_1 as usize)?;
res |= self.keystate.contain(keycode_2 as usize)?;
if res {
self.keymods.set(mod_state as usize)?;
} else {
self.keymods.clear(mod_state as usize)?;
}
Ok(())
}
}
impl ClientIoHandler {
/// Keyboard event.
pub fn key_envent(&mut self) {
if self.expect == 1 {
self.expect = 8;
return;
}
let buf = self.read_incoming_msg();
let down: bool = buf[1] != 0;
let mut keysym = i32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
let server = self.server.clone();
// Uppercase -> Lowercase.
if (ASCII_A..=ASCII_Z).contains(&keysym) {
keysym += UPPERCASE_TO_LOWERCASE;
}
let mut kbd_state = server.keyboard_state.borrow_mut();
let keycode: u16 = match server.keysym2keycode.get(&(keysym as u16)) {
Some(k) => *k,
None => 0,
};
// Ctr + Alt + Num(1~9)
// Switch to the corresponding display device.
if (KEYCODE_1..KEYCODE_9 + 1).contains(&keycode)
&& down
&& self.server.display_listener.is_some()
&& kbd_state.keyboard_modifier_get(KeyboardModifier::KeyModCtrl)
&& kbd_state.keyboard_modifier_get(KeyboardModifier::KeyModAlt)
{
kbd_state.keyboard_state_reset();
console_select(Some((keycode - KEYCODE_1) as usize))
.unwrap_or_else(|e| error!("{:?}", e));
}
kbd_state
.keyboard_state_update(keycode, down)
.unwrap_or_else(|e| error!("Key State update error: {:?}", e));
key_event(keycode, down).unwrap_or_else(|e| error!("Key event error: {:?}", e));
self.update_event_handler(1, ClientIoHandler::handle_protocol_msg);
}
// Mouse event.
pub fn point_event(&mut self) {
if self.expect == 1 {
self.expect = 6;
return;
}
let buf = self.read_incoming_msg();
let mut x = ((buf[2] as u16) << 8) + buf[3] as u16;
let mut y = ((buf[4] as u16) << 8) + buf[5] as u16;
// Window size alignment.
let locked_surface = self.server.vnc_surface.lock().unwrap();
let width = get_image_width(locked_surface.server_image);
let height = get_image_height(locked_surface.server_image);
drop(locked_surface);
x = ((x as u64 * ABS_MAX) / width as u64) as u16;
y = ((y as u64 * ABS_MAX) / height as u64) as u16;
// ASCII -> HidCode.
let button_mask: u8 = match buf[1] {
INPUT_POINT_LEFT => 0x01,
INPUT_POINT_MIDDLE => 0x04,
INPUT_POINT_RIGHT => 0x02,
_ => buf[1],
};
point_event(button_mask as u32, x as u32, y as u32)
.unwrap_or_else(|e| error!("Point event error: {:?}", e));
self.update_event_handler(1, ClientIoHandler::handle_protocol_msg);
}
/// Client cut text.
pub fn client_cut_event(&mut self) {
let buf = self.read_incoming_msg();
if self.expect == 1 {
self.expect = 8;
return;
}
if self.expect == 8 {
let buf = [buf[4], buf[5], buf[6], buf[7]];
let len = u32::from_be_bytes(buf);
if len > 0 {
self.expect += len as usize;
return;
}
}
self.update_event_handler(1, ClientIoHandler::handle_protocol_msg);
}
}
static INPUTS: Lazy<Arc<Mutex<Inputs>>> = Lazy::new(|| Arc::new(Mutex::new(Inputs::default())));
#[derive(Default)]
struct Inputs {
active_kbd: Option<String>,
active_tablet: Option<String>,
kbd_lists: HashMap<String, Arc<Mutex<dyn KeyboardOpts>>>,
tablet_lists: HashMap<String, Arc<Mutex<dyn PointerOpts>>>,
}
impl Inputs {
fn register_kbd(&mut self, device: &str, kbd: Arc<Mutex<dyn KeyboardOpts>>) {
if self.active_kbd.is_none() {
self.active_kbd = Some(device.to_string());
}
self.kbd_lists.insert(device.to_string(), kbd);
}
fn register_mouse(&mut self, device: &str, tablet: Arc<Mutex<dyn PointerOpts>>) {
if self.active_tablet.is_none() {
self.active_tablet = Some(device.to_string());
}
self.tablet_lists.insert(device.to_string(), tablet);
}
fn get_active_kbd(&mut self) -> Option<Arc<Mutex<dyn KeyboardOpts>>> {
match &self.active_kbd {
Some(active_kbd) => {
let kbd = self.kbd_lists.get(active_kbd)?.clone();
Some(kbd)
}
None => None,
}
}
fn get_active_mouse(&mut self) -> Option<Arc<Mutex<dyn PointerOpts>>> {
match &self.active_tablet {
Some(active_mouse) => {
let mouse = self.tablet_lists.get(active_mouse)?.clone();
Some(mouse)
}
None => None,
}
}
}
pub fn register_keyboard(device: &str, kbd: Arc<Mutex<dyn KeyboardOpts>>) {
INPUTS.lock().unwrap().register_kbd(device, kbd);
}
pub fn register_pointer(device: &str, tablet: Arc<Mutex<dyn PointerOpts>>) {
INPUTS.lock().unwrap().register_mouse(device, tablet);
}
pub fn key_event(keycode: u16, down: bool) -> Result<()> {
let kbd = INPUTS.lock().unwrap().get_active_kbd();
if let Some(k) = kbd {
k.lock().unwrap().do_key_event(keycode, down)?;
}
Ok(())
}
pub fn point_event(button: u32, x: u32, y: u32) -> Result<()> {
let mouse = INPUTS.lock().unwrap().get_active_mouse();
if let Some(m) = mouse {
m.lock().unwrap().do_point_event(button, x, y)?;
}
Ok(())
}
pub trait KeyboardOpts: Send {
fn do_key_event(&mut self, keycode: u16, down: bool) -> Result<()>;
}
pub trait PointerOpts: Send {
fn do_point_event(&mut self, button: u32, x: u32, y: u32) -> Result<()>;
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Default)]
pub struct TestKbd {
keycode: u16,
down: bool,
}
impl KeyboardOpts for TestKbd {
fn do_key_event(&mut self, keycode: u16, down: bool) -> Result<()> {
self.keycode = keycode;
self.down = down;
Ok(())
}
}
#[derive(Default)]
pub struct TestTablet {
pub button: u32,
x: u32,
y: u32,
}
impl PointerOpts for TestTablet {
fn do_point_event(&mut self, button: u32, x: u32, y: u32) -> Result<()> {
self.button = button;
self.x = x;
self.y = y;
Ok(())
}
}
#[test]
fn test_input_basic() {
// Test keyboard event.
let test_kdb = Arc::new(Mutex::new(TestKbd {
keycode: 0,
down: false,
}));
register_keyboard("TestKeyboard", test_kdb.clone());
assert!(key_event(12, true).is_ok());
assert_eq!(test_kdb.lock().unwrap().keycode, 12);
assert_eq!(test_kdb.lock().unwrap().down, true);
// Test point event.
let test_mouse = Arc::new(Mutex::new(TestTablet::default()));
assert_eq!(test_mouse.lock().unwrap().button, 0);
assert_eq!(test_mouse.lock().unwrap().x, 0);
assert_eq!(test_mouse.lock().unwrap().y, 0);
register_pointer("TestPointer", test_mouse.clone());
assert!(point_event(1, 54, 12).is_ok());
assert_eq!(test_mouse.lock().unwrap().button, 1);
assert_eq!(test_mouse.lock().unwrap().x, 54);
assert_eq!(test_mouse.lock().unwrap().y, 12);
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )