If you're writing a simple GTK application in Rust (e.g. with gtk4-rs) and you get this error
GLib-GIO-CRITICAL **: 13:39:45.953: This application can not open files.
and go "But I'm not opening any files, and I didn't ask to?!", you might want to be more explicit about that.
It might be because you're taking command-line arguments intended for other purposes, but gtk4 for Rust's Application::run() 'helpfully' collects any CLI arguments on your behalf without being asked to, even though you did not provide them directly (e.g. with Application::run_with_args()).
So, if you'd like to parse some CLI arguments for other reasons, you'll need to explicitly not provide them to your GTK application, or you'll need to pretend to handle them.
Approach 1: Explicitly ignore arguments
Instead of running your Application `app` like this:
let exit_code : ExitCode = app.run ();
Be explicit, like this:
let no_args : [&str; 0] = []; let exit_code : ExitCode = app.run_with_args (&no_args);
Approach 2: Claim to handle files (and then don't!)
let app : Application = Application::builder () .application_id (APP_ID) .flags (ApplicationFlags::HANDLES_OPEN) .build (); ... app.connect_open (open_cb); let exit_code : ExitCode = app.run (); ... pub fn open_cb (_app : &Application, _files : &[File], _hint: &str) { }
This can be unintuitive, because in C, if you don't claim to handle opening of files, and don't explicitly provide argc/argv to g_application_run (), it does not assume you want to handle open. But C is a bit like approach 1, in that you are explicitly not providing them, since you have to pass 0 and NULL for argc and argv respectively.
Simple C application
This will simply and naively pop-up a window that shows the text provided in argv[1].
main.c#include <gtk/gtk.h> int activate (GApplication *app, gpointer *user_data) { GtkWidget *window = gtk_application_window_new (GTK_APPLICATION (app)); gtk_window_set_title (GTK_WINDOW (window), "Demo"); gtk_window_set_default_size (GTK_WINDOW (window), 600, 400); GtkWidget *label = gtk_label_new ((char*)user_data); gtk_window_set_child (GTK_WINDOW (window), label); gtk_window_present (GTK_WINDOW (window)); } int main (int argc, char **argv) { GtkApplication *app = gtk_application_new ("org.kosmokaryote.test20240415.C", G_APPLICATION_DEFAULT_FLAGS); g_signal_connect (G_APPLICATION (app), "activate", G_CALLBACK (activate), argv[1]); return g_application_run (G_APPLICATION (app), 0, NULL); }
Compiled with:
gcc `pkg-config --cflags --libs gtk4` main.c -o main
Corresponding Rust
cargo new test cargo add gtk4 --features v4_12src/main.rs
use gtk4::{Application,gio::ApplicationFlags, glib::ExitCode, prelude::*, ApplicationWindow, Label}; use std::env::{self, Args}; fn activate (app : &Application) { let mut args : Args = env::args (); let window : ApplicationWindow = ApplicationWindow::builder () .application (app) .title ("Demo") .default_width (600) .default_height (400) .build (); let label : Label = match args.nth (1) { Some(s) => Label::new (Some (s.as_str ())), None => Label::new (None) }; window.set_child (Some(&label)); window.present (); } fn main() -> ExitCode { let app : Application = Application::new (Some ("org.kosmokaryote.test20240415.Rust"), ApplicationFlags::FLAGS_NONE); app.connect_activate (activate); // app.run () let no_args : [&str; 0] = []; app.run_with_args (&no_args) }