Skip to content

Commit

Permalink
Add an OwnedDisplayHandle type
Browse files Browse the repository at this point in the history
This makes glutin integration much easier.
  • Loading branch information
notgull committed Jul 15, 2023
1 parent a359acc commit 0fd050e
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 5 deletions.
51 changes: 51 additions & 0 deletions src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,16 @@ impl<T> EventLoopWindowTarget<T> {
#[cfg(any(x11_platform, wasm_platform, wayland_platform, windows))]
self.p.listen_device_events(_allowed);
}

/// Get an [`OwnedDisplayHandle`] that keeps the underlying display handle alive.
///
/// This is necessary to use the display handle outside of the event loop, for example for
/// OpenGL setup.
pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle {
p: self.p.owned_display_handle(),
}
}
}

unsafe impl<T> HasRawDisplayHandle for EventLoopWindowTarget<T> {
Expand Down Expand Up @@ -419,6 +429,47 @@ unsafe impl<T> raw_window_handle_05::HasRawDisplayHandle for EventLoopWindowTarg
}
}

/// An owned handle used to represent the underlying display.
///
/// It is sometimes necessary to pass a display handle to a function without involving any
/// windows. This comes in play, for example, for OpenGL setup. However, it is impossible to hold
/// a reliable reference to the [`EventLoop`] or an [`EventLoopWindowTarget`] while the event loop
/// is running. This type aims to fill that gap by being a generic-free, cheaply clonable handle
/// representing the display server.
///
/// If you already have a [`Window`], you can get a display handle from it instead of this.
///
/// [`Window`]: crate::window::Window
#[derive(Clone)]
pub struct OwnedDisplayHandle {
p: platform_impl::OwnedDisplayHandle,
}

unsafe impl HasRawDisplayHandle for OwnedDisplayHandle {
fn raw_display_handle(&self) -> Result<RawDisplayHandle, HandleError> {
Ok(self.p.raw_display_handle())
}
}

impl HasDisplayHandle for OwnedDisplayHandle {
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
// SAFETY: The returned display handle is always valid for this lifetime.
self.raw_display_handle()
.map(|handle| unsafe { DisplayHandle::borrow_raw(handle) })
}
}

unsafe impl raw_window_handle_05::HasRawDisplayHandle for OwnedDisplayHandle {
fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle {
let result = HasRawDisplayHandle::raw_display_handle(self);

match result {
Ok(handle) => cvt_rdh_06_to_05(handle),
Err(e) => panic!("Failed to get raw display handle: {:?}", e),
}
}
}

/// Used to send custom events to [`EventLoop`].
pub struct EventLoopProxy<T: 'static> {
event_loop_proxy: platform_impl::EventLoopProxy<T>,
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,19 @@ impl<T: 'static> EventLoopWindowTarget<T> {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::Android(AndroidDisplayHandle::empty())
}

pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
}

#[derive(Clone)]
pub struct OwnedDisplayHandle;

impl OwnedDisplayHandle {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::Android(AndroidDisplayHandle::empty())
}
}

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/ios/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,25 @@ impl<T: 'static> EventLoopWindowTarget<T> {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::UiKit(UiKitDisplayHandle::empty())
}

pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
}

pub struct EventLoop<T: 'static> {
window_target: RootEventLoopWindowTarget<T>,
}

#[derive(Clone)]
pub struct OwnedDisplayHandle;

impl OwnedDisplayHandle {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::UiKit(UiKitDisplayHandle::empty())
}
}

#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub(crate) struct PlatformSpecificEventLoopAttributes {}

Expand Down
3 changes: 2 additions & 1 deletion src/platform_impl/ios/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ use std::fmt;

pub(crate) use self::{
event_loop::{
EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes,
EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle,
PlatformSpecificEventLoopAttributes,
},
monitor::{MonitorHandle, VideoMode},
window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId},
Expand Down
43 changes: 43 additions & 0 deletions src/platform_impl/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,14 @@ pub enum EventLoop<T: 'static> {
X(x11::EventLoop<T>),
}

#[derive(Clone)]
pub(crate) enum OwnedDisplayHandle {
#[cfg(wayland_platform)]
Wayland(wayland_client::Connection),
#[cfg(x11_platform)]
X(Arc<x11::XConnection>),
}

pub enum EventLoopProxy<T: 'static> {
#[cfg(x11_platform)]
X(x11::EventLoopProxy<T>),
Expand Down Expand Up @@ -904,6 +912,41 @@ impl<T> EventLoopWindowTarget<T> {
pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle())
}

pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
match self {
#[cfg(wayland_platform)]
EventLoopWindowTarget::Wayland(ref evlp) => {
OwnedDisplayHandle::Wayland(evlp.display().clone())
}

#[cfg(x11_platform)]
EventLoopWindowTarget::X(ref evlp) => {
OwnedDisplayHandle::X(evlp.x_connection().clone())
}
}
}
}

