Reputation: 29
Recently, I have been working on a small gui app that uses GTK4. This gui app uses a combination of Java and Rust (I am using the jni crate for interop).
I am creating the Gui window using the Gtk-rs crate in Rust. I have Java code calling into Rust using the JNI.
The compilation process is pretty smooth, I produce a dynamic library (.so) from the Rust side and load it in Java, compile the Java files and create a Java archive that's executable. The native library is dynamically linked.
However, when I execute the archive, I get this weird message:
"Unknown option -jar"
and nothing happens.
The main function in Java is defined as:
//runner.java
public static void main(String[] args) {
Application app = new Application(
"Test",
"/home/radon/RustroverProjects/guiframe/target/release/libguiframe.so"
);
}
This Application class takes the Application name and the library path as its constructor arguments.
The Application constructor is defined as (there is only 1 constructor):
public Application(
String name,
String nativeLibAbsolutePath
) {
this.name = name;
bridge = new NativeBridge(nativeLibAbsolutePath); //bridge is a class field
bridge.getApplication(this);
}
This getApplication function of NativeBridge class is defined in Rust. It uses JNI to access the name field of the class and creates a GTK window using the start function which uses the get_app function:
//This is the getApplication method.
#[allow(static_mut_refs)]
#[allow(non_snake_case)]
#[no_mangle]
pub(crate) extern "C" fn Java_ix_radon_guiframe_ffi_NativeBridge_getApplication<'local> (
mut env: JNIEnv<'local>,
_native_bridge_object: JObject<'local>,
app: JObject
) {
let _name = Into::<JString>::into(env.get_field(&app, "name", "Ljava/lang/String;").unwrap().l().unwrap());
let name = Into::<String>::into(env.get_string(&_name).unwrap());
unsafe {
JAPPLICATION = Application { //JAPPLICATION is a mutable static
name
};
JAPPLICATION.start();
}
}
#[allow(static_mut_refs)]
pub(crate) fn get_app(name: String) {
let app = Application::builder()
.application_id(&format!("ix.radon.guiframe.{}", &name))
.build();
app.connect_activate(move |app| {
let window = ApplicationWindow::builder()
.application(app)
.default_width(960)
.default_height(540)
.title(&name)
.build();
window.present();
});
app.run();
}
I have checked the jar's manifest and everything else, but it doesn't seem to work.
If I dont use the Application class in my main function, everything works as normal.
I did add .flags(ApplicationFlags::HANDLES_COMMAND_LINE)
and test it out. Fortunately, Unknown option -jar doesnt happen but I get this on executing the jar:
(java:17014): Gtk-WARNING **: Unknown key gtk-modules in /my_path/.config/gtk-4.0/settings.ini
(java:17014): GLib-GIO-WARNING **: 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.
Some help on this would be nice.
Upvotes: 0
Views: 145
Reputation: 31020
This is actually default behavior of GApplication
(the superclass of GtkApplication
):
GApplication processes arguments in a way that is reasonable for most applications:
an invocation with no command line arguments results in the application being activated (ie: the 'activate' signal is emitted or your 'activate' method is called) an invocation with one or more filenames or URIs on the command line will result in the 'open' signal being emitted (or 'open' method being called)
if --gapplication-service is given as the sole command line argument, GApplication will set the G_APPLICATION_IS_SERVICE flag and run in service mode. See HowDoI/DBusApplicationLaunching for information about that.
if the application enables it, --gapplication-app-id can be used to override the app id
if using GtkApplication then Gtk-specific commandline arguments will be handled in the usual way
--help is supported
all other commandline flags are rejected
You can disable this default processing by telling Gtk (Glib, really) your application will do its own processing:
let app = Application::builder()
.application_id(&format!("ix.radon.guiframe.{}", &name))
.flags(ApplicationFlags::HANDLES_COMMAND_LINE) // <-- add this line
.build();
Upvotes: 2