summaryrefslogtreecommitdiff
path: root/src/macos/pardes.h
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-11 15:58:58 -0300
committerGabriel Schneider <[email protected]>2026-08-11 16:26:20 -0300
commit4ca28745d774c232cd31a29c17878f19bbe24cf5 (patch)
treeface852acae5bc347e6bab2bb5cede501e0ce1d3 /src/macos/pardes.h
parentdedfdea43f0d6c7151c541284c81027969d89032 (diff)
parent89d93d5e7348304bc7d8a148f9ad9c1beb200459 (diff)
downloadpardes-4ca28745d774c232cd31a29c17878f19bbe24cf5.tar.gz
pardes-4ca28745d774c232cd31a29c17878f19bbe24cf5.zip
merge the macOS app branch: the AppKit shell, pixel attachments, live theming, and mupdf -Djpx
Three commits off 38e9919 (macos-app@upstream) merged into main's ghostty bump. No textual conflicts, and two things the merge needed: - nested.zig asked libc for fstatat. Darwin has it; on linux std.c declares it `void` (glibc hides it behind a versioned symbol std cannot name), so the tty build stopped at 'type void not a function'. statNoFollow keeps fstatat on darwin and asks statx on linux for the same three fields, which is what this file did before the branch generalized it to both platforms. - .DS_Store rode along with a797a1a. Deleted, and .gitignore now says so. linux: snap 86/86, unit-test, image-harness and mupdf-check green. nested.zig also type-checks for aarch64-macos.
Diffstat (limited to 'src/macos/pardes.h')
-rw-r--r--src/macos/pardes.h146
1 files changed, 136 insertions, 10 deletions
diff --git a/src/macos/pardes.h b/src/macos/pardes.h
index e0d6fa32..1591130e 100644
--- a/src/macos/pardes.h
+++ b/src/macos/pardes.h
@@ -118,6 +118,15 @@ typedef enum {
PARDES_MOUSE_DRAG = 3,
} pardes_mouse_kind_e;
+// What the core just did, for a shell that can answer with something the hand
+// feels. Taken with pardes_take_haptic once per pump; the two acme verbs are
+// distinguished because they deserve distinct taps.
+typedef enum {
+ PARDES_HAPTIC_NONE = 0,
+ PARDES_HAPTIC_EXEC = 1,
+ PARDES_HAPTIC_LOOK = 2,
+} pardes_haptic_e;
+
// ---------------------------------------------------------------- runtime
// What the host lends the core. Two callbacks, because everything else the
@@ -149,8 +158,14 @@ int pardes_init(const pardes_runtime_s *runtime, uint16_t cols, uint16_t rows);
void pardes_deinit(void);
// Drain pty output into the core and perform the effects it queued. Call after
-// every input function and on every wakeup. Returns true if anything changed
-// and the host should mark its view dirty.
+// every input function and on every wakeup.
+//
+// The return value is whether this tick did any IO — bytes arrived from a pty,
+// or an effect was performed. It is NOT a repaint signal, and a host that uses
+// it as one shows a stale screen: moving the cursor, extending a selection,
+// changing mode and scrolling all mutate the grid while queueing nothing and
+// performing nothing, so they tick false. Mark the view dirty after any call
+// into the core and use this only to decide whether there was work.
bool pardes_tick(void);
// The core asked to exit (the Exit builtin, or the last pane closing).
@@ -159,6 +174,16 @@ bool pardes_should_quit(void);
// A theme transition is mid-flight and wants ~60 Hz ticks until it settles.
bool pardes_animating(void);
+// What to paint where the grid does not: the window background behind the
+// titlebar and behind a live resize the view has not caught up with. The
+// theme's own background, so it changes the instant the theme does — chrome
+// (taglines, the move box) fades instead, which is why this is not it.
+//
+// PARDES_COLOR_DEFAULT means the theme declares NO background of its own. A
+// terminal wears whatever it was already wearing; a window has nothing to
+// wear, so the host should go transparent and show its own backdrop.
+uint32_t pardes_theme_bg(void);
+
// ---------------------------------------------------------------- events in
// `cp` is a codepoint or one of PARDES_KEY_*; `text`/`len` are the host's
@@ -169,14 +194,41 @@ void pardes_paste(const char *text, size_t len);
void pardes_mouse(pardes_mouse_button_e button, pardes_mouse_kind_e kind,
uint16_t col, uint16_t row, uint32_t mods);
-// Trackpad/precision wheel distance in rows, sign following the grid (positive
-// scrolls down). The core has no fractional scroll — it moves a row at a time —
-// so libpardes accumulates here and emits whole-row wheel presses, keeping the
-// remainder. Both other shells do this same accumulation host-side (stepScroll
-// in gui.zig, the drain loop in web/app.mjs); it lives in Zig here so the Swift
-// side stays a translator. A discrete wheel notch should go through
-// pardes_mouse instead.
-void pardes_scroll(float delta_rows, uint16_t col, uint16_t row);
+// Trackpad/precision wheel distance in CELLS, sign following the grid
+// (positive scrolls down and right). The core has no fractional scroll — it
+// moves a row or a column at a time — so libpardes accumulates here and emits
+// whole wheel presses, keeping the remainder. Both other shells do this same
+// accumulation host-side (stepScroll in gui.zig, the drain loop in
+// web/app.mjs); it lives in Zig here so the Swift side stays a translator, and
+// so the quantizer is unit-tested on a machine with no trackpad. A discrete
+// wheel notch should go through pardes_mouse instead.
+void pardes_scroll(float delta_rows, float delta_cols, uint16_t col,
+ uint16_t row);
+
+// A two-finger trackpad rotation, in degrees since the last call, positive
+// counterclockwise (AppKit's sign, unchanged). The core has no rotation: this
+// is spent as the search-step keys, clockwise `n` and counterclockwise `N`, a
+// notch at a time with the remainder kept — the same accumulate-and-spend
+// shape as pardes_scroll, and in Zig for the same reason. Feed it the raw
+// per-event delta; pass 0 at gesture start to drop a stale remainder and to
+// stop a fling still coasting.
+void pardes_rotate(float degrees);
+
+// The fingers lifted. How fast they were moving decides everything: a slow
+// twist stops exactly where it was put, a flick keeps turning in proportion to
+// how hard it was thrown, and the two are the same curve — momentum ramps up
+// from zero rather than switching on at a threshold.
+//
+// A coast makes pardes_animating true and is spent by pardes_tick, so a host
+// that already re-pumps for theme transitions needs no new machinery; one that
+// never calls this simply has a dial with no momentum.
+void pardes_rotate_end(void);
+
+// Run one builtin command line, exactly as executing the same text in a tag
+// would. This is the core's own `command` event, which is how a nested pardes
+// talks to its host; here it is what a menu item is made of, and what opens
+// the file named on argv or dropped on the Dock icon (`Look <path>`).
+void pardes_command(const char *text, size_t len);
// `cell_w`/`cell_h` are one cell in physical pixels, which only the native PDF
// placement path reads. Pass the backing-store size, not points.
@@ -192,11 +244,85 @@ const pardes_cell_s *pardes_frame_cells(void);
uint16_t pardes_frame_cols(void);
uint16_t pardes_frame_rows(void);
+// One rasterized pixel attachment: a PDF page, or an image pane's pixels.
+//
+// Geometry is in PHYSICAL PIXELS, the space pardes_resize's cell_w/cell_h put
+// the core in. `cell_x`/`cell_y` are the pane body's origin in CELLS and the
+// only thing to multiply out; `dst_*` is relative to that origin and `src_*`
+// is the crop of the raster to take. Both are already clipped to the viewport,
+// so a continuous-scroll page needs no overflow clip of its own — but the body
+// (`cell_w` x `cell_h` cells) is still the rectangle nothing may paint past.
+//
+// `serial`, `page` and `revision` together are the cache key: a host holds its
+// decoded texture while all three hold still, and panning, fit and scrolling
+// deliberately do not move them.
+typedef struct {
+ uint32_t serial;
+ uint32_t page;
+ uint32_t revision;
+ uint16_t cell_x;
+ uint16_t cell_y;
+ uint16_t cell_w;
+ uint16_t cell_h;
+ uint32_t dst_x;
+ uint32_t dst_y;
+ uint32_t dst_w;
+ uint32_t dst_h;
+ uint32_t src_x;
+ uint32_t src_y;
+ uint32_t src_w;
+ uint32_t src_h;
+ // subpixel vertical displacement a proportional wheel kept
+ float offset_y;
+ uint32_t iw;
+ uint32_t ih;
+ // iw * ih * 4 bytes, RGBA8, borrowed until the next pardes_frame
+ const uint8_t *rgba;
+} pardes_image_s;
+
+// This frame's attachments, in paint order. Ask after pardes_frame; both are
+// valid until the next one, exactly like the cell buffer.
+uint32_t pardes_frame_images(void);
+const pardes_image_s *pardes_frame_image_list(void);
+
+// The file behind the FOCUSED pane, or NULL when there is none: a terminal, an
+// output buffer, or nothing focused. PDFs and images count — they are real
+// paths, and a titlebar proxy icon is about the file, not about who may edit
+// it. Borrowed until the next call, like pardes_font_take.
+const char *pardes_active_path(void);
+
+// ...and whether that pane holds edits which are not on disk. Always false for
+// anything with no buffer to save, PDFs and images included.
+bool pardes_active_dirty(void);
+
// -1 when the cursor is hidden. `bar` asks for a thin insert-mode caret.
int32_t pardes_cursor_x(void);
int32_t pardes_cursor_y(void);
bool pardes_cursor_bar(void);
+// The Look or Exec the core performed since this was last asked, and clears
+// it. Call it once per pump, after pardes_tick — the input functions run the
+// dispatch synchronously, so a gesture's pulse is already waiting by the time
+// its tick returns. PARDES_HAPTIC_NONE means nothing to feel.
+pardes_haptic_e pardes_take_haptic(void);
+
+// The font file the `Font` builtin asked for since this was last called, and
+// clears it; NULL when nothing was asked. Ask once per pump, beside the haptic
+// above. The string is a NUL-terminated absolute path owned by libpardes and
+// valid until the next call.
+//
+// A path rather than a family name: the core found the file by walking the
+// font directories itself, so both shells agree on which faces exist and
+// neither has to ask its platform to resolve a name it might resolve
+// differently. A `.ttc` collection names its first face, which is the cut the
+// file is named after.
+//
+// The host loads it, re-measures its cell, and reports the new grid through
+// pardes_resize. A file the host cannot load is one to ignore: keep wearing
+// the face that works, because a terminal that cannot draw has no way back
+// out of it.
+const char *pardes_font_take(void);
+
#ifdef __cplusplus
}
#endif