X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5f0b2f22d3cc98b9a9ba31908f7170b3590295eb..92629fa47bbb6d9a2d58b44c34edf3b02c6ad82c:/src/mac/toplevel.cpp diff --git a/src/mac/toplevel.cpp b/src/mac/toplevel.cpp index 32c34193ab..e074c7fb31 100644 --- a/src/mac/toplevel.cpp +++ b/src/mac/toplevel.cpp @@ -31,20 +31,37 @@ #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/toplevel.h" + #include "wx/frame.h" #include "wx/string.h" #include "wx/log.h" #include "wx/intl.h" #endif //WX_PRECOMP #include "wx/mac/uma.h" +#include "wx/mac/aga.h" +#include "wx/app.h" #include "wx/tooltip.h" +#include "wx/dnd.h" + +#define wxMAC_DEBUG_REDRAW 0 +#ifndef wxMAC_DEBUG_REDRAW +#define wxMAC_DEBUG_REDRAW 0 +#endif // ---------------------------------------------------------------------------- // globals // ---------------------------------------------------------------------------- // list of all frames and modeless dialogs -wxWindowList wxModelessWindows; +wxWindowList wxModelessWindows; + +// double click testing +static Point gs_lastWhere; +static long gs_lastWhen = 0; + +// cursor stuff +extern int wxBusyCursorCount; + // ============================================================================ // wxTopLevelWindowMac implementation @@ -57,7 +74,7 @@ wxWindowList wxModelessWindows; // Find an item given the Macintosh Window Reference wxList *wxWinMacWindowList = NULL; -wxTopLevelWindowMac *wxFindWinFromMacWindow(WindowRef inWindowRef) +wxTopLevelWindowMac *wxFindWinFromMacWindow(WXWindow inWindowRef) { wxNode *node = wxWinMacWindowList->Find((long)inWindowRef); if (!node) @@ -65,7 +82,7 @@ wxTopLevelWindowMac *wxFindWinFromMacWindow(WindowRef inWindowRef) return (wxTopLevelWindowMac *)node->Data(); } -void wxAssociateWinWithMacWindow(WindowRef inWindowRef, wxTopLevelWindowMac *win) +void wxAssociateWinWithMacWindow(WXWindow inWindowRef, wxTopLevelWindowMac *win) { // adding NULL WindowRef is (first) surely a result of an error and // (secondly) breaks menu command processing @@ -85,7 +102,7 @@ void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win) // wxTopLevelWindowMac creation // ---------------------------------------------------------------------------- -WindowRef wxTopLevelWindowMac::s_macWindowInUpdate = NULL; +WXHWND wxTopLevelWindowMac::s_macWindowInUpdate = NULL; void wxTopLevelWindowMac::Init() { @@ -93,8 +110,25 @@ void wxTopLevelWindowMac::Init() m_maximizeOnShow = FALSE; m_macNoEraseUpdateRgn = NewRgn() ; m_macNeedsErasing = false ; + m_macWindow = NULL ; + m_macEventHandler = NULL ; } +class wxMacDeferredWindowDeleter : public wxObject +{ +public : + wxMacDeferredWindowDeleter( WindowRef windowRef ) + { + m_macWindow = windowRef ; + } + virtual ~wxMacDeferredWindowDeleter() + { + UMADisposeWindow( (WindowRef) m_macWindow ) ; + } + protected : + WindowRef m_macWindow ; +} ; + bool wxTopLevelWindowMac::Create(wxWindow *parent, wxWindowID id, const wxString& title, @@ -122,27 +156,25 @@ bool wxTopLevelWindowMac::Create(wxWindow *parent, wxTopLevelWindowMac::~wxTopLevelWindowMac() { - wxToolTip::NotifyWindowDelete(m_macWindow) ; - UMADisposeWindow( m_macWindow ) ; - + if ( m_macWindow ) + { + wxToolTip::NotifyWindowDelete(m_macWindow) ; + wxPendingDelete.Append( new wxMacDeferredWindowDeleter( (WindowRef) m_macWindow ) ) ; + } + +#if TARGET_CARBON + if ( m_macEventHandler ) + { + ::RemoveEventHandler((EventHandlerRef) m_macEventHandler); + m_macEventHandler = NULL ; + } +#endif wxRemoveMacWindowAssociation( this ) ; - wxTopLevelWindows.DeleteObject(this); - if ( wxModelessWindows.Find(this) ) wxModelessWindows.DeleteObject(this); - // If this is the last top-level window, exit. - if ( wxTheApp && (wxTopLevelWindows.Number() == 0) ) - { - wxTheApp->SetTopWindow(NULL); - - if ( wxTheApp->GetExitOnFrameDelete() ) - { - wxTheApp->ExitMainLoop() ; - } - } - DisposeRgn( m_macNoEraseUpdateRgn ) ; + DisposeRgn( (RgnHandle) m_macNoEraseUpdateRgn ) ; } @@ -167,7 +199,7 @@ void wxTopLevelWindowMac::Iconize(bool iconize) bool wxTopLevelWindowMac::IsIconized() const { - // mac dialogs cannot be iconized + // mac dialogs cannot be iconized return FALSE; } @@ -186,6 +218,59 @@ void wxTopLevelWindowMac::SetIcon(const wxIcon& icon) wxTopLevelWindowBase::SetIcon(icon); } +#if TARGET_CARBON + +EventHandlerUPP wxMacWindowEventHandlerUPP = NULL ; + +extern long wxMacTranslateKey(unsigned char key, unsigned char code) ; + +pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) +{ + OSStatus result = eventNotHandledErr ; + EventRecord rec ; + switch ( GetEventClass( event ) ) + { + case kEventClassTextInput : + if ( wxMacConvertEventToRecord( event , &rec ) ) + { + wxTheApp->m_macCurrentEvent = &rec ; + wxWindow* focus = wxWindow::FindFocus() ; + if ( (focus != NULL) && !UMAMenuEvent(&rec) && wxTheApp->MacSendKeyDownEvent( focus , rec.message , rec.modifiers , rec.when , rec.where.h , rec.where.v ) ) + { + // was handled internally + result = noErr ; + } + } + break ; + default : + break ; + } + return result ; +} + +#endif + +void wxTopLevelWindowMac::MacInstallEventHandler() +{ +#if TARGET_CARBON + if ( wxMacWindowEventHandlerUPP == NULL ) + { + wxMacWindowEventHandlerUPP = NewEventHandlerUPP( wxMacWindowEventHandler ) ; + } + + static const EventTypeSpec eventList[] = + { + { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } + } ; + if ( m_macEventHandler ) + { + ::RemoveEventHandler((EventHandlerRef) m_macEventHandler); + m_macEventHandler = NULL ; + } + InstallWindowEventHandler(MAC_WXHWND(m_macWindow), wxMacWindowEventHandlerUPP, WXSIZEOF(eventList), eventList, this, &((EventHandlerRef)m_macEventHandler)); +#endif +} + void wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title, const wxPoint& pos, const wxSize& size, @@ -221,19 +306,34 @@ void wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title, WindowClass wclass = 0; WindowAttributes attr = kWindowNoAttributes ; - if ( HasFlag(wxTINY_CAPTION_HORIZ) || HasFlag(wxTINY_CAPTION_VERT) ) + if ( HasFlag( wxFRAME_TOOL_WINDOW) ) { - wclass = kFloatingWindowClass ; - if ( HasFlag(wxTINY_CAPTION_VERT) ) + if ( + HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) || + HasFlag( wxSYSTEM_MENU ) || HasFlag( wxCAPTION ) || + HasFlag(wxTINY_CAPTION_HORIZ) || HasFlag(wxTINY_CAPTION_VERT) + ) { - attr |= kWindowSideTitlebarAttribute ; + wclass = kFloatingWindowClass ; + if ( HasFlag(wxTINY_CAPTION_VERT) ) + { + attr |= kWindowSideTitlebarAttribute ; + } + } + else + { +#if TARGET_CARBON + wclass = kPlainWindowClass ; +#else + wclass = kFloatingWindowClass ; +#endif } } else if ( HasFlag( wxCAPTION ) ) { if ( HasFlag( wxDIALOG_MODAL ) ) { - wclass = kMovableModalWindowClass ; + wclass = kDocumentWindowClass ; // kMovableModalWindowClass ; } else { @@ -242,7 +342,19 @@ void wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title, } else { - wclass = kModalWindowClass ; + if ( HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) || + HasFlag( wxSYSTEM_MENU ) ) + { + wclass = kDocumentWindowClass ; + } + else + { +#if TARGET_CARBON + wclass = kPlainWindowClass ; +#else + wclass = kModalWindowClass ; +#endif + } } if ( HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) ) @@ -259,55 +371,38 @@ void wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title, attr |= kWindowCloseBoxAttribute ; } - ::CreateNewWindow( wclass , attr , &theBoundsRect , &m_macWindow ) ; + ::CreateNewWindow( wclass , attr , &theBoundsRect , (WindowRef*)&m_macWindow ) ; wxAssociateWinWithMacWindow( m_macWindow , this ) ; wxString label ; if( wxApp::s_macDefaultEncodingIsPC ) label = wxMacMakeMacStringFromPC( title ) ; else label = title ; - UMASetWTitleC( m_macWindow , label ) ; - ::CreateRootControl( m_macWindow , &m_macRootControl ) ; + UMASetWTitleC( (WindowRef)m_macWindow , label ) ; + ::CreateRootControl( (WindowRef)m_macWindow , (ControlHandle*)&m_macRootControl ) ; + MacInstallEventHandler() ; m_macFocus = NULL ; } -void wxTopLevelWindowMac::MacDoGetPortClientParams(Point* localOrigin, Rect* clipRect, WindowRef *window , wxWindowMac** rootwin ) +void wxTopLevelWindowMac::MacGetPortParams(WXPOINTPTR localOrigin, WXRECTPTR clipRect, WXHWND *window , wxWindowMac** rootwin) { - localOrigin->h = 0; - localOrigin->v = 0; - clipRect->left = 0; - clipRect->top = 0; - clipRect->right = m_width ;//width; - clipRect->bottom = m_height ;// height; - *window = m_macWindow ; - *rootwin = this ; -} - -void wxTopLevelWindowMac::MacGetPortParams(Point* localOrigin, Rect* clipRect, WindowRef *window , wxWindowMac** rootwin) -{ - localOrigin->h = 0; - localOrigin->v = 0; - clipRect->left = 0; - clipRect->top = 0; - clipRect->right = m_width; - clipRect->bottom = m_height; + ((Point*)localOrigin)->h = 0; + ((Point*)localOrigin)->v = 0; + ((Rect*)clipRect)->left = 0; + ((Rect*)clipRect)->top = 0; + ((Rect*)clipRect)->right = m_width; + ((Rect*)clipRect)->bottom = m_height; *window = m_macWindow ; *rootwin = this ; } void wxTopLevelWindowMac::Clear() { - wxMacDrawingClientHelper helper ( this ) ; - int w ,h ; - wxPoint origin = GetClientAreaOrigin() ; - GetClientSize( &w , &h ) ; - ::SetThemeWindowBackground( m_macWindow , m_macWindowBackgroundTheme , false ) ; - Rect r = { origin.y , origin.x, origin.y+h , origin.x+w } ; - EraseRect( &r ) ; + wxWindow::Clear() ; } -ControlHandle wxTopLevelWindowMac::MacGetContainerForEmbedding() +WXWidget wxTopLevelWindowMac::MacGetContainerForEmbedding() { return m_macRootControl ; } @@ -315,20 +410,17 @@ ControlHandle wxTopLevelWindowMac::MacGetContainerForEmbedding() void wxTopLevelWindowMac::MacUpdate( long timestamp) { - #if TARGET_CARBON - AGAPortHelper help( GetWindowPort(m_macWindow) ) ; - #else - AGAPortHelper help( (m_macWindow) ) ; - #endif - SetOrigin( 0 , 0 ) ; - BeginUpdate( m_macWindow ) ; + + wxMacPortStateHelper help( (GrafPtr) GetWindowPort( (WindowRef) m_macWindow) ) ; + + BeginUpdate( (WindowRef)m_macWindow ) ; RgnHandle updateRgn = NewRgn(); RgnHandle diffRgn = NewRgn() ; if ( updateRgn && diffRgn ) { - GetPortVisibleRegion( GetWindowPort( m_macWindow ), updateRgn ); - DiffRgn( updateRgn , m_macNoEraseUpdateRgn , diffRgn ) ; + GetPortVisibleRegion( GetWindowPort( (WindowRef)m_macWindow ), updateRgn ); + DiffRgn( updateRgn , (RgnHandle) m_macNoEraseUpdateRgn , diffRgn ) ; if ( !EmptyRgn( updateRgn ) ) { MacRedraw( updateRgn , timestamp , m_macNeedsErasing || !EmptyRgn( diffRgn ) ) ; @@ -338,8 +430,8 @@ void wxTopLevelWindowMac::MacUpdate( long timestamp) DisposeRgn( updateRgn ); if ( diffRgn ) DisposeRgn( diffRgn ); - EndUpdate( m_macWindow ) ; - SetEmptyRgn( m_macNoEraseUpdateRgn ) ; + EndUpdate( (WindowRef)m_macWindow ) ; + SetEmptyRgn( (RgnHandle) m_macNoEraseUpdateRgn ) ; m_macNeedsErasing = false ; } @@ -347,21 +439,18 @@ void wxTopLevelWindowMac::MacUpdate( long timestamp) // Raise the window to the top of the Z order void wxTopLevelWindowMac::Raise() { - ::BringToFront( m_macWindow ) ; + ::BringToFront( (WindowRef)m_macWindow ) ; } // Lower the window to the bottom of the Z order void wxTopLevelWindowMac::Lower() { - ::SendBehind( m_macWindow , NULL ) ; + ::SendBehind( (WindowRef)m_macWindow , NULL ) ; } -Point lastWhere ; -long lastWhen = 0 ; -extern int wxBusyCursorCount ; - -void wxTopLevelWindowMac::MacFireMouseEvent( EventRecord *ev ) +void wxTopLevelWindowMac::MacFireMouseEvent( WXEVENTREF evr ) { + EventRecord *ev = (EventRecord*) evr ; wxMouseEvent event(wxEVT_LEFT_DOWN); bool isDown = !(ev->modifiers & btnState) ; // 1 is for up bool controlDown = ev->modifiers & controlKey ; // for simulating right mouse @@ -399,28 +488,31 @@ void wxTopLevelWindowMac::MacFireMouseEvent( EventRecord *ev ) GrafPtr port ; ::GetPort( &port ) ; - ::SetPort( UMAGetWindowPort( m_macWindow ) ) ; + ::SetPort( UMAGetWindowPort( (WindowRef)m_macWindow ) ) ; ::GlobalToLocal( &localwhere ) ; ::SetPort( port ) ; if ( ev->what == mouseDown ) { - if ( ev->when - lastWhen <= GetDblTime() ) + if ( ev->when - gs_lastWhen <= GetDblTime() ) { - if ( abs( localwhere.h - lastWhere.h ) < 3 || abs( localwhere.v - lastWhere.v ) < 3 ) + if ( abs( localwhere.h - gs_lastWhere.h ) < 3 && abs( localwhere.v - gs_lastWhere.v ) < 3 ) { + // This is not right if the second mouse down + // event occured in a differen window. We + // correct this in MacDispatchMouseEvent. if ( controlDown ) event.SetEventType(wxEVT_RIGHT_DCLICK ) ; else event.SetEventType(wxEVT_LEFT_DCLICK ) ; } - lastWhen = 0 ; + gs_lastWhen = 0 ; } else { - lastWhen = ev->when ; + gs_lastWhen = ev->when ; } - lastWhere = localwhere ; + gs_lastWhere = localwhere ; } event.m_x = localwhere.h; @@ -428,13 +520,6 @@ void wxTopLevelWindowMac::MacFireMouseEvent( EventRecord *ev ) event.m_x += m_x; event.m_y += m_y; -/* - wxPoint origin = GetClientAreaOrigin() ; - - event.m_x += origin.x ; - event.m_y += origin.y ; -*/ - event.m_timeStamp = ev->when; event.SetEventObject(this); if ( wxTheApp->s_captureWindow ) @@ -444,7 +529,9 @@ void wxTopLevelWindowMac::MacFireMouseEvent( EventRecord *ev ) wxTheApp->s_captureWindow->ScreenToClient( &x , &y ) ; event.m_x = x ; event.m_y = y ; + event.SetEventObject( wxTheApp->s_captureWindow ) ; wxTheApp->s_captureWindow->GetEventHandler()->ProcessEvent( event ) ; + if ( ev->what == mouseUp ) { wxTheApp->s_captureWindow = NULL ; @@ -460,12 +547,12 @@ void wxTopLevelWindowMac::MacFireMouseEvent( EventRecord *ev ) } } -void wxTopLevelWindowMac::MacMouseDown( EventRecord *ev , short part) +void wxTopLevelWindowMac::MacMouseDown( WXEVENTREF ev , short part) { MacFireMouseEvent( ev ) ; } -void wxTopLevelWindowMac::MacMouseUp( EventRecord *ev , short part) +void wxTopLevelWindowMac::MacMouseUp( WXEVENTREF ev , short part) { switch (part) { @@ -477,7 +564,7 @@ void wxTopLevelWindowMac::MacMouseUp( EventRecord *ev , short part) } } -void wxTopLevelWindowMac::MacMouseMoved( EventRecord *ev , short part) +void wxTopLevelWindowMac::MacMouseMoved( WXEVENTREF ev , short part) { switch (part) { @@ -488,22 +575,20 @@ void wxTopLevelWindowMac::MacMouseMoved( EventRecord *ev , short part) break ; } } -void wxTopLevelWindowMac::MacActivate( EventRecord *ev , bool inIsActivating ) +void wxTopLevelWindowMac::MacActivate( WXEVENTREF ev , bool inIsActivating ) { wxActivateEvent event(wxEVT_ACTIVATE, inIsActivating , m_windowId); - event.m_timeStamp = ev->when ; + event.m_timeStamp = ((EventRecord*)ev)->when ; event.SetEventObject(this); GetEventHandler()->ProcessEvent(event); - UMAHighlightAndActivateWindow( m_macWindow , inIsActivating ) ; + UMAHighlightAndActivateWindow( (WindowRef)m_macWindow , inIsActivating ) ; - Refresh( FALSE ) ; -// MacSuperEnabled( inIsActivating ) ; -// MacUpdateImmediately() ; + MacSuperEnabled( inIsActivating ) ; } -void wxTopLevelWindowMac::MacKeyDown( EventRecord *ev ) +void wxTopLevelWindowMac::MacKeyDown( WXEVENTREF ev ) { } @@ -518,7 +603,7 @@ void wxTopLevelWindowMac::SetTitle(const wxString& title) else label = m_label ; - UMASetWTitleC( m_macWindow , label ) ; + UMASetWTitleC( (WindowRef)m_macWindow , label ) ; } bool wxTopLevelWindowMac::Show(bool show) @@ -527,9 +612,9 @@ bool wxTopLevelWindowMac::Show(bool show) return FALSE; if (show) - { - ::ShowWindow( m_macWindow ) ; - ::SelectWindow( m_macWindow ) ; + { + ::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); @@ -539,7 +624,7 @@ bool wxTopLevelWindowMac::Show(bool show) } else { - ::HideWindow( m_macWindow ) ; + ::TransitionWindow((WindowRef)m_macWindow,kWindowZoomTransitionEffect,kWindowHideTransitionAction,nil); } if ( !show ) @@ -594,13 +679,17 @@ void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height) m_height = actualHeight ; if ( doMove ) - ::MoveWindow(m_macWindow, m_x, m_y , false); // don't make frontmost + ::MoveWindow((WindowRef)m_macWindow, m_x, m_y , false); // don't make frontmost if ( doResize ) - ::SizeWindow(m_macWindow, m_width, m_height , true); + ::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) ) + Refresh() ; - // the OS takes care of invalidating and erasing the new area - // we have erased the old one if ( IsKindOf( CLASSINFO( wxFrame ) ) ) { @@ -645,11 +734,11 @@ void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height) * will get the eraseBackground event first */ -void wxTopLevelWindowMac::MacInvalidate( const Rect * rect, bool eraseBackground ) +void wxTopLevelWindowMac::MacInvalidate( const WXRECTPTR rect, bool eraseBackground ) { GrafPtr formerPort ; GetPort( &formerPort ) ; - SetPortWindowPort( m_macWindow ) ; + SetPortWindowPort( (WindowRef)m_macWindow ) ; m_macNeedsErasing |= eraseBackground ; @@ -664,11 +753,11 @@ void wxTopLevelWindowMac::MacInvalidate( const Rect * rect, bool eraseBackground RgnHandle diffRgn = NewRgn() ; if ( updateRgn && diffRgn ) { - GetWindowUpdateRgn( m_macWindow , updateRgn ); + GetWindowUpdateRgn( (WindowRef)m_macWindow , updateRgn ); Point pt = {0,0} ; LocalToGlobal( &pt ) ; OffsetRgn( updateRgn , -pt.h , -pt.v ) ; - DiffRgn( updateRgn , m_macNoEraseUpdateRgn , diffRgn ) ; + DiffRgn( updateRgn , (RgnHandle) m_macNoEraseUpdateRgn , diffRgn ) ; if ( !EmptyRgn( diffRgn ) ) { m_macNeedsErasing = true ; @@ -682,15 +771,16 @@ void wxTopLevelWindowMac::MacInvalidate( const Rect * rect, bool eraseBackground if ( !m_macNeedsErasing ) { RgnHandle rectRgn = NewRgn() ; - SetRectRgn( rectRgn , rect->left , rect->top , rect->right , rect->bottom ) ; - UnionRgn( m_macNoEraseUpdateRgn , rectRgn , m_macNoEraseUpdateRgn ) ; + SetRectRgn( rectRgn , ((Rect*)rect)->left , ((Rect*)rect)->top , ((Rect*)rect)->right , ((Rect*)rect)->bottom ) ; + UnionRgn( (RgnHandle) m_macNoEraseUpdateRgn , rectRgn , (RgnHandle) m_macNoEraseUpdateRgn ) ; DisposeRgn( rectRgn ) ; } } - InvalWindowRect( m_macWindow , rect ) ; + InvalWindowRect( (WindowRef)m_macWindow , (Rect*)rect ) ; // turn this on to debug the refreshing cycle -#if 0 +#if wxMAC_DEBUG_REDRAW PaintRect( rect ) ; #endif SetPort( formerPort ) ; } +