mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 05:21:31 +11:00
Add WindowBuilder::with_parent_window
(#2548)
* On macOS, add `WindowBuilderExtMacOS::with_parent_window` * Replace Parent with Option<Id<NSWindow, Shared>> * Add addChildWindow method on NSWindow instead * Update with_parent_window to be unsafe fn * Add unified `with_parent_window` * Remove `WindowBuilderExtUnix::with_parent` * Remove `WindowBuilderExtWindows::with_parent_window` * Clean up CI warnings * Update CHANGELOG.md It's `WindowBuilderExtX11` rather than `WindowBuilderExtUnix` * Rename parent to owner * Make with_parent_window unsafe and update its doc * Add another way to get window on mac * Add more documentations * Add match arm and panic on invalid varients * Add Xcb arm * Update child_window example to make it safer and work in i686 * Remove duplicate entry in CHANGELOG.md * Propogate error instead of expect * Replace unreachable to panic * Add platform note to X11 Co-authored-by: Wu Yu Wei <wusyong9104@gmail.com>
This commit is contained in:
parent
8934d2765d
commit
da7422c6e1
|
@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
|
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
- **Breaking:** Removed platform specific `WindowBuilder::with_parent` API in favor of `WindowBuilder::with_parent_window`.
|
||||||
- On Windows, retain `WS_MAXIMIZE` window style when un-minimizing a maximized window.
|
- On Windows, retain `WS_MAXIMIZE` window style when un-minimizing a maximized window.
|
||||||
- On Windows, fix left mouse button release event not being sent after `Window::drag_window`.
|
- On Windows, fix left mouse button release event not being sent after `Window::drag_window`.
|
||||||
- On macOS, run most actions on the main thread, which is strictly more correct, but might make multithreaded applications block slightly more.
|
- On macOS, run most actions on the main thread, which is strictly more correct, but might make multithreaded applications block slightly more.
|
||||||
|
|
|
@ -1,37 +1,39 @@
|
||||||
#[cfg(all(target_os = "linux", feature = "x11"))]
|
#[cfg(any(
|
||||||
|
all(target_os = "linux", feature = "x11"),
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "windows"
|
||||||
|
))]
|
||||||
|
fn main() {
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", feature = "x11"))]
|
use raw_window_handle::HasRawWindowHandle;
|
||||||
use winit::{
|
use winit::{
|
||||||
dpi::{LogicalPosition, LogicalSize, Position},
|
dpi::{LogicalPosition, LogicalSize, Position},
|
||||||
event::{ElementState, Event, KeyboardInput, WindowEvent},
|
event::{ElementState, Event, KeyboardInput, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
|
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
|
||||||
platform::x11::{WindowBuilderExtX11, WindowExtX11},
|
|
||||||
window::{Window, WindowBuilder, WindowId},
|
window::{Window, WindowBuilder, WindowId},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", feature = "x11"))]
|
|
||||||
fn spawn_child_window(
|
fn spawn_child_window(
|
||||||
parent: u32,
|
parent: &Window,
|
||||||
event_loop: &EventLoopWindowTarget<()>,
|
event_loop: &EventLoopWindowTarget<()>,
|
||||||
windows: &mut HashMap<u32, Window>,
|
windows: &mut HashMap<WindowId, Window>,
|
||||||
) {
|
) {
|
||||||
let child_window = WindowBuilder::new()
|
let parent = parent.raw_window_handle();
|
||||||
.with_parent(WindowId::from(parent as u64))
|
let mut builder = WindowBuilder::new()
|
||||||
.with_title("child window")
|
.with_title("child window")
|
||||||
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
|
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
|
||||||
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
|
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
|
||||||
.with_visible(true)
|
.with_visible(true);
|
||||||
.build(event_loop)
|
// `with_parent_window` is unsafe. Parent window must a valid window.
|
||||||
.unwrap();
|
builder = unsafe { builder.with_parent_window(Some(parent)) };
|
||||||
|
let child_window = builder.build(event_loop).unwrap();
|
||||||
|
|
||||||
let id = child_window.xlib_window().unwrap() as u32;
|
let id = child_window.id();
|
||||||
windows.insert(id, child_window);
|
windows.insert(id, child_window);
|
||||||
println!("child window created with id: {}", id);
|
println!("child window created with id: {:?}", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", feature = "x11"))]
|
|
||||||
fn main() {
|
|
||||||
let mut windows = HashMap::new();
|
let mut windows = HashMap::new();
|
||||||
|
|
||||||
let event_loop: EventLoop<()> = EventLoop::new();
|
let event_loop: EventLoop<()> = EventLoop::new();
|
||||||
|
@ -42,8 +44,8 @@ fn main() {
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let root = parent_window.xlib_window().unwrap() as u32;
|
let root = parent_window;
|
||||||
println!("parent window id: {})", root);
|
println!("parent window: {:?})", root);
|
||||||
|
|
||||||
event_loop.run(move |event: Event<'_, ()>, event_loop, control_flow| {
|
event_loop.run(move |event: Event<'_, ()>, event_loop, control_flow| {
|
||||||
*control_flow = ControlFlow::Wait;
|
*control_flow = ControlFlow::Wait;
|
||||||
|
@ -55,7 +57,7 @@ fn main() {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
}
|
}
|
||||||
WindowEvent::CursorEntered { device_id: _ } => {
|
WindowEvent::CursorEntered { device_id: _ } => {
|
||||||
// println when the cursor entered in a window even if the child window is created
|
// On x11, println when the cursor entered in a window even if the child window is created
|
||||||
// by some key inputs.
|
// by some key inputs.
|
||||||
// the child windows are always placed at (0, 0) with size (200, 200) in the parent window,
|
// the child windows are always placed at (0, 0) with size (200, 200) in the parent window,
|
||||||
// so we also can see this log when we move the cursor arround (200, 200) in parent window.
|
// so we also can see this log when we move the cursor arround (200, 200) in parent window.
|
||||||
|
@ -69,7 +71,7 @@ fn main() {
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
spawn_child_window(root, event_loop, &mut windows);
|
spawn_child_window(&root, event_loop, &mut windows);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -77,7 +79,11 @@ fn main() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(all(target_os = "linux", feature = "x11")))]
|
#[cfg(not(any(
|
||||||
|
all(target_os = "linux", feature = "x11"),
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "windows"
|
||||||
|
)))]
|
||||||
fn main() {
|
fn main() {
|
||||||
panic!("This example is supported only on x11.");
|
panic!("This example is supported only on x11, macOS, and Windows.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
event::DeviceId,
|
event::DeviceId,
|
||||||
event_loop::EventLoopBuilder,
|
event_loop::EventLoopBuilder,
|
||||||
monitor::MonitorHandle,
|
monitor::MonitorHandle,
|
||||||
platform_impl::{Parent, WinIcon},
|
platform_impl::WinIcon,
|
||||||
window::{BadIcon, Icon, Window, WindowBuilder},
|
window::{BadIcon, Icon, Window, WindowBuilder},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -179,14 +179,8 @@ impl WindowExtWindows for Window {
|
||||||
|
|
||||||
/// Additional methods on `WindowBuilder` that are specific to Windows.
|
/// Additional methods on `WindowBuilder` that are specific to Windows.
|
||||||
pub trait WindowBuilderExtWindows {
|
pub trait WindowBuilderExtWindows {
|
||||||
/// Sets a parent to the window to be created.
|
|
||||||
///
|
|
||||||
/// A child window has the WS_CHILD style and is confined to the client area of its parent window.
|
|
||||||
///
|
|
||||||
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#child-windows>
|
|
||||||
fn with_parent_window(self, parent: HWND) -> WindowBuilder;
|
|
||||||
|
|
||||||
/// Set an owner to the window to be created. Can be used to create a dialog box, for example.
|
/// Set an owner to the window to be created. Can be used to create a dialog box, for example.
|
||||||
|
/// This only works when [`WindowBuilder::with_parent_window`] isn't called or set to `None`.
|
||||||
/// Can be used in combination with [`WindowExtWindows::set_enable(false)`](WindowExtWindows::set_enable)
|
/// Can be used in combination with [`WindowExtWindows::set_enable(false)`](WindowExtWindows::set_enable)
|
||||||
/// on the owner window to create a modal dialog box.
|
/// on the owner window to create a modal dialog box.
|
||||||
///
|
///
|
||||||
|
@ -235,15 +229,9 @@ pub trait WindowBuilderExtWindows {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowBuilderExtWindows for WindowBuilder {
|
impl WindowBuilderExtWindows for WindowBuilder {
|
||||||
#[inline]
|
|
||||||
fn with_parent_window(mut self, parent: HWND) -> WindowBuilder {
|
|
||||||
self.platform_specific.parent = Parent::ChildOf(parent);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_owner_window(mut self, parent: HWND) -> WindowBuilder {
|
fn with_owner_window(mut self, parent: HWND) -> WindowBuilder {
|
||||||
self.platform_specific.parent = Parent::OwnedBy(parent);
|
self.platform_specific.owner = Some(parent);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::os::raw;
|
use std::os::raw;
|
||||||
use std::{ptr, sync::Arc};
|
use std::{ptr, sync::Arc};
|
||||||
|
|
||||||
use crate::window::WindowId;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
|
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
|
||||||
monitor::MonitorHandle,
|
monitor::MonitorHandle,
|
||||||
|
@ -172,8 +171,6 @@ pub trait WindowBuilderExtX11 {
|
||||||
fn with_x11_visual<T>(self, visual_infos: *const T) -> Self;
|
fn with_x11_visual<T>(self, visual_infos: *const T) -> Self;
|
||||||
|
|
||||||
fn with_x11_screen(self, screen_id: i32) -> Self;
|
fn with_x11_screen(self, screen_id: i32) -> Self;
|
||||||
/// Build window with parent window.
|
|
||||||
fn with_parent(self, parent_id: WindowId) -> Self;
|
|
||||||
|
|
||||||
/// Build window with the given `general` and `instance` names.
|
/// Build window with the given `general` and `instance` names.
|
||||||
///
|
///
|
||||||
|
@ -227,12 +224,6 @@ impl WindowBuilderExtX11 for WindowBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn with_parent(mut self, parent_id: WindowId) -> Self {
|
|
||||||
self.platform_specific.parent_id = Some(parent_id.0);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_override_redirect(mut self, override_redirect: bool) -> Self {
|
fn with_override_redirect(mut self, override_redirect: bool) -> Self {
|
||||||
self.platform_specific.override_redirect = override_redirect;
|
self.platform_specific.override_redirect = override_redirect;
|
||||||
|
|
|
@ -96,8 +96,6 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
pub screen_id: Option<i32>,
|
pub screen_id: Option<i32>,
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
pub parent_id: Option<WindowId>,
|
|
||||||
#[cfg(feature = "x11")]
|
|
||||||
pub base_size: Option<Size>,
|
pub base_size: Option<Size>,
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
pub override_redirect: bool,
|
pub override_redirect: bool,
|
||||||
|
@ -114,8 +112,6 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
screen_id: None,
|
screen_id: None,
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
parent_id: None,
|
|
||||||
#[cfg(feature = "x11")]
|
|
||||||
base_size: None,
|
base_size: None,
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
override_redirect: false,
|
override_redirect: false,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::{
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XlibDisplayHandle, XlibWindowHandle};
|
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XlibDisplayHandle, XlibWindowHandle};
|
||||||
use x11_dl::xlib::TrueColor;
|
use x11_dl::xlib::{TrueColor, XID};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
|
@ -122,11 +122,11 @@ impl UnownedWindow {
|
||||||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||||
) -> Result<UnownedWindow, RootOsError> {
|
) -> Result<UnownedWindow, RootOsError> {
|
||||||
let xconn = &event_loop.xconn;
|
let xconn = &event_loop.xconn;
|
||||||
let root = if let Some(id) = pl_attribs.parent_id {
|
let root = match window_attrs.parent_window {
|
||||||
// WindowId is XID under the hood which doesn't exceed u32, so this conversion is lossless
|
Some(RawWindowHandle::Xlib(handle)) => handle.window,
|
||||||
u64::from(id) as _
|
Some(RawWindowHandle::Xcb(handle)) => handle.window as XID,
|
||||||
} else {
|
Some(raw) => unreachable!("Invalid raw window handle {raw:?} on X11"),
|
||||||
event_loop.root
|
None => event_loop.root,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut monitors = xconn.available_monitors();
|
let mut monitors = xconn.available_monitors();
|
||||||
|
|
|
@ -54,7 +54,7 @@ pub(crate) use self::version::NSAppKitVersion;
|
||||||
pub(crate) use self::view::{NSTrackingRectTag, NSView};
|
pub(crate) use self::view::{NSTrackingRectTag, NSView};
|
||||||
pub(crate) use self::window::{
|
pub(crate) use self::window::{
|
||||||
NSBackingStoreType, NSWindow, NSWindowButton, NSWindowLevel, NSWindowOcclusionState,
|
NSBackingStoreType, NSWindow, NSWindowButton, NSWindowLevel, NSWindowOcclusionState,
|
||||||
NSWindowSharingType, NSWindowStyleMask, NSWindowTitleVisibility,
|
NSWindowOrderingMode, NSWindowSharingType, NSWindowStyleMask, NSWindowTitleVisibility,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[link(name = "AppKit", kind = "framework")]
|
#[link(name = "AppKit", kind = "framework")]
|
||||||
|
|
|
@ -7,7 +7,7 @@ use objc2::rc::{Id, Shared};
|
||||||
use objc2::runtime::Object;
|
use objc2::runtime::Object;
|
||||||
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
|
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
|
||||||
|
|
||||||
use super::{NSCursor, NSResponder, NSTextInputContext};
|
use super::{NSCursor, NSResponder, NSTextInputContext, NSWindow};
|
||||||
|
|
||||||
extern_class!(
|
extern_class!(
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -52,6 +52,10 @@ extern_methods!(
|
||||||
|
|
||||||
#[sel(convertPoint:fromView:)]
|
#[sel(convertPoint:fromView:)]
|
||||||
pub fn convertPoint_fromView(&self, point: NSPoint, view: Option<&NSView>) -> NSPoint;
|
pub fn convertPoint_fromView(&self, point: NSPoint, view: Option<&NSView>) -> NSPoint;
|
||||||
|
|
||||||
|
pub fn window(&self) -> Option<Id<NSWindow, Shared>> {
|
||||||
|
unsafe { msg_send_id![self, window] }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl NSView {
|
unsafe impl NSView {
|
||||||
|
|
|
@ -213,6 +213,9 @@ extern_methods!(
|
||||||
|
|
||||||
#[sel(sendEvent:)]
|
#[sel(sendEvent:)]
|
||||||
pub unsafe fn sendEvent(&self, event: &NSEvent);
|
pub unsafe fn sendEvent(&self, event: &NSEvent);
|
||||||
|
|
||||||
|
#[sel(addChildWindow:ordered:)]
|
||||||
|
pub unsafe fn addChildWindow(&self, child: &NSWindow, ordered: NSWindowOrderingMode);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -379,3 +382,16 @@ pub enum NSWindowSharingType {
|
||||||
unsafe impl Encode for NSWindowSharingType {
|
unsafe impl Encode for NSWindowSharingType {
|
||||||
const ENCODING: Encoding = NSUInteger::ENCODING;
|
const ENCODING: Encoding = NSUInteger::ENCODING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[repr(isize)] // NSInteger
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum NSWindowOrderingMode {
|
||||||
|
NSWindowAbove = 1,
|
||||||
|
NSWindowBelow = -1,
|
||||||
|
NSWindowOut = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Encode for NSWindowOrderingMode {
|
||||||
|
const ENCODING: Encoding = NSInteger::ENCODING;
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
||||||
platform::macos::WindowExtMacOS,
|
platform::macos::WindowExtMacOS,
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
app_state::AppState,
|
app_state::AppState,
|
||||||
|
appkit::NSWindowOrderingMode,
|
||||||
ffi,
|
ffi,
|
||||||
monitor::{self, MonitorHandle, VideoMode},
|
monitor::{self, MonitorHandle, VideoMode},
|
||||||
util,
|
util,
|
||||||
|
@ -45,7 +46,7 @@ use objc2::{declare_class, msg_send, msg_send_id, sel, ClassType};
|
||||||
use super::appkit::{
|
use super::appkit::{
|
||||||
NSApp, NSAppKitVersion, NSAppearance, NSApplicationPresentationOptions, NSBackingStoreType,
|
NSApp, NSAppKitVersion, NSAppearance, NSApplicationPresentationOptions, NSBackingStoreType,
|
||||||
NSColor, NSCursor, NSFilenamesPboardType, NSRequestUserAttentionType, NSResponder, NSScreen,
|
NSColor, NSCursor, NSFilenamesPboardType, NSRequestUserAttentionType, NSResponder, NSScreen,
|
||||||
NSWindow, NSWindowButton, NSWindowLevel, NSWindowSharingType, NSWindowStyleMask,
|
NSView, NSWindow, NSWindowButton, NSWindowLevel, NSWindowSharingType, NSWindowStyleMask,
|
||||||
NSWindowTitleVisibility,
|
NSWindowTitleVisibility,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -369,6 +370,38 @@ impl WinitWindow {
|
||||||
})
|
})
|
||||||
.ok_or_else(|| os_error!(OsError::CreationError("Couldn't create `NSWindow`")))?;
|
.ok_or_else(|| os_error!(OsError::CreationError("Couldn't create `NSWindow`")))?;
|
||||||
|
|
||||||
|
match attrs.parent_window {
|
||||||
|
Some(RawWindowHandle::AppKit(handle)) => {
|
||||||
|
// SAFETY: Caller ensures the pointer is valid or NULL
|
||||||
|
let parent: Id<NSWindow, Shared> =
|
||||||
|
match unsafe { Id::retain(handle.ns_window.cast()) } {
|
||||||
|
Some(window) => window,
|
||||||
|
None => {
|
||||||
|
// SAFETY: Caller ensures the pointer is valid or NULL
|
||||||
|
let parent_view: Id<NSView, Shared> =
|
||||||
|
match unsafe { Id::retain(handle.ns_view.cast()) } {
|
||||||
|
Some(view) => view,
|
||||||
|
None => {
|
||||||
|
return Err(os_error!(OsError::CreationError(
|
||||||
|
"raw window handle should be non-empty"
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parent_view.window().ok_or_else(|| {
|
||||||
|
os_error!(OsError::CreationError(
|
||||||
|
"parent view should be installed in a window"
|
||||||
|
))
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// SAFETY: We know that there are no parent -> child -> parent cycles since the only place in `winit`
|
||||||
|
// where we allow making a window a child window is right here, just after it's been created.
|
||||||
|
unsafe { parent.addChildWindow(&this, NSWindowOrderingMode::NSWindowAbove) };
|
||||||
|
}
|
||||||
|
Some(raw) => panic!("Invalid raw window handle {raw:?} on macOS"),
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
|
||||||
let view = WinitView::new(&this, pl_attrs.accepts_first_mouse);
|
let view = WinitView::new(&this, pl_attrs.accepts_first_mouse);
|
||||||
|
|
||||||
// The default value of `setWantsBestResolutionOpenGLSurface:` was `false` until
|
// The default value of `setWantsBestResolutionOpenGLSurface:` was `false` until
|
||||||
|
|
|
@ -20,16 +20,9 @@ pub(self) use crate::platform_impl::Fullscreen;
|
||||||
use crate::event::DeviceId as RootDeviceId;
|
use crate::event::DeviceId as RootDeviceId;
|
||||||
use crate::icon::Icon;
|
use crate::icon::Icon;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum Parent {
|
|
||||||
None,
|
|
||||||
ChildOf(HWND),
|
|
||||||
OwnedBy(HWND),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes {
|
pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
pub parent: Parent,
|
pub owner: Option<HWND>,
|
||||||
pub menu: Option<HMENU>,
|
pub menu: Option<HMENU>,
|
||||||
pub taskbar_icon: Option<Icon>,
|
pub taskbar_icon: Option<Icon>,
|
||||||
pub no_redirection_bitmap: bool,
|
pub no_redirection_bitmap: bool,
|
||||||
|
@ -41,7 +34,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
impl Default for PlatformSpecificWindowBuilderAttributes {
|
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent: Parent::None,
|
owner: None,
|
||||||
menu: None,
|
menu: None,
|
||||||
taskbar_icon: None,
|
taskbar_icon: None,
|
||||||
no_redirection_bitmap: false,
|
no_redirection_bitmap: false,
|
||||||
|
|
|
@ -69,7 +69,7 @@ use crate::{
|
||||||
monitor::{self, MonitorHandle},
|
monitor::{self, MonitorHandle},
|
||||||
util,
|
util,
|
||||||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||||
Fullscreen, Parent, PlatformSpecificWindowBuilderAttributes, WindowId,
|
Fullscreen, PlatformSpecificWindowBuilderAttributes, WindowId,
|
||||||
},
|
},
|
||||||
window::{
|
window::{
|
||||||
CursorGrabMode, CursorIcon, Theme, UserAttentionType, WindowAttributes, WindowButtons,
|
CursorGrabMode, CursorIcon, Theme, UserAttentionType, WindowAttributes, WindowButtons,
|
||||||
|
@ -1062,22 +1062,25 @@ where
|
||||||
// so the diffing later can work.
|
// so the diffing later can work.
|
||||||
window_flags.set(WindowFlags::CLOSABLE, true);
|
window_flags.set(WindowFlags::CLOSABLE, true);
|
||||||
|
|
||||||
let parent = match pl_attribs.parent {
|
let parent = match attributes.parent_window {
|
||||||
Parent::ChildOf(parent) => {
|
Some(RawWindowHandle::Win32(handle)) => {
|
||||||
window_flags.set(WindowFlags::CHILD, true);
|
window_flags.set(WindowFlags::CHILD, true);
|
||||||
if pl_attribs.menu.is_some() {
|
if pl_attribs.menu.is_some() {
|
||||||
warn!("Setting a menu on a child window is unsupported");
|
warn!("Setting a menu on a child window is unsupported");
|
||||||
}
|
}
|
||||||
Some(parent)
|
Some(handle.hwnd as HWND)
|
||||||
}
|
}
|
||||||
Parent::OwnedBy(parent) => {
|
Some(raw) => unreachable!("Invalid raw window handle {raw:?} on Windows"),
|
||||||
|
None => match pl_attribs.owner {
|
||||||
|
Some(parent) => {
|
||||||
window_flags.set(WindowFlags::POPUP, true);
|
window_flags.set(WindowFlags::POPUP, true);
|
||||||
Some(parent)
|
Some(parent)
|
||||||
}
|
}
|
||||||
Parent::None => {
|
None => {
|
||||||
window_flags.set(WindowFlags::ON_TASKBAR, true);
|
window_flags.set(WindowFlags::ON_TASKBAR, true);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut initdata = InitData {
|
let mut initdata = InitData {
|
||||||
|
|
|
@ -138,6 +138,7 @@ pub(crate) struct WindowAttributes {
|
||||||
pub resize_increments: Option<Size>,
|
pub resize_increments: Option<Size>,
|
||||||
pub content_protected: bool,
|
pub content_protected: bool,
|
||||||
pub window_level: WindowLevel,
|
pub window_level: WindowLevel,
|
||||||
|
pub parent_window: Option<RawWindowHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WindowAttributes {
|
impl Default for WindowAttributes {
|
||||||
|
@ -161,6 +162,7 @@ impl Default for WindowAttributes {
|
||||||
preferred_theme: None,
|
preferred_theme: None,
|
||||||
resize_increments: None,
|
resize_increments: None,
|
||||||
content_protected: false,
|
content_protected: false,
|
||||||
|
parent_window: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,6 +403,27 @@ impl WindowBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build window with parent window.
|
||||||
|
///
|
||||||
|
/// The default is `None`.
|
||||||
|
///
|
||||||
|
/// ## Safety
|
||||||
|
///
|
||||||
|
/// `parent_window` must be a valid window handle.
|
||||||
|
///
|
||||||
|
/// ## Platform-specific
|
||||||
|
///
|
||||||
|
/// - **Windows** : A child window has the WS_CHILD style and is confined
|
||||||
|
/// to the client area of its parent window. For more information, see
|
||||||
|
/// <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#child-windows>
|
||||||
|
/// - **X11**: A child window is confined to the client area of its parent window.
|
||||||
|
/// - **Android / iOS / Wayland:** Unsupported.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn with_parent_window(mut self, parent_window: Option<RawWindowHandle>) -> Self {
|
||||||
|
self.window.parent_window = parent_window;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Builds the window.
|
/// Builds the window.
|
||||||
///
|
///
|
||||||
/// Possible causes of error include denied permission, incompatible system, and lack of memory.
|
/// Possible causes of error include denied permission, incompatible system, and lack of memory.
|
||||||
|
|
Loading…
Reference in a new issue