previously we assumed that clipboard support was always there, so
unwrap() was inappropriate meaning that if the clipboard provider failed to
initialize, we panicked.
todo: in fact we should ERASE all unwrap() from the codebase if not tests.
so to model the thing we actually have:
- a clipboard provider that *can* be available
- or it can be unavailable, with a reason
x11 PRIMARY vs CLIPBOARD selections
see https://specifications.freedesktop.org/clipboard-spec/1.0
x11 display connection is explicit and may fail
see https://www.x.org/archive/X11R7.5/doc/man/man3/XOpenDisplay.3.html
wayland display is an explicit compositor connection and connect can fail
see https://wayland.freedesktop.org/docs/html/apb.html
see: https://github.com/neovide/neovide/issues/3447
after the multi-window refactor, the renderer can be created before
neovim initial globals are ready.
the runtime path had a second bug:
scale factor updates through settings updates stored the new user scale
and then recomputed the grid scale with the old one. so scale changes were
always one step behind also reported at
https://github.com/neovide/neovide/issues/3447
the real problem is that neovim handle wasnt really ready yet. The queued file-open events
e.g from finder were being flushed as soon as the first handler registered,
but the handler registration happens before ui_attach and in embedded mode neovim
does not finish startup until the UI attaches.
we were replaying `:drop` into an instance that had not finished loading a bunch of
of things like filetype detection, syntax setup or user startup scripts.
see: https://github.com/neovide/neovide/issues/3444
* reintroduce error window for launch failures
* fix: high cpu usage launch-error windows
just adding some control flow for the eventloop scheduler to avoid it
to wake up immediately when the only remaining window is an error
dialog, or if it is an error window in general.
---------
Co-authored-by: Alexsander Falcucci <alex.falcucci@gmail.com>
the old :restart progpath/argv payload is not the protocol anymore
see: https://github.com/neovim/neovim/pull/35223
the contract is now simpler:
- the server starts the new neovim instance
- the UI gets a restart event with the new listen address
- the UI follows that address instead of rebuilding argv
impl the new protocol exposes the second bug. if a reused Neovide process
opens a new embedded window, that route has to start with the files it was
actually asked to open, otherwise :restart will attempt to restart the
process startup args from the first window, or an empty session.
note: neovim reports message grids with the full default-grid height even when only
the bottom few rows are actually on screen.
f2d0b06ecb/src/nvim/message.c?plain=1#L205-L254
we were already compensating for that in one place when clamping the target
position, but then we turned around and used the full backing-grid size for
pixel_region()
that means the renderer still treated the message window as if
all rows were visible, which is wrong.
https://github.com/neovide/neovide/issues/3427
we mistakenly added a theme option to the config file, but it is not
actually used anywhere, must be impl in the future.
let g:neovide_theme has no changes.
the mistake here was treating --chdir and a relative file arg as if
they described the same directory.
they don't.
For a handoff like
cd ~/neovide
neovide --reuse-instance --new-window src/main.rs --chdir ~
the file comes from the caller shell cwd, so it should still mean ~/neovide/src/main.rs
but the new neovim route itself should start with cwd ~
now we take both meanings explicitly through the handoff path:
- cwd: the per-route startup cwd
- caller_cwd: the base directory for resolving relative file drops
we were treating anything non-absolute as relative to the caller cwd
so we ended up resolving wrong paths like /path/to/user/~/project
instead of $HOME/project
this is actually an improvement to the --reuse-instance handoff case.
we should follow the cwd semantics of the request the user actually
dispatched, not whatever happened to be loaded.
we split the problem properly.
this helps us to keep the it simple and visible at the handoff level:
only the chdir option for this invocation gets to override the cwd sent
to the already-running instance.
the handoff path was forwarding files, but not its context.
as current cwd for the request.
- absolute paths stay unchanged
- relative paths are joined against the caller cwd
- otherwise relative paths are preserved as-is
(also needed for the future smart routing matching path)
reusing an existing instance but leaving the app in the background is not
correct for a default workflow, so if --reuse-instance succeeds we activate
the target window.
this turns the handoff transport into an actual startup path instead of
just a socket we can reproduce calling the IPC by hand.
we now accept it from the cli. if there is no listener, startup should continue.
if the request is rejected or the transport fails, we return an explicit startup
outcome.
the other important fix here is tabs handling. The original file-drop
path always read `CmdLineSettings.tabs` from the running instance. That
would have made `neovide --reuse-instance --no-tabs file.txt` silently use
whatever tab setting the runtime uses, which is wrong.
An optional `tabs` override through the existing file-drop pipeline.
here we add `files_to_open` to `HandoffRequest` and introduce `UserEvent::OpenFiles`
meaning that we can already use the IPC transport to receive file-open
requests from the listener and actually open them.
once the listener send that event to the main thread we handle it by marking
the focused route active when one exists, then forward each path through
`send_or_queue_file_drop()`
- IPC transport: receive and forward requests
- event loop: decide where the request lands
- file-drop: actually open the paths
here we add a small IPC layer to enable cross communication.
this is the very first bedside work forward to make reusable neovide instances
possible. first on macOS only since it is my primary development platform,
but the design is not macOS-specific. we will acomplish some of the features
by having the new handoff listener to be cross-platform in the future.
the request currently have a BUILD_VERSION for identity/debugging,
but it's important to say that we *do not reject* on protocol version mismatch.
that kind of check sounds cleaner than it is. In a daily basis it can
lead into incompatible transports when an older Neovide process is still running.
^ this can be rethinked in the future. but there is no need for a real securit
boundary anyway right now. The real problem is silent schema drift, so the wire
structs use `deny_unknown_fields` and the transport stays small enough to reason
about directly.
route requests into a window or open files request are not implemented
yet, but the transport is ready to be used for that.
As I said, it's a bedside work.
the multi-window refactor changed the render loop in two ways,
but they both push work into the path where we already know the
compositor is behind.
mainly Windows users were seeing a regression on nightly such as
typing latency, slow animations.
first, the schedule_render() stopped checking out on skipped_frame.
that means we can still request another redraw even after deciding that
the current frame was missed. That is backwards. A skipped frame is not
a signal to queue more work, it is a signal to get out of the way and
let the already scheduled render finish.
second, ResumeTimeReached started calling prepare_and_animate(),
even though about_to_wait() already does the exact same work. So the
loop grew a second preparation fraction for no real gain. that is just extra
churn and on throttled backends it makes missed-frame recovery noisier
than it needs to be.
here we now put the frame preparation back in one place, as before and avoids
re-arming redraws for frames that we already know they are late. we also match
the pre-refactor control flow that did not exhibit the Windows
typing-latency regression.
size and grid are not independent runtime options. together with
`maximized` they define one mutually exclusive geometry choice,
so we don't model them as separate hot reload events.
todo: we need to improve how we declare mutually exclusive config
options in the config file.
if reload emitted a size/grid independently, then a transition like size -> grid
would depend on event order and could briefly drive invalid state.
in the end, we make geometry hot reload work, but we do it in a way that preserves the
actual model. One geometry setting, one parser, one reload event, one place to
apply it.
we had a single `HotReloadConfigs` and a dispatch path that made every config type
go through. That worked but the "hot reload" was just meant to "renderer properties"
at the moment. so we added a window-level option as well to act as a
bedside for the other properties like window.
Now the watcher emits categorized reload events, the renderer only accepts
renderer configs and the window wrapper owns window-level application of
window config.
First, we now set a sane default window title
we already handle title updates from nvim, but the default startup
behavior was still effectively "call everything Neovide" until
otherwise.
that's not very useful.
now, if the user hasn't configured either 'title' or 'titlestring', we enable
titles and use "%F" so the window follows the current path. *but we don't
override user configuration. if either option was already set, we leave it alone.
---
The second, "title-hidden" means "don't show the title", not "make the window
stop having one"
On macOS we got that wrong. when title hiding was enabled, we hid the
title visually and then also **cleared** the underlying NSWindow title by
setting it to an empty string.
That broke the native bookkeeping for secondary windows. The window itself
was created fine and the native tab showed up, but AppKit no longer had
a real title to use for the Window menu entry. So the second window
ended up effectively unnamed there.
we fix it by leaving the NSWindow title alone. keep the title hidden from
the titlebar, but preserve it for the platform APIs that actually need
it.
we already know the style of the cell under the cursor. Not using the cell color
fallback when `guicursor` leaves fg/bg unset, not falling back means the block
cursor ignores the actual colors being shown in that cell.
In fact instead, neovim ui protocol leave this responsability up the client to impl,
which is reasonable.
we also add `neovide_cursor_cell_color_fallback` as an opt-in. If enabled, the cursor falls
back to the covered cell colors, while explicit cursor colors still override them.
the trail vfx now keep a stable per-particle emission color. each particle captures the
cursor color when it is spawned, and rendering uses that stored color instead of
re-resolving from the current cursor position.
macOS runners occasionally fails due to resource busy while create-dmg
is building the image.
```
Creating disk image...
hdiutil: create failed - Resource busy
Error: Process completed with exit code 1.
```
we introduce NEOVIDE_BUILD_VERSION in build.rs from `git describe` so tagged builds keep the
package version and non-tagged builds report `nightly-<count>+g<sha>` with `-dirty`
preserved when applicable.
we kinda of follow the neovim pattern for nightly versions since the target users are used to it.
we also add cargo rerun tracking for git metadata and tracked files, and use the generated version
for the CLI `--version` output, startup version logging and `g:neovide_version`
consecutively.
note: bundles will not be affected since they have its own limited versioning scheme.
when a TTY launch respawns after --fork on macOS, the new process can look like
a desktop launch and route Neovim through /usr/bin/login. That breaks
terminal-originated launches.
the bug made neovide ignore the files and open an empty buffer, for example
NEOVIDE_FORK=1 cargo run -- ./Cargo.lock
or
env -u TMUX tmux new 'cargo run -- ./Cargo.toml --fork; sleep 3'
this fix a regression introduced at https://github.com/neovide/neovide/pull/3393
appending --embed to the end of the fully merged argv was the wrong fix.
It solved the ssh first-start, but it also turned
nvim --embed -p file1 file2
into
nvim -p file1 file2 --embed
which breaks the normal tabbed startup path.
the old workflow deleted and recreated the nightly release on every scheduled
run, even when the nightly tag already pointed to HEAD. that's just CI churn
and it republishes identical artifacts for no real reason.
we keep the daily schedule, but compare HEAD against the current nightly tag
first and skip the release jobs when they match.
manual dispatch gets a force flag for the rare case where rebuilding the same
commit is actually intended.
* move --embed to be last argument
* add helper fn to build neovim restart command parts
---------
Co-authored-by: Alexsander Falcucci <alex.falcucci@gmail.com>
this is a very specific bug - if we can consider it as one.
when the content width is not an exact multiple of the grid cell width,
we can end up with a tiny strip to the right of the last column.
Fullscreen tends to hide it because the geometry lines up differently,
but in a normal window the seam is visible as soon as the trailing cell
background is not the default one.
Note: this is not really a grid sizing bug. The grid still has to snap to
whole cells. The actual problem is that we were leaving the fractional
remainder completely unpainted.
So we fix it in the renderer instead. Extend the trailing background
slightly into that remainder and cap the fill to a few cell widths so we
do not visibly stretch the last column if the grid briefly lags a
resize.
The multi-window refactor made macOS openFiles depend on the active
handler. On a cold start there is no handler yet, so for example
situation like the Finder 'Open With' drops the files and
neovide opens an empty window.
Now we bring back the old behavior by buffering file drops until the first
route handler registers, then flushing keeping warm starts going
straight to the active handler.
the new multi-window refactor creates the window only after the first
draw batch, but that batch was handled in the route-core and the
font-changed flag got lost probably resolving a conflict.
That made the initial grid sizing skip the first resize,
leaving the UI at the default attach size.
we now track and pass through the font-changed flag from the route-core
into the route state so the first frame forces a grid sync just like
before.