Commit Graph

12 Commits

Author SHA1 Message Date
Emil Ernerfeldt 76ec982958 Lower some logging from debug -> trace 2024-01-19 13:44:04 +01:00
Emil Ernerfeldt b766a48fa7
Update wgpu to 0.19 (#3824)
* Closes https://github.com/emilk/egui/issues/3675

---------

Co-authored-by: Andreas Reich <r_andreas2@web.de>
Co-authored-by: Mingun <Alexander_Sergey@mail.ru>
2024-01-19 10:14:13 +01:00
Konkitoman 83aa3109d3
Multiple viewports/windows (#3172)
* Closes #1044

---
(new PR description written by @emilk)

## Overview
This PR introduces the concept of `Viewports`, which on the native
eframe backend corresponds to native OS windows.

You can spawn a new viewport using `Context::show_viewport` and
`Cotext::show_viewport_immediate`.
These needs to be called every frame the viewport should be visible.

This is implemented by the native `eframe` backend, but not the web one.

## Viewport classes
The viewports form a tree of parent-child relationships.

There are different classes of viewports.

### Root vieport
The root viewport is the original viewport, and cannot be closed without
closing the application.

### Deferred viewports
These are created with `Context::show_viewport`.
Deferred viewports take a closure that is called by the integration at a
later time, perhaps multiple times.
Deferred viewports are repainted independenantly of the parent viewport.
This means communication with them need to done via channels, or
`Arc/Mutex`.

This is the most performant type of child viewport, though a bit more
cumbersome to work with compared to immediate viewports.

### Immediate viewports
These are created with `Context::show_viewport_immediate`.
Immediate viewports take a `FnOnce` closure, similar to other egui
functions, and is called immediately. This makes communication with them
much simpler than with deferred viewports, but this simplicity comes at
a cost: whenever tha parent viewports needs to be repainted, so will the
child viewport, and vice versa. This means that if you have `N`
viewports you are poentially doing `N` times as much CPU work. However,
if all your viewports are showing animations, and thus are repainting
constantly anyway, this doesn't matter.

In short: immediate viewports are simpler to use, but can waste a lot of
CPU time.

### Embedded viewports
These are not real, independenant viewports, but is a fallback mode for
when the integration does not support real viewports. In your callback
is called with `ViewportClass::Embedded` it means you need to create an
`egui::Window` to wrap your ui in, which will then be embedded in the
parent viewport, unable to escape it.


## Using the viewports
Only one viewport is active at any one time, identified wth
`Context::viewport_id`.
You can send commands to other viewports using
`Context::send_viewport_command_to`.

There is an example in
<https://github.com/emilk/egui/tree/master/examples/multiple_viewports/src/main.rs>.

## For integrations
There are several changes relevant to integrations.

* There is a [`crate::RawInput::viewport`] with information about the
current viewport.
* The repaint callback set by `Context::set_request_repaint_callback`
now points to which viewport should be repainted.
* `Context::run` now returns a list of viewports in `FullOutput` which
should result in their own independant windows
* There is a new `Context::set_immediate_viewport_renderer` for setting
up the immediate viewport integration
* If you support viewports, you need to call
`Context::set_embed_viewports(false)`, or all new viewports will be
embedded (the default behavior).


## Future work
* Make it easy to wrap child viewports in the same chrome as
`egui::Window`
* Automatically show embedded viewports using `egui::Window`
* Use the new `ViewportBuilder` in `eframe::NativeOptions`
* Automatically position new viewport windows (they currently cover each
other)
* Add a `Context` method for listing all existing viewports

Find more at https://github.com/emilk/egui/issues/3556




---

<details>
<summary>
Outdated PR description by @konkitoman
</summary>


## Inspiration
- Godot because the app always work desktop or single_window because of
embedding
- Dear ImGui viewport system

## What is a Viewport

A Viewport is a egui isolated component!
Can be used by the egui integration to create native windows!

When you create a Viewport is possible that the backend do not supports
that!
So you need to check if the Viewport was created or you are in the
normal egui context!
This is how you can do that:
```rust
if ctx.viewport_id() != ctx.parent_viewport_id() {
    // In here you add the code for the viewport context, like
    egui::CentralPanel::default().show(ctx, |ui|{
        ui.label("This is in a native window!");
    });
}else{
    // In here you add the code for when viewport cannot be created!
   // You cannot use CentralPanel in here because you will override the app CentralPanel
   egui::Window::new("Virtual Viewport").show(ctx, |ui|{
       ui.label("This is without a native window!\nThis is in a embedded viewport");
   });
}
```

This PR do not support for drag and drop between Viewports!

After this PR is accepted i will begin work to intregrate the Viewport
system in `egui::Window`!
The `egui::Window` i want to behave the same on desktop and web
The `egui::Window` will be like Godot Window

## Changes and new

These are only public structs and functions!

<details>
<summary>

## New
</summary>

- `egui::ViewportId`
- `egui::ViewportBuilder`
This is like winit WindowBuilder

- `egui::ViewportCommand`
With this you can set any winit property on a viewport, when is a native
window!

- `egui::Context::new`
- `egui::Context::create_viewport`
- `egui::Context::create_viewport_sync`
- `egui::Context::viewport_id`
- `egui::Context::parent_viewport_id`
- `egui::Context::viewport_id_pair`
- `egui::Context::set_render_sync_callback`
- `egui::Context::is_desktop`
- `egui::Context::force_embedding`
- `egui::Context::set_force_embedding`
- `egui::Context::viewport_command`
- `egui::Context::send_viewport_command_to`
- `egui::Context::input_for`
- `egui::Context::input_mut_for`
- `egui::Context::frame_nr_for`
- `egui::Context::request_repaint_for`
- `egui::Context::request_repaint_after_for`
- `egui::Context::requested_repaint_last_frame`
- `egui::Context::requested_repaint_last_frame_for`
- `egui::Context::requested_repaint`
- `egui::Context::requested_repaint_for`
- `egui::Context::inner_rect`
- `egui::Context::outer_rect`

- `egui::InputState::inner_rect`
- `egui::InputState::outer_rect`

- `egui::WindowEvent`

</details>

<details>
<summary>

## Changes
</summary>

- `egui::Context::run`
Now needs the viewport that we want to render!

- `egui::Context::begin_frame`
Now needs the viewport that we want to render!

- `egui::Context::tessellate`
Now needs the viewport that we want to render!

- `egui::FullOutput`
```diff
- repaint_after
+ viewports
+ viewport_commands
```

- `egui::RawInput`
```diff
+ inner_rect
+ outer_rect
```

- `egui::Event`
```diff
+ WindowEvent
```
</details>

### Async Viewport

Async means that is independent from other viewports!

Is created by `egui::Context::create_viewport`

To be used you will need to wrap your state in `Arc<RwLock<T>>`
Look at viewports example to understand how to use it!

### Sync Viewport

Sync means that is dependent on his parent!

Is created by `egui::Context::create_viewport_sync`

This will pause the parent then render itself the resumes his parent!

#### ⚠️ This currently will make the fps/2 for every sync
viewport

### Common

#### ⚠️ Attention

You will need to do this when you render your content
```rust
ctx.create_viewport(ViewportBuilder::new("Simple Viewport"), | ctx | {
    let content = |ui: &mut egui::Ui|{
        ui.label("Content");
    };

    // This will make the content a popup if cannot create a native window
    if ctx.viewport_id() != ctx.parent_viewport_id() {
        egui::CentralPanel::default().show(ctx, content);
    } else {
        egui::Area::new("Simple Viewport").show(ctx, |ui| {
            egui::Frame::popup(ui.style()).show(ui, content);
        });
    };
});
````

## What you need to know as egui user

### If you are using eframe

You don't need to change anything!

### If you have a manual implementation

Now `egui::run` or `egui::begin` and `egui::tessellate` will need the
current viewport id!
You cannot create a `ViewportId` only `ViewportId::MAIN`

If you make a single window app you will set the viewport id to be
`egui::ViewportId::MAIN` or see the `examples/pure_glow`
If you want to have multiples window support look at `crates/eframe`
glow or wgpu implementations!

## If you want to try this

- cargo run -p viewports

## This before was wanted to change

This will probably be in feature PR's

### egui::Window

To create a native window when embedded was set to false
You can try that in viewports example before:
[78a0ae8](78a0ae879e)

### egui popups, context_menu, tooltip

To be a native window

</details>

---------

Co-authored-by: Konkitoman <konkitoman@users.noreply.github.com>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Co-authored-by: Pablo Sichert <mail@pablosichert.com>
2023-11-16 11:25:05 +01:00
Emil Ernerfeldt 82704bebbf
Update MSRV to Rust 1.70.0 (#3310)
* Update to Rust 1.70

* Fix renamed clippy lint

* Use let-else more

* Code cleanup

* Remove derelict Safety comments

* Enable more clippy lints
2023-09-06 07:59:24 +02:00
bernsteining 67d5bd4392
fix(docs): remove duplicate typo (#3111) 2023-07-26 19:00:13 +02:00
Ryan Hileman ede3ded977
egui-winit: Use RawDisplayHandle for smithay clipboard init (#2914) 2023-04-19 09:14:23 +02:00
Emil Ernerfeldt 9c9a54ce36
Replace `tracing` with `log` (#2928)
* Replace tracing crate with log

It's just so much simpler to use

* Add `bacon wasm` job

* eframe: add a WebLogger for piping log events to the web console
2023-04-18 21:11:26 +02:00
Diggory Hardy fb726aaabb
egui-winit: fix unsafe API of Clipboard::new (#2765)
* egui-winit: fix unsafe API of Clipboard::new

The old API allowed passing an arbitrary pointer. The new
API still breaks safety by allowing the object to outlive
the input, but is at least safer.

* Update crates/egui-winit/src/clipboard.rs

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>

* Fix typo

* Update crates/egui-winit/src/clipboard.rs

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>

* cargo fmt

* egui-winit: fix init_smithay_clipboard

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2023-03-30 10:21:07 +02:00
Emil Ernerfeldt 32677a54e4 egui-winit: improve clipboard logging 2022-12-13 09:09:25 +01:00
Emil Ernerfeldt 17501d7e3e
Update arboard, fixing copy-paste on X11 (#2238)
* Revert "Fix copy-paste on Windows (#2120)"

This reverts commit f61044cef7.

* Update arboard to 3.2
2022-11-07 09:54:42 +01:00
Emil Ernerfeldt f61044cef7
Fix copy-paste on Windows (#2120)
Closes https://github.com/emilk/egui/issues/2109

Since arboard 3.0 you must absolutely not hold onto `arboard::Clipbaord`
longer than you are using it.

See https://github.com/1Password/arboard/issues/84
2022-10-07 14:46:42 +02:00
Emil Ernerfeldt 041f2e64ba
Move all crates into a `crates` directory (#1940) 2022-08-20 10:41:49 +02:00