diff options
Diffstat (limited to 'src/api/cocoa')
-rw-r--r-- | src/api/cocoa/headless.rs | 8 | ||||
-rw-r--r-- | src/api/cocoa/mod.rs | 77 |
2 files changed, 59 insertions, 26 deletions
diff --git a/src/api/cocoa/headless.rs b/src/api/cocoa/headless.rs index 7cd0f88..f9bbffd 100644 --- a/src/api/cocoa/headless.rs +++ b/src/api/cocoa/headless.rs @@ -1,8 +1,9 @@ use ContextError; use CreationError; use CreationError::OsError; -use BuilderAttribs; +use GlAttributes; use GlContext; +use PixelFormatRequirements; use libc; use std::ptr; @@ -27,8 +28,9 @@ pub struct HeadlessContext { } impl HeadlessContext { - pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> { - let (width, height) = builder.dimensions.unwrap_or((1024, 768)); + pub fn new((width, height): (u32, u32), pf_reqs: &PixelFormatRequirements, + opengl: &GlAttributes<&HeadlessContext>) -> Result<HeadlessContext, CreationError> + { let context = unsafe { let attributes = [ NSOpenGLPFAAccelerated as u32, diff --git a/src/api/cocoa/mod.rs b/src/api/cocoa/mod.rs index 0314dd3..539545c 100644 --- a/src/api/cocoa/mod.rs +++ b/src/api/cocoa/mod.rs @@ -7,13 +7,15 @@ use CreationError::OsError; use libc; use Api; -use BuilderAttribs; use ContextError; +use GlAttributes; use GlContext; use GlProfile; use GlRequest; use PixelFormat; +use PixelFormatRequirements; use Robustness; +use WindowAttributes; use native_monitor::NativeMonitorId; use objc::runtime::{Class, Object, Sel, BOOL, YES, NO}; @@ -44,7 +46,7 @@ use std::sync::Mutex; use std::ascii::AsciiExt; use std::ops::Deref; -use events::Event::{Awakened, MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel, Closed}; +use events::Event::{Awakened, MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel, Closed, Focused}; use events::ElementState::{Pressed, Released}; use events::MouseButton; use events; @@ -105,6 +107,25 @@ impl WindowDelegate { } } + extern fn window_did_become_key(this: &Object, _: Sel, _: id) { + unsafe { + // TODO: center the cursor if the window had mouse grab when it + // lost focus + + let state: *mut libc::c_void = *this.get_ivar("glutinState"); + let state = state as *mut DelegateState; + (*state).pending_events.lock().unwrap().push_back(Focused(true)); + } + } + + extern fn window_did_resign_key(this: &Object, _: Sel, _: id) { + unsafe { + let state: *mut libc::c_void = *this.get_ivar("glutinState"); + let state = state as *mut DelegateState; + (*state).pending_events.lock().unwrap().push_back(Focused(false)); + } + } + static mut delegate_class: *const Class = 0 as *const Class; static INIT: Once = ONCE_INIT; @@ -118,6 +139,11 @@ impl WindowDelegate { window_should_close as extern fn(&Object, Sel, id) -> BOOL); decl.add_method(sel!(windowDidResize:), window_did_resize as extern fn(&Object, Sel, id)); + + decl.add_method(sel!(windowDidBecomeKey:), + window_did_become_key as extern fn(&Object, Sel, id)); + decl.add_method(sel!(windowDidResignKey:), + window_did_resign_key as extern fn(&Object, Sel, id)); // Store internal state as user data decl.add_ivar::<*mut libc::c_void>("glutinState"); @@ -242,12 +268,14 @@ impl<'a> Iterator for WaitEventsIterator<'a> { impl Window { #[cfg(feature = "window")] - pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> { - if builder.sharing.is_some() { + pub fn new(win_attribs: &WindowAttributes, pf_reqs: &PixelFormatRequirements, + opengl: &GlAttributes<&Window>) -> Result<Window, CreationError> + { + if opengl.sharing.is_some() { unimplemented!() } - match builder.gl_robustness { + match opengl.robustness { Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => { return Err(CreationError::RobustnessNotSupported); }, @@ -259,7 +287,7 @@ impl Window { None => { return Err(OsError(format!("Couldn't create NSApplication"))); }, }; - let window = match Window::create_window(&builder) + let window = match Window::create_window(win_attribs) { Some(window) => window, None => { return Err(OsError(format!("Couldn't create NSWindow"))); }, @@ -271,13 +299,13 @@ impl Window { // TODO: perhaps we should return error from create_context so we can // determine the cause of failure and possibly recover? - let (context, pf) = match Window::create_context(*view, &builder) { + let (context, pf) = match Window::create_context(*view, pf_reqs, opengl) { Ok((context, pf)) => (context, pf), Err(e) => { return Err(OsError(format!("Couldn't create OpenGL context: {}", e))); }, }; unsafe { - if builder.transparent { + if win_attribs.transparent { let clear_col = { let cls = Class::get("NSColor").unwrap(); @@ -293,7 +321,7 @@ impl Window { } app.activateIgnoringOtherApps_(YES); - if builder.visible { + if win_attribs.visible { window.makeKeyAndOrderFront_(nil); } else { window.makeKeyWindow(); @@ -332,9 +360,9 @@ impl Window { } } - fn create_window(builder: &BuilderAttribs) -> Option<IdRef> { + fn create_window(attrs: &WindowAttributes) -> Option<IdRef> { unsafe { - let screen = match builder.monitor { + let screen = match attrs.monitor { Some(ref monitor_id) => { let native_id = match monitor_id.get_native_identifier() { NativeMonitorId::Numeric(num) => num, @@ -366,13 +394,14 @@ impl Window { let frame = match screen { Some(screen) => NSScreen::frame(screen), None => { - let (width, height) = builder.dimensions.unwrap_or((800, 600)); + let (width, height) = attrs.dimensions.unwrap_or((800, 600)); NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64)) } }; - let masks = if screen.is_some() || !builder.decorations { - NSBorderlessWindowMask as NSUInteger + let masks = if screen.is_some() || !attrs.decorations { + NSBorderlessWindowMask as NSUInteger | + NSResizableWindowMask as NSUInteger } else { NSTitledWindowMask as NSUInteger | NSClosableWindowMask as NSUInteger | @@ -387,7 +416,7 @@ impl Window { NO, )); window.non_nil().map(|window| { - let title = IdRef::new(NSString::alloc(nil).init_str(&builder.title)); + let title = IdRef::new(NSString::alloc(nil).init_str(&attrs.title)); window.setTitle_(*title); window.setAcceptsMouseMovedEvents_(YES); if screen.is_some() { @@ -412,8 +441,10 @@ impl Window { } } - fn create_context(view: id, builder: &BuilderAttribs) -> Result<(IdRef, PixelFormat), CreationError> { - let profile = match (builder.gl_version, builder.gl_version.to_gl_version(), builder.gl_profile) { + fn create_context(view: id, pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&Window>) + -> Result<(IdRef, PixelFormat), CreationError> + { + let profile = match (opengl.version, opengl.version.to_gl_version(), opengl.profile) { // Note: we are not using ranges because of a rust bug that should be fixed here: // https://github.com/rust-lang/rust/pull/27050 @@ -446,16 +477,16 @@ impl Window { // full color size and hope for the best. Another hiccup is that // `NSOpenGLPFAColorSize` also includes `NSOpenGLPFAAlphaSize`, // so we have to account for that as well. - let alpha_depth = builder.alpha_bits.unwrap_or(8); - let color_depth = builder.color_bits.unwrap_or(24) + alpha_depth; + let alpha_depth = pf_reqs.alpha_bits.unwrap_or(8); + let color_depth = pf_reqs.color_bits.unwrap_or(24) + alpha_depth; let mut attributes = vec![ NSOpenGLPFADoubleBuffer as u32, NSOpenGLPFAClosestPolicy as u32, NSOpenGLPFAColorSize as u32, color_depth as u32, NSOpenGLPFAAlphaSize as u32, alpha_depth as u32, - NSOpenGLPFADepthSize as u32, builder.depth_bits.unwrap_or(24) as u32, - NSOpenGLPFAStencilSize as u32, builder.stencil_bits.unwrap_or(8) as u32, + NSOpenGLPFADepthSize as u32, pf_reqs.depth_bits.unwrap_or(24) as u32, + NSOpenGLPFAStencilSize as u32, pf_reqs.stencil_bits.unwrap_or(8) as u32, NSOpenGLPFAOpenGLProfile as u32, profile, ]; @@ -466,7 +497,7 @@ impl Window { attributes.push(NSOpenGLPFAColorFloat as u32); } - builder.multisampling.map(|samples| { + pf_reqs.multisampling.map(|samples| { attributes.push(NSOpenGLPFAMultisample as u32); attributes.push(NSOpenGLPFASampleBuffers as u32); attributes.push(1); attributes.push(NSOpenGLPFASamples as u32); attributes.push(samples as u32); @@ -515,7 +546,7 @@ impl Window { }; cxt.setView_(view); - let value = if builder.vsync { 1 } else { 0 }; + let value = if opengl.vsync { 1 } else { 0 }; cxt.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval); CGLEnable(cxt.CGLContextObj(), kCGLCECrashOnRemovedFunctions); |