mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
Merge pull request #160 from glennw/mac-resize
Add callback function to allow resize messages to be sent on mac.
This commit is contained in:
commit
70f9f8cf43
|
@ -15,10 +15,15 @@ android_start!(main)
|
||||||
fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }
|
fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
fn main() {
|
fn resize_callback(width: uint, height: uint) {
|
||||||
let window = glutin::Window::new().unwrap();
|
println!("Window resized to {}x{}", width, height);
|
||||||
window.set_title("A fantastic window!");
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "window")]
|
||||||
|
fn main() {
|
||||||
|
let mut window = glutin::Window::new().unwrap();
|
||||||
|
window.set_title("A fantastic window!");
|
||||||
|
window.set_window_resize_callback(Some(resize_callback));
|
||||||
unsafe { window.make_current() };
|
unsafe { window.make_current() };
|
||||||
|
|
||||||
let context = support::load(&window);
|
let context = support::load(&window);
|
||||||
|
|
|
@ -273,6 +273,9 @@ impl Window {
|
||||||
pub fn get_api(&self) -> ::Api {
|
pub fn get_api(&self) -> ::Api {
|
||||||
::Api::OpenGlEs
|
::Api::OpenGlEs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -482,6 +482,14 @@ impl Window {
|
||||||
proxy: self.window.create_window_proxy()
|
proxy: self.window.create_window_proxy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets a resize callback that is called by Mac (and potentially other
|
||||||
|
/// operating systems) during resize operations. This can be used to repaint
|
||||||
|
/// during window resizing.
|
||||||
|
#[experimental]
|
||||||
|
pub fn set_window_resize_callback(&mut self, callback: Option<fn(uint, uint)>) {
|
||||||
|
self.window.set_window_resize_callback(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
|
@ -542,6 +550,10 @@ impl HeadlessContext {
|
||||||
pub fn get_api(&self) -> Api {
|
pub fn get_api(&self) -> Api {
|
||||||
self.context.get_api()
|
self.context.get_api()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[experimental]
|
||||||
|
pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "headless")]
|
#[cfg(feature = "headless")]
|
||||||
|
|
108
src/osx/mod.rs
108
src/osx/mod.rs
|
@ -18,12 +18,12 @@ use core_foundation::base::TCFType;
|
||||||
use core_foundation::string::CFString;
|
use core_foundation::string::CFString;
|
||||||
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
use std::c_str::CString;
|
use std::c_str::CString;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::atomic::{AtomicBool, Relaxed};
|
|
||||||
|
|
||||||
use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
|
use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, Resized, MouseWheel};
|
||||||
use events::ElementState::{Pressed, Released};
|
use events::ElementState::{Pressed, Released};
|
||||||
use events::MouseButton::{LeftMouseButton, RightMouseButton};
|
use events::MouseButton::{LeftMouseButton, RightMouseButton};
|
||||||
use events;
|
use events;
|
||||||
|
@ -42,25 +42,23 @@ static mut win_pressed: bool = false;
|
||||||
static mut alt_pressed: bool = false;
|
static mut alt_pressed: bool = false;
|
||||||
|
|
||||||
static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
|
static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
|
||||||
static DELEGATE_THIS_IVAR: &'static [u8] = b"glutin_this";
|
static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
|
||||||
|
|
||||||
struct InternalState {
|
struct DelegateState<'a> {
|
||||||
is_closed: AtomicBool,
|
is_closed: bool,
|
||||||
}
|
context: id,
|
||||||
|
view: id,
|
||||||
impl InternalState {
|
handler: Option<fn(uint, uint)>,
|
||||||
fn new() -> InternalState {
|
|
||||||
InternalState {
|
|
||||||
is_closed: AtomicBool::new(false),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
view: id,
|
view: id,
|
||||||
window: id,
|
window: id,
|
||||||
context: id,
|
context: id,
|
||||||
state: Box<InternalState>,
|
delegate: id,
|
||||||
|
resize: Option<fn(uint, uint)>,
|
||||||
|
|
||||||
|
is_closed: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
|
@ -103,16 +101,36 @@ impl WindowProxy {
|
||||||
extern fn window_should_close(this: id, _: id) -> id {
|
extern fn window_should_close(this: id, _: id) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut stored_value = ptr::null_mut();
|
let mut stored_value = ptr::null_mut();
|
||||||
object_getInstanceVariable(this, DELEGATE_THIS_IVAR.as_ptr() as *const i8, &mut stored_value);
|
object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
|
||||||
let state = stored_value as *mut InternalState;
|
let state = stored_value as *mut DelegateState;
|
||||||
(*state).is_closed.store(true, Relaxed);
|
|
||||||
|
(*state).is_closed = true;
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn window_did_resize(this: id, _: id) -> id {
|
||||||
|
unsafe {
|
||||||
|
let mut stored_value = ptr::null_mut();
|
||||||
|
object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
|
||||||
|
let state = &mut *(stored_value as *mut DelegateState);
|
||||||
|
|
||||||
|
let _: id = msg_send()(state.context, selector("update"));
|
||||||
|
|
||||||
|
match state.handler {
|
||||||
|
Some(handler) => {
|
||||||
|
let rect = NSView::frame(state.view);
|
||||||
|
(handler)(rect.size.width as uint, rect.size.height as uint);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
|
fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
|
||||||
vsync: bool, visible: bool) -> Result<Window, CreationError> {
|
vsync: bool, _visible: bool) -> Result<Window, CreationError> {
|
||||||
let app = match Window::create_app() {
|
let app = match Window::create_app() {
|
||||||
Some(app) => app,
|
Some(app) => app,
|
||||||
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
|
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
|
||||||
|
@ -136,30 +154,33 @@ impl Window {
|
||||||
window.makeKeyAndOrderFront_(nil);
|
window.makeKeyAndOrderFront_(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
let window = Window {
|
|
||||||
view: view,
|
|
||||||
window: window,
|
|
||||||
context: context,
|
|
||||||
state: box InternalState::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set up the window delegate to receive events
|
// Set up the window delegate to receive events
|
||||||
let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
|
let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
|
||||||
let ns_object = class("NSObject");
|
let ns_object = class("NSObject");
|
||||||
|
|
||||||
unsafe {
|
let delegate = unsafe {
|
||||||
// Create a delegate class, add callback methods and store InternalState as user data.
|
// Create a delegate class, add callback methods and store InternalState as user data.
|
||||||
let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
|
let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
|
||||||
class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
|
class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
|
||||||
class_addIvar(delegate, DELEGATE_THIS_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
|
class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, "V@:@".to_c_str().as_ptr());
|
||||||
|
class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
|
||||||
objc_registerClassPair(delegate);
|
objc_registerClassPair(delegate);
|
||||||
|
|
||||||
let del_obj = msg_send()(delegate, selector("alloc"));
|
let del_obj = msg_send()(delegate, selector("alloc"));
|
||||||
let del_obj: id = msg_send()(del_obj, selector("init"));
|
let del_obj: id = msg_send()(del_obj, selector("init"));
|
||||||
object_setInstanceVariable(del_obj, DELEGATE_THIS_IVAR.as_ptr() as *const i8,
|
let _: id = msg_send()(window, selector("setDelegate:"), del_obj);
|
||||||
&*window.state as *const InternalState as *mut libc::c_void);
|
del_obj
|
||||||
let _: id = msg_send()(window.window, selector("setDelegate:"), del_obj);
|
};
|
||||||
}
|
|
||||||
|
let window = Window {
|
||||||
|
view: view,
|
||||||
|
window: window,
|
||||||
|
context: context,
|
||||||
|
delegate: delegate,
|
||||||
|
resize: None,
|
||||||
|
|
||||||
|
is_closed: Cell::new(false),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(window)
|
Ok(window)
|
||||||
}
|
}
|
||||||
|
@ -267,7 +288,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_closed(&self) -> bool {
|
pub fn is_closed(&self) -> bool {
|
||||||
self.state.is_closed.load(Relaxed)
|
self.is_closed.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_title(&self, title: &str) {
|
pub fn set_title(&self, title: &str) {
|
||||||
|
@ -319,7 +340,26 @@ impl Window {
|
||||||
NSDefaultRunLoopMode,
|
NSDefaultRunLoopMode,
|
||||||
true);
|
true);
|
||||||
if event == nil { break; }
|
if event == nil { break; }
|
||||||
|
{
|
||||||
|
// Create a temporary structure with state that delegates called internally
|
||||||
|
// by sendEvent can read and modify. When that returns, update window state.
|
||||||
|
// This allows the synchronous resize loop to continue issuing callbacks
|
||||||
|
// to the user application, by passing handler through to the delegate state.
|
||||||
|
let mut ds = DelegateState {
|
||||||
|
is_closed: self.is_closed.get(),
|
||||||
|
context: self.context,
|
||||||
|
view: self.view,
|
||||||
|
handler: self.resize,
|
||||||
|
};
|
||||||
|
object_setInstanceVariable(self.delegate,
|
||||||
|
DELEGATE_STATE_IVAR.as_ptr() as *const i8,
|
||||||
|
&mut ds as *mut DelegateState as *mut libc::c_void);
|
||||||
NSApp().sendEvent_(event);
|
NSApp().sendEvent_(event);
|
||||||
|
object_setInstanceVariable(self.delegate,
|
||||||
|
DELEGATE_STATE_IVAR.as_ptr() as *const i8,
|
||||||
|
ptr::null_mut());
|
||||||
|
self.is_closed.set(ds.is_closed);
|
||||||
|
}
|
||||||
|
|
||||||
match event.get_type() {
|
match event.get_type() {
|
||||||
NSLeftMouseDown => { events.push(MouseInput(Pressed, LeftMouseButton)); },
|
NSLeftMouseDown => { events.push(MouseInput(Pressed, LeftMouseButton)); },
|
||||||
|
@ -434,4 +474,8 @@ impl Window {
|
||||||
pub fn get_api(&self) -> ::Api {
|
pub fn get_api(&self) -> ::Api {
|
||||||
::Api::OpenGl
|
::Api::OpenGl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_window_resize_callback(&mut self, callback: Option<fn(uint, uint)>) {
|
||||||
|
self.resize = callback;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,9 @@ impl HeadlessContext {
|
||||||
pub fn get_api(&self) -> ::Api {
|
pub fn get_api(&self) -> ::Api {
|
||||||
::Api::OpenGl
|
::Api::OpenGl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Win32 implementation of the main `Window` object.
|
/// The Win32 implementation of the main `Window` object.
|
||||||
|
@ -276,6 +279,9 @@ impl Window {
|
||||||
pub fn get_api(&self) -> ::Api {
|
pub fn get_api(&self) -> ::Api {
|
||||||
::Api::OpenGl
|
::Api::OpenGl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
|
|
|
@ -52,6 +52,9 @@ impl HeadlessContext {
|
||||||
pub fn get_api(&self) -> ::Api {
|
pub fn get_api(&self) -> ::Api {
|
||||||
::Api::OpenGl
|
::Api::OpenGl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for HeadlessContext {
|
impl Drop for HeadlessContext {
|
||||||
|
|
|
@ -598,4 +598,7 @@ impl Window {
|
||||||
pub fn get_api(&self) -> ::Api {
|
pub fn get_api(&self) -> ::Api {
|
||||||
::Api::OpenGl
|
::Api::OpenGl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue