mirror of
https://gitlab.com/marcandre.lureau/qemu-display.git
synced 2024-12-22 05:35:20 +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
|
||||
#[derive(Debug)]
|
||||
pub enum ConsoleEvent {
|
||||
@ -66,11 +73,7 @@ pub enum ConsoleEvent {
|
||||
w: i32,
|
||||
h: i32,
|
||||
},
|
||||
MouseSet {
|
||||
x: i32,
|
||||
y: i32,
|
||||
on: i32,
|
||||
},
|
||||
MouseSet(MouseSet),
|
||||
CursorDefine {
|
||||
width: 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) {
|
||||
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>) {
|
||||
|
@ -24,4 +24,7 @@ pub trait Mouse {
|
||||
|
||||
/// SetAbsPosition method
|
||||
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);
|
||||
ec.connect_motion(clone!(@weak obj => move |_, x, y| {
|
||||
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();
|
||||
@ -284,9 +291,16 @@ mod imp {
|
||||
let pb = pb.scale_simple(width * scale, height * scale, gdk::gdk_pixbuf::InterpType::Bilinear).unwrap();
|
||||
let tex = gdk::Texture::new_for_pixbuf(&pb);
|
||||
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)
|
||||
}),
|
||||
|
@ -2,14 +2,14 @@ use glib::subclass::prelude::*;
|
||||
use glib::translate::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::subclass::widget::WidgetImplExt;
|
||||
use gtk::{gdk, glib};
|
||||
use std::cell::Cell;
|
||||
use gtk::{gdk, glib, graphene};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use crate::egl;
|
||||
use crate::error::*;
|
||||
use gl::{self, types::*};
|
||||
use qemu_display_listener::{Scanout, ScanoutDMABUF, Update};
|
||||
use qemu_display_listener::{MouseSet, Scanout, ScanoutDMABUF, Update};
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
@ -23,6 +23,9 @@ mod imp {
|
||||
pub texture_blit_flip_prog: Cell<GLuint>,
|
||||
pub scanout: Cell<Option<ScanoutDMABUF>>,
|
||||
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]
|
||||
@ -91,6 +94,31 @@ mod imp {
|
||||
self.parent_size_allocate(widget, width, height, baseline);
|
||||
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 {
|
||||
@ -104,6 +132,7 @@ mod imp {
|
||||
gl::Viewport(vp.x, vp.y, vp.width, vp.height);
|
||||
self.texture_blit(false);
|
||||
}
|
||||
|
||||
// parent will return to update call
|
||||
false
|
||||
}
|
||||
@ -383,6 +412,30 @@ impl QemuConsoleArea {
|
||||
let y = (y - vp.y) as f64 * (sh as f64 / vp.height as f64);
|
||||
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 {
|
||||
|
@ -316,7 +316,7 @@ impl Server {
|
||||
inner.tx.send(Event::ConsoleUpdate(rect)).unwrap();
|
||||
}
|
||||
ConsoleEvent::CursorDefine { .. } => {}
|
||||
ConsoleEvent::MouseSet { .. } => {}
|
||||
ConsoleEvent::MouseSet(_) => {}
|
||||
e => {
|
||||
dbg!(e);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user