new Cocoa graphics pipe is now fully functional

This commit is contained in:
rdb 2012-08-03 12:14:04 +00:00
parent dcdc6d9877
commit 1f0304c696
8 changed files with 174 additions and 81 deletions

View File

@ -21,6 +21,7 @@
#import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSAutoreleasePool.h>
#import <AppKit/NSApplication.h> #import <AppKit/NSApplication.h>
#import <AppKit/NSRunningApplication.h>
#include <mach-o/arch.h> #include <mach-o/arch.h>
@ -31,9 +32,15 @@ static void init_app() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication]; [NSApplication sharedApplication];
[NSApp setActivationPolicy:nil]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp finishLaunching]; [NSApp finishLaunching];
[NSApp activateIgnoringOtherApps:YES]; [NSApp activateIgnoringOtherApps:YES];
// Put Cocoa into thread-safe mode
// by spawning a thread which immediately exits.
NSThread* thread = [[NSThread alloc] init];
[thread start];
[thread autorelease];
} }
} }
@ -264,7 +271,7 @@ pipe_constructor() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
GraphicsPipe::PreferredWindowThread GraphicsPipe::PreferredWindowThread
CocoaGraphicsPipe::get_preferred_window_thread() const { CocoaGraphicsPipe::get_preferred_window_thread() const {
// The NSView and NSWindow classes are not thread-safe, // The NSView and NSWindow classes are not completely thread-safe,
// they can only be called from the main thread! // they can only be called from the main thread!
return PWT_app; return PWT_app;
} }
@ -309,8 +316,8 @@ make_output(const string &name,
return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop, return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop,
flags, gsg, host); flags, gsg, host);
} }
/*
// Second thing to try: a GLES(2)GraphicsBuffer // Second thing to try: a GLGraphicsBuffer
if (retry == 1) { if (retry == 1) {
if ((host==0)|| if ((host==0)||
// (!gl_support_fbo)|| // (!gl_support_fbo)||
@ -334,7 +341,7 @@ make_output(const string &name,
(cocoagsg->is_valid()) && (cocoagsg->is_valid()) &&
(!cocoagsg->needs_reset()) && (!cocoagsg->needs_reset()) &&
(cocoagsg->_supports_framebuffer_object) && (cocoagsg->_supports_framebuffer_object) &&
(cocoagsg->_glDrawBuffers != 0)&& (cocoagsg->_glDrawBuffers != 0) &&
(fb_prop.is_basic())) { (fb_prop.is_basic())) {
precertify = true; precertify = true;
} }
@ -342,7 +349,7 @@ make_output(const string &name,
return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop, return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
flags, gsg, host); flags, gsg, host);
} }
/*
// Third thing to try: a CocoaGraphicsBuffer // Third thing to try: a CocoaGraphicsBuffer
if (retry == 2) { if (retry == 2) {
if (((flags&BF_require_parasite)!=0)|| if (((flags&BF_require_parasite)!=0)||

View File

@ -33,7 +33,7 @@ public:
NSOpenGLPixelFormat *pixel_format, int virtual_screen); NSOpenGLPixelFormat *pixel_format, int virtual_screen);
void choose_pixel_format(const FrameBufferProperties &properties, void choose_pixel_format(const FrameBufferProperties &properties,
CGDirectDisplayID display, CGDirectDisplayID display,
bool need_window, bool need_pbuffer); bool need_pbuffer);
CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
CocoaGraphicsStateGuardian *share_with); CocoaGraphicsStateGuardian *share_with);

View File

@ -17,6 +17,7 @@
#include "lightReMutexHolder.h" #include "lightReMutexHolder.h"
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
#import <AppKit/AppKit.h>
#import <OpenGL/CGLRenderers.h> #import <OpenGL/CGLRenderers.h>
TypeHandle CocoaGraphicsStateGuardian::_type_handle; TypeHandle CocoaGraphicsStateGuardian::_type_handle;
@ -69,20 +70,20 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
depth_size, stencil_size, accum_size, sample_buffers, samples, depth_size, stencil_size, accum_size, sample_buffers, samples,
renderer_id, accelerated, window, pbuffer; renderer_id, accelerated, window, pbuffer;
[pixel_format getValues: &double_buffer forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: screen]; [pixel_format getValues:&double_buffer forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:screen];
[pixel_format getValues: &stereo forAttribute: NSOpenGLPFAStereo forVirtualScreen: screen]; [pixel_format getValues:&stereo forAttribute:NSOpenGLPFAStereo forVirtualScreen:screen];
[pixel_format getValues: &aux_buffers forAttribute: NSOpenGLPFAAuxBuffers forVirtualScreen: screen]; [pixel_format getValues:&aux_buffers forAttribute:NSOpenGLPFAAuxBuffers forVirtualScreen:screen];
[pixel_format getValues: &color_size forAttribute: NSOpenGLPFAColorSize forVirtualScreen: screen]; [pixel_format getValues:&color_size forAttribute:NSOpenGLPFAColorSize forVirtualScreen:screen];
[pixel_format getValues: &alpha_size forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: screen]; [pixel_format getValues:&alpha_size forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:screen];
[pixel_format getValues: &depth_size forAttribute: NSOpenGLPFADepthSize forVirtualScreen: screen]; [pixel_format getValues:&depth_size forAttribute:NSOpenGLPFADepthSize forVirtualScreen:screen];
[pixel_format getValues: &stencil_size forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: screen]; [pixel_format getValues:&stencil_size forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:screen];
[pixel_format getValues: &accum_size forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: screen]; [pixel_format getValues:&accum_size forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:screen];
[pixel_format getValues: &sample_buffers forAttribute: NSOpenGLPFASampleBuffers forVirtualScreen: screen]; [pixel_format getValues:&sample_buffers forAttribute:NSOpenGLPFASampleBuffers forVirtualScreen:screen];
[pixel_format getValues: &samples forAttribute: NSOpenGLPFASamples forVirtualScreen: screen]; [pixel_format getValues:&samples forAttribute:NSOpenGLPFASamples forVirtualScreen:screen];
[pixel_format getValues: &renderer_id forAttribute: NSOpenGLPFARendererID forVirtualScreen: screen]; [pixel_format getValues:&renderer_id forAttribute:NSOpenGLPFARendererID forVirtualScreen:screen];
[pixel_format getValues: &accelerated forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: screen]; [pixel_format getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:screen];
[pixel_format getValues: &window forAttribute: NSOpenGLPFAWindow forVirtualScreen: screen]; [pixel_format getValues:&window forAttribute:NSOpenGLPFAWindow forVirtualScreen:screen];
[pixel_format getValues: &pbuffer forAttribute: NSOpenGLPFAPixelBuffer forVirtualScreen: screen]; [pixel_format getValues:&pbuffer forAttribute:NSOpenGLPFAPixelBuffer forVirtualScreen:screen];
properties.set_back_buffers(double_buffer); properties.set_back_buffers(double_buffer);
properties.set_stereo(stereo); properties.set_stereo(stereo);
@ -97,11 +98,16 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
} }
//TODO: add aux buffers //TODO: add aux buffers
// Extract the renderer ID bits and check if our
// renderer matches the known software renderers.
renderer_id &= kCGLRendererIDMatchingMask;
if (renderer_id == kCGLRendererGenericID || if (renderer_id == kCGLRendererGenericID ||
renderer_id == kCGLRendererGenericFloatID || renderer_id == kCGLRendererGenericFloatID ||
renderer_id == kCGLRendererAppleSWID) { renderer_id == kCGLRendererAppleSWID) {
properties.set_force_software(1); properties.set_force_software(1);
} }
if (accelerated) { if (accelerated) {
properties.set_force_hardware(1); properties.set_force_hardware(1);
} }
@ -117,16 +123,16 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
void CocoaGraphicsStateGuardian:: void CocoaGraphicsStateGuardian::
choose_pixel_format(const FrameBufferProperties &properties, choose_pixel_format(const FrameBufferProperties &properties,
CGDirectDisplayID display, CGDirectDisplayID display,
bool need_window, bool need_pbuffer) { bool need_pbuffer) {
_context = nil; _context = nil;
_fbprops.clear(); _fbprops.clear();
// Neither Cocoa nor CGL seem to have a mechanism to query the available // Neither Cocoa nor CGL seem to have a mechanism to query the available
// pixel formats, unfortunately, so the only thing we can do is ask for one // pixel formats, unfortunately, so the only thing we can do is ask for
// with the properties we have requested. // one with the properties we have requested.
pvector<NSOpenGLPixelFormatAttribute> attribs; pvector<NSOpenGLPixelFormatAttribute> attribs;
attribs.reserve(13); attribs.reserve(15);
// Picked this up from the pyglet source - seems // Picked this up from the pyglet source - seems
// to be necessary to support RAGE-II, which is not compliant. // to be necessary to support RAGE-II, which is not compliant.
@ -135,8 +141,9 @@ choose_pixel_format(const FrameBufferProperties &properties,
// Don't let it fall back to a different renderer. // Don't let it fall back to a different renderer.
attribs.push_back(NSOpenGLPFANoRecovery); attribs.push_back(NSOpenGLPFANoRecovery);
// Selection policy. // Consider pixel formats with properties equal
//attribs.push_back(NSOpenGLPFAMinimumPolicy); // to or better than we requested.
attribs.push_back(NSOpenGLPFAMinimumPolicy);
if (!properties.is_single_buffered()) { if (!properties.is_single_buffered()) {
attribs.push_back(NSOpenGLPFADoubleBuffer); attribs.push_back(NSOpenGLPFADoubleBuffer);
@ -151,13 +158,22 @@ choose_pixel_format(const FrameBufferProperties &properties,
attribs.push_back(aux_buffers); attribs.push_back(aux_buffers);
attribs.push_back(NSOpenGLPFAColorSize); attribs.push_back(NSOpenGLPFAColorSize);
attribs.push_back(properties.get_color_bits()); attribs.push_back(properties.get_color_bits());
attribs.push_back(NSOpenGLPFAAlphaSize);
attribs.push_back(properties.get_alpha_bits());
attribs.push_back(NSOpenGLPFADepthSize); attribs.push_back(NSOpenGLPFADepthSize);
attribs.push_back(properties.get_depth_bits()); attribs.push_back(properties.get_depth_bits());
attribs.push_back(NSOpenGLPFAStencilSize); attribs.push_back(NSOpenGLPFAStencilSize);
attribs.push_back(properties.get_stencil_bits()); attribs.push_back(properties.get_stencil_bits());
// Curious case - if we request anything less than 8 alpha bits,
// then on some ATI cards, it will grab a pixel format with just
// 2 alpha bits, which just shows a white window and nothing else.
// Might have something to do with the compositing window manager.
// Omitting it altogether seems to make it grab one with 8 bits, though.
// Dirty hack. Needs more research.
if (properties.get_alpha_bits() > 0) {
attribs.push_back(NSOpenGLPFAAlphaSize);
attribs.push_back(max(8, properties.get_alpha_bits()));
}
if (properties.get_multisamples() > 0) { if (properties.get_multisamples() > 0) {
attribs.push_back(NSOpenGLPFASampleBuffers); attribs.push_back(NSOpenGLPFASampleBuffers);
attribs.push_back(1); attribs.push_back(1);
@ -167,19 +183,16 @@ choose_pixel_format(const FrameBufferProperties &properties,
} }
if (properties.get_force_software()) { if (properties.get_force_software()) {
// Request the generic software renderer.
attribs.push_back(NSOpenGLPFARendererID); attribs.push_back(NSOpenGLPFARendererID);
attribs.push_back(kCGLRendererAppleSWID); attribs.push_back(kCGLRendererGenericFloatID);
} }
if (properties.get_force_hardware()) { if (properties.get_force_hardware()) {
attribs.push_back(NSOpenGLPFAAccelerated); attribs.push_back(NSOpenGLPFAAccelerated);
} }
if (need_window) { attribs.push_back(NSOpenGLPFAWindow);
//TODO: when to request fullscreen on Cocoa?
attribs.push_back(NSOpenGLPFAWindow);
//attribs.push_back(NSOpenGLPFAFullScreen);
}
if (need_pbuffer) { if (need_pbuffer) {
attribs.push_back(NSOpenGLPFAPixelBuffer); attribs.push_back(NSOpenGLPFAPixelBuffer);
@ -189,19 +202,25 @@ choose_pixel_format(const FrameBufferProperties &properties,
attribs.push_back(NSOpenGLPFAScreenMask); attribs.push_back(NSOpenGLPFAScreenMask);
attribs.push_back(CGDisplayIDToOpenGLDisplayMask(display)); attribs.push_back(CGDisplayIDToOpenGLDisplayMask(display));
// End of the array
attribs.push_back((NSOpenGLPixelFormatAttribute) nil); attribs.push_back((NSOpenGLPixelFormatAttribute) nil);
// Create the format. // Create the format.
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: &attribs[0]]; NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
if (format == nil) { if (format == nil) {
cocoadisplay_cat.error() << cocoadisplay_cat.error() <<
"Could not find a usable pixel format.\n"; "Could not find a usable pixel format.\n";
return; return;
} }
//XXX not sure what to do with virtual_screen, let's just set it to 0. // For now, I'm just using the first virtual screen.
cocoadisplay_cat.debug() <<
"Pixel format has " << [format numberOfVirtualScreens] << " virtual screens.\n";
get_properties(_fbprops, format, 0); get_properties(_fbprops, format, 0);
_context = [[NSOpenGLContext alloc] initWithFormat: format shareContext: _share_context];
//TODO: print out renderer
_context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:_share_context];
[format release]; [format release];
if (_context == nil) { if (_context == nil) {
cocoadisplay_cat.error() << cocoadisplay_cat.error() <<
@ -230,6 +249,9 @@ query_gl_version() {
// where the GL version has been output, and it's nice to see the // where the GL version has been output, and it's nice to see the
// two of these together. // two of these together.
if (glgsg_cat.is_debug()) { if (glgsg_cat.is_debug()) {
//XXX this is supposed to work, but the NSOpenGLGetVersion
// symbol cannot be found when I do this
//GLint major, minor; //GLint major, minor;
//NSOpenGLGetVersion(&major, &minor); //NSOpenGLGetVersion(&major, &minor);
@ -264,7 +286,7 @@ do_get_extension_func(const char *prefix, const char *name) {
return (void *) NSAddressOfSymbol(symbol); return (void *) NSAddressOfSymbol(symbol);
} }
cocoadisplay_cat.error() << cocoadisplay_cat.warning() <<
"do_get_extension_func failed for " << prefix << name << "!\n"; "do_get_extension_func failed for " << prefix << name << "!\n";
free(fullname); free(fullname);

View File

@ -56,7 +56,7 @@ public:
void handle_close_event(); void handle_close_event();
void handle_key_event(NSEvent *event); void handle_key_event(NSEvent *event);
void handle_mouse_button_event(int button, bool down); void handle_mouse_button_event(int button, bool down);
void handle_mouse_moved_event(bool in_window, int x, int y, bool absolute); void handle_mouse_moved_event(bool in_window, double x, double y, bool absolute);
void handle_wheel_event(double x, double y); void handle_wheel_event(double x, double y);
INLINE NSWindow *get_nswindow() const; INLINE NSWindow *get_nswindow() const;

View File

@ -39,7 +39,7 @@
#import <AppKit/NSImage.h> #import <AppKit/NSImage.h>
#import <AppKit/NSScreen.h> #import <AppKit/NSScreen.h>
#import <OpenGL/OpenGL.h> #import <OpenGL/OpenGL.h>
#import <Carbon/Carbon.h> //#import <Carbon/Carbon.h>
TypeHandle CocoaGraphicsWindow::_type_handle; TypeHandle CocoaGraphicsWindow::_type_handle;
@ -97,20 +97,35 @@ CocoaGraphicsWindow::
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool CocoaGraphicsWindow:: bool CocoaGraphicsWindow::
move_pointer(int device, int x, int y) { move_pointer(int device, int x, int y) {
//Hack! Will go away when we have floating-point mouse pos.
MouseData md = get_pointer(device);
if (md.get_x() == x && md.get_y() == y) {
return true;
}
if (device == 0) { if (device == 0) {
CGPoint point; CGPoint point;
if (_properties.get_fullscreen()) { if (_properties.get_fullscreen()) {
point = CGPointMake(x, y); point = CGPointMake(x, y + 1);
} else { } else {
point = CGPointMake(x + _properties.get_x_origin(), point = CGPointMake(x + _properties.get_x_origin(),
y + _properties.get_y_origin()); y + _properties.get_y_origin() + 1);
} }
return (CGDisplayMoveCursorToPoint(_display, point) == kCGErrorSuccess); // I don't know what the difference between these two methods is.
//if (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
if (CGDisplayMoveCursorToPoint(_display, point) == kCGErrorSuccess) {
// Generate a mouse event.
NSPoint pos = [_window mouseLocationOutsideOfEventStream];
NSPoint loc = [_view convertPoint:pos fromView:nil];
BOOL inside = [_view mouse:loc inRect:[_view bounds]];
handle_mouse_moved_event(inside, loc.x, loc.y, true);
return true;
}
} else { } else {
// No support for raw mice at the moment. // No support for raw mice at the moment.
return false;
} }
return false;
} }
@ -145,13 +160,16 @@ begin_frame(FrameMode mode, Thread *current_thread) {
// Fullscreen. // Fullscreen.
[cocoagsg->_context setFullScreen]; [cocoagsg->_context setFullScreen];
} else { } else {
nassertr([_view lockFocusIfCanDraw], false);
// Although not recommended, it is technically possible to // Although not recommended, it is technically possible to
// use the same context with multiple different-sized windows. // use the same context with multiple different-sized windows.
// If that happens, the context needs to be updated accordingly. // If that happens, the context needs to be updated accordingly.
if ([cocoagsg->_context view] != _view) { if ([cocoagsg->_context view] != _view) {
//XXX I'm not 100% sure that changing the view requires it to update.
_context_needs_update = true; _context_needs_update = true;
[cocoagsg->_context setView:_view]; [cocoagsg->_context setView:_view];
cocoadisplay_cat.spam()
<< "Switching context to view " << _view << "\n";
} }
} }
@ -161,6 +179,11 @@ begin_frame(FrameMode mode, Thread *current_thread) {
_context_needs_update = false; _context_needs_update = false;
} }
// Lock the view for drawing.
if (!_properties.get_fullscreen()) {
nassertr([_view lockFocusIfCanDraw], false);
}
// Make the context current. // Make the context current.
[cocoagsg->_context makeCurrentContext]; [cocoagsg->_context makeCurrentContext];
@ -191,6 +214,15 @@ end_frame(FrameMode mode, Thread *current_thread) {
end_frame_spam(mode); end_frame_spam(mode);
nassertv(_gsg != (GraphicsStateGuardian *)NULL); nassertv(_gsg != (GraphicsStateGuardian *)NULL);
if (!_properties.get_fullscreen()) {
[_view unlockFocus];
}
// Release the context.
CocoaGraphicsStateGuardian *cocoagsg;
DCAST_INTO_V(cocoagsg, _gsg);
CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]);
if (mode == FM_render) { if (mode == FM_render) {
// end_render_texture(); // end_render_texture();
copy_to_textures(); copy_to_textures();
@ -221,12 +253,14 @@ end_flip() {
CocoaGraphicsStateGuardian *cocoagsg; CocoaGraphicsStateGuardian *cocoagsg;
DCAST_INTO_V(cocoagsg, _gsg); DCAST_INTO_V(cocoagsg, _gsg);
[cocoagsg->_context flushBuffer]; CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]);
if (!_properties.get_fullscreen()) {
[_view unlockFocus]; // Swap the front and back buffer.
} [cocoagsg->_context flushBuffer];
// Flush the window
[[_view window] flushWindow];
// Release the context.
CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]);
} }
GraphicsWindow::end_flip(); GraphicsWindow::end_flip();
@ -247,15 +281,14 @@ process_events() {
GraphicsWindow::process_events(); GraphicsWindow::process_events();
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSEvent *event = nil; NSEvent *event = nil;
while (true) { while (true) {
event = [NSApp event = [NSApp
nextEventMatchingMask: NSAnyEventMask nextEventMatchingMask:NSAnyEventMask
untilDate: nil untilDate:nil
inMode: NSDefaultRunLoopMode inMode:NSDefaultRunLoopMode
dequeue: YES]; dequeue:YES];
if (event == nil) { if (event == nil) {
break; break;
@ -288,7 +321,7 @@ open_window() {
if (_gsg == 0) { if (_gsg == 0) {
// There is no old gsg. Create a new one. // There is no old gsg. Create a new one.
cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, NULL); cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, NULL);
cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, true, false); cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, false);
_gsg = cocoagsg; _gsg = cocoagsg;
} else { } else {
// If the old gsg has the wrong pixel format, create a // If the old gsg has the wrong pixel format, create a
@ -296,7 +329,7 @@ open_window() {
DCAST_INTO_R(cocoagsg, _gsg, false); DCAST_INTO_R(cocoagsg, _gsg, false);
if (!cocoagsg->get_fb_properties().subsumes(_fb_properties)) { if (!cocoagsg->get_fb_properties().subsumes(_fb_properties)) {
cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, cocoagsg); cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, cocoagsg);
cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, true, false); cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, false);
_gsg = cocoagsg; _gsg = cocoagsg;
} }
} }
@ -348,7 +381,7 @@ open_window() {
// Depending on whether the window handle comes from a Carbon or a Cocoa // Depending on whether the window handle comes from a Carbon or a Cocoa
// application, it could be either a HIViewRef or an NSView or NSWindow. // application, it could be either a HIViewRef or an NSView or NSWindow.
// Currently, we only support a Cocoa NSView, but we may in the future // Currently, we only support a Cocoa NSView, but we could in the future
// add support for Carbon parents using HICocoaView. // add support for Carbon parents using HICocoaView.
if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) { if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
@ -373,6 +406,8 @@ open_window() {
} }
// Center the window if coordinates were set to -1 or -2 // Center the window if coordinates were set to -1 or -2
//TODO: perhaps in future, in the case of -1, it should use the origin
// used in a previous run of Panda
NSRect container; NSRect container;
if (parent_nsview != NULL) { if (parent_nsview != NULL) {
container = [parent_nsview bounds]; container = [parent_nsview bounds];
@ -498,14 +533,14 @@ open_window() {
[_window setShowsResizeIndicator: !_properties.get_fixed_size()]; [_window setShowsResizeIndicator: !_properties.get_fixed_size()];
if (_properties.get_fullscreen()) { if (_properties.get_fullscreen()) {
[_window makeKeyAndOrderFront: nil]; [_window makeKeyAndOrderFront:nil];
} else if (_properties.get_minimized()) { } else if (_properties.get_minimized()) {
[_window makeKeyAndOrderFront: nil]; [_window makeKeyAndOrderFront:nil];
[_window miniaturize: nil]; [_window miniaturize:nil];
} else if (_properties.get_foreground()) { } else if (_properties.get_foreground()) {
[_window makeKeyAndOrderFront: nil]; [_window makeKeyAndOrderFront:nil];
} else { } else {
[_window orderBack: nil]; [_window orderBack:nil];
} }
if (_properties.get_fullscreen()) { if (_properties.get_fullscreen()) {
@ -547,8 +582,9 @@ open_window() {
// Make the context current. // Make the context current.
_context_needs_update = false; _context_needs_update = false;
[cocoagsg->_context update];
[cocoagsg->_context makeCurrentContext]; [cocoagsg->_context makeCurrentContext];
[cocoagsg->_context setView:_view];
[cocoagsg->_context update];
cocoagsg->reset_if_new(); cocoagsg->reset_if_new();
@ -821,8 +857,6 @@ set_properties_now(WindowProperties &properties) {
properties.clear_origin(); properties.clear_origin();
} }
//TODO: mouse mode
if (properties.has_title() && _window != nil) { if (properties.has_title() && _window != nil) {
_properties.set_title(properties.get_title()); _properties.set_title(properties.get_title());
[_window setTitle:[NSString stringWithUTF8String:properties.get_title().c_str()]]; [_window setTitle:[NSString stringWithUTF8String:properties.get_title().c_str()]];
@ -1224,10 +1258,6 @@ handle_minimize_event(bool minimized) {
return; return;
} }
WindowProperties properties;
properties.set_minimized(minimized);
system_changed_properties(properties);
if (cocoadisplay_cat.is_debug()) { if (cocoadisplay_cat.is_debug()) {
if (minimized) { if (minimized) {
cocoadisplay_cat.debug() << "Window was miniaturized\n"; cocoadisplay_cat.debug() << "Window was miniaturized\n";
@ -1235,6 +1265,10 @@ handle_minimize_event(bool minimized) {
cocoadisplay_cat.debug() << "Window was deminiaturized\n"; cocoadisplay_cat.debug() << "Window was deminiaturized\n";
} }
} }
WindowProperties properties;
properties.set_minimized(minimized);
system_changed_properties(properties);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -1245,10 +1279,6 @@ handle_minimize_event(bool minimized) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void CocoaGraphicsWindow:: void CocoaGraphicsWindow::
handle_foreground_event(bool foreground) { handle_foreground_event(bool foreground) {
WindowProperties properties;
properties.set_foreground(foreground);
system_changed_properties(properties);
if (cocoadisplay_cat.is_debug()) { if (cocoadisplay_cat.is_debug()) {
if (foreground) { if (foreground) {
cocoadisplay_cat.debug() << "Window became key\n"; cocoadisplay_cat.debug() << "Window became key\n";
@ -1257,6 +1287,10 @@ handle_foreground_event(bool foreground) {
} }
} }
WindowProperties properties;
properties.set_foreground(foreground);
system_changed_properties(properties);
if (foreground && _properties.get_mouse_mode() != WindowProperties::M_relative) { if (foreground && _properties.get_mouse_mode() != WindowProperties::M_relative) {
// The mouse position may have changed during // The mouse position may have changed during
// the time that we were not the key window. // the time that we were not the key window.
@ -1500,7 +1534,7 @@ handle_mouse_button_event(int button, bool down) {
// Should only be called by CocoaPandaView. // Should only be called by CocoaPandaView.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void CocoaGraphicsWindow:: void CocoaGraphicsWindow::
handle_mouse_moved_event(bool in_window, int x, int y, bool absolute) { handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
if (absolute) { if (absolute) {
if (cocoadisplay_cat.is_spam()) { if (cocoadisplay_cat.is_spam()) {
if (in_window != _input_devices[0].get_pointer().get_in_window()) { if (in_window != _input_devices[0].get_pointer().get_in_window()) {
@ -1553,11 +1587,11 @@ handle_wheel_event(double x, double y) {
_input_devices[0].button_up(MouseButton::wheel_down()); _input_devices[0].button_up(MouseButton::wheel_down());
} }
//TODO: check if this is correct //TODO: check if this is correct, I don't own a MacBook
if (x > 0.0) { if (x > 0.0) {
_input_devices[0].button_down(MouseButton::wheel_right()); _input_devices[0].button_down(MouseButton::wheel_right());
_input_devices[0].button_up(MouseButton::wheel_right()); _input_devices[0].button_up(MouseButton::wheel_right());
} else if (y < 0.0) { } else if (x < 0.0) {
_input_devices[0].button_down(MouseButton::wheel_left()); _input_devices[0].button_down(MouseButton::wheel_left());
_input_devices[0].button_up(MouseButton::wheel_left()); _input_devices[0].button_up(MouseButton::wheel_left());
} }
@ -1659,6 +1693,7 @@ map_function_key(unsigned short keycode) {
case NSUserFunctionKey: case NSUserFunctionKey:
case NSSystemFunctionKey: case NSSystemFunctionKey:
case NSPrintFunctionKey: case NSPrintFunctionKey:
break;
case NSClearLineFunctionKey: case NSClearLineFunctionKey:
return KeyboardButton::num_lock(); return KeyboardButton::num_lock();
case NSClearDisplayFunctionKey: case NSClearDisplayFunctionKey:
@ -1673,6 +1708,7 @@ map_function_key(unsigned short keycode) {
case NSUndoFunctionKey: case NSUndoFunctionKey:
case NSRedoFunctionKey: case NSRedoFunctionKey:
case NSFindFunctionKey: case NSFindFunctionKey:
break;
case NSHelpFunctionKey: case NSHelpFunctionKey:
return KeyboardButton::help(); return KeyboardButton::help();
case NSModeSwitchFunctionKey: case NSModeSwitchFunctionKey:

View File

@ -23,8 +23,13 @@ class CocoaGraphicsWindow;
} }
- (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window; - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window;
- (NSOpenGLContext*) openGLContext;
- (GraphicsWindow*) graphicsWindow;
- (void) drawRect:(NSRect)dirtyRect;
- (void) finalize; - (void) finalize;
- (BOOL) isFlipped; - (BOOL) isFlipped;
- (BOOL) needsDisplay;
- (BOOL) acceptsFirstResponder; - (BOOL) acceptsFirstResponder;
- (BOOL) becomeFirstResponder; - (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder; - (BOOL) resignFirstResponder;

View File

@ -21,6 +21,9 @@
- (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window { - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window {
self = [super initWithFrame: frameRect]; self = [super initWithFrame: frameRect];
_context = context;
[self setCanDrawConcurrently:YES];
cocoadisplay_cat.debug() cocoadisplay_cat.debug()
<< "Created CocoaPandaView " << self << " for GraphicsWindow " << window << "\n"; << "Created CocoaPandaView " << self << " for GraphicsWindow " << window << "\n";
_graphicsWindow = window; _graphicsWindow = window;
@ -28,6 +31,21 @@
return self; return self;
} }
- (NSOpenGLContext*) openGLContext {
return _context;
}
- (GraphicsWindow*) graphicsWindow {
return _graphicsWindow;
}
- (void) drawRect:(NSRect)dirtyRect {
// Do nothing. We draw from another thread.
cocoadisplay_cat.spam()
<< "drawRect was called.\n";
}
- (void) finalize { - (void) finalize {
_graphicsWindow->handle_close_event(); _graphicsWindow->handle_close_event();
[super finalize]; [super finalize];
@ -39,6 +57,11 @@
return YES; return YES;
} }
- (BOOL) needsDisplay {
// Never, we don't use drawRect. We draw from elsewhere.
return NO;
}
- (BOOL) acceptsFirstResponder { - (BOOL) acceptsFirstResponder {
return YES; return YES;
} }
@ -59,7 +82,6 @@
- (void) setFrame: (NSRect) frame { - (void) setFrame: (NSRect) frame {
[super setFrame: frame]; [super setFrame: frame];
//[_context update];
//_graphicsWindow->handle_resize_event(); //_graphicsWindow->handle_resize_event();
} }
@ -111,7 +133,7 @@
} }
- (void) otherMouseDown: (NSEvent *) event { - (void) otherMouseDown: (NSEvent *) event {
// 2 and 3 are swapped, for consistency with X11 implementation // 1 and 2 are swapped, for consistency with X11 implementation
if ([event buttonNumber] == 2) { if ([event buttonNumber] == 2) {
_graphicsWindow->handle_mouse_button_event(1, true); _graphicsWindow->handle_mouse_button_event(1, true);
} else { } else {
@ -124,7 +146,7 @@
} }
- (void) otherMouseUp: (NSEvent *) event { - (void) otherMouseUp: (NSEvent *) event {
// 2 and 3 are swapped, for consistency with X11 implementation // 1 and 2 are swapped, for consistency with X11 implementation
if ([event buttonNumber] == 2) { if ([event buttonNumber] == 2) {
_graphicsWindow->handle_mouse_button_event(1, false); _graphicsWindow->handle_mouse_button_event(1, false);
} else { } else {

View File

@ -29,6 +29,7 @@
[self setDelegate:delegate]; [self setDelegate:delegate];
[self setOpaque:YES]; [self setOpaque:YES];
[self setReleasedWhenClosed:YES]; [self setReleasedWhenClosed:YES];
[self setAllowsConcurrentViewDrawing:YES];
// Necessary to be able to accept mouseMoved in the NSView // Necessary to be able to accept mouseMoved in the NSView
[self setAcceptsMouseMovedEvents:YES]; [self setAcceptsMouseMovedEvents:YES];