]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/toplevel.cpp
don't call SelectObject() twice in SetBrush() nor SetFont() neither
[wxWidgets.git] / src / mac / carbon / toplevel.cpp
index a4b965bcbfa4b5eaa37995a9b4d0e9ce3cdc24ea..67a8669f690a21e8a597a9a466b6c2dbbc3653e1 100644 (file)
@@ -1,11 +1,11 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Name:        mac/toplevel.cpp
-// Purpose:     implements wxTopLevelWindow for MSW
-// Author:      Vadim Zeitlin
+// Purpose:     implements wxTopLevelWindow for Mac
+// Author:      Stefan Csomor
 // Modified by:
 // Created:     24.09.01
 // RCS-ID:      $Id$
-// Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
+// Copyright:   (c) 2001-2004 Stefan Csomor
 // License:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -42,6 +42,9 @@
 #include "wx/app.h"
 #include "wx/tooltip.h"
 #include "wx/dnd.h"
+#if wxUSE_SYSTEM_OPTIONS
+    #include "wx/sysopt.h"
+#endif
 
 #include "ToolUtils.h"
 
@@ -88,6 +91,7 @@ static const EventTypeSpec eventList[] =
     { kEventClassKeyboard, kEventRawKeyUp } ,
     { kEventClassKeyboard, kEventRawKeyModifiersChanged } ,
 
+    { kEventClassWindow , kEventWindowShown } ,
     { kEventClassWindow , kEventWindowUpdate } ,
     { kEventClassWindow , kEventWindowActivated } ,
     { kEventClassWindow , kEventWindowDeactivated } ,
@@ -97,6 +101,7 @@ static const EventTypeSpec eventList[] =
 
     { kEventClassMouse , kEventMouseDown } ,
     { kEventClassMouse , kEventMouseUp } ,
+    { kEventClassMouse , kEventMouseWheelMoved } ,
     { kEventClassMouse , kEventMouseMoved } ,
     { kEventClassMouse , kEventMouseDragged } ,
 
@@ -242,7 +247,7 @@ static pascal OSStatus KeyboardEventHandler( EventHandlerCallRef handler , Event
     return result ;
 }
 
