first try to allow child window on windows

This commit is contained in:
k-brac 2016-11-25 17:05:39 +01:00
parent 13620118f6
commit 5a09e8ba21
5 changed files with 83 additions and 14 deletions

44
examples/child_window.rs Normal file
View file

@ -0,0 +1,44 @@
extern crate winit;
use std::thread;
use winit::os::windows::WindowBuilderExt;
fn resize_callback(width: u32, height: u32) {
println!("Window resized to {}x{}", width, height);
}
fn main() {
let window = winit::WindowBuilder::new()
.with_title("A fantastic window!")
.with_window_resize_callback(resize_callback)
.build()
.unwrap();
let proxy = window.create_window_proxy();
thread::spawn(move || {
let child = winit::WindowBuilder::new()
.with_title("child window!")
.with_window_resize_callback(resize_callback)
.with_decorations(false)
.with_parent_window(proxy)
.build()
.unwrap();
for event in child.wait_events() {
println!("child {:?}", event);
match event {
winit::Event::Closed => break,
_ => (),
}
}
});
for event in window.wait_events() {
println!("parent {:?}", event);
match event {
winit::Event::Closed => break,
_ => (),
}
}
}

View file

@ -3,6 +3,7 @@
use libc; use libc;
use Window; use Window;
use WindowBuilder; use WindowBuilder;
use window;
/// Additional methods on `Window` that are specific to Windows. /// Additional methods on `Window` that are specific to Windows.
pub trait WindowExt { pub trait WindowExt {
@ -23,8 +24,14 @@ impl WindowExt for Window {
/// Additional methods on `WindowBuilder` that are specific to Windows. /// Additional methods on `WindowBuilder` that are specific to Windows.
pub trait WindowBuilderExt { pub trait WindowBuilderExt {
fn with_parent_window(self, parent: window::WindowProxy) -> WindowBuilder;
} }
impl WindowBuilderExt for WindowBuilder { impl WindowBuilderExt for WindowBuilder {
/// Sets a parent to the window to be created
#[inline]
fn with_parent_window(mut self, parent: window::WindowProxy) -> WindowBuilder {
self.platform_specific.parent = Some(parent);
self
}
} }

View file

@ -9,6 +9,7 @@ use super::WindowState;
use super::Window; use super::Window;
use super::MonitorId; use super::MonitorId;
use super::WindowWrapper; use super::WindowWrapper;
use super::PlatformSpecificWindowBuilderAttributes;
use CreationError; use CreationError;
use CreationError::OsError; use CreationError::OsError;
@ -24,9 +25,9 @@ use kernel32;
use dwmapi; use dwmapi;
use user32; use user32;
pub fn new_window(window: &WindowAttributes) -> Result<Window, CreationError> { pub fn new_window(window: &WindowAttributes, pl_attribs: &PlatformSpecificWindowBuilderAttributes) -> Result<Window, CreationError> {
let window = window.clone(); let window = window.clone();
let attribs = pl_attribs.clone();
// initializing variables to be sent to the task // initializing variables to be sent to the task
let title = OsStr::new(&window.title).encode_wide().chain(Some(0).into_iter()) let title = OsStr::new(&window.title).encode_wide().chain(Some(0).into_iter())
@ -39,7 +40,7 @@ pub fn new_window(window: &WindowAttributes) -> Result<Window, CreationError> {
thread::spawn(move || { thread::spawn(move || {
unsafe { unsafe {
// creating and sending the `Window` // creating and sending the `Window`
match init(title, &window) { match init(title, &window, attribs) {
Ok(w) => tx.send(Ok(w)).ok(), Ok(w) => tx.send(Ok(w)).ok(),
Err(e) => { Err(e) => {
tx.send(Err(e)).ok(); tx.send(Err(e)).ok();
@ -65,7 +66,7 @@ pub fn new_window(window: &WindowAttributes) -> Result<Window, CreationError> {
rx.recv().unwrap() rx.recv().unwrap()
} }
unsafe fn init(title: Vec<u16>, window: &WindowAttributes) -> Result<Window, CreationError> { unsafe fn init(title: Vec<u16>, window: &WindowAttributes, pl_attribs: PlatformSpecificWindowBuilderAttributes) -> Result<Window, CreationError> {
// registering the window class // registering the window class
let class_name = register_window_class(); let class_name = register_window_class();
@ -84,8 +85,16 @@ unsafe fn init(title: Vec<u16>, window: &WindowAttributes) -> Result<Window, Cre
} }
// computing the style and extended style of the window // computing the style and extended style of the window
let (ex_style, style) = if window.monitor.is_some() || window.decorations == false { let (ex_style, style) = if window.monitor.is_some() || !window.decorations {
(winapi::WS_EX_APPWINDOW, winapi::WS_POPUP | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN) (winapi::WS_EX_APPWINDOW,
//winapi::WS_POPUP is incompatible with winapi::WS_CHILD
if pl_attribs.parent.is_some() {
winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN
}
else {
winapi::WS_POPUP | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN
}
)
} else { } else {
(winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, (winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE,
winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN) winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN)
@ -108,19 +117,24 @@ unsafe fn init(title: Vec<u16>, window: &WindowAttributes) -> Result<Window, Cre
(None, None) (None, None)
}; };
let style = if !window.visible { let mut style = if !window.visible {
style style
} else { } else {
style | winapi::WS_VISIBLE style | winapi::WS_VISIBLE
}; };
if pl_attribs.parent.is_some() {
style |= winapi::WS_CHILD;
}
let handle = user32::CreateWindowExW(ex_style | winapi::WS_EX_ACCEPTFILES, let handle = user32::CreateWindowExW(ex_style | winapi::WS_EX_ACCEPTFILES,
class_name.as_ptr(), class_name.as_ptr(),
title.as_ptr() as winapi::LPCWSTR, title.as_ptr() as winapi::LPCWSTR,
style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN, style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN,
x.unwrap_or(winapi::CW_USEDEFAULT), y.unwrap_or(winapi::CW_USEDEFAULT), x.unwrap_or(winapi::CW_USEDEFAULT), y.unwrap_or(winapi::CW_USEDEFAULT),
width.unwrap_or(winapi::CW_USEDEFAULT), height.unwrap_or(winapi::CW_USEDEFAULT), width.unwrap_or(winapi::CW_USEDEFAULT), height.unwrap_or(winapi::CW_USEDEFAULT),
ptr::null_mut(), ptr::null_mut(), kernel32::GetModuleHandleW(ptr::null()), pl_attribs.parent.map_or(ptr::null_mut(), |v| v.proxy.hwnd),
ptr::null_mut(), kernel32::GetModuleHandleW(ptr::null()),
ptr::null_mut()); ptr::null_mut());
if handle.is_null() { if handle.is_null() {

View file

@ -15,8 +15,12 @@ use CursorState;
use WindowAttributes; use WindowAttributes;
use window;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes; pub struct PlatformSpecificWindowBuilderAttributes {
pub parent: Option<window::WindowProxy>,
}
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes; pub struct PlatformSpecificHeadlessBuilderAttributes;
@ -76,7 +80,7 @@ impl Drop for WindowWrapper {
#[derive(Clone)] #[derive(Clone)]
pub struct WindowProxy { pub struct WindowProxy {
hwnd: winapi::HWND, pub hwnd: winapi::HWND,
} }
unsafe impl Send for WindowProxy {} unsafe impl Send for WindowProxy {}
@ -93,10 +97,10 @@ impl WindowProxy {
impl Window { impl Window {
/// See the docs in the crate root file. /// See the docs in the crate root file.
pub fn new(window: &WindowAttributes, _: &PlatformSpecificWindowBuilderAttributes) pub fn new(window: &WindowAttributes, pl_attribs: &PlatformSpecificWindowBuilderAttributes)
-> Result<Window, CreationError> -> Result<Window, CreationError>
{ {
init::new_window(window) init::new_window(window, pl_attribs)
} }
/// See the docs in the crate root file. /// See the docs in the crate root file.

View file

@ -361,7 +361,7 @@ impl Window {
/// threads. /// threads.
#[derive(Clone)] #[derive(Clone)]
pub struct WindowProxy { pub struct WindowProxy {
proxy: platform::WindowProxy, pub proxy: platform::WindowProxy,
} }
impl WindowProxy { impl WindowProxy {