Hello openjfx-dev, First of all I want thank you all for an amazing work you are doing. I'm excited about new features comming to FX and in general I do enjoy to work with the framework.
I would like to ask for help. I'm trying get more experience with new java FFM API. The best way how to learn new API is by using is in a project. My goal is to somehow have the ability to show on a taskbar progress of some long running task. As far as I know, there is no "native" support of this in JavaFX. There are some libraries like "https://github.com/Dansoftowner/FXTaskbarProgressBar" which serves the purpose, but only for Windows. And it is using the "old" JNI. After a short research, I found a simple library in go https://github.com/bibelin/taskbar. It got inspired by this library and tried to "convert" it to JavaFX. First I used jextract to get java bindings to native library calls: jextract --output target/generated-sources/jextract -t "taskbar_test.gen" -- include-function "XOpenDisplay" --include-function "XChangeProperty" -- include-function "XFlush" --include-function "XCloseDisplay" /usr/include/X 11/Xlib.h Then I created a simple application to simulate long running process where I try to update progress on taskbar by calling method "XChangeProperty" which I found in documentation of X11: https://www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html# XChangeProperty Unfortunately this does not work. The program does not crash, task is running on background, but no update on taskbar is happening. Here is the code I created: package taskbar_test; import com.sun.glass.ui.Window; import javafx.application.Application; import javafx.concurrent.Task; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.VBox; import javafx.stage.Stage; import taskbar_test.gen.Xlib_h; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; public class AppLinuxXlib extends Application { @Override public void start(Stage primaryStage) { Button startButton = new Button("Start Long Running Task"); startButton.setOnAction(event -> { final long rawHandle = Window.getWindows().getFirst(). getRawHandle(); System.out.println(rawHandle); // Create a long-running task Task<Void> longTask = new Task<>() { @Override protected Void call() throws Exception { System.out.println("Started"); try (var arena = Arena.ofConfined()) { var NET_WM_XAPP_PROGRESS = arena.allocateFrom("NET_ WM_XAPP_PROGRESS"); // var NET_WM_XAPP_PROGRESS_PULSE = arena. allocateFrom("NET_WM_XAPP_PROGRESS_PULSE"); MemorySegment x11Session = Xlib_h.XOpenDisplay (MemorySegment.NULL); System.out.println(x11Session); // Prepare the progress data MemorySegment initData = arena.allocateFrom (ValueLayout.JAVA_INT, 0); Xlib_h.XChangeProperty(x11Session, // display MemorySegment.ofAddress(rawHandle).address() , // window NET_WM_XAPP_PROGRESS.address(), // property 6, // type 32, // format 0, // mode PropModeReplace=0 initData, // data 1); // nelements Xlib_h.XFlush(x11Session); System.out.println("Countdown started"); // Set the taskbar progress for (int i = 0; i <= 100; i+=20) { // Simulate work Thread.sleep(500); System.out.println(i); MemorySegment progressData = arena.allocateFrom (ValueLayout.JAVA_INT, i); // Update taskbar progress // https://www.x.org/releases/X11R7.7/doc/libX 11/libX11/libX11.html#XChangeProperty Xlib_h.XChangeProperty(x11Session, // display MemorySegment.ofAddress(rawHandle). address(), // window NET_WM_XAPP_PROGRESS.address(), // property 6, // type 32, // format 0, // mode PropModeReplace=0 progressData, // data 1); // nelements Xlib_h.XFlush(x11Session); } System.out.println("Finished"); Xlib_h.XCloseDisplay(x11Session); } catch (Throwable ex) { ex.printStackTrace(); } return null; } }; // Start the task in a new thread new Thread(longTask).start(); }); VBox vbox = new VBox(10, startButton); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.setTitle("Taskbar Progress Example Linux"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } Can someone show me what am I doing wrong and maybe point me to the correct direction with how to make the implementation work? Thank you very much. Best regards, Petr Štechmüller