X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/eabe8426ccfd2241128fce8831842be042b6c581..c8eab84f834989c4c7285376ece45504c51b1205:/src/osx/cocoa/nonownedwnd.mm diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index 066989265c..35e7553229 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -13,6 +13,8 @@ #ifndef WX_PRECOMP #include "wx/nonownedwnd.h" #include "wx/frame.h" + #include "wx/app.h" + #include "wx/dialog.h" #endif #include "wx/osx/private.h" @@ -78,39 +80,82 @@ bool shouldHandleSelector(SEL selector) } // -// wx native implementation classes +// wx category for NSWindow (our own and wrapped instances) // -typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector); +@interface NSWindow (wxNSWindowSupport) + +- (wxNonOwnedWindowCocoaImpl*) WX_implementation; + +- (bool) WX_filterSendEvent:(NSEvent *) event; + +@end + +@implementation NSWindow (wxNSWindowSupport) + +- (wxNonOwnedWindowCocoaImpl*) WX_implementation +{ + return (wxNonOwnedWindowCocoaImpl*) wxNonOwnedWindowImpl::FindFromWXWindow( self ); +} + +// TODO in cocoa everything during a drag is sent to the NSWindow the mouse down occured, +// this does not conform to the wx behaviour if the window is not captured, so try to resend +// or capture all wx mouse event handling at the tlw as we did for carbon + +- (bool) WX_filterSendEvent:(NSEvent *) event +{ + bool handled = false; + if ( ([event type] >= NSLeftMouseDown) && ([event type] <= NSMouseExited) ) + { + wxWindow* cw = wxWindow::GetCapture(); + if ( cw != NULL ) + { + ((wxWidgetCocoaImpl*)cw->GetPeer())->DoHandleMouseEvent( event); + handled = true; + } + } + return handled; +} +@end + +// +// wx native implementation +// @interface wxNSWindow : NSWindow { - wxNonOwnedWindowCocoaImpl* impl; } +- (void) sendEvent:(NSEvent *)event; - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen; -- (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation; -- (wxNonOwnedWindowCocoaImpl*) implementation; - (void)noResponderFor: (SEL) selector; @end @implementation wxNSWindow -// The default implementation always moves the window back onto the screen, -// even when the programmer explicitly wants to hide it. -- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen +- (void)sendEvent:(NSEvent *) event { - return frameRect; -} + if ( ![self WX_filterSendEvent: event] ) + { + WXEVENTREF formerEvent = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEvent(); + WXEVENTHANDLERCALLREF formerHandler = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEventHandlerCallRef(); -- (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation -{ - impl = theImplementation; + if (wxTheApp) + wxTheApp->MacSetCurrentEvent(event, NULL); + + [super sendEvent: event]; + + if (wxTheApp) + wxTheApp->MacSetCurrentEvent(formerEvent , formerHandler); + } } -- (wxNonOwnedWindowCocoaImpl*) implementation +// The default implementation always moves the window back onto the screen, +// even when the programmer explicitly wants to hide it. +- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen { - return impl; + wxUnusedVar(screen); + return frameRect; } - (void)doCommandBySelector:(SEL)selector @@ -127,41 +172,34 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector if (selector != @selector(keyDown:) && selector != @selector(keyUp:)) { [super noResponderFor:selector]; -// wxOSX_NoResponderHandlerPtr superimpl = (wxOSX_NoResponderHandlerPtr) [[self superclass] instanceMethodForSelector:@selector(noResponderFor:)]; -// superimpl(self, @selector(noResponderFor:), selector); } } +// We need this for borderless windows, i.e. shaped windows or windows without +// a title bar. For more info, see: +// http://lists.apple.com/archives/cocoa-dev/2008/May/msg02091.html +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + @end @interface wxNSPanel : NSPanel - { - wxNonOwnedWindowCocoaImpl* impl; } -- (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation; -- (wxNonOwnedWindowCocoaImpl*) implementation; - (void)noResponderFor: (SEL) selector; +- (void)sendEvent:(NSEvent *)event; @end @implementation wxNSPanel -- (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation -{ - impl = theImplementation; -} - - (BOOL)canBecomeKeyWindow { return YES; } -- (wxNonOwnedWindowCocoaImpl*) implementation -{ - return impl; -} - - (void)doCommandBySelector:(SEL)selector { if (shouldHandleSelector(selector)) @@ -174,11 +212,15 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector if (selector != @selector(keyDown:) && selector != @selector(keyUp:)) { [super noResponderFor:selector]; -// wxOSX_NoResponderHandlerPtr superimpl = (wxOSX_NoResponderHandlerPtr) [[self superclass] instanceMethodForSelector:@selector(noResponderFor:)]; -// superimpl(self, @selector(noResponderFor:), selector); } } +- (void)sendEvent:(NSEvent *) event +{ + if ( ![self WX_filterSendEvent: event] ) + [super sendEvent: event]; +} + @end @@ -186,7 +228,7 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector // controller // -@interface wxNonOwnedWindowController : NSObject +@interface wxNonOwnedWindowController : NSObject wxOSX_10_6_AND_LATER() { } @@ -196,6 +238,7 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector - (void)windowDidBecomeKey:(NSNotification *)notification; - (void)windowDidMove:(NSNotification *)notification; - (BOOL)windowShouldClose:(id)window; +- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame; @end @@ -209,8 +252,7 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector - (BOOL)windowShouldClose:(id)nwindow { - wxNSWindow* window = (wxNSWindow*) nwindow; - wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation]; + wxNonOwnedWindowCocoaImpl* windowimpl = [(NSWindow*) nwindow WX_implementation]; if ( windowimpl ) { wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer(); @@ -220,15 +262,15 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector return NO; } -- (NSSize)windowWillResize:(NSWindow *)win +- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize { - NSRect frame = [win frame]; + NSRect frame = [window frame]; wxRect wxframe = wxFromNSRect( NULL, frame ); wxframe.SetWidth( (int)proposedFrameSize.width ); wxframe.SetHeight( (int)proposedFrameSize.height ); - wxNSWindow* window = (wxNSWindow*) win; - wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation]; + + wxNonOwnedWindowCocoaImpl* windowimpl = [window WX_implementation]; if ( windowimpl ) { wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer(); @@ -245,8 +287,8 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector - (void)windowDidResize:(NSNotification *)notification { - wxNSWindow* window = (wxNSWindow*) [notification object]; - wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation]; + NSWindow* window = (NSWindow*) [notification object]; + wxNonOwnedWindowCocoaImpl* windowimpl = [window WX_implementation]; if ( windowimpl ) { wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer(); @@ -258,7 +300,7 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector - (void)windowDidMove:(NSNotification *)notification { wxNSWindow* window = (wxNSWindow*) [notification object]; - wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation]; + wxNonOwnedWindowCocoaImpl* windowimpl = [window WX_implementation]; if ( windowimpl ) { wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer(); @@ -269,8 +311,8 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector - (void)windowDidBecomeKey:(NSNotification *)notification { - wxNSWindow* window = (wxNSWindow*) [notification object]; - wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation]; + NSWindow* window = (NSWindow*) [notification object]; + wxNonOwnedWindowCocoaImpl* windowimpl = [window WX_implementation]; if ( windowimpl ) { wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer(); @@ -281,8 +323,8 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector - (void)windowDidResignKey:(NSNotification *)notification { - wxNSWindow* window = (wxNSWindow*) [notification object]; - wxNonOwnedWindowCocoaImpl* windowimpl = [window implementation]; + NSWindow* window = (NSWindow*) [notification object]; + wxNonOwnedWindowCocoaImpl* windowimpl = [window WX_implementation]; if ( windowimpl ) { wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer(); @@ -319,6 +361,20 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector return nil; } +- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame +{ + wxUnusedVar(newFrame); + wxNonOwnedWindowCocoaImpl* windowimpl = [window WX_implementation]; + if ( windowimpl ) + { + wxNonOwnedWindow* wxpeer = windowimpl->GetWXPeer(); + wxMaximizeEvent event(wxpeer->GetId()); + event.SetEventObject(wxpeer); + return !wxpeer->HandleWindowEvent(event); + } + return true; +} + @end IMPLEMENT_DYNAMIC_CLASS( wxNonOwnedWindowCocoaImpl , wxNonOwnedWindowImpl ) @@ -338,17 +394,22 @@ wxNonOwnedWindowCocoaImpl::wxNonOwnedWindowCocoaImpl() wxNonOwnedWindowCocoaImpl::~wxNonOwnedWindowCocoaImpl() { - [m_macWindow setImplementation:nil]; - [m_macWindow setDelegate:nil]; - [m_macWindow release]; + if ( !m_wxPeer->IsNativeWindowWrapper() ) + { + [m_macWindow setDelegate:nil]; + [m_macWindow release]; + } } -void wxNonOwnedWindowCocoaImpl::Destroy() +void wxNonOwnedWindowCocoaImpl::WillBeDestroyed() { - wxPendingDelete.Append( new wxDeferredObjectDeleter( this ) ); + if ( !m_wxPeer->IsNativeWindowWrapper() ) + { + [m_macWindow setDelegate:nil]; + } } -void wxNonOwnedWindowCocoaImpl::Create( wxWindow* WXUNUSED(parent), const wxPoint& pos, const wxSize& size, +void wxNonOwnedWindowCocoaImpl::Create( wxWindow* parent, const wxPoint& pos, const wxSize& size, long style, long extraStyle, const wxString& WXUNUSED(name) ) { static wxNonOwnedWindowController* controller = NULL; @@ -448,7 +509,7 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) NSRect r = wxToNSRect( NULL, wxRect( pos, size) ); - [m_macWindow setImplementation:this]; + r = [NSWindow contentRectForFrameRect:r styleMask:windowstyle]; [m_macWindow initWithContentRect:r styleMask:windowstyle @@ -456,13 +517,49 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) defer:NO ]; + // If the parent is modal, windows with wxFRAME_FLOAT_ON_PARENT style need + // to be in kCGUtilityWindowLevel and not kCGFloatingWindowLevel to stay + // above the parent. + wxDialog * const parentDialog = wxDynamicCast(parent, wxDialog); + if (parentDialog && parentDialog->IsModal()) + { + if (level == kCGFloatingWindowLevel) + { + level = kCGUtilityWindowLevel; + } + + // Cocoa's modal loop does not process other windows by default, but + // don't call this on normal window levels so nested modal dialogs will + // still behave modally. + if (level != kCGNormalWindowLevel) + { + if ([m_macWindow isKindOfClass:[NSPanel class]]) + { + [(NSPanel*)m_macWindow setWorksWhenModal:YES]; + } + } + } + [m_macWindow setLevel:level]; [m_macWindow setDelegate:controller]; [m_macWindow setAcceptsMouseMovedEvents: YES]; + + if ( ( style & wxFRAME_SHAPED) ) + { + [m_macWindow setOpaque:NO]; + [m_macWindow setAlphaValue:1.0]; + } + + if ( !(style & wxFRAME_TOOL_WINDOW) ) + [m_macWindow setHidesOnDeactivate:NO]; } +void wxNonOwnedWindowCocoaImpl::Create( wxWindow* WXUNUSED(parent), WXWindow nativeWindow ) +{ + m_macWindow = nativeWindow; +} WXWindow wxNonOwnedWindowCocoaImpl::GetWXWindow() const { @@ -481,7 +578,7 @@ void wxNonOwnedWindowCocoaImpl::Lower() void wxNonOwnedWindowCocoaImpl::ShowWithoutActivating() { - [m_macWindow orderBack:nil]; + [m_macWindow orderFront:nil]; [[m_macWindow contentView] setNeedsDisplay: YES]; } @@ -620,7 +717,19 @@ void wxNonOwnedWindowCocoaImpl::SetTitle( const wxString& title, wxFontEncoding bool wxNonOwnedWindowCocoaImpl::IsMaximized() const { - return [m_macWindow isZoomed]; + if (([m_macWindow styleMask] & NSResizableWindowMask) != 0) + { + return [m_macWindow isZoomed]; + } + else + { + NSRect rectScreen = [[NSScreen mainScreen] visibleFrame]; + NSRect rectWindow = [m_macWindow frame]; + return (rectScreen.origin.x == rectWindow.origin.x && + rectScreen.origin.y == rectWindow.origin.y && + rectScreen.size.width == rectWindow.size.width && + rectScreen.size.height == rectWindow.size.height); + } } bool wxNonOwnedWindowCocoaImpl::IsIconized() const @@ -683,8 +792,25 @@ bool wxNonOwnedWindowCocoaImpl::ShowFullScreen(bool show, long WXUNUSED(style)) return true; } -void wxNonOwnedWindowCocoaImpl::RequestUserAttention(int WXUNUSED(flags)) +void wxNonOwnedWindowCocoaImpl::RequestUserAttention(int flagsWX) { + NSRequestUserAttentionType flagsOSX; + switch ( flagsWX ) + { + case wxUSER_ATTENTION_INFO: + flagsOSX = NSInformationalRequest; + break; + + case wxUSER_ATTENTION_ERROR: + flagsOSX = NSCriticalRequest; + break; + + default: + wxFAIL_MSG( "invalid RequestUserAttention() flags" ); + return; + } + + [NSApp requestUserAttention:flagsOSX]; } void wxNonOwnedWindowCocoaImpl::ScreenToWindow( int *x, int *y ) @@ -718,6 +844,23 @@ bool wxNonOwnedWindowCocoaImpl::IsActive() return [m_macWindow isKeyWindow]; } +void wxNonOwnedWindowCocoaImpl::SetModified(bool modified) +{ + [m_macWindow setDocumentEdited:modified]; +} + +bool wxNonOwnedWindowCocoaImpl::IsModified() const +{ + return [m_macWindow isDocumentEdited]; +} + +wxNonOwnedWindowImpl* wxNonOwnedWindowImpl::CreateNonOwnedWindow( wxNonOwnedWindow* wxpeer, wxWindow* parent, WXWindow nativeWindow) +{ + wxNonOwnedWindowCocoaImpl* now = new wxNonOwnedWindowCocoaImpl( wxpeer ); + now->Create( parent, nativeWindow ); + return now; +} + wxNonOwnedWindowImpl* wxNonOwnedWindowImpl::CreateNonOwnedWindow( wxNonOwnedWindow* wxpeer, wxWindow* parent, const wxPoint& pos, const wxSize& size, long style, long extraStyle, const wxString& name ) {