/////////////////////////////////////////////////////////////////////////////
-// 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 ;
short wxApp::MacHandleAEQuit(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
{
- wxWindow* win = GetTopWindow() ;
- if ( win )
- {
- wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, s_macExitMenuItemId);
- if (!win->ProcessEvent(exitEvent))
- win->Close(true) ;
- }
- else
+ wxCloseEvent event;
+ wxTheApp->OnQueryEndSession(event);
+ if ( !event.GetVeto() )
{
- ExitMainLoop() ;
+ wxCloseEvent event;
+ wxTheApp->OnEndSession(event);
}
-
return noErr ;
}
// 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 = 0 ;
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 = (wxMenuItem*) refCon;
}
}
#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 :
DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler )
#endif
-#if defined( __WXDEBUG__ ) && wxOSX_USE_COCOA_OR_CARBON
+#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
pascal static void
wxMacAssertOutputHandler(OSType WXUNUSED(componentSignature),
#endif
}
-#endif //__WXDEBUG__
-
-extern "C" void macPostedEventCallback(void *WXUNUSED(unused))
-{
- wxTheApp->ProcessPendingEvents();
-}
+#endif // wxDEBUG_LEVEL
bool wxApp::Initialize(int& argc, wxChar **argv)
{
// Mac-specific
-#if defined( __WXDEBUG__ ) && wxOSX_USE_COCOA_OR_CARBON
+#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler ) );
#endif
// application (otherwise applications would need to handle it)
if ( argc > 1 )
{
- static const wxChar *ARG_PSN = _T("-psn_");
+ static const wxChar *ARG_PSN = wxT("-psn_");
if ( wxStrncmp(argv[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 )
{
// remove this argument
wxSetWorkingDirectory( cwd ) ;
}
- /* 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;
}
+#if wxOSX_USE_COCOA_OR_CARBON
+bool wxApp::CallOnInit()
+{
+ wxMacAutoreleasePool autoreleasepool;
+ return OnInit();
+}
+#endif
+
bool wxApp::OnInitGui()
{
if ( !wxAppBase::OnInitGui() )
return false ;
+
+ if ( !DoInitGui() )
+ return false;
+
+ return true ;
+}
+
+bool wxApp::ProcessIdle()
+{
+ wxMacAutoreleasePool autoreleasepool;
+ return wxAppBase::ProcessIdle();
+}
+
+int wxApp::OnRun()
+{
+ wxMacAutoreleasePool pool;
+ return wxAppBase::OnRun();
+}
+
#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()
+{
+ wxMacAutoreleasePool autoreleasepool;
+#if wxUSE_TOOLTIPS
+ wxToolTip::RemoveToolTips() ;
#endif
+ 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_macCurrentEvent = NULL ;
m_macCurrentEventHandlerCallRef = NULL ;
- m_macEventPosted = NULL ;
+ m_macPool = new wxMacAutoreleasePool();
+}
+
+wxApp::~wxApp()
+{
+ if (m_macPool)
+ delete m_macPool;
+}
+
+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::MacReleaseAutoreleasePool()
+{
+ if (m_macPool)
+ delete m_macPool;
+ m_macPool = new wxMacAutoreleasePool();
}
void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event))
// 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()
{
- if (m_macEventPosted)
- {
- CFRunLoopSourceSignal(m_macEventPosted);
- }
+ wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
- wxMacWakeUp() ;
+ if ( loop )
+ loop->WakeUp();
}
void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
// user can veto the close, and therefore the end session.
void wxApp::OnQueryEndSession(wxCloseEvent& event)
{
- if (GetTopWindow())
- {
- if (!GetTopWindow()->Close(!event.CanVeto()))
- event.Veto(true);
- }
-}
-
-extern "C" void wxCYield() ;
-void wxCYield()
-{
- wxYield() ;
-}
-
-// Yield to other processes
-
-bool wxApp::Yield(bool onlyIfNeeded)
-{
- if (s_inYield)
+ if ( !wxDialog::OSXHasModalDialogsOpen() )
{
- if ( !onlyIfNeeded )
+ if (GetTopWindow())
{
- wxFAIL_MSG( wxT("wxYield called recursively" ) );
+ if (!GetTopWindow()->Close(!event.CanVeto()))
+ event.Veto(true);
}
-
- 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.
- if ( !wxThread::IsMain() )
+ else
{
- return true;
+ event.Veto(true);
}
-#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 )
- {
- 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
- {
- MacHandleOneEvent( theEvent ) ;
- ReleaseEvent(theEvent);
- }
- }
-
-#else
-
-#endif
-
- s_inYield = false;
-
- return true;
}
-void wxApp::MacDoOneEvent()
+extern "C" void wxCYield() ;
+void wxCYield()
{
-#if wxOSX_USE_COCOA_OR_CARBON
- wxMacAutoreleasePool autoreleasepool;
- EventRef theEvent;
-
- s_inReceiveEvent = true ;
- OSStatus status = ReceiveNextEvent(0, NULL, sleepTime, true, &theEvent) ;
- s_inReceiveEvent = false ;
-
- switch (status)
- {
- case eventLoopTimedOutErr :
- if ( wxTheApp->ProcessIdle() )
- sleepTime = kEventDurationNoWait ;
- else
- {
- sleepTime = kEventDurationSecond;
-#if wxUSE_THREADS
- wxMutexGuiLeave();
- wxMilliSleep(20);
- wxMutexGuiEnter();
-#endif
- }
- break;
-
- case eventLoopQuitErr :
- // according to QA1061 this may also occur
- // when a WakeUp Process is executed
- break;
-
- default:
- MacHandleOneEvent( theEvent ) ;
- ReleaseEvent( theEvent );
- sleepTime = kEventDurationNoWait ;
- break;
- }
- // repeaters
-#else
-#endif
- DeletePendingObjects() ;
+ wxYield() ;
}
// 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);
-#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)
{
}
#endif
+#if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+
+// defined in utils.mm
+
+#elif wxOSX_USE_COCOA_OR_CARBON
+
wxMouseState wxGetMouseState()
{
wxMouseState ms;
-#if wxOSX_USE_COCOA_OR_CARBON
wxPoint pt = wxGetMousePosition();
ms.SetX(pt.x);
ms.SetAltDown(modifiers & optionKey);
ms.SetMetaDown(modifiers & cmdKey);
-#endif
return ms;
}
+#endif
+
// TODO : once the new key/char handling is tested, move all the code to wxWindow
bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
if ( !focus )
return false ;
- bool handled;
wxKeyEvent event(wxEVT_KEY_DOWN) ;
MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
- handled = focus->HandleWindowEvent( event ) ;
- if ( handled && event.GetSkipped() )
- handled = false ;
-
-#if wxUSE_ACCEL
- if ( !handled )
- {
- wxWindow *ancestor = focus;
- while (ancestor)
- {
- int command = ancestor->GetAcceleratorTable()->GetCommand( event );
- if (command != -1)
- {
- wxEvtHandler * const handler = ancestor->GetEventHandler();
-
- wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
- handled = handler->ProcessEvent( command_event );
-
- if ( !handled )
- {
- // accelerators can also be used with buttons, try them too
- command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
- handled = handler->ProcessEvent( command_event );
- }
-
- break;
- }
-
- if (ancestor->IsTopLevel())
- break;
-
- ancestor = ancestor->GetParent();
- }
- }
-#endif // wxUSE_ACCEL
-
- return handled ;
+ return focus->OSXHandleKeyEvent(event);
}
bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
if ( !focus )
return false ;
- bool handled;
wxKeyEvent event( wxEVT_KEY_UP ) ;
MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
- handled = focus->HandleWindowEvent( event ) ;
- return handled ;
+ return focus->OSXHandleKeyEvent(event) ;
}
bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
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);
// control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
// and look at the character after
#ifdef __LP64__
- // TODO new implementation using TextInputSources
+ // TODO new implementation using TextInputSources
#else
UInt32 state = 0;
UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey | shiftKey | optionKey))) | keycode, &state);
{
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;
event.m_y = wherey;
event.SetTimestamp(when);
event.SetEventObject(focus);
+#else
+ wxUnusedVar(event);
+ wxUnusedVar(focus);
+ wxUnusedVar(keymessage);
+ wxUnusedVar(modifiers);
+ wxUnusedVar(when);
+ wxUnusedVar(wherex);
+ wxUnusedVar(wherey);
+ wxUnusedVar(uniChar);
#endif
}
HICommand command;
memset( &command, 0 , sizeof(command) );
command.commandID = kHICommandHide ;
- event.SetParameter<HICommand>(kEventParamDirectObject, command );
+ event.SetParameter<HICommand>(kEventParamDirectObject, command );
SendEventToApplication( event );
#endif
}