mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-05-28 07:45:20 +00:00
libghostty: starting the SelectionGesture API, just init/get
This commit is contained in:
@@ -39,6 +39,17 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Opaque handle to state for interpreting terminal selection gestures.
|
||||
*
|
||||
* The gesture owns only the state required to interpret pointer events. Calls
|
||||
* that use a gesture are not concurrency-safe and must be serialized with
|
||||
* terminal mutations.
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
typedef struct GhosttySelectionGestureImpl* GhosttySelectionGesture;
|
||||
|
||||
/**
|
||||
* A snapshot selection range defined by two grid references.
|
||||
*
|
||||
@@ -283,6 +294,189 @@ typedef enum GHOSTTY_ENUM_TYPED {
|
||||
GHOSTTY_SELECTION_ADJUST_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttySelectionAdjust;
|
||||
|
||||
/**
|
||||
* Selection behavior chosen for a gesture's click sequence.
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
typedef enum GHOSTTY_ENUM_TYPED {
|
||||
/** Cell-granular drag selection. */
|
||||
GHOSTTY_SELECTION_GESTURE_BEHAVIOR_CELL = 0,
|
||||
|
||||
/** Word selection on press and word-granular drag selection. */
|
||||
GHOSTTY_SELECTION_GESTURE_BEHAVIOR_WORD = 1,
|
||||
|
||||
/** Line selection on press and line-granular drag selection. */
|
||||
GHOSTTY_SELECTION_GESTURE_BEHAVIOR_LINE = 2,
|
||||
|
||||
/** Semantic command output selection on press and drag. */
|
||||
GHOSTTY_SELECTION_GESTURE_BEHAVIOR_OUTPUT = 3,
|
||||
|
||||
GHOSTTY_SELECTION_GESTURE_BEHAVIOR_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttySelectionGestureBehavior;
|
||||
|
||||
/**
|
||||
* Current autoscroll direction for an active selection drag gesture.
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
typedef enum GHOSTTY_ENUM_TYPED {
|
||||
/** No selection autoscroll is requested. */
|
||||
GHOSTTY_SELECTION_GESTURE_AUTOSCROLL_NONE = 0,
|
||||
|
||||
/** Selection dragging should autoscroll the viewport upward. */
|
||||
GHOSTTY_SELECTION_GESTURE_AUTOSCROLL_UP = 1,
|
||||
|
||||
/** Selection dragging should autoscroll the viewport downward. */
|
||||
GHOSTTY_SELECTION_GESTURE_AUTOSCROLL_DOWN = 2,
|
||||
|
||||
GHOSTTY_SELECTION_GESTURE_AUTOSCROLL_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttySelectionGestureAutoscroll;
|
||||
|
||||
/**
|
||||
* Data fields readable from a selection gesture with
|
||||
* ghostty_selection_gesture_get().
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
typedef enum GHOSTTY_ENUM_TYPED {
|
||||
/** Current click count: uint8_t*. 0 means inactive. */
|
||||
GHOSTTY_SELECTION_GESTURE_DATA_CLICK_COUNT = 0,
|
||||
|
||||
/** Whether the current/last left-click gesture has dragged: bool*. */
|
||||
GHOSTTY_SELECTION_GESTURE_DATA_DRAGGED = 1,
|
||||
|
||||
/** Current autoscroll request: GhosttySelectionGestureAutoscroll*. */
|
||||
GHOSTTY_SELECTION_GESTURE_DATA_AUTOSCROLL = 2,
|
||||
|
||||
/** Current gesture behavior: GhosttySelectionGestureBehavior*. */
|
||||
GHOSTTY_SELECTION_GESTURE_DATA_BEHAVIOR = 3,
|
||||
|
||||
/**
|
||||
* Current left-click anchor: GhosttyGridRef*.
|
||||
*
|
||||
* Returns GHOSTTY_NO_VALUE if there is no valid active anchor. On success,
|
||||
* writes an untracked GhosttyGridRef snapshot with normal GhosttyGridRef
|
||||
* lifetime rules.
|
||||
*/
|
||||
GHOSTTY_SELECTION_GESTURE_DATA_ANCHOR = 4,
|
||||
|
||||
GHOSTTY_SELECTION_GESTURE_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttySelectionGestureData;
|
||||
|
||||
/**
|
||||
* Create a selection gesture object.
|
||||
*
|
||||
* The gesture stores mutable state for terminal text selection gestures. The
|
||||
* gesture is not bound to a terminal at creation time; terminal-dependent APIs
|
||||
* take the terminal explicitly.
|
||||
*
|
||||
* @param allocator Allocator, or NULL for the default allocator
|
||||
* @param out_gesture Receives the created gesture handle
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if out_gesture is
|
||||
* NULL, or GHOSTTY_OUT_OF_MEMORY if allocation fails
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
GHOSTTY_API GhosttyResult ghostty_selection_gesture_new(
|
||||
const GhosttyAllocator* allocator,
|
||||
GhosttySelectionGesture* out_gesture);
|
||||
|
||||
/**
|
||||
* Free a selection gesture object.
|
||||
*
|
||||
* This releases any tracked terminal references owned by the gesture using the
|
||||
* provided terminal, then frees the gesture object. Passing NULL for gesture is
|
||||
* allowed and is a no-op.
|
||||
*
|
||||
* If the terminal is still alive, pass the terminal most recently used with the
|
||||
* gesture so any tracked terminal references can be released correctly. If the
|
||||
* terminal has already been freed, pass NULL for terminal; the terminal's page
|
||||
* storage has already released the underlying tracked references, so the
|
||||
* gesture wrapper can be safely discarded without touching the stale terminal
|
||||
* state.
|
||||
*
|
||||
* @param gesture Selection gesture handle to free
|
||||
* @param terminal Terminal used to release tracked gesture state, or NULL if
|
||||
* the terminal has already been freed
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
GHOSTTY_API void ghostty_selection_gesture_free(
|
||||
GhosttySelectionGesture gesture,
|
||||
GhosttyTerminal terminal);
|
||||
|
||||
/**
|
||||
* Reset any active selection gesture state.
|
||||
*
|
||||
* This cancels the active click sequence and releases any tracked terminal
|
||||
* references owned by the gesture without freeing the gesture object.
|
||||
* Passing NULL is allowed and is a no-op.
|
||||
*
|
||||
* @param gesture Selection gesture handle to reset
|
||||
* @param terminal Terminal used to release tracked gesture state
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
GHOSTTY_API void ghostty_selection_gesture_reset(
|
||||
GhosttySelectionGesture gesture,
|
||||
GhosttyTerminal terminal);
|
||||
|
||||
/**
|
||||
* Read data from a selection gesture.
|
||||
*
|
||||
* The type of value depends on data and is documented by
|
||||
* GhosttySelectionGestureData. For GHOSTTY_SELECTION_GESTURE_DATA_ANCHOR,
|
||||
* the returned GhosttyGridRef is an untracked snapshot with normal grid-ref
|
||||
* lifetime rules.
|
||||
*
|
||||
* @param gesture Selection gesture handle (NULL returns GHOSTTY_INVALID_VALUE)
|
||||
* @param terminal Terminal used to validate terminal-backed gesture state
|
||||
* @param data Data field to read
|
||||
* @param value Output pointer whose type depends on data
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_NO_VALUE if the requested data
|
||||
* has no value, or GHOSTTY_INVALID_VALUE if gesture, terminal, data, or
|
||||
* value is invalid
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
GHOSTTY_API GhosttyResult ghostty_selection_gesture_get(
|
||||
GhosttySelectionGesture gesture,
|
||||
GhosttyTerminal terminal,
|
||||
GhosttySelectionGestureData data,
|
||||
void* value);
|
||||
|
||||
/**
|
||||
* Read multiple data fields from a selection gesture in a single call.
|
||||
*
|
||||
* This is an optimization over calling ghostty_selection_gesture_get() multiple
|
||||
* times. Each entry in values must point to storage of the type documented by
|
||||
* the corresponding GhosttySelectionGestureData key.
|
||||
*
|
||||
* If any individual read fails, the function returns that error and writes the
|
||||
* index of the failing key to out_written when out_written is non-NULL. On
|
||||
* success, out_written receives count when non-NULL.
|
||||
*
|
||||
* @param gesture Selection gesture handle (NULL returns GHOSTTY_INVALID_VALUE)
|
||||
* @param terminal Terminal used to validate terminal-backed gesture state
|
||||
* @param count Number of data fields to read
|
||||
* @param keys Data fields to read (must not be NULL)
|
||||
* @param values Output pointers corresponding to keys (must not be NULL)
|
||||
* @param out_written Optional number of fields read, or failing index on error
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_NO_VALUE if a requested data
|
||||
* field has no value, or GHOSTTY_INVALID_VALUE if gesture, terminal,
|
||||
* keys, values, or a value pointer is invalid
|
||||
*
|
||||
* @ingroup selection
|
||||
*/
|
||||
GHOSTTY_API GhosttyResult ghostty_selection_gesture_get_multi(
|
||||
GhosttySelectionGesture gesture,
|
||||
GhosttyTerminal terminal,
|
||||
size_t count,
|
||||
const GhosttySelectionGestureData* keys,
|
||||
void** values,
|
||||
size_t* out_written);
|
||||
|
||||
/**
|
||||
* Derive a word selection snapshot from a terminal grid reference.
|
||||
*
|
||||
|
||||
@@ -251,6 +251,11 @@ comptime {
|
||||
@export(&c.terminal_selection_ordered, .{ .name = "ghostty_terminal_selection_ordered" });
|
||||
@export(&c.terminal_selection_contains, .{ .name = "ghostty_terminal_selection_contains" });
|
||||
@export(&c.terminal_selection_equal, .{ .name = "ghostty_terminal_selection_equal" });
|
||||
@export(&c.selection_gesture_new, .{ .name = "ghostty_selection_gesture_new" });
|
||||
@export(&c.selection_gesture_free, .{ .name = "ghostty_selection_gesture_free" });
|
||||
@export(&c.selection_gesture_reset, .{ .name = "ghostty_selection_gesture_reset" });
|
||||
@export(&c.selection_gesture_get, .{ .name = "ghostty_selection_gesture_get" });
|
||||
@export(&c.selection_gesture_get_multi, .{ .name = "ghostty_selection_gesture_get_multi" });
|
||||
@export(&c.terminal_grid_ref, .{ .name = "ghostty_terminal_grid_ref" });
|
||||
@export(&c.terminal_grid_ref_track, .{ .name = "ghostty_terminal_grid_ref_track" });
|
||||
@export(&c.terminal_point_from_grid_ref, .{ .name = "ghostty_terminal_point_from_grid_ref" });
|
||||
|
||||
@@ -70,6 +70,7 @@ const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const lib = @import("lib.zig");
|
||||
const PageList = @import("PageList.zig");
|
||||
const Pin = PageList.Pin;
|
||||
const Screen = @import("Screen.zig");
|
||||
@@ -118,22 +119,26 @@ left_drag_autoscroll: Autoscroll,
|
||||
///
|
||||
/// This is used to implement selection above/below the viewport that
|
||||
/// wants to drag the viewport.
|
||||
pub const Autoscroll = enum { none, up, down };
|
||||
pub const Autoscroll = lib.Enum(lib.target, &.{
|
||||
"none",
|
||||
"up",
|
||||
"down",
|
||||
});
|
||||
|
||||
/// The selection behavior for a click and subsequent drag.
|
||||
pub const Behavior = enum {
|
||||
/// Cell-granular drag selection. Press returns null to clear selection.
|
||||
cell,
|
||||
pub const Behavior = lib.Enum(lib.target, &.{
|
||||
// Cell-granular drag selection. Press returns null to clear selection.
|
||||
"cell",
|
||||
|
||||
/// Word selection on press and word-granular drag selection.
|
||||
word,
|
||||
// Word selection on press and word-granular drag selection.
|
||||
"word",
|
||||
|
||||
/// Line selection on press and line-granular drag selection.
|
||||
line,
|
||||
// Line selection on press and line-granular drag selection.
|
||||
"line",
|
||||
|
||||
/// Semantic command output selection on press and drag.
|
||||
output,
|
||||
};
|
||||
// Semantic command output selection on press and drag.
|
||||
"output",
|
||||
});
|
||||
|
||||
/// Standard terminal selection behavior for single-, double-, and triple-clicks.
|
||||
///
|
||||
|
||||
@@ -31,6 +31,7 @@ pub const modes = @import("modes.zig");
|
||||
pub const osc = @import("osc.zig");
|
||||
pub const render = @import("render.zig");
|
||||
pub const selection = @import("selection.zig");
|
||||
pub const selection_gesture = @import("selection_gesture.zig");
|
||||
pub const key_event = @import("key_event.zig");
|
||||
pub const key_encode = @import("key_encode.zig");
|
||||
pub const mouse_event = @import("mouse_event.zig");
|
||||
@@ -182,6 +183,11 @@ pub const terminal_selection_order = selection.order;
|
||||
pub const terminal_selection_ordered = selection.ordered;
|
||||
pub const terminal_selection_contains = selection.contains;
|
||||
pub const terminal_selection_equal = selection.equal;
|
||||
pub const selection_gesture_new = selection_gesture.new;
|
||||
pub const selection_gesture_free = selection_gesture.free;
|
||||
pub const selection_gesture_reset = selection_gesture.reset;
|
||||
pub const selection_gesture_get = selection_gesture.get;
|
||||
pub const selection_gesture_get_multi = selection_gesture.get_multi;
|
||||
pub const terminal_grid_ref = terminal.grid_ref;
|
||||
pub const terminal_grid_ref_track = terminal.grid_ref_track;
|
||||
pub const terminal_point_from_grid_ref = terminal.point_from_grid_ref;
|
||||
@@ -214,6 +220,7 @@ test {
|
||||
_ = osc;
|
||||
_ = render;
|
||||
_ = selection;
|
||||
_ = selection_gesture;
|
||||
_ = key_event;
|
||||
_ = key_encode;
|
||||
_ = mouse_event;
|
||||
|
||||
272
src/terminal/c/selection_gesture.zig
Normal file
272
src/terminal/c/selection_gesture.zig
Normal file
@@ -0,0 +1,272 @@
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const lib = @import("../lib.zig");
|
||||
const CAllocator = lib.alloc.Allocator;
|
||||
const SelectionGesture = @import("../SelectionGesture.zig");
|
||||
const grid_ref = @import("grid_ref.zig");
|
||||
const terminal_c = @import("terminal.zig");
|
||||
const Result = @import("result.zig").Result;
|
||||
|
||||
const log = std.log.scoped(.selection_gesture_c);
|
||||
|
||||
/// C: GhosttySelectionGesture
|
||||
pub const Gesture = ?*GestureWrapper;
|
||||
|
||||
const GestureWrapper = struct {
|
||||
alloc: std.mem.Allocator,
|
||||
gesture: SelectionGesture = .init,
|
||||
};
|
||||
|
||||
/// C: GhosttySelectionGestureBehavior
|
||||
pub const Behavior = SelectionGesture.Behavior;
|
||||
|
||||
/// C: GhosttySelectionGestureAutoscroll
|
||||
pub const Autoscroll = SelectionGesture.Autoscroll;
|
||||
|
||||
/// C: GhosttySelectionGestureData
|
||||
pub const Data = enum(c_int) {
|
||||
click_count = 0,
|
||||
dragged = 1,
|
||||
autoscroll = 2,
|
||||
behavior = 3,
|
||||
anchor = 4,
|
||||
|
||||
pub fn OutType(comptime self: Data) type {
|
||||
return switch (self) {
|
||||
.click_count => u8,
|
||||
.dragged => bool,
|
||||
.autoscroll => Autoscroll,
|
||||
.behavior => Behavior,
|
||||
.anchor => grid_ref.CGridRef,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn new(
|
||||
alloc_: ?*const CAllocator,
|
||||
out_gesture: ?*Gesture,
|
||||
) callconv(lib.calling_conv) Result {
|
||||
const out = out_gesture orelse return .invalid_value;
|
||||
|
||||
const alloc = lib.alloc.default(alloc_);
|
||||
const gesture = alloc.create(GestureWrapper) catch {
|
||||
out.* = null;
|
||||
return .out_of_memory;
|
||||
};
|
||||
gesture.* = .{
|
||||
.alloc = alloc,
|
||||
};
|
||||
out.* = gesture;
|
||||
return .success;
|
||||
}
|
||||
|
||||
pub fn free(
|
||||
gesture_: Gesture,
|
||||
terminal: terminal_c.Terminal,
|
||||
) callconv(lib.calling_conv) void {
|
||||
const wrapper = gesture_ orelse return;
|
||||
if (terminal_c.zigTerminal(terminal)) |t| {
|
||||
wrapper.gesture.deinit(t);
|
||||
}
|
||||
const alloc = wrapper.alloc;
|
||||
alloc.destroy(wrapper);
|
||||
}
|
||||
|
||||
pub fn reset(
|
||||
gesture_: Gesture,
|
||||
terminal: terminal_c.Terminal,
|
||||
) callconv(lib.calling_conv) void {
|
||||
const wrapper = gesture_ orelse return;
|
||||
const t = terminal_c.zigTerminal(terminal) orelse return;
|
||||
wrapper.gesture.reset(t);
|
||||
}
|
||||
|
||||
pub fn get(
|
||||
gesture_: Gesture,
|
||||
terminal: terminal_c.Terminal,
|
||||
data: Data,
|
||||
out: ?*anyopaque,
|
||||
) callconv(lib.calling_conv) Result {
|
||||
if (comptime std.debug.runtime_safety) {
|
||||
_ = std.meta.intToEnum(Data, @intFromEnum(data)) catch {
|
||||
log.warn("selection_gesture_get invalid data value={d}", .{@intFromEnum(data)});
|
||||
return .invalid_value;
|
||||
};
|
||||
}
|
||||
|
||||
const out_ptr = out orelse return .invalid_value;
|
||||
return switch (data) {
|
||||
inline else => |comptime_data| getTyped(
|
||||
gesture_,
|
||||
terminal,
|
||||
comptime_data,
|
||||
@ptrCast(@alignCast(out_ptr)),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_multi(
|
||||
gesture_: Gesture,
|
||||
terminal: terminal_c.Terminal,
|
||||
count: usize,
|
||||
keys: ?[*]const Data,
|
||||
values: ?[*]?*anyopaque,
|
||||
out_written: ?*usize,
|
||||
) callconv(lib.calling_conv) Result {
|
||||
const k = keys orelse return .invalid_value;
|
||||
const v = values orelse return .invalid_value;
|
||||
|
||||
for (0..count) |i| {
|
||||
const result = get(gesture_, terminal, k[i], v[i]);
|
||||
if (result != .success) {
|
||||
if (out_written) |w| w.* = i;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (out_written) |w| w.* = count;
|
||||
return .success;
|
||||
}
|
||||
|
||||
fn getTyped(
|
||||
gesture_: Gesture,
|
||||
terminal: terminal_c.Terminal,
|
||||
comptime data: Data,
|
||||
out: *data.OutType(),
|
||||
) Result {
|
||||
const wrapper = gesture_ orelse return .invalid_value;
|
||||
const t = terminal_c.zigTerminal(terminal) orelse return .invalid_value;
|
||||
|
||||
switch (data) {
|
||||
.click_count => out.* = wrapper.gesture.left_click_count,
|
||||
.dragged => out.* = wrapper.gesture.left_click_dragged,
|
||||
.autoscroll => out.* = wrapper.gesture.left_drag_autoscroll,
|
||||
.behavior => out.* = wrapper.gesture.left_click_behavior,
|
||||
.anchor => {
|
||||
const pin = wrapper.gesture.validatedLeftClickPin(&t.screens) orelse
|
||||
return .no_value;
|
||||
out.* = .fromPin(pin.*);
|
||||
},
|
||||
}
|
||||
|
||||
return .success;
|
||||
}
|
||||
|
||||
test "selection gesture lifecycle and get" {
|
||||
var terminal: terminal_c.Terminal = null;
|
||||
try testing.expectEqual(Result.success, terminal_c.new(
|
||||
&lib.alloc.test_allocator,
|
||||
&terminal,
|
||||
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
|
||||
));
|
||||
defer terminal_c.free(terminal);
|
||||
|
||||
var gesture: Gesture = null;
|
||||
try testing.expectEqual(Result.success, new(
|
||||
&lib.alloc.test_allocator,
|
||||
&gesture,
|
||||
));
|
||||
defer free(gesture, terminal);
|
||||
|
||||
var click_count: u8 = 255;
|
||||
try testing.expectEqual(Result.success, get(gesture, terminal, .click_count, &click_count));
|
||||
try testing.expectEqual(@as(u8, 0), click_count);
|
||||
|
||||
var dragged = true;
|
||||
try testing.expectEqual(Result.success, get(gesture, terminal, .dragged, &dragged));
|
||||
try testing.expect(!dragged);
|
||||
|
||||
var autoscroll: Autoscroll = .up;
|
||||
try testing.expectEqual(Result.success, get(gesture, terminal, .autoscroll, &autoscroll));
|
||||
try testing.expectEqual(Autoscroll.none, autoscroll);
|
||||
|
||||
var behavior: Behavior = .word;
|
||||
try testing.expectEqual(Result.success, get(gesture, terminal, .behavior, &behavior));
|
||||
try testing.expectEqual(Behavior.cell, behavior);
|
||||
|
||||
var anchor: grid_ref.CGridRef = undefined;
|
||||
try testing.expectEqual(Result.no_value, get(gesture, terminal, .anchor, &anchor));
|
||||
}
|
||||
|
||||
test "selection gesture get_multi" {
|
||||
var terminal: terminal_c.Terminal = null;
|
||||
try testing.expectEqual(Result.success, terminal_c.new(
|
||||
&lib.alloc.test_allocator,
|
||||
&terminal,
|
||||
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
|
||||
));
|
||||
defer terminal_c.free(terminal);
|
||||
|
||||
var gesture: Gesture = null;
|
||||
try testing.expectEqual(Result.success, new(
|
||||
&lib.alloc.test_allocator,
|
||||
&gesture,
|
||||
));
|
||||
defer free(gesture, terminal);
|
||||
|
||||
const keys = [_]Data{ .click_count, .dragged, .autoscroll, .behavior };
|
||||
var click_count: u8 = 255;
|
||||
var dragged = true;
|
||||
var autoscroll: Autoscroll = .up;
|
||||
var behavior: Behavior = .word;
|
||||
var values = [_]?*anyopaque{
|
||||
&click_count,
|
||||
&dragged,
|
||||
&autoscroll,
|
||||
&behavior,
|
||||
};
|
||||
var written: usize = 0;
|
||||
|
||||
try testing.expectEqual(Result.success, get_multi(
|
||||
gesture,
|
||||
terminal,
|
||||
keys.len,
|
||||
&keys,
|
||||
&values,
|
||||
&written,
|
||||
));
|
||||
try testing.expectEqual(keys.len, written);
|
||||
try testing.expectEqual(@as(u8, 0), click_count);
|
||||
try testing.expect(!dragged);
|
||||
try testing.expectEqual(Autoscroll.none, autoscroll);
|
||||
try testing.expectEqual(Behavior.cell, behavior);
|
||||
}
|
||||
|
||||
test "selection gesture get_multi returns first failing index" {
|
||||
var terminal: terminal_c.Terminal = null;
|
||||
try testing.expectEqual(Result.success, terminal_c.new(
|
||||
&lib.alloc.test_allocator,
|
||||
&terminal,
|
||||
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
|
||||
));
|
||||
defer terminal_c.free(terminal);
|
||||
|
||||
var gesture: Gesture = null;
|
||||
try testing.expectEqual(Result.success, new(
|
||||
&lib.alloc.test_allocator,
|
||||
&gesture,
|
||||
));
|
||||
defer free(gesture, terminal);
|
||||
|
||||
const keys = [_]Data{ .click_count, .anchor, .dragged };
|
||||
var click_count: u8 = 255;
|
||||
var anchor: grid_ref.CGridRef = undefined;
|
||||
var dragged = true;
|
||||
var values = [_]?*anyopaque{ &click_count, &anchor, &dragged };
|
||||
var written: usize = 0;
|
||||
|
||||
try testing.expectEqual(Result.no_value, get_multi(
|
||||
gesture,
|
||||
terminal,
|
||||
keys.len,
|
||||
&keys,
|
||||
&values,
|
||||
&written,
|
||||
));
|
||||
try testing.expectEqual(@as(usize, 1), written);
|
||||
try testing.expectEqual(@as(u8, 0), click_count);
|
||||
try testing.expect(dragged);
|
||||
}
|
||||
|
||||
test "selection gesture free null" {
|
||||
free(null, null);
|
||||
}
|
||||
Reference in New Issue
Block a user