26646 Commits
Author SHA1 Message Date
Mike-Solar 79b3a8fbd4 feat(widgets): CurveEditor::is_dragging for host re-sync suppression 2026-08-21 04:42:30 +08:00
Mike-Solar 4067918c67 feat(macos): tag the Metal layer with the display colorspace on demand
When the app self-manages the display transform (OAK_MACOS_LAYER_
COLORSPACE=display set at startup), the CAMetalLayer is tagged with the
main display's colorspace so ColorSync passes the already-transformed
pixels through — without the tag the OS would re-correct them (double
correction). The CoreGraphics FFI lives in its own module because the
build script forwards metal_renderer.rs FFI declarations into the
Metal shader header.
2026-08-21 02:17:16 +08:00
Mike-Solar 3325521a85 feat(effect_stack,timeline,node_graph): library drag-drop, params view caching, clip click select
- effect_stack: the params view is cached per effect (recreation per
  render killed in-progress slider drags and clicks); new
  LibraryEffectDrag payload + AddTypeRequested event let an effect
  dragged from the app's effect library drop onto the stack at the
  indicator position
- timeline: left-press selects clips (plain press selects an
  unselected clip, keeps multi-selection on a selected one for group
  drags, Ctrl/Cmd toggles membership)
- node_graph: graph_position_at() converts a window-space point (drop
  position) to graph space
2026-08-20 23:45:22 +08:00
Mike-Solar 8a0b7569a3 fix(widgets): menu hover occlusion and popup placement, clip selection shading
- Menu popups (menu bar, context menus, submenus) now occlude hover
  beneath them via a BlockMouse hitbox, so items under an open popup no
  longer stay highlighted.
- Menu bar dropdowns anchor to the opened title's bottom-left (local
  anchoring) instead of the raw pointer position plus a fixed offset;
  submenus are absolute children of the popup with separator-aware row
  alignment.
- Selected timeline clips render one luma notch darker so the
  selection is visible against the green clip body.
2026-08-20 18:56:01 +08:00
Mike-Solar dea33c713f style: professional dark theme refresh aligned with the design spec
- oak theme palette to a denser professional dark (near-black base,
  container/window surfaces, subtler secondary text).
- Dock tabs: selected tab solid accent with white text, hairline
  separators between panels.
- Timeline: green clip blocks, blue playhead, neutral track headers,
  brighter ruler labels, deep-green waveforms.
- Viewer: green timecode readout, solid-accent play button, chip-style
  fit/safe-margin buttons.
- Effect stack cards and node cards get rounded borders; spinbox
  values in amber per the design.
2026-08-20 17:43:44 +08:00
Mike-Solar 3870d6da06 feat(node_graph,effect_stack): programmatic selection and card selection events
NodeGraphView::set_selection selects nodes programmatically (emitting
SelectionChanged); EffectStackDataSource::selected_effect highlights
the chosen card and EffectStackEvent::CardSelected reports card clicks
— the two-way clip/node selection sync between the timeline, node
editor and inspector.
2026-08-20 17:08:25 +08:00
Mike-Solar f7a00fdd91 feat(dock,timeline): visible tab close buttons, tear-off windows, clip drag ghost, explorer thumbnails
- Tab close buttons are now visible and right-aligned with a hover
  background (they were nearly invisible, causing accidental panel
  closes).
- Tear-off: dragging a tab outside the dock opens the panel in its own
  floating window; closing the window re-docks the panel to its last
  group (or closes it outright from the Window menu).
- Timeline clip dragging shows a translucent ghost at the target track
  and frame, including cross-track moves.
- Project explorer icon view renders real thumbnail images when the
  engine provides them, with debug selectors and a structural test.
2026-08-20 16:20:49 +08:00
Mike-Solar 0b3e30c095 feat(widgets): viewer interact pointer/key events for OFX interacts
ViewerEvent gains InteractPointer/InteractKey variants and the picture
area captures pointer and key input for them (the OFX Interact overlay
integration forwards these to the plugin).
2026-08-20 15:11:29 +08:00
Mike-Solar c4c1d34bd7 fix(widgets): context-menu hover tracking, submenus, and snap-proof placement
The right-click ContextMenu never tracked hover (the listener was a
no-op), so rows did not highlight and parent items never opened their
submenus. Hover now drives the highlight and opens the parent's
submenu, with Left/Right and Enter keyboard parity.

The submenu is an absolutely positioned child of the popup instead of
a second window-anchored popup computed from the raw click point, so
it follows the popup's final snapped/switched bounds and can never
detach from its parent row.
2026-08-19 17:41:40 +08:00
Mike-Solar e521a8af83 fix(widgets): open context-menu submenus on hover
The right-click ContextMenu's hover listener was a no-op: it never
tracked the hovered row and never rendered a submenu popup, so every
menu item with a submenu (Proxy, Cache, Color, Show Thumbnails, Zoom,
Playback Resolution...) was a dead end. Hover now drives the row
highlight and opens the parent's submenu anchored to its right (the
menu bar's model), with keyboard Left/Right to close/open it and Enter
expanding a parent row instead of firing it.
2026-08-19 15:21:54 +08:00
Mike-Solar a761d96c82 perf(wgpu_atlas): upload identity-format textures from the caller's slice
BGRA atlas uploads (every viewer video frame on macOS) were staged
through swizzle_upload_data's to_vec() into pending_uploads — a
full-frame CPU copy per upload. Non-swizzled formats now write_texture
directly from the borrowed bytes; only the RGBA swizzle and the
not-yet-allocated fallback keep the owned staging path.
2026-08-19 01:19:52 +08:00
Mike-Solar 050d5ba22d feat(widgets): right-click context-menu events for timeline, node graph, explorer
TimelineView emits ContextMenuRequested with hit target (clip/empty/
track head/ruler marker), NodeGraphView emits it for nodes and the
background, and ProjectExplorer emits it for entries and blank areas,
so the app can open context menus aligned with the C++ version.
2026-08-18 17:14:37 +08:00
Mike-Solar 6f75d3c92a fix(dock): split divider drag resizes smoothly instead of jumping
The handle mixed the hitbox-local drag origin with window-space
drag-move positions, so the first move snapped the ratio to a clamp
boundary (a panel suddenly grew and further drags did nothing). Drags
are now incremental window-space deltas applied to the freshly-read
ratio; drag-move routing is filtered to the owning split container so
nested splits no longer double-apply with wrong geometry; pair extent
excludes the divider itself so the boundary tracks the pointer 1:1.
2026-08-18 12:41:12 +08:00
Mike-Solar 447353ebbd fix(gpui): node cards scale with zoom; explorer icon grid shows thumbnails
- node_graph: card geometry stays graph-space; paint/hit-test/wire
  endpoints scale by zoom so nodes no longer overlap at zoom != 1
- project_explorer: icon grid aligns items to start (no full-height
  selection stretch), loads thumbnails from filesystem paths and
  observes the data source for late arrivals
2026-08-18 12:41:04 +08:00
Mike-Solar 27c6c393c3 feat(gpui): track-header toggle targets + explorer icon buttons 2026-08-17 01:37:31 +08:00
Mike-Solar 819029e876 fix(dock): panel drag reorders the layout
The strip handed the drag to the dock area via cx.emit, which is
deferred — the dock's drag state was created a dispatch too late, so
the hovered target was never recorded and drops were no-ops. The dock
area now lazily begins the drag in its own capture-phase handler;
drops onto the root edge from the panel's own group split the tree
instead of being swallowed as self-drops.
2026-08-16 19:46:05 +08:00
Mike-Solar c1fc52c654 feat: explorer icons show root-level footage; footage drag source; timeline layout constants public 2026-08-16 19:07:33 +08:00
Mike-Solar 6162b2fc50 feat(gpui): ruler markers + work-area drag reshape 2026-08-16 16:06:19 +08:00
Mike-Solar df726fd3e3 fix(gpui_widgets): file drops onto the project explorer fire (bare ExternalPaths type) 2026-08-16 15:05:17 +08:00
Mike-Solar fc0420ddd8 feat(gpui): content-width dock tabs, rounded timeline clips 2026-08-13 23:37:57 +08:00
Mike-Solar 888c39bf27 feat(gpui_widgets): menu scrubbing, content-width popups, density pass
- MenuBar: hover another title with a menu open to switch (scrubbing)
- menu popup width computed from the longest label; ROW_HEIGHT 22
- dock tab bar 26px / smaller tab text; viewer transport tightened
2026-08-13 18:16:10 +08:00
Mike-Solar af5482d774 style: cargo fmt with the workspace tab policy (hard_tabs)
Whitespace only; the fork has no own rustfmt.toml so the Oak root
policy applies.
2026-08-11 23:06:13 +08:00
Mike-Solar 507d7e6e8d fix(gpui_widgets): submenu hover opens nested popup; add icons + tooltip helpers
- MenuBar: mouse hover now sets the hovered row and opens submenus next
  to the hovered item (previously hover state was never set from the
  mouse, so '>' rows never opened their submenu)
- Menu popup: debug selectors for test automation
- viewer: transport bar renders 16px icon buttons with localized
  tooltips via a host-registered icon resolver (glyph fallback kept)
- new icons.rs (theme-aware icon resolver) and tooltip.rs helpers
2026-08-11 00:23:59 +08:00
Mike-Solar 49e471ae64 feat(gpui, gpui_widgets): i18n string-table hook + node-graph fit API
- gpui::i18n: minimal string-table override (set_table/tr/clear_table) with
  built-in defaults; effect-stack and viewer strings now go through it so
  hosts can localize widget-baked labels without a full i18n framework.
- gpui_widgets::i18n re-exports the hook (gpui_widgets::i18n::set_table).
- node_graph: GraphViewState::fit_to_rect for fit-window/initial viewports
  (unit tested); NodeGraphView::viewport_size accessor for fit targets.
2026-08-10 16:52:39 +08:00
Mike-Solar 16ae7c42df gpui_widgets defect fixes: menu checkmarks, dock ratios, meter orientation, CPU frames, drop-frame timecode
- menu: add runtime set-checked path (MenuItem::set_checked/clear_checked,
  Menu::set_item_checked recursive, MenuBar::set_item_checked)
- dock: Split now stores per-child ratios (sum 1.0) so 3+ panels on one
  axis keep distinct sizes; resize_split_child adjusts a single boundary,
  resize_split keeps its two-arg whole-share semantics; one handle per
  boundary; DockLayoutState VERSION bumped to 2 for the new ratios field
- audio_meter: MeterOrientation::Vertical for the 26px transport strip,
  segments lit bottom to top
- viewer: ViewerFrameSource::CpuFrame + set_cpu_frame (BGRA8 RenderImage
  via the sprite atlas) for platforms without CVPixelBuffer
- timeline: TimeDisplay::TimecodeDropFrame (SMPTE drop-frame for NTSC
  rates, non-drop fallback otherwise)
- gpui_widgets: regression test pinning the fractional spacing helpers
  (py_0p5/py_1p5/py_2p5/py_3p5 already exist; no _0_5 aliases added)
2026-08-10 05:45:53 +08:00
Mike-Solar a64234936c test(gpui_widgets): add interaction tests for view code, raising coverage to 89.4%
Adds interaction/render tests for the untested view layers: menu bar popup
open/click/keyboard-nav/escape, project explorer expand/open/view-switch,
scope widgets and keyable diamond rendering in windows, progress and file
dialog content rendering, and viewer transport buttons. gpui_widgets line
coverage rises from 75.4% to 89.4% (menu/mod 3.7%->71.9%, project_explorer
21.4%->91.3%, scopes/mod 0%->96.7%, keyable 69%->98.4%); every module is now
>=70%. 115 widget tests pass.
2026-08-09 07:37:57 +08:00
Mike-Solar 816d6db93e fix(gpui_macos): silence const-in-pattern warnings in surface format check
Compare the pixel format with == instead of match patterns to avoid
non_upper_case_globals warnings from the CoreVideo constants.
2026-08-09 06:33:31 +08:00
Mike-Solar 098d422628 feat(gpui_widgets): add olive theme system with runtime switching
W7 of the oak task list. OakTheme::olive_dark/olive_light translate oak's
palette.ini files into a structured theme (window/base/alternate/accent/
link/disabled plus a derived border). apply_theme swaps gpui's GlobalColors
so every widget reading cx.default_colors() re-themes immediately, and
stores the full theme in a ThemeGlobal. Palette contrast and mapping are
unit-tested, with a gpui::test verifying the runtime switch;
examples/themes.rs toggles between the two themes live. 101 widget tests
pass.
2026-08-09 06:31:44 +08:00
Mike-Solar bdb1684de7 feat(gpui_widgets): add scope widgets and audio level meter
W6 of the oak task list. scopes::math is a pure, unit-tested core
(histogram binning, waveform min/max envelopes, vectorscope chroma
projection, meter segment math, peak-hold decay) feeding three canvas
widgets - Histogram, Waveform, Vectorscope - generic over LumaDataSource /
ChromaDataSource traits the host implements over its frame buffers, plus an
AudioLevelMeter over AudioMeterDataSource with lit segments and a peak
marker. examples/scopes.rs drives all four from mock signals. 96 widget
tests pass.
2026-08-09 06:29:06 +08:00
Mike-Solar 63dbc64a32 feat(gpui_widgets): add project explorer (material bin) with tree/icon views
W5 companion widget. ProjectExplorer is data-agnostic over a
ProjectDataSource trait: a tree view with expandable folders and
double-click-to-open, an icon grid with thumbnails (img/placeholder
swatch), a view switcher, and file-drop import via on_drop (platform
FileDrop becomes an internal drag), emitting OpenRequested /
FileDropRequested / ViewChanged requests. flatten_tree (pure) is
unit-tested; examples/project_explorer.rs demos a mock project. 89 widget
tests pass.
2026-08-09 06:25:38 +08:00
Mike-Solar 47c6126d0c feat(gpui): add track selection and transition-resize gestures to timeline
W5 timeline supplements: clicking a track header toggles the track in a
selected_tracks set and emits TimelineEvent::TrackSelected; clips with in/out
transitions get a resize handle at the wedge edge that emits
TimelineEvent::TransitionChanged with the clamped new length (delta-scaled
by zoom). Both follow the request-only contract. 182 gpui tests pass.
2026-08-09 06:22:15 +08:00
Mike-Solar d97e3abd20 feat(gpui): support BGRA surfaces on macOS; add W4 viewer widget
Two changes landing W4 of the oak task list:

gpui_macos: the Surface renderer only accepted biplanar YUV 4:2:0 pixel
buffers, so engine BGRA frames could not be displayed. SurfaceBounds gains an
is_bgra flag and draw_surfaces now creates a single BGRA8Unorm texture (and
the fragment shader swizzles it to RGBA) for 32BGRA buffers, keeping the
YUV path unchanged. Verified by running the W3 surface_bridge demo.

