use crate::Error;
use super::device::{Adapter, Device, NativeDevice};
use super::surface::{NSView, NativeWidget};
use cocoa::base::id;
use core_foundation::base::TCFType;
use core_foundation::boolean::CFBoolean;
use core_foundation::bundle::CFBundleGetInfoDictionary;
use core_foundation::bundle::CFBundleGetMainBundle;
use core_foundation::dictionary::{CFMutableDictionary, CFMutableDictionaryRef};
use core_foundation::string::CFString;
use euclid::default::Size2D;
use std::str::FromStr;
use std::os::raw::c_void;
#[cfg(feature = "sm-winit")]
use winit::Window;
#[cfg(feature = "sm-winit")]
use winit::os::macos::WindowExt;
#[derive(Clone)]
pub struct Connection;
#[derive(Clone)]
pub struct NativeConnection;
impl Connection {
#[inline]
pub fn new() -> Result<Connection, Error> {
unsafe {
let main_bundle = CFBundleGetMainBundle();
assert!(!main_bundle.is_null());
let bundle_info_dictionary = CFBundleGetInfoDictionary(main_bundle) as
CFMutableDictionaryRef;
assert!(!bundle_info_dictionary.is_null());
let mut bundle_info_dictionary =
CFMutableDictionary::wrap_under_get_rule(bundle_info_dictionary);
let supports_automatic_graphics_switching_key: CFString =
FromStr::from_str("NSSupportsAutomaticGraphicsSwitching").unwrap();
let supports_automatic_graphics_switching_value: CFBoolean =
CFBoolean::true_value();
bundle_info_dictionary.set(supports_automatic_graphics_switching_key,
supports_automatic_graphics_switching_value);
}
Ok(Connection)
}
#[inline]
pub unsafe fn from_native_connection(_: NativeConnection) -> Result<Connection, Error> {
Connection::new()
}
#[inline]
pub fn native_connection(&self) -> NativeConnection {
NativeConnection
}
#[inline]
pub fn create_adapter(&self) -> Result<Adapter, Error> {
self.create_hardware_adapter()
}
#[inline]
pub fn create_hardware_adapter(&self) -> Result<Adapter, Error> {
Ok(Adapter { is_low_power: false })
}
#[inline]
pub fn create_low_power_adapter(&self) -> Result<Adapter, Error> {
Ok(Adapter { is_low_power: true })
}
#[inline]
pub fn create_software_adapter(&self) -> Result<Adapter, Error> {
self.create_low_power_adapter()
}
#[inline]
pub fn create_device(&self, adapter: &Adapter) -> Result<Device, Error> {
Device::new((*adapter).clone())
}
#[inline]
pub unsafe fn create_device_from_native_device(&self, _: NativeDevice)
-> Result<Device, Error> {
self.create_device(&self.create_adapter()?)
}
#[cfg(feature = "sm-winit")]
pub fn from_winit_window(_: &Window) -> Result<Connection, Error> {
Connection::new()
}
#[cfg(feature = "sm-winit")]
pub fn create_native_widget_from_winit_window(&self, window: &Window)
-> Result<NativeWidget, Error> {
let ns_view = window.get_nsview() as id;
if ns_view.is_null() {
return Err(Error::IncompatibleNativeWidget);
}
unsafe {
Ok(NativeWidget { view: NSView(msg_send![ns_view, retain]) })
}
}
pub unsafe fn create_native_widget_from_ptr(&self, raw: *mut c_void, _size: Size2D<i32>) -> NativeWidget {
NativeWidget {
view: NSView(raw as id),
}
}
#[cfg(feature = "sm-raw-window-handle")]
#[inline]
pub fn create_native_widget_from_rwh(&self, raw_handle: raw_window_handle::RawWindowHandle)
-> Result<NativeWidget, Error> {
use raw_window_handle::RawWindowHandle::MacOS;
match raw_handle {
MacOS(handle) => Ok(NativeWidget {
view: NSView(unsafe {
msg_send![handle.ns_view as id, retain]
}),
}),
_ => Err(Error::IncompatibleNativeWidget),
}
}
}
impl NativeConnection {
#[inline]
pub fn current() -> Result<NativeConnection, Error> {
Ok(NativeConnection)
}
}