Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eframe: selectively expose parts of the API based on compile target #1867

Merged
merged 2 commits into from
Jul 29, 2022
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
1 change: 1 addition & 0 deletions eframe/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ NOTE: [`egui-winit`](../egui-winit/CHANGELOG.md), [`egui_glium`](../egui_glium/C
* Use `Arc` for `glow::Context` instead of `Rc` ([#1640](https://github.com/emilk/egui/pull/1640)).
* Fixed bug where the result returned from `App::on_exit_event` would sometimes be ignored ([#1696](https://github.com/emilk/egui/pull/1696)).
* Added `NativeOptions::follow_system_theme` and `NativeOptions::default_theme` ([#1726](https://github.com/emilk/egui/pull/1726)).
* Selectively expose parts of the API based on target arch (`wasm32` or not) ([#1867](https://github.com/emilk/egui/pull/1867)).

#### Desktop/Native:
* Fixed clipboard on Wayland ([#1613](https://github.com/emilk/egui/pull/1613)).
Expand Down
59 changes: 40 additions & 19 deletions eframe/src/epi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,21 +476,17 @@ pub struct IconData {
/// allocate textures, and change settings (e.g. window size).
pub struct Frame {
/// Information about the integration.
#[doc(hidden)]
pub info: IntegrationInfo,
pub(crate) info: IntegrationInfo,

/// Where the app can issue commands back to the integration.
#[doc(hidden)]
pub output: backend::AppOutput,
pub(crate) output: backend::AppOutput,

/// A place where you can store custom data in a way that persists when you restart the app.
#[doc(hidden)]
pub storage: Option<Box<dyn Storage>>,
pub(crate) storage: Option<Box<dyn Storage>>,

/// A reference to the underlying [`glow`] (OpenGL) context.
#[cfg(feature = "glow")]
#[doc(hidden)]
pub gl: Option<std::sync::Arc<glow::Context>>,
pub(crate) gl: Option<std::sync::Arc<glow::Context>>,

/// Can be used to manage GPU resources for custom rendering with WGPU using
/// [`egui::PaintCallback`]s.
Expand All @@ -500,8 +496,11 @@ pub struct Frame {

impl Frame {
/// True if you are in a web environment.
///
/// Equivalent to `cfg!(target_arch = "wasm32")`
#[allow(clippy::unused_self)]
pub fn is_web(&self) -> bool {
self.info.web_info.is_some()
cfg!(target_arch = "wasm32")
}

/// Information about the integration.
Expand Down Expand Up @@ -538,33 +537,39 @@ impl Frame {

/// Signal the app to stop/exit/quit the app (only works for native apps, not web apps).
/// The framework will not quit immediately, but at the end of the this frame.
#[cfg(not(target_arch = "wasm32"))]
pub fn quit(&mut self) {
self.output.quit = true;
}

/// Set the desired inner size of the window (in egui points).
#[cfg(not(target_arch = "wasm32"))]
pub fn set_window_size(&mut self, size: egui::Vec2) {
self.output.window_size = Some(size);
}

/// Set the desired title of the window.
#[cfg(not(target_arch = "wasm32"))]
pub fn set_window_title(&mut self, title: &str) {
self.output.window_title = Some(title.to_owned());
}

/// Set whether to show window decorations (i.e. a frame around you app).
///
/// If false it will be difficult to move and resize the app.
#[cfg(not(target_arch = "wasm32"))]
pub fn set_decorations(&mut self, decorated: bool) {
self.output.decorated = Some(decorated);
}

/// Turn borderless fullscreen on/off (native only).
#[cfg(not(target_arch = "wasm32"))]
pub fn set_fullscreen(&mut self, fullscreen: bool) {
self.output.fullscreen = Some(fullscreen);
}

/// set the position of the outer window
/// set the position of the outer window.
#[cfg(not(target_arch = "wasm32"))]
pub fn set_window_pos(&mut self, pos: egui::Pos2) {
self.output.window_pos = Some(pos);
}
Expand All @@ -573,35 +578,41 @@ impl Frame {
/// movement of the cursor while the primary mouse button is down.
///
/// Does not work on the web.
#[cfg(not(target_arch = "wasm32"))]
pub fn drag_window(&mut self) {
self.output.drag_window = true;
}

/// Set the visibility of the window.
#[cfg(not(target_arch = "wasm32"))]
pub fn set_visible(&mut self, visible: bool) {
self.output.visible = Some(visible);
}

/// for integrations only: call once per frame
#[doc(hidden)]
pub fn take_app_output(&mut self) -> backend::AppOutput {
pub(crate) fn take_app_output(&mut self) -> backend::AppOutput {
std::mem::take(&mut self.output)
}
}

/// Information about the web environment (if applicable).
#[derive(Clone, Debug)]
#[cfg(target_arch = "wasm32")]
pub struct WebInfo {
/// Information about the URL.
pub location: Location,
}

/// Information about the application's main window, if available.
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug)]
pub struct WindowInfo {
/// Coordinates of the window's outer top left corner, relative to the top left corner of the first display.
///
/// Unit: egui points (logical pixels).
pub position: egui::Pos2,
///
/// `None` = unknown.
pub position: Option<egui::Pos2>,

/// Are we in fullscreen mode?
pub fullscreen: bool,
Expand All @@ -613,6 +624,7 @@ pub struct WindowInfo {
/// Information about the URL.
///
/// Everything has been percent decoded (`%20` -> ` ` etc).
#[cfg(target_arch = "wasm32")]
#[derive(Clone, Debug)]
pub struct Location {
/// The full URL (`location.href`) without the hash.
Expand Down Expand Up @@ -667,8 +679,9 @@ pub struct Location {
/// Information about the integration passed to the use app each frame.
#[derive(Clone, Debug)]
pub struct IntegrationInfo {
/// If the app is running in a Web context, this returns information about the environment.
pub web_info: Option<WebInfo>,
/// Information about the surrounding web environment.
#[cfg(target_arch = "wasm32")]
pub web_info: WebInfo,

/// Does the OS use dark or light mode?
///
Expand All @@ -682,8 +695,9 @@ pub struct IntegrationInfo {
/// The OS native pixels-per-point
pub native_pixels_per_point: Option<f32>,

/// Window-specific geometry information, if provided by the platform.
pub window_info: Option<WindowInfo>,
/// The position and size of the native window.
#[cfg(not(target_arch = "wasm32"))]
pub window_info: WindowInfo,
}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -736,35 +750,42 @@ pub const APP_KEY: &str = "app";
// ----------------------------------------------------------------------------

/// You only need to look here if you are writing a backend for `epi`.
#[doc(hidden)]
pub mod backend {
pub(crate) mod backend {
/// Action that can be taken by the user app.
#[derive(Clone, Debug, Default)]
#[must_use]
pub struct AppOutput {
/// Set to `true` to stop the app.
/// This does nothing for web apps.
#[cfg(not(target_arch = "wasm32"))]
pub quit: bool,

/// Set to some size to resize the outer window (e.g. glium window) to this size.
#[cfg(not(target_arch = "wasm32"))]
pub window_size: Option<egui::Vec2>,

/// Set to some string to rename the outer window (e.g. glium window) to this title.
#[cfg(not(target_arch = "wasm32"))]
pub window_title: Option<String>,

/// Set to some bool to change window decorations.
#[cfg(not(target_arch = "wasm32"))]
pub decorated: Option<bool>,

/// Set to some bool to change window fullscreen.
#[cfg(not(target_arch = "wasm32"))] // TODO: implement fullscreen on web
pub fullscreen: Option<bool>,

/// Set to true to drag window while primary mouse button is down.
#[cfg(not(target_arch = "wasm32"))]
pub drag_window: bool,

/// Set to some position to move the outer window (e.g. glium window) to this position
#[cfg(not(target_arch = "wasm32"))]
pub window_pos: Option<egui::Pos2>,

/// Set to some bool to change window visibility.
#[cfg(not(target_arch = "wasm32"))]
pub visible: Option<bool>,
}
}
39 changes: 18 additions & 21 deletions eframe/src/native/epi_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,24 @@ pub fn points_to_size(points: egui::Vec2) -> winit::dpi::LogicalSize<f64> {
}
}

pub fn read_window_info(
window: &winit::window::Window,
pixels_per_point: f32,
) -> Option<WindowInfo> {
match window.outer_position() {
Ok(pos) => {
let pos = pos.to_logical::<f32>(pixels_per_point.into());
let size = window
.inner_size()
.to_logical::<f32>(pixels_per_point.into());
Some(WindowInfo {
position: egui::Pos2 { x: pos.x, y: pos.y },
fullscreen: window.fullscreen().is_some(),
size: egui::Vec2 {
x: size.width,
y: size.height,
},
})
}
Err(_) => None,
pub fn read_window_info(window: &winit::window::Window, pixels_per_point: f32) -> WindowInfo {
let position = window
.outer_position()
.ok()
.map(|pos| pos.to_logical::<f32>(pixels_per_point.into()))
.map(|pos| egui::Pos2 { x: pos.x, y: pos.y });

let size = window
.inner_size()
.to_logical::<f32>(pixels_per_point.into());

WindowInfo {
position,
fullscreen: window.fullscreen().is_some(),
size: egui::Vec2 {
x: size.width,
y: size.height,
},
}
}

Expand Down Expand Up @@ -206,7 +204,6 @@ impl EpiIntegration {

let frame = epi::Frame {
info: epi::IntegrationInfo {
web_info: None,
system_theme,
cpu_usage: None,
native_pixels_per_point: Some(native_pixels_per_point(window)),
Expand Down
16 changes: 3 additions & 13 deletions eframe/src/web/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,12 @@ impl AppRunner {
};

let info = epi::IntegrationInfo {
web_info: Some(epi::WebInfo {
web_info: epi::WebInfo {
location: web_location(),
}),
},
system_theme,
cpu_usage: None,
native_pixels_per_point: Some(native_pixels_per_point()),
window_info: None,
};
let storage = LocalStorage::default();

Expand Down Expand Up @@ -293,16 +292,7 @@ impl AppRunner {

{
let app_output = self.frame.take_app_output();
let epi::backend::AppOutput {
quit: _, // Can't quit a web page
window_size: _, // Can't resize a web page
window_title: _, // TODO(emilk): change title of window
decorated: _, // Can't toggle decorations
fullscreen: _, // TODO(emilk): fullscreen web window
drag_window: _, // Can't be dragged
window_pos: _, // Can't set position of a web page
visible: _, // Can't hide a web page
} = app_output;
let epi::backend::AppOutput {} = app_output;
}

self.frame.info.cpu_usage = Some((now_sec() - frame_start) as f32);
Expand Down
4 changes: 1 addition & 3 deletions eframe/src/web/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,7 @@ pub fn install_document_events(runner_container: &AppRunnerContainer) -> Result<
"hashchange",
|_: web_sys::Event, mut runner_lock| {
// `epi::Frame::info(&self)` clones `epi::IntegrationInfo`, but we need to modify the original here
if let Some(web_info) = &mut runner_lock.frame.info.web_info {
web_info.location.hash = location_hash();
}
runner_lock.frame.info.web_info.location.hash = location_hash();
},
)?;

Expand Down
19 changes: 10 additions & 9 deletions egui_demo_app/src/backend_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ impl BackendPanel {
ui.ctx().options().screen_reader = screen_reader;
}

if !frame.is_web() {
#[cfg(not(target_arch = "wasm32"))]
{
ui.separator();
if ui.button("Quit").clicked() {
frame.quit();
Expand All @@ -159,11 +160,10 @@ impl BackendPanel {
ui.label(".");
});

if let Some(web_info) = &frame.info().web_info {
ui.collapsing("Web info (location)", |ui| {
ui.monospace(format!("{:#?}", web_info.location));
});
}
#[cfg(target_arch = "wasm32")]
ui.collapsing("Web info (location)", |ui| {
ui.monospace(format!("{:#?}", frame.info().web_info.location));
});

// For instance: `eframe` web sets `pixels_per_point` every frame to force
// egui to use the same scale as the web zoom factor.
Expand All @@ -174,10 +174,11 @@ impl BackendPanel {
}
}

if !frame.is_web() {
#[cfg(not(target_arch = "wasm32"))]
{
ui.horizontal(|ui| {
if let Some(window_info) = &frame.info().window_info {
let mut fullscreen = window_info.fullscreen;
{
let mut fullscreen = frame.info().window_info.fullscreen;
ui.checkbox(&mut fullscreen, "🗖 Fullscreen")
.on_hover_text("Fullscreen the window");
frame.set_fullscreen(fullscreen);
Expand Down
7 changes: 3 additions & 4 deletions egui_demo_app/src/wrap_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,9 @@ impl eframe::App for WrapApp {
}

fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
if let Some(web_info) = frame.info().web_info.as_ref() {
if let Some(anchor) = web_info.location.hash.strip_prefix('#') {
self.state.selected_anchor = anchor.to_owned();
}
#[cfg(target_arch = "wasm32")]
if let Some(anchor) = frame.info().web_info.location.hash.strip_prefix('#') {
self.state.selected_anchor = anchor.to_owned();
}

if self.state.selected_anchor.is_empty() {
Expand Down