From e9a775c6b1f6487744cd7f3d19b484f859cde0ef Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 14 Jan 2015 10:04:28 +0100 Subject: [PATCH] Implement win32 initialization in a cleaner way --- src/lib.rs | 27 +++++++++++++++++++++++++++ src/win32/init.rs | 37 +++++++++++++++++-------------------- src/win32/mod.rs | 14 +++++--------- 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index da2e83d6..85d373ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,6 +217,33 @@ impl BuilderAttribs<'static> { } } +impl<'a> BuilderAttribs<'a> { + fn extract_non_static(mut self) -> (BuilderAttribs<'static>, Option<&'a winimpl::Window>) { + let sharing = self.sharing.take(); + + let new_attribs = BuilderAttribs { + headless: self.headless, + strict: self.strict, + sharing: None, + dimensions: self.dimensions, + title: self.title, + monitor: self.monitor, + gl_version: self.gl_version, + gl_debug: self.gl_debug, + vsync: self.vsync, + visible: self.visible, + multisampling: self.multisampling, + depth_bits: self.depth_bits, + stencil_bits: self.stencil_bits, + color_bits: self.color_bits, + alpha_bits: self.alpha_bits, + stereoscopy: self.stereoscopy, + }; + + (new_attribs, sharing) + } +} + #[cfg(feature = "window")] impl<'a> WindowBuilder<'a> { /// Initializes a new `WindowBuilder` with default values. diff --git a/src/win32/init.rs b/src/win32/init.rs index 754d251c..9e0e3a7f 100644 --- a/src/win32/init.rs +++ b/src/win32/init.rs @@ -2,6 +2,7 @@ use std::sync::atomic::AtomicBool; use std::ptr; use super::event; use super::Window; +use BuilderAttribs; use {CreationError, Event}; use CreationError::OsError; @@ -27,18 +28,14 @@ thread_local!(static WINDOW: Rc)>>> pub struct ContextHack(pub winapi::HGLRC); unsafe impl Send for ContextHack {} -pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, - builder_monitor: Option, - builder_gl_version: Option<(u32, u32)>, builder_debug: bool, - builder_vsync: bool, builder_hidden: bool, - builder_sharelists: Option, builder_multisampling: Option) +pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option) -> Result { use std::mem; use std::os; // initializing variables to be sent to the task - let title = builder_title.as_slice().utf16_units() + let title = builder.title.as_slice().utf16_units() .chain(Some(0).into_iter()).collect::>(); // title to utf16 //let hints = hints.clone(); let (tx, rx) = channel(); @@ -80,15 +77,15 @@ pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, // building a RECT object with coordinates let mut rect = winapi::RECT { - left: 0, right: builder_dimensions.unwrap_or((1024, 768)).0 as winapi::LONG, - top: 0, bottom: builder_dimensions.unwrap_or((1024, 768)).1 as winapi::LONG, + left: 0, right: builder.dimensions.unwrap_or((1024, 768)).0 as winapi::LONG, + top: 0, bottom: builder.dimensions.unwrap_or((1024, 768)).1 as winapi::LONG, }; // switching to fullscreen if necessary // this means adjusting the window's position so that it overlaps the right monitor, // and change the monitor's resolution if necessary - if builder_monitor.is_some() { - let monitor = builder_monitor.as_ref().unwrap(); + if builder.monitor.is_some() { + let monitor = builder.monitor.as_ref().unwrap(); // adjusting the rect { @@ -117,7 +114,7 @@ pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, } // computing the style and extended style of the window - let (ex_style, style) = if builder_monitor.is_some() { + let (ex_style, style) = if builder.monitor.is_some() { (winapi::WS_EX_APPWINDOW, winapi::WS_POPUP | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN) } else { (winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, @@ -250,13 +247,13 @@ pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, // creating the real window this time let real_window = unsafe { - let (width, height) = if builder_monitor.is_some() || builder_dimensions.is_some() { + let (width, height) = if builder.monitor.is_some() || builder.dimensions.is_some() { (Some(rect.right - rect.left), Some(rect.bottom - rect.top)) } else { (None, None) }; - let style = if builder_hidden { + let style = if !builder.visible || builder.headless { style } else { style | winapi::WS_VISIBLE @@ -265,8 +262,8 @@ pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, let handle = user32::CreateWindowExW(ex_style, class_name.as_ptr(), title.as_ptr() as winapi::LPCWSTR, style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN, - if builder_monitor.is_some() { 0 } else { winapi::CW_USEDEFAULT }, - if builder_monitor.is_some() { 0 } else { winapi::CW_USEDEFAULT }, + if builder.monitor.is_some() { 0 } else { winapi::CW_USEDEFAULT }, + if builder.monitor.is_some() { 0 } else { 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()), ptr::null_mut()); @@ -309,15 +306,15 @@ pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, let mut attributes = Vec::new(); - if builder_gl_version.is_some() { - let version = builder_gl_version.as_ref().unwrap(); + if builder.gl_version.is_some() { + let version = builder.gl_version.as_ref().unwrap(); attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); attributes.push(version.0 as libc::c_int); attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); attributes.push(version.1 as libc::c_int); } - if builder_debug { + if builder.gl_debug { attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as libc::c_int); attributes.push(gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int); } @@ -351,7 +348,7 @@ pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, }; // calling SetForegroundWindow if fullscreen - if builder_monitor.is_some() { + if builder.monitor.is_some() { unsafe { user32::SetForegroundWindow(real_window) }; } @@ -381,7 +378,7 @@ pub fn new_window(builder_dimensions: Option<(u32, u32)>, builder_title: String, }; // handling vsync - if builder_vsync { + if builder.vsync { if extra_functions.SwapIntervalEXT.is_loaded() { unsafe { gl::wgl::MakeCurrent(hdc as *const libc::c_void, context) }; if unsafe { extra_functions.SwapIntervalEXT(1) } == 0 { diff --git a/src/win32/mod.rs b/src/win32/mod.rs index 8104fc87..beb7825c 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -26,10 +26,8 @@ pub struct HeadlessContext(Window); impl HeadlessContext { /// See the docs in the crate root file. pub fn new(builder: BuilderAttribs) -> Result { - let BuilderAttribs { dimensions, gl_version, gl_debug, .. } = builder; - init::new_window(dimensions, "".to_string(), None, gl_version, gl_debug, false, true, - None, None) - .map(|w| HeadlessContext(w)) + let (builder, _) = builder.extract_non_static(); + init::new_window(builder, None).map(|w| HeadlessContext(w)) } /// See the docs in the crate root file. @@ -86,11 +84,9 @@ unsafe impl Sync for Window {} impl Window { /// See the docs in the crate root file. pub fn new(builder: BuilderAttribs) -> Result { - let BuilderAttribs { dimensions, title, monitor, gl_version, - gl_debug, vsync, visible, sharing, multisampling, .. } = builder; - init::new_window(dimensions, title, monitor, gl_version, gl_debug, vsync, - !visible, sharing.map(|w| init::ContextHack(w.context)), - multisampling) + let (builder, sharing) = builder.extract_non_static(); + let sharing = sharing.map(|w| init::ContextHack(w.context)); + init::new_window(builder, sharing) } }