/////////////////////////////////////////////////////////////////////////////
-// Name: src/mac/carbon/app.cpp
+// Name: src/osx/carbon/app.cpp
// Purpose: wxApp
// Author: Stefan Csomor
// Modified by:
#include "wx/filename.h"
#include "wx/link.h"
#include "wx/thread.h"
+#include "wx/evtloop.h"
#include <string.h>
// Keep linker from discarding wxStockGDIMac
wxFORCE_LINK_MODULE(gdiobj)
-// statics for implementation
-static bool s_inYield = false;
-static bool s_inReceiveEvent = false ;
-#if wxOSX_USE_COCOA_OR_CARBON
-static EventTime sleepTime = kEventDurationNoWait ;
-#endif
-
IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
EVT_IDLE(wxApp::OnIdle)
bool wxApp::sm_isEmbedded = false; // Normally we're not a plugin
-#if wxOSX_USE_COCOA_OR_CARBON
+#if wxOSX_USE_CARBON
//----------------------------------------------------------------------
// Core Apple Event Support
if (err != noErr)
return err;
- url[actualSize] = '\0'; // Terminate the C string
+ url[actualSize] = '\0'; // Terminate the C string
ProcessSerialNumber PSN ;
PSN.highLongOfPSN = 0 ;
// make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow
if ( firstHidden == NULL && ( wxDynamicCast( win, wxFrame ) || wxDynamicCast( win, wxDialog ) ) )
firstHidden = win ;
- }
+ }
else if ( win->IsIconized() )
- {
+ {
if ( firstIconized == NULL )
firstIconized = win ;
}
// is it part of the application or the Help menu, then look for the id directly
if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) ||
- ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) ||
+ ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) ||
wxMenuBar::MacGetWindowMenuHMenu() != NULL && command.menu.menuRef == wxMenuBar::MacGetWindowMenuHMenu() )
{
wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
}
else
{
- URefCon refCon ;
+ URefCon refCon = NULL ;
GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ;
itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ;
- if ( itemMenu != NULL )
- item = (wxMenuItem*) refCon ;
+ if ( itemMenu != NULL && refCon != 0)
+ item = ((wxMenuItemImpl*) refCon)->GetWXPeer() ;
}
}
#endif
if ( menu )
{
- wxEventType type=0;
- MenuCommand cmd=0;
switch (GetEventKind(event))
{
case kEventMenuOpening:
- type = wxEVT_MENU_OPEN;
+ menu->HandleMenuOpened();
break;
case kEventMenuClosed:
- type = wxEVT_MENU_CLOSE;
+ menu->HandleMenuClosed();
break;
case kEventMenuTargetItem:
- cmd = cEvent.GetParameter<MenuCommand>(kEventParamMenuCommand,typeMenuCommand) ;
- if (cmd != 0)
- type = wxEVT_MENU_HIGHLIGHT;
+ {
+ HICommand command ;
+
+ command.menu.menuRef = menuRef;
+ command.menu.menuItemIndex = cEvent.GetParameter<MenuItemIndex>(kEventParamMenuItemIndex,typeMenuItemIndex) ;
+ command.commandID = cEvent.GetParameter<MenuCommand>(kEventParamMenuCommand,typeMenuCommand) ;
+ if (command.commandID != 0)
+ {
+ wxMenuItem* item = NULL ;
+ wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
+ if ( itemMenu && item )
+ itemMenu->HandleMenuItemHighlighted( item );
+ }
+ }
break;
default:
break;
}
- if ( type )
- {
- wxMenuEvent wxevent(type, cmd, menu);
- wxevent.SetEventObject(menu);
-
- wxEvtHandler* handler = menu->GetEventHandler();
- if (handler && handler->ProcessEvent(wxevent))
- {
- // handled
- }
- else
- {
- wxWindow *win = menu->GetInvokingWindow();
- if (win)
- win->HandleWindowEvent(wxevent);
- }
- }
}
#endif
return eventNotHandledErr;
wxMenuItem* item = NULL ;
wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
- int id = wxMacCommandToId( command.commandID ) ;
if ( item )
{
switch ( cEvent.GetKind() )
{
case kEventProcessCommand :
- result = itemMenu->MacHandleCommandProcess( item, id );
+ if ( itemMenu->HandleCommandProcess( item ) )
+ result = noErr;
break ;
case kEventCommandUpdateStatus:
- result = itemMenu->MacHandleCommandUpdateStatus( item, id );
+ if ( itemMenu->HandleCommandUpdateStatus( item ) )
+ result = noErr;
break ;
default :
/* connect posted events to common-mode run loop so that wxPostEvent events
are handled even while we're in the menu or on a scrollbar */
+ /*
CFRunLoopSourceContext event_posted_context = {0};
event_posted_context.perform = macPostedEventCallback;
m_macEventPosted = CFRunLoopSourceCreate(NULL,0,&event_posted_context);
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes);
// run loop takes ownership
CFRelease(m_macEventPosted);
-
+ */
return true;
}
+bool wxApp::CallOnInit()
+{
+ wxMacAutoreleasePool autoreleasepool;
+ return OnInit();
+}
+
bool wxApp::OnInitGui()
{
if ( !wxAppBase::OnInitGui() )
return false ;
+
+ if ( !DoInitGui() )
+ return false;
+
+ return true ;
+}
+
+bool wxApp::ProcessIdle()
+{
+ wxMacAutoreleasePool autoreleasepool;
+ return wxAppBase::ProcessIdle();
+}
+
#if wxOSX_USE_CARBON
+bool wxApp::DoInitGui()
+{
InstallStandardEventHandler( GetApplicationEventTarget() ) ;
if (!sm_isEmbedded)
{
GetwxMacAppEventHandlerUPP(),
GetEventTypeCount(eventList), eventList, wxTheApp, (EventHandlerRef *)&(wxTheApp->m_macEventHandler));
}
-#endif
-#if wxOSX_USE_COCOA_OR_CARBON
if (!sm_isEmbedded)
{
sODocHandler = NewAEEventHandlerUPP(AEHandleODoc) ;
AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
sQuitHandler , 0 , FALSE ) ;
}
-#endif
-#if wxOSX_USE_CARBON
+
if ( !wxMacInitCocoa() )
return false;
-#endif
- return true ;
+ return true;
}
-void wxApp::CleanUp()
+void wxApp::DoCleanUp()
{
-#if wxUSE_TOOLTIPS
- wxToolTip::RemoveToolTips() ;
-#endif
-
- if (m_macEventPosted)
- {
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes);
- m_macEventPosted = NULL;
- }
-
- // One last chance for pending objects to be cleaned up
- wxTheApp->DeletePendingObjects();
-
-#if wxOSX_USE_COCOA_OR_CARBON
-
if (!sm_isEmbedded)
RemoveEventHandler( (EventHandlerRef)(wxTheApp->m_macEventHandler) );
DisposeAEEventHandlerUPP( sRAppHandler ) ;
DisposeAEEventHandlerUPP( sQuitHandler ) ;
}
+}
#endif
+void wxApp::CleanUp()
+{
+#if wxUSE_TOOLTIPS
+ wxToolTip::RemoveToolTips() ;
+#endif
+
+ if (m_macEventPosted)
+ {
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes);
+ m_macEventPosted = NULL;
+ }
+
+ DoCleanUp();
+
wxAppBase::CleanUp();
}
// misc initialization stuff
//----------------------------------------------------------------------
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+#if wxOSX_USE_CARBON && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
bool wxMacConvertEventToRecord( EventRef event , EventRecord *rec)
{
OSStatus err = noErr ;
m_macEventPosted = NULL ;
}
+CFMutableArrayRef GetAutoReleaseArray()
+{
+ static CFMutableArrayRef array = 0;
+ if ( array == 0)
+ array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
+ return array;
+}
+
+void wxApp::MacAddToAutorelease( void* cfrefobj )
+{
+ CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj );
+}
+
void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event))
{
// If they are pending events, we must process them: pending events are
// either events to the threads other than main or events posted with
// wxPostEvent() functions
#ifndef __WXUNIVERSAL__
+#if wxUSE_MENUS
if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
#endif
+#endif
+ CFArrayRemoveAllValues( GetAutoReleaseArray() );
}
void wxApp::WakeUpIdle()
bool wxApp::Yield(bool onlyIfNeeded)
{
- if (s_inYield)
- {
- if ( !onlyIfNeeded )
- {
- wxFAIL_MSG( wxT("wxYield called recursively" ) );
- }
-
- return false;
- }
-
#if wxUSE_THREADS
// Yielding from a non-gui thread needs to bail out, otherwise we end up
// possibly sending events in the thread too.
}
#endif // wxUSE_THREADS
- s_inYield = true;
-
- // by definition yield should handle all non-processed events
-
-#if wxOSX_USE_COCOA_OR_CARBON
-
- EventRef theEvent;
-
- OSStatus status = noErr ;
-
- while ( status == noErr )
+ if (m_isInsideYield)
{
- s_inReceiveEvent = true ;
- status = ReceiveNextEvent(0, NULL,kEventDurationNoWait,true,&theEvent) ;
- s_inReceiveEvent = false ;
-
- if ( status == eventLoopTimedOutErr )
- {
- // make sure next time the event loop will trigger idle events
- sleepTime = kEventDurationNoWait ;
- }
- else if ( status == eventLoopQuitErr )
- {
- // according to QA1061 this may also occur when a WakeUp Process
- // is executed
- }
- else
+ if ( !onlyIfNeeded )
{
- MacHandleOneEvent( theEvent ) ;
- ReleaseEvent(theEvent);
+ wxFAIL_MSG( wxT("wxYield called recursively" ) );
}
- }
-
-#else
-#endif
-
- s_inYield = false;
-
- return true;
-}
+ return false;
+ }
-void wxApp::MacDoOneEvent()
-{
-#if wxOSX_USE_COCOA_OR_CARBON
- wxMacAutoreleasePool autoreleasepool;
- EventRef theEvent;
+ m_isInsideYield = true;
- s_inReceiveEvent = true ;
- OSStatus status = ReceiveNextEvent(0, NULL, sleepTime, true, &theEvent) ;
- s_inReceiveEvent = false ;
+#if wxUSE_LOG
+ // disable log flushing from here because a call to wxYield() shouldn't
+ // normally result in message boxes popping up &c
+ wxLog::Suspend();
+#endif // wxUSE_LOG
- switch (status)
+ wxEventLoop * const
+ loop = static_cast<wxEventLoop *>(wxEventLoop::GetActive());
+ if ( loop )
{
- case eventLoopTimedOutErr :
- if ( wxTheApp->ProcessIdle() )
- sleepTime = kEventDurationNoWait ;
- else
- sleepTime = kEventDurationSecond;
- break;
+ // process all pending events:
+ while ( loop->Pending() )
+ loop->Dispatch();
+ }
- case eventLoopQuitErr :
- // according to QA1061 this may also occur
- // when a WakeUp Process is executed
- break;
+ // it's necessary to call ProcessIdle() to update the frames sizes which
+ // might have been changed (it also will update other things set from
+ // OnUpdateUI() which is a nice (and desired) side effect)
+ while ( ProcessIdle() ) {}
- default:
- MacHandleOneEvent( theEvent ) ;
- ReleaseEvent( theEvent );
- sleepTime = kEventDurationNoWait ;
- break;
- }
- // repeaters
-#else
-#endif
- DeletePendingObjects() ;
+#if wxUSE_LOG
+ wxLog::Resume();
+#endif // wxUSE_LOG
+ m_isInsideYield = false;
+
+ return true;
}
// virtual
// Override to process unhandled events as you please
}
-CFMutableArrayRef GetAutoReleaseArray()
-{
- static CFMutableArrayRef array = 0;
- if ( array == 0)
- array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
- return array;
-}
-
-//
-//
-//
-
-
-//
-//
-//
-
-void wxApp::MacHandleOneEvent( WXEVENTREF evr )
-{
-#if wxOSX_USE_COCOA_OR_CARBON
- EventTargetRef theTarget;
- theTarget = GetEventDispatcherTarget();
- m_macCurrentEvent = evr ;
-
- OSStatus status = SendEventToEventTarget((EventRef) evr , theTarget);
- if (status == eventNotHandledErr)
- MacHandleUnhandledEvent(evr);
-
-#if wxUSE_THREADS
- wxMutexGuiLeaveOrEnter();
-#endif // wxUSE_THREADS
-
-#else
- // TODO Threads
-#endif
-
-
- CFArrayRemoveAllValues( GetAutoReleaseArray() );
-}
-
-void wxApp::MacAddToAutorelease( void* cfrefobj )
-{
- CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj );
-}
-
-#if wxOSX_USE_COCOA_OR_CARBON
+#if wxOSX_USE_CARBON
long wxMacTranslateKey(unsigned char key, unsigned char code)
{
wxMouseState wxGetMouseState()
{
wxMouseState ms;
-#if wxOSX_USE_COCOA_OR_CARBON
wxPoint pt = wxGetMousePosition();
ms.SetX(pt.x);
ms.SetY(pt.y);
+#if wxOSX_USE_CARBON
UInt32 buttons = GetCurrentButtonState();
ms.SetLeftDown( (buttons & 0x01) != 0 );
ms.SetMiddleDown( (buttons & 0x04) != 0 );
ms.SetShiftDown(modifiers & shiftKey);
ms.SetAltDown(modifiers & optionKey);
ms.SetMetaDown(modifiers & cmdKey);
-
+#else
+ // TODO
#endif
return ms;
}
return false ;
wxKeyEvent event(wxEVT_CHAR) ;
MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
- long keyval = event.m_keyCode ;
bool handled = false ;
#if wxOSX_USE_CARBON
+ long keyval = event.m_keyCode ;
wxNonOwnedWindow *tlw = focus->MacGetTopLevelWindow() ;
if (tlw)
// This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
{
-#if wxOSX_USE_COCOA_OR_CARBON
+#if wxOSX_USE_CARBON
short keycode, keychar ;
keychar = short(keymessage & charCodeMask);
{
keyval = (keyval - '0') + WXK_NUMPAD0;
}
- else if (keycode >= 65 && keycode <= 81)
+ else if (keycode >= 65 && keycode <= 81)
{
switch (keycode)
{
case 76 :
keyval = WXK_NUMPAD_ENTER;
break;
-
+
case 81:
keyval = WXK_NUMPAD_EQUAL;
break;
-
+
case 67:
keyval = WXK_NUMPAD_MULTIPLY;
break;
-
+
case 75:
keyval = WXK_NUMPAD_DIVIDE;
break;
-
+
case 78:
keyval = WXK_NUMPAD_SUBTRACT;
break;
-
+
case 69:
keyval = WXK_NUMPAD_ADD;
break;
-
+
case 65:
keyval = WXK_NUMPAD_DECIMAL;
break;
}
}
}
-
+
event.m_shiftDown = modifiers & shiftKey;
event.m_controlDown = modifiers & controlKey;
event.m_altDown = modifiers & optionKey;
HICommand command;
memset( &command, 0 , sizeof(command) );
command.commandID = kHICommandHide ;
- event.SetParameter<HICommand>(kEventParamDirectObject, command );
+ event.SetParameter<HICommand>(kEventParamDirectObject, command );
SendEventToApplication( event );
#endif
}