mirror of
https://github.com/rustdesk/qemu-display.git
synced 2025-07-01 15:25:29 +00:00
gtk: draw client cursor
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
ced718c264
commit
609a0732b4
@ -54,6 +54,13 @@ impl Drop for ScanoutDMABUF {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct MouseSet {
|
||||||
|
pub x: i32,
|
||||||
|
pub y: i32,
|
||||||
|
pub on: i32,
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: replace events mpsc with async traits
|
// TODO: replace events mpsc with async traits
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ConsoleEvent {
|
pub enum ConsoleEvent {
|
||||||
@ -66,11 +73,7 @@ pub enum ConsoleEvent {
|
|||||||
w: i32,
|
w: i32,
|
||||||
h: i32,
|
h: i32,
|
||||||
},
|
},
|
||||||
MouseSet {
|
MouseSet(MouseSet),
|
||||||
x: i32,
|
|
||||||
y: i32,
|
|
||||||
on: i32,
|
|
||||||
},
|
|
||||||
CursorDefine {
|
CursorDefine {
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
@ -160,7 +163,7 @@ impl<E: 'static + EventSender<Event = ConsoleEvent>> ConsoleListener<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_set(&mut self, x: i32, y: i32, on: i32) {
|
fn mouse_set(&mut self, x: i32, y: i32, on: i32) {
|
||||||
self.send(ConsoleEvent::MouseSet { x, y, on })
|
self.send(ConsoleEvent::MouseSet(MouseSet { x, y, on }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_define(&mut self, width: i32, height: i32, hot_x: i32, hot_y: i32, data: Vec<u8>) {
|
fn cursor_define(&mut self, width: i32, height: i32, hot_x: i32, hot_y: i32, data: Vec<u8>) {
|
||||||
|
@ -24,4 +24,7 @@ pub trait Mouse {
|
|||||||
|
|
||||||
/// SetAbsPosition method
|
/// SetAbsPosition method
|
||||||
fn set_abs_position(&self, x: u32, y: u32) -> zbus::Result<()>;
|
fn set_abs_position(&self, x: u32, y: u32) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[dbus_proxy(property)]
|
||||||
|
fn is_absolute(&self) -> zbus::Result<bool>;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,14 @@ mod imp {
|
|||||||
self.area.add_controller(&ec);
|
self.area.add_controller(&ec);
|
||||||
ec.connect_motion(clone!(@weak obj => move |_, x, y| {
|
ec.connect_motion(clone!(@weak obj => move |_, x, y| {
|
||||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||||
priv_.motion(x, y);
|
let c = obj.qemu_console();
|
||||||
|
if let Ok(abs) = c.mouse.is_absolute() {
|
||||||
|
if abs {
|
||||||
|
priv_.motion(x, y);
|
||||||
|
} else {
|
||||||
|
dbg!()
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let ec = gtk::GestureClick::new();
|
let ec = gtk::GestureClick::new();
|
||||||
@ -284,9 +291,16 @@ mod imp {
|
|||||||
let pb = pb.scale_simple(width * scale, height * scale, gdk::gdk_pixbuf::InterpType::Bilinear).unwrap();
|
let pb = pb.scale_simple(width * scale, height * scale, gdk::gdk_pixbuf::InterpType::Bilinear).unwrap();
|
||||||
let tex = gdk::Texture::new_for_pixbuf(&pb);
|
let tex = gdk::Texture::new_for_pixbuf(&pb);
|
||||||
let cur = gdk::Cursor::from_texture(&tex, hot_x * scale, hot_y * scale, None);
|
let cur = gdk::Cursor::from_texture(&tex, hot_x * scale, hot_y * scale, None);
|
||||||
priv_.area.set_cursor(Some(&cur));
|
priv_.area.cursor_define(cur);
|
||||||
|
}
|
||||||
|
Event::MouseSet(m) => {
|
||||||
|
priv_.area.mouse_set(m);
|
||||||
|
let c = obj.qemu_console();
|
||||||
|
if let Ok(abs) = c.mouse.is_absolute() {
|
||||||
|
priv_.area.set_cursor_abs(abs);
|
||||||
|
}
|
||||||
|
priv_.area.queue_render();
|
||||||
}
|
}
|
||||||
_t => { }
|
|
||||||
}
|
}
|
||||||
Continue(true)
|
Continue(true)
|
||||||
}),
|
}),
|
||||||
|
@ -2,14 +2,14 @@ use glib::subclass::prelude::*;
|
|||||||
use glib::translate::*;
|
use glib::translate::*;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::subclass::widget::WidgetImplExt;
|
use gtk::subclass::widget::WidgetImplExt;
|
||||||
use gtk::{gdk, glib};
|
use gtk::{gdk, glib, graphene};
|
||||||
use std::cell::Cell;
|
use std::cell::{Cell, RefCell};
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
use crate::egl;
|
use crate::egl;
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use gl::{self, types::*};
|
use gl::{self, types::*};
|
||||||
use qemu_display_listener::{Scanout, ScanoutDMABUF, Update};
|
use qemu_display_listener::{MouseSet, Scanout, ScanoutDMABUF, Update};
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -23,6 +23,9 @@ mod imp {
|
|||||||
pub texture_blit_flip_prog: Cell<GLuint>,
|
pub texture_blit_flip_prog: Cell<GLuint>,
|
||||||
pub scanout: Cell<Option<ScanoutDMABUF>>,
|
pub scanout: Cell<Option<ScanoutDMABUF>>,
|
||||||
pub scanout_size: Cell<(u32, u32)>,
|
pub scanout_size: Cell<(u32, u32)>,
|
||||||
|
pub cursor_abs: Cell<bool>,
|
||||||
|
pub cursor: RefCell<Option<gdk::Cursor>>,
|
||||||
|
pub mouse: Cell<Option<MouseSet>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
@ -91,6 +94,31 @@ mod imp {
|
|||||||
self.parent_size_allocate(widget, width, height, baseline);
|
self.parent_size_allocate(widget, width, height, baseline);
|
||||||
widget.notify("resize-hack");
|
widget.notify("resize-hack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn snapshot(&self, widget: &Self::Type, snapshot: >k::Snapshot) {
|
||||||
|
self.parent_snapshot(widget, snapshot);
|
||||||
|
|
||||||
|
if !self.cursor_abs.get() {
|
||||||
|
if let Some(mouse) = self.mouse.get() {
|
||||||
|
if mouse.on != 0 {
|
||||||
|
if let Some(cursor) = self.cursor.borrow().clone() {
|
||||||
|
if let Some(texture) = cursor.get_texture() {
|
||||||
|
let sf = widget.get_scale_factor();
|
||||||
|
snapshot.append_texture(
|
||||||
|
&texture,
|
||||||
|
&graphene::Rect::new(
|
||||||
|
(mouse.x - cursor.get_hotspot_x() / sf) as f32,
|
||||||
|
(mouse.y - cursor.get_hotspot_y() / sf) as f32,
|
||||||
|
(texture.get_width() / sf) as f32,
|
||||||
|
(texture.get_height() / sf) as f32,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GLAreaImpl for QemuConsoleArea {
|
impl GLAreaImpl for QemuConsoleArea {
|
||||||
@ -104,6 +132,7 @@ mod imp {
|
|||||||
gl::Viewport(vp.x, vp.y, vp.width, vp.height);
|
gl::Viewport(vp.x, vp.y, vp.width, vp.height);
|
||||||
self.texture_blit(false);
|
self.texture_blit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// parent will return to update call
|
// parent will return to update call
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -383,6 +412,30 @@ impl QemuConsoleArea {
|
|||||||
let y = (y - vp.y) as f64 * (sh as f64 / vp.height as f64);
|
let y = (y - vp.y) as f64 * (sh as f64 / vp.height as f64);
|
||||||
Some((x as u32, y as u32))
|
Some((x as u32, y as u32))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_cursor_abs(&self, abs: bool) {
|
||||||
|
let priv_ = imp::QemuConsoleArea::from_instance(self);
|
||||||
|
|
||||||
|
priv_.cursor_abs.set(abs);
|
||||||
|
if abs {
|
||||||
|
if let Some(cursor) = priv_.cursor.borrow().clone() {
|
||||||
|
self.set_cursor(Some(&cursor));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.set_cursor_from_name(Some("none"))
|
||||||
|
}
|
||||||
|
self.queue_render();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_define(&self, cursor: gdk::Cursor) {
|
||||||
|
let priv_ = imp::QemuConsoleArea::from_instance(self);
|
||||||
|
priv_.cursor.replace(Some(cursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mouse_set(&self, mouse: MouseSet) {
|
||||||
|
let priv_ = imp::QemuConsoleArea::from_instance(self);
|
||||||
|
priv_.mouse.set(Some(mouse));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn compile_shader(type_: GLenum, src: &CStr) -> GLuint {
|
unsafe fn compile_shader(type_: GLenum, src: &CStr) -> GLuint {
|
||||||
|
@ -316,7 +316,7 @@ impl Server {
|
|||||||
inner.tx.send(Event::ConsoleUpdate(rect)).unwrap();
|
inner.tx.send(Event::ConsoleUpdate(rect)).unwrap();
|
||||||
}
|
}
|
||||||
ConsoleEvent::CursorDefine { .. } => {}
|
ConsoleEvent::CursorDefine { .. } => {}
|
||||||
ConsoleEvent::MouseSet { .. } => {}
|
ConsoleEvent::MouseSet(_) => {}
|
||||||
e => {
|
e => {
|
||||||
dbg!(e);
|
dbg!(e);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user