Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "vendor/baseview"]
path = vendor/baseview
url = git@github.com:Wild-Surmise/baseview.git
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ members = [
"examples/stft",
"examples/sysex",
]
# baseview is a vendored submodule with its own [workspace] root; keep it out
# of ours so each side stays self-contained for upstream-diff sanity.
exclude = ["vendor/baseview"]
default-members = ["crates/nih_plug"]

[workspace.package]
Expand All @@ -42,7 +45,13 @@ serde = { version = "1.0", features = ["derive"] }
atomic_float = "1.1"
atomic_refcell = "0.1"
bitflags = "2.11"
baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "1ec490c99fa2bef0c3c81c4f42d0b7552412c50d", default-features = false }
# Vendored at vendor/baseview (submodule of Wild-Surmise/baseview, branch
# gealach-occlusion-patch). Carries a macOS occlusion-state patch so the
# 15ms CFRunLoop draw timer skips frames when the window is occluded —
# without it, App Nap-throttled draws backlog and freeze the host UI on
# resume. Upstream rev the patch sits on top of:
# 5187acfc578f4fd10c247de6a39c19604e72fab6.
baseview = { path = "vendor/baseview", default-features = false }
raw-window-handle = "0.5"
realfft = "3.0"
approx = "0.5.1"
Expand Down
20 changes: 13 additions & 7 deletions baseview-adapters/egui-baseview/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,12 @@ where
};

self.egui_input.time = Some(self.start_time.elapsed().as_secs_f64());
self.egui_input.screen_rect = Some(calculate_screen_rect(
self.physical_size,
self.points_per_pixel,
));
let effective_points_per_pixel = self.egui_ctx.pixels_per_point().recip();
let screen_rect = calculate_screen_rect(self.physical_size, effective_points_per_pixel);
self.egui_input.screen_rect = Some(screen_rect);
if let Some(viewport_info) = self.egui_input.viewports.get_mut(&self.viewport_id) {
viewport_info.inner_rect = Some(screen_rect);
}

//let mut repaint_requested = false;
let mut queue = Queue::new(
Expand Down Expand Up @@ -386,7 +388,7 @@ where
window,
self.bg_color,
self.physical_size,
self.pixels_per_point,
full_output.pixels_per_point,
&mut self.egui_ctx,
&mut full_output,
);
Expand Down Expand Up @@ -465,7 +467,11 @@ where
} => {
self.update_modifiers(modifiers);

let pos = pos2(position.x as f32, position.y as f32);
let point_scale = self.pixels_per_point / self.egui_ctx.pixels_per_point();
let pos = pos2(
position.x as f32 * point_scale,
position.y as f32 * point_scale,
);
self.pointer_pos_in_points = Some(pos);
self.egui_input.events.push(egui::Event::PointerMoved(pos));
}
Expand Down Expand Up @@ -511,7 +517,7 @@ where

baseview::ScrollDelta::Pixels { x, y } => (
egui::MouseWheelUnit::Point,
egui::vec2(*x, *y) * self.points_per_pixel,
egui::vec2(*x, *y) * self.egui_ctx.pixels_per_point().recip(),
),
};

Expand Down
21 changes: 12 additions & 9 deletions crates/nih_plug/src/wrapper/clap/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2863,12 +2863,20 @@ impl<P: ClapPlugin> Wrapper<P> {
window: *const clap_window,
) -> bool {
check_null_ptr!(false, plugin, unsafe { (*plugin).plugin_data }, window);
// For this function we need the underlying Arc so we can pass it to the editor
let wrapper = unsafe { Arc::from_raw((*plugin).plugin_data as *const Self) };
let wrapper_ref = unsafe { &*((*plugin).plugin_data as *const Self) };
// For this function we need an `Arc<Self>` so we can pass it to the editor. The raw
// `plugin_data` pointer is owned by the CLAP instance and must only be consumed by
// `destroy()`. Reconstructing an `Arc` from it here would temporarily take ownership of
// the plugin wrapper, and any early return before re-leaking it would destroy the live
// plugin while the host may still process audio.
let Some(wrapper) = wrapper_ref.this.borrow().upgrade() else {
nih_debug_assert_failure!("Plugin wrapper was dropped before GUI attachment");
return false;
};

let window = unsafe { &*window };

let result = {
{
let mut editor_handle = wrapper.editor_handle.lock();
if editor_handle.is_none() {
let api = unsafe { CStr::from_ptr(window.api) };
Expand Down Expand Up @@ -2904,12 +2912,7 @@ impl<P: ClapPlugin> Wrapper<P> {

false
}
};

// Leak the Arc again since we only needed a clone to pass to the GuiContext
let _ = Arc::into_raw(wrapper);

result
}
}

unsafe extern "C" fn ext_gui_set_transient(
Expand Down
Loading