Слияние кода завершено, страница обновится автоматически
// Copyright (c) 2023 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 std::{cell::RefCell, rc::Rc};
use anyhow::Result;
use gdk::{prelude::SeatExt, SeatCapabilities};
use gtk::{
cairo,
gdk::{self, EventMask, ScrollDirection},
glib::{self, translate::IntoGlib},
prelude::WidgetExtManual,
traits::WidgetExt,
DrawingArea, Inhibit,
};
use log::error;
use crate::{
console::graphic_hardware_ui_info,
gtk::GtkDisplayScreen,
input::{
self, input_button, input_move_abs, input_point_sync, press_mouse, release_all_key,
update_key_state, Axis, ABS_MAX, INPUT_BUTTON_WHEEL_DOWN, INPUT_BUTTON_WHEEL_LEFT,
INPUT_BUTTON_WHEEL_RIGHT, INPUT_BUTTON_WHEEL_UP, INPUT_POINT_BACK, INPUT_POINT_FORWARD,
INPUT_POINT_LEFT, INPUT_POINT_MIDDLE, INPUT_POINT_RIGHT,
},
};
const GTK_INPUT_BUTTON_LEFT: u32 = 1;
const GTK_INPUT_BUTTON_MIDDLE: u32 = 2;
const GTK_INPUT_BUTTON_RIGHT: u32 = 3;
const GTK_INPUT_BUTTON_BACK: u32 = 8;
const GTK_INPUT_BUTTON_FORWARD: u32 = 9;
pub(crate) fn set_callback_for_draw_area(
draw_area: &DrawingArea,
gs: Rc<RefCell<GtkDisplayScreen>>,
) -> Result<()> {
draw_area.connect_draw(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_, cr| {
da_draw_callback(&gs, cr).unwrap_or_else(|e| error!("Draw: {}", e));
Inhibit(false)
}),
);
draw_area.connect_event(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_, event| {
da_event_callback(&gs, event).unwrap_or_else(|e| error!("Draw event: {}", e));
Inhibit(false)}),
);
draw_area.connect_button_press_event(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_, button_event| {
da_pointer_callback(button_event).unwrap_or_else(|e| error!("Press event: {}", e));
Inhibit(false)
}),
);
draw_area.connect_button_release_event(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_, button_event| {
da_pointer_callback(button_event).unwrap_or_else(|e| error!("Release event: {}", e));
Inhibit(false)
}),
);
draw_area.connect_scroll_event(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_, scroll_event| {
da_scroll_callback(scroll_event).unwrap_or_else(|e| error!("Scroll event: {}", e));
Inhibit(false)
}),
);
draw_area.connect_key_press_event(
glib::clone!(@weak gs => @default-return Inhibit(true), move |_, key_event| {
da_key_callback(&gs,key_event, true).unwrap_or_else(|e|error!("Press event: {}", e));
Inhibit(true)}
),
);
draw_area.connect_key_release_event(
glib::clone!(@weak gs => @default-return Inhibit(true), move |_, key_event| {
da_key_callback(&gs,key_event, false).unwrap_or_else(|e|error!("Key event: {}", e));
Inhibit(true)}
),
);
draw_area.connect_configure_event(
glib::clone!(@weak gs => @default-return false, move |_, event_configure| {
da_configure_callback(&gs, event_configure).unwrap_or_else(|e|error!("Configure event: {}", e));
false}
),
);
draw_area.connect_focus_out_event(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_, _| {
da_focus_out_callback().unwrap_or_else(|e|error!("Focus out event: {:?}", e));
Inhibit(false)}
),
);
draw_area.connect_enter_notify_event(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_,enter_event| {
da_enter_callback(&gs, enter_event).unwrap_or_else(|e|error!("Enter event: {:?}", e));
Inhibit(false)}
),
);
draw_area.connect_leave_notify_event(
glib::clone!(@weak gs => @default-return Inhibit(false), move |_, leave_event| {
da_leave_callback(&gs, leave_event).unwrap_or_else(|e|error!("Leave event: {:?}", e));
Inhibit(false)}
),
);
let event_mask = EventMask::BUTTON_PRESS_MASK
| EventMask::BUTTON_RELEASE_MASK
| EventMask::BUTTON_MOTION_MASK
| EventMask::SCROLL_MASK
| EventMask::SMOOTH_SCROLL_MASK
| EventMask::KEY_PRESS_MASK
| EventMask::KEY_RELEASE_MASK
| EventMask::BUTTON1_MOTION_MASK
| EventMask::FOCUS_CHANGE_MASK
| EventMask::ENTER_NOTIFY_MASK
| EventMask::LEAVE_NOTIFY_MASK
| EventMask::POINTER_MOTION_MASK;
draw_area.add_events(event_mask);
Ok(())
}
fn da_enter_callback(
gs: &Rc<RefCell<GtkDisplayScreen>>,
_event: &gdk::EventCrossing,
) -> Result<()> {
trace::gtk_enter_callback(&"enter".to_string());
update_keyboard_grab(gs, true);
Ok(())
}
fn da_leave_callback(
gs: &Rc<RefCell<GtkDisplayScreen>>,
_event: &gdk::EventCrossing,
) -> Result<()> {
trace::gtk_enter_callback(&"leave".to_string());
update_keyboard_grab(gs, false);
Ok(())
}
fn update_keyboard_grab(gs: &Rc<RefCell<GtkDisplayScreen>>, grab: bool) {
let borrowed_gs = gs.borrow();
let display = borrowed_gs.draw_area.display();
if let Some(seat) = display.default_seat() {
if grab {
if let Some(w) = borrowed_gs.draw_area.window() {
seat.grab(&w, SeatCapabilities::KEYBOARD, false, None, None, None);
}
} else {
seat.ungrab();
}
}
}
/// When the window size changes,
/// the image resolution adapts to the window.
fn da_configure_callback(
gs: &Rc<RefCell<GtkDisplayScreen>>,
event_configure: &gdk::EventConfigure,
) -> Result<()> {
trace::gtk_configure_callback(&event_configure.size().0, &event_configure.size().1);
let borrowed_gs = gs.borrow();
if !borrowed_gs.scale_mode.borrow().is_free_scale() {
return Ok(());
}
let con = match borrowed_gs.con.upgrade() {
Some(c) => c,
None => return Ok(()),
};
drop(borrowed_gs);
let (width, height) = event_configure.size();
graphic_hardware_ui_info(con, width, height)
}
fn da_focus_out_callback() -> Result<()> {
release_all_key()
}
fn da_key_callback(
gs: &Rc<RefCell<GtkDisplayScreen>>,
key_event: &gdk::EventKey,
press: bool,
) -> Result<()> {
let keysym2keycode = gs.borrow().keysym2keycode.clone();
let org_key_value = key_event.keyval().into_glib() as i32;
let key_value: u16 = key_event.keyval().to_lower().into_glib() as u16;
let keycode: u16 = match keysym2keycode.borrow().get(&key_value) {
Some(k) => *k,
None => 0,
};
trace::gtk_key_event_callback(&key_value, &press);
update_key_state(press, org_key_value, keycode)?;
input::key_event(keycode, press)?;
Ok(())
}
fn da_event_callback(gs: &Rc<RefCell<GtkDisplayScreen>>, event: &gdk::Event) -> Result<()> {
// Cursor movement.
if event.event_type() == gdk::EventType::MotionNotify {
gd_cursor_move_event(gs, event).unwrap_or_else(|e| error!("Cursor movement: {:?}", e));
}
Ok(())
}
/// Cursor Movement.
fn gd_cursor_move_event(gs: &Rc<RefCell<GtkDisplayScreen>>, event: &gdk::Event) -> Result<()> {
let mut borrowed_gs = gs.borrow_mut();
let (width, height) = match &borrowed_gs.cairo_image {
Some(image) => (image.width() as f64, image.height() as f64),
None => return Ok(()),
};
let (x, y) = match event.coords() {
Some(value) => value,
None => return Ok(()),
};
trace::gtk_cursor_move_event(&x, &y);
let (real_x, real_y) = borrowed_gs.convert_coord(x, y)?;
let standard_x = ((real_x * (ABS_MAX as f64)) / width) as u16;
let standard_y = ((real_y * (ABS_MAX as f64)) / height) as u16;
input_move_abs(Axis::X, standard_x as u32)?;
input_move_abs(Axis::Y, standard_y as u32)?;
input_point_sync()
}
fn da_pointer_callback(button_event: &gdk::EventButton) -> Result<()> {
let button_mask = match button_event.button() {
GTK_INPUT_BUTTON_LEFT => INPUT_POINT_LEFT,
GTK_INPUT_BUTTON_RIGHT => INPUT_POINT_RIGHT,
GTK_INPUT_BUTTON_MIDDLE => INPUT_POINT_MIDDLE,
GTK_INPUT_BUTTON_BACK => INPUT_POINT_BACK,
GTK_INPUT_BUTTON_FORWARD => INPUT_POINT_FORWARD,
_ => return Ok(()),
};
trace::gtk_pointer_callback(&button_mask);
match button_event.event_type() {
gdk::EventType::ButtonRelease => {
input_button(button_mask, false)?;
input_point_sync()
}
gdk::EventType::ButtonPress => {
input_button(button_mask, true)?;
input_point_sync()
}
gdk::EventType::DoubleButtonPress => {
press_mouse(button_mask)?;
press_mouse(button_mask)
}
_ => Ok(()),
}
}
fn da_scroll_callback(scroll_event: &gdk::EventScroll) -> Result<()> {
trace::gtk_scroll_callback(&scroll_event.direction());
match scroll_event.direction() {
ScrollDirection::Up => press_mouse(INPUT_BUTTON_WHEEL_UP),
ScrollDirection::Down => press_mouse(INPUT_BUTTON_WHEEL_DOWN),
ScrollDirection::Left => press_mouse(INPUT_BUTTON_WHEEL_LEFT),
ScrollDirection::Right => press_mouse(INPUT_BUTTON_WHEEL_RIGHT),
ScrollDirection::Smooth => match scroll_event.scroll_deltas() {
Some((delta_x, delta_y)) => {
if delta_x.eq(&0.0) && delta_y.eq(&0.0) {
return Ok(());
}
// Horizontal scrolling.
if delta_x.gt(&0.0) {
press_mouse(INPUT_BUTTON_WHEEL_RIGHT)?;
} else if delta_x.lt(&0.0) {
press_mouse(INPUT_BUTTON_WHEEL_LEFT)?;
}
// Vertical scrolling.
if delta_y.gt(&0.0) {
press_mouse(INPUT_BUTTON_WHEEL_DOWN)?;
} else if delta_y.lt(&0.0) {
press_mouse(INPUT_BUTTON_WHEEL_UP)?;
}
Ok(())
}
None => Ok(()),
},
_ => Ok(()),
}
}
/// Draw_area callback func for draw signal.
fn da_draw_callback(gs: &Rc<RefCell<GtkDisplayScreen>>, cr: &cairo::Context) -> Result<()> {
let mut borrowed_gs = gs.borrow_mut();
let scale_mode = borrowed_gs.scale_mode.clone();
let (mut surface_width, mut surface_height) = match &borrowed_gs.cairo_image {
Some(image) => (image.width() as f64, image.height() as f64),
None => return Ok(()),
};
if surface_width.le(&0.0) || surface_height.le(&0.0) {
return Ok(());
}
let (window_width, window_height);
match borrowed_gs.get_window_size() {
Some((w, h)) => (window_width, window_height) = (w, h),
None => return Ok(()),
};
if scale_mode.borrow().is_full_screen() || scale_mode.borrow().is_free_scale() {
borrowed_gs.scale_x = window_width / surface_width;
borrowed_gs.scale_y = window_height / surface_height;
}
surface_width *= borrowed_gs.scale_x;
surface_height *= borrowed_gs.scale_y;
let mut mx: f64 = 0.0;
let mut my: f64 = 0.0;
if window_width.gt(&surface_width) {
mx = (window_width - surface_width) / (2.0);
}
if window_height.gt(&surface_height) {
my = (window_height - surface_height) / (2.0);
}
cr.rectangle(0.0, 0.0, window_width, window_height);
cr.rectangle(mx + surface_width, my, surface_width * -1.0, surface_height);
cr.fill()?;
cr.scale(borrowed_gs.scale_x, borrowed_gs.scale_y);
if let Some(image) = &borrowed_gs.cairo_image {
cr.set_source_surface(image, mx / borrowed_gs.scale_x, my / borrowed_gs.scale_y)?;
}
cr.paint()?;
Ok(())
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )