I was interested in potentially using gpui for a hobby project, but
needed [layer
shell](https://wayland.app/protocols/wlr-layer-shell-unstable-v1)
support for it. Turns out gpui's (excellent!) architecture made that
super easy to implement, so I went ahead and did it.
Layer shell is a window role used for notification windows, lock
screens, docks, backgrounds, etc. Supporting it in gpui opens the door
to implementing applications like that using the framework.
If this turns out interesting enough to merge - I'm also happy to
provide a follow-up PR (when I have the time to) to implement some of
the desirable window options for layer shell surfaces, such as:
- namespace (currently always `""`)
- keyboard interactivity (currently always `OnDemand`, which mimics
normal keyboard interactivity)
- anchor, exclusive zone, margins
- popups
Release Notes:
- Added support for wayland layer shell surfaces in gpui
---------
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
This is another attempt to solve the same problem as
https://github.com/zed-industries/zed/pull/29718, while avoiding the
regression on Intel GPUs.
### Background
Currently, on main, all paths are first rendered to an intermediate
"atlas" texture, similar to what we use for rendering glyphs, but with
multi-sample antialiasing enabled. They are then drawn into our actual
frame buffer in a separate pass, via the "path sprite" shaders.
Notably, the intermediate texture acts as an "atlas" - the paths are
laid out in a non-overlapping way, so that each path could be copied to
an arbitrary position in the final scene. This non-overlapping approach
makes a lot sense for Glyphs (which are frequently re-used in multiple
places within a frame, and even across frames), but paths do not have
these properties.
* we clear the atlas every frame
* we rasterize each path separately. there is no deduping.
The problem with our current approach is that the path atlas textures
can end up using lots of VRAM if the scene contains many paths. This is
more of a problem in other apps that use GPUI than it is in Zed, but I
do think it's an issue for Zed as well. On Windows, I have hit some
crashes related to GPU memory.
In https://github.com/zed-industries/zed/pull/29718, @sunli829
simplified path rendering to just draw directly to the frame buffer, and
enabled msaa for the whole frame buffer. But apparently this doesn't
work well on Intel GPUs because MSAA is slow on those GPUs. So we
reverted that PR.
### Solution
With this PR, we rasterize paths to an intermediate texture with MSAA.
But rather than treating this intermediate texture like an *atlas*
(growing it in order to allocate non-overlapping rectangles for every
path), we simply use a single fixed-size, color texture that is the same
size as thew viewport. In this texture, we rasterize the paths in their
final screen position, allowing them to overlap. Then we simply blit
them from the resolved texture to the frame buffer.
### To do
* [x] Implement for Metal
* [x] Implement for Blade
* [x] Fix content masking for paths
* [x] Fix rendering of partially transparent paths
* [x] Verify that this performs well on Intel GPUs (help @notpeter 🙏 )
* [ ] Profile and optimize
Release Notes:
- N/A
---------
Co-authored-by: Junkui Zhang <364772080@qq.com>
Instead of selecting a screen to share arbitrarily, we'll now allow user
to select the screen to share. Note that sharing multiple screens at the
time is still not supported (though prolly not too far-fetched).
Related to #4666

Release Notes:
- Added screen selector dropdown to screen share button
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: Cole Miller <cole@zed.dev>
Reverts zed-industries/zed#29718
We've noticed some issues with Zed on Intel-based Macs where typing has
become sluggish, and git bisect has seemed to point towards this PR.
Reverting for now, until we can understand why it is causing this issue.
Currently, the rendering path required creating a texture for each path,
which wasted a large amount of video memory. In our application, simply
drawing some charts resulted in video memory usage as high as 5G.
I removed the step of creating path textures and directly drew the paths
on the rendering target, adding post-processing global multi-sampling
anti-aliasing. Drawing paths no longer requires allocating any
additional video memory and also improves the performance of path
rendering.
Release Notes:
- N/A
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
Add `screen-capture` feature to gpui to enable screen capture support. The motivation for this is to make dependencies on scap / x11 / xcb optional.
Release Notes:
- N/A
---------
Co-authored-by: Michael Sloan <michael@zed.dev>
Continuing this work from a while back in #21079, now greatly aided by
agent + sonnet 4. With this change, there are now only a few spots that
explicitly panic, though errors during initialization will panic.
Motivation was this recent user panic in `handle_event`, figured fixing
all this use of unwrap was a great use of the agent.
> called `Result::unwrap()` on an `Err` value: X11 GetProperty for
_NET_WM_STATE failed.
Release Notes:
- N/A
Closes#21700
Release Notes:
- Added caps lock support and show a warning if the user is entering an
SSH password with Caps Lock enabled
---------
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: 张小白 <364772080@qq.com>
Fixes: #29812Fixes: #22538
Co-Authored-By: <corentinhenry@gmail.com>
Release Notes:
- vim: Multi-key bindings in insert mode will now show the pending
keystroke in the buffer. For example if you have `jk` mapped to escape,
pressing `j` will immediately show a `j`.
Allows setting element as window control elements which consist of
`Drag`, `Close`, `Max`, or `Min`. This allows you to implement
dynamically sized elements that control the platform window, this is
used for areas such as the title bar. Currently only implemented for
Windows.
Release Notes:
- N/A
Closes#16527
Release Notes:
- Added MacOS titlebar double-click action
---
Unfortunately, Apple doesn't seem to make the "Fill" API public or
documented anywhere.
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
Release Notes:
- N/A
----
The before version GPUI used `Cancel` for cancel text, if we use
non-English text (e.g.: "取消" in Chinese), then the press `Esc` to cancel
will not work.
So this PR to change it by use `PromptButton` to instead the `&str`,
then we can use `PromptButton::cancel("取消")` for the `Cancel` button.
Run `cargo run -p gpui --example window` to test.
---
Platform Test:
- [x] macOS
- [x] Windows
- [x] Linux (x11 and Wayland)
---------
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Open inspector with `dev: toggle inspector` from command palette or
`cmd-alt-i` on mac or `ctrl-alt-i` on linux.
https://github.com/user-attachments/assets/54c43034-d40b-414e-ba9b-190bed2e6d2f
* Picking of elements via the mouse, with scroll wheel to inspect
occluded elements.
* Temporary manipulation of the selected element.
* Layout info and JSON-based style manipulation for `Div`.
* Navigation to code that constructed the element.
Big thanks to @as-cii and @maxdeviant for sorting out how to implement
the core of an inspector.
Release Notes:
- N/A
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
Co-authored-by: Federico Dionisi <code@fdionisi.me>
This glyphs field is usually larger than 8 elements, and SmallVec is not
efficient when it cannot store the value inline.
This change also adds precise glyphs run preallocation in some places
`ShapedRun` is constructed.
Release Notes:
- N/A
This pull request introduces a new tool for streaming edits. The
short-term goal is for this tool to replace the existing `EditFileTool`,
but we want to get this out the door as soon as possible so that we can
start testing it.
`StreamingEditFileTool` is mutually exclusive with `EditFileTool`. It
will be enabled by default for anyone who has the `agent-stream-edits`
feature flag, as well as people that set `assistant.stream_edits` to
`true` in their settings.
### Implementation
Streaming is achieved by requesting a completion while the `edit_file`
tool gets called. We invoke the model by taking the existing
conversation with the agent and appending a prompt specifically tailored
for editing. In that prompt, we ask the model to produce a stream of
`<old_text>`/`<new_text>` tags. As the model streams text in, we
incrementally parse it and start editing as soon as we can.
### Evals
Note that, as part of this pull request, I also defined some new evals
that I used to drive the behavior of the recursive LLM call. To run
them, use this command:
```bash
cargo test --package=assistant_tools --features eval -- eval_extract_handle_command_output
```
Or comment out the `#[cfg_attr(not(feature = "eval"), ignore)]` macro.
I recommend running them one at a time, because right now we don't
really have a way of orchestrating of all these evals. I think we should
invest into that effort once the new agent panel goes live.
Release Notes:
- N/A
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: Oleksiy Syvokon <oleksiy.syvokon@gmail.com>
This PR fixes several possible memory leaks due to loading images in
markdown files and the image viewer, using the new image cache APIs
TODO:
- [x] Ensure this didn't break rendering in any of the affected
components.
Release Notes:
- Fixed several image related memory leaks
Closes:
https://github.com/zed-industries/zed/pull/29177#issuecomment-2823359242
Removes dependency on
[quininer/x11-clipboard](https://github.com/quininer/x11-clipboard) as
it is in [maintenance
mode](https://github.com/quininer/x11-clipboard/issues/19).
X11 clipboard functionality is now built-in to GPUI which was
accomplished by stripping the non-x11-related code/abstractions from
[1Password/arboard](https://github.com/1Password/arboard) and extending
it to support all image formats already supported by GPUI on wayland and
macos.
A benefit of switching over to the `arboard` implementation, is that we
now make an attempt to have an X11 "clipboard manager" (if available -
something the user has to setup themselves) save the contents of
clipboard (if the last copy operation was within Zed) so that the copied
contents can still be pasted once Zed has completely stopped.
Release Notes:
- Linux(X11): Add support for pasting images from clipboard
Closes#27414
`ImageCache` is independent of the original image loader and can
actively release its cached images to solve the problem of images loaded
from the network or files not being released.
It has two constructors:
- `ImageCache::new`: Manually manage the cache.
- `ImageCache::max_items`: Remove the least recently used items when the
cache reaches the specified number.
When creating an `img` element, you can specify the cache object with
`Img::cache`, and the image cache will be managed by `ImageCache`.
In the example `crates\gpui\examples\image-gallery.rs`, the
`ImageCache::clear` method is actively called when switching a set of
images, and the memory will no longer continuously increase.
Release Notes:
- N/A
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
This PR adds a new `PlatformKeyboardLayout` trait with two methods:
`id(&self) -> &str` and `name(&self) -> &str`. The `id()` method returns
a unique identifier for the keyboard layout, while `name()` provides a
human-readable name. This distinction is especially important on
Windows, where the `id` and `name` can be quite different. For example,
the French layout has an `id` of `0000040C`, which is not
human-readable, whereas the `name` would simply be `French`. Currently,
the existing `keyboard_layout()` method returns what's essentially the
same as `id()` in this new design.
This PR implements the `name()` method for both Windows and macOS. On
Linux, for now, `name()` still returns the same value as `id()`.
Release Notes:
- N/A
While working on implementing `add_recent_documents` for Windows, I
found that the process is significantly more complex compared to macOS.
On macOS, simply registering the `add_recent_documents` function is
enough, as the system handles everything automatically.
On Windows, however, there are two cases to consider:
- **Files opened by the app**: These appear in the "Recent" section (as
shown in the screenshot, "test.txt") and are managed automatically by
Windows (by setting windows registry), similar to macOS.

- **Folders opened by the app**: This is more complicated because
Windows does not handle it automatically, requiring the application to
track opened folders manually.
To address this, this PR introduces a `History Manager` along with
`HistoryManagerEvent::Update` and `HistoryManagerEvent::Delete` events
to simplify the process of managing recently opened folders.
https://github.com/user-attachments/assets/a2581c15-7653-4faf-96b0-7c48ab1dcc8d
Release Notes:
- N/A
---------
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
allow DisplayId to be compared to u32. This is handy since gpui doesn't
provide a method to detect current active display of the user. So when
using mouse location to get the active display we need to then compare
that display u32 to DisplayID
Release Notes:
- added From to allow u32 comparison
Reapplies #27807 after [revert due to not building on
ARM](https://github.com/zed-industries/zed/pull/28141) by updating scap
to include [a fix to its build on
ARM](08f0a01417)
Release Notes:
- N/A
---------
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
While `scap` does have support for Wayland and Windows, but haven't seen
screensharing work properly there yet. So for now just adding support
for X11 screensharing.
WIP branches for enabling wayland and windows support:
* https://github.com/zed-industries/zed/tree/wayland-screenshare
* https://github.com/zed-industries/zed/tree/windows-screenshare
Release Notes:
- Added support for screensharing on X11 (Linux)
---------
Co-authored-by: Conrad <conrad@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Junkui Zhang <364772080@qq.com>
Implement the From trait for some simple conversations between Clipboard
related structs.
This PR only adds the From trait implementations and doesn't touch any
code. In a future PR we can simplify usage throughout the codebase, such
as:
```rust
// impl ClipboardString
fn new(text: String) -> Self {
Self::from(text)
}
```
Release Notes:
- N/A *or* Added/Fixed/Improved ...
Closes#4461
Take 2 on https://github.com/zed-industries/zed/pull/25040.
Fixes panic caused due to using `setHiddenUntilMouseMoves` return type
to `set` cursor on macOS.
Release Notes:
- Now cursor hides when the user is typing in editor. It will stay
hidden until it is moved again. This behavior is `true` by default, and
can be configured with `hide_mouse_while_typing` in settings.
---------
Co-authored-by: Peter Tripp <peter@zed.dev>
Co-authored-by: Thomas Mickley-Doyle <thomas@zed.dev>
Co-authored-by: Agus <agus@zed.dev>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: Agus Zubiaga <hi@aguz.me>
Co-authored-by: Angelk90 <angelo.k90@hotmail.it>
This reverts commit a8610fbd13.
I've been seeing some reports of segmentation faults that appear to
point to this change as the culprit.
Closes#25366.
Release Notes:
- Community: Reverted #25040, so remove the corresponding entry from the
release notes.
Closes https://github.com/zed-industries/zed/issues/4461
This PR improves the coding experience by hiding the mouse while the
user is typing so it does not accidentally get in their way, making it
challenging to ready characters in the editor.
Release Notes:
- The following PR hides the cursor when the user is typing by adding a
new cursor style called `None`.
- Assuming the user does not move the mouse, it will stay hidden until
it is moved again.
https://github.com/user-attachments/assets/6ba9f2ee-b9f3-4595-81e4-e9d986da4a39
---------
Co-authored-by: Agus <agus@zed.dev>
Co-authored-by: Peter Tripp <peter@zed.dev>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Fixes#22939Fixes#23970
Supersedes https://github.com/zed-industries/zed/pull/23469
Release Notes:
- Fixed a bug where Zed could crash with certain input sources on macOS
---------
Co-authored-by: Louis Brunner <louis.brunner.fr@gmail.com>
Co-authored-by: ben <ben@zed.dev>
GPUI applications can set the window class by the `app_id` window
option. However, GPUI will map the window first and then change the
window class after the window is displayed. This doesn't work on some
X11 window managers. FVWM, for example, does not track window class
after a window is mapped. Because in practice, a window shouldn't change
its application group on the fly.
This PR fixed this by adding a `map_window()` function `PlatformWindow`.
On X11, it will `set_app_id()` first and then map the window.
Release Notes:
- N/A
Fix bugs caused by the window context PR, where the window could be on
the stack and is then requested from the App.
This PR also adds derive macros for `AppContext` and `VisualContext` so
that it's easy to define further contexts in API code, such as
`editor::BlockContext`.
Release Notes:
- N/A
There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:
- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`
Not pictured here are the two other failed attempts. It's been quite a
month!
Tasks:
- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs
### issues post merge
- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue
Release Notes:
- N/A
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
Closes#17870
Context:
On Linux, when creating a new window, bounds are either pulled from
existing workspace data (serialized in an SQLite DB) or fall back to
some default constants if no data exists.
These bounds include the full dimensions of the window (width and
height), which already account for insets. However, properties like
`inset` (Wayland) or `last_insets` (X11) exist only at the platform
level and are not part of the window bounds themselves.
During rendering, we call `set_client_inset`, which updates the inset
values and also adjusts the window bounds, increasing their dimensions.
In Zed's case, the inset is 10px, which adds 20px to both the width and
height (10px from each side).
Problem:
When quitting, the full window bounds (which already account for inset)
are saved to the DB. On reopening, these saved bounds are used to create
the window. `set_client_inset` runs again and inflates the dimensions
even more.
Solution:
Store window bounds *without* the inset-inflated dimensions. On the next
session, `set_client_inset` will take care of applying the inset,
resulting window dimensions matching the previous session. This fix is
in the PR.
Alternative Solution:
Another option is to save the inset explicitly in the DB and apply it
during window creation. But this means storing more data, and the inset
would need to be platform-agnostic, which adds complexity. Doesn’t seem
worth it for no real gain.
X11 Before:
```sh
saving window bounds with width: 1136, height: 784
tims@lemon ~/w/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.37s
Running `target/debug/zed`
saving window bounds with width: 1156, height: 804 <---- +20px
tims@lemon ~/w/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s
Running `target/debug/zed`
saving window bounds with width: 1176, height: 824 <---- +20px
tims@lemon ~/w/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.36s
Running `target/debug/zed`
saving window bounds with width: 1196, height: 844 <---- +20px
```
X11 After:
```sh
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s
Running `target/debug/zed`
saving window bounds with width: 1116, height: 764
tims@lemon ~/w/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s
Running `target/debug/zed`
saving window bounds with width: 1116, height: 764 <---- same
tims@lemon ~/w/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s
Running `target/debug/zed`
saving window bounds with width: 1116, height: 764 <---- same
```
On Wayland, saving occurs only when you actually resize the window (on
X11, saving happens both on init and while dragging the window). To
trigger saving, I manually resized the window by ~1px to make it print.
Wayland Before:
```sh
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 36s
Running `target/debug/zed`
saving window bounds with width: 945, height: 577
tims@orange ~/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.77s
Running `target/debug/zed`
saving window bounds with width: 966, height: 597 <--- +20px on both (1px increase in width is me resizing)
tims@orange ~/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.87s
Running `target/debug/zed`
saving window bounds with width: 987, height: 618 <--- +20px on both (1px increase in width and height is me resizing)
tims@orange ~/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.89s
Running `target/debug/zed`
saving window bounds with width: 1006, height: 638 <--- +20px on both (1px decrease in width is me resizing)
```
Wayland After:
```sh
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.82s
Running `target/debug/zed`
saving window bounds with width: 925, height: 558
tims@orange ~/zed (fix-window-growing-larger)> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.84s
Running `target/debug/zed`
saving window bounds with width: 925, height: 557 <--- same (1px decrease in height is me resizing)
saving window bounds with width: 925, height: 558
```
Release Notes:
- Fix non-maximized zed windows growing larger across sessions on Linux
---------
Co-authored-by: mgsloan@gmail.com <michael@zed.dev>