Each ClideCodeBlock and EditorView created its own TreeSitterService,
each allocating a WASM engine, store, parser, and cursor via FFI.
When widgets were disposed, multiple instances freeing the same
underlying native resources caused double-free corruption on startup.
Single shared instance for the app lifetime. Also fixes overlapping
tree-sitter spans that caused duplicated text in code blocks — spans
are now clipped to avoid re-emitting already-rendered characters.
Co-Authored-By: Claude <noreply@anthropic.com>
Ctrl+Plus/Minus/0 text zoom (5% steps, 60%–200%) via MediaQuery
textScaler. App-wide clideLineHeight (1.25) applied in DefaultTextStyle.
Context panel drag resize was inverted — dragging left shrank the
panel instead of growing it. Negate delta for right-anchored slots.
Default sidebar widened from 240px to 400px, context panel from 280px
to 420px (both at their previous maximums).
Co-Authored-By: Claude <noreply@anthropic.com>
Icons now declared on TabContribution via the icon field — the
hardcoded switch in _BottomRail is a fallback only. All sidebar
and context extensions set their Phosphor icon explicitly.
PanelRegistry supports setTabOrder(slot, List<String>) — tabs
render in the order specified by project.layout.sidebar.order /
context.order in settings.yaml. Falls back to registration order.
Priority field removed from all contributions.
Context tabs are static again — persist with their last content,
selection just loads new data and switches focus. No spawn/despawn.
Tickets sidebar priority set to -200 (leftmost, default open).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DaemonBus (was EventBus): typed events for system/IPC layer.
MessageBus: channel-based pub/sub for UI/extension coordination.
Messages carry publisher (auto-stamped from extension ID),
channel (required), timestamp, and payload. Subscribe by
publisher, channel, or both — zero collision across extensions.
Extension context gains publish() and subscribe() convenience
methods that auto-stamp the extension's ID as publisher.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ToolCheck kernel service checks ptyc/pql/tmux/git availability
once at boot, shared by status bar and welcome screen. Welcome
status line shows "application ok" in green or lists missing
tools in amber. Logo doubled to 144px. DialogHost moved inside
Expanded to fix blank workspace. Welcome maxWidth 850px, path
overflow fixed with Flexible.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Flutter's globalPosition is window-relative, not screen-absolute.
Now using gdk_device_get_position() on the native side to get
the actual screen coordinates at the moment startDrag/startResize
is called. Dart no longer passes coordinates — the native handler
queries the pointer directly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace XWayland fallback with proper xdg-decoration protocol
negotiation. On Wayland: binds zxdg_decoration_manager_v1 from
the compositor registry, requests CLIENT_SIDE mode on the toplevel
surface — KWin respects this and drops server-side decorations.
Falls back to gdk_window_set_decorations(0) + set_decorated(FALSE)
on X11. GDK_BACKEND=x11 removed from Makefile.
Also fixes mouse-jumping glitch: startDrag and startResize now
pass screen coordinates from Flutter's globalPosition through the
method channel to gtk_window_begin_move/resize_drag.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Without OS decorations there are no resize handles. Added 6px
edge and 12px corner invisible hit zones around the window
perimeter via ClideResizeBorder. Each zone changes the cursor
and calls gtk_window_begin_resize_drag via the clide/window
method channel with a GdkWindowEdge direction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New tokens: chromeBackground, chromeForeground, chromeBorder —
shared root for hat bar, sidebar, context panel, status bar,
spines, and drag handles. All resolve to bgSunken/textDim/border
in the palette by default. Themes can override individually to
diverge surfaces. Replaces direct sidebarBackground/statusBar
references in chrome contexts. Updated theme-ui skill.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The non-line pixels in the 5px drag handle now fill with the
adjacent panel's background color (sidebar or context) instead
of being transparent. The 1px divider line stays on the inner
edge touching the center column.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 1px visible line in the 5px drag handle now sits on the
innermost pixel (touching the center column) instead of centered.
Side panels (sidebar and context) get 2px padding on all sides
except the bottom, creating a balanced inset that matches the
divider's visual weight.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Handle is 5px wide for comfortable drag, with a 1px center line
using dividerColor (switches to panelActiveBorder on hover).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hat bar is now a single continuous row above the three columns
instead of per-column segments. Left: macOS traffic lights or
empty. Center: project > branch. Right: minimize/maximize/close
on Linux or empty. Column separators keep 4px hit area but show
a 1px centered line.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hide GTK title bar via gtk_window_set_decorated(FALSE). Add
MethodChannel('clide/window') for drag/minimize/maximize/close
wired to GTK window functions. Dart WindowControls service wraps
the channel. Three per-column hats in RootLayout: left (macOS
traffic lights or plain drag), center (project > branch label),
right (minimize/maximize/close glyph buttons on Linux). Resolves
Q-006.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Branch picker now handles Escape key to dismiss, shows an × close
button in the header, and displays error/empty states instead of
silently showing nothing. Dialog backdrop is click-to-dismiss (the
dialog content stops propagation so clicks inside don't close it).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
InProcessClient dispatches IPC requests directly to handlers in the
same process, bypassing the unix socket entirely. All subsystem
registries (pane, files, editor, git, pql) are created in the
Flutter app's boot sequence and registered on a DaemonDispatcher.
Events bridge to the kernel EventBus via _BusEventSink. The app
no longer needs `clide --daemon` running.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Single Flutter package at the repo root. All code, tests, assets,
and platform directories moved from app/ to root. Package renamed
from clide_app to clide — all imports rewritten. Merged pubspec
combines core (ffi) and app (flutter, yaml, xterm) dependencies.
Makefile simplified: no APP_PRESENT conditionals, no cd, no daemon
lifecycle. 317 tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>