Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
# One arm per platform the crate produces on. Neither needs a display: the Windows arm opens a hidden
# Direct3D window, and the Linux arm is a bare Vulkan device its tests allocate and export on.
#
# The Linux example (`examples/interop_linux.rs`) is deliberately not built here. Its `example`
# feature turns on the facade's platform bundle, which compiles the windowing stack and needs the
# system graphics libraries a bare runner does not carry; the library and its tests use none of it,
# so keeping the example out is what lets this job run on a stock image.
# The Linux examples are not built in the `linux-interop` job. Their `example` feature turns on the
# facade's platform bundle, which compiles the windowing stack and needs the system graphics libraries
# a bare runner does not carry; the library and its tests use none of it, so keeping the examples out
# is what lets that job run on a stock image. They are checked in `package`, which already installs
# those libraries.
name: CI

on:
Expand Down Expand Up @@ -84,6 +85,13 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/linux-deps
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: steps::checkout_core
shell: bash
run: git clone --depth 1 --single-branch --branch bite_1.25.202 https://github.com/bite-gpui/bite-gpui.git ../bite-gpui
# The examples carry `required-features = ["example"]`, so no test job builds them. This
# caught the non-exhaustive `SurfaceEvent` match when the vocabulary grew.
- name: steps::cargo_check_examples
run: cargo check -p gpui_interop --examples --features example
- name: steps::stage_publishable_tree
run: python3 scripts/prepare-publish.py "$RUNNER_TEMP/gpui-interop-publish"
- name: steps::cargo_publish_dry_run
Expand Down
39 changes: 16 additions & 23 deletions crates/gpui_interop/examples/interop_cube_drag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
//! factor alongside, and its `SurfaceEvent` is the crate's vocabulary rather than GPUI's. A drag starts
//! on the viewport, which founds the gateway's own drag, so the cube keeps turning while the pointer is
//! off past the edge — and because the gateway refreshes the window after each event, the producer only
//! has to change its own state. Not every event takes that road: the wheel, which zooms the cube, is the
//! demo's own `on_scroll_wheel`, because the gateway's vocabulary carries no scroll yet and the zoom is
//! the view's rather than the producer's.
//! has to change its own state. The wheel arrives the same way: `SurfaceEvent::Scroll` carries the
//! delta, so the zoom is the producer's too.
//!
//! # Three layers, and why the frame is transparent
//!
Expand Down Expand Up @@ -73,10 +72,10 @@ mod demo {
use std::rc::Rc;

use gpui::{
AnyElement, App, Bounds, Context, IntoElement, Render, ScrollDelta, Window, WindowBounds,
AnyElement, App, Bounds, Context, IntoElement, Render, Window, WindowBounds,
WindowOptions, div, gpu_canvas, prelude::*, px, rgb, rgba, size,
};
use gpui_interop::{SurfaceEvent, SurfaceInput, SurfacePoint, surface_input};
use gpui_interop::{SurfaceEvent, SurfaceInput, SurfacePoint, SurfaceScroll, surface_input};

use crate::cube::{Cube, TRANSPARENT};

Expand Down Expand Up @@ -215,7 +214,6 @@ mod demo {
spinning: Rc<Cell<bool>>,
) -> AnyElement {
let drawing = cube.clone();
let zooming = cube.clone();
let covering = cube.clone();
let surface = gpu_canvas(move |gpu| {
let mut cube = drawing.borrow_mut();
Expand Down Expand Up @@ -247,23 +245,7 @@ mod demo {
.as_ref()
.is_some_and(|cube| cube.covers(uv))
})
// The wheel zooms the *cube*, so it is the demo's own gpui handler and not the gateway's: the
// gateway's vocabulary carries no scroll yet, and the zoom is the view's rather than the
// producer's. One notch moves the eye by a fixed proportion, so zooming out to see the layer
// behind the cube and zooming back in feel the same at either end.
.on_scroll_wheel(move |event, window, _cx| {
let notches = match event.delta {
ScrollDelta::Lines(lines) => lines.y,
ScrollDelta::Pixels(pixels) => pixels.y.as_f32() / PIXELS_PER_LINE,
};
let mut cube = zooming.borrow_mut();
let Some(cube) = cube.as_mut() else {
// Nothing to zoom before the first paint has built the cube.
return;
};
cube.zoom(ZOOM_PER_NOTCH.powf(notches));
window.refresh();
})

// No background of its own: the surface is composited over the layer beneath it, and where
// the producer left the frame transparent that layer shows through.
.absolute()
Expand Down Expand Up @@ -296,6 +278,17 @@ mod demo {
grab.set(false);
last.set(None);
}
// One notch moves the eye by a fixed proportion, so zooming out to see the layer
// behind the cube and zooming back in feel the same at either end.
SurfaceEvent::Scroll { delta, .. } => {
let notches = match delta {
SurfaceScroll::Lines { y, .. } => y,
SurfaceScroll::Pixels { y, .. } => y / PIXELS_PER_LINE,
};
cube.zoom(ZOOM_PER_NOTCH.powf(notches));
}
// The cube has no hover state.
SurfaceEvent::PointerEnter { .. } | SurfaceEvent::PointerLeave { .. } => {}
}
};

Expand Down
3 changes: 2 additions & 1 deletion crates/gpui_interop/src/gpui_interop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ pub use adapter::{Adapter, Unavailable};
pub use guest::{Guest, GuestFrame, GuestOptions};
#[cfg(feature = "gpui")]
pub use input::{
SurfaceButton, SurfaceEvent, SurfaceInput, SurfaceModifiers, SurfacePoint, surface_input,
SurfaceButton, SurfaceEvent, SurfaceInput, SurfaceModifiers, SurfacePoint, SurfaceScroll,
surface_input,
};
#[cfg(target_os = "linux")]
pub use linux::{
Expand Down
Loading
Loading