impl OwnedDisplayHandle {
pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
match self {
#[cfg(wayland_platform)]
OwnedDisplayHandle::Wayland(ref conn) => {
use wayland_client::Proxy;

let mut handle = raw_window_handle::WaylandDisplayHandle::empty();
handle.display = conn.display().id().as_ptr().cast();
handle.into()
}
#[cfg(x11_platform)]
OwnedDisplayHandle::X(ref conn) => {
let mut handle = raw_window_handle::XlibDisplayHandle::empty();
handle.display = conn.display as *mut _;
handle.into()
}
}
}
}

fn sticky_exit_callback<T, F>(
Expand Down
4 changes: 4 additions & 0 deletions src/platform_impl/linux/wayland/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ impl<T> EventLoopWindowTarget<T> {
display_handle.display = self.connection.display().id().as_ptr() as *mut _;
RawDisplayHandle::Wayland(display_handle)
}

pub fn display(&self) -> &Connection {
&self.connection
}
}

// The default routine does floor, but we need round on Wayland.
Expand Down
14 changes: 14 additions & 0 deletions src/platform_impl/macos/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ impl<T: 'static> EventLoopWindowTarget<T> {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::AppKit(AppKitDisplayHandle::empty())
}

#[inline]
pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
}

impl<T> EventLoopWindowTarget<T> {
Expand All @@ -111,6 +116,15 @@ impl<T> EventLoopWindowTarget<T> {
}
}

#[derive(Clone)]
pub struct OwnedDisplayHandle;

impl OwnedDisplayHandle {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::AppKit(AppKitDisplayHandle::empty())
}
}

pub struct EventLoop<T: 'static> {
/// The delegate is only weakly referenced by NSApplication, so we keep
/// it around here as well.
Expand Down
3 changes: 2 additions & 1 deletion src/platform_impl/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use self::window_delegate::WinitWindowDelegate;
pub(crate) use self::{
event::KeyEventExtra,
event_loop::{
EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes,
EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle,
PlatformSpecificEventLoopAttributes,
},
monitor::{MonitorHandle, VideoMode},
window::{PlatformSpecificWindowBuilderAttributes, WindowId},
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/orbital/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -763,4 +763,17 @@ impl<T: 'static> EventLoopWindowTarget<T> {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty())
}

pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
}

#[derive(Clone)]
pub struct OwnedDisplayHandle;

impl OwnedDisplayHandle {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty())
}
}
2 changes: 1 addition & 1 deletion src/platform_impl/web/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod state;
mod window_target;

pub use self::proxy::EventLoopProxy;
pub use self::window_target::EventLoopWindowTarget;
pub use self::window_target::{EventLoopWindowTarget, OwnedDisplayHandle};

use super::{backend, device, window};
use crate::event::Event;
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/web/event_loop/window_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,4 +753,17 @@ impl<T> EventLoopWindowTarget<T> {
pub fn listen_device_events(&self, allowed: DeviceEvents) {
self.runner.listen_device_events(allowed)
}

pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
}

#[derive(Clone)]
pub struct OwnedDisplayHandle;

impl OwnedDisplayHandle {
pub(crate) fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
raw_window_handle::WebDisplayHandle::empty().into()
}
}
3 changes: 2 additions & 1 deletion src/platform_impl/web/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ mod backend;
pub use self::device::DeviceId;
pub use self::error::OsError;
pub(crate) use self::event_loop::{
EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes,
EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle,
PlatformSpecificEventLoopAttributes,
};
pub use self::monitor::{MonitorHandle, VideoMode};
pub use self::window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId};
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ pub struct EventLoopWindowTarget<T: 'static> {
pub(crate) runner_shared: EventLoopRunnerShared<T>,
}

#[derive(Clone)]
pub struct OwnedDisplayHandle;

impl<T: 'static> EventLoop<T> {
pub(crate) fn new(attributes: &mut PlatformSpecificEventLoopAttributes) -> Self {
let thread_id = unsafe { GetCurrentThreadId() };
Expand Down Expand Up @@ -348,6 +351,16 @@ impl<T> EventLoopWindowTarget<T> {
pub fn listen_device_events(&self, allowed: DeviceEvents) {
raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, allowed);
}

pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
}

impl OwnedDisplayHandle {
pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
raw_window_handle::WindowsDisplayHandle::empty().into()
}
}

/// Returns the id of the main thread.
Expand Down
3 changes: 2 additions & 1 deletion src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use windows_sys::Win32::{

pub(crate) use self::{
event_loop::{
EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes,
EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle,
PlatformSpecificEventLoopAttributes,
},
icon::WinIcon,
monitor::{MonitorHandle, VideoMode},
Expand Down

0 comments on commit 0fd050e

Please sign in to comment.