mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2025-01-11 11:31:32 +11:00
Mac fixes
* Removed hard coded global values for width, height, buffer - These are now tracked on a per window basis. * Fixed multi-window support * Various cleanup and fixes
This commit is contained in:
parent
092965cb49
commit
946aa5ec14
|
@ -15,8 +15,7 @@ fn main() {
|
|||
let mut window = Window::new("Noise Test - Press ESC to exit",
|
||||
WIDTH,
|
||||
HEIGHT,
|
||||
Scale::X1,
|
||||
Vsync::No)
|
||||
Scale::X1)
|
||||
.unwrap();
|
||||
|
||||
while window.is_open() && !window.is_key_down(Key::Escape) {
|
||||
|
|
35
src/lib.rs
35
src/lib.rs
|
@ -1,14 +1,3 @@
|
|||
extern crate libc;
|
||||
#[cfg(target_os = "macos")]
|
||||
#[macro_use]
|
||||
extern crate objc;
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate cgl;
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate cocoa;
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate core_foundation;
|
||||
|
||||
/// Scale will scale the frame buffer and the window that is being sent in when calling the update
|
||||
/// function. This is useful if you for example want to display a 320 x 256 window on a screen with
|
||||
/// much higher resolution which would result in that the window is very small.
|
||||
|
@ -32,20 +21,6 @@ pub enum Scale {
|
|||
X32,
|
||||
}
|
||||
|
||||
/// Vsync will allow syncronized rendering with the screen refresh rate.
|
||||
/// Currently Vsync isn't implemented so nothing will change regardless of given value right now
|
||||
pub enum Vsync {
|
||||
/// No vsync
|
||||
No,
|
||||
/// Require accurate vsync. Notice that if the library is unable to to setup an accurate
|
||||
/// syncing the window creation will fail.
|
||||
Accurate,
|
||||
/// Setup a best guess syncing with the screen. This will always succesed but may not be
|
||||
/// accurate. What this means is if the lib is unable to create a accurate syncing approach
|
||||
/// a 'emulated' one will be used (for example using a timer to approximate syncing)
|
||||
BestGuess,
|
||||
}
|
||||
|
||||
/// Used for is_key_pressed and get_keys_pressed() to indicated if repeat of presses is wanted
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub enum KeyRepeat {
|
||||
|
@ -172,13 +147,15 @@ pub enum Key {
|
|||
Count = 103,
|
||||
}
|
||||
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod windows;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::*;
|
||||
|
||||
//#[cfg(target_os = "macos")]
|
||||
//pub mod macos;
|
||||
//#[cfg(target_os = "macos")]
|
||||
//pub use macos::*;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use macos::*;
|
||||
|
||||
|
|
396
src/macos.rs
396
src/macos.rs
|
@ -1,377 +1,93 @@
|
|||
#![cfg(target_os = "macos")]
|
||||
|
||||
use Scale;
|
||||
use Vsync;
|
||||
use Key;
|
||||
use {Scale, Key, KeyRepeat};
|
||||
|
||||
use libc;
|
||||
//use cocoa::appkit;
|
||||
use cocoa::appkit::*;
|
||||
//use cocoa::appkit::NSEventSubtype::*;
|
||||
use libc::{c_void, c_char, c_uchar};
|
||||
use std::ffi::{CString};
|
||||
use std::ptr;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use cocoa::base::{id, nil};
|
||||
#[allow(unused_imports)]
|
||||
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
|
||||
use objc::declare::ClassDecl;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
|
||||
NSString, NSUInteger};
|
||||
|
||||
use std::ops::Deref;
|
||||
#[link(name = "Cocoa", kind = "framework")]
|
||||
extern {
|
||||
fn mfb_open(name: *const c_char, width: u32, height: u32, scale: u32) -> *mut c_void;
|
||||
fn mfb_close(window: *mut c_void);
|
||||
fn mfb_update(window: *mut c_void, buffer: *const c_uchar);
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
view: IdRef,
|
||||
window: IdRef,
|
||||
delegate: WindowDelegate,
|
||||
view_delegate: ViewDelegate,
|
||||
window_handle: *mut c_void,
|
||||
}
|
||||
|
||||
struct DelegateState {
|
||||
view: IdRef,
|
||||
window: IdRef,
|
||||
resize_handler: Option<fn(u32, u32)>,
|
||||
}
|
||||
|
||||
struct WindowDelegate {
|
||||
state: Box<DelegateState>,
|
||||
_this: IdRef,
|
||||
}
|
||||
|
||||
struct ViewDelegateState {
|
||||
view: IdRef,
|
||||
}
|
||||
|
||||
struct ViewDelegate {
|
||||
state: Box<ViewDelegateState>,
|
||||
_this: IdRef,
|
||||
}
|
||||
|
||||
impl WindowDelegate {
|
||||
/// Get the delegate class, initiailizing it neccessary
|
||||
fn class() -> *const Class {
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
|
||||
extern fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
||||
println!("Should close");
|
||||
unsafe {
|
||||
//let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
|
||||
//let state = state as *mut DelegateState;
|
||||
//(*state).pending_events.lock().unwrap().push_back(Closed);
|
||||
}
|
||||
YES
|
||||
}
|
||||
|
||||
extern fn window_did_resize(this: &Object, _: Sel, _: id) {
|
||||
unsafe {
|
||||
let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
|
||||
let state = &mut *(state as *mut DelegateState);
|
||||
|
||||
println!("did_resize");
|
||||
|
||||
//let _: () = msg_send![*state.context, update];
|
||||
|
||||
if let Some(handler) = state.resize_handler {
|
||||
let rect = NSView::frame(*state.view);
|
||||
let scale_factor = NSWindow::backingScaleFactor(*state.window) as f32;
|
||||
(handler)((scale_factor * rect.size.width as f32) as u32,
|
||||
(scale_factor * rect.size.height as f32) as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern fn window_did_become_key(this: &Object, _: Sel, _: id) {
|
||||
unsafe {
|
||||
// TODO: center the cursor if the window had mouse grab when it
|
||||
// lost focus
|
||||
|
||||
println!("became key window");
|
||||
let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
|
||||
let state = state as *mut DelegateState;
|
||||
//(*state).pending_events.lock().unwrap().push_back(Focused(true));
|
||||
}
|
||||
}
|
||||
|
||||
extern fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
||||
unsafe {
|
||||
let state: *mut libc::c_void = *this.get_ivar("minifb_window_state");
|
||||
let state = state as *mut DelegateState;
|
||||
//(*state).pending_events.lock().unwrap().push_back(Focused(false));
|
||||
}
|
||||
}
|
||||
|
||||
static mut delegate_class: *const Class = 0 as *const Class;
|
||||
static INIT: Once = ONCE_INIT;
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
println!("Create new NSWindowDelegate");
|
||||
let superclass = Class::get("NSObject").unwrap();
|
||||
let mut decl = ClassDecl::new(superclass, "minifb_window_delegate").unwrap();
|
||||
|
||||
// Add callback methods
|
||||
decl.add_method(sel!(windowShouldClose:),
|
||||
window_should_close as extern fn(&Object, Sel, id) -> BOOL);
|
||||
decl.add_method(sel!(windowDidResize:),
|
||||
window_did_resize as extern fn(&Object, Sel, id));
|
||||
|
||||
decl.add_method(sel!(windowDidBecomeKey:),
|
||||
window_did_become_key as extern fn(&Object, Sel, id));
|
||||
decl.add_method(sel!(windowDidResignKey:),
|
||||
window_did_resign_key as extern fn(&Object, Sel, id));
|
||||
|
||||
// Store internal state as user data
|
||||
decl.add_ivar::<*mut libc::c_void>("minifb_window_state");
|
||||
|
||||
delegate_class = decl.register();
|
||||
});
|
||||
|
||||
unsafe {
|
||||
delegate_class
|
||||
}
|
||||
}
|
||||
|
||||
fn new(state: DelegateState) -> WindowDelegate {
|
||||
// Box the state so we can give a pointer to it
|
||||
let mut state = Box::new(state);
|
||||
let state_ptr: *mut DelegateState = &mut *state;
|
||||
unsafe {
|
||||
let delegate = IdRef::new(msg_send![WindowDelegate::class(), new]);
|
||||
|
||||
(&mut **delegate).set_ivar("minifb_window_state", state_ptr as *mut libc::c_void);
|
||||
let _: () = msg_send![*state.window, setDelegate:*delegate];
|
||||
|
||||
println!("Setup delegate");
|
||||
|
||||
WindowDelegate { state: state, _this: delegate }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WindowDelegate {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Nil the window's delegate so it doesn't still reference us
|
||||
let _: () = msg_send![*self.state.window, setDelegate:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewDelegate {
|
||||
fn class() -> *const Class {
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
|
||||
extern fn draw_rect(this: &Object, _: Sel, _: id) {
|
||||
println!("draw_rect");
|
||||
}
|
||||
|
||||
static mut delegate_class: *const Class = 0 as *const Class;
|
||||
static INIT: Once = ONCE_INIT;
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
println!("Create new ViewDelegate");
|
||||
let superclass = Class::get("NSObject").unwrap();
|
||||
let mut decl = ClassDecl::new(superclass, "minifb_view_delegate").unwrap();
|
||||
|
||||
// Add callback methods
|
||||
decl.add_method(sel!(drawRect:),
|
||||
draw_rect as extern fn(&Object, Sel, id));
|
||||
// Store internal state as user data
|
||||
decl.add_ivar::<*mut libc::c_void>("minifb_view_state");
|
||||
|
||||
delegate_class = decl.register();
|
||||
});
|
||||
|
||||
unsafe {
|
||||
delegate_class
|
||||
}
|
||||
}
|
||||
|
||||
fn new(state: ViewDelegateState) -> ViewDelegate {
|
||||
let mut state = Box::new(state);
|
||||
let state_ptr: *mut ViewDelegateState = &mut *state;
|
||||
unsafe {
|
||||
let delegate = IdRef::new(msg_send![ViewDelegate::class(), new]);
|
||||
|
||||
(&mut **delegate).set_ivar("minifb_view_state", state_ptr as *mut libc::c_void);
|
||||
let _: () = msg_send![*state.view, setDelegate:*delegate];
|
||||
|
||||
ViewDelegate { state: state, _this: delegate }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ViewDelegate {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Nil the views's delegate so it doesn't still reference us
|
||||
let _: () = msg_send![*self.state.view, setDelegate:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Window {
|
||||
pub fn new(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result<Window, &str> {
|
||||
pub fn new(name: &str,
|
||||
width: usize,
|
||||
height: usize,
|
||||
scale: Scale)
|
||||
-> Result<Window, &str> {
|
||||
let n = match CString::new(name) {
|
||||
Err(_) => {
|
||||
println!("Unable to convert {} to c_string", name);
|
||||
return Err("Unable to set correct name");
|
||||
}
|
||||
Ok(n) => n,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let app = match Self::create_app() {
|
||||
Some(app) => app,
|
||||
None => {
|
||||
return Err("Couldn't create NSApplication");
|
||||
},
|
||||
};
|
||||
let handle = mfb_open(n.as_ptr(), width as u32, height as u32, scale as u32);
|
||||
|
||||
let window = match Self::create_window(name, width, height) {
|
||||
Some(window) => window,
|
||||
None => {
|
||||
return Err("Unable to create NSWindow");
|
||||
if handle == ptr::null_mut() {
|
||||
return Err("Unable to open Window");
|
||||
}
|
||||
};
|
||||
|
||||
let view = match Self::create_view(*window) {
|
||||
Some(view) => view,
|
||||
None => {
|
||||
return Err("Unable to create NSView");
|
||||
}
|
||||
};
|
||||
|
||||
app.activateIgnoringOtherApps_(YES);
|
||||
window.makeKeyAndOrderFront_(nil);
|
||||
|
||||
let ds = DelegateState {
|
||||
view: view.clone(),
|
||||
window: window.clone(),
|
||||
resize_handler: None,
|
||||
};
|
||||
|
||||
let vs = ViewDelegateState {
|
||||
view: view.clone(),
|
||||
};
|
||||
|
||||
println!("Created window and view");
|
||||
|
||||
return Ok(Window {
|
||||
window: window,
|
||||
view: view,
|
||||
delegate: WindowDelegate::new(ds),
|
||||
view_delegate: ViewDelegate::new(vs),
|
||||
});
|
||||
Ok(Window { window_handle: handle })
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn create_window(name: &str, width: usize, height: usize) -> Option<IdRef> {
|
||||
let masks = NSResizableWindowMask as NSUInteger |
|
||||
NSClosableWindowMask as NSUInteger |
|
||||
NSTitledWindowMask as NSUInteger;
|
||||
|
||||
let frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));
|
||||
|
||||
let window = IdRef::new(NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
||||
frame,
|
||||
masks,
|
||||
NSBackingStoreBuffered,
|
||||
NO,
|
||||
));
|
||||
|
||||
window.non_nil().map(|window| {
|
||||
let title = IdRef::new(NSString::alloc(nil).init_str(name));
|
||||
window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
|
||||
window.setTitle_(*title);
|
||||
window.center();
|
||||
window
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn create_view(window: id) -> Option<IdRef> {
|
||||
let view = IdRef::new(NSView::alloc(nil).init());
|
||||
view.non_nil().map(|view| {
|
||||
window.setContentView_(*view);
|
||||
view
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update(&self, _: &[u32]) {
|
||||
pub fn update(&mut self, buffer: &[u32]) {
|
||||
unsafe {
|
||||
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
||||
NSAnyEventMask.bits(),
|
||||
NSDate::distantPast(nil),
|
||||
NSDefaultRunLoopMode,
|
||||
YES);
|
||||
|
||||
if event != nil {
|
||||
NSApp().sendEvent_(event);
|
||||
}
|
||||
mfb_update(self.window_handle, buffer.as_ptr() as *const u8);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_keys() -> Option<Vec<Key>> {
|
||||
return None;
|
||||
pub fn get_keys(&self) -> Option<Vec<Key>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn is_esc_pressed() -> bool {
|
||||
pub fn get_keys_pressed(&self, _: KeyRepeat) -> Option<Vec<Key>> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_key_down(&self, _: Key) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn close() {
|
||||
|
||||
#[inline]
|
||||
pub fn set_key_repeat_delay(&mut self, _: f32) {
|
||||
}
|
||||
|
||||
fn create_app() -> Option<id> {
|
||||
unsafe {
|
||||
let app = NSApp();
|
||||
if app == nil {
|
||||
None
|
||||
} else {
|
||||
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
||||
Some(app)
|
||||
#[inline]
|
||||
pub fn set_key_repeat_rate(&mut self, _: f32) {
|
||||
}
|
||||
|
||||
pub fn key_pressed(&self, _: usize, _: KeyRepeat) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_key_pressed(&self, _: Key, _: KeyRepeat) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_open(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct IdRef(id);
|
||||
|
||||
impl IdRef {
|
||||
fn new(i: id) -> IdRef {
|
||||
IdRef(i)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn retain(i: id) -> IdRef {
|
||||
if i != nil {
|
||||
let _: id = unsafe { msg_send![i, retain] };
|
||||
}
|
||||
IdRef(i)
|
||||
}
|
||||
|
||||
fn non_nil(self) -> Option<IdRef> {
|
||||
if self.0 == nil { None } else { Some(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for IdRef {
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
if self.0 != nil {
|
||||
let _: () = unsafe { msg_send![self.0, release] };
|
||||
unsafe {
|
||||
mfb_close(self.window_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for IdRef {
|
||||
type Target = id;
|
||||
fn deref<'a>(&'a self) -> &'a id {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for IdRef {
|
||||
fn clone(&self) -> IdRef {
|
||||
if self.0 != nil {
|
||||
let _: id = unsafe { msg_send![self.0, retain] };
|
||||
}
|
||||
IdRef(self.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,83 +3,74 @@
|
|||
#include <Cocoa/Cocoa.h>
|
||||
#include <unistd.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* g_updateBuffer = 0;
|
||||
int g_width = 0;
|
||||
int g_height = 0;
|
||||
static NSWindow* window_;
|
||||
static bool s_init = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int mfb_open(const char* name, int width, int height)
|
||||
void* mfb_open(const char* name, int width, int height, int scale)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
g_width = width;
|
||||
g_height = height;
|
||||
|
||||
if (!s_init) {
|
||||
[NSApplication sharedApplication];
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
s_init = true;
|
||||
}
|
||||
|
||||
unsigned int styles = NSResizableWindowMask | NSClosableWindowMask | NSTitledWindowMask;
|
||||
|
||||
NSRect rectangle = NSMakeRect(0, 0, width, height);
|
||||
window_ = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO];
|
||||
OSXWindow* window = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO];
|
||||
|
||||
if (!window_)
|
||||
if (!window)
|
||||
return 0;
|
||||
|
||||
[window_ setTitle:[NSString stringWithUTF8String:name]];
|
||||
[window_ setReleasedWhenClosed:NO];
|
||||
[window_ performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:YES];
|
||||
window->draw_buffer = malloc(width * height * 4);
|
||||
|
||||
[window_ center];
|
||||
if (!window->draw_buffer)
|
||||
return 0;
|
||||
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
window->scale = scale;
|
||||
|
||||
[window updateSize];
|
||||
|
||||
[window setTitle:[NSString stringWithUTF8String:name]];
|
||||
[window setReleasedWhenClosed:NO];
|
||||
[window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:YES];
|
||||
|
||||
[window center];
|
||||
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
||||
[pool drain];
|
||||
|
||||
return 1;
|
||||
return window;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void mfb_close()
|
||||
void mfb_close(void* win)
|
||||
{
|
||||
NSWindow* window = (NSWindow*)win;
|
||||
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (window_)
|
||||
[window_ close];
|
||||
if (window)
|
||||
[window close];
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int updateEvents()
|
||||
static int update_events()
|
||||
{
|
||||
int state = 0;
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
if (event)
|
||||
{
|
||||
switch ([event type])
|
||||
{
|
||||
case NSKeyDown:
|
||||
case NSKeyUp:
|
||||
{
|
||||
state = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
default :
|
||||
{
|
||||
[NSApp sendEvent:event];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[pool release];
|
||||
|
||||
return state;
|
||||
|
@ -87,10 +78,13 @@ static int updateEvents()
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int mfb_update(void* buffer)
|
||||
int mfb_update(void* window, void* buffer)
|
||||
{
|
||||
g_updateBuffer = buffer;
|
||||
int state = updateEvents();
|
||||
[[window_ contentView] setNeedsDisplay:YES];
|
||||
OSXWindow* win = (OSXWindow*)window;
|
||||
memcpy(win->draw_buffer, buffer, win->width * win->height * 4);
|
||||
|
||||
//g_updateBuffer = buffer;
|
||||
int state = update_events();
|
||||
[[win contentView] setNeedsDisplay:YES];
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
// @class OSXWindowFrameView;
|
||||
|
||||
@interface OSXWindow : NSWindow
|
||||
{
|
||||
NSView* childContentView;
|
||||
@public int width;
|
||||
@public int height;
|
||||
@public int scale;
|
||||
@public void* draw_buffer;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
newFrameSize.width += sizeDelta.width;
|
||||
newFrameSize.height += sizeDelta.height;
|
||||
|
||||
printf("conten size\n");
|
||||
|
||||
[super setContentSize:newFrameSize];
|
||||
}
|
||||
|
||||
|
@ -79,18 +81,22 @@
|
|||
NSRect bounds = [self frame];
|
||||
bounds.origin = NSZeroPoint;
|
||||
|
||||
printf("view size\n");
|
||||
|
||||
OSXWindowFrameView* frameView = [super contentView];
|
||||
if (!frameView)
|
||||
{
|
||||
frameView = [[[OSXWindowFrameView alloc] initWithFrame:bounds] autorelease];
|
||||
|
||||
frameView->width = width;
|
||||
frameView->height = height;
|
||||
frameView->draw_buffer = draw_buffer;
|
||||
frameView->scale = scale;
|
||||
[super setContentView:frameView];
|
||||
}
|
||||
|
||||
if (childContentView)
|
||||
{
|
||||
[childContentView removeFromSuperview];
|
||||
}
|
||||
|
||||
childContentView = aView;
|
||||
[childContentView setFrame:[self contentRectForFrameRect:bounds]];
|
||||
[childContentView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
|
@ -133,4 +139,20 @@
|
|||
return NSInsetRect(windowContentRect, 0, 0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)updateSize
|
||||
{
|
||||
OSXWindowFrameView* frameView = [super contentView];
|
||||
if (frameView)
|
||||
{
|
||||
frameView->width = width;
|
||||
frameView->height = height;
|
||||
frameView->draw_buffer = draw_buffer;
|
||||
frameView->scale = scale;
|
||||
}
|
||||
|
||||
printf("UpdateSize %d %d - %d\n", width, height, scale);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
@interface OSXWindowFrameView : NSView
|
||||
{
|
||||
@public int scale;
|
||||
@public int width;
|
||||
@public int height;
|
||||
@public void* draw_buffer;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
@implementation OSXWindowFrameView
|
||||
|
||||
extern void* g_updateBuffer;
|
||||
extern int g_width;
|
||||
extern int g_height;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (NSRect)resizeRect
|
||||
|
@ -27,21 +23,18 @@ extern int g_height;
|
|||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
if (!g_updateBuffer)
|
||||
return;
|
||||
|
||||
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
|
||||
|
||||
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, g_updateBuffer, g_width * g_height * 4, NULL);
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, draw_buffer, width * height * 4, NULL);
|
||||
|
||||
CGImageRef img = CGImageCreate(g_width, g_height, 8, 32, g_width * 4, space, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
|
||||
CGImageRef img = CGImageCreate(width, height, 8, 32, width * 4, space, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
|
||||
provider, NULL, false, kCGRenderingIntentDefault);
|
||||
|
||||
CGColorSpaceRelease(space);
|
||||
CGDataProviderRelease(provider);
|
||||
|
||||
CGContextDrawImage(context, CGRectMake(0, 0, g_width, g_height), img);
|
||||
CGContextDrawImage(context, CGRectMake(0, 0, width, height), img);
|
||||
|
||||
CGImageRelease(img);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue