Conflicts:
	.travis.yml
	Cargo.toml
	examples/fullscreen.rs
	src/api/android/mod.rs
	src/api/cocoa/headless.rs
	src/api/cocoa/helpers.rs
	src/api/cocoa/mod.rs
	src/api/glx/mod.rs
	src/api/osmesa/mod.rs
	src/api/win32/callback.rs
	src/headless.rs
	src/lib.rs
	src/platform/linux/mod.rs
	src/window.rs
This commit is contained in:
Andrey Lesnikov 2016-09-19 19:53:28 +03:00
commit 7f6ae8910e
22 changed files with 332 additions and 194 deletions

View file

@ -6,6 +6,7 @@ use libc;
use WindowAttributes;
use native_monitor::NativeMonitorId;
use os::macos::ActivationPolicy;
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
use objc::declare::ClassDecl;
@ -15,9 +16,7 @@ use cgl::{CGLEnable, kCGLCECrashOnRemovedFunctions, CGLSetParameter, kCGLCPSurfa
use cocoa::base::{id, nil};
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
NSString, NSUInteger};
use cocoa::appkit;
use cocoa::appkit::*;
use cocoa::appkit::NSEventSubtype::*;
use cocoa::appkit::{self, NSApplication, NSEvent, NSOpenGLContext, NSOpenGLPixelFormat, NSView, NSWindow};
use core_foundation::base::TCFType;
use core_foundation::string::CFString;
@ -30,12 +29,9 @@ use std::collections::VecDeque;
use std::str::FromStr;
use std::str::from_utf8;
use std::sync::Mutex;
use std::ascii::AsciiExt;
use std::ops::Deref;
use events::ElementState::{Pressed, Released};
use events::Event::{Awakened, MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
use events::Event::{MouseWheel, Closed, Focused, TouchpadPressure};
use events::ElementState;
use events::{self, MouseButton, TouchPhase};
pub use self::monitor::{MonitorId, get_available_monitors, get_primary_monitor};
@ -72,7 +68,7 @@ impl WindowDelegate {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = state as *mut DelegateState;
(*state).pending_events.lock().unwrap().push_back(Closed);
(*state).pending_events.lock().unwrap().push_back(Event::Closed);
}
YES
}
@ -101,7 +97,7 @@ impl WindowDelegate {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = state as *mut DelegateState;
(*state).pending_events.lock().unwrap().push_back(Focused(true));
(*state).pending_events.lock().unwrap().push_back(Event::Focused(true));
}
}
@ -109,7 +105,7 @@ impl WindowDelegate {
unsafe {
let state: *mut c_void = *this.get_ivar("glutinState");
let state = state as *mut DelegateState;
(*state).pending_events.lock().unwrap().push_back(Focused(false));
(*state).pending_events.lock().unwrap().push_back(Event::Focused(false));
}
}
@ -167,8 +163,10 @@ impl Drop for WindowDelegate {
}
}
#[derive(Default)]
pub struct PlatformSpecificWindowBuilderAttributes;
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub activation_policy: ActivationPolicy,
}
pub struct Window {
view: IdRef,
@ -188,9 +186,9 @@ impl WindowProxy {
let pool = NSAutoreleasePool::new(nil);
let event =
NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
nil, NSApplicationDefined, NSPoint::new(0.0, 0.0), NSEventModifierFlags::empty(),
0.0, 0, nil, NSApplicationActivatedEventType, 0, 0);
NSApp().postEvent_atStart_(event, NO);
nil, appkit::NSApplicationDefined, NSPoint::new(0.0, 0.0), appkit::NSEventModifierFlags::empty(),
0.0, 0, nil, appkit::NSEventSubtype::NSApplicationActivatedEventType, 0, 0);
appkit::NSApp().postEvent_atStart_(event, NO);
pool.drain();
}
}
@ -212,8 +210,8 @@ impl<'a> Iterator for PollEventsIterator<'a> {
unsafe {
let pool = NSAutoreleasePool::new(nil);
let nsevent = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
NSAnyEventMask.bits() | NSEventMaskPressure.bits(),
let nsevent = appkit::NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
appkit::NSAnyEventMask.bits() | appkit::NSEventMaskPressure.bits(),
NSDate::distantPast(nil),
NSDefaultRunLoopMode,
YES);
@ -241,8 +239,8 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
unsafe {
let pool = NSAutoreleasePool::new(nil);
let nsevent = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
NSAnyEventMask.bits() | NSEventMaskPressure.bits(),
let nsevent = appkit::NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
appkit::NSAnyEventMask.bits() | appkit::NSEventMaskPressure.bits(),
NSDate::distantFuture(nil),
NSDefaultRunLoopMode,
YES);
@ -252,7 +250,7 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
}
if event.is_none() {
return Some(Awakened);
return Some(Event::Awakened);
} else {
return event;
}
@ -261,14 +259,15 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
impl Window {
pub fn new(win_attribs: &WindowAttributes,
_: &PlatformSpecificWindowBuilderAttributes)
-> Result<Window, CreationError>
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
-> Result<Window, CreationError>
{
// not implemented
assert!(win_attribs.min_dimensions.is_none());
assert!(win_attribs.max_dimensions.is_none());
let app = match Window::create_app() {
// let app = match Window::create_app() {
let app = match Window::create_app(pl_attribs.activation_policy) {
Some(app) => app,
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
};
@ -312,13 +311,13 @@ impl Window {
Ok(window)
}
fn create_app() -> Option<id> {
fn create_app(activation_policy: ActivationPolicy) -> Option<id> {
unsafe {
let app = NSApp();
let app = appkit::NSApp();
if app == nil {
None
} else {
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
app.setActivationPolicy_(activation_policy.into());
app.finishLaunching();
Some(app)
}
@ -334,13 +333,13 @@ impl Window {
_ => panic!("OS X monitors should always have a numeric native ID")
};
let matching_screen = {
let screens = NSScreen::screens(nil);
let screens = appkit::NSScreen::screens(nil);
let count: NSUInteger = msg_send![screens, count];
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
let mut matching_screen: Option<id> = None;
for i in 0..count {
let screen = msg_send![screens, objectAtIndex:i as NSUInteger];
let device_description = NSScreen::deviceDescription(screen);
let device_description = appkit::NSScreen::deviceDescription(screen);
let value: id = msg_send![device_description, objectForKey:*key];
if value != nil {
let screen_number: NSUInteger = msg_send![value, unsignedIntegerValue];
@ -352,12 +351,12 @@ impl Window {
}
matching_screen
};
Some(matching_screen.unwrap_or(NSScreen::mainScreen(nil)))
Some(matching_screen.unwrap_or(appkit::NSScreen::mainScreen(nil)))
},
None => None
};
let frame = match screen {
Some(screen) => NSScreen::frame(screen),
Some(screen) => appkit::NSScreen::frame(screen),
None => {
let (width, height) = attrs.dimensions.unwrap_or((800, 600));
NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
@ -366,42 +365,43 @@ impl Window {
let masks = if screen.is_some() || attrs.transparent {
// Fullscreen or transparent window
NSBorderlessWindowMask as NSUInteger |
NSResizableWindowMask as NSUInteger |
NSTitledWindowMask as NSUInteger
appkit::NSBorderlessWindowMask as NSUInteger |
appkit::NSResizableWindowMask as NSUInteger |
appkit::NSTitledWindowMask as NSUInteger
} else if attrs.decorations {
// Classic opaque window with titlebar
NSClosableWindowMask as NSUInteger |
NSMiniaturizableWindowMask as NSUInteger |
NSResizableWindowMask as NSUInteger |
NSTitledWindowMask as NSUInteger
appkit::NSClosableWindowMask as NSUInteger |
appkit::NSMiniaturizableWindowMask as NSUInteger |
appkit::NSResizableWindowMask as NSUInteger |
appkit::NSTitledWindowMask as NSUInteger
} else {
// Opaque window without a titlebar
NSClosableWindowMask as NSUInteger |
NSMiniaturizableWindowMask as NSUInteger |
NSResizableWindowMask as NSUInteger |
NSTitledWindowMask as NSUInteger |
NSFullSizeContentViewWindowMask as NSUInteger
appkit::NSClosableWindowMask as NSUInteger |
appkit::NSMiniaturizableWindowMask as NSUInteger |
appkit::NSResizableWindowMask as NSUInteger |
appkit::NSTitledWindowMask as NSUInteger |
appkit::NSFullSizeContentViewWindowMask as NSUInteger
};
let window = IdRef::new(NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
frame,
masks,
NSBackingStoreBuffered,
appkit::NSBackingStoreBuffered,
NO,
));
window.non_nil().map(|window| {
let title = IdRef::new(NSString::alloc(nil).init_str(&attrs.title));
window.setReleasedWhenClosed_(NO);
window.setTitle_(*title);
window.setAcceptsMouseMovedEvents_(YES);
if !attrs.decorations {
window.setTitleVisibility_(NSWindowTitleVisibility::NSWindowTitleHidden);
window.setTitleVisibility_(appkit::NSWindowTitleVisibility::NSWindowTitleHidden);
window.setTitlebarAppearsTransparent_(YES);
}
if screen.is_some() {
window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
window.setLevel_(appkit::NSMainMenuWindowLevel as i64 + 1);
}
else {
window.center();
@ -511,11 +511,11 @@ impl Window {
}
}
unsafe fn modifier_event(event: id, keymask: NSEventModifierFlags, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
unsafe fn modifier_event(event: id, keymask: appkit::NSEventModifierFlags, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
if !key_pressed && NSEvent::modifierFlags(event).contains(keymask) {
return Some(KeyboardInput(Pressed, NSEvent::keyCode(event) as u8, Some(key)));
return Some(Event::KeyboardInput(ElementState::Pressed, NSEvent::keyCode(event) as u8, Some(key)));
} else if key_pressed && !NSEvent::modifierFlags(event).contains(keymask) {
return Some(KeyboardInput(Released, NSEvent::keyCode(event) as u8, Some(key)));
return Some(Event::KeyboardInput(ElementState::Released, NSEvent::keyCode(event) as u8, Some(key)));
}
return None;
@ -609,7 +609,10 @@ impl Window {
unsafe {
// TODO: Check for errors.
let _ = CGWarpMouseCursorPosition(CGPoint { x: cursor_x as CGFloat, y: cursor_y as CGFloat });
let _ = CGWarpMouseCursorPosition(appkit::CGPoint {
x: cursor_x as appkit::CGFloat,
y: cursor_y as appkit::CGFloat,
});
let _ = CGAssociateMouseAndMouseCursorPosition(true);
}
@ -661,22 +664,22 @@ impl Clone for IdRef {
}
}
#[allow(non_snake_case)]
#[allow(non_snake_case, non_upper_case_globals)]
unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
if nsevent == nil { return None; }
let event_type = nsevent.eventType();
NSApp().sendEvent_(if let NSKeyDown = event_type { nil } else { nsevent });
appkit::NSApp().sendEvent_(if let appkit::NSKeyDown = event_type { nil } else { nsevent });
match event_type {
NSLeftMouseDown => { Some(MouseInput(Pressed, MouseButton::Left)) },
NSLeftMouseUp => { Some(MouseInput(Released, MouseButton::Left)) },
NSRightMouseDown => { Some(MouseInput(Pressed, MouseButton::Right)) },
NSRightMouseUp => { Some(MouseInput(Released, MouseButton::Right)) },
NSMouseMoved |
NSLeftMouseDragged |
NSOtherMouseDragged |
NSRightMouseDragged => {
appkit::NSLeftMouseDown => { Some(Event::MouseInput(ElementState::Pressed, MouseButton::Left)) },
appkit::NSLeftMouseUp => { Some(Event::MouseInput(ElementState::Released, MouseButton::Left)) },
appkit::NSRightMouseDown => { Some(Event::MouseInput(ElementState::Pressed, MouseButton::Right)) },
appkit::NSRightMouseUp => { Some(Event::MouseInput(ElementState::Released, MouseButton::Right)) },
appkit::NSMouseMoved |
appkit::NSLeftMouseDragged |
appkit::NSOtherMouseDragged |
appkit::NSRightMouseDragged => {
let window_point = nsevent.locationInWindow();
let cWindow: id = msg_send![nsevent, window];
let view_point = if cWindow == nil {
@ -688,29 +691,29 @@ unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
let view_rect = NSView::frame(*window.view);
let scale_factor = window.hidpi_factor();
Some(MouseMoved(((scale_factor * view_point.x as f32) as i32,
(scale_factor * (view_rect.size.height - view_point.y) as f32) as i32)))
Some(Event::MouseMoved((scale_factor * view_point.x as f32) as i32,
(scale_factor * (view_rect.size.height - view_point.y) as f32) as i32))
},
NSKeyDown => {
appkit::NSKeyDown => {
let mut events = VecDeque::new();
let received_c_str = nsevent.characters().UTF8String();
let received_str = CStr::from_ptr(received_c_str);
for received_char in from_utf8(received_str.to_bytes()).unwrap().chars() {
events.push_back(ReceivedCharacter(received_char));
events.push_back(Event::ReceivedCharacter(received_char));
}
let vkey = event::vkeycode_to_element(NSEvent::keyCode(nsevent));
events.push_back(KeyboardInput(Pressed, NSEvent::keyCode(nsevent) as u8, vkey));
events.push_back(Event::KeyboardInput(ElementState::Pressed, NSEvent::keyCode(nsevent) as u8, vkey));
let event = events.pop_front();
window.delegate.state.pending_events.lock().unwrap().extend(events.into_iter());
event
},
NSKeyUp => {
appkit::NSKeyUp => {
let vkey = event::vkeycode_to_element(NSEvent::keyCode(nsevent));
Some(KeyboardInput(Released, NSEvent::keyCode(nsevent) as u8, vkey))
Some(Event::KeyboardInput(ElementState::Released, NSEvent::keyCode(nsevent) as u8, vkey))
},
NSFlagsChanged => {
appkit::NSFlagsChanged => {
let mut events = VecDeque::new();
let shift_modifier = Window::modifier_event(nsevent, appkit::NSShiftKeyMask, events::VirtualKeyCode::LShift, shift_pressed);
if shift_modifier.is_some() {
@ -736,7 +739,7 @@ unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
window.delegate.state.pending_events.lock().unwrap().extend(events.into_iter());
event
},
NSScrollWheel => {
appkit::NSScrollWheel => {
use events::MouseScrollDelta::{LineDelta, PixelDelta};
let scale_factor = window.hidpi_factor();
let delta = if nsevent.hasPreciseScrollingDeltas() == YES {
@ -747,14 +750,14 @@ unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
scale_factor * nsevent.scrollingDeltaY() as f32)
};
let phase = match nsevent.phase() {
NSEventPhaseMayBegin | NSEventPhaseBegan => TouchPhase::Started,
NSEventPhaseEnded => TouchPhase::Ended,
appkit::NSEventPhaseMayBegin | appkit::NSEventPhaseBegan => TouchPhase::Started,
appkit::NSEventPhaseEnded => TouchPhase::Ended,
_ => TouchPhase::Moved,
};
Some(MouseWheel(delta, phase))
Some(Event::MouseWheel(delta, phase))
},
NSEventTypePressure => {
Some(TouchpadPressure(nsevent.pressure(), nsevent.stage()))
appkit::NSEventTypePressure => {
Some(Event::TouchpadPressure(nsevent.pressure(), nsevent.stage()))
},
_ => { None },
}