mirror of
https://gitlab.com/marcandre.lureau/qemu-display.git
synced 2024-12-22 05:35:20 +00:00
gtk: some refactoring
This commit is contained in:
parent
7cda1c29e3
commit
f6bbaf0b2d
@ -1,2 +1,4 @@
|
||||
paths = ['../gtk4-rs/gtk4']
|
||||
|
||||
[alias]
|
||||
xtask = "run --package xtask --"
|
||||
|
@ -74,20 +74,21 @@ mod imp {
|
||||
let ec = gtk::EventControllerMotion::new();
|
||||
self.area.add_controller(&ec);
|
||||
ec.connect_motion(clone!(@weak obj => move |_, x, y| {
|
||||
obj.motion(x, y);
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
priv_.motion(x, y);
|
||||
}));
|
||||
|
||||
let ec = gtk::GestureClick::new();
|
||||
ec.set_button(0);
|
||||
self.area.add_controller(&ec);
|
||||
ec.connect_pressed(clone!(@weak obj => @default-panic, move |gesture, _n_press, x, y| {
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
let c = obj.qemu_console();
|
||||
let button = from_gdk_button(gesture.get_current_button());
|
||||
obj.motion(x, y);
|
||||
priv_.motion(x, y);
|
||||
let _ = c.mouse.press(button);
|
||||
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
if let Some(toplevel) = obj.get_toplevel() {
|
||||
if let Some(toplevel) = priv_.get_toplevel() {
|
||||
if !toplevel.get_property_shortcuts_inhibited() {
|
||||
toplevel.inhibit_system_shortcuts::<gdk::ButtonEvent>(None);
|
||||
|
||||
@ -135,9 +136,11 @@ mod imp {
|
||||
priv_.area.grab_focus();
|
||||
}));
|
||||
ec.connect_released(clone!(@weak obj => move |gesture, _n_press, x, y| {
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
let c = obj.qemu_console();
|
||||
let button = from_gdk_button(gesture.get_current_button());
|
||||
obj.motion(x, y);
|
||||
|
||||
priv_.motion(x, y);
|
||||
let _ = c.mouse.release(button);
|
||||
}));
|
||||
|
||||
@ -164,6 +167,17 @@ mod imp {
|
||||
self.area.set_focusable(true);
|
||||
self.area.set_focus_on_click(true);
|
||||
|
||||
self.area
|
||||
.connect_create_context(clone!(@weak obj => @default-panic, move |_| {
|
||||
// can't connect-after create-context yet, so idle it
|
||||
glib::idle_add_local(clone!(@weak ec => @default-panic, move || {
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
priv_.attach_qemu_console(&obj);
|
||||
glib::Continue(false)
|
||||
}));
|
||||
None
|
||||
}));
|
||||
|
||||
unsafe {
|
||||
self.area.connect_notify_unsafe(
|
||||
Some("resize-hack"),
|
||||
@ -189,6 +203,93 @@ mod imp {
|
||||
}
|
||||
|
||||
impl WidgetImpl for QemuConsole {}
|
||||
|
||||
impl QemuConsole {
|
||||
fn get_toplevel(&self) -> Option<gdk::Toplevel> {
|
||||
self.area
|
||||
.get_root()
|
||||
.and_then(|r| r.get_native())
|
||||
.and_then(|n| n.get_surface())
|
||||
.and_then(|s| s.downcast::<gdk::Toplevel>().ok())
|
||||
}
|
||||
|
||||
fn motion(&self, x: f64, y: f64) {
|
||||
if let Some((x, y)) = self.area.transform_input(x, y) {
|
||||
let c = self.console.get().unwrap();
|
||||
let _ = c.mouse.set_abs_position(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn attach_qemu_console(&self, obj: &super::QemuConsole) {
|
||||
let console = match self.console.get() {
|
||||
Some(console) => console,
|
||||
None => return,
|
||||
};
|
||||
if !obj.get_realized() {
|
||||
return;
|
||||
}
|
||||
|
||||
let (rx, wait_tx) = console
|
||||
.glib_listen()
|
||||
.expect("Failed to listen to the console");
|
||||
self.area
|
||||
.connect_render(clone!(@weak obj => @default-panic, move |_, _| {
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
let wait_rendering = priv_.wait_rendering.get();
|
||||
if wait_rendering > 0 {
|
||||
if let Err(e) = wait_tx.send(()) {
|
||||
eprintln!("Failed to ack rendering: {}", e);
|
||||
}
|
||||
priv_.wait_rendering.set(wait_rendering - 1);
|
||||
}
|
||||
glib::signal::Inhibit(false)
|
||||
}));
|
||||
rx.attach(
|
||||
None,
|
||||
clone!(@weak obj => @default-panic, move |t| {
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
debug!("Console event: {:?}", t);
|
||||
match t {
|
||||
Event::Scanout(s) => {
|
||||
priv_.area.set_scanout(s);
|
||||
priv_.area.queue_render();
|
||||
}
|
||||
Event::Update(u) => {
|
||||
priv_.area.update(u);
|
||||
priv_.area.queue_render();
|
||||
}
|
||||
Event::ScanoutDMABUF(s) => {
|
||||
priv_.label.set_label(&format!("{:?}", s));
|
||||
priv_.area.set_scanout_dmabuf(s);
|
||||
}
|
||||
Event::UpdateDMABUF { .. } => {
|
||||
priv_.wait_rendering.set(priv_.wait_rendering.get() + 1);
|
||||
// we don't simply queue_render, as we want a copy immediately
|
||||
priv_.area.make_current();
|
||||
priv_.area.attach_buffers();
|
||||
let _ = unsafe {
|
||||
glib::Object::from_glib_borrow(priv_.area.as_ptr() as *mut glib::gobject_ffi::GObject)
|
||||
.emit_by_name("render", &[&priv_.area.get_context().as_ref()])
|
||||
.unwrap()
|
||||
};
|
||||
priv_.area.queue_draw();
|
||||
}
|
||||
Event::Disconnected => {
|
||||
priv_.label.set_label("Console disconnected!");
|
||||
}
|
||||
Event::CursorDefine { width, height, hot_x, hot_y, data }=> {
|
||||
let bytes = glib::Bytes::from(&data);
|
||||
let tex = gdk::MemoryTexture::new(width, height, gdk::MemoryFormat::B8g8r8a8, &bytes, width as usize * 4);
|
||||
let cur = gdk::Cursor::from_texture(&tex, hot_x, hot_y, None);
|
||||
priv_.area.set_cursor(Some(&cur));
|
||||
}
|
||||
_t => { }
|
||||
}
|
||||
Continue(true)
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
@ -198,92 +299,14 @@ glib::wrapper! {
|
||||
impl QemuConsole {
|
||||
pub fn set_qemu_console(&self, console: Console) {
|
||||
let priv_ = imp::QemuConsole::from_instance(self);
|
||||
let (rx, wait_tx) = console
|
||||
.glib_listen()
|
||||
.expect("Failed to listen to the console");
|
||||
priv_
|
||||
.area
|
||||
.connect_render(clone!(@weak self as obj => @default-panic, move |_, _| {
|
||||
let priv_ = imp::QemuConsole::from_instance(&obj);
|
||||
let wait_rendering = priv_.wait_rendering.get();
|
||||
if wait_rendering > 0 {
|
||||
if let Err(e) = wait_tx.send(()) {
|
||||
eprintln!("Failed to ack rendering: {}", e);
|
||||
}
|
||||
priv_.wait_rendering.set(wait_rendering - 1);
|
||||
}
|
||||
glib::signal::Inhibit(false)
|
||||
}));
|
||||
rx.attach(
|
||||
None,
|
||||
clone!(@weak self as con => @default-panic, move |t| {
|
||||
let priv_ = imp::QemuConsole::from_instance(&con);
|
||||
debug!("Console event: {:?}", t);
|
||||
match t {
|
||||
Event::Scanout(s) => {
|
||||
priv_.area.set_scanout(s);
|
||||
priv_.area.queue_render();
|
||||
}
|
||||
Event::Update(u) => {
|
||||
priv_.area.update(u);
|
||||
priv_.area.queue_render();
|
||||
}
|
||||
Event::ScanoutDMABUF(s) => {
|
||||
priv_.label.set_label(&format!("{:?}", s));
|
||||
priv_.area.set_scanout_dmabuf(s);
|
||||
}
|
||||
Event::UpdateDMABUF { .. } => {
|
||||
priv_.wait_rendering.set(priv_.wait_rendering.get() + 1);
|
||||
// we don't simply queue_render, as we want a copy immediately
|
||||
priv_.area.make_current();
|
||||
priv_.area.attach_buffers();
|
||||
let _ = unsafe {
|
||||
glib::Object::from_glib_borrow(priv_.area.as_ptr() as *mut glib::gobject_ffi::GObject)
|
||||
.emit_by_name("render", &[&priv_.area.get_context().as_ref()])
|
||||
.unwrap()
|
||||
};
|
||||
priv_.area.queue_draw();
|
||||
}
|
||||
Event::Disconnected => {
|
||||
priv_.label.set_label("Console disconnected!");
|
||||
}
|
||||
Event::CursorDefine { width, height, hot_x, hot_y, data }=> {
|
||||
let bytes = glib::Bytes::from(&data);
|
||||
let tex = gdk::MemoryTexture::new(width, height, gdk::MemoryFormat::B8g8r8a8, &bytes, width as usize * 4);
|
||||
let cur = gdk::Cursor::from_texture(&tex, hot_x, hot_y, None);
|
||||
priv_.area.set_cursor(Some(&cur));
|
||||
}
|
||||
_t => { }
|
||||
}
|
||||
Continue(true)
|
||||
}),
|
||||
);
|
||||
priv_.console.set(console).unwrap();
|
||||
}
|
||||
|
||||
fn get_toplevel(&self) -> Option<gdk::Toplevel> {
|
||||
let priv_ = imp::QemuConsole::from_instance(self);
|
||||
priv_
|
||||
.area
|
||||
.get_root()
|
||||
.and_then(|r| r.get_native())
|
||||
.and_then(|n| n.get_surface())
|
||||
.and_then(|s| s.downcast::<gdk::Toplevel>().ok())
|
||||
priv_.attach_qemu_console(self);
|
||||
}
|
||||
|
||||
fn qemu_console(&self) -> &Console {
|
||||
let priv_ = imp::QemuConsole::from_instance(self);
|
||||
priv_.console.get().expect("Console is not yet set!")
|
||||
}
|
||||
|
||||
fn motion(&self, x: f64, y: f64) {
|
||||
let priv_ = imp::QemuConsole::from_instance(self);
|
||||
|
||||
if let Some((x, y)) = priv_.area.transform_input(x, y) {
|
||||
let c = self.qemu_console();
|
||||
let _ = c.mouse.set_abs_position(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_gdk_button(button: u32) -> MouseButton {
|
||||
|
Loading…
Reference in New Issue
Block a user