api: make VideoModeHandle into VideoMode
The video mode is generally a static data and not a reference to some video mode. This changes the exclusive fullscreen API to match that an accept a monitor now.
This commit is contained in:
parent
5462f27dda
commit
ee245c569d
28 changed files with 247 additions and 475 deletions
|
|
@ -4,7 +4,6 @@
|
|||
compile_error!("Please select a feature to build for unix: `x11`, `wayland`");
|
||||
|
||||
use std::env;
|
||||
use std::num::{NonZeroU16, NonZeroU32};
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
||||
use std::time::Duration;
|
||||
#[cfg(x11_platform)]
|
||||
|
|
@ -17,13 +16,14 @@ pub(crate) use self::common::xkb::{physicalkey_to_scancode, scancode_to_physical
|
|||
use self::x11::{XConnection, XError, XNotSupported};
|
||||
use crate::application::ApplicationHandler;
|
||||
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
#[cfg(x11_platform)]
|
||||
use crate::dpi::Size;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::error::{EventLoopError, NotSupportedError};
|
||||
use crate::event_loop::ActiveEventLoop;
|
||||
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
|
||||
use crate::keyboard::Key;
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
#[cfg(x11_platform)]
|
||||
use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook};
|
||||
|
|
@ -165,46 +165,16 @@ impl MonitorHandle {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.current_video_mode())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> Box<dyn Iterator<Item = VideoModeHandle>> {
|
||||
pub fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => Box::new(m.video_modes()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum VideoModeHandle {
|
||||
#[cfg(x11_platform)]
|
||||
X(x11::VideoModeHandle),
|
||||
#[cfg(wayland_platform)]
|
||||
Wayland(wayland::VideoModeHandle),
|
||||
}
|
||||
|
||||
impl VideoModeHandle {
|
||||
#[inline]
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
x11_or_wayland!(match self; VideoModeHandle(m) => m.size())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bit_depth(&self) -> Option<NonZeroU16> {
|
||||
x11_or_wayland!(match self; VideoModeHandle(m) => m.bit_depth())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
x11_or_wayland!(match self; VideoModeHandle(m) => m.refresh_rate_millihertz())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn monitor(&self) -> MonitorHandle {
|
||||
x11_or_wayland!(match self; VideoModeHandle(m) => m.monitor(); as MonitorHandle)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct KeyEventExtra {
|
||||
pub text_with_all_modifiers: Option<SmolStr>,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! Winit's Wayland backend.
|
||||
|
||||
pub use event_loop::{ActiveEventLoop, EventLoop};
|
||||
pub use output::{MonitorHandle, VideoModeHandle};
|
||||
pub use output::MonitorHandle;
|
||||
use sctk::reexports::client::protocol::wl_surface::WlSurface;
|
||||
use sctk::reexports::client::Proxy;
|
||||
pub use window::Window;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::num::{NonZeroU16, NonZeroU32};
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use sctk::output::{Mode, OutputData};
|
||||
use sctk::reexports::client::protocol::wl_output::WlOutput;
|
||||
use sctk::reexports::client::Proxy;
|
||||
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::platform_impl::platform::VideoModeHandle as PlatformVideoModeHandle;
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition};
|
||||
use crate::monitor::VideoMode;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MonitorHandle {
|
||||
|
|
@ -54,27 +54,19 @@ impl MonitorHandle {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<PlatformVideoModeHandle> {
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
output_data.with_output_info(|info| {
|
||||
let mode = info.modes.iter().find(|mode| mode.current).cloned();
|
||||
|
||||
mode.map(|mode| {
|
||||
PlatformVideoModeHandle::Wayland(VideoModeHandle::new(self.clone(), mode))
|
||||
})
|
||||
mode.map(wayland_mode_to_core_mode)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = PlatformVideoModeHandle> {
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
let modes = output_data.with_output_info(|info| info.modes.clone());
|
||||
|
||||
let monitor = self.clone();
|
||||
|
||||
modes.into_iter().map(move |mode| {
|
||||
PlatformVideoModeHandle::Wayland(VideoModeHandle::new(monitor.clone(), mode))
|
||||
})
|
||||
modes.into_iter().map(wayland_mode_to_core_mode)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,38 +96,11 @@ impl std::hash::Hash for MonitorHandle {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct VideoModeHandle {
|
||||
pub(crate) size: PhysicalSize<u32>,
|
||||
pub(crate) refresh_rate_millihertz: Option<NonZeroU32>,
|
||||
pub(crate) monitor: MonitorHandle,
|
||||
}
|
||||
|
||||
impl VideoModeHandle {
|
||||
fn new(monitor: MonitorHandle, mode: Mode) -> Self {
|
||||
VideoModeHandle {
|
||||
size: (mode.dimensions.0 as u32, mode.dimensions.1 as u32).into(),
|
||||
refresh_rate_millihertz: NonZeroU32::new(mode.refresh_rate as u32),
|
||||
monitor: monitor.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
self.size
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bit_depth(&self) -> Option<NonZeroU16> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
self.refresh_rate_millihertz
|
||||
}
|
||||
|
||||
pub fn monitor(&self) -> MonitorHandle {
|
||||
self.monitor.clone()
|
||||
/// Convert Wayland's [`Mode`] to winit's [`VideoMode`].
|
||||
fn wayland_mode_to_core_mode(mode: Mode) -> VideoMode {
|
||||
VideoMode {
|
||||
size: (mode.dimensions.0, mode.dimensions.1).into(),
|
||||
bit_depth: None,
|
||||
refresh_rate_millihertz: NonZeroU32::new(mode.refresh_rate as u32),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ impl Window {
|
|||
|
||||
// Set startup mode.
|
||||
match attributes.fullscreen.map(Into::into) {
|
||||
Some(Fullscreen::Exclusive(_)) => {
|
||||
Some(Fullscreen::Exclusive(..)) => {
|
||||
warn!("`Fullscreen::Exclusive` is ignored on Wayland");
|
||||
},
|
||||
#[cfg_attr(not(x11_platform), allow(clippy::bind_instead_of_map))]
|
||||
|
|
@ -438,7 +438,7 @@ impl CoreWindow for Window {
|
|||
|
||||
fn set_fullscreen(&self, fullscreen: Option<CoreFullscreen>) {
|
||||
match fullscreen {
|
||||
Some(CoreFullscreen::Exclusive(_)) => {
|
||||
Some(CoreFullscreen::Exclusive(..)) => {
|
||||
warn!("`Fullscreen::Exclusive` is ignored on Wayland");
|
||||
},
|
||||
#[cfg_attr(not(x11_platform), allow(clippy::bind_instead_of_map))]
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use std::num::{NonZeroU16, NonZeroU32};
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use x11rb::connection::RequestConnection;
|
||||
use x11rb::protocol::randr::{self, ConnectionExt as _};
|
||||
use x11rb::protocol::xproto;
|
||||
|
||||
use super::{util, X11Error, XConnection};
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::platform_impl::VideoModeHandle as PlatformVideoModeHandle;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::monitor::VideoMode;
|
||||
|
||||
// Used for testing. This should always be committed as false.
|
||||
const DISABLE_MONITOR_LIST_CACHING: bool = false;
|
||||
|
|
@ -21,32 +21,14 @@ impl XConnection {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct VideoModeHandle {
|
||||
pub(crate) current: bool,
|
||||
pub(crate) size: (u32, u32),
|
||||
pub(crate) bit_depth: Option<NonZeroU16>,
|
||||
pub(crate) refresh_rate_millihertz: Option<NonZeroU32>,
|
||||
pub(crate) mode: VideoMode,
|
||||
pub(crate) native_mode: randr::Mode,
|
||||
pub(crate) monitor: Option<MonitorHandle>,
|
||||
}
|
||||
|
||||
impl VideoModeHandle {
|
||||
#[inline]
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
self.size.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bit_depth(&self) -> Option<NonZeroU16> {
|
||||
self.bit_depth
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
self.refresh_rate_millihertz
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn monitor(&self) -> MonitorHandle {
|
||||
self.monitor.clone().unwrap()
|
||||
impl From<VideoModeHandle> for VideoMode {
|
||||
fn from(handle: VideoModeHandle) -> Self {
|
||||
handle.mode
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +47,7 @@ pub struct MonitorHandle {
|
|||
/// Used to determine which windows are on this monitor
|
||||
pub(crate) rect: util::AaRect,
|
||||
/// Supported video modes on this monitor
|
||||
video_modes: Vec<VideoModeHandle>,
|
||||
pub(crate) video_modes: Vec<VideoModeHandle>,
|
||||
}
|
||||
|
||||
impl PartialEq for MonitorHandle {
|
||||
|
|
@ -159,17 +141,13 @@ impl MonitorHandle {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<PlatformVideoModeHandle> {
|
||||
self.video_modes.iter().find(|mode| mode.current).cloned().map(PlatformVideoModeHandle::X)
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
self.video_modes.iter().find(|mode| mode.current).cloned().map(Into::into)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = PlatformVideoModeHandle> {
|
||||
let monitor = self.clone();
|
||||
self.video_modes.clone().into_iter().map(move |mut x| {
|
||||
x.monitor = Some(monitor.clone());
|
||||
PlatformVideoModeHandle::X(x)
|
||||
})
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
self.video_modes.clone().into_iter().map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use x11rb::protocol::randr::{self, ConnectionExt as _};
|
|||
|
||||
use super::*;
|
||||
use crate::dpi::validate_scale_factor;
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::platform_impl::platform::x11::{monitor, VideoModeHandle};
|
||||
|
||||
/// Represents values of `WINIT_HIDPI_FACTOR`.
|
||||
|
|
@ -85,9 +86,11 @@ impl XConnection {
|
|||
.map(|mode| {
|
||||
VideoModeHandle {
|
||||
current: mode.id == current_mode,
|
||||
size: (mode.width.into(), mode.height.into()),
|
||||
refresh_rate_millihertz: monitor::mode_refresh_rate_millihertz(mode),
|
||||
bit_depth: NonZeroU16::new(bit_depth as u16),
|
||||
mode: VideoMode {
|
||||
size: (mode.width as u32, mode.height as u32).into(),
|
||||
refresh_rate_millihertz: monitor::mode_refresh_rate_millihertz(mode),
|
||||
bit_depth: NonZeroU16::new(bit_depth as u16),
|
||||
},
|
||||
native_mode: mode.id,
|
||||
// This is populated in `MonitorHandle::video_modes` as the
|
||||
// video mode is returned to the user
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ use crate::platform_impl::x11::{
|
|||
};
|
||||
use crate::platform_impl::{
|
||||
common, Fullscreen, MonitorHandle as PlatformMonitorHandle, PlatformCustomCursor, PlatformIcon,
|
||||
VideoModeHandle as PlatformVideoModeHandle,
|
||||
};
|
||||
use crate::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
|
||||
|
|
@ -327,7 +326,7 @@ impl Drop for Window {
|
|||
let xconn = &window.xconn;
|
||||
|
||||
// Restore the video mode on drop.
|
||||
if let Some(Fullscreen::Exclusive(_)) = window.fullscreen() {
|
||||
if let Some(Fullscreen::Exclusive(..)) = window.fullscreen() {
|
||||
window.set_fullscreen(None);
|
||||
}
|
||||
|
||||
|
|
@ -1035,20 +1034,17 @@ impl UnownedWindow {
|
|||
// fullscreen, so we can restore it upon exit, as XRandR does not
|
||||
// provide a mechanism to set this per app-session or restore this
|
||||
// to the desktop video mode as macOS and Windows do
|
||||
(&None, &Some(Fullscreen::Exclusive(PlatformVideoModeHandle::X(ref video_mode))))
|
||||
| (
|
||||
&Some(Fullscreen::Borderless(_)),
|
||||
&Some(Fullscreen::Exclusive(PlatformVideoModeHandle::X(ref video_mode))),
|
||||
) => {
|
||||
let monitor = video_mode.monitor.as_ref().unwrap();
|
||||
(&None, &Some(Fullscreen::Exclusive(ref monitor, _)))
|
||||
| (&Some(Fullscreen::Borderless(_)), &Some(Fullscreen::Exclusive(ref monitor, _))) => {
|
||||
let id = monitor.native_identifier();
|
||||
shared_state_lock.desktop_video_mode = Some((
|
||||
monitor.id,
|
||||
self.xconn.get_crtc_mode(monitor.id).expect("Failed to get desktop video mode"),
|
||||
id,
|
||||
self.xconn.get_crtc_mode(id).expect("Failed to get desktop video mode"),
|
||||
));
|
||||
},
|
||||
// Restore desktop video mode upon exiting exclusive fullscreen
|
||||
(&Some(Fullscreen::Exclusive(_)), &None)
|
||||
| (&Some(Fullscreen::Exclusive(_)), &Some(Fullscreen::Borderless(_))) => {
|
||||
(&Some(Fullscreen::Exclusive(..)), &None)
|
||||
| (&Some(Fullscreen::Exclusive(..)), &Some(Fullscreen::Borderless(_))) => {
|
||||
let (monitor_id, mode_id) = shared_state_lock.desktop_video_mode.take().unwrap();
|
||||
self.xconn
|
||||
.set_crtc_config(monitor_id, mode_id)
|
||||
|
|
@ -1072,8 +1068,8 @@ impl UnownedWindow {
|
|||
},
|
||||
Some(fullscreen) => {
|
||||
let (video_mode, monitor) = match fullscreen {
|
||||
Fullscreen::Exclusive(PlatformVideoModeHandle::X(ref video_mode)) => {
|
||||
(Some(video_mode), video_mode.monitor.clone().unwrap())
|
||||
Fullscreen::Exclusive(PlatformMonitorHandle::X(monitor), video_mode) => {
|
||||
(Some(video_mode), monitor.clone())
|
||||
},
|
||||
Fullscreen::Borderless(Some(PlatformMonitorHandle::X(monitor))) => {
|
||||
(None, monitor)
|
||||
|
|
@ -1090,7 +1086,15 @@ impl UnownedWindow {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Some(video_mode) = video_mode {
|
||||
if let Some(native_mode) = video_mode.and_then(|requested| {
|
||||
monitor.video_modes.iter().find_map(|mode| {
|
||||
if mode.mode == requested {
|
||||
Some(mode.native_mode)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}) {
|
||||
// FIXME: this is actually not correct if we're setting the
|
||||
// video mode to a resolution higher than the current
|
||||
// desktop resolution, because XRandR does not automatically
|
||||
|
|
@ -1117,7 +1121,7 @@ impl UnownedWindow {
|
|||
// this will make someone unhappy, but it's very unusual for
|
||||
// games to want to do this anyway).
|
||||
self.xconn
|
||||
.set_crtc_config(monitor.id, video_mode.native_mode)
|
||||
.set_crtc_config(monitor.id, native_mode)
|
||||
.expect("failed to set video mode");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue