Skip to content

Commit

Permalink
Always display platform-specific documentation, regardless of target
Browse files Browse the repository at this point in the history
This required a few ugly hacks, such as making some #[doc(hidden)] empty structs on platforms where we expose some external dependency - but I tend to think that's a somewhat good thing, since it makes it more explicit that we have a public dependency here.
  • Loading branch information
madsmtm committed Dec 24, 2023
1 parent 1ce2e3d commit b4c5553
Show file tree
Hide file tree
Showing 18 changed files with 142 additions and 120 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Unreleased` header.

# Unreleased

- **Breaking:** No longer export `platform::x11::XNotSupported`.
- On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example.
- Add `Window::set_custom_cursor`
- Add `CustomCursor`
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ features = [
"rwh_05",
"rwh_06",
"serde",
"mint",
# Enabled to get docs to compile
"android-native-activity",
]
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,11 @@
#![deny(unsafe_op_in_unsafe_fn)]
#![cfg_attr(feature = "cargo-clippy", deny(warnings))]
// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(
docsrs,
feature(doc_auto_cfg, doc_cfg_hide),
doc(cfg_hide(doc, docsrs))
)]
#![allow(clippy::missing_safety_doc)]

#[cfg(feature = "rwh_06")]
Expand Down
13 changes: 12 additions & 1 deletion src/platform/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
window::{Window, WindowBuilder},
};

use android_activity::{AndroidApp, ConfigurationRef, Rect};
use self::activity::{AndroidApp, ConfigurationRef, Rect};

/// Additional methods on [`EventLoop`] that are specific to Android.
pub trait EventLoopExtAndroid {}
Expand Down Expand Up @@ -89,5 +89,16 @@ pub mod activity {
// feature enabled, so we avoid inlining it so that they're forced to view
// it on the crate's own docs.rs page.
#[doc(no_inline)]
#[cfg(android_platform)]
pub use android_activity::*;

#[cfg(all(not(android_platform), doc))]
#[doc(hidden)]
pub struct Rect(());
#[cfg(all(not(android_platform), doc))]
#[doc(hidden)]
pub struct ConfigurationRef(());
#[cfg(all(not(android_platform), doc))]
#[doc(hidden)]
pub struct AndroidApp(());
}
7 changes: 2 additions & 5 deletions src/platform/ios.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use std::os::raw::c_void;

use icrate::Foundation::MainThreadMarker;
use objc2::rc::Id;

use crate::{
event_loop::EventLoop,
monitor::{MonitorHandle, VideoMode},
Expand Down Expand Up @@ -240,8 +237,8 @@ impl MonitorHandleExtIOS for MonitorHandle {
#[inline]
fn ui_screen(&self) -> *mut c_void {
// SAFETY: The marker is only used to get the pointer of the screen
let mtm = unsafe { MainThreadMarker::new_unchecked() };
Id::as_ptr(self.inner.ui_screen(mtm)) as *mut c_void
let mtm = unsafe { icrate::Foundation::MainThreadMarker::new_unchecked() };
objc2::rc::Id::as_ptr(self.inner.ui_screen(mtm)) as *mut c_void
}

#[inline]
Expand Down
9 changes: 4 additions & 5 deletions src/platform/macos.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use std::os::raw::c_void;

use icrate::Foundation::MainThreadMarker;
use objc2::rc::Id;

use crate::{
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
monitor::MonitorHandle,
Expand Down Expand Up @@ -367,8 +364,10 @@ impl MonitorHandleExtMacOS for MonitorHandle {

fn ns_screen(&self) -> Option<*mut c_void> {
// SAFETY: We only use the marker to get a pointer
let mtm = unsafe { MainThreadMarker::new_unchecked() };
self.inner.ns_screen(mtm).map(|s| Id::as_ptr(&s) as _)
let mtm = unsafe { icrate::Foundation::MainThreadMarker::new_unchecked() };
self.inner
.ns_screen(mtm)
.map(|s| objc2::rc::Id::as_ptr(&s) as _)
}
}

Expand Down
55 changes: 29 additions & 26 deletions src/platform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,33 @@
//! Contains traits with platform-specific methods in them.
//!
//! Contains the follow OS-specific modules:
//!
//! - `android`
//! - `ios`
//! - `macos`
//! - `unix`
//! - `windows`
//! - `web`
//!
//! And the following platform-specific modules:
//!
//! - `run_on_demand` (available on `windows`, `unix`, `macos`, `android`)
//! - `pump_events` (available on `windows`, `unix`, `macos`, `android`)
//!
//! However only the module corresponding to the platform you're compiling to will be available.
//! Only the modules corresponding to the platform you're compiling to will be available.

#[cfg(android_platform)]
#[cfg(any(android_platform, all(docsrs, not(doctest))))]
pub mod android;
#[cfg(ios_platform)]
#[cfg(any(ios_platform, all(docsrs, not(doctest))))]
pub mod ios;
#[cfg(macos_platform)]
#[cfg(any(macos_platform, all(docsrs, not(doctest))))]
pub mod macos;
#[cfg(orbital_platform)]
#[cfg(any(orbital_platform, all(docsrs, not(doctest))))]
pub mod orbital;
#[cfg(any(x11_platform, wayland_platform))]
#[cfg(any(x11_platform, wayland_platform, all(docsrs, not(doctest))))]
pub mod startup_notify;
#[cfg(wayland_platform)]
#[cfg(any(wayland_platform, all(docsrs, not(doctest))))]
pub mod wayland;
#[cfg(wasm_platform)]
#[cfg(any(wasm_platform, all(docsrs, not(doctest))))]
pub mod web;
#[cfg(windows_platform)]
#[cfg(any(windows_platform, all(docsrs, not(doctest))))]
pub mod windows;
#[cfg(x11_platform)]
#[cfg(any(x11_platform, all(docsrs, not(doctest))))]
pub mod x11;

#[cfg(any(
windows_platform,
macos_platform,
android_platform,
x11_platform,
wayland_platform
wayland_platform,
all(docsrs, not(doctest)),
))]
pub mod run_on_demand;

Expand All @@ -49,9 +36,25 @@ pub mod run_on_demand;
macos_platform,
android_platform,
x11_platform,
wayland_platform
wayland_platform,
all(docsrs, not(doctest)),
))]
pub mod pump_events;

#[cfg(any(
windows_platform,
macos_platform,
x11_platform,
wayland_platform,
all(docsrs, not(doctest))
))]
pub mod modifier_supplement;

#[cfg(any(
windows_platform,
macos_platform,
x11_platform,
wayland_platform,
all(docsrs, not(doctest))
))]
pub mod scancode;
2 changes: 0 additions & 2 deletions src/platform/modifier_supplement.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform))]

use crate::event::KeyEvent;
use crate::keyboard::Key;

Expand Down
2 changes: 0 additions & 2 deletions src/platform/scancode.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform))]

use crate::keyboard::{KeyCode, PhysicalKey};

// TODO: Describe what this value contains for each platform
Expand Down
9 changes: 5 additions & 4 deletions src/platform/wayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use crate::{
window::{Window, WindowBuilder},
};

use crate::platform_impl::{ApplicationName, Backend};

pub use crate::window::Theme;

/// Additional methods on [`EventLoopWindowTarget`] that are specific to Wayland.
Expand Down Expand Up @@ -36,7 +34,7 @@ pub trait EventLoopBuilderExtWayland {
impl<T> EventLoopBuilderExtWayland for EventLoopBuilder<T> {
#[inline]
fn with_wayland(&mut self) -> &mut Self {
self.platform_specific.forced_backend = Some(Backend::Wayland);
self.platform_specific.forced_backend = Some(crate::platform_impl::Backend::Wayland);
self
}

Expand Down Expand Up @@ -67,7 +65,10 @@ pub trait WindowBuilderExtWayland {
impl WindowBuilderExtWayland for WindowBuilder {
#[inline]
fn with_name(mut self, general: impl Into<String>, instance: impl Into<String>) -> Self {
self.platform_specific.name = Some(ApplicationName::new(general.into(), instance.into()));
self.platform_specific.name = Some(crate::platform_impl::ApplicationName::new(
general.into(),
instance.into(),
));
self
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/platform/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ use crate::window::CustomCursor;
use crate::window::{Window, WindowBuilder};
use crate::SendSyncWrapper;

#[cfg(wasm_platform)]
use web_sys::HtmlCanvasElement;

#[cfg(all(not(wasm_platform), doc))]
#[doc(hidden)]
pub struct HtmlCanvasElement(());

pub trait WindowExtWebSys {
/// Only returns the canvas if called from inside the window.
fn canvas(&self) -> Option<HtmlCanvasElement>;
Expand Down
14 changes: 10 additions & 4 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
event::DeviceId,
event_loop::EventLoopBuilder,
monitor::MonitorHandle,
platform_impl::WinIcon,
window::{BadIcon, Icon, Window, WindowBuilder},
};

Expand Down Expand Up @@ -183,7 +182,14 @@ pub trait WindowBuilderExtWindows {
/// Note: Dark mode cannot be supported for win32 menus, it's simply not possible to change how the menus look.
/// If you use this, it is recommended that you combine it with `with_theme(Some(Theme::Light))` to avoid a jarring effect.
///
/// [`CreateMenu`]: windows_sys::Win32::UI::WindowsAndMessaging::CreateMenu
#[cfg_attr(
platform_windows,
doc = "[`CreateMenu`]: windows_sys::Win32::UI::WindowsAndMessaging::CreateMenu"
)]
#[cfg_attr(
not(platform_windows),
doc = "[`CreateMenu`]: #only-available-on-windows"
)]
fn with_menu(self, menu: HMENU) -> Self;

/// This sets `ICON_BIG`. A good ceiling here is 256x256.
Expand Down Expand Up @@ -326,12 +332,12 @@ impl IconExtWindows for Icon {
path: P,
size: Option<PhysicalSize<u32>>,
) -> Result<Self, BadIcon> {
let win_icon = WinIcon::from_path(path, size)?;
let win_icon = crate::platform_impl::WinIcon::from_path(path, size)?;
Ok(Icon { inner: win_icon })
}

fn from_resource(ordinal: u16, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon> {
let win_icon = WinIcon::from_resource(ordinal, size)?;
let win_icon = crate::platform_impl::WinIcon::from_resource(ordinal, size)?;
Ok(Icon { inner: win_icon })
}
}
67 changes: 57 additions & 10 deletions src/platform/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,50 @@ use crate::{
};

use crate::dpi::Size;
use crate::platform_impl::{ApplicationName, Backend, XLIB_ERROR_HOOKS};

pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported};
/// X window type. Maps directly to
/// [`_NET_WM_WINDOW_TYPE`](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html).
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum WindowType {
/// A desktop feature. This can include a single window containing desktop icons with the same dimensions as the
/// screen, allowing the desktop environment to have full control of the desktop, without the need for proxying
/// root window clicks.
Desktop,
/// A dock or panel feature. Typically a Window Manager would keep such windows on top of all other windows.
Dock,
/// Toolbar windows. "Torn off" from the main application.
Toolbar,
/// Pinnable menu windows. "Torn off" from the main application.
Menu,
/// A small persistent utility window, such as a palette or toolbox.
Utility,
/// The window is a splash screen displayed as an application is starting up.
Splash,
/// This is a dialog window.
Dialog,
/// A dropdown menu that usually appears when the user clicks on an item in a menu bar.
/// This property is typically used on override-redirect windows.
DropdownMenu,
/// A popup menu that usually appears when the user right clicks on an object.
/// This property is typically used on override-redirect windows.
PopupMenu,
/// A tooltip window. Usually used to show additional information when hovering over an object with the cursor.
/// This property is typically used on override-redirect windows.
Tooltip,
/// The window is a notification.
/// This property is typically used on override-redirect windows.
Notification,
/// This should be used on the windows that are popped up by combo boxes.
/// This property is typically used on override-redirect windows.
Combo,
/// This indicates the the window is being dragged.
/// This property is typically used on override-redirect windows.
Dnd,
/// This is a normal, top-level window.
#[default]
Normal,
}

/// The first argument in the provided hook will be the pointer to `XDisplay`
/// and the second one the pointer to [`XErrorEvent`]. The returned `bool` is an
Expand Down Expand Up @@ -38,7 +79,10 @@ pub type XWindow = u32;
pub fn register_xlib_error_hook(hook: XlibErrorHook) {
// Append new hook.
unsafe {
XLIB_ERROR_HOOKS.lock().unwrap().push(hook);
crate::platform_impl::XLIB_ERROR_HOOKS
.lock()
.unwrap()
.push(hook);
}
}

Expand Down Expand Up @@ -70,7 +114,7 @@ pub trait EventLoopBuilderExtX11 {
impl<T> EventLoopBuilderExtX11 for EventLoopBuilder<T> {
#[inline]
fn with_x11(&mut self) -> &mut Self {
self.platform_specific.forced_backend = Some(Backend::X);
self.platform_specific.forced_backend = Some(crate::platform_impl::Backend::X);
self
}

Expand Down Expand Up @@ -102,13 +146,13 @@ pub trait WindowBuilderExtX11 {
/// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id)
fn with_name(self, general: impl Into<String>, instance: impl Into<String>) -> Self;

/// Build window with override-redirect flag; defaults to false. Only relevant on X11.
/// Build window with override-redirect flag; defaults to false.
fn with_override_redirect(self, override_redirect: bool) -> Self;

/// Build window with `_NET_WM_WINDOW_TYPE` hints; defaults to `Normal`. Only relevant on X11.
fn with_x11_window_type(self, x11_window_type: Vec<XWindowType>) -> Self;
/// Build window with `_NET_WM_WINDOW_TYPE` hints; defaults to `Normal`.
fn with_x11_window_type(self, x11_window_type: Vec<WindowType>) -> Self;

/// Build window with base size hint. Only implemented on X11.
/// Build window with base size hint.
///
/// ```
/// # use winit::dpi::{LogicalSize, PhysicalSize};
Expand Down Expand Up @@ -155,7 +199,10 @@ impl WindowBuilderExtX11 for WindowBuilder {

#[inline]
fn with_name(mut self, general: impl Into<String>, instance: impl Into<String>) -> Self {
self.platform_specific.name = Some(ApplicationName::new(general.into(), instance.into()));
self.platform_specific.name = Some(crate::platform_impl::ApplicationName::new(
general.into(),
instance.into(),
));
self
}

Expand All @@ -166,7 +213,7 @@ impl WindowBuilderExtX11 for WindowBuilder {
}

#[inline]
fn with_x11_window_type(mut self, x11_window_types: Vec<XWindowType>) -> Self {
fn with_x11_window_type(mut self, x11_window_types: Vec<WindowType>) -> Self {
self.platform_specific.x11.x11_window_types = x11_window_types;
self
}
Expand Down
Loading

0 comments on commit b4c5553

Please sign in to comment.