Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DO NOT MERGE] Initial script to build a working Graal binary, Windows #159

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions deploy/META-INF/native-image/io.github.humbleui.jwm/jni-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
[
{
"name":"io.github.humbleui.jwm.Clipboard",
"methods":[{"name":"_registerPredefinedFormat","parameterTypes":["java.lang.String"] }]}
,
{
"name":"io.github.humbleui.jwm.ClipboardEntry",
"fields":[
{"name":"_data"},
{"name":"_format"}
],
"methods":[{"name":"make","parameterTypes":["io.github.humbleui.jwm.ClipboardFormat","byte[]"] }]}
,
{
"name":"io.github.humbleui.jwm.ClipboardFormat",
"fields":[{"name":"_formatId"}]}
,
{
"name":"io.github.humbleui.jwm.EventFrame",
"fields":[{"name":"INSTANCE"}]}
,
{
"name":"io.github.humbleui.jwm.EventKey",
"methods":[{"name":"<init>","parameterTypes":["int","boolean","int","int"] }]}
,
{
"name":"io.github.humbleui.jwm.EventMouseButton",
"methods":[{"name":"<init>","parameterTypes":["int","boolean","int"] }]}
,
{
"name":"io.github.humbleui.jwm.EventMouseMove",
"methods":[{"name":"<init>","parameterTypes":["int","int","int","int"] }]}
,
{
"name":"io.github.humbleui.jwm.EventMouseScroll",
"methods":[{"name":"<init>","parameterTypes":["float","float","int"] }]}
,
{
"name":"io.github.humbleui.jwm.EventTextInput",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]}
,
{
"name":"io.github.humbleui.jwm.EventTextInputMarked",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","int","int"] }]}
,
{
"name":"io.github.humbleui.jwm.EventWindowCloseRequest",
"fields":[{"name":"INSTANCE"}]}
,
{
"name":"io.github.humbleui.jwm.EventWindowMaximize",
"fields":[{"name":"INSTANCE"}]}
,
{
"name":"io.github.humbleui.jwm.EventWindowMinimize",
"fields":[{"name":"INSTANCE"}]}
,
{
"name":"io.github.humbleui.jwm.EventWindowMove",
"methods":[{"name":"<init>","parameterTypes":["int","int"] }]}
,
{
"name":"io.github.humbleui.jwm.EventWindowResize",
"methods":[{"name":"<init>","parameterTypes":["int","int","int","int"] }]}
,
{
"name":"io.github.humbleui.jwm.EventWindowRestore",
"fields":[{"name":"INSTANCE"}]}
,
{
"name":"io.github.humbleui.jwm.EventWindowScreenChange",
"fields":[{"name":"INSTANCE"}]}
,
{
"name":"io.github.humbleui.jwm.LayerNotSupportedException"}
,
{
"name":"io.github.humbleui.jwm.Screen",
"methods":[{"name":"<init>","parameterTypes":["long","boolean","io.github.humbleui.jwm.UIRect","io.github.humbleui.jwm.UIRect","float"] }]}
,
{
"name":"io.github.humbleui.jwm.TextInputClient",
"methods":[{"name":"getRectForMarkedRange","parameterTypes":["int","int"] }]}
,
{
"name":"io.github.humbleui.jwm.UIRect",
"fields":[
{"name":"_bottom"},
{"name":"_left"},
{"name":"_right"},
{"name":"_top"}
],
"methods":[{"name":"<init>","parameterTypes":["int","int","int","int"] }]}
,
{
"name":"io.github.humbleui.jwm.impl.Native",
"fields":[{"name":"_ptr"}]}
,
{
"name":"java.lang.ClassLoader",
"methods":[
{"name":"getPlatformClassLoader","parameterTypes":[] },
{"name":"loadClass","parameterTypes":["java.lang.String"] }
]}
,
{
"name":"java.lang.Runnable",
"methods":[{"name":"run","parameterTypes":[] }]}
,
{
"name":"java.lang.RuntimeException"}
,
{
"name":"java.lang.Throwable",
"methods":[{"name":"printStackTrace","parameterTypes":[] }]}
,
{
"name":"java.util.function.Consumer",
"methods":[{"name":"accept","parameterTypes":["java.lang.Object"] }]}
,
{
"name":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"}
,
{
"name":"org.graalvm.nativebridge.jni.JNIExceptionWrapperEntryPoints",
"methods":[{"name":"getClassName","parameterTypes":["java.lang.Class"] }]}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"resources":{
"includes":[
{"pattern":"\\Qjwm.version\\E"},
{"pattern":"\\Qjwm_x64.dll\\E"}
]},
"bundles":[]
}
235 changes: 52 additions & 183 deletions examples/java/Example.java
Original file line number Diff line number Diff line change
@@ -1,205 +1,74 @@
package io.github.humbleui.jwm.examples;

import io.github.humbleui.jwm.*;
import org.jetbrains.skija.*;

import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.stream.*;
import java.io.File;

public class Example implements Consumer<Event> {
public static int PADDING = 10;
public static int COLS = 4, ROWS = 3;
public static final KeyModifier MODIFIER = Platform.CURRENT == Platform.MACOS ? KeyModifier.MAC_COMMAND : KeyModifier.CONTROL;
public static Font FONT12 = new Font(FontMgr.getDefault().matchFamilyStyleCharacter(null, FontStyle.NORMAL, null, "↑".codePointAt(0)), 12);
public static Font FONT24 = new Font(FontMgr.getDefault().matchFamilyStyle(null, FontStyle.NORMAL), 24);
public static Font FONT48 = new Font(FontMgr.getDefault().matchFamilyStyle(null, FontStyle.BOLD), 48);

public float lastScale = 1f;
public PanelTextInput panelTextInput;
public PanelScreens panelScreens;
public PanelLegend panelLegend;
public PanelMouse panelMouse;
public PanelAnimation panelAnimation;
public PanelMouseCursors panelMouseCursors;
public PanelRendering panelRendering;
public PanelEvents panelEvents;

public Window window;

public boolean paused = true;
public boolean closed = false;

public Example() {
window = App.makeWindow();
window.setEventListener(this);

panelTextInput = new PanelTextInput(window);
panelScreens = new PanelScreens(window);
panelLegend = new PanelLegend(window);
panelMouse = new PanelMouse(window);
panelAnimation = new PanelAnimation(window);
panelMouseCursors = new PanelMouseCursors(window);
panelRendering = new PanelRendering(window);
panelEvents = new PanelEvents(window);
import java.util.function.Consumer;

import io.github.humbleui.jwm.App;
import io.github.humbleui.jwm.Event;
import io.github.humbleui.jwm.EventFrame;
import io.github.humbleui.jwm.EventWindowCloseRequest;
import io.github.humbleui.jwm.EventWindowResize;
import io.github.humbleui.jwm.EventWindowScreenChange;
import io.github.humbleui.jwm.LayerGL;
import io.github.humbleui.jwm.UIRect;
import io.github.humbleui.jwm.Window;
import io.github.humbleui.jwm.WindowWin32;
public class Example {
public static void main(String[] args) {
App.init();

var scale = window.getScreen().getScale();
int count = App._windows.size() - 1;
Screen screen = App.getScreens()[(count / 5) % App.getScreens().length];
UIRect bounds = screen.getWorkArea();
// Using the generic window seems to cause:
// Exception in thread "main" java.lang.NoSuchMethodException: io.github.humbleui.jwm.WindowWin32.<init>()
// at java.lang.Class.getConstructor0(DynamicHub.java:3585)
// at java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754)
// at io.github.humbleui.jwm.App.makeWindow(App.java:50)
// at io.github.humbleui.jwm.examples.Example.main(Example.java:18)

window.setWindowSize(bounds.getWidth() / 2, bounds.getHeight() / 2);
switch (count % 5) {
case 0 -> window.setWindowPosition(bounds.getLeft() + bounds.getWidth() / 4, bounds.getTop() + bounds.getHeight() / 4);
case 1 -> window.setWindowPosition(bounds.getLeft(), bounds.getTop());
case 2 -> window.setWindowPosition(bounds.getLeft() + bounds.getWidth() / 2, bounds.getTop());
case 3 -> window.setWindowPosition(bounds.getLeft(), bounds.getTop() + bounds.getHeight() / 2);
case 4 -> window.setWindowPosition(bounds.getLeft() + bounds.getWidth() / 2, bounds.getTop() + bounds.getHeight() / 2);
}
window.setTitle("JWM Window #" + count);
// Maybe because the underlying constructor isn't directly invoked, so Graal doesn't statically analyze it?
// Potential solution: Hard-code "if OS == WINDOWS { new WindowWin32() }" etc?

switch (Platform.CURRENT) {
case WINDOWS -> {
window.setIcon(new File("examples/resources/windows.ico"));
}
case MACOS -> {
window.setIcon(new File("examples/resources/macos.icns"));
}
}
// Window window = App.makeWindow();
WindowWin32 window = new WindowWin32();
window.setEventListener(new EventHandler(window));
window.setVisible(true);
window.requestFrame();
App.start();
}
}

public void paint(String reason) {
if (closed)
return;

UIRect contentRect = window.getContentRect();

// If content area empty no rendering must happen
if (contentRect.getWidth() <= 0 || contentRect.getHeight() <= 0)
return;

float scale = window.getScreen().getScale();
PADDING = (int) (10 * scale);
int panelWidth = (contentRect.getWidth() - (COLS + 1) * PADDING) / COLS;
int panelHeight = (contentRect.getHeight() - (ROWS + 1) * PADDING) / ROWS;
if (panelWidth <= 0 || panelHeight <= 0)
return;

if (lastScale != scale) {
FONT12.setSize(12 * scale);
FONT24.setSize(24 * scale);
FONT48.setSize(48 * scale);
}

var canvas = panelRendering.layer.beforePaint();
canvas.clear(0xFF264653);
int canvasCount = canvas.save();

// First row
panelTextInput.paint (canvas, PADDING + (panelWidth + PADDING) * 0, PADDING + (panelHeight + PADDING) * 0, panelWidth, panelHeight, scale);
panelMouse.paint (canvas, PADDING + (panelWidth + PADDING) * 1, PADDING + (panelHeight + PADDING) * 0, panelWidth, panelHeight, scale);
panelMouseCursors.paint (canvas, PADDING + (panelWidth + PADDING) * 2, PADDING + (panelHeight + PADDING) * 0, panelWidth, panelHeight, scale);
panelLegend.paint (canvas, PADDING + (panelWidth + PADDING) * 3, PADDING + (panelHeight + PADDING) * 0, panelWidth, panelHeight * 3 + PADDING * 2, scale);

// Second row
panelScreens.paint (canvas, PADDING + (panelWidth + PADDING) * 0, PADDING + (panelHeight + PADDING) * 1, panelWidth, panelHeight, scale);
panelAnimation.paint (canvas, PADDING + (panelWidth + PADDING) * 1, PADDING + (panelHeight + PADDING) * 1, panelWidth, panelHeight, scale);
panelRendering.bumpCounter(reason);
panelRendering.paint (canvas, PADDING + (panelWidth + PADDING) * 2, PADDING + (panelHeight + PADDING) * 1, panelWidth, panelHeight, scale);

// Third row
panelEvents.paint (canvas, PADDING + (panelWidth + PADDING) * 0, PADDING + (panelHeight + PADDING) * 2, panelWidth * 3 + PADDING * 2, panelHeight, scale);

// Colored bars
try (var paint = new Paint()) {
int width = contentRect.getWidth();
int height = contentRect.getHeight();
var barSize = 3 * scale;

// left
paint.setColor(0xFFe76f51);
canvas.drawRect(Rect.makeXYWH(0, 0, barSize, 100 * scale), paint);
canvas.drawRect(Rect.makeXYWH(0, height / 2 - 50 * scale, barSize, 100 * scale), paint);
canvas.drawRect(Rect.makeXYWH(0, height - 100 * scale, barSize, 100 * scale), paint);

// top
paint.setColor(0xFF2a9d8f);
canvas.drawRect(Rect.makeXYWH(0, 0, 100 * scale, barSize), paint);
canvas.drawRect(Rect.makeXYWH(width / 2 - 50 * scale, 0, 100 * scale, barSize), paint);
canvas.drawRect(Rect.makeXYWH(width - 100 * scale, 0, 100 * scale, barSize), paint);

// right
paint.setColor(0xFFe9c46a);
canvas.drawRect(Rect.makeXYWH(width - barSize, 0, barSize, 100 * scale), paint);
canvas.drawRect(Rect.makeXYWH(width - barSize, height / 2 - 50 * scale, barSize, 100 * scale), paint);
canvas.drawRect(Rect.makeXYWH(width - barSize, height - 100 * scale, barSize, 100 * scale), paint);

// bottom
paint.setColor(0xFFFFFFFF);
canvas.drawRect(Rect.makeXYWH(0, height - barSize, 100 * scale, barSize), paint);
canvas.drawRect(Rect.makeXYWH(width / 2 - 50 * scale, height - barSize, 100 * scale, barSize), paint);
canvas.drawRect(Rect.makeXYWH(width - 100 * scale, height - barSize, 100 * scale, barSize), paint);
}
canvas.restoreToCount(canvasCount);
class EventHandler implements Consumer<Event> {
public final Window window;
public final LayerGL layer;

panelRendering.layer.afterPaint();
public EventHandler(Window window) {
this.window = window;
layer = new LayerGL();
layer.attach(window);
}

@Override
public void accept(Event e) {
panelTextInput.accept(e);
panelScreens.accept(e);
panelMouse.accept(e);
panelMouseCursors.accept(e);
panelRendering.accept(e);
panelEvents.accept(e);
System.out.println(e);

float scale = window.getScreen().getScale();
if (e instanceof EventKey eventKey) {
if (eventKey.isPressed() == true && eventKey.isModifierDown(MODIFIER)) {
switch (eventKey.getKey()) {
case P -> {
paused = !paused;
if (!paused)
window.requestFrame();
}
case N ->
new Example();
case H ->
window.setVisible(false);
case W ->
accept(EventWindowCloseRequest.INSTANCE);
case O ->
window.setOpacity(window.getOpacity() == 1f ? 0.5f : 1f);
case UP ->
window.maximize();
case DOWN ->
window.restore();
case M ->
window.minimize();
}
}
if (e instanceof EventWindowCloseRequest) {
window.close();
App.terminate();
} else if (e instanceof EventWindowScreenChange) {
layer.reconfigure();
UIRect contentRect = window.getContentRect();
layer.resize(contentRect.getWidth(), contentRect.getHeight());
paint();
} else if (e instanceof EventWindowResize ee) {
paint("Resize");
layer.resize(ee.getContentWidth(), ee.getContentHeight());
paint();
} else if (e instanceof EventFrame) {
paint("Frame");
if (!paused)
window.requestFrame();
} else if (e instanceof EventWindowCloseRequest) {
closed = true;
window.close();
if (App._windows.size() == 0)
App.terminate();
paint();
window.requestFrame();
}
}

public static void main(String[] args) {
App.init();
new Example();
App.start();
public void paint() {
layer.makeCurrent();
// do the drawing
layer.swapBuffers();
}
}
Loading