diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm index bf579926ef..abadedc7e6 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm @@ -21,6 +21,7 @@ #import #import +#import #include @@ -31,9 +32,15 @@ static void init_app() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [NSApplication sharedApplication]; - [NSApp setActivationPolicy:nil]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [NSApp finishLaunching]; [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 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! return PWT_app; } @@ -309,8 +316,8 @@ make_output(const string &name, return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop, flags, gsg, host); } -/* - // Second thing to try: a GLES(2)GraphicsBuffer + + // Second thing to try: a GLGraphicsBuffer if (retry == 1) { if ((host==0)|| // (!gl_support_fbo)|| @@ -334,7 +341,7 @@ make_output(const string &name, (cocoagsg->is_valid()) && (!cocoagsg->needs_reset()) && (cocoagsg->_supports_framebuffer_object) && - (cocoagsg->_glDrawBuffers != 0)&& + (cocoagsg->_glDrawBuffers != 0) && (fb_prop.is_basic())) { precertify = true; } @@ -342,7 +349,7 @@ make_output(const string &name, return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host); } - +/* // Third thing to try: a CocoaGraphicsBuffer if (retry == 2) { if (((flags&BF_require_parasite)!=0)|| diff --git a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h index f211812ef4..d70061a813 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h +++ b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h @@ -33,7 +33,7 @@ public: NSOpenGLPixelFormat *pixel_format, int virtual_screen); void choose_pixel_format(const FrameBufferProperties &properties, CGDirectDisplayID display, - bool need_window, bool need_pbuffer); + bool need_pbuffer); CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, CocoaGraphicsStateGuardian *share_with); diff --git a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm index c218176cd7..8f9809acbd 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm @@ -17,6 +17,7 @@ #include "lightReMutexHolder.h" #include +#import #import TypeHandle CocoaGraphicsStateGuardian::_type_handle; @@ -69,20 +70,20 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for depth_size, stencil_size, accum_size, sample_buffers, samples, renderer_id, accelerated, window, pbuffer; - [pixel_format getValues: &double_buffer forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: screen]; - [pixel_format getValues: &stereo forAttribute: NSOpenGLPFAStereo forVirtualScreen: screen]; - [pixel_format getValues: &aux_buffers forAttribute: NSOpenGLPFAAuxBuffers forVirtualScreen: screen]; - [pixel_format getValues: &color_size forAttribute: NSOpenGLPFAColorSize forVirtualScreen: screen]; - [pixel_format getValues: &alpha_size forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: screen]; - [pixel_format getValues: &depth_size forAttribute: NSOpenGLPFADepthSize forVirtualScreen: screen]; - [pixel_format getValues: &stencil_size forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: screen]; - [pixel_format getValues: &accum_size forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: screen]; - [pixel_format getValues: &sample_buffers forAttribute: NSOpenGLPFASampleBuffers forVirtualScreen: screen]; - [pixel_format getValues: &samples forAttribute: NSOpenGLPFASamples forVirtualScreen: screen]; - [pixel_format getValues: &renderer_id forAttribute: NSOpenGLPFARendererID forVirtualScreen: screen]; - [pixel_format getValues: &accelerated forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: screen]; - [pixel_format getValues: &window forAttribute: NSOpenGLPFAWindow forVirtualScreen: screen]; - [pixel_format getValues: &pbuffer forAttribute: NSOpenGLPFAPixelBuffer forVirtualScreen: screen]; + [pixel_format getValues:&double_buffer forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:screen]; + [pixel_format getValues:&stereo forAttribute:NSOpenGLPFAStereo forVirtualScreen:screen]; + [pixel_format getValues:&aux_buffers forAttribute:NSOpenGLPFAAuxBuffers forVirtualScreen:screen]; + [pixel_format getValues:&color_size forAttribute:NSOpenGLPFAColorSize forVirtualScreen:screen]; + [pixel_format getValues:&alpha_size forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:screen]; + [pixel_format getValues:&depth_size forAttribute:NSOpenGLPFADepthSize forVirtualScreen:screen]; + [pixel_format getValues:&stencil_size forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:screen]; + [pixel_format getValues:&accum_size forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:screen]; + [pixel_format getValues:&sample_buffers forAttribute:NSOpenGLPFASampleBuffers forVirtualScreen:screen]; + [pixel_format getValues:&samples forAttribute:NSOpenGLPFASamples forVirtualScreen:screen]; + [pixel_format getValues:&renderer_id forAttribute:NSOpenGLPFARendererID forVirtualScreen:screen]; + [pixel_format getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:screen]; + [pixel_format getValues:&window forAttribute:NSOpenGLPFAWindow forVirtualScreen:screen]; + [pixel_format getValues:&pbuffer forAttribute:NSOpenGLPFAPixelBuffer forVirtualScreen:screen]; properties.set_back_buffers(double_buffer); properties.set_stereo(stereo); @@ -97,11 +98,16 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for } //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 || renderer_id == kCGLRendererGenericFloatID || renderer_id == kCGLRendererAppleSWID) { + properties.set_force_software(1); } + if (accelerated) { properties.set_force_hardware(1); } @@ -117,16 +123,16 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for void CocoaGraphicsStateGuardian:: choose_pixel_format(const FrameBufferProperties &properties, CGDirectDisplayID display, - bool need_window, bool need_pbuffer) { + bool need_pbuffer) { _context = nil; _fbprops.clear(); // 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 - // with the properties we have requested. + // pixel formats, unfortunately, so the only thing we can do is ask for + // one with the properties we have requested. pvector attribs; - attribs.reserve(13); + attribs.reserve(15); // Picked this up from the pyglet source - seems // 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. attribs.push_back(NSOpenGLPFANoRecovery); - // Selection policy. - //attribs.push_back(NSOpenGLPFAMinimumPolicy); + // Consider pixel formats with properties equal + // to or better than we requested. + attribs.push_back(NSOpenGLPFAMinimumPolicy); if (!properties.is_single_buffered()) { attribs.push_back(NSOpenGLPFADoubleBuffer); @@ -151,13 +158,22 @@ choose_pixel_format(const FrameBufferProperties &properties, attribs.push_back(aux_buffers); attribs.push_back(NSOpenGLPFAColorSize); 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(properties.get_depth_bits()); attribs.push_back(NSOpenGLPFAStencilSize); 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) { attribs.push_back(NSOpenGLPFASampleBuffers); attribs.push_back(1); @@ -167,19 +183,16 @@ choose_pixel_format(const FrameBufferProperties &properties, } if (properties.get_force_software()) { + // Request the generic software renderer. attribs.push_back(NSOpenGLPFARendererID); - attribs.push_back(kCGLRendererAppleSWID); + attribs.push_back(kCGLRendererGenericFloatID); } if (properties.get_force_hardware()) { attribs.push_back(NSOpenGLPFAAccelerated); } - if (need_window) { - //TODO: when to request fullscreen on Cocoa? - attribs.push_back(NSOpenGLPFAWindow); - //attribs.push_back(NSOpenGLPFAFullScreen); - } + attribs.push_back(NSOpenGLPFAWindow); if (need_pbuffer) { attribs.push_back(NSOpenGLPFAPixelBuffer); @@ -189,19 +202,25 @@ choose_pixel_format(const FrameBufferProperties &properties, attribs.push_back(NSOpenGLPFAScreenMask); attribs.push_back(CGDisplayIDToOpenGLDisplayMask(display)); + // End of the array attribs.push_back((NSOpenGLPixelFormatAttribute) nil); // Create the format. - NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: &attribs[0]]; + NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]]; if (format == nil) { cocoadisplay_cat.error() << "Could not find a usable pixel format.\n"; 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); - _context = [[NSOpenGLContext alloc] initWithFormat: format shareContext: _share_context]; + + //TODO: print out renderer + + _context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:_share_context]; [format release]; if (_context == nil) { cocoadisplay_cat.error() << @@ -230,6 +249,9 @@ query_gl_version() { // where the GL version has been output, and it's nice to see the // two of these together. 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; //NSOpenGLGetVersion(&major, &minor); @@ -264,7 +286,7 @@ do_get_extension_func(const char *prefix, const char *name) { return (void *) NSAddressOfSymbol(symbol); } - cocoadisplay_cat.error() << + cocoadisplay_cat.warning() << "do_get_extension_func failed for " << prefix << name << "!\n"; free(fullname); diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.h b/panda/src/cocoadisplay/cocoaGraphicsWindow.h index c09c44fc58..4eedac3a7a 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.h +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.h @@ -56,7 +56,7 @@ public: void handle_close_event(); void handle_key_event(NSEvent *event); 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); INLINE NSWindow *get_nswindow() const; diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index e7fc7081d2..8ea9acd065 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -39,7 +39,7 @@ #import #import #import -#import +//#import TypeHandle CocoaGraphicsWindow::_type_handle; @@ -97,20 +97,35 @@ CocoaGraphicsWindow:: //////////////////////////////////////////////////////////////////// bool CocoaGraphicsWindow:: 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) { CGPoint point; if (_properties.get_fullscreen()) { - point = CGPointMake(x, y); + point = CGPointMake(x, y + 1); } else { 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 { // No support for raw mice at the moment. - return false; } + return false; } @@ -145,13 +160,16 @@ begin_frame(FrameMode mode, Thread *current_thread) { // Fullscreen. [cocoagsg->_context setFullScreen]; } else { - nassertr([_view lockFocusIfCanDraw], false); // Although not recommended, it is technically possible to // use the same context with multiple different-sized windows. // If that happens, the context needs to be updated accordingly. if ([cocoagsg->_context view] != _view) { + //XXX I'm not 100% sure that changing the view requires it to update. _context_needs_update = true; [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; } + // Lock the view for drawing. + if (!_properties.get_fullscreen()) { + nassertr([_view lockFocusIfCanDraw], false); + } + // Make the context current. [cocoagsg->_context makeCurrentContext]; @@ -191,6 +214,15 @@ end_frame(FrameMode mode, Thread *current_thread) { end_frame_spam(mode); 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) { // end_render_texture(); copy_to_textures(); @@ -221,12 +253,14 @@ end_flip() { CocoaGraphicsStateGuardian *cocoagsg; DCAST_INTO_V(cocoagsg, _gsg); - [cocoagsg->_context flushBuffer]; - if (!_properties.get_fullscreen()) { - [_view unlockFocus]; - } + CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + + // Swap the front and back buffer. + [cocoagsg->_context flushBuffer]; + + // Flush the window + [[_view window] flushWindow]; - // Release the context. CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); } GraphicsWindow::end_flip(); @@ -247,15 +281,14 @@ process_events() { GraphicsWindow::process_events(); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSEvent *event = nil; while (true) { event = [NSApp - nextEventMatchingMask: NSAnyEventMask - untilDate: nil - inMode: NSDefaultRunLoopMode - dequeue: YES]; + nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]; if (event == nil) { break; @@ -288,7 +321,7 @@ open_window() { if (_gsg == 0) { // There is no old gsg. Create a new one. 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; } else { // If the old gsg has the wrong pixel format, create a @@ -296,7 +329,7 @@ open_window() { DCAST_INTO_R(cocoagsg, _gsg, false); if (!cocoagsg->get_fb_properties().subsumes(_fb_properties)) { 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; } } @@ -348,7 +381,7 @@ open_window() { // 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. - // 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. 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 + //TODO: perhaps in future, in the case of -1, it should use the origin + // used in a previous run of Panda NSRect container; if (parent_nsview != NULL) { container = [parent_nsview bounds]; @@ -498,14 +533,14 @@ open_window() { [_window setShowsResizeIndicator: !_properties.get_fixed_size()]; if (_properties.get_fullscreen()) { - [_window makeKeyAndOrderFront: nil]; + [_window makeKeyAndOrderFront:nil]; } else if (_properties.get_minimized()) { - [_window makeKeyAndOrderFront: nil]; - [_window miniaturize: nil]; + [_window makeKeyAndOrderFront:nil]; + [_window miniaturize:nil]; } else if (_properties.get_foreground()) { - [_window makeKeyAndOrderFront: nil]; + [_window makeKeyAndOrderFront:nil]; } else { - [_window orderBack: nil]; + [_window orderBack:nil]; } if (_properties.get_fullscreen()) { @@ -547,8 +582,9 @@ open_window() { // Make the context current. _context_needs_update = false; - [cocoagsg->_context update]; [cocoagsg->_context makeCurrentContext]; + [cocoagsg->_context setView:_view]; + [cocoagsg->_context update]; cocoagsg->reset_if_new(); @@ -821,8 +857,6 @@ set_properties_now(WindowProperties &properties) { properties.clear_origin(); } - //TODO: mouse mode - if (properties.has_title() && _window != nil) { _properties.set_title(properties.get_title()); [_window setTitle:[NSString stringWithUTF8String:properties.get_title().c_str()]]; @@ -1224,10 +1258,6 @@ handle_minimize_event(bool minimized) { return; } - WindowProperties properties; - properties.set_minimized(minimized); - system_changed_properties(properties); - if (cocoadisplay_cat.is_debug()) { if (minimized) { cocoadisplay_cat.debug() << "Window was miniaturized\n"; @@ -1235,6 +1265,10 @@ handle_minimize_event(bool minimized) { 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:: handle_foreground_event(bool foreground) { - WindowProperties properties; - properties.set_foreground(foreground); - system_changed_properties(properties); - if (cocoadisplay_cat.is_debug()) { if (foreground) { 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) { // The mouse position may have changed during // 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. //////////////////////////////////////////////////////////////////// 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 (cocoadisplay_cat.is_spam()) { 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()); } - //TODO: check if this is correct + //TODO: check if this is correct, I don't own a MacBook if (x > 0.0) { _input_devices[0].button_down(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_up(MouseButton::wheel_left()); } @@ -1659,6 +1693,7 @@ map_function_key(unsigned short keycode) { case NSUserFunctionKey: case NSSystemFunctionKey: case NSPrintFunctionKey: + break; case NSClearLineFunctionKey: return KeyboardButton::num_lock(); case NSClearDisplayFunctionKey: @@ -1673,6 +1708,7 @@ map_function_key(unsigned short keycode) { case NSUndoFunctionKey: case NSRedoFunctionKey: case NSFindFunctionKey: + break; case NSHelpFunctionKey: return KeyboardButton::help(); case NSModeSwitchFunctionKey: diff --git a/panda/src/cocoadisplay/cocoaPandaView.h b/panda/src/cocoadisplay/cocoaPandaView.h index aed1e93aa7..f892c6a685 100644 --- a/panda/src/cocoadisplay/cocoaPandaView.h +++ b/panda/src/cocoadisplay/cocoaPandaView.h @@ -23,8 +23,13 @@ class CocoaGraphicsWindow; } - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window; +- (NSOpenGLContext*) openGLContext; +- (GraphicsWindow*) graphicsWindow; + +- (void) drawRect:(NSRect)dirtyRect; - (void) finalize; - (BOOL) isFlipped; +- (BOOL) needsDisplay; - (BOOL) acceptsFirstResponder; - (BOOL) becomeFirstResponder; - (BOOL) resignFirstResponder; diff --git a/panda/src/cocoadisplay/cocoaPandaView.mm b/panda/src/cocoadisplay/cocoaPandaView.mm index 2e2c82a11e..fc31079ff7 100644 --- a/panda/src/cocoadisplay/cocoaPandaView.mm +++ b/panda/src/cocoadisplay/cocoaPandaView.mm @@ -21,6 +21,9 @@ - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window { self = [super initWithFrame: frameRect]; + _context = context; + [self setCanDrawConcurrently:YES]; + cocoadisplay_cat.debug() << "Created CocoaPandaView " << self << " for GraphicsWindow " << window << "\n"; _graphicsWindow = window; @@ -28,6 +31,21 @@ 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 { _graphicsWindow->handle_close_event(); [super finalize]; @@ -39,6 +57,11 @@ return YES; } +- (BOOL) needsDisplay { + // Never, we don't use drawRect. We draw from elsewhere. + return NO; +} + - (BOOL) acceptsFirstResponder { return YES; } @@ -59,7 +82,6 @@ - (void) setFrame: (NSRect) frame { [super setFrame: frame]; - //[_context update]; //_graphicsWindow->handle_resize_event(); } @@ -111,7 +133,7 @@ } - (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) { _graphicsWindow->handle_mouse_button_event(1, true); } else { @@ -124,7 +146,7 @@ } - (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) { _graphicsWindow->handle_mouse_button_event(1, false); } else { diff --git a/panda/src/cocoadisplay/cocoaPandaWindow.mm b/panda/src/cocoadisplay/cocoaPandaWindow.mm index c007803d77..9f2a737276 100644 --- a/panda/src/cocoadisplay/cocoaPandaWindow.mm +++ b/panda/src/cocoadisplay/cocoaPandaWindow.mm @@ -29,6 +29,7 @@ [self setDelegate:delegate]; [self setOpaque:YES]; [self setReleasedWhenClosed:YES]; + [self setAllowsConcurrentViewDrawing:YES]; // Necessary to be able to accept mouseMoved in the NSView [self setAcceptsMouseMovedEvents:YES];