everything
This commit is contained in:
16
src/main/java/dev/jlibghostty/FocusEvent.java
Normal file
16
src/main/java/dev/jlibghostty/FocusEvent.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package dev.jlibghostty;
|
||||
|
||||
public enum FocusEvent {
|
||||
GAINED(0),
|
||||
LOST(1);
|
||||
|
||||
private final int nativeValue;
|
||||
|
||||
FocusEvent(int nativeValue) {
|
||||
this.nativeValue = nativeValue;
|
||||
}
|
||||
|
||||
int nativeValue() {
|
||||
return nativeValue;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,14 @@ public final class Ghostty {
|
||||
return Terminal.open(options);
|
||||
}
|
||||
|
||||
public static GhosttyBuildInfo buildInfo() {
|
||||
return GhosttyLibrary.loadDefault().buildInfo();
|
||||
}
|
||||
|
||||
public static String typeJson() {
|
||||
return GhosttyLibrary.loadDefault().typeJson();
|
||||
}
|
||||
|
||||
public static boolean pasteIsSafe(String text) {
|
||||
return pasteIsSafe(text.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
@@ -28,4 +36,28 @@ public final class Ghostty {
|
||||
public static byte[] encodePaste(byte[] data, boolean bracketed) {
|
||||
return GhosttyLibrary.loadDefault().pasteEncode(data, bracketed);
|
||||
}
|
||||
|
||||
public static String encodeFocus(FocusEvent event) {
|
||||
return new String(encodeFocusBytes(event), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static byte[] encodeFocusBytes(FocusEvent event) {
|
||||
return GhosttyLibrary.loadDefault().focusEncode(event.nativeValue());
|
||||
}
|
||||
|
||||
public static String encodeModeReport(int mode, ModeReportState state) {
|
||||
return new String(encodeModeReportBytes(mode, state), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static byte[] encodeModeReportBytes(int mode, ModeReportState state) {
|
||||
return GhosttyLibrary.loadDefault().modeReportEncode(mode, state.nativeValue());
|
||||
}
|
||||
|
||||
public static String encodeSizeReport(SizeReportStyle style, SizeReportSize size) {
|
||||
return new String(encodeSizeReportBytes(style, size), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static byte[] encodeSizeReportBytes(SizeReportStyle style, SizeReportSize size) {
|
||||
return GhosttyLibrary.loadDefault().sizeReportEncode(style.nativeValue(), size);
|
||||
}
|
||||
}
|
||||
|
||||
15
src/main/java/dev/jlibghostty/GhosttyBuildInfo.java
Normal file
15
src/main/java/dev/jlibghostty/GhosttyBuildInfo.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package dev.jlibghostty;
|
||||
|
||||
public record GhosttyBuildInfo(
|
||||
boolean simd,
|
||||
boolean kittyGraphics,
|
||||
boolean tmuxControlMode,
|
||||
OptimizeMode optimizeMode,
|
||||
String version,
|
||||
long versionMajor,
|
||||
long versionMinor,
|
||||
long versionPatch,
|
||||
String versionPre,
|
||||
String versionBuild
|
||||
) {
|
||||
}
|
||||
165
src/main/java/dev/jlibghostty/GhosttyNative.java
Normal file
165
src/main/java/dev/jlibghostty/GhosttyNative.java
Normal file
@@ -0,0 +1,165 @@
|
||||
package dev.jlibghostty;
|
||||
|
||||
import dev.jlibghostty.internal.NativeLibraryLoader;
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.SymbolLookup;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class GhosttyNative {
|
||||
private static final SymbolLookup SYMBOLS = SymbolLookup.libraryLookup(
|
||||
NativeLibraryLoader.resolve(),
|
||||
Arena.global()
|
||||
);
|
||||
|
||||
private GhosttyNative() {
|
||||
}
|
||||
|
||||
public static List<String> symbolNames() {
|
||||
return Symbols.ALL;
|
||||
}
|
||||
|
||||
public static Optional<MemorySegment> findSymbol(String name) {
|
||||
return SYMBOLS.find(name);
|
||||
}
|
||||
|
||||
public static MemorySegment requireSymbol(String name) {
|
||||
return findSymbol(name)
|
||||
.orElseThrow(() -> new UnsatisfiedLinkError("Missing libghostty-vt symbol: " + name));
|
||||
}
|
||||
|
||||
public static MethodHandle downcall(String name, FunctionDescriptor descriptor) {
|
||||
return Linker.nativeLinker().downcallHandle(requireSymbol(name), descriptor);
|
||||
}
|
||||
|
||||
private static final class Symbols {
|
||||
private static final List<String> ALL = List.of(
|
||||
"ghostty_alloc",
|
||||
"ghostty_build_info",
|
||||
"ghostty_cell_get",
|
||||
"ghostty_cell_get_multi",
|
||||
"ghostty_color_rgb_get",
|
||||
"ghostty_focus_encode",
|
||||
"ghostty_formatter_format_alloc",
|
||||
"ghostty_formatter_format_buf",
|
||||
"ghostty_formatter_free",
|
||||
"ghostty_formatter_terminal_new",
|
||||
"ghostty_free",
|
||||
"ghostty_grid_ref_cell",
|
||||
"ghostty_grid_ref_graphemes",
|
||||
"ghostty_grid_ref_hyperlink_uri",
|
||||
"ghostty_grid_ref_row",
|
||||
"ghostty_grid_ref_style",
|
||||
"ghostty_kitty_graphics_get",
|
||||
"ghostty_kitty_graphics_image",
|
||||
"ghostty_kitty_graphics_image_get",
|
||||
"ghostty_kitty_graphics_image_get_multi",
|
||||
"ghostty_kitty_graphics_placement_get",
|
||||
"ghostty_kitty_graphics_placement_get_multi",
|
||||
"ghostty_kitty_graphics_placement_grid_size",
|
||||
"ghostty_kitty_graphics_placement_iterator_free",
|
||||
"ghostty_kitty_graphics_placement_iterator_new",
|
||||
"ghostty_kitty_graphics_placement_iterator_set",
|
||||
"ghostty_kitty_graphics_placement_next",
|
||||
"ghostty_kitty_graphics_placement_pixel_size",
|
||||
"ghostty_kitty_graphics_placement_rect",
|
||||
"ghostty_kitty_graphics_placement_render_info",
|
||||
"ghostty_kitty_graphics_placement_source_rect",
|
||||
"ghostty_kitty_graphics_placement_viewport_pos",
|
||||
"ghostty_mode_report_encode",
|
||||
"ghostty_osc_command_data",
|
||||
"ghostty_osc_command_type",
|
||||
"ghostty_osc_end",
|
||||
"ghostty_osc_free",
|
||||
"ghostty_osc_new",
|
||||
"ghostty_osc_next",
|
||||
"ghostty_osc_reset",
|
||||
"ghostty_paste_encode",
|
||||
"ghostty_paste_is_safe",
|
||||
"ghostty_render_state_colors_get",
|
||||
"ghostty_render_state_free",
|
||||
"ghostty_render_state_get",
|
||||
"ghostty_render_state_get_multi",
|
||||
"ghostty_render_state_new",
|
||||
"ghostty_render_state_row_cells_free",
|
||||
"ghostty_render_state_row_cells_get",
|
||||
"ghostty_render_state_row_cells_get_multi",
|
||||
"ghostty_render_state_row_cells_new",
|
||||
"ghostty_render_state_row_cells_next",
|
||||
"ghostty_render_state_row_cells_select",
|
||||
"ghostty_render_state_row_get",
|
||||
"ghostty_render_state_row_get_multi",
|
||||
"ghostty_render_state_row_iterator_free",
|
||||
"ghostty_render_state_row_iterator_new",
|
||||
"ghostty_render_state_row_iterator_next",
|
||||
"ghostty_render_state_row_set",
|
||||
"ghostty_render_state_set",
|
||||
"ghostty_render_state_update",
|
||||
"ghostty_row_get",
|
||||
"ghostty_row_get_multi",
|
||||
"ghostty_sgr_attribute_tag",
|
||||
"ghostty_sgr_attribute_value",
|
||||
"ghostty_sgr_free",
|
||||
"ghostty_sgr_new",
|
||||
"ghostty_sgr_next",
|
||||
"ghostty_sgr_reset",
|
||||
"ghostty_sgr_set_params",
|
||||
"ghostty_sgr_unknown_full",
|
||||
"ghostty_sgr_unknown_partial",
|
||||
"ghostty_size_report_encode",
|
||||
"ghostty_style_default",
|
||||
"ghostty_style_is_default",
|
||||
"ghostty_sys_log_stderr",
|
||||
"ghostty_sys_set",
|
||||
"ghostty_terminal_free",
|
||||
"ghostty_terminal_get",
|
||||
"ghostty_terminal_get_multi",
|
||||
"ghostty_terminal_grid_ref",
|
||||
"ghostty_terminal_grid_ref_track",
|
||||
"ghostty_terminal_mode_get",
|
||||
"ghostty_terminal_mode_set",
|
||||
"ghostty_terminal_new",
|
||||
"ghostty_terminal_point_from_grid_ref",
|
||||
"ghostty_terminal_reset",
|
||||
"ghostty_terminal_resize",
|
||||
"ghostty_terminal_scroll_viewport",
|
||||
"ghostty_terminal_select_all",
|
||||
"ghostty_terminal_select_line",
|
||||
"ghostty_terminal_select_output",
|
||||
"ghostty_terminal_select_word",
|
||||
"ghostty_terminal_select_word_between",
|
||||
"ghostty_terminal_selection_adjust",
|
||||
"ghostty_terminal_selection_contains",
|
||||
"ghostty_terminal_selection_equal",
|
||||
"ghostty_terminal_selection_format_alloc",
|
||||
"ghostty_terminal_selection_format_buf",
|
||||
"ghostty_terminal_selection_order",
|
||||
"ghostty_terminal_selection_ordered",
|
||||
"ghostty_terminal_set",
|
||||
"ghostty_terminal_vt_write",
|
||||
"ghostty_tracked_grid_ref_free",
|
||||
"ghostty_tracked_grid_ref_has_value",
|
||||
"ghostty_tracked_grid_ref_point",
|
||||
"ghostty_tracked_grid_ref_set",
|
||||
"ghostty_tracked_grid_ref_snapshot",
|
||||
"ghostty_type_json",
|
||||
"ghostty_wasm_alloc_opaque",
|
||||
"ghostty_wasm_alloc_sgr_attribute",
|
||||
"ghostty_wasm_alloc_u16_array",
|
||||
"ghostty_wasm_alloc_u8",
|
||||
"ghostty_wasm_alloc_u8_array",
|
||||
"ghostty_wasm_alloc_usize",
|
||||
"ghostty_wasm_free_opaque",
|
||||
"ghostty_wasm_free_sgr_attribute",
|
||||
"ghostty_wasm_free_u16_array",
|
||||
"ghostty_wasm_free_u8",
|
||||
"ghostty_wasm_free_u8_array",
|
||||
"ghostty_wasm_free_usize"
|
||||
);
|
||||
}
|
||||
}
|
||||
19
src/main/java/dev/jlibghostty/ModeReportState.java
Normal file
19
src/main/java/dev/jlibghostty/ModeReportState.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package dev.jlibghostty;
|
||||
|
||||
public enum ModeReportState {
|
||||
NOT_RECOGNIZED(0),
|
||||
SET(1),
|
||||
RESET(2),
|
||||
PERMANENTLY_SET(3),
|
||||
PERMANENTLY_RESET(4);
|
||||
|
||||
private final int nativeValue;
|
||||
|
||||
ModeReportState(int nativeValue) {
|
||||
this.nativeValue = nativeValue;
|
||||
}
|
||||
|
||||
int nativeValue() {
|
||||
return nativeValue;
|
||||
}
|
||||
}
|
||||
23
src/main/java/dev/jlibghostty/OptimizeMode.java
Normal file
23
src/main/java/dev/jlibghostty/OptimizeMode.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package dev.jlibghostty;
|
||||
|
||||
public enum OptimizeMode {
|
||||
DEBUG(0),
|
||||
RELEASE_SAFE(1),
|
||||
RELEASE_SMALL(2),
|
||||
RELEASE_FAST(3);
|
||||
|
||||
private final int nativeValue;
|
||||
|
||||
OptimizeMode(int nativeValue) {
|
||||
this.nativeValue = nativeValue;
|
||||
}
|
||||
|
||||
public static OptimizeMode fromNative(int value) {
|
||||
for (OptimizeMode mode : values()) {
|
||||
if (mode.nativeValue == value) {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown Ghostty optimize mode: " + value);
|
||||
}
|
||||
}
|
||||
18
src/main/java/dev/jlibghostty/SizeReportSize.java
Normal file
18
src/main/java/dev/jlibghostty/SizeReportSize.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package dev.jlibghostty;
|
||||
|
||||
public record SizeReportSize(int rows, int columns, long cellWidth, long cellHeight) {
|
||||
public SizeReportSize {
|
||||
if (rows < 1 || rows > 65535) {
|
||||
throw new IllegalArgumentException("rows must be between 1 and 65535");
|
||||
}
|
||||
if (columns < 1 || columns > 65535) {
|
||||
throw new IllegalArgumentException("columns must be between 1 and 65535");
|
||||
}
|
||||
if (cellWidth < 0 || cellWidth > 0xffffffffL) {
|
||||
throw new IllegalArgumentException("cellWidth must fit in uint32_t");
|
||||
}
|
||||
if (cellHeight < 0 || cellHeight > 0xffffffffL) {
|
||||
throw new IllegalArgumentException("cellHeight must fit in uint32_t");
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/main/java/dev/jlibghostty/SizeReportStyle.java
Normal file
18
src/main/java/dev/jlibghostty/SizeReportStyle.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package dev.jlibghostty;
|
||||
|
||||
public enum SizeReportStyle {
|
||||
MODE_2048(0),
|
||||
CSI_14_T(1),
|
||||
CSI_16_T(2),
|
||||
CSI_18_T(3);
|
||||
|
||||
private final int nativeValue;
|
||||
|
||||
SizeReportStyle(int nativeValue) {
|
||||
this.nativeValue = nativeValue;
|
||||
}
|
||||
|
||||
int nativeValue() {
|
||||
return nativeValue;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package dev.jlibghostty.internal;
|
||||
|
||||
import dev.jlibghostty.GhosttyBuildInfo;
|
||||
import dev.jlibghostty.GhosttyException;
|
||||
import dev.jlibghostty.OptimizeMode;
|
||||
import dev.jlibghostty.SizeReportSize;
|
||||
import dev.jlibghostty.TerminalOptions;
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
@@ -61,6 +64,17 @@ public final class GhosttyLibrary {
|
||||
private static final int GHOSTTY_OUT_OF_SPACE = -3;
|
||||
private static final int GHOSTTY_NO_VALUE = -4;
|
||||
|
||||
private static final int BUILD_INFO_SIMD = 1;
|
||||
private static final int BUILD_INFO_KITTY_GRAPHICS = 2;
|
||||
private static final int BUILD_INFO_TMUX_CONTROL_MODE = 3;
|
||||
private static final int BUILD_INFO_OPTIMIZE = 4;
|
||||
private static final int BUILD_INFO_VERSION_STRING = 5;
|
||||
private static final int BUILD_INFO_VERSION_MAJOR = 6;
|
||||
private static final int BUILD_INFO_VERSION_MINOR = 7;
|
||||
private static final int BUILD_INFO_VERSION_PATCH = 8;
|
||||
private static final int BUILD_INFO_VERSION_PRE = 9;
|
||||
private static final int BUILD_INFO_VERSION_BUILD = 10;
|
||||
|
||||
private static final Linker LINKER = Linker.nativeLinker();
|
||||
private static final AddressLayout C_POINTER = (AddressLayout) LINKER.canonicalLayouts().get("void*");
|
||||
private static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) LINKER.canonicalLayouts().get("bool");
|
||||
@@ -81,6 +95,13 @@ public final class GhosttyLibrary {
|
||||
C_SIZE_T.withName("len")
|
||||
);
|
||||
|
||||
private static final GroupLayout SIZE_REPORT_SIZE = MemoryLayout.structLayout(
|
||||
C_SHORT.withName("rows"),
|
||||
C_SHORT.withName("columns"),
|
||||
C_INT.withName("cell_width"),
|
||||
C_INT.withName("cell_height")
|
||||
);
|
||||
|
||||
private static final GroupLayout KITTY_RENDER_INFO = MemoryLayout.structLayout(
|
||||
C_SIZE_T.withName("size"),
|
||||
C_INT.withName("pixel_width"),
|
||||
@@ -107,6 +128,11 @@ public final class GhosttyLibrary {
|
||||
private final MethodHandle terminalGet;
|
||||
private final MethodHandle pasteIsSafe;
|
||||
private final MethodHandle pasteEncode;
|
||||
private final MethodHandle buildInfo;
|
||||
private final MethodHandle typeJson;
|
||||
private final MethodHandle focusEncode;
|
||||
private final MethodHandle modeReportEncode;
|
||||
private final MethodHandle sizeReportEncode;
|
||||
private final MethodHandle kittyGraphicsGet;
|
||||
private final MethodHandle kittyGraphicsImage;
|
||||
private final MethodHandle kittyGraphicsImageGet;
|
||||
@@ -139,6 +165,16 @@ public final class GhosttyLibrary {
|
||||
FunctionDescriptor.of(C_BOOL, C_POINTER, C_SIZE_T));
|
||||
pasteEncode = downcall(symbols, "ghostty_paste_encode",
|
||||
FunctionDescriptor.of(C_INT, C_POINTER, C_SIZE_T, C_BOOL, C_POINTER, C_SIZE_T, C_POINTER));
|
||||
buildInfo = downcall(symbols, "ghostty_build_info",
|
||||
FunctionDescriptor.of(C_INT, C_INT, C_POINTER));
|
||||
typeJson = downcall(symbols, "ghostty_type_json",
|
||||
FunctionDescriptor.of(C_POINTER));
|
||||
focusEncode = downcall(symbols, "ghostty_focus_encode",
|
||||
FunctionDescriptor.of(C_INT, C_INT, C_POINTER, C_SIZE_T, C_POINTER));
|
||||
modeReportEncode = downcall(symbols, "ghostty_mode_report_encode",
|
||||
FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER, C_SIZE_T, C_POINTER));
|
||||
sizeReportEncode = downcall(symbols, "ghostty_size_report_encode",
|
||||
FunctionDescriptor.of(C_INT, C_INT, SIZE_REPORT_SIZE, C_POINTER, C_SIZE_T, C_POINTER));
|
||||
kittyGraphicsGet = downcall(symbols, "ghostty_kitty_graphics_get",
|
||||
FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_POINTER));
|
||||
kittyGraphicsImage = downcall(symbols, "ghostty_kitty_graphics_image",
|
||||
@@ -375,6 +411,56 @@ public final class GhosttyLibrary {
|
||||
}
|
||||
}
|
||||
|
||||
public GhosttyBuildInfo buildInfo() {
|
||||
return new GhosttyBuildInfo(
|
||||
buildInfoBoolean(BUILD_INFO_SIMD),
|
||||
buildInfoBoolean(BUILD_INFO_KITTY_GRAPHICS),
|
||||
buildInfoBoolean(BUILD_INFO_TMUX_CONTROL_MODE),
|
||||
OptimizeMode.fromNative(buildInfoInt(BUILD_INFO_OPTIMIZE)),
|
||||
buildInfoString(BUILD_INFO_VERSION_STRING),
|
||||
buildInfoSizeT(BUILD_INFO_VERSION_MAJOR),
|
||||
buildInfoSizeT(BUILD_INFO_VERSION_MINOR),
|
||||
buildInfoSizeT(BUILD_INFO_VERSION_PATCH),
|
||||
buildInfoString(BUILD_INFO_VERSION_PRE),
|
||||
buildInfoString(BUILD_INFO_VERSION_BUILD)
|
||||
);
|
||||
}
|
||||
|
||||
public String typeJson() {
|
||||
try {
|
||||
MemorySegment ptr = (MemorySegment) typeJson.invoke();
|
||||
if (ptr.address() == 0) {
|
||||
return "";
|
||||
}
|
||||
return ptr.reinterpret(16L * 1024L * 1024L).getString(0);
|
||||
} catch (Throwable t) {
|
||||
return rethrow(t);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] focusEncode(int event) {
|
||||
return encodeBuffer("ghostty_focus_encode", (arena, out, outLen, outWritten) ->
|
||||
(int) focusEncode.invoke(event, out, outLen, outWritten)
|
||||
);
|
||||
}
|
||||
|
||||
public byte[] modeReportEncode(int mode, int state) {
|
||||
return encodeBuffer("ghostty_mode_report_encode", (arena, out, outLen, outWritten) ->
|
||||
(int) modeReportEncode.invoke(mode, state, out, outLen, outWritten)
|
||||
);
|
||||
}
|
||||
|
||||
public byte[] sizeReportEncode(int style, SizeReportSize size) {
|
||||
return encodeBuffer("ghostty_size_report_encode", (arena, out, outLen, outWritten) -> {
|
||||
MemorySegment nativeSize = arena.allocate(SIZE_REPORT_SIZE);
|
||||
nativeSize.set(C_SHORT, 0, (short) size.rows());
|
||||
nativeSize.set(C_SHORT, 2, (short) size.columns());
|
||||
nativeSize.set(C_INT, 4, (int) size.cellWidth());
|
||||
nativeSize.set(C_INT, 8, (int) size.cellHeight());
|
||||
return (int) sizeReportEncode.invoke(style, nativeSize, out, outLen, outWritten);
|
||||
});
|
||||
}
|
||||
|
||||
public void kittyGraphicsPopulatePlacementIterator(MemorySegment graphics, MemorySegment iterator) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment out = arena.allocate(C_POINTER);
|
||||
@@ -544,6 +630,90 @@ public final class GhosttyLibrary {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean buildInfoBoolean(int key) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment out = arena.allocate(C_BOOL);
|
||||
int result = (int) buildInfo.invoke(key, out);
|
||||
checkResult("ghostty_build_info", result);
|
||||
return out.get(C_BOOL, 0);
|
||||
} catch (Throwable t) {
|
||||
return rethrow(t);
|
||||
}
|
||||
}
|
||||
|
||||
private int buildInfoInt(int key) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment out = arena.allocate(C_INT);
|
||||
int result = (int) buildInfo.invoke(key, out);
|
||||
checkResult("ghostty_build_info", result);
|
||||
return out.get(C_INT, 0);
|
||||
} catch (Throwable t) {
|
||||
return rethrow(t);
|
||||
}
|
||||
}
|
||||
|
||||
private long buildInfoSizeT(int key) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment out = arena.allocate(C_SIZE_T);
|
||||
int result = (int) buildInfo.invoke(key, out);
|
||||
checkResult("ghostty_build_info", result);
|
||||
return out.get(C_SIZE_T, 0);
|
||||
} catch (Throwable t) {
|
||||
return rethrow(t);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildInfoString(int key) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment out = arena.allocate(GHOSTTY_STRING);
|
||||
int result = (int) buildInfo.invoke(key, out);
|
||||
checkResult("ghostty_build_info", result);
|
||||
return readGhosttyString(out);
|
||||
} catch (Throwable t) {
|
||||
return rethrow(t);
|
||||
}
|
||||
}
|
||||
|
||||
private String readGhosttyString(MemorySegment string) {
|
||||
MemorySegment ptr = string.get(C_POINTER, 0);
|
||||
long len = string.get(C_SIZE_T, 8);
|
||||
if (ptr.address() == 0 || len == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] bytes = ptr.reinterpret(len).toArray(JAVA_BYTE);
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private byte[] encodeBuffer(String operation, Encoder encoder) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment outWritten = arena.allocate(C_SIZE_T);
|
||||
int result = encoder.invoke(arena, MemorySegment.NULL, 0L, outWritten);
|
||||
if (result != GHOSTTY_SUCCESS && result != GHOSTTY_OUT_OF_SPACE) {
|
||||
checkResult(operation, result);
|
||||
}
|
||||
|
||||
long required = outWritten.get(C_SIZE_T, 0);
|
||||
if (required == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
MemorySegment out = arena.allocate(required, 1);
|
||||
result = encoder.invoke(arena, out, required, outWritten);
|
||||
checkResult(operation, result);
|
||||
|
||||
long written = outWritten.get(C_SIZE_T, 0);
|
||||
return out.asSlice(0, written).toArray(JAVA_BYTE);
|
||||
} catch (Throwable t) {
|
||||
return rethrow(t);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface Encoder {
|
||||
int invoke(Arena arena, MemorySegment out, long outLen, MemorySegment outWritten) throws Throwable;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T rethrow(Throwable t) {
|
||||
if (t instanceof RuntimeException runtimeException) {
|
||||
|
||||
@@ -72,6 +72,46 @@
|
||||
"void*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"returnType": "int",
|
||||
"parameterTypes": [
|
||||
"int",
|
||||
"void*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"returnType": "void*",
|
||||
"parameterTypes": []
|
||||
},
|
||||
{
|
||||
"returnType": "int",
|
||||
"parameterTypes": [
|
||||
"int",
|
||||
"void*",
|
||||
"size_t",
|
||||
"void*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"returnType": "int",
|
||||
"parameterTypes": [
|
||||
"int",
|
||||
"int",
|
||||
"void*",
|
||||
"size_t",
|
||||
"void*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"returnType": "int",
|
||||
"parameterTypes": [
|
||||
"int",
|
||||
"struct(short, short, int, int)",
|
||||
"void*",
|
||||
"size_t",
|
||||
"void*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"returnType": "void*",
|
||||
"parameterTypes": [
|
||||
|
||||
@@ -14,6 +14,21 @@ public final class GhosttySmokeTest {
|
||||
if (!"hello".equals(Ghostty.encodePaste("hello", false))) {
|
||||
throw new AssertionError("simple paste encoding changed unexpectedly");
|
||||
}
|
||||
if (Ghostty.buildInfo().version().isEmpty()) {
|
||||
throw new AssertionError("build info version should not be empty");
|
||||
}
|
||||
if (Ghostty.typeJson().isEmpty()) {
|
||||
throw new AssertionError("type JSON should not be empty");
|
||||
}
|
||||
if (Ghostty.encodeFocus(FocusEvent.GAINED).isEmpty()) {
|
||||
throw new AssertionError("focus encoding should not be empty");
|
||||
}
|
||||
if (Ghostty.encodeModeReport(25, ModeReportState.SET).isEmpty()) {
|
||||
throw new AssertionError("mode report encoding should not be empty");
|
||||
}
|
||||
if (Ghostty.encodeSizeReport(SizeReportStyle.CSI_18_T, new SizeReportSize(24, 80, 8, 16)).isEmpty()) {
|
||||
throw new AssertionError("size report encoding should not be empty");
|
||||
}
|
||||
|
||||
try (Terminal terminal = Ghostty.open(TerminalOptions.of(80, 24))) {
|
||||
terminal.setKittyImageStorageLimit(1024 * 1024);
|
||||
|
||||
Reference in New Issue
Block a user