gtk: some refactoring

This commit is contained in:
Marc-André Lureau 2021-03-26 01:44:09 +04:00
parent 7cda1c29e3
commit f6bbaf0b2d
2 changed files with 109 additions and 84 deletions

View File

@ -1,2 +1,4 @@
paths = ['../gtk4-rs/gtk4']
[alias]
xtask = "run --package xtask --"

View File

@ -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,21 +203,37 @@ mod imp {
}
impl WidgetImpl for QemuConsole {}
}
glib::wrapper! {
pub struct QemuConsole(ObjectSubclass<imp::QemuConsole>) @extends gtk::Widget;
}
impl QemuConsole {
pub fn set_qemu_console(&self, console: Console) {
let priv_ = imp::QemuConsole::from_instance(self);
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");
priv_
.area
.connect_render(clone!(@weak self as obj => @default-panic, move |_, _| {
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 {
@ -216,8 +246,8 @@ impl QemuConsole {
}));
rx.attach(
None,
clone!(@weak self as con => @default-panic, move |t| {
let priv_ = imp::QemuConsole::from_instance(&con);
clone!(@weak obj => @default-panic, move |t| {
let priv_ = imp::QemuConsole::from_instance(&obj);
debug!("Console event: {:?}", t);
match t {
Event::Scanout(s) => {
@ -258,32 +288,25 @@ impl QemuConsole {
Continue(true)
}),
);
priv_.console.set(console).unwrap();
}
}
}
fn get_toplevel(&self) -> Option<gdk::Toplevel> {
glib::wrapper! {
pub struct QemuConsole(ObjectSubclass<imp::QemuConsole>) @extends gtk::Widget;
}
impl QemuConsole {
pub fn set_qemu_console(&self, console: Console) {
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_.console.set(console).unwrap();
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 {