gpui_widgets::viewer: ViewerWidget with a pure TransportState machine
(advance/loop/step/in-out, unit-tested), a PlaybackClock trait the host
implements over the engine, a ~60Hz polling ticker, a transport bar emitting
ViewerEvent requests, timecode via gpui::timeline::time, and safe-frame/zoom
toggles. examples/viewer.rs shows a mock clock with generated macOS test
frames. 87 widget + 182 gpui tests pass.
2026-08-09 06:05:54 +08:00
Mike-Solar 66b05b0ebe feat(oak_bridge): macOS wgpu Metal texture to IOSurface CVPixelBuffer bridge
W3 of the oak task list. SurfaceBridge wraps an engine wgpu (Metal) texture
into an IOSurface-backed CVPixelBuffer for gpui's Surface element: a reused
pixel buffer created with kCVPixelBufferIOSurfacePropertiesKey +
MetalCompatibility, aliased to a Metal texture via gpui_media's
CVMetalTextureCache, with a GPU-to-GPU MTLBlitCommandEncoder copy (a
device.poll(Wait) before the blit keeps the v1 path correct and
synchronous). A CPU readback fallback (stage_readback/finish_readback)
works on any backend. The surface_bridge demo (demo feature) streams a
moving test pattern through the bridge into a window and prints FPS;
smoke-verified on macOS at 1280x720. Windows/Linux paths are left for a
follow-up (noted in docs/zh). 2 tests pass.
2026-08-09 05:54:58 +08:00
Mike-Solar d72d2e8210 feat(gpui_widgets): add menu bar, context menu and modal dialog framework
W2 of the oak task list. A pure menu model (nesting, disabled items,
separators, checked state, wrap-around keyboard navigation arithmetic) feeds
two views: a MenuBar with drop-down popups and a right-click ContextMenu,
both built on anchored+deferred with keyboard navigation (up/down/enter/
escape), hover-opened submenus, check marks, shortcut labels and request
events. The Modal framework provides the mask, title bar, content slot and
button row with escape/enter defaults; message_box (info/warning/error),
progress_dialog (driven by ProgressContent) and file_dialog (native gpui
fallback - the fork has no prompt_for_paths platform API) are built on it.
A menus_dialogs example demonstrates everything. 79 tests pass.
2026-08-09 05:33:29 +08:00
Mike-Solar 4a92ab13d8 feat(gpui_widgets): add controls demo example and mark W1 complete
Adds a parameter-panel example (cargo run -p gpui_widgets --example controls)
that demonstrates every form control: float/rational/angle sliders with
keying diamonds, a spinbox, a combo box, checkboxes, a radio group, a color
picker and a curve editor, printing each edit as a request event. Marks all
W1 checklist items done in docs/zh/oak-app-rewrite.md. 65 tests pass.
2026-08-09 05:24:10 +08:00
Mike-Solar b2ed7a66e4 feat(gpui_widgets): add curve editor with bezier handle dragging
CurveEditor edits a normalized x->y keyframe curve: cubic bezier segments
with per-point in/out control handles. Points are dragged with x clamped to
keep the list sorted; handles drag as offsets; double-click inserts a new
point at the cursor. Every gesture emits CurveEditorEvent requests while the
widget keeps a local working copy for fluid dragging. Pure geometry
(bezier evaluation, sampling via binary search, polyline approximation, hit
tests) is unit-tested; interaction tests cover point dragging and adding.
65 tests pass.
2026-08-09 05:22:30 +08:00
Mike-Solar 25b3167162 feat(gpui_widgets): add color swatch + HSV color picker popup
ColorPicker is a swatch button that opens a popup picker built from
anchored+deferred: an SV square (layered linear gradients over the hue) and
a 48-segment hue strip, both click- and drag-editable, plus RGBA spinboxes
reusing the SpinBox control. Pure HsvColor math (hue wrapping, saturation/
value extremes, u8 conversion) is unit-tested; an interaction test verifies
clicking the SV square emits ColorChanged. The eyedropper is a placeholder.
55 tests pass.
2026-08-09 05:11:32 +08:00
Mike-Solar 23b1f610a2 feat(gpui_widgets): add combo box with anchored+deferred popup menu
ComboBox renders a field showing the selection and a drop-down menu built
entirely with gpui's anchored + deferred elements (no platform primitives).
Menu dismissal is mouse-up-out based so an option click is never swallowed
by a capture-phase close that would redraw the menu away; the field toggles
from the open state recorded at mouse-down. Arrow keys cycle the selection
with wrap-around, escape closes. 48 tests pass.
2026-08-09 05:02:04 +08:00
Mike-Solar b65ccf1417 feat(gpui_widgets): add spinbox, checkbox and radio group controls
Completes the basic form controls of W1: a SpinBox reusing SliderModel for
range/step/clamping with an editable_text field (enter/blur commits,
escape reverts, invalid input rejected) and up/down buttons; a CheckBox with
optional tri-state and request-only Toggled events; a RadioGroup that emits
Selected requests. All three follow the request-only contract: the host
applies changes and updates the widget's display state. 45 tests pass.
2026-08-09 04:54:31 +08:00
Mike-Solar 6e0b541660 feat(gpui_widgets): add slider family with drag/double-click/wheel/reset gestures
Implements W1's slider: a pure SliderModel state machine (float, integer,
rational and angle kinds with clamping, step snapping, fine adjustment and
drag math) plus the Slider view with vertical-drag scrubbing (shift for
fine), double-click direct entry backed by editable_text (enter commits,
escape cancels, click-away commits, invalid text rejected), wheel stepping,
middle-click reset and arrow-key navigation. Every edit is emitted as a
SliderEvent request; keyable controls expose a Keying diamond. 37 unit and
interaction tests pass.
2026-08-09 04:48:57 +08:00
Mike-Solar df7c3d274f feat(gpui_widgets): scaffold form-controls crate with value core and keying diamond
New workspace crate implementing W1 of the oak task list. This first
slice lands the pure numeric core (ValueKind / SliderValue /
RationalValue / ValueFormatter with round-trip tests) and the keying
diamond button (KeyingState / KeyingRequest) that keyable controls
embed. 12 unit tests pass.
2026-08-09 04:20:48 +08:00
Mike-Solar ad7c965c5a feat(gpui): add dock, effect stack, node graph, and timeline widgets
Implements four workspace widget modules with accompanying learn examples:

