Skip to content

Commit

Permalink
Replace EventLoopExtWindows with EventLoopBuilderExtWindows for ease …
Browse files Browse the repository at this point in the history
…of use
  • Loading branch information
madsmtm committed Jan 5, 2022
1 parent a21f8b1 commit f4a4ece
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 76 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
`EventLoopBuilder::with_user_event` instead.
- Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has
renamed methods).
- Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also
has renamed methods).

# 0.26.1 (2022-01-05)

Expand Down
76 changes: 36 additions & 40 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,61 @@ use winapi::shared::windef::{HMENU, HWND};
use crate::{
dpi::PhysicalSize,
event::DeviceId,
event_loop::EventLoop,
event_loop::EventLoopBuilder,
monitor::MonitorHandle,
platform_impl::{EventLoop as WindowsEventLoop, Parent, WinIcon},
platform_impl::{Parent, WinIcon},
window::{BadIcon, Icon, Theme, Window, WindowBuilder},
};

/// Additional methods on `EventLoop` that are specific to Windows.
pub trait EventLoopExtWindows {
/// Creates an event loop off of the main thread.
pub trait EventLoopBuilderExtWindows {
/// Whether to allow the event loop to be created off of the main thread.
///
/// By default, the window is only allowed to be created on the main
/// thread, to make platform compatibility easier.
///
/// # `Window` caveats
///
/// Note that any `Window` created on the new thread will be destroyed when the thread
/// terminates. Attempting to use a `Window` after its parent thread terminates has
/// unspecified, although explicitly not undefined, behavior.
fn new_any_thread() -> Self
where
Self: Sized;

/// By default, winit on Windows will attempt to enable process-wide DPI awareness. If that's
/// undesirable, you can create an `EventLoop` using this function instead.
fn new_dpi_unaware() -> Self
where
Self: Sized;
fn any_thread(&mut self, any_thread: bool) -> &mut Self;

/// Creates a DPI-unaware event loop off of the main thread.
/// Whether to enable process-wide DPI awareness.
///
/// By default, we will attempt to enable process-wide DPI awareness. If
/// that's undesirable, you can create disable it with this function.
///
/// # Example
///
/// Disable process-wide DPI awareness:
///
/// ```
/// use winit::event_loop::EventLoopBuilder;
/// #[cfg(target_os = "windows")]
/// use winit::platform::windows::EventLoopBuilderExtWindows;
///
/// The `Window` caveats in [`new_any_thread`](EventLoopExtWindows::new_any_thread) also apply here.
fn new_dpi_unaware_any_thread() -> Self
where
Self: Sized;
/// let mut builder = EventLoopBuilder::new();
/// #[cfg(target_os = "windows")]
/// builder.dpi_aware(false);
/// # if false { // We can't test this part
/// let event_loop = builder.build();
/// # }
/// ```
fn dpi_aware(&mut self, dpi_aware: bool) -> &mut Self;
}

impl<T> EventLoopExtWindows for EventLoop<T> {
impl<T> EventLoopBuilderExtWindows for EventLoopBuilder<T> {
#[inline]
fn new_any_thread() -> Self {
EventLoop {
// Temporary
event_loop: WindowsEventLoop::new_any_thread(&Default::default()),
_marker: ::std::marker::PhantomData,
}
}

#[inline]
fn new_dpi_unaware() -> Self {
EventLoop {
// Temporary
event_loop: WindowsEventLoop::new_dpi_unaware(&Default::default()),
_marker: ::std::marker::PhantomData,
}
fn any_thread(&mut self, any_thread: bool) -> &mut Self {
self.platform_specific.any_thread = any_thread;
self
}

#[inline]
fn new_dpi_unaware_any_thread() -> Self {
EventLoop {
// Temporary
event_loop: WindowsEventLoop::new_dpi_unaware_any_thread(&Default::default()),
_marker: ::std::marker::PhantomData,
}
fn dpi_aware(&mut self, dpi_aware: bool) -> &mut Self {
self.platform_specific.dpi_aware = dpi_aware;
self
}
}

Expand Down
61 changes: 25 additions & 36 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,54 +113,43 @@ pub struct EventLoop<T: 'static> {
window_target: RootELW<T>,
}

#[derive(Default, Debug, Copy, Clone, PartialEq, Hash)]
pub(crate) struct PlatformSpecificEventLoopAttributes {}
#[derive(Debug, Copy, Clone, PartialEq, Hash)]
pub(crate) struct PlatformSpecificEventLoopAttributes {
pub(crate) any_thread: bool,
pub(crate) dpi_aware: bool,
}

impl Default for PlatformSpecificEventLoopAttributes {
fn default() -> Self {
Self {
any_thread: false,
dpi_aware: true,
}
}
}

pub struct EventLoopWindowTarget<T: 'static> {
thread_id: DWORD,
thread_msg_target: HWND,
pub(crate) runner_shared: EventLoopRunnerShared<T>,
}

macro_rules! main_thread_check {
($fn_name:literal) => {{
impl<T: 'static> EventLoop<T> {
pub(crate) fn new(attributes: &PlatformSpecificEventLoopAttributes) -> Self {
let thread_id = unsafe { processthreadsapi::GetCurrentThreadId() };
if thread_id != main_thread_id() {
panic!(concat!(

if !attributes.any_thread && thread_id != main_thread_id() {
panic!(
"Initializing the event loop outside of the main thread is a significant \
cross-platform compatibility hazard. If you really, absolutely need to create an \
EventLoop on a different thread, please use the `EventLoopExtWindows::",
$fn_name,
"` function."
));
EventLoop on a different thread, you can use the \
`EventLoopBuilderExtWindows::any_thread` function."
);
}
}};
}

impl<T: 'static> EventLoop<T> {
pub(crate) fn new(attributes: &PlatformSpecificEventLoopAttributes) -> EventLoop<T> {
main_thread_check!("new_any_thread");

Self::new_any_thread(attributes)
}

pub(crate) fn new_any_thread(attributes: &PlatformSpecificEventLoopAttributes) -> EventLoop<T> {
become_dpi_aware();
Self::new_dpi_unaware_any_thread(attributes)
}

pub(crate) fn new_dpi_unaware(
attributes: &PlatformSpecificEventLoopAttributes,
) -> EventLoop<T> {
main_thread_check!("new_dpi_unaware_any_thread");

Self::new_dpi_unaware_any_thread(attributes)
}

pub(crate) fn new_dpi_unaware_any_thread(
_: &PlatformSpecificEventLoopAttributes,
) -> EventLoop<T> {
let thread_id = unsafe { processthreadsapi::GetCurrentThreadId() };
if attributes.dpi_aware {
become_dpi_aware();
}

let thread_msg_target = create_event_target_window::<T>();

Expand Down

0 comments on commit f4a4ece

Please sign in to comment.