-static pascal OSStatus MouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+pascal OSStatus MouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
 {
     OSStatus result = eventNotHandledErr ;
 
@@ -264,10 +269,18 @@ static pascal OSStatus MouseEventHandler( EventHandlerCallRef handler , EventRef
     if ( button == 0 || GetEventKind( event ) == kEventMouseUp )
         modifiers += btnState ;
 
+       // temporary hack to support true two button mouse
+       if ( button == kEventMouseButtonSecondary )
+       {
+               modifiers |= controlKey ;
+       }
     WindowRef window ;
     short windowPart = ::FindWindow(point, &window);
 
-    if ( IsWindowActive(window) && windowPart == inContent )
+    // either we really are active or we are capturing mouse events
+
+    if ( (IsWindowActive(window) && windowPart == inContent) || 
+        (wxTheApp->s_captureWindow && wxTheApp->s_captureWindow->MacGetTopLevelWindow() == toplevelWindow) )
     {
         switch ( GetEventKind( event ) )
         {
@@ -287,6 +300,39 @@ static pascal OSStatus MouseEventHandler( EventHandlerCallRef handler , EventRef
                 toplevelWindow->MacFireMouseEvent( nullEvent , point.h , point.v , modifiers , EventTimeToTicks( GetEventTime( event ) ) ) ;
                 result = noErr ;
                 break ;
+            case kEventMouseWheelMoved :
+                {
+                    //bClearTooltip = false;
+                    EventMouseWheelAxis axis = kEventMouseWheelAxisY;
+                    SInt32 delta = 0;
+                    Point mouseLoc = {0, 0};
+                    if (::GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis,
+                                        NULL, sizeof(EventMouseWheelAxis), NULL, &axis) == noErr &&
+                        ::GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger,
+                                        NULL, sizeof(SInt32), NULL, &delta) == noErr &&
+                        ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
+                                        NULL, sizeof(Point), NULL, &mouseLoc) == noErr)
+                    {
+                        wxMouseEvent wheelEvent(wxEVT_MOUSEWHEEL);
+                       
+                        wheelEvent.m_x = mouseLoc.h;
+                        wheelEvent.m_y = mouseLoc.v;
+                       
+                        wheelEvent.m_wheelRotation = delta;
+                        wheelEvent.m_wheelDelta = 1;
+                        wheelEvent.m_linesPerAction = 1;
+
+                        wxWindow* currentMouseWindow = NULL;
+                        wxWindow::MacGetWindowFromPoint(wxPoint(mouseLoc.h, mouseLoc.v), &currentMouseWindow);
+                       
+                        if (currentMouseWindow)
+                        {
+                            currentMouseWindow->GetEventHandler()->ProcessEvent(wheelEvent);
+                            result = noErr;
+                        }
+                    }
+                }
+                break ;
             default :
                 break ;
         }
@@ -323,6 +369,10 @@ static pascal OSStatus WindowEventHandler( EventHandlerCallRef handler , EventRe
                 toplevelWindow->MacActivate( EventTimeToTicks( GetEventTime( event ) ) , false) ;
             result = noErr ;
             break ;
+       case kEventWindowShown :
+               toplevelWindow->Refresh() ;
+               result = noErr ;
+               break ;
         case kEventWindowClose :
                 toplevelWindow->Close() ;
             result = noErr ;
@@ -421,6 +471,8 @@ DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
 wxList *wxWinMacWindowList = NULL;
 wxTopLevelWindowMac *wxFindWinFromMacWindow(WXWindow inWindowRef)
 {
+    if ( wxWinMacWindowList == NULL )
+        return NULL ;
     wxNode *node = wxWinMacWindowList->Find((long)inWindowRef);
     if (!node)
         return NULL;
@@ -449,6 +501,7 @@ void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win)
 
 WXHWND wxTopLevelWindowMac::s_macWindowInUpdate = NULL;
 wxTopLevelWindowMac *wxTopLevelWindowMac::s_macDeactivateWindow = NULL;
+bool wxTopLevelWindowMac::s_macWindowCompositing = FALSE;
 
 void wxTopLevelWindowMac::Init()
 {
@@ -457,6 +510,7 @@ void wxTopLevelWindowMac::Init()
     m_macNoEraseUpdateRgn = NewRgn() ;
     m_macNeedsErasing = false ;
     m_macWindow = NULL ;
+    m_macUsesCompositing = FALSE ;
 #if TARGET_CARBON
     m_macEventHandler = NULL ;
  #endif
@@ -533,6 +587,8 @@ wxTopLevelWindowMac::~wxTopLevelWindowMac()
 
 void wxTopLevelWindowMac::Maximize(bool maximize)
 {
+    wxMacPortStateHelper help( (GrafPtr) GetWindowPort( (WindowRef) m_macWindow) ) ;
+    wxMacWindowClipper clip (this);
     ZoomWindow( (WindowRef)m_macWindow , maximize ? inZoomOut : inZoomIn , false ) ;
 
     Rect tempRect ;
@@ -676,13 +732,34 @@ void  wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title,
         attr |= kWindowCloseBoxAttribute ;
     }
 
+    if (UMAGetSystemVersion() >= 0x1000)
+    {
+        //turn on live resizing (OS X only)
+        attr |= kWindowLiveResizeAttribute;
+    }
+
 #if TARGET_CARBON
 #if 0 //  having problems right now with that
     if (HasFlag(wxSTAY_ON_TOP))
-       wclass = kUtilityWindowClass;
+        wclass = kUtilityWindowClass;
 #endif
 #endif
 
+    //this setup lets us have compositing and non-compositing 
+    //windows in the same application. 
+  
+#if UNIVERSAL_INTERFACES_VERSION >= 0x0400  
+    if ( wxTopLevelWindowMac::s_macWindowCompositing )
+    {
+        attr |= kWindowCompositingAttribute;
+        m_macUsesCompositing = TRUE;
+    }
+    else
+#endif
+    {
+        m_macUsesCompositing = FALSE;
+    }
+    
 #if TARGET_CARBON
     if ( HasFlag(wxFRAME_SHAPED) )
     {
@@ -702,8 +779,15 @@ void  wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title,
 
     wxCHECK_RET( err == noErr, wxT("Mac OS error when trying to create new window") );
     wxAssociateWinWithMacWindow( m_macWindow , this ) ;
-    UMASetWTitle( (WindowRef)m_macWindow , title ) ;
-    ::CreateRootControl( (WindowRef)m_macWindow , (ControlHandle*)&m_macRootControl ) ;
+    UMASetWTitle( (WindowRef)m_macWindow , title , m_font.GetEncoding() ) ;
+    if ( wxTopLevelWindowMac::s_macWindowCompositing )
+    {
+        ::GetRootControl( (WindowRef)m_macWindow, (ControlHandle*)&m_macRootControl ) ;
+    }
+    else
+    {
+        ::CreateRootControl( (WindowRef)m_macWindow , (ControlHandle*)&m_macRootControl ) ;
+    }
 #if TARGET_CARBON
     InstallStandardEventHandler( GetWindowEventTarget(MAC_WXHWND(m_macWindow)) ) ;
     InstallWindowEventHandler(MAC_WXHWND(m_macWindow), GetwxMacWindowEventHandlerUPP(),
@@ -720,6 +804,16 @@ void  wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title,
         SetShape(rgn);
     }
 #endif
+
+    wxWindowCreateEvent event(this);
+    GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxTopLevelWindowMac::MacEnableCompositing( bool useCompositing )
+{
+    bool oldval = s_macWindowCompositing;
+    s_macWindowCompositing = useCompositing; 
+    return oldval; 
 }
 
 void wxTopLevelWindowMac::MacGetPortParams(WXPOINTPTR localOrigin, WXRECTPTR clipRect, WXHWND *window  , wxWindowMac** rootwin)
@@ -993,7 +1087,7 @@ void wxTopLevelWindowMac::MacKeyDown( WXEVENTREF ev )
 void wxTopLevelWindowMac::SetTitle(const wxString& title)
 {
     wxWindow::SetTitle( title ) ;
-    UMASetWTitle( (WindowRef)m_macWindow , title ) ;
+    UMASetWTitle( (WindowRef)m_macWindow , title , m_font.GetEncoding() ) ;
 }
 
 bool wxTopLevelWindowMac::Show(bool show)
@@ -1003,18 +1097,36 @@ bool wxTopLevelWindowMac::Show(bool show)
 
     if (show)
     {
-      ::TransitionWindow((WindowRef)m_macWindow,kWindowZoomTransitionEffect,kWindowShowTransitionAction,nil);
-      ::SelectWindow( (WindowRef)m_macWindow ) ;
-      // no need to generate events here, they will get them triggered by macos
-      // actually they should be , but apparently they are not
-      wxSize size(m_width, m_height);
-      wxSizeEvent event(size, m_windowId);
-      event.SetEventObject(this);
-      GetEventHandler()->ProcessEvent(event);
+        #if wxUSE_SYSTEM_OPTIONS       //code contributed by Ryan Wilcox December 18, 2003
+        if ( (wxSystemOptions::HasOption(wxMAC_WINDOW_PLAIN_TRANSITION) ) && ( wxSystemOptions::GetOptionInt( wxMAC_WINDOW_PLAIN_TRANSITION ) == 1) )
+        {
+           ::ShowWindow( (WindowRef)m_macWindow );
+        }
+        else
+        #endif
+        {
+           ::TransitionWindow((WindowRef)m_macWindow,kWindowZoomTransitionEffect,kWindowShowTransitionAction,nil);
+        }
+        ::SelectWindow( (WindowRef)m_macWindow ) ;
+        // no need to generate events here, they will get them triggered by macos
+        // actually they should be , but apparently they are not
+        wxSize size(m_width, m_height);
+        wxSizeEvent event(size, m_windowId);
+        event.SetEventObject(this);
+        GetEventHandler()->ProcessEvent(event);
     }
     else
     {
-      ::TransitionWindow((WindowRef)m_macWindow,kWindowZoomTransitionEffect,kWindowHideTransitionAction,nil);
+        #if wxUSE_SYSTEM_OPTIONS
+        if ( (wxSystemOptions::HasOption(wxMAC_WINDOW_PLAIN_TRANSITION) ) && ( wxSystemOptions::GetOptionInt( wxMAC_WINDOW_PLAIN_TRANSITION ) == 1) )
+        {
+           ::HideWindow((WindowRef) m_macWindow );
+        }
+        else
+        #endif
+        {
+           ::TransitionWindow((WindowRef)m_macWindow,kWindowZoomTransitionEffect,kWindowHideTransitionAction,nil);
+        }
     }
 
     if ( !show )
@@ -1030,6 +1142,9 @@ bool wxTopLevelWindowMac::Show(bool show)
 
 void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height)
 {
+    wxMacPortStateHelper help( (GrafPtr) GetWindowPort( (WindowRef) m_macWindow) ) ;
+    wxMacWindowClipper clip (this);
+
     int former_x = m_x ;
     int former_y = m_y ;
     int former_w = m_width ;
@@ -1065,27 +1180,32 @@ void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height)
     {
         m_x = actualX ;
         m_y = actualY ;
-        m_width = actualWidth ;
-        m_height = actualHeight ;
 
         if ( doMove )
             ::MoveWindow((WindowRef)m_macWindow, m_x, m_y  , false); // don't make frontmost
 
+        m_width = actualWidth ;
+        m_height = actualHeight ;
+
         if ( doResize )
             ::SizeWindow((WindowRef)m_macWindow, m_width, m_height  , true);
 
         // the OS takes care of invalidating and erasing the new area so we only have to
         // take care of refreshing for full repaints
 
-        if ( doResize && !HasFlag(wxNO_FULL_REPAINT_ON_RESIZE) )
+        if ( doResize && HasFlag(wxFULL_REPAINT_ON_RESIZE) )
             Refresh() ;
 
 
         if ( IsKindOf( CLASSINFO( wxFrame ) ) )
         {
             wxFrame* frame = (wxFrame*) this ;
+#if wxUSE_STATUSBAR
             frame->PositionStatusBar();
+#endif            
+#if wxUSE_TOOLBAR
             frame->PositionToolBar();
+#endif            
         }
         if ( doMove )
             wxWindowMac::MacTopLevelWindowChangedPosition() ; // like this only children will be notified