2014-08-03 18:30:31 +02:00
|
|
|
use {Event, WindowBuilder};
|
2014-08-03 09:25:30 +02:00
|
|
|
|
2014-10-04 15:49:39 +02:00
|
|
|
use cocoa::base::{id, NSUInteger, nil};
|
|
|
|
|
use cocoa::appkit::*;
|
2014-08-03 09:25:30 +02:00
|
|
|
|
2014-10-04 15:49:39 +02:00
|
|
|
use core_foundation::base::TCFType;
|
|
|
|
|
use core_foundation::string::CFString;
|
|
|
|
|
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
|
|
|
|
|
|
|
|
|
pub struct Window {
|
|
|
|
|
context: id,
|
|
|
|
|
}
|
2014-08-03 09:25:30 +02:00
|
|
|
|
2014-10-04 15:49:39 +02:00
|
|
|
pub struct MonitorID;
|
2014-08-12 09:16:08 +02:00
|
|
|
|
2014-08-03 09:25:30 +02:00
|
|
|
pub fn get_available_monitors() -> Vec<MonitorID> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_primary_monitor() -> MonitorID {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MonitorID {
|
|
|
|
|
pub fn get_name(&self) -> Option<String> {
|
2014-10-06 18:37:06 +02:00
|
|
|
unimplemented!()
|
2014-08-03 09:25:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_dimensions(&self) -> (uint, uint) {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Window {
|
|
|
|
|
pub fn new(_builder: WindowBuilder) -> Result<Window, String> {
|
2014-10-04 15:49:39 +02:00
|
|
|
|
2014-10-05 23:45:38 +02:00
|
|
|
let app = match Window::create_app() {
|
|
|
|
|
Some(app) => app,
|
|
|
|
|
None => { return Err(format!("Couldn't create NSApplication")); },
|
|
|
|
|
};
|
|
|
|
|
let window = match Window::create_window(_builder.dimensions.unwrap_or((800, 600)), _builder.title.as_slice()) {
|
|
|
|
|
Some(window) => window,
|
|
|
|
|
None => { return Err(format!("Couldn't create NSWindow")); },
|
|
|
|
|
};
|
|
|
|
|
let view = match Window::create_view(window) {
|
|
|
|
|
Some(view) => view,
|
|
|
|
|
None => { return Err(format!("Couldn't create NSView")); },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let context = match Window::create_context(view) {
|
|
|
|
|
Some(context) => context,
|
|
|
|
|
None => { return Err(format!("Couldn't create OpenGL context")); },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
app.activateIgnoringOtherApps_(true);
|
|
|
|
|
window.makeKeyAndOrderFront_(nil);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let window = Window {
|
|
|
|
|
context: context,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok(window)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_app() -> Option<id> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let app = NSApp();
|
|
|
|
|
if app == nil {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
|
|
|
|
app.finishLaunching();
|
|
|
|
|
Some(app)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-10-04 15:49:39 +02:00
|
|
|
|
2014-10-05 23:45:38 +02:00
|
|
|
fn create_window(dimensions: (uint, uint), title: &str) -> Option<id> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let (width, height) = dimensions;
|
|
|
|
|
let scr_frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));
|
2014-10-04 15:49:39 +02:00
|
|
|
|
|
|
|
|
let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
|
|
|
|
scr_frame,
|
|
|
|
|
NSTitledWindowMask as NSUInteger | NSClosableWindowMask as NSUInteger | NSMiniaturizableWindowMask as NSUInteger,
|
|
|
|
|
NSBackingStoreBuffered,
|
|
|
|
|
false
|
|
|
|
|
);
|
|
|
|
|
|
2014-10-05 23:45:38 +02:00
|
|
|
if window == nil {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
let title = NSString::alloc(nil).init_str(title);
|
|
|
|
|
window.setTitle_(title);
|
|
|
|
|
window.center();
|
|
|
|
|
Some(window)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_view(window: id) -> Option<id> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let view = NSView::alloc(nil).init();
|
|
|
|
|
if view == nil {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
view.setWantsBestResolutionOpenGLSurface_(true);
|
|
|
|
|
window.setContentView(view);
|
|
|
|
|
Some(view)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-10-04 15:49:39 +02:00
|
|
|
|
2014-10-05 23:45:38 +02:00
|
|
|
fn create_context(view: id) -> Option<id> {
|
|
|
|
|
unsafe {
|
2014-10-04 15:49:39 +02:00
|
|
|
let attributes = [
|
|
|
|
|
NSOpenGLPFADoubleBuffer as uint,
|
|
|
|
|
NSOpenGLPFAClosestPolicy as uint,
|
|
|
|
|
NSOpenGLPFAColorSize as uint, 24,
|
|
|
|
|
NSOpenGLPFAAlphaSize as uint, 8,
|
|
|
|
|
NSOpenGLPFADepthSize as uint, 24,
|
|
|
|
|
NSOpenGLPFAStencilSize as uint, 8,
|
|
|
|
|
0
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(attributes);
|
|
|
|
|
if pixelformat == nil {
|
2014-10-05 23:45:38 +02:00
|
|
|
return None;
|
2014-10-04 15:49:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
|
|
|
|
|
if context == nil {
|
2014-10-05 23:45:38 +02:00
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
context.setView_(view);
|
|
|
|
|
Some(context)
|
2014-10-04 15:49:39 +02:00
|
|
|
}
|
2014-10-05 23:45:38 +02:00
|
|
|
}
|
2014-08-03 09:25:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_closed(&self) -> bool {
|
2014-10-04 15:49:39 +02:00
|
|
|
// TODO: remove fake implementation
|
|
|
|
|
false
|
2014-08-03 09:25:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_title(&self, _title: &str) {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_position(&self) -> Option<(int, int)> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-07 18:07:48 +02:00
|
|
|
pub fn set_position(&self, _x: int, _y: int) {
|
2014-08-03 09:25:30 +02:00
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_inner_size(&self) -> Option<(uint, uint)> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_outer_size(&self) -> Option<(uint, uint)> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_inner_size(&self, _x: uint, _y: uint) {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn poll_events(&self) -> Vec<Event> {
|
2014-10-06 17:54:15 +02:00
|
|
|
let mut events = Vec::new();
|
2014-08-03 09:25:30 +02:00
|
|
|
|
2014-10-04 15:49:39 +02:00
|
|
|
loop {
|
|
|
|
|
unsafe {
|
2014-10-06 17:54:15 +02:00
|
|
|
use {MouseInput, Pressed, Released, LeftMouseButton, RightMouseButton};
|
2014-10-04 15:49:39 +02:00
|
|
|
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
|
|
|
|
NSAnyEventMask as u64,
|
2014-10-06 17:54:15 +02:00
|
|
|
NSDate::distantPast(nil),
|
2014-10-04 15:49:39 +02:00
|
|
|
NSDefaultRunLoopMode,
|
|
|
|
|
true);
|
|
|
|
|
if event == nil { break; }
|
2014-10-06 17:54:15 +02:00
|
|
|
|
|
|
|
|
match event.get_type() {
|
|
|
|
|
NSLeftMouseDown => { events.push(MouseInput(Pressed, LeftMouseButton)); },
|
|
|
|
|
NSLeftMouseUp => { events.push(MouseInput(Released, LeftMouseButton)); },
|
|
|
|
|
NSRightMouseDown => { events.push(MouseInput(Pressed, RightMouseButton)); },
|
|
|
|
|
NSRightMouseUp => { events.push(MouseInput(Released, RightMouseButton)); },
|
|
|
|
|
NSMouseMoved => { },
|
|
|
|
|
NSKeyDown => { },
|
|
|
|
|
NSKeyUp => { },
|
|
|
|
|
NSFlagsChanged => { },
|
|
|
|
|
NSScrollWheel => { },
|
|
|
|
|
NSOtherMouseDown => { },
|
|
|
|
|
NSOtherMouseUp => { },
|
|
|
|
|
NSOtherMouseDragged => { },
|
|
|
|
|
_ => { },
|
|
|
|
|
}
|
2014-10-04 15:49:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
2014-10-06 17:54:15 +02:00
|
|
|
events
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn wait_events(&self) -> Vec<Event> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
|
|
|
|
NSAnyEventMask as u64,
|
|
|
|
|
NSDate::distantFuture(nil),
|
|
|
|
|
NSDefaultRunLoopMode,
|
|
|
|
|
true);
|
|
|
|
|
NSApp().sendEvent_(event);
|
|
|
|
|
self.poll_events()
|
|
|
|
|
}
|
2014-08-03 09:25:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub unsafe fn make_current(&self) {
|
2014-10-04 15:49:39 +02:00
|
|
|
self.context.makeCurrentContext();
|
2014-08-03 09:25:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_proc_address(&self, _addr: &str) -> *const () {
|
2014-10-04 15:49:39 +02:00
|
|
|
let symbol_name: CFString = from_str(_addr).unwrap();
|
|
|
|
|
let framework_name: CFString = from_str("com.apple.opengl").unwrap();
|
|
|
|
|
let framework = unsafe {
|
|
|
|
|
CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
|
|
|
|
|
};
|
|
|
|
|
let symbol = unsafe {
|
|
|
|
|
CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
|
|
|
|
|
};
|
|
|
|
|
symbol as *const ()
|
2014-08-03 09:25:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn swap_buffers(&self) {
|
2014-10-04 15:49:39 +02:00
|
|
|
unsafe { self.context.flushBuffer(); }
|
2014-08-03 09:25:30 +02:00
|
|
|
}
|
|
|
|
|
}
|