int intchar = [s characterAtIndex: 0];
if ( intchar >= NSF1FunctionKey && intchar <= NSF24FunctionKey )
retval = WXK_F1 + (intchar - NSF1FunctionKey );
+ else if ( intchar > 0 && intchar < 32 )
+ retval = intchar;
break;
}
}
{
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);
+ }
}
}
}
wxEvtHandler * const handler = m_wxPeer->GetEventHandler();
wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
+ command_event.SetEventObject( wxevent.GetEventObject() );
handled = handler->ProcessEvent( command_event );
if ( !handled )
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;
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 );
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) )
if ( !CanFocus() )
return false;
- [[m_osxView window] makeKeyAndOrderFront:nil] ;
+ // TODO remove if no issues arise: should not raise the window, only assign focus
+ //[[m_osxView window] makeKeyAndOrderFront:nil] ;
[[m_osxView window] makeFirstResponder: m_osxView] ;
return true;
}
{
if ( [m_osxView respondsToSelector:@selector(setImage:)] )
{
- [m_osxView setImage:bitmap.GetNSImage()];
+ if (bitmap.IsOk())
+ [m_osxView setImage:bitmap.GetNSImage()];
+ else
+ [m_osxView setImage:nil];
+
[m_osxView setNeedsDisplay:YES];
}
}
{
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