X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/01639b0809cfceac03392aeefd5a5d8af62b2014..0afeb753e0a6a3fdba290bf3612bb2f012d44d95:/src/osx/cocoa/nonownedwnd.mm diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index fd0b0a3648..030b1e6a23 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -4,7 +4,7 @@ // Author: DavidStefan Csomor // Modified by: // Created: 2008-06-20 -// RCS-ID: $Id: nonownedwnd.mm 48805 2007-09-19 14:52:25Z SC $ +// RCS-ID: $Id$ // Copyright: (c) Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -13,13 +13,27 @@ #ifndef WX_PRECOMP #include "wx/nonownedwnd.h" #include "wx/frame.h" + #include "wx/app.h" + #include "wx/dialog.h" + #include "wx/menuitem.h" + #include "wx/menu.h" #endif #include "wx/osx/private.h" +NSScreen* wxOSXGetMenuScreen() +{ + if ( [NSScreen screens] == nil ) + return [NSScreen mainScreen]; + else + { + return [[NSScreen screens] objectAtIndex:0]; + } +} + NSRect wxToNSRect( NSView* parent, const wxRect& r ) { - NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame]; + NSRect frame = parent ? [parent bounds] : [wxOSXGetMenuScreen() frame]; int y = r.y; int x = r.x ; if ( parent == NULL || ![ parent isFlipped ] ) @@ -29,7 +43,7 @@ NSRect wxToNSRect( NSView* parent, const wxRect& r ) wxRect wxFromNSRect( NSView* parent, const NSRect& rect ) { - NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame]; + NSRect frame = parent ? [parent bounds] : [wxOSXGetMenuScreen() frame]; int y = (int)rect.origin.y; int x = (int)rect.origin.x; if ( parent == NULL || ![ parent isFlipped ] ) @@ -39,7 +53,7 @@ wxRect wxFromNSRect( NSView* parent, const NSRect& rect ) NSPoint wxToNSPoint( NSView* parent, const wxPoint& p ) { - NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame]; + NSRect frame = parent ? [parent bounds] : [wxOSXGetMenuScreen() frame]; int x = p.x ; int y = p.y; if ( parent == NULL || ![ parent isFlipped ] ) @@ -49,7 +63,7 @@ NSPoint wxToNSPoint( NSView* parent, const wxPoint& p ) wxPoint wxFromNSPoint( NSView* parent, const NSPoint& p ) { - NSRect frame = parent ? [parent bounds] : [[NSScreen mainScreen] frame]; + NSRect frame = parent ? [parent bounds] : [wxOSXGetMenuScreen() frame]; int x = (int)p.x; int y = (int)p.y; if ( parent == NULL || ![ parent isFlipped ] ) @@ -65,6 +79,7 @@ bool shouldHandleSelector(SEL selector) || selector == @selector(deleteForward:) || selector == @selector(insertNewline:) || selector == @selector(insertTab:) + || selector == @selector(insertBacktab:) || selector == @selector(keyDown:) || selector == @selector(keyUp:) || selector == @selector(scrollPageUp:) @@ -78,39 +93,95 @@ bool shouldHandleSelector(SEL selector) } // -// wx native implementation classes +// wx category for NSWindow (our own and wrapped instances) +// + +@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 occurred, +// 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) ) + { + WXEVENTREF formerEvent = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEvent(); + WXEVENTHANDLERCALLREF formerHandler = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEventHandlerCallRef(); + + wxWindow* cw = wxWindow::GetCapture(); + if ( cw != NULL ) + { + if (wxTheApp) + wxTheApp->MacSetCurrentEvent(event, NULL); + ((wxWidgetCocoaImpl*)cw->GetPeer())->DoHandleMouseEvent( event); + handled = true; + } + if ( handled ) + { + if (wxTheApp) + wxTheApp->MacSetCurrentEvent(formerEvent , formerHandler); + } + } + return handled; +} +@end + +// +// wx native implementation // -typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector); +static NSResponder* s_nextFirstResponder = NULL; @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; +- (BOOL)makeFirstResponder:(NSResponder *)aResponder; @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,29 +198,46 @@ 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; +} + +- (BOOL)makeFirstResponder:(NSResponder *)aResponder +{ + s_nextFirstResponder = aResponder; + BOOL retval = [super makeFirstResponder:aResponder]; + s_nextFirstResponder = nil; + return retval; +} + @end @interface wxNSPanel : NSPanel - { - wxNonOwnedWindowCocoaImpl* impl; } -- (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation; -- (wxNonOwnedWindowCocoaImpl*) implementation; +- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen; - (void)noResponderFor: (SEL) selector; +- (void)sendEvent:(NSEvent *)event; +- (BOOL)makeFirstResponder:(NSResponder *)aResponder; @end @implementation wxNSPanel -- (void)setImplementation: (wxNonOwnedWindowCocoaImpl *) theImplementation +- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen { - impl = theImplementation; + wxNonOwnedWindowCocoaImpl* impl = (wxNonOwnedWindowCocoaImpl*) wxNonOwnedWindowImpl::FindFromWXWindow( self ); + if (impl && impl->IsFullScreen()) + return frameRect; + else + return [super constrainFrameRect:frameRect toScreen:screen]; } - (BOOL)canBecomeKeyWindow @@ -157,11 +245,6 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector return YES; } -- (wxNonOwnedWindowCocoaImpl*) implementation -{ - return impl; -} - - (void)doCommandBySelector:(SEL)selector { if (shouldHandleSelector(selector)) @@ -174,11 +257,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); } } +- (void)sendEvent:(NSEvent *) event +{ + if ( ![self WX_filterSendEvent: event] ) + { + WXEVENTREF formerEvent = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEvent(); + WXEVENTHANDLERCALLREF formerHandler = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEventHandlerCallRef(); + + if (wxTheApp) + wxTheApp->MacSetCurrentEvent(event, NULL); + + [super sendEvent: event]; + + if (wxTheApp) + wxTheApp->MacSetCurrentEvent(formerEvent , formerHandler); + } +} + +- (BOOL)makeFirstResponder:(NSResponder *)aResponder +{ + s_nextFirstResponder = aResponder; + BOOL retval = [super makeFirstResponder:aResponder]; + s_nextFirstResponder = nil; + return retval; +} + @end @@ -186,7 +292,7 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector // controller // -@interface wxNonOwnedWindowController : NSObject +@interface wxNonOwnedWindowController : NSObject wxOSX_10_6_AND_LATER() { } @@ -196,21 +302,96 @@ 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 +extern int wxOSXGetIdFromSelector(SEL action ); + @implementation wxNonOwnedWindowController - (id) init { - [super init]; + self = [super init]; return self; } +- (BOOL) triggerMenu:(SEL) action +{ + wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar(); + if ( mbar ) + { + wxMenu* menu = NULL; + wxMenuItem* menuitem = mbar->FindItem(wxOSXGetIdFromSelector(action), &menu); + if ( menu != NULL && menuitem != NULL) + return menu->HandleCommandProcess(menuitem); + } + return NO; +} + +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + SEL action = [menuItem action]; + + wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar(); + if ( mbar ) + { + wxMenu* menu = NULL; + wxMenuItem* menuitem = mbar->FindItem(wxOSXGetIdFromSelector(action), &menu); + if ( menu != NULL && menuitem != NULL) + { + menu->HandleCommandUpdateStatus(menuitem); + return menuitem->IsEnabled(); + } + } + return YES; +} + +- (void)undo:(id)sender +{ + wxUnusedVar(sender); + [self triggerMenu:_cmd]; +} + +- (void)redo:(id)sender +{ + wxUnusedVar(sender); + [self triggerMenu:_cmd]; +} + +- (void)cut:(id)sender +{ + wxUnusedVar(sender); + [self triggerMenu:_cmd]; +} + +- (void)copy:(id)sender +{ + wxUnusedVar(sender); + [self triggerMenu:_cmd]; +} + +- (void)paste:(id)sender +{ + wxUnusedVar(sender); + [self triggerMenu:_cmd]; +} + +- (void)delete:(id)sender +{ + wxUnusedVar(sender); + [self triggerMenu:_cmd]; +} + +- (void)selectAll:(id)sender +{ + wxUnusedVar(sender); + [self triggerMenu:_cmd]; +} + - (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 +401,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 +426,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 +439,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 +450,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,20 +462,27 @@ 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(); if ( wxpeer ) { wxpeer->HandleActivated(0, false); + // as for wx the deactivation also means losing focus we + // must trigger this manually + [window makeFirstResponder:nil]; + + // TODO Remove if no problems arise with Popup Windows +#if 0 // Needed for popup window since the firstResponder // (focus in wx) doesn't change when this // TLW becomes inactive. wxFocusEvent event( wxEVT_KILL_FOCUS, wxpeer->GetId()); event.SetEventObject(wxpeer); wxpeer->HandleWindowEvent(event); +#endif } } } @@ -312,13 +500,41 @@ typedef void (*wxOSX_NoResponderHandlerPtr)(NSView* self, SEL _cmd, SEL selector editor = [[wxNSTextFieldEditor alloc] init]; [editor setFieldEditor:YES]; [tf setFieldEditor:editor]; + [editor release]; } return editor; - } - + } + else if ([anObject isKindOfClass:[wxNSComboBox class]]) + { + wxNSComboBox * cb = (wxNSComboBox*) anObject; + wxNSTextFieldEditor* editor = [cb fieldEditor]; + if ( editor == nil ) + { + editor = [[wxNSTextFieldEditor alloc] init]; + [editor setFieldEditor:YES]; + [cb setFieldEditor:editor]; + [editor release]; + } + return editor; + } + 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 +554,28 @@ wxNonOwnedWindowCocoaImpl::wxNonOwnedWindowCocoaImpl() wxNonOwnedWindowCocoaImpl::~wxNonOwnedWindowCocoaImpl() { - [m_macWindow setImplementation:nil]; - [m_macWindow setDelegate:nil]; - [m_macWindow release]; + if ( !m_wxPeer->IsNativeWindowWrapper() ) + { + [m_macWindow setDelegate:nil]; + + // make sure we remove this first, otherwise the ref count will not lead to the + // native window's destruction + if ([m_macWindow parentWindow] != 0) + [[m_macWindow parentWindow] removeChildWindow: m_macWindow]; + + [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; @@ -361,41 +588,21 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) if ( style & wxFRAME_TOOL_WINDOW || ( style & wxPOPUP_WINDOW ) || GetWXPeer()->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG ) - { m_macWindow = [wxNSPanel alloc]; - } else m_macWindow = [wxNSWindow alloc]; + [m_macWindow setAcceptsMouseMovedEvents:YES]; + CGWindowLevel level = kCGNormalWindowLevel; if ( style & wxFRAME_TOOL_WINDOW ) { windowstyle |= NSUtilityWindowMask; - if ( ( style & wxMINIMIZE_BOX ) || ( style & wxMAXIMIZE_BOX ) || - ( style & wxCLOSE_BOX ) || ( style & wxSYSTEM_MENU ) ) - { - windowstyle |= NSTitledWindowMask ; - } } else if ( ( style & wxPOPUP_WINDOW ) ) { level = kCGPopUpMenuWindowLevel; - /* - if ( ( style & wxBORDER_NONE ) ) - { - wclass = kHelpWindowClass ; // has no border - attr |= kWindowNoShadowAttribute; - } - else - { - wclass = kPlainWindowClass ; // has a single line border, it will have to do for now - } - */ - } - else if ( ( style & wxCAPTION ) ) - { - windowstyle |= NSTitledWindowMask ; } else if ( ( style & wxFRAME_DRAWER ) ) { @@ -403,40 +610,24 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) wclass = kDrawerWindowClass; */ } - else - { - // set these even if we have no title, otherwise the controls won't be visible - if ( ( style & wxMINIMIZE_BOX ) || ( style & wxMAXIMIZE_BOX ) || - ( style & wxCLOSE_BOX ) || ( style & wxSYSTEM_MENU ) ) - { - windowstyle |= NSTitledWindowMask ; - } - /* - else if ( ( style & wxNO_BORDER ) ) - { - wclass = kSimpleWindowClass ; - } - else - { - wclass = kPlainWindowClass ; - } - */ - } - - if ( windowstyle & NSTitledWindowMask ) + + if ( ( style & wxMINIMIZE_BOX ) || ( style & wxMAXIMIZE_BOX ) || + ( style & wxCLOSE_BOX ) || ( style & wxSYSTEM_MENU ) || ( style & wxCAPTION ) ) { + windowstyle |= NSTitledWindowMask ; if ( ( style & wxMINIMIZE_BOX ) ) windowstyle |= NSMiniaturizableWindowMask ; - + if ( ( style & wxMAXIMIZE_BOX ) ) - windowstyle |= NSResizableWindowMask ; // TODO showing ZOOM ? - - if ( ( style & wxRESIZE_BORDER ) ) windowstyle |= NSResizableWindowMask ; - + if ( ( style & wxCLOSE_BOX) ) windowstyle |= NSClosableWindowMask ; } + + if ( ( style & wxRESIZE_BORDER ) ) + windowstyle |= NSResizableWindowMask ; + if ( extraStyle & wxFRAME_EX_METAL) windowstyle |= NSTexturedBackgroundWindowMask; @@ -448,7 +639,6 @@ 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 @@ -456,14 +646,58 @@ long style, long extraStyle, const wxString& WXUNUSED(name) ) backing:NSBackingStoreBuffered defer:NO ]; + + // if we just have a title bar with no buttons needed, hide them + if ( (windowstyle & NSTitledWindowMask) && + !(style & wxCLOSE_BOX) && !(style & wxMAXIMIZE_BOX) && !(style & wxMINIMIZE_BOX) ) + { + [[m_macWindow standardWindowButton:NSWindowZoomButton] setHidden:YES]; + [[m_macWindow standardWindowButton:NSWindowCloseButton] setHidden:YES]; + [[m_macWindow standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; + } + + // 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_macWindowLevel = 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 { @@ -472,7 +706,7 @@ WXWindow wxNonOwnedWindowCocoaImpl::GetWXWindow() const void wxNonOwnedWindowCocoaImpl::Raise() { - [m_macWindow orderWindow:NSWindowAbove relativeTo:0]; + [m_macWindow makeKeyAndOrderFront:nil]; } void wxNonOwnedWindowCocoaImpl::Lower() @@ -482,7 +716,7 @@ void wxNonOwnedWindowCocoaImpl::Lower() void wxNonOwnedWindowCocoaImpl::ShowWithoutActivating() { - [m_macWindow orderBack:nil]; + [m_macWindow orderFront:nil]; [[m_macWindow contentView] setNeedsDisplay: YES]; } @@ -491,14 +725,35 @@ bool wxNonOwnedWindowCocoaImpl::Show(bool show) if ( show ) { wxNonOwnedWindow* wxpeer = GetWXPeer(); - if (wxpeer && !(wxpeer->GetWindowStyle() & wxFRAME_TOOL_WINDOW)) - [m_macWindow makeKeyAndOrderFront:nil]; - else - [m_macWindow orderFront:nil]; + if ( wxpeer ) + { + // add to parent window before showing + wxDialog * const dialog = wxDynamicCast(wxpeer, wxDialog); + if ( wxpeer->GetParent() && dialog && dialog->IsModal()) + { + NSView * parentView = wxpeer->GetParent()->GetPeer()->GetWXWidget(); + if ( parentView ) + { + NSWindow* parentNSWindow = [parentView window]; + if ( parentNSWindow ) + [parentNSWindow addChildWindow:m_macWindow ordered:NSWindowAbove]; + } + } + + if (!(wxpeer->GetWindowStyle() & wxFRAME_TOOL_WINDOW)) + [m_macWindow makeKeyAndOrderFront:nil]; + else + [m_macWindow orderFront:nil]; + } [[m_macWindow contentView] setNeedsDisplay: YES]; } else + { + // avoid propagation of orderOut to parent + if ([m_macWindow parentWindow] != 0) + [[m_macWindow parentWindow] removeChildWindow: m_macWindow]; [m_macWindow orderOut:nil]; + } return true; } @@ -521,8 +776,12 @@ bool wxNonOwnedWindowCocoaImpl::SetTransparent(wxByte alpha) return true; } -bool wxNonOwnedWindowCocoaImpl::SetBackgroundColour(const wxColour& WXUNUSED(col) ) +bool wxNonOwnedWindowCocoaImpl::SetBackgroundColour(const wxColour& col ) { + [m_macWindow setBackgroundColor:[NSColor colorWithCalibratedRed:(CGFloat) (col.Red() / 255.0) + green:(CGFloat) (col.Green() / 255.0) + blue:(CGFloat) (col.Blue() / 255.0) + alpha:(CGFloat) (col.Alpha() / 255.0)]]; return true; } @@ -545,7 +804,8 @@ void wxNonOwnedWindowCocoaImpl::SetExtraStyle( long exStyle ) void wxNonOwnedWindowCocoaImpl::SetWindowStyleFlag( long style ) { - if (m_macWindow) + // don't mess with native wrapped windows, they might throw an exception when their level is changed + if (!m_wxPeer->IsNativeWindowWrapper() && m_macWindow) { CGWindowLevel level = kCGNormalWindowLevel; @@ -555,6 +815,7 @@ void wxNonOwnedWindowCocoaImpl::SetWindowStyleFlag( long style ) level = kCGFloatingWindowLevel; [m_macWindow setLevel: level]; + m_macWindowLevel = level; } } @@ -597,8 +858,6 @@ void wxNonOwnedWindowCocoaImpl::GetSize( int &width, int &height ) const void wxNonOwnedWindowCocoaImpl::GetContentArea( int& left, int &top, int &width, int &height ) const { - NSRect outer = NSMakeRect(100,100,100,100); - NSRect content = [NSWindow contentRectForFrameRect:outer styleMask:[m_macWindow styleMask] ]; NSRect rect = [[m_macWindow contentView] frame]; left = (int)rect.origin.x; top = (int)rect.origin.y; @@ -621,7 +880,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 @@ -647,6 +918,7 @@ void wxNonOwnedWindowCocoaImpl::Maximize(bool WXUNUSED(maximize)) typedef struct { + NSUInteger m_formerStyleMask; int m_formerLevel; NSRect m_formerFrame; } FullScreenData ; @@ -667,25 +939,74 @@ bool wxNonOwnedWindowCocoaImpl::ShowFullScreen(bool show, long WXUNUSED(style)) m_macFullScreenData = data ; data->m_formerLevel = [m_macWindow level]; data->m_formerFrame = [m_macWindow frame]; - CGDisplayCapture( kCGDirectMainDisplay ); - [m_macWindow setLevel:CGShieldingWindowLevel()]; - [m_macWindow setFrame:[[NSScreen mainScreen] frame] display:YES]; + data->m_formerStyleMask = [m_macWindow styleMask]; +#if 0 + // CGDisplayCapture( kCGDirectMainDisplay ); + //[m_macWindow setLevel:NSMainMenuWindowLevel+1/*CGShieldingWindowLevel()*/]; +#endif + NSRect screenframe = [[NSScreen mainScreen] frame]; + NSRect frame = NSMakeRect (0, 0, 100, 100); + NSRect contentRect; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + if ( [ m_macWindow respondsToSelector:@selector(setStyleMask:) ] ) + [m_macWindow setStyleMask:data->m_formerStyleMask & ~ NSResizableWindowMask]; +#endif + + contentRect = [NSWindow contentRectForFrameRect: frame + styleMask: [m_macWindow styleMask]]; + screenframe.origin.y += (frame.origin.y - contentRect.origin.y); + screenframe.size.height += (frame.size.height - contentRect.size.height); + [m_macWindow setFrame:screenframe display:YES]; + + SetSystemUIMode(kUIModeAllHidden, + kUIOptionDisableAppleMenu + /* + | kUIOptionDisableProcessSwitch + | kUIOptionDisableForceQuit + */); } else if ( m_macFullScreenData != NULL ) { FullScreenData *data = (FullScreenData *) m_macFullScreenData ; - CGDisplayRelease( kCGDirectMainDisplay ); - [m_macWindow setLevel:data->m_formerLevel]; +#if 0 + // CGDisplayRelease( kCGDirectMainDisplay ); + // [m_macWindow setLevel:data->m_formerLevel]; +#endif + [m_macWindow setFrame:data->m_formerFrame display:YES]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + if ( [ m_macWindow respondsToSelector:@selector(setStyleMask:) ] ) + [m_macWindow setStyleMask:data->m_formerStyleMask]; +#endif delete data ; m_macFullScreenData = NULL ; + + SetSystemUIMode(kUIModeNormal, 0); } 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 ) @@ -719,6 +1040,44 @@ bool wxNonOwnedWindowCocoaImpl::IsActive() return [m_macWindow isKeyWindow]; } +void wxNonOwnedWindowCocoaImpl::SetModified(bool modified) +{ + [m_macWindow setDocumentEdited:modified]; +} + +bool wxNonOwnedWindowCocoaImpl::IsModified() const +{ + return [m_macWindow isDocumentEdited]; +} + +void wxNonOwnedWindowCocoaImpl::SetRepresentedFilename(const wxString& filename) +{ + [m_macWindow setRepresentedFilename:wxCFStringRef(filename).AsNSString()]; +} + +void wxNonOwnedWindowCocoaImpl::RestoreWindowLevel() +{ + if ( [m_macWindow level] != m_macWindowLevel ) + [m_macWindow setLevel:m_macWindowLevel]; +} + +WX_NSResponder wxNonOwnedWindowCocoaImpl::GetNextFirstResponder() +{ + return s_nextFirstResponder; +} + + +// +// +// + +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 ) { @@ -726,3 +1085,4 @@ wxNonOwnedWindowImpl* wxNonOwnedWindowImpl::CreateNonOwnedWindow( wxNonOwnedWind now->Create( parent, pos, size, style , extraStyle, name ); return now; } +