- dock: dockable panel layout system (tabs, splits, drag-to-dock) with
  serde-based persistence via PanelRegistry / DockLayoutState
- effect_stack: linear effect-stack inspector widget
- node_graph: node-graph editor (nodes, ports, wires, pan/zoom canvas)
- timeline: video-editing timeline (tracks, clips, ruler, playhead)

Timeline snapping prefers the earlier frame when two snap points are
equally close, with SnapKind priority breaking same-frame ties.
2026-08-09 03:31:06 +08:00
Max Carter 祁明思 6043651563 Add letter spacing and text transforms to GPUI (#111)
* Add text spacing and transform style plumbing

* Apply byte-stable transforms and spacing-aware truncation

* Add platform letter spacing support

* Fix scheduler clippy warning

* Refresh dependency lockfile

* Fix CI for text spacing changes

* Add text transform preview example
2026-08-07 21:48:02 -07:00
Brendon Felix 568271c01c feat(macos): support haptic feedback (#71)
* Support haptic feedback on macOS

* add tests for haptic feedback
2026-08-04 14:52:28 -07:00
443eb9#C c1faa21ced Fixed gpui_windows not compiling with wgpu feature (#90) 2026-07-27 23:17:27 -07:00
Dustin Yost 2542e1154a add App::emit such that events can be emitted without acquiring a Context (#94) 2026-07-27 23:16:59 -07:00
Dustin Yost 1fe82dbcd7 implement start_window_move on win32 platform (#102) 2026-07-27 23:05:44 -07:00
Miles Wirht 6c799b8e99 removed all of the git sources (#91) 2026-07-13 21:25:00 -04:00
temportalflux 309d319880 remove legacy input example now that gpui_elements::editable_text exists 2026-07-12 17:44:06 -04:00
temportalflux cb26ad76dc remove stop_propagation on_mouse_up to avoid unintended consequence of input always highlighting/selecting while mousing over 2026-07-11 13:16:17 -04:00