mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-29 04:51:09 +00:00
examples/tutorials: Use cocoa crate to initialize the shared NSApplication instance
This is required for OpenGL to work nowadays on macOS. Simply running an CFRunLoop on the main thread is not sufficient. Thanks to Philippe Normand for testing this on macOS and making sure it actually compiles and works.
This commit is contained in:
parent
386bd05817
commit
a091ea201c
4 changed files with 74 additions and 92 deletions
|
@ -36,6 +36,9 @@ glutin = { version = "0.27", optional = true }
|
||||||
once_cell = "1.0"
|
once_cell = "1.0"
|
||||||
image = { version="0.23", optional = true }
|
image = { version="0.23", optional = true }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
|
cocoa = "0.24"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gl_generator = { version = "0.14", optional = true }
|
gl_generator = { version = "0.14", optional = true }
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,6 @@
|
||||||
/// macOS has a specific requirement that there must be a run loop running
|
/// macOS has a specific requirement that there must be a run loop running on the main thread in
|
||||||
/// on the main thread in order to open windows and use OpenGL.
|
/// order to open windows and use OpenGL, and that the global NSApplication instance must be
|
||||||
|
/// initialized.
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
mod runloop {
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
pub struct CFRunLoop(*mut c_void);
|
|
||||||
|
|
||||||
#[link(name = "foundation", kind = "framework")]
|
|
||||||
extern "C" {
|
|
||||||
fn CFRunLoopRun();
|
|
||||||
fn CFRunLoopGetMain() -> *mut c_void;
|
|
||||||
fn CFRunLoopStop(l: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CFRunLoop {
|
|
||||||
pub fn run() {
|
|
||||||
unsafe {
|
|
||||||
CFRunLoopRun();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(alias = "get_main")]
|
|
||||||
pub fn main() -> CFRunLoop {
|
|
||||||
unsafe {
|
|
||||||
let r = CFRunLoopGetMain();
|
|
||||||
assert!(!r.is_null());
|
|
||||||
CFRunLoop(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stop(&self) {
|
|
||||||
unsafe { CFRunLoopStop(self.0) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for CFRunLoop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// On macOS this launches the callback function on a thread.
|
/// On macOS this launches the callback function on a thread.
|
||||||
/// On other platforms it's just executed immediately.
|
/// On other platforms it's just executed immediately.
|
||||||
|
@ -52,16 +17,38 @@ pub fn run<T, F: FnOnce() -> T + Send + 'static>(main: F) -> T
|
||||||
where
|
where
|
||||||
T: Send + 'static,
|
T: Send + 'static,
|
||||||
{
|
{
|
||||||
|
use cocoa::appkit::NSApplication;
|
||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
let l = runloop::CFRunLoop::main();
|
unsafe {
|
||||||
let t = thread::spawn(move || {
|
let app = cocoa::appkit::NSApp();
|
||||||
let res = main();
|
let t = thread::spawn(|| {
|
||||||
l.stop();
|
let res = main();
|
||||||
res
|
|
||||||
});
|
|
||||||
|
|
||||||
runloop::CFRunLoop::run();
|
let app = cocoa::appkit::NSApp();
|
||||||
|
app.stop_(cocoa::base::nil);
|
||||||
|
|
||||||
t.join().unwrap()
|
// Stopping the event loop requires an actual event
|
||||||
|
let event = cocoa::appkit::NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
|
||||||
|
cocoa::base::nil,
|
||||||
|
cocoa::appkit::NSEventType::NSApplicationDefined,
|
||||||
|
cocoa::foundation::NSPoint { x: 0.0, y: 0.0 },
|
||||||
|
cocoa::appkit::NSEventModifierFlags::empty(),
|
||||||
|
0.0,
|
||||||
|
0,
|
||||||
|
cocoa::base::nil,
|
||||||
|
cocoa::appkit::NSEventSubtype::NSApplicationActivatedEventType,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
app.postEvent_atStart_(event, cocoa::base::YES);
|
||||||
|
|
||||||
|
res
|
||||||
|
});
|
||||||
|
|
||||||
|
app.run();
|
||||||
|
|
||||||
|
t.join().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ byte-slice-cast = "1"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
termion = { version = "1.5", optional = true }
|
termion = { version = "1.5", optional = true }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
|
cocoa = "0.24"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
tutorial5 = ["gtk", "gdk", "gst-video"]
|
tutorial5 = ["gtk", "gdk", "gst-video"]
|
||||||
tutorial5-x11 = ["tutorial5"]
|
tutorial5-x11 = ["tutorial5"]
|
||||||
|
|
|
@ -1,41 +1,6 @@
|
||||||
/// macOS has a specific requirement that there must be a run loop running
|
/// macOS has a specific requirement that there must be a run loop running on the main thread in
|
||||||
/// on the main thread in order to open windows and use OpenGL.
|
/// order to open windows and use OpenGL, and that the global NSApplication instance must be
|
||||||
|
/// initialized.
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
mod runloop {
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
pub struct CFRunLoop(*mut c_void);
|
|
||||||
|
|
||||||
#[link(name = "foundation", kind = "framework")]
|
|
||||||
extern "C" {
|
|
||||||
fn CFRunLoopRun();
|
|
||||||
fn CFRunLoopGetMain() -> *mut c_void;
|
|
||||||
fn CFRunLoopStop(l: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CFRunLoop {
|
|
||||||
pub fn run() {
|
|
||||||
unsafe {
|
|
||||||
CFRunLoopRun();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(alias = "get_main")]
|
|
||||||
pub fn main() -> CFRunLoop {
|
|
||||||
unsafe {
|
|
||||||
let r = CFRunLoopGetMain();
|
|
||||||
assert!(!r.is_null());
|
|
||||||
CFRunLoop(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stop(&self) {
|
|
||||||
unsafe { CFRunLoopStop(self.0) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for CFRunLoop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// On macOS this launches the callback function on a thread.
|
/// On macOS this launches the callback function on a thread.
|
||||||
/// On other platforms it's just executed immediately.
|
/// On other platforms it's just executed immediately.
|
||||||
|
@ -52,16 +17,40 @@ pub fn run<T, F: FnOnce() -> T + Send + 'static>(main: F) -> T
|
||||||
where
|
where
|
||||||
T: Send + 'static,
|
T: Send + 'static,
|
||||||
{
|
{
|
||||||
|
use cocoa::appkit::NSApplication;
|
||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
let l = runloop::CFRunLoop::main();
|
unsafe {
|
||||||
let t = thread::spawn(move || {
|
let app = cocoa::appkit::NSApp();
|
||||||
let res = main();
|
let t = thread::spawn(|| {
|
||||||
l.stop();
|
let res = main();
|
||||||
res
|
|
||||||
});
|
|
||||||
|
|
||||||
runloop::CFRunLoop::run();
|
let app = cocoa::appkit::NSApp();
|
||||||
|
app.stop_(cocoa::base::nil);
|
||||||
|
|
||||||
t.join().unwrap()
|
// Stopping the event loop requires an actual event
|
||||||
|
let event = cocoa::appkit::NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
|
||||||
|
cocoa::base::nil,
|
||||||
|
cocoa::appkit::NSEventType::NSApplicationDefined,
|
||||||
|
cocoa::foundation::NSPoint { x: 0.0, y: 0.0 },
|
||||||
|
cocoa::appkit::NSEventModifierFlags::empty(),
|
||||||
|
0.0,
|
||||||
|
0,
|
||||||
|
cocoa::base::nil,
|
||||||
|
cocoa::appkit::NSEventSubtype::NSApplicationActivatedEventType,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
app.postEvent_atStart_(event, cocoa::base::YES);
|
||||||
|
|
||||||
|
std::process::exit(0);
|
||||||
|
|
||||||
|
res
|
||||||
|
});
|
||||||
|
|
||||||
|
app.run();
|
||||||
|
|
||||||
|
t.join().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue