X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7c5a378ff21de766bab2fd76293be1008610afc2..11fe6505b848a968f4c89cb3c3fd37a6a03bcaea:/src/cocoa/window.mm diff --git a/src/cocoa/window.mm b/src/cocoa/window.mm index 83874d9ad0..2eaaafc97b 100644 --- a/src/cocoa/window.mm +++ b/src/cocoa/window.mm @@ -24,6 +24,7 @@ #include "wx/cocoa/string.h" #include "wx/cocoa/trackingrectmanager.h" +#import #import #include "wx/cocoa/objc/NSView.h" #import @@ -41,6 +42,18 @@ #import #endif //def WXCOCOA_FILL_DUMMY_VIEW +/* NSComparisonResult is typedef'd as an enum pre-Leopard but typedef'd as + * NSInteger post-Leopard. Pre-Leopard the Cocoa toolkit expects a function + * returning int and not NSComparisonResult. Post-Leopard the Cocoa toolkit + * expects a function returning the new non-enum NSComparsionResult. + * Hence we create a typedef named CocoaWindowCompareFunctionResult. + */ +#if defined(NSINTEGER_DEFINED) +typedef NSComparisonResult CocoaWindowCompareFunctionResult; +#else +typedef int CocoaWindowCompareFunctionResult; +#endif + // A category for methods that are only present in Panther's SDK @interface NSView(wxNSViewPrePantherCompatibility) - (void)getRectsBeingDrawn:(const NSRect **)rects count:(int *)count; @@ -368,6 +381,9 @@ wxWindow::~wxWindow() void wxWindowCocoa::CocoaAddChild(wxWindowCocoa *child) { + // Pool here due to lack of one during wx init phase + wxAutoNSAutoreleasePool pool; + NSView *childView = child->GetNSViewForSuperview(); wxASSERT(childView); @@ -458,7 +474,7 @@ bool wxWindowCocoa::Cocoa_drawRect(const NSRect &rect) // Set m_updateRegion const NSRect *rects = ▭ // The bounding box of the region - int countRects = 1; + NSInteger countRects = 1; // Try replacing the larger rectangle with a list of smaller ones: if ([GetNSView() respondsToSelector:@selector(getRectsBeingDrawn:count:)]) [GetNSView() getRectsBeingDrawn:&rects count:&countRects]; @@ -654,6 +670,15 @@ bool wxWindowCocoa::Cocoa_resetCursorRects() return true; } +bool wxWindowCocoa::SetCursor(const wxCursor &cursor) +{ + if(!wxWindowBase::SetCursor(cursor)) + return false; + // Invalidate the cursor rects so the cursor will change + [[GetNSView() window] invalidateCursorRectsForView:GetNSView()]; + return true; +} + bool wxWindowCocoa::Cocoa_viewDidMoveToWindow() { wxLogTrace(wxTRACE_COCOA,wxT("wxWindow=%p::viewDidMoveToWindow"),this); @@ -1007,19 +1032,82 @@ void wxWindow::DoSetVirtualSize( int x, int y ) bool wxWindow::SetFont(const wxFont& font) { - // TODO - return true; + // FIXME: We may need to handle wx font inheritance. + return wxWindowBase::SetFont(font); } -static int CocoaRaiseWindowCompareFunction(id first, id second, void *target) +#if 0 // these are used when debugging the algorithm. +static char const * const comparisonresultStrings[] = +{ "<" +, "==" +, ">" +}; +#endif + +class CocoaWindowCompareContext +{ + DECLARE_NO_COPY_CLASS(CocoaWindowCompareContext) +public: + CocoaWindowCompareContext(); // Not implemented + CocoaWindowCompareContext(NSView *target, NSArray *subviews) + { + m_target = target; + // Cocoa sorts subviews in-place.. make a copy + m_subviews = [subviews copy]; + } + ~CocoaWindowCompareContext() + { // release the copy + [m_subviews release]; + } + NSView* target() + { return m_target; } + NSArray* subviews() + { return m_subviews; } + /* Helper function that returns the comparison based off of the original ordering */ + CocoaWindowCompareFunctionResult CompareUsingOriginalOrdering(id first, id second) + { + NSUInteger firstI = [m_subviews indexOfObjectIdenticalTo:first]; + NSUInteger secondI = [m_subviews indexOfObjectIdenticalTo:second]; + // NOTE: If either firstI or secondI is NSNotFound then it will be NSIntegerMax and thus will + // likely compare higher than the other view which is reasonable considering the only way that + // can happen is if the subview was added after our call to subviews but before the call to + // sortSubviewsUsingFunction:context:. Thus we don't bother checking. Particularly because + // that case should never occur anyway because that would imply a multi-threaded GUI call + // which is a big no-no with Cocoa. + + // Subviews are ordered from back to front meaning one that is already lower will have an lower index. + NSComparisonResult result = (firstI < secondI) + ? NSOrderedAscending /* -1 */ + : (firstI > secondI) + ? NSOrderedDescending /* 1 */ + : NSOrderedSame /* 0 */; + +#if 0 // Enable this if you need to debug the algorithm. + NSLog(@"%@ [%d] %s %@ [%d]\n", first, firstI, comparisonresultStrings[result+1], second, secondI); +#endif + return result; + } +private: + /* The subview we are trying to Raise or Lower */ + NSView *m_target; + /* A copy of the original array of subviews */ + NSArray *m_subviews; +}; + +/* Causes Cocoa to raise the target view to the top of the Z-Order by telling the sort function that + * the target view is always higher than every other view. When comparing two views neither of + * which is the target, it returns the correct response based on the original ordering + */ +static CocoaWindowCompareFunctionResult CocoaRaiseWindowCompareFunction(id first, id second, void *ctx) { + CocoaWindowCompareContext *compareContext = (CocoaWindowCompareContext*)ctx; // first should be ordered higher - if(first==target) + if(first==compareContext->target()) return NSOrderedDescending; // second should be ordered higher - if(second==target) + if(second==compareContext->target()) return NSOrderedAscending; - return NSOrderedSame; + return compareContext->CompareUsingOriginalOrdering(first,second); } // Raise the window to the top of the Z order @@ -1027,29 +1115,47 @@ void wxWindow::Raise() { // wxAutoNSAutoreleasePool pool; NSView *nsview = GetNSViewForSuperview(); - [[nsview superview] sortSubviewsUsingFunction: + NSView *superview = [nsview superview]; + CocoaWindowCompareContext compareContext(nsview, [superview subviews]); + + [superview sortSubviewsUsingFunction: CocoaRaiseWindowCompareFunction - context: nsview]; + context: &compareContext]; } -static int CocoaLowerWindowCompareFunction(id first, id second, void *target) +/* Causes Cocoa to lower the target view to the bottom of the Z-Order by telling the sort function that + * the target view is always lower than every other view. When comparing two views neither of + * which is the target, it returns the correct response based on the original ordering + */ +static CocoaWindowCompareFunctionResult CocoaLowerWindowCompareFunction(id first, id second, void *ctx) { + CocoaWindowCompareContext *compareContext = (CocoaWindowCompareContext*)ctx; // first should be ordered lower - if(first==target) + if(first==compareContext->target()) return NSOrderedAscending; // second should be ordered lower - if(second==target) + if(second==compareContext->target()) return NSOrderedDescending; - return NSOrderedSame; + return compareContext->CompareUsingOriginalOrdering(first,second); } // Lower the window to the bottom of the Z order void wxWindow::Lower() { NSView *nsview = GetNSViewForSuperview(); - [[nsview superview] sortSubviewsUsingFunction: + NSView *superview = [nsview superview]; + CocoaWindowCompareContext compareContext(nsview, [superview subviews]); + +#if 0 + NSLog(@"Target:\n%@\n", nsview); + NSLog(@"Before:\n%@\n", compareContext.subviews()); +#endif + [superview sortSubviewsUsingFunction: CocoaLowerWindowCompareFunction - context: nsview]; + context: &compareContext]; +#if 0 + NSLog(@"After:\n%@\n", [superview subviews]); +#endif } bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) @@ -1153,6 +1259,9 @@ void wxCocoaTrackingRectManager::StopSynthesizingEvents() void wxCocoaTrackingRectManager::BuildTrackingRect() { + // Pool here due to lack of one during wx init phase + wxAutoNSAutoreleasePool pool; + wxASSERT_MSG(!m_isTrackingRectActive, wxT("Tracking rect was not cleared")); if([m_window->GetNSView() window] != nil) {