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

Reply via email to