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

expose window as RawWindowHandle #877

Closed
Be-ing opened this issue Jan 26, 2022 · 8 comments · Fixed by #4918
Closed

expose window as RawWindowHandle #877

Be-ing opened this issue Jan 26, 2022 · 8 comments · Fixed by #4918
Labels
a:backend-winit Winit backend (mS,mO) a:language-rust Rust API and codegen (mO,mS) enhancement New feature or request

Comments

@Be-ing
Copy link
Contributor

Be-ing commented Jan 26, 2022

RawWindowHandle is a cross platform API for window handles. Some libraries like rfd can make use of a RawWindowHandle (in rfd's case, to parent a popup dialog to the appropriate window).

tronical added a commit that referenced this issue Jan 26, 2022
…st for sixtyfps::Window

RWH is the de-facto standard crate in Rust to express window handles
(and associated windowing system connections). This should be safe to
use in the public API.

This patch implements RWH for the GL backend.

cc #877
@tronical
Copy link
Member

I pushed a WIP - see linked commit/branch. The Qt implementation is missing, which is a bit of work, but quite doable I think.

In C++ we can get the window handle for a QWidget/Window via QWindow::winId() and the display connection via QPlatformNativeInterface, which supports a per-window connection, for example for the xcb_connection_t. After that we should be able to construct the different variants of https://docs.rs/raw-window-handle/0.4.2/raw_window_handle/index.html .

tronical added a commit that referenced this issue Jan 26, 2022
…st for sixtyfps::Window

RWH is the de-facto standard crate in Rust to express window handles
(and associated windowing system connections). This should be safe to
use in the public API.

This patch implements RWH for the GL backend.

cc #877
tronical added a commit that referenced this issue Feb 10, 2022
…st for sixtyfps::Window

RWH is the de-facto standard crate in Rust to express window handles
(and associated windowing system connections). This should be safe to
use in the public API.

This patch implements RWH for the GL backend.

cc #877
@levrik
Copy link
Contributor

levrik commented May 5, 2022

@tronical I couldn't find this code in the current Slint UI release. I'm guessing it was never finished?

@ogoffart
Copy link
Member

ogoffart commented May 5, 2022

Right, this was not yet merged to the master branch.

@ogoffart
Copy link
Member

ogoffart commented May 5, 2022

I had another look at this and this is not so easy as it looked originally:

  • QWindow::winId is not a native handle on all platform (for example not with wayland https://bugreports.qt.io/browse/QTBUG-76983 ) and getting the actual meaning of it can't seem to be done with public API
  • It's a bit difficult to uphold the unsafety rules. The implementation in the current wip/raw-window-handle branch is unsoud because the PlatformWindow trait could return an invalid window handle. It would be unfortunate to mark the PlatformWindow trait as unsafe just because of that. Also I don't exactly know what's the validity of the handle. For how long is it valid?
  • Would be nice if the RawWindowHandle had a variant that means "None". Right now, if I want to return that there is no handle, I need to make a null pointer for some random other platform.

@ogoffart ogoffart added the enhancement New feature or request label Nov 29, 2022
@ogoffart
Copy link
Member

consumer API

From the consumer point of view, we have two option:

  1. impl HasRawWindowHandle for Window and impl HasRawDisplayHandle for Window .
    That would be my preference. But one the issue with this is that slint::Window can only be accessed as a reference from the consumer side (given a ComponentHandle), and some API that consume the RawWindowHandle take the ownership of it. But they can take a &Window as well. We'll have to see how this play with consumer API

  2. Add a getter: fn Window::raw_handle(&slef) -> impl RawDisplayHandle + RawWindowHandle

platform API

Then from the platform point of view, we need to extend the WindowAdapter trait in some way.

  • This would have to be optional to implement (with a default that would return an invalid handle)
  • This shouldn't make the WindowAdapter unsafe to implement.

I wonder if this should be just one function, or two functions for the window and display handle. The example bellow use one function with a tuple, but it would be changed.
So one suggestions:

trait WindowAdapter {
   fn raw_handle(&self) -> (Option<&dyn HasRawWindowHandle>, Option<&dyn HasRawDisplayHandle>) 
   { ... }
}

With such API, one would typically implement Has*Handle for the struct that implements WindowAdapter and just return self. But that means that the platform need to be unsafe.

trait WindowAdapter {
   fn raw_handle(&self) -> (Option<Rc<dyn HasRawWindowHandle>>, Option<Rc<dyn HasRawDisplayHandle>>) 
   { ... }
}

That would work fine for the winit platform when we keep a Rcwinit::Window. But otherwise we have the risk that we'd need to make an allocation just to put the return value in the Rc. Also the returned struct must have a 'static lifetime.

trait WindowAdapter {
   type RawHandle<'a> : HasRawWindowHandle + HasRawDisplayHandle;
   fn raw_handle<'a>(&'a self) -> Self::RawHandle<'a>;
}

But since there is no default for associated types, we can't make it optional. (Looking forward for the return impl in trait)

  1. If we implement the trait on slint::Window, something that would work and would be the most flexible would be using a callback, but it's also a bit ugly
trait WindowAdapter {
   fn  raw_handle(callback: &mut dyn FnMut(&dyn HasRawWindowHandle, &dyn HasRawDisplayHandle)) {}
}

I think i'd go with 2 at first

@ghost
Copy link

ghost commented Apr 14, 2023

any progress?

@tronical
Copy link
Member

We're trying to sort out how to model the RWH api with the interior mutability of the winit window owner. Meanwhile #2617 adds API to the i-slint-backend-winit crate to provide you with access to the winit window and consequently the RWH. Can you give it a try?

@ogoffart ogoffart added a:language-rust Rust API and codegen (mO,mS) a:backend-winit Winit backend (mS,mO) labels Jul 13, 2023
tronical added a commit that referenced this issue Mar 22, 2024
Add a `rwh_06` feature to the Rust API crates, which adds support for version 0.6 of rwh to slint::Window, by delegation to the backend.

HasDisplayHandle could also be provided on the backend, but that can be
done separately if needed.

Fixes #877
tronical added a commit that referenced this issue Mar 22, 2024
Add a `rwh_06` feature to the Rust API crates, which adds support for version 0.6 of rwh to slint::Window, by delegation to the backend.

HasDisplayHandle could also be provided on the backend, but that can be
done separately if needed.

This is only implemented for the winit backend right now.

Fixes #877
tronical added a commit that referenced this issue Mar 22, 2024
Add a `rwh_06` feature to the Rust API crates, which adds support for version 0.6 of rwh to slint::Window, by delegation to the backend.

HasDisplayHandle could also be provided on the backend, but that can be
done separately if needed.

This is only implemented for the winit backend right now.

Fixes #877
tronical added a commit that referenced this issue Mar 22, 2024
Add a `raw-window-handle-06` feature to the Rust API crates, which adds support for version 0.6 of rwh to slint::Window, by delegation adding a `window_handle()` function that returns a struct that implements the corresponding traits from rwh.

HasDisplayHandle could also be provided on the backend, but that can be
done separately if needed.

This is only implemented for the winit backend right now.

cc #877
@tronical
Copy link
Member

For Qt, commit db9b6a5 in the Slint repo attempts to implement RHW support for the Qt backend. This works on macOS and Windows, but requires the use of private API. For Linux, the same could be done, but that kind of sucks because it means it can't be easily compiled against Linux distro package, which typically don't install private Qt headers.

One workaround would be to use QWindow::winId() and cast accordingly. By looking at the public QGuiApplication::platformName() we could see if we need to cast that to a wl_surface* or xcb_window*. However, I don't see a way to retrieve the wl_display* using public API.

So for now, I'll leave the Qt backend. If you need RWH support, the use of the winit backend is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:backend-winit Winit backend (mS,mO) a:language-rust Rust API and codegen (mO,mS) enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants