winit-core: move window

Create `WindowAttributes` for respective platform specific window
attributes in `winit` due to move of `WindowAttributes`.
This commit is contained in:
Kirill Chibisov 2025-05-03 18:24:44 +09:00
parent c8b9a86885
commit b4c5b76155
48 changed files with 843 additions and 808 deletions

View file

@ -18,6 +18,7 @@ use sctk::reexports::client::{globals, Connection, QueueHandle};
use tracing::warn;
use crate::application::ApplicationHandler;
use crate::cursor::{CustomCursor as CoreCustomCursor, CustomCursorSource};
use crate::dpi::LogicalSize;
use crate::error::{EventLoopError, NotSupportedError, OsError, RequestError};
use crate::event::{DeviceEvent, StartCause, SurfaceSizeWriter, WindowEvent};
@ -29,7 +30,7 @@ use crate::monitor::MonitorHandle as CoreMonitorHandle;
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::platform::min_timeout;
use crate::platform_impl::wayland::types::cursor::WaylandCustomCursor;
use crate::window::{CustomCursor as CoreCustomCursor, CustomCursorSource, Theme};
use crate::window::Theme;
mod proxy;
pub mod sink;

View file

@ -163,9 +163,9 @@ pub trait ZwpTextInputV3Ext {
impl ZwpTextInputV3Ext for ZwpTextInputV3 {
fn set_content_type_by_purpose(&self, purpose: ImePurpose) {
let (hint, purpose) = match purpose {
ImePurpose::Normal => (ContentHint::None, ContentPurpose::Normal),
ImePurpose::Password => (ContentHint::SensitiveData, ContentPurpose::Password),
ImePurpose::Terminal => (ContentHint::None, ContentPurpose::Terminal),
_ => (ContentHint::None, ContentPurpose::Normal),
};
self.set_content_type(hint, purpose);
}

View file

@ -19,15 +19,17 @@ use super::output::MonitorHandle;
use super::state::WinitState;
use super::types::xdg_activation::XdgActivationTokenData;
use super::ActiveEventLoop;
use crate::cursor::Cursor;
use crate::dpi::{LogicalSize, PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{NotSupportedError, RequestError};
use crate::event::{Ime, WindowEvent};
use crate::event_loop::AsyncRequestSerial;
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
use crate::platform::wayland::WindowAttributesWayland;
use crate::platform_impl::wayland::output;
use crate::window::{
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
Window as CoreWindow, WindowAttributes, WindowButtons, WindowId, WindowLevel,
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
WindowAttributes, WindowButtons, WindowId, WindowLevel,
};
pub(crate) mod state;
@ -78,7 +80,7 @@ pub struct Window {
impl Window {
pub(crate) fn new(
event_loop_window_target: &ActiveEventLoop,
attributes: WindowAttributes,
mut attributes: WindowAttributes,
) -> Result<Self, RequestError> {
let queue_handle = event_loop_window_target.queue_handle.clone();
let mut state = event_loop_window_target.state.borrow_mut();
@ -121,8 +123,15 @@ impl Window {
// Set the decorations hint.
window_state.set_decorate(attributes.decorations);
let (app_name, activation_token) =
match attributes.platform.take().and_then(|p| p.cast::<WindowAttributesWayland>().ok())
{
Some(attrs) => (attrs.name, attrs.activation_token),
None => (None, None),
};
// Set the app_id.
if let Some(name) = attributes.platform_specific.name.map(|name| name.general) {
if let Some(name) = app_name.map(|name| name.general) {
window.set_app_id(name);
}
@ -162,10 +171,8 @@ impl Window {
}
// Activate the window when the token is passed.
if let (Some(xdg_activation), Some(token)) =
(xdg_activation.as_ref(), attributes.platform_specific.activation_token)
{
xdg_activation.activate(token.token, &surface);
if let (Some(xdg_activation), Some(token)) = (xdg_activation.as_ref(), activation_token) {
xdg_activation.activate(token.into_raw(), &surface);
}
// XXX Do initial commit.
@ -497,7 +504,7 @@ impl CoreWindow for Window {
fn set_window_level(&self, _level: WindowLevel) {}
fn set_window_icon(&self, _window_icon: Option<crate::window::Icon>) {}
fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
#[inline]
fn set_ime_cursor_area(&self, position: Position, size: Size) {
@ -678,23 +685,3 @@ impl WindowRequests {
self.redraw_requested.swap(false, Ordering::Relaxed)
}
}
impl TryFrom<&str> for Theme {
type Error = ();
/// ```
/// use winit::window::Theme;
///
/// assert_eq!("dark".try_into(), Ok(Theme::Dark));
/// assert_eq!("lIghT".try_into(), Ok(Theme::Light));
/// ```
fn try_from(theme: &str) -> Result<Self, Self::Error> {
if theme.eq_ignore_ascii_case("dark") {
Ok(Self::Dark)
} else if theme.eq_ignore_ascii_case("light") {
Ok(Self::Light)
} else {
Err(())
}
}
}

View file

@ -28,7 +28,7 @@ use sctk::subcompositor::SubcompositorState;
use tracing::{info, warn};
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur;
use crate::cursor::CustomCursor as CoreCustomCursor;
use crate::cursor::{CursorIcon, CustomCursor as CoreCustomCursor};
use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Size};
use crate::error::{NotSupportedError, RequestError};
use crate::platform_impl::wayland::event_loop::OwnedDisplayHandle;
@ -41,7 +41,7 @@ use crate::platform_impl::wayland::types::cursor::{
CustomCursor, SelectedCursor, WaylandCustomCursor,
};
use crate::platform_impl::wayland::types::kwin_blur::KWinBlurManager;
use crate::window::{CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, WindowId};
use crate::window::{CursorGrabMode, ImePurpose, ResizeDirection, Theme, WindowId};
#[cfg(feature = "sctk-adwaita")]
pub type WinitFrame = sctk_adwaita::AdwaitaFrame<WinitState>;
@ -398,7 +398,7 @@ impl WindowState {
self.apply_on_pointer(|_, data| {
let serial = data.latest_button_serial();
let seat = data.seat();
xdg_toplevel.resize(seat, serial, direction.into());
xdg_toplevel.resize(seat, serial, resize_direction_to_xdg(direction));
});
Ok(())
@ -1148,18 +1148,16 @@ pub enum FrameCallbackState {
Received,
}
impl From<ResizeDirection> for XdgResizeEdge {
fn from(value: ResizeDirection) -> Self {
match value {
ResizeDirection::North => XdgResizeEdge::Top,
ResizeDirection::West => XdgResizeEdge::Left,
ResizeDirection::NorthWest => XdgResizeEdge::TopLeft,
ResizeDirection::NorthEast => XdgResizeEdge::TopRight,
ResizeDirection::East => XdgResizeEdge::Right,
ResizeDirection::SouthWest => XdgResizeEdge::BottomLeft,
ResizeDirection::SouthEast => XdgResizeEdge::BottomRight,
ResizeDirection::South => XdgResizeEdge::Bottom,
}
fn resize_direction_to_xdg(direction: ResizeDirection) -> XdgResizeEdge {
match direction {
ResizeDirection::North => XdgResizeEdge::Top,
ResizeDirection::West => XdgResizeEdge::Left,
ResizeDirection::NorthWest => XdgResizeEdge::TopLeft,
ResizeDirection::NorthEast => XdgResizeEdge::TopRight,
ResizeDirection::East => XdgResizeEdge::Right,
ResizeDirection::SouthWest => XdgResizeEdge::BottomLeft,
ResizeDirection::SouthEast => XdgResizeEdge::BottomRight,
ResizeDirection::South => XdgResizeEdge::Bottom,
}
}

View file

@ -23,6 +23,7 @@ use x11rb::x11_utils::X11Error as LogicalError;
use x11rb::xcb_ffi::ReplyOrIdError;
use crate::application::ApplicationHandler;
use crate::cursor::{CustomCursor as CoreCustomCursor, CustomCursorSource};
use crate::error::{EventLoopError, RequestError};
use crate::event::{DeviceId, StartCause, WindowEvent};
use crate::event_loop::{
@ -36,10 +37,7 @@ use crate::platform::x11::XlibErrorHook;
use crate::platform_impl::common::xkb::Context;
use crate::platform_impl::platform::min_timeout;
use crate::platform_impl::x11::window::Window;
use crate::window::{
CustomCursor as CoreCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
WindowAttributes, WindowId,
};
use crate::window::{Theme, Window as CoreWindow, WindowAttributes, WindowId};
mod activation;
mod atoms;

View file

@ -9,9 +9,8 @@ use x11rb::protocol::xproto;
use super::super::ActiveEventLoop;
use super::*;
use crate::cursor::{CustomCursorProvider, CustomCursorSource};
use crate::cursor::{CursorIcon, CustomCursorProvider, CustomCursorSource};
use crate::error::{NotSupportedError, RequestError};
use crate::window::CursorIcon;
impl XConnection {
pub fn set_cursor_icon(

View file

@ -32,7 +32,7 @@ use crate::icon::RgbaIcon;
use crate::monitor::{
Fullscreen, MonitorHandle as CoreMonitorHandle, MonitorHandleProvider, VideoMode,
};
use crate::platform::x11::WindowType;
use crate::platform::x11::{WindowAttributesX11, WindowType};
use crate::platform_impl::common;
use crate::platform_impl::x11::atoms::*;
use crate::platform_impl::x11::util::rgba_to_cardinals;
@ -204,7 +204,7 @@ impl CoreWindow for Window {
self.0.set_window_level(level);
}
fn set_window_icon(&self, window_icon: Option<crate::window::Icon>) {
fn set_window_icon(&self, window_icon: Option<crate::icon::Icon>) {
let icon = match window_icon.as_ref() {
Some(icon) => icon.cast_ref::<RgbaIcon>(),
None => None,
@ -443,12 +443,18 @@ impl UnownedWindow {
#[allow(clippy::unnecessary_cast)]
pub(crate) fn new(
event_loop: &ActiveEventLoop,
window_attrs: WindowAttributes,
mut window_attrs: WindowAttributes,
) -> Result<UnownedWindow, RequestError> {
let xconn = &event_loop.xconn;
let atoms = xconn.atoms();
let screen_id = match window_attrs.platform_specific.x11.screen_id {
let x11_attributes = window_attrs
.platform
.take()
.and_then(|attrs| attrs.cast::<WindowAttributesX11>().ok())
.unwrap_or_default();
let screen_id = match x11_attributes.screen_id {
Some(id) => id,
None => xconn.default_screen_index() as c_int,
};
@ -461,7 +467,7 @@ impl UnownedWindow {
)?
};
let root = match window_attrs.parent_window.as_ref().map(|handle| handle.0) {
let root = match window_attrs.parent_window() {
Some(rwh_06::RawWindowHandle::Xlib(handle)) => handle.window as xproto::Window,
Some(rwh_06::RawWindowHandle::Xcb(handle)) => handle.window.get(),
Some(raw) => unreachable!("Invalid raw window handle {raw:?} on X11"),
@ -528,33 +534,32 @@ impl UnownedWindow {
.flat_map(|depth| depth.visuals.iter().map(move |visual| (visual, depth.depth)));
// creating
let (visualtype, depth, require_colormap) =
match window_attrs.platform_specific.x11.visual_id {
Some(vi) => {
// Find this specific visual.
let (visualtype, depth) = all_visuals
.find(|(visual, _)| visual.visual_id == vi)
.ok_or_else(|| os_error!(X11Error::NoSuchVisual(vi)))?;
let (visualtype, depth, require_colormap) = match x11_attributes.visual_id {
Some(vi) => {
// Find this specific visual.
let (visualtype, depth) = all_visuals
.find(|(visual, _)| visual.visual_id == vi)
.ok_or_else(|| os_error!(X11Error::NoSuchVisual(vi)))?;
(Some(visualtype), depth, true)
},
None if window_attrs.transparent => {
// Find a suitable visual, true color with 32 bits of depth.
all_visuals
.find_map(|(visual, depth)| {
(depth == 32 && visual.class == xproto::VisualClass::TRUE_COLOR)
.then_some((Some(visual), depth, true))
})
.unwrap_or_else(|| {
debug!(
"Could not set transparency, because XMatchVisualInfo returned \
zero for the required parameters"
);
(None as _, x11rb::COPY_FROM_PARENT as _, false)
})
},
_ => (None, x11rb::COPY_FROM_PARENT as _, false),
};
(Some(visualtype), depth, true)
},
None if window_attrs.transparent => {
// Find a suitable visual, true color with 32 bits of depth.
all_visuals
.find_map(|(visual, depth)| {
(depth == 32 && visual.class == xproto::VisualClass::TRUE_COLOR)
.then_some((Some(visual), depth, true))
})
.unwrap_or_else(|| {
debug!(
"Could not set transparency, because XMatchVisualInfo returned zero \
for the required parameters"
);
(None as _, x11rb::COPY_FROM_PARENT as _, false)
})
},
_ => (None, x11rb::COPY_FROM_PARENT as _, false),
};
let mut visual = visualtype.map_or(x11rb::COPY_FROM_PARENT, |v| v.visual_id);
let window_attributes = {
@ -574,12 +579,12 @@ impl UnownedWindow {
aux = aux.event_mask(event_mask).border_pixel(0);
if window_attrs.platform_specific.x11.override_redirect {
if x11_attributes.override_redirect {
aux = aux.override_redirect(true as u32);
}
// Add a colormap if needed.
let colormap_visual = match window_attrs.platform_specific.x11.visual_id {
let colormap_visual = match x11_attributes.visual_id {
Some(vi) => Some(vi),
None if require_colormap => Some(visual),
_ => None,
@ -602,7 +607,7 @@ impl UnownedWindow {
};
// Figure out the window's parent.
let parent = window_attrs.platform_specific.x11.embed_window.unwrap_or(root);
let parent = x11_attributes.embed_window.unwrap_or(root);
// finally creating the window
let xwindow = {
@ -665,7 +670,7 @@ impl UnownedWindow {
}
// Embed the window if needed.
if window_attrs.platform_specific.x11.embed_window.is_some() {
if x11_attributes.embed_window.is_some() {
window.embed_window()?;
}
@ -686,7 +691,7 @@ impl UnownedWindow {
// WM_CLASS must be set *before* mapping the window, as per ICCCM!
{
let (instance, class) = if let Some(name) = window_attrs.platform_specific.name {
let (instance, class) = if let Some(name) = x11_attributes.name {
(name.instance, name.general)
} else {
let class = env::args_os()
@ -717,8 +722,7 @@ impl UnownedWindow {
flusher.ignore_error()
}
leap!(window.set_window_types(window_attrs.platform_specific.x11.x11_window_types))
.ignore_error();
leap!(window.set_window_types(x11_attributes.x11_window_types)).ignore_error();
// Set size hints.
let mut min_surface_size =
@ -739,7 +743,7 @@ impl UnownedWindow {
shared_state.min_surface_size = min_surface_size.map(Into::into);
shared_state.max_surface_size = max_surface_size.map(Into::into);
shared_state.surface_resize_increments = window_attrs.surface_resize_increments;
shared_state.base_size = window_attrs.platform_specific.x11.base_size;
shared_state.base_size = x11_attributes.base_size;
let normal_hints = WmSizeHints {
position: position.map(|PhysicalPosition { x, y }| {
@ -755,9 +759,7 @@ impl UnownedWindow {
size_increment: window_attrs
.surface_resize_increments
.map(|size| cast_size_to_hint(size, scale_factor)),
base_size: window_attrs
.platform_specific
.x11
base_size: x11_attributes
.base_size
.map(|size| cast_size_to_hint(size, scale_factor)),
aspect: None,
@ -884,8 +886,8 @@ impl UnownedWindow {
window.set_cursor(window_attrs.cursor);
// Remove the startup notification if we have one.
if let Some(startup) = window_attrs.platform_specific.activation_token.as_ref() {
leap!(xconn.remove_activation_token(xwindow, &startup.token));
if let Some(startup) = x11_attributes.activation_token.as_ref() {
leap!(xconn.remove_activation_token(xwindow, startup.as_raw()));
}
// We never want to give the user a broken window, since by then, it's too late to handle.

View file

@ -16,7 +16,7 @@ use x11rb::xcb_ffi::XCBConnection;
use super::atoms::Atoms;
use super::ffi;
use super::monitor::MonitorHandle;
use crate::window::CursorIcon;
use crate::cursor::CursorIcon;
/// A connection to an X server.
pub struct XConnection {