Gtk-rs: BC won't let me close window

Hi, I'm pretty new to gtk-rs.

pub fn build_app_window(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);
    scopeguard::defer_on_success!(window.show_all());

    window.set_title(consts::APP_NAME);
    window.set_default_size(30*16, 100); // golden ratio
    window.set_border_width(consts::WINDOW_BORDER_WIDTH_PX);
    window.set_position(gtk::WindowPosition::Center);

    let framebox = gtk::Box::new(gtk::Orientation::Vertical, 5);
    scopeguard::defer_on_success!(window.add(&framebox));

    framebox.pack_start(&gtk::Label::new(Some(
        "Inxi not found in your PATH. Please install Inxi.",
    )), true, true, 0);

    framebox.pack_start(&{
        let btn = gtk::Button::new_with_label("Ok");
        btn.connect_clicked(move |_| window.close()); // NOTE HERE
        btn
        },true, false, 0);
}

Here, the noted line I used move and of course the borrow checker prevents it since I use window.shaw_all() later. Now if I remove the move, the BC says

closure may outlive the current function, but it borrows `window`, which is owned by the current function
  --> src/ui.rs:32:29
   |
32 |         btn.connect_clicked(|_| window.close());
   |                             ^^^ ------ `window` is borrowed here
   |                             |
   |                             may outlive borrowed value `window`
   |
note: function requires argument type to outlive `'static`
  --> src/ui.rs:32:9
   |
32 |         btn.connect_clicked(|_| window.close());
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `window` (and any other referenced variables), use the `move` keyword
   |
32 |         btn.connect_clicked(move |_| window.close());
   |                             ^^^^^^^^

error: aborting due to previous error

How can I deal with this?

You need to clone it before moving it into the closure.

// ...snip...
framebox.pack_start(&{
        let window_clone = window.clone();    // ADDED LINE
        let btn = gtk::Button::new_with_label("Ok");
        btn.connect_clicked(move |_| window_clone.close()); // CHANGED HERE TOO
        btn
        },true, false, 0);

If you dig into the gtk-rs documentation way down to the gobject level, you'll find that cloning gobjects just increments the ref count, so it's really cheap. When a gobject is dropped, g_object_unref is called.

GObject documentation (c-code)

This page on the Gtk-rs documentation explains it well with examples.

Edit: Here is where the gtk-rs documentation talks about cheap clones and mapping clone/drop to g_object_ref/g_object_unref in the C-library.

1 Like