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