rustgtk4

Struggling to implement argument handling inside of my Rust GTK4 project


I'm working on a library that abstracts a lot of GTK4 and GTK4 Layer Shell, but I'm hitting a standstill on implementing the ability to process arguments.

When this code is ran:

impl Factory {
    /// Creates a new `Factory` with the given application ID.
    pub fn new(id: &str) -> Self {
        if env::args().len() > 1 {
            let application = Application::builder()
                .application_id(id)
                .flags(ApplicationFlags::HANDLES_COMMAND_LINE)
                .build();

            Self { application }
        } else {
            let application = Application::builder().application_id(id).build();
            Self { application }
        }
    }

    ...

    /// Runs the application with arguments.
    pub fn pollute_with_args(
        self,
        chunks: impl Fn(Application) + 'static,
        args: Vec<String>,
    ) -> ExitCode {
        self.application.connect_activate(move |app| {
            chunks(app.clone());
        });

        self.application.run_with_args(&args);
        ExitCode::SUCCESS
    }
}

...

fn main() {
    let factory = Factory::new("chunk.factory");
    let args: Vec<String> = env::args().collect();

    let args_clone = args.clone();
    let chunks = move |factory: GtkApp| {
        match args_clone[1].as_str() {
            "storage" => storage(&factory),
            "clock" => clock(&factory),
            _ => eprintln!("Unknown argument: {}", args_clone[1]),
        }
        load_css(STYLE);
    };

    factory.pollute_with_args(chunks, args);
}

It gives this error:

GLib-GIO-WARNING **: 03:08:44.991: Your application claims to support custom command line handling but does not implement g_application_command_line() and has no handlers connected to the 'command-line' signal.

And I'm not quite sure how to fix it.

I feel as if the answer may be staring me in the face, and it is driving me mad.


Solution

  • You need to use connect_command_line:

    /// Runs the application with arguments.
    pub fn pollute_with_args(
        self,
        handler: impl Fn(&Application, &ApplicationCommandLine) -> i32 + 'static,
        args: Vec<String>,
    ) -> ExitCode {
        // Connect the command-line signal with correct signature
        self.application.connect_command_line(handler);
    
        self.application.run_with_args(&args);
        ExitCode::SUCCESS
    }
    

    (as you already figured out in your Github repository)