rust-windowing / winit

Window handling library in pure Rust
https://docs.rs/winit/
Apache License 2.0
4.55k stars 877 forks source link

Support subsurface/subview/widgets? #3506

Open madsmtm opened 4 months ago

madsmtm commented 4 months ago

The idea to support "subviews", i.e. a sort of limited Window that can be nested inside of Window, has floated around a few times, so I wanted to open an issue to discuss it.

A Subview would have the following platform equivalent (feel free to edit this):

Related: https://github.com/rust-windowing/winit/issues/696. Also discussion in https://github.com/rust-windowing/winit/issues/3311.

madsmtm commented 4 months ago

Personally, I think we should declare this as out of scope of Winit.

At least on macOS and iOS such subviews wouldn't really be useful on their own, we'd have to start allowing creating NSStackView, NSSplitView, NSTextFieldView and so on, and that's a slippery slope, then we're basically becoming GTK.

kchibisov commented 4 months ago

Keep in mind that this is already present in a form of child_window, but the only reason it worked is because of XID and HWND being the same for window. However the API doesn't match what subviews should do, since obviously they can't fullscreen and they have a special way to receive events and resize.

So I guess this issue is more about removing hacky child window stuff and doing proper subview.

Personally, I think we should declare this as out of scope of Winit.

it's already in winit and they are very much required to do complex scene compositing/video players, etc. The same as mixing renderers.

ids1024 commented 4 months ago

then we're basically becoming GTK

Having some way to do subsurfaces/subviews is pretty important for creating a general purpose toolkit like GTK on top of winit. So it seems important unless being a backend for a UI toolkit, or a video player is considered out of scope for winit. Or being used to create a video player, etc.

If it's not supported in winit, there would need to be some acceptable way at least to use platform-specific code to implement this on top of winit. Not sure how practical this would be currently on all of these platforms.

Actually using subsurfaces for things like hardware decoded video will inevitably be platform-specific... at least in the absence of libraries that help with that.

Is it possible to represent all of these kind of subviews as a raw-window-handle currently, or would we need changes there too?

kchibisov commented 4 months ago

Basic subviews don't require anything special. We may have option to create special purpose subveiws, but in general the end goal is to have a way to a separate render target within a window to have video players, overlays drawn with software rendering, just transparent surfaces to dim main scene, etc.

And on macOS maybe some views that affect compositing which you can pass via the platform specific attributes.

madsmtm commented 4 months ago

Discussed a bit on Matrix.

Reconsidering, I think my problem is actually that a Winit Window already does a bunch of stuff that I don't want it to do, like handle keyboard input, because fundamentally that's often a bad idea to do for the entire window (unless you're in the limited sphere of a game). And I don't want to add yet another suboptimal solution for things that people really should resolve using system APIs.

But I realize that subviews could actually resolve most of my issues here, especially if we started assigning events to subviews instead of windows (e.g. split some of the events in WindowEvent out to a new SubViewEvent).

But then again, once we do that, we will likely also have to implement some sort of event bubbling, which, ugh, feature creep.

madsmtm commented 4 months ago

Copying the rough notes from today's meeting:

We can route mouse input events to each subsurface, as that's already done automatically on each platform.

Routing keyboard input events needs focus. Maybe we re-implement focusing? Definitely need some sort of platform-specific focusing support.

Some things maybe cannot bubble (e.g. popups, but maybe those are still separate windows?). Has to be user-controllable.

jgcodes2020 commented 4 months ago

Throwing my two cents in. (Author of Wayland subsurface PR here)

We're trying to support multiple types of window. All windows can:

However, each window type has their own features:

Since we're aiming to use a trait-based API for this, it would make sense to do something like:

pub trait Surface: rwh_06::HasRawWindowHandle/*, etc. */ {
  // surface-specific methods
}
pub trait Toplevel: Surface {
  pub fn set_maximized(maximized: bool);
}
pub trait Subview: Surface {
  pub fn set_position(pos: &Position);
}
MarijnS95 commented 3 months ago

For Android, as discussed in Matrix before I left for a month, using multiple Surfaces for compositing independent planes inside one app requires SurfaceControl and SurfaceTransaction bindings in the NDK (experimental branches are up on the repo), but I haven't gotten it to work on a plain NDK app without Java hacks yet: https://issuetracker.google.com/issues/320706287

axelkar commented 3 months ago

Wayland subsurfaces would be really important for power optimization: https://nical.github.io/drafts/gui-gpu-notes.html