X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b8702c673a43e398df644670f4f343cb43df50d0..8a31648287be0ef976f133de2786b137f1e98340:/src/osx/cocoa/window.mm diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 26c705fcdd..3adaae15f4 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -1030,6 +1030,17 @@ void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd) { wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; superimpl(slf, (SEL)_cmd, event); + + // super of built-ins keeps the mouse up, as wx expects this event, we have to synthesize it + + if ( [ event type] == NSLeftMouseDown ) + { + wxMouseEvent wxevent(wxEVT_LEFT_DOWN); + SetupMouseEvent(wxevent , event) ; + wxevent.SetEventType(wxEVT_LEFT_UP); + + GetWXPeer()->HandleWindowEvent(wxevent); + } } } } @@ -1201,13 +1212,28 @@ void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *WXUNUSED(_cmd)) updateRgn.Offset( wxpeer->MacGetLeftBorderSize() , wxpeer->MacGetTopBorderSize() ); } - if ( wxpeer->MacGetTopLevelWindow()->GetWindowStyle() & wxFRAME_SHAPED ) + // Restrict the update region to the shape of the window, if any, and also + // remember the region that we need to clear later. + wxNonOwnedWindow* const tlwParent = wxpeer->MacGetTopLevelWindow(); + const bool isTopLevel = tlwParent == wxpeer; + wxRegion clearRgn; + if ( tlwParent->GetWindowStyle() & wxFRAME_SHAPED ) { + if ( isTopLevel ) + clearRgn = updateRgn; + int xoffset = 0, yoffset = 0; - wxRegion rgn = wxpeer->MacGetTopLevelWindow()->GetShape(); + wxRegion rgn = tlwParent->GetShape(); wxpeer->MacRootWindowToWindow( &xoffset, &yoffset ); rgn.Offset( xoffset, yoffset ); updateRgn.Intersect(rgn); + + if ( isTopLevel ) + { + // Exclude the window shape from the region to be cleared below. + rgn.Xor(wxpeer->GetSize()); + clearRgn.Intersect(rgn); + } } wxpeer->GetUpdateRegion() = updateRgn; @@ -1259,6 +1285,35 @@ void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *WXUNUSED(_cmd)) CGContextTranslateCTM( context, 0, [m_osxView bounds].size.height ); CGContextScaleCTM( context, 1, -1 ); } + + if ( isTopLevel ) + { + // We also need to explicitly draw the part of the top level window + // outside of its region with transparent colour to ensure that it is + // really transparent. + if ( clearRgn.IsOk() ) + { + wxMacCGContextStateSaver saveState(context); + wxWindowDC dc(wxpeer); + dc.SetBackground(wxBrush(wxTransparentColour)); + dc.SetDeviceClippingRegion(clearRgn); + dc.Clear(); + } + +#if wxUSE_GRAPHICS_CONTEXT + // If the window shape is defined by a path, stroke the path to show + // the window border. + const wxGraphicsPath& path = tlwParent->GetShapePath(); + if ( !path.IsNull() ) + { + CGContextSetLineWidth(context, 1); + CGContextSetStrokeColorWithColor(context, wxLIGHT_GREY->GetCGColor()); + CGContextAddPath(context, (CGPathRef) path.GetNativePath()); + CGContextStrokePath(context); + } +#endif // wxUSE_GRAPHICS_CONTEXT + } + wxpeer->MacPaintChildrenBorders(); wxpeer->MacSetCGContextRef( NULL ); CGContextRestoreGState( context ); @@ -1674,14 +1729,126 @@ bool wxWidgetCocoaImpl::ShowWithEffect(bool show, return ShowViewOrWindowWithEffect(m_wxPeer, show, effect, timeout); } +/* note that the drawing order between siblings is not defined under 10.4 */ +/* only starting from 10.5 the subview order is respected */ + +/* 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 + +class CocoaWindowCompareContext +{ + wxDECLARE_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 */; + + 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==compareContext->target()) + return NSOrderedDescending; + // second should be ordered higher + if(second==compareContext->target()) + return NSOrderedAscending; + return compareContext->CompareUsingOriginalOrdering(first,second); +} + void wxWidgetCocoaImpl::Raise() { - // Not implemented + NSView* nsview = m_osxView; + + NSView *superview = [nsview superview]; + CocoaWindowCompareContext compareContext(nsview, [superview subviews]); + + [superview sortSubviewsUsingFunction: + CocoaRaiseWindowCompareFunction + context: &compareContext]; + +} + +/* 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==compareContext->target()) + return NSOrderedAscending; + // second should be ordered lower + if(second==compareContext->target()) + return NSOrderedDescending; + return compareContext->CompareUsingOriginalOrdering(first,second); } void wxWidgetCocoaImpl::Lower() { - // Not implemented + NSView* nsview = m_osxView; + + NSView *superview = [nsview superview]; + CocoaWindowCompareContext compareContext(nsview, [superview subviews]); + + [superview sortSubviewsUsingFunction: + CocoaLowerWindowCompareFunction + context: &compareContext]; } void wxWidgetCocoaImpl::ScrollRect( const wxRect *WXUNUSED(rect), int WXUNUSED(dx), int WXUNUSED(dy) ) @@ -2132,6 +2299,18 @@ bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event) { wxKeyEvent wxevent(wxEVT_KEY_DOWN); SetupKeyEvent( wxevent, event ); + + // Generate wxEVT_CHAR_HOOK before sending any other events but only when + // the key is pressed, not when it's released (the type of wxevent is + // changed by SetupKeyEvent() so it can be wxEVT_KEY_UP too by now). + if ( wxevent.GetEventType() == wxEVT_KEY_DOWN ) + { + wxKeyEvent eventHook(wxEVT_CHAR_HOOK, wxevent); + if ( GetWXPeer()->OSXHandleKeyEvent(eventHook) + && !eventHook.IsNextEventAllowed() ) + return true; + } + bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent); // this will fire higher level events, like insertText, to help