Hi all,
As the title says, I’m trying to use a GestureMultiPress
to capture mouse input. However, I’ve found Rust deallocates it once the scope it lives in ends.
My default approach to fix this would be to add a return argument mut reference to the function, but the function signature is fixed because it’s used in a call to connect_activate
.
If instead I make a function which takes a return argument, and returns a closure, it either won’t let me mutate, because it’s a Fn
(no mutation of captured vars allowed), or I make in an FnMut
, which would allow mutation, but then it’s the incorrect type to be given to connect_activate
.
That all said, I’m stuck. How am I supposed to keep the gesture alive here?
Here’s the original code; uncomment the Rc leak if you want to see the GestureMultiPress
activate properly.
use std::rc::Rc;
use std::mem;
use gtk::gdk::EventMask;
use gtk::prelude::*;
use gtk::{DrawingArea, GestureMultiPress};
const APP_NAME : &'static str = "com.example.appname";
const APP_TITLE : &'static str = "Example App";
const APP_WIDTH : i32 = 600;
const APP_HEIGHT : i32 = 600;
const APP_BORDER_WIDTH : u32 = 20;
fn build_ui<'a>(application : &'a gtk::Application) {
let window = gtk::ApplicationWindow::new(application);
window.set_title(APP_TITLE);
window.set_border_width(APP_BORDER_WIDTH);
window.set_position(gtk::WindowPosition::Center);
window.set_default_size(APP_WIDTH, APP_HEIGHT);
let drw_area = {
DrawingArea::builder()
.width_request(APP_WIDTH - 2*APP_BORDER_WIDTH as i32)
.height_request(APP_HEIGHT - 2*APP_BORDER_WIDTH as i32)
.build()
};
drw_area.connect_draw(|a, c| {
c.set_source_rgb(0.0, 0.0, 0.0);
c.rectangle(0.0, 0.0, a.allocated_width() as f64, a.allocated_height() as f64);
let _ = c.fill();
Inhibit(false)
});
window.add(&drw_area);
drw_area.add_events(EventMask::BUTTON_PRESS_MASK | EventMask::BUTTON_RELEASE_MASK);
let gmpress =
GestureMultiPress::builder()
.widget(&drw_area)
.button(0)
.build();
gmpress.connect_pressed(|g, npress, x, y| {
println!("({}, {npress}, {x}, {y})", g.current_button());
});
let a = Rc::new(gmpress);
// mem::forget(a.clone());
window.show_all();
}
fn main() {
let application =
gtk::Application::new(Some(APP_NAME), Default::default());
application.connect_activate(build_ui);
application.run();
}