wxOSX's wxApp::MacReopenApp() previously contained logic to unhide hidden windows, but this code was commended out since 2013 as problematic - it was showing windows like closed, but not yet destroyed, non-modal dialogs. Unfortunately while this part was commented out, the rest of the code that handled existence of hidden windows was not, resulting in a bug where nothing happened after clicking app icon in the Dock if the application didn't have any visible window at the moment, but had a "technical" hidden one, e.g. after opening and closing wxPreferencesEditor. Fixed by simplyfing and removing all (functionally commented-out) code related to hidden windows. Instead, the logic is now: 1. do nothing if some window is already visible 2. restore an iconized window if there's one 3. call MacNewFile() if neither happened
908 lines
26 KiB
C++
908 lines
26 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/osx/carbon/app.cpp
|
|
// Purpose: wxApp
|
|
// Author: Stefan Csomor
|
|
// Modified by:
|
|
// Created: 1998-01-01
|
|
// Copyright: (c) Stefan Csomor
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
#include "wx/app.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/intl.h"
|
|
#include "wx/log.h"
|
|
#include "wx/utils.h"
|
|
#include "wx/window.h"
|
|
#include "wx/frame.h"
|
|
#include "wx/dc.h"
|
|
#include "wx/button.h"
|
|
#include "wx/menu.h"
|
|
#include "wx/pen.h"
|
|
#include "wx/brush.h"
|
|
#include "wx/palette.h"
|
|
#include "wx/icon.h"
|
|
#include "wx/cursor.h"
|
|
#include "wx/dialog.h"
|
|
#include "wx/msgdlg.h"
|
|
#include "wx/textctrl.h"
|
|
#include "wx/memory.h"
|
|
#include "wx/gdicmn.h"
|
|
#include "wx/module.h"
|
|
#endif
|
|
|
|
#include "wx/tooltip.h"
|
|
#include "wx/docview.h"
|
|
#include "wx/filename.h"
|
|
#include "wx/link.h"
|
|
#include "wx/thread.h"
|
|
#include "wx/evtloop.h"
|
|
|
|
#include <string.h>
|
|
|
|
// mac
|
|
#include "wx/osx/private.h"
|
|
|
|
#if defined(WXMAKINGDLL_CORE)
|
|
# include <mach-o/dyld.h>
|
|
#endif
|
|
|
|
// Keep linker from discarding wxStockGDIMac
|
|
wxFORCE_LINK_MODULE(gdiobj)
|
|
|
|
wxIMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler);
|
|
wxBEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
|
|
EVT_IDLE(wxApp::OnIdle)
|
|
EVT_END_SESSION(wxApp::OnEndSession)
|
|
EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
|
|
wxEND_EVENT_TABLE()
|
|
|
|
|
|
wxWindow* wxApp::s_captureWindow = NULL ;
|
|
long wxApp::s_lastModifiers = 0 ;
|
|
|
|
long wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
|
|
long wxApp::s_macPreferencesMenuItemId = wxID_PREFERENCES ;
|
|
long wxApp::s_macExitMenuItemId = wxID_EXIT ;
|
|
wxString wxApp::s_macHelpMenuTitleName = wxT("&Help") ;
|
|
wxString wxApp::s_macWindowMenuTitleName = wxT("&Window") ;
|
|
|
|
bool wxApp::sm_isEmbedded = false; // Normally we're not a plugin
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// Support Routines linking the Mac...File Calls to the Document Manager
|
|
//----------------------------------------------------------------------
|
|
|
|
void wxApp::MacOpenFiles(const wxArrayString & fileNames )
|
|
{
|
|
size_t i;
|
|
const size_t fileCount = fileNames.GetCount();
|
|
for (i = 0; i < fileCount; i++)
|
|
{
|
|
MacOpenFile(fileNames[i]);
|
|
}
|
|
}
|
|
|
|
void wxApp::MacOpenFile(const wxString & fileName )
|
|
{
|
|
#if wxUSE_DOC_VIEW_ARCHITECTURE
|
|
wxDocManager* dm = wxDocManager::GetDocumentManager() ;
|
|
if ( dm )
|
|
dm->CreateDocument(fileName , wxDOC_SILENT ) ;
|
|
#endif
|
|
}
|
|
|
|
void wxApp::MacOpenURL(const wxString & WXUNUSED(url) )
|
|
{
|
|
}
|
|
|
|
void wxApp::MacPrintFiles(const wxArrayString & fileNames )
|
|
{
|
|
size_t i;
|
|
const size_t fileCount = fileNames.GetCount();
|
|
for (i = 0; i < fileCount; i++)
|
|
{
|
|
MacPrintFile(fileNames[i]);
|
|
}
|
|
}
|
|
|
|
void wxApp::MacPrintFile(const wxString & fileName )
|
|
{
|
|
#if wxUSE_DOC_VIEW_ARCHITECTURE
|
|
|
|
#if wxUSE_PRINTING_ARCHITECTURE
|
|
wxDocManager* dm = wxDocManager::GetDocumentManager() ;
|
|
if ( dm )
|
|
{
|
|
wxDocument *doc = dm->CreateDocument(fileName , wxDOC_SILENT ) ;
|
|
if ( doc )
|
|
{
|
|
wxView* view = doc->GetFirstView() ;
|
|
if ( view )
|
|
{
|
|
wxPrintout *printout = view->OnCreatePrintout();
|
|
if (printout)
|
|
{
|
|
wxPrinter printer;
|
|
printer.Print(view->GetFrame(), printout, true);
|
|
delete printout;
|
|
}
|
|
}
|
|
|
|
if (doc->Close())
|
|
{
|
|
doc->DeleteAllViews();
|
|
dm->RemoveDocument(doc) ;
|
|
}
|
|
}
|
|
}
|
|
#endif //print
|
|
|
|
#endif //docview
|
|
}
|
|
|
|
|
|
|
|
void wxApp::MacNewFile()
|
|
{
|
|
}
|
|
|
|
void wxApp::MacReopenApp()
|
|
{
|
|
// HIG says :
|
|
// if there is no open window -> create a new one
|
|
// if all windows are hidden -> show the first
|
|
// if some windows are not hidden -> do nothing
|
|
//
|
|
// Showing hidden windows is not really always a good solution, also non-modal dialogs when closed end up
|
|
// as hidden TLWs, so do preferences and some classes like wxTaskBarIconWindow use placeholder TLWs.
|
|
// We don't want to reshow those, so let's just reopen the minimized a.k.a. iconized TLWs.
|
|
|
|
wxTopLevelWindow* firstIconized = NULL;
|
|
wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
|
|
|
|
while (node)
|
|
{
|
|
wxTopLevelWindow* win = (wxTopLevelWindow*) node->GetData();
|
|
if ( win->IsShown() )
|
|
{
|
|
// we do have a visible, non-iconized toplevelwindow -> do nothing
|
|
return;
|
|
}
|
|
else if ( win->IsIconized() )
|
|
{
|
|
if ( firstIconized == NULL )
|
|
firstIconized = win;
|
|
}
|
|
|
|
node = node->GetNext();
|
|
}
|
|
|
|
if ( firstIconized )
|
|
{
|
|
firstIconized->Iconize(false);
|
|
return;
|
|
}
|
|
|
|
// no window was shown, we need to create a new one
|
|
MacNewFile();
|
|
}
|
|
|
|
#if wxOSX_USE_COCOA_OR_IPHONE
|
|
void wxApp::OSXOnWillFinishLaunching()
|
|
{
|
|
}
|
|
|
|
void wxApp::OSXOnDidFinishLaunching()
|
|
{
|
|
// on cocoa we cannot do this, as it would arrive "AFTER" an OpenFiles event
|
|
#if wxOSX_USE_IPHONE
|
|
wxTheApp->OnInit();
|
|
#endif
|
|
}
|
|
|
|
void wxApp::OSXOnWillTerminate()
|
|
{
|
|
wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY);
|
|
event.SetEventObject(this);
|
|
event.SetCanVeto(false);
|
|
ProcessEvent(event);
|
|
}
|
|
|
|
bool wxApp::OSXOnShouldTerminate()
|
|
{
|
|
wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY);
|
|
event.SetEventObject(this);
|
|
event.SetCanVeto(true);
|
|
ProcessEvent(event);
|
|
return !event.GetVeto();
|
|
}
|
|
#endif
|
|
|
|
#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
|
|
|
|
pascal static void
|
|
wxMacAssertOutputHandler(OSType WXUNUSED(componentSignature),
|
|
UInt32 WXUNUSED(options),
|
|
const char *assertionString,
|
|
const char *exceptionLabelString,
|
|
const char *errorString,
|
|
const char *fileName,
|
|
long lineNumber,
|
|
void *value,
|
|
ConstStr255Param WXUNUSED(outputMsg))
|
|
{
|
|
// flow into assert handling
|
|
wxString fileNameStr ;
|
|
wxString assertionStr ;
|
|
wxString exceptionStr ;
|
|
wxString errorStr ;
|
|
|
|
#if wxUSE_UNICODE
|
|
fileNameStr = wxString(fileName, wxConvLocal);
|
|
assertionStr = wxString(assertionString, wxConvLocal);
|
|
exceptionStr = wxString((exceptionLabelString!=0) ? exceptionLabelString : "", wxConvLocal) ;
|
|
errorStr = wxString((errorString!=0) ? errorString : "", wxConvLocal) ;
|
|
#else
|
|
fileNameStr = fileName;
|
|
assertionStr = assertionString;
|
|
exceptionStr = (exceptionLabelString!=0) ? exceptionLabelString : "" ;
|
|
errorStr = (errorString!=0) ? errorString : "" ;
|
|
#endif
|
|
|
|
#if 1
|
|
// flow into log
|
|
wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
|
|
assertionStr.c_str() ,
|
|
exceptionStr.c_str() ,
|
|
errorStr.c_str(),
|
|
fileNameStr.c_str(), lineNumber ,
|
|
value ) ;
|
|
#else
|
|
|
|
wxOnAssert(fileNameStr, lineNumber , assertionStr ,
|
|
wxString::Format( wxT("%s %s value (%p)") , exceptionStr, errorStr , value ) ) ;
|
|
#endif
|
|
}
|
|
|
|
#endif // wxDEBUG_LEVEL
|
|
|
|
bool wxApp::Initialize(int& argc, wxChar **argv)
|
|
{
|
|
// Mac-specific
|
|
|
|
#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
|
|
InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler ) );
|
|
#endif
|
|
|
|
/*
|
|
Cocoa supports -Key value options which set the user defaults key "Key"
|
|
to the value "value" Some of them are very handy for debugging like
|
|
-NSShowAllViews YES. Cocoa picks these up from the real argv so
|
|
our removal of them from the wx copy of it does not affect Cocoa's
|
|
ability to see them.
|
|
|
|
We basically just assume that any "-NS" option and its following
|
|
argument needs to be removed from argv. We hope that user code does
|
|
not expect to see -NS options and indeed it's probably a safe bet
|
|
since most user code accepting options is probably using the
|
|
double-dash GNU-style syntax.
|
|
*/
|
|
for(int i=1; i < argc; ++i)
|
|
{
|
|
static const wxChar *ARG_NS = wxT("-NS");
|
|
if( wxStrncmp(argv[i], ARG_NS, wxStrlen(ARG_NS)) == 0 )
|
|
{
|
|
// Only eat this option if it has an argument
|
|
if( (i + 1) < argc )
|
|
{
|
|
memmove(argv + i, argv + i + 2, (argc-i-1)*sizeof(wxChar*));
|
|
argc -= 2;
|
|
// drop back one position so the next run through the loop
|
|
// reprocesses the argument at our current index.
|
|
--i;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !wxAppBase::Initialize(argc, argv) )
|
|
return false;
|
|
|
|
#if wxUSE_INTL
|
|
wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
|
|
#endif
|
|
|
|
// these might be the startup dirs, set them to the 'usual' dir containing the app bundle
|
|
wxString startupCwd = wxGetCwd() ;
|
|
if ( startupCwd == wxT("/") || startupCwd.Right(15) == wxT("/Contents/MacOS") )
|
|
{
|
|
CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
|
|
CFURLRef urlParent = CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault , url ) ;
|
|
CFRelease( url ) ;
|
|
CFStringRef path = CFURLCopyFileSystemPath ( urlParent , kCFURLPOSIXPathStyle ) ;
|
|
CFRelease( urlParent ) ;
|
|
wxString cwd = wxCFStringRef(path).AsString(wxLocale::GetSystemEncoding());
|
|
wxSetWorkingDirectory( cwd ) ;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void wxApp::CleanUp()
|
|
{
|
|
wxMacAutoreleasePool autoreleasepool;
|
|
#if wxUSE_TOOLTIPS
|
|
wxToolTip::RemoveToolTips() ;
|
|
#endif
|
|
|
|
DoCleanUp();
|
|
|
|
wxAppBase::CleanUp();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// misc initialization stuff
|
|
//----------------------------------------------------------------------
|
|
|
|
wxApp::wxApp()
|
|
{
|
|
m_printMode = wxPRINT_WINDOWS;
|
|
|
|
m_macCurrentEvent = NULL ;
|
|
m_macCurrentEventHandlerCallRef = 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))
|
|
{
|
|
// 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()
|
|
{
|
|
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
|
|
|
if ( loop )
|
|
loop->WakeUp();
|
|
}
|
|
|
|
void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
|
|
{
|
|
if (GetTopWindow())
|
|
GetTopWindow()->Close(true);
|
|
}
|
|
|
|
// Default behaviour: close the application with prompts. The
|
|
// user can veto the close, and therefore the end session.
|
|
void wxApp::OnQueryEndSession(wxCloseEvent& event)
|
|
{
|
|
if ( !wxDialog::OSXHasModalDialogsOpen() )
|
|
{
|
|
if (GetTopWindow())
|
|
{
|
|
if (!GetTopWindow()->Close(!event.CanVeto()))
|
|
event.Veto(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
event.Veto(true);
|
|
}
|
|
}
|
|
|
|
extern "C" void wxCYield() ;
|
|
void wxCYield()
|
|
{
|
|
wxYield() ;
|
|
}
|
|
|
|
// virtual
|
|
void wxApp::MacHandleUnhandledEvent( WXEVENTREF WXUNUSED(evr) )
|
|
{
|
|
// Override to process unhandled events as you please
|
|
}
|
|
|
|
#if wxOSX_USE_COCOA_OR_CARBON
|
|
|
|
CGKeyCode wxCharCodeWXToOSX(wxKeyCode code)
|
|
{
|
|
CGKeyCode keycode;
|
|
|
|
switch (code)
|
|
{
|
|
// Clang warns about switch values not of the same type as (enumerated)
|
|
// switch controlling expression. This is generally useful but here we
|
|
// really want to be able to use letters and digits without making them
|
|
// part of wxKeyCode enum.
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wswitch"
|
|
#endif // __clang__
|
|
|
|
case 'a': case 'A': keycode = kVK_ANSI_A; break;
|
|
case 'b': case 'B': keycode = kVK_ANSI_B; break;
|
|
case 'c': case 'C': keycode = kVK_ANSI_C; break;
|
|
case 'd': case 'D': keycode = kVK_ANSI_D; break;
|
|
case 'e': case 'E': keycode = kVK_ANSI_E; break;
|
|
case 'f': case 'F': keycode = kVK_ANSI_F; break;
|
|
case 'g': case 'G': keycode = kVK_ANSI_G; break;
|
|
case 'h': case 'H': keycode = kVK_ANSI_H; break;
|
|
case 'i': case 'I': keycode = kVK_ANSI_I; break;
|
|
case 'j': case 'J': keycode = kVK_ANSI_J; break;
|
|
case 'k': case 'K': keycode = kVK_ANSI_K; break;
|
|
case 'l': case 'L': keycode = kVK_ANSI_L; break;
|
|
case 'm': case 'M': keycode = kVK_ANSI_M; break;
|
|
case 'n': case 'N': keycode = kVK_ANSI_N; break;
|
|
case 'o': case 'O': keycode = kVK_ANSI_O; break;
|
|
case 'p': case 'P': keycode = kVK_ANSI_P; break;
|
|
case 'q': case 'Q': keycode = kVK_ANSI_Q; break;
|
|
case 'r': case 'R': keycode = kVK_ANSI_R; break;
|
|
case 's': case 'S': keycode = kVK_ANSI_S; break;
|
|
case 't': case 'T': keycode = kVK_ANSI_T; break;
|
|
case 'u': case 'U': keycode = kVK_ANSI_U; break;
|
|
case 'v': case 'V': keycode = kVK_ANSI_V; break;
|
|
case 'w': case 'W': keycode = kVK_ANSI_W; break;
|
|
case 'x': case 'X': keycode = kVK_ANSI_X; break;
|
|
case 'y': case 'Y': keycode = kVK_ANSI_Y; break;
|
|
case 'z': case 'Z': keycode = kVK_ANSI_Z; break;
|
|
|
|
case '0': keycode = kVK_ANSI_0; break;
|
|
case '1': keycode = kVK_ANSI_1; break;
|
|
case '2': keycode = kVK_ANSI_2; break;
|
|
case '3': keycode = kVK_ANSI_3; break;
|
|
case '4': keycode = kVK_ANSI_4; break;
|
|
case '5': keycode = kVK_ANSI_5; break;
|
|
case '6': keycode = kVK_ANSI_6; break;
|
|
case '7': keycode = kVK_ANSI_7; break;
|
|
case '8': keycode = kVK_ANSI_8; break;
|
|
case '9': keycode = kVK_ANSI_9; break;
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic pop
|
|
#endif // __clang__
|
|
|
|
case WXK_BACK: keycode = kVK_Delete; break;
|
|
case WXK_TAB: keycode = kVK_Tab; break;
|
|
case WXK_RETURN: keycode = kVK_Return; break;
|
|
case WXK_ESCAPE: keycode = kVK_Escape; break;
|
|
case WXK_SPACE: keycode = kVK_Space; break;
|
|
case WXK_DELETE: keycode = kVK_ForwardDelete; break;
|
|
|
|
case WXK_SHIFT: keycode = kVK_Shift; break;
|
|
case WXK_ALT: keycode = kVK_Option; break;
|
|
case WXK_RAW_CONTROL: keycode = kVK_Control; break;
|
|
case WXK_CONTROL: keycode = kVK_Command; break;
|
|
|
|
case WXK_CAPITAL: keycode = kVK_CapsLock; break;
|
|
case WXK_END: keycode = kVK_End; break;
|
|
case WXK_HOME: keycode = kVK_Home; break;
|
|
case WXK_LEFT: keycode = kVK_LeftArrow; break;
|
|
case WXK_UP: keycode = kVK_UpArrow; break;
|
|
case WXK_RIGHT: keycode = kVK_RightArrow; break;
|
|
case WXK_DOWN: keycode = kVK_DownArrow; break;
|
|
|
|
case WXK_HELP: keycode = kVK_Help; break;
|
|
|
|
|
|
case WXK_NUMPAD0: keycode = kVK_ANSI_Keypad0; break;
|
|
case WXK_NUMPAD1: keycode = kVK_ANSI_Keypad1; break;
|
|
case WXK_NUMPAD2: keycode = kVK_ANSI_Keypad2; break;
|
|
case WXK_NUMPAD3: keycode = kVK_ANSI_Keypad3; break;
|
|
case WXK_NUMPAD4: keycode = kVK_ANSI_Keypad4; break;
|
|
case WXK_NUMPAD5: keycode = kVK_ANSI_Keypad5; break;
|
|
case WXK_NUMPAD6: keycode = kVK_ANSI_Keypad6; break;
|
|
case WXK_NUMPAD7: keycode = kVK_ANSI_Keypad7; break;
|
|
case WXK_NUMPAD8: keycode = kVK_ANSI_Keypad8; break;
|
|
case WXK_NUMPAD9: keycode = kVK_ANSI_Keypad9; break;
|
|
case WXK_F1: keycode = kVK_F1; break;
|
|
case WXK_F2: keycode = kVK_F2; break;
|
|
case WXK_F3: keycode = kVK_F3; break;
|
|
case WXK_F4: keycode = kVK_F4; break;
|
|
case WXK_F5: keycode = kVK_F5; break;
|
|
case WXK_F6: keycode = kVK_F6; break;
|
|
case WXK_F7: keycode = kVK_F7; break;
|
|
case WXK_F8: keycode = kVK_F8; break;
|
|
case WXK_F9: keycode = kVK_F9; break;
|
|
case WXK_F10: keycode = kVK_F10; break;
|
|
case WXK_F11: keycode = kVK_F11; break;
|
|
case WXK_F12: keycode = kVK_F12; break;
|
|
case WXK_F13: keycode = kVK_F13; break;
|
|
case WXK_F14: keycode = kVK_F14; break;
|
|
case WXK_F15: keycode = kVK_F15; break;
|
|
case WXK_F16: keycode = kVK_F16; break;
|
|
case WXK_F17: keycode = kVK_F17; break;
|
|
case WXK_F18: keycode = kVK_F18; break;
|
|
case WXK_F19: keycode = kVK_F19; break;
|
|
case WXK_F20: keycode = kVK_F20; break;
|
|
|
|
case WXK_PAGEUP: keycode = kVK_PageUp; break;
|
|
case WXK_PAGEDOWN: keycode = kVK_PageDown; break;
|
|
|
|
case WXK_NUMPAD_DELETE: keycode = kVK_ANSI_KeypadClear; break;
|
|
case WXK_NUMPAD_EQUAL: keycode = kVK_ANSI_KeypadEquals; break;
|
|
case WXK_NUMPAD_MULTIPLY: keycode = kVK_ANSI_KeypadMultiply; break;
|
|
case WXK_NUMPAD_ADD: keycode = kVK_ANSI_KeypadPlus; break;
|
|
case WXK_NUMPAD_SUBTRACT: keycode = kVK_ANSI_KeypadMinus; break;
|
|
case WXK_NUMPAD_DECIMAL: keycode = kVK_ANSI_KeypadDecimal; break;
|
|
case WXK_NUMPAD_DIVIDE: keycode = kVK_ANSI_KeypadDivide; break;
|
|
|
|
default:
|
|
wxLogDebug( "Unrecognised keycode %d", code );
|
|
keycode = static_cast<CGKeyCode>(-1);
|
|
}
|
|
|
|
return keycode;
|
|
}
|
|
|
|
long wxMacTranslateKey(unsigned char key, unsigned char code)
|
|
{
|
|
long retval = key ;
|
|
switch (key)
|
|
{
|
|
case kHomeCharCode :
|
|
retval = WXK_HOME;
|
|
break;
|
|
|
|
case kEnterCharCode :
|
|
retval = WXK_RETURN;
|
|
break;
|
|
case kEndCharCode :
|
|
retval = WXK_END;
|
|
break;
|
|
|
|
case kHelpCharCode :
|
|
retval = WXK_HELP;
|
|
break;
|
|
|
|
case kBackspaceCharCode :
|
|
retval = WXK_BACK;
|
|
break;
|
|
|
|
case kTabCharCode :
|
|
retval = WXK_TAB;
|
|
break;
|
|
|
|
case kPageUpCharCode :
|
|
retval = WXK_PAGEUP;
|
|
break;
|
|
|
|
case kPageDownCharCode :
|
|
retval = WXK_PAGEDOWN;
|
|
break;
|
|
|
|
case kReturnCharCode :
|
|
retval = WXK_RETURN;
|
|
break;
|
|
|
|
case kFunctionKeyCharCode :
|
|
{
|
|
switch ( code )
|
|
{
|
|
case 0x7a :
|
|
retval = WXK_F1 ;
|
|
break;
|
|
|
|
case 0x78 :
|
|
retval = WXK_F2 ;
|
|
break;
|
|
|
|
case 0x63 :
|
|
retval = WXK_F3 ;
|
|
break;
|
|
|
|
case 0x76 :
|
|
retval = WXK_F4 ;
|
|
break;
|
|
|
|
case 0x60 :
|
|
retval = WXK_F5 ;
|
|
break;
|
|
|
|
case 0x61 :
|
|
retval = WXK_F6 ;
|
|
break;
|
|
|
|
case 0x62:
|
|
retval = WXK_F7 ;
|
|
break;
|
|
|
|
case 0x64 :
|
|
retval = WXK_F8 ;
|
|
break;
|
|
|
|
case 0x65 :
|
|
retval = WXK_F9 ;
|
|
break;
|
|
|
|
case 0x6D :
|
|
retval = WXK_F10 ;
|
|
break;
|
|
|
|
case 0x67 :
|
|
retval = WXK_F11 ;
|
|
break;
|
|
|
|
case 0x6F :
|
|
retval = WXK_F12 ;
|
|
break;
|
|
|
|
case 0x69 :
|
|
retval = WXK_F13 ;
|
|
break;
|
|
|
|
case 0x6B :
|
|
retval = WXK_F14 ;
|
|
break;
|
|
|
|
case 0x71 :
|
|
retval = WXK_F15 ;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case kEscapeCharCode :
|
|
retval = WXK_ESCAPE ;
|
|
break ;
|
|
|
|
case kLeftArrowCharCode :
|
|
retval = WXK_LEFT ;
|
|
break ;
|
|
|
|
case kRightArrowCharCode :
|
|
retval = WXK_RIGHT ;
|
|
break ;
|
|
|
|
case kUpArrowCharCode :
|
|
retval = WXK_UP ;
|
|
break ;
|
|
|
|
case kDownArrowCharCode :
|
|
retval = WXK_DOWN ;
|
|
break ;
|
|
|
|
case kDeleteCharCode :
|
|
retval = WXK_DELETE ;
|
|
break ;
|
|
|
|
default:
|
|
break ;
|
|
} // end switch
|
|
|
|
return retval;
|
|
}
|
|
|
|
int wxMacKeyCodeToModifier(wxKeyCode key)
|
|
{
|
|
switch (key)
|
|
{
|
|
case WXK_START:
|
|
case WXK_MENU:
|
|
case WXK_COMMAND:
|
|
return cmdKey;
|
|
|
|
case WXK_SHIFT:
|
|
return shiftKey;
|
|
|
|
case WXK_CAPITAL:
|
|
return alphaLock;
|
|
|
|
case WXK_ALT:
|
|
return optionKey;
|
|
|
|
case WXK_RAW_CONTROL:
|
|
return controlKey;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if wxOSX_USE_COCOA
|
|
|
|
// defined in utils.mm
|
|
|
|
#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 , wxChar uniChar )
|
|
{
|
|
if ( !focus )
|
|
return false ;
|
|
|
|
wxKeyEvent event(wxEVT_KEY_DOWN) ;
|
|
MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
|
|
|
|
return focus->OSXHandleKeyEvent(event);
|
|
}
|
|
|
|
bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
|
|
{
|
|
if ( !focus )
|
|
return false ;
|
|
|
|
wxKeyEvent event( wxEVT_KEY_UP ) ;
|
|
MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
|
|
|
|
return focus->OSXHandleKeyEvent(event) ;
|
|
}
|
|
|
|
bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
|
|
{
|
|
if ( !focus )
|
|
return false ;
|
|
wxKeyEvent event(wxEVT_CHAR) ;
|
|
MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
|
|
|
|
bool handled = false ;
|
|
|
|
return handled ;
|
|
}
|
|
|
|
// This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
|
|
void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
|
|
{
|
|
#if wxOSX_USE_COCOA_OR_CARBON
|
|
|
|
short keycode, keychar ;
|
|
|
|
keychar = short(keymessage & charCodeMask);
|
|
keycode = short(keymessage & keyCodeMask) >> 8 ;
|
|
if ( !(event.GetEventType() == wxEVT_CHAR) && (modifiers & (controlKey | shiftKey | optionKey) ) )
|
|
{
|
|
// 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
|
|
#else
|
|
UInt32 state = 0;
|
|
UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey | shiftKey | optionKey))) | keycode, &state);
|
|
keychar = short(keyInfo & charCodeMask);
|
|
#endif
|
|
}
|
|
|
|
long keyval = wxMacTranslateKey(keychar, keycode) ;
|
|
if ( keyval == keychar && ( event.GetEventType() == wxEVT_KEY_UP || event.GetEventType() == wxEVT_KEY_DOWN ) )
|
|
keyval = wxToupper( keyval ) ;
|
|
|
|
// Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
|
|
// WXK_NUMPAD constants, but for the CHAR event we want to use the
|
|
// standard ascii values
|
|
if ( event.GetEventType() != wxEVT_CHAR )
|
|
{
|
|
if (keyval >= '0' && keyval <= '9' && keycode >= 82 && keycode <= 92)
|
|
{
|
|
keyval = (keyval - '0') + WXK_NUMPAD0;
|
|
}
|
|
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;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
event.m_shiftDown = modifiers & shiftKey;
|
|
event.m_rawControlDown = modifiers & controlKey;
|
|
event.m_altDown = modifiers & optionKey;
|
|
event.m_controlDown = modifiers & cmdKey;
|
|
event.m_keyCode = keyval ;
|
|
#if wxUSE_UNICODE
|
|
event.m_uniChar = uniChar ;
|
|
#endif
|
|
|
|
event.m_rawCode = keymessage;
|
|
event.m_rawFlags = modifiers;
|
|
event.SetTimestamp(when);
|
|
event.SetEventObject(focus);
|
|
#else
|
|
wxUnusedVar(event);
|
|
wxUnusedVar(focus);
|
|
wxUnusedVar(keymessage);
|
|
wxUnusedVar(modifiers);
|
|
wxUnusedVar(when);
|
|
wxUnusedVar(uniChar);
|
|
#endif
|
|
}
|
|
|
|
|
|
void wxApp::MacHideApp()
|
|
{
|
|
}
|