gtk-rs / gtk

DEPRECATED, use https://github.com/gtk-rs/gtk3-rs repository instead!

Home Page:https://gtk-rs.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GtkWindow "set-focus" Signal Parameter is Nullable

misson20000 opened this issue · comments

It is poorly (read: not) documented, but the "set-focus" on GtkWindow signal's widget parameter can be null.

The “set-focus” signal

void
user_function (GtkWindow *window,
               GtkWidget *widget,
               gpointer   user_data)

https://developer.gnome.org/gtk3/stable/GtkWindow.html

I know this because I had it happen to me. See (ptr=0x0) in the backtrace.

(gdb) bt
#0  rust_panic () at src/libstd/panicking.rs:563
#1  0x00005555556b8f45 in std::panicking::rust_panic_with_hook () at src/libstd/panicking.rs:533
#2  0x00005555556ae7b1 in std::panicking::begin_panic (msg=...) at /rustc/76b11980ad416c3ad6143504c2277757ecacf9b5/src/libstd/panicking.rs:438
#3  0x00005555556804fd in <gtk::auto::widget::Widget as glib::translate::FromGlibPtrBorrow<*mut gtk_sys::GtkWidget>>::from_glib_borrow (ptr=0x0) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.3/src/object.rs:902
#4  0x000055555567c34e in glib::translate::from_glib_borrow (ptr=0x0) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.3/src/translate.rs:1228
#5  0x000055555559c19e in <O as gtk::auto::window::GtkWindowExt>::connect_set_focus::set_focus_trampoline (this=0x555555ac42b0, object=0x0, f=0x555555b5c2b0) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/gtk-0.8.1/src/auto/window.rs:2161
#6  0x00007ffff733d61a in g_closure_invoke () at /usr/lib/libgobject-2.0.so.0
#7  0x00007ffff731e97e in  () at /usr/lib/libgobject-2.0.so.0
#8  0x00007ffff7321ab9 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#9  0x00007ffff73236b0 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#10 0x00007ffff78d59c0 in  () at /usr/lib/libgtk-3.so.0
#11 0x00007ffff78ecfbe in gtk_widget_set_child_visible () at /usr/lib/libgtk-3.so.0
#12 0x00007ffff7a10896 in  () at /usr/lib/libgtk-3.so.0
#13 0x00007ffff733d61a in g_closure_invoke () at /usr/lib/libgobject-2.0.so.0
#14 0x00007ffff731e0e8 in  () at /usr/lib/libgobject-2.0.so.0
#15 0x00007ffff7321ab9 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#16 0x00007ffff73236b0 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#17 0x00007ffff7a1432c in gtk_notebook_set_current_page () at /usr/lib/libgtk-3.so.0
#18 0x00005555555b9292 in <O as gtk::notebook::NotebookExtManual>::set_current_page (self=0x555555b6de48, page_num=...) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/gtk-0.8.1/src/notebook.rs:254

The signature of gtk::GtkWindowExt::connect_set_focus's callback probably needs to be changed to take a Option<&Widget>. Or, (and I expect this to be the more preferable option), the code generator needs to somehow be informed that this value is nullable. Not sure how to do that myself or I'd PR it.

Here's a backtrace with better symbols. The null focus comes from _gtk_window_unset_focus_and_default.

#0  rust_panic () at src/libstd/panicking.rs:563
#1  0x00005555556b8f45 in std::panicking::rust_panic_with_hook () at src/libstd/panicking.rs:533
#2  0x00005555556ae7b1 in std::panicking::begin_panic (msg=...) at /rustc/76b11980ad416c3ad6143504c2277757ecacf9b5/src/libstd/panicking.rs:438
#3  0x00005555556804fd in <gtk::auto::widget::Widget as glib::translate::FromGlibPtrBorrow<*mut gtk_sys::GtkWidget>>::from_glib_borrow (ptr=0x0) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.3/src/object.rs:902
#4  0x000055555567c34e in glib::translate::from_glib_borrow (ptr=0x0) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.3/src/translate.rs:1228
#5  0x000055555559c19e in <O as gtk::auto::window::GtkWindowExt>::connect_set_focus::set_focus_trampoline (this=0x555555abe2b0, object=0x0, f=0x555555ab5a90) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/gtk-0.8.1/src/auto/window.rs:2161
#6  0x00007ffff734b61a in g_closure_invoke () at /usr/lib/libgobject-2.0.so.0
#7  0x00007ffff732c97e in  () at /usr/lib/libgobject-2.0.so.0
#8  0x00007ffff732fab9 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#9  0x00007ffff73316b0 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#10 0x00007ffff78e7257 in _gtk_window_unset_focus_and_default (window=0x555555abe2b0, widget=0x555555a71210) at ../gtk/gtk/gtkwindow.c:9125
#11 0x00007ffff78fde8a in gtk_widget_set_child_visible (widget=0x555555a71210, is_visible=0) at ../gtk/gtk/gtkwidget.c:10815
#12 0x00007ffff7a19e93 in gtk_notebook_real_switch_page (notebook=0x555555ad82b0, child=<optimized out>, page_num=<optimized out>) at ../gtk/gtk/gtknotebook.c:6209
#13 0x00007ffff734b61a in g_closure_invoke () at /usr/lib/libgobject-2.0.so.0
#14 0x00007ffff732c0e8 in  () at /usr/lib/libgobject-2.0.so.0
#15 0x00007ffff732fab9 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#16 0x00007ffff73316b0 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#17 0x00007ffff7a15ce0 in gtk_notebook_switch_page (notebook=<optimized out>, page=<optimized out>) at ../gtk/gtk/gtknotebook.c:6264
#18 0x00007ffff7a1d7c9 in gtk_notebook_set_current_page (notebook=0x555555ad82b0, page_num=<optimized out>) at ../gtk/gtk/gtknotebook.c:6847
#19 0x00005555555b9292 in <O as gtk::notebook::NotebookExtManual>::set_current_page (self=0x555555b93ad8, page_num=...) at /home/misson20000/.cargo/registry/src/github.com-1ecc6299db9ec823/gtk-0.8.1/src/notebook.rs:254

And a minimal case:

extern crate gio;
extern crate gtk;

use gio::prelude::*;
use gtk::prelude::*;

use std::env::args;

fn build_ui(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);

    window.set_title("null poc");
    window.set_border_width(10);
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(350, 70);

    let button = gtk::Button::new_with_label("Click me!");
    window.add(&button);

    window.show_all();

    button.grab_focus();
    window.connect_set_focus(|_, _| println!("got set focus signal"));
    button.hide();
}

fn main() {
    let application =
        gtk::Application::new(None, Default::default())
            .expect("Initialization failed.");

    application.connect_activate(|app| {
        build_ui(app);
    });

    application.run(&args().collect::<Vec<_>>());
}

Seems to be an upstream issue caused by someone having botched the formatting on the signal's annotation GNOME/gtk@93bcca7. There is one colon where in every other annotation there are two.

Ugh, but this signal seems to have actually recently been entirely removed from mainline GTK in favor of the focus-widget property.

And the story continues to develop, since the focus-widget property doesn't exist in release versions of GTK yet. Looks like we're stuck between versions here. Not sure what to do about that.

git master of GTK is GTK 4, GTK 3 is maintained in a branch. These bindings are for GTK 3.

So two steps are needed here: 1) report this to GTK against their GTK 3 branch, ideally as a MR, 2) fix it on our side by adding the nullable annotation via Gir.toml.

Probably also want to do a short check with grep if there are other such documentation/annotation mistakes in GTK.

Fixed upstream: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/1677.
Couldn't find any other mistakes.

Perhaps this issue should be left open so that we don't forget to remove the workaround when the upstream fix makes its way into gir-files.