Manage taskbar from JavaFX
petr.stechmuller at seznam.cz
petr.stechmuller at seznam.cz
Fri Jan 10 09:03:26 UTC 2025
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20250110/98fcef07/attachment-0001.htm>
More information about the openjfx-dev
mailing list