renaming
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54115 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
732
src/mac/core/cfstring.cpp
Normal file
732
src/mac/core/cfstring.cpp
Normal file
@@ -0,0 +1,732 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/mac/corefoundation/cfstring.cpp
|
||||
// Purpose: wxCFStringHolder and other string functions
|
||||
// Author: Stefan Csomor
|
||||
// Modified by:
|
||||
// Created: 2004-10-29 (from code in src/mac/carbon/utils.cpp)
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Stefan Csomor
|
||||
// Licence: wxWindows licence
|
||||
// Usage: Darwin (base library)
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/string.h"
|
||||
#include "wx/intl.h"
|
||||
#if wxUSE_GUI
|
||||
#include "wx/font.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "wx/mac/corefoundation/cfstring.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
void wxMacConvertNewlines13To10( char * data )
|
||||
{
|
||||
char * buf = data ;
|
||||
while( (buf=strchr(buf,0x0d)) != NULL )
|
||||
{
|
||||
*buf = 0x0a ;
|
||||
buf++ ;
|
||||
}
|
||||
}
|
||||
|
||||
void wxMacConvertNewlines10To13( char * data )
|
||||
{
|
||||
char * buf = data ;
|
||||
while( (buf=strchr(buf,0x0a)) != NULL )
|
||||
{
|
||||
*buf = 0x0d ;
|
||||
buf++ ;
|
||||
}
|
||||
}
|
||||
|
||||
const wxString sCR((wxChar)13);
|
||||
const wxString sLF((wxChar)10);
|
||||
|
||||
void wxMacConvertNewlines13To10( wxString * data )
|
||||
{
|
||||
data->Replace( sCR,sLF);
|
||||
}
|
||||
|
||||
void wxMacConvertNewlines10To13( wxString * data )
|
||||
{
|
||||
data->Replace( sLF,sCR);
|
||||
}
|
||||
|
||||
wxUint32 wxMacGetSystemEncFromFontEnc(wxFontEncoding encoding)
|
||||
{
|
||||
CFStringEncoding enc = 0 ;
|
||||
if ( encoding == wxFONTENCODING_DEFAULT )
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
encoding = wxFont::GetDefaultEncoding() ;
|
||||
#else
|
||||
encoding = wxFONTENCODING_SYSTEM; // to be set below
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( encoding == wxFONTENCODING_SYSTEM )
|
||||
{
|
||||
enc = CFStringGetSystemEncoding();
|
||||
}
|
||||
|
||||
switch( encoding)
|
||||
{
|
||||
case wxFONTENCODING_ISO8859_1 :
|
||||
enc = kCFStringEncodingISOLatin1 ;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_2 :
|
||||
enc = kCFStringEncodingISOLatin2;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_3 :
|
||||
enc = kCFStringEncodingISOLatin3 ;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_4 :
|
||||
enc = kCFStringEncodingISOLatin4;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_5 :
|
||||
enc = kCFStringEncodingISOLatinCyrillic;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_6 :
|
||||
enc = kCFStringEncodingISOLatinArabic;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_7 :
|
||||
enc = kCFStringEncodingISOLatinGreek;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_8 :
|
||||
enc = kCFStringEncodingISOLatinHebrew;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_9 :
|
||||
enc = kCFStringEncodingISOLatin5;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_10 :
|
||||
enc = kCFStringEncodingISOLatin6;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_13 :
|
||||
enc = kCFStringEncodingISOLatin7;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_14 :
|
||||
enc = kCFStringEncodingISOLatin8;
|
||||
break ;
|
||||
case wxFONTENCODING_ISO8859_15 :
|
||||
enc = kCFStringEncodingISOLatin9;
|
||||
break ;
|
||||
|
||||
case wxFONTENCODING_KOI8 :
|
||||
enc = kCFStringEncodingKOI8_R;
|
||||
break ;
|
||||
case wxFONTENCODING_ALTERNATIVE : // MS-DOS CP866
|
||||
enc = kCFStringEncodingDOSRussian;
|
||||
break ;
|
||||
/*
|
||||
case wxFONTENCODING_BULGARIAN :
|
||||
enc = ;
|
||||
break ;
|
||||
*/
|
||||
case wxFONTENCODING_CP437 :
|
||||
enc =kCFStringEncodingDOSLatinUS ;
|
||||
break ;
|
||||
case wxFONTENCODING_CP850 :
|
||||
enc = kCFStringEncodingDOSLatin1;
|
||||
break ;
|
||||
case wxFONTENCODING_CP852 :
|
||||
enc = kCFStringEncodingDOSLatin2;
|
||||
break ;
|
||||
case wxFONTENCODING_CP855 :
|
||||
enc = kCFStringEncodingDOSCyrillic;
|
||||
break ;
|
||||
case wxFONTENCODING_CP866 :
|
||||
enc =kCFStringEncodingDOSRussian ;
|
||||
break ;
|
||||
case wxFONTENCODING_CP874 :
|
||||
enc = kCFStringEncodingDOSThai;
|
||||
break ;
|
||||
case wxFONTENCODING_CP932 :
|
||||
enc = kCFStringEncodingDOSJapanese;
|
||||
break ;
|
||||
case wxFONTENCODING_CP936 :
|
||||
enc = kCFStringEncodingDOSChineseSimplif ;
|
||||
break ;
|
||||
case wxFONTENCODING_CP949 :
|
||||
enc = kCFStringEncodingDOSKorean;
|
||||
break ;
|
||||
case wxFONTENCODING_CP950 :
|
||||
enc = kCFStringEncodingDOSChineseTrad;
|
||||
break ;
|
||||
|
||||
case wxFONTENCODING_CP1250 :
|
||||
enc = kCFStringEncodingWindowsLatin2;
|
||||
break ;
|
||||
case wxFONTENCODING_CP1251 :
|
||||
enc =kCFStringEncodingWindowsCyrillic ;
|
||||
break ;
|
||||
case wxFONTENCODING_CP1252 :
|
||||
enc =kCFStringEncodingWindowsLatin1 ;
|
||||
break ;
|
||||
case wxFONTENCODING_CP1253 :
|
||||
enc = kCFStringEncodingWindowsGreek;
|
||||
break ;
|
||||
case wxFONTENCODING_CP1254 :
|
||||
enc = kCFStringEncodingWindowsLatin5;
|
||||
break ;
|
||||
case wxFONTENCODING_CP1255 :
|
||||
enc =kCFStringEncodingWindowsHebrew ;
|
||||
break ;
|
||||
case wxFONTENCODING_CP1256 :
|
||||
enc =kCFStringEncodingWindowsArabic ;
|
||||
break ;
|
||||
case wxFONTENCODING_CP1257 :
|
||||
enc = kCFStringEncodingWindowsBalticRim;
|
||||
break ;
|
||||
#if 0
|
||||
case wxFONTENCODING_UTF7 :
|
||||
enc = CreateTextEncoding(kCFStringEncodingUnicodeDefault,0,kUnicodeUTF7Format) ;
|
||||
#endif
|
||||
break ;
|
||||
case wxFONTENCODING_UTF8 :
|
||||
enc = kCFStringEncodingUTF8;
|
||||
break ;
|
||||
case wxFONTENCODING_EUC_JP :
|
||||
enc = kCFStringEncodingEUC_JP;
|
||||
break ;
|
||||
case wxFONTENCODING_UTF16BE :
|
||||
enc = kCFStringEncodingUTF16BE;
|
||||
break ;
|
||||
case wxFONTENCODING_UTF16LE :
|
||||
enc = kCFStringEncodingUTF16LE;
|
||||
break ;
|
||||
case wxFONTENCODING_UTF32BE :
|
||||
enc = kCFStringEncodingUTF32BE;
|
||||
break ;
|
||||
case wxFONTENCODING_UTF32LE :
|
||||
enc = kCFStringEncodingUTF32LE;
|
||||
break ;
|
||||
|
||||
case wxFONTENCODING_MACROMAN :
|
||||
enc = kCFStringEncodingMacRoman ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACJAPANESE :
|
||||
enc = kCFStringEncodingMacJapanese ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACCHINESETRAD :
|
||||
enc = kCFStringEncodingMacChineseTrad ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACKOREAN :
|
||||
enc = kCFStringEncodingMacKorean ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACARABIC :
|
||||
enc = kCFStringEncodingMacArabic ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACHEBREW :
|
||||
enc = kCFStringEncodingMacHebrew ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACGREEK :
|
||||
enc = kCFStringEncodingMacGreek ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACCYRILLIC :
|
||||
enc = kCFStringEncodingMacCyrillic ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACDEVANAGARI :
|
||||
enc = kCFStringEncodingMacDevanagari ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACGURMUKHI :
|
||||
enc = kCFStringEncodingMacGurmukhi ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACGUJARATI :
|
||||
enc = kCFStringEncodingMacGujarati ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACORIYA :
|
||||
enc = kCFStringEncodingMacOriya ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACBENGALI :
|
||||
enc = kCFStringEncodingMacBengali ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACTAMIL :
|
||||
enc = kCFStringEncodingMacTamil ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACTELUGU :
|
||||
enc = kCFStringEncodingMacTelugu ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACKANNADA :
|
||||
enc = kCFStringEncodingMacKannada ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACMALAJALAM :
|
||||
enc = kCFStringEncodingMacMalayalam ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACSINHALESE :
|
||||
enc = kCFStringEncodingMacSinhalese ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACBURMESE :
|
||||
enc = kCFStringEncodingMacBurmese ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACKHMER :
|
||||
enc = kCFStringEncodingMacKhmer ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACTHAI :
|
||||
enc = kCFStringEncodingMacThai ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACLAOTIAN :
|
||||
enc = kCFStringEncodingMacLaotian ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACGEORGIAN :
|
||||
enc = kCFStringEncodingMacGeorgian ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACARMENIAN :
|
||||
enc = kCFStringEncodingMacArmenian ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACCHINESESIMP :
|
||||
enc = kCFStringEncodingMacChineseSimp ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACTIBETAN :
|
||||
enc = kCFStringEncodingMacTibetan ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACMONGOLIAN :
|
||||
enc = kCFStringEncodingMacMongolian ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACETHIOPIC :
|
||||
enc = kCFStringEncodingMacEthiopic ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACCENTRALEUR :
|
||||
enc = kCFStringEncodingMacCentralEurRoman ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACVIATNAMESE :
|
||||
enc = kCFStringEncodingMacVietnamese ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACARABICEXT :
|
||||
enc = kCFStringEncodingMacExtArabic ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACSYMBOL :
|
||||
enc = kCFStringEncodingMacSymbol ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACDINGBATS :
|
||||
enc = kCFStringEncodingMacDingbats ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACTURKISH :
|
||||
enc = kCFStringEncodingMacTurkish ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACCROATIAN :
|
||||
enc = kCFStringEncodingMacCroatian ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACICELANDIC :
|
||||
enc = kCFStringEncodingMacIcelandic ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACROMANIAN :
|
||||
enc = kCFStringEncodingMacRomanian ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACCELTIC :
|
||||
enc = kCFStringEncodingMacCeltic ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACGAELIC :
|
||||
enc = kCFStringEncodingMacGaelic ;
|
||||
break ;
|
||||
case wxFONTENCODING_MACKEYBOARD :
|
||||
enc = 41; /* kTextEncodingMacKeyboardGlyphs ; */
|
||||
break ;
|
||||
default : // to make gcc happy
|
||||
break ;
|
||||
};
|
||||
return enc ;
|
||||
}
|
||||
|
||||
wxFontEncoding wxMacGetFontEncFromSystemEnc(wxUint32 encoding)
|
||||
{
|
||||
wxFontEncoding enc = wxFONTENCODING_DEFAULT ;
|
||||
|
||||
switch( encoding)
|
||||
{
|
||||
case kCFStringEncodingISOLatin1 :
|
||||
enc = wxFONTENCODING_ISO8859_1 ;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin2 :
|
||||
enc = wxFONTENCODING_ISO8859_2;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin3 :
|
||||
enc = wxFONTENCODING_ISO8859_3 ;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin4 :
|
||||
enc = wxFONTENCODING_ISO8859_4;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatinCyrillic :
|
||||
enc = wxFONTENCODING_ISO8859_5;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatinArabic :
|
||||
enc = wxFONTENCODING_ISO8859_6;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatinGreek :
|
||||
enc = wxFONTENCODING_ISO8859_7;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatinHebrew :
|
||||
enc = wxFONTENCODING_ISO8859_8;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin5 :
|
||||
enc = wxFONTENCODING_ISO8859_9;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin6 :
|
||||
enc = wxFONTENCODING_ISO8859_10;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin7 :
|
||||
enc = wxFONTENCODING_ISO8859_13;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin8 :
|
||||
enc = wxFONTENCODING_ISO8859_14;
|
||||
break ;
|
||||
case kCFStringEncodingISOLatin9 :
|
||||
enc =wxFONTENCODING_ISO8859_15 ;
|
||||
break ;
|
||||
|
||||
case kCFStringEncodingKOI8_R :
|
||||
enc = wxFONTENCODING_KOI8;
|
||||
break ;
|
||||
/*
|
||||
case :
|
||||
enc = wxFONTENCODING_BULGARIAN;
|
||||
break ;
|
||||
*/
|
||||
case kCFStringEncodingDOSLatinUS :
|
||||
enc = wxFONTENCODING_CP437;
|
||||
break ;
|
||||
case kCFStringEncodingDOSLatin1 :
|
||||
enc = wxFONTENCODING_CP850;
|
||||
break ;
|
||||
case kCFStringEncodingDOSLatin2 :
|
||||
enc =wxFONTENCODING_CP852 ;
|
||||
break ;
|
||||
case kCFStringEncodingDOSCyrillic :
|
||||
enc = wxFONTENCODING_CP855;
|
||||
break ;
|
||||
case kCFStringEncodingDOSRussian :
|
||||
enc = wxFONTENCODING_CP866;
|
||||
break ;
|
||||
case kCFStringEncodingDOSThai :
|
||||
enc =wxFONTENCODING_CP874 ;
|
||||
break ;
|
||||
case kCFStringEncodingDOSJapanese :
|
||||
enc = wxFONTENCODING_CP932;
|
||||
break ;
|
||||
case kCFStringEncodingDOSChineseSimplif :
|
||||
enc = wxFONTENCODING_CP936;
|
||||
break ;
|
||||
case kCFStringEncodingDOSKorean :
|
||||
enc = wxFONTENCODING_CP949;
|
||||
break ;
|
||||
case kCFStringEncodingDOSChineseTrad :
|
||||
enc = wxFONTENCODING_CP950;
|
||||
break ;
|
||||
|
||||
case kCFStringEncodingWindowsLatin2 :
|
||||
enc = wxFONTENCODING_CP1250;
|
||||
break ;
|
||||
case kCFStringEncodingWindowsCyrillic :
|
||||
enc = wxFONTENCODING_CP1251;
|
||||
break ;
|
||||
case kCFStringEncodingWindowsLatin1 :
|
||||
enc = wxFONTENCODING_CP1252;
|
||||
break ;
|
||||
case kCFStringEncodingWindowsGreek :
|
||||
enc = wxFONTENCODING_CP1253;
|
||||
break ;
|
||||
case kCFStringEncodingWindowsLatin5 :
|
||||
enc = wxFONTENCODING_CP1254;
|
||||
break ;
|
||||
case kCFStringEncodingWindowsHebrew :
|
||||
enc = wxFONTENCODING_CP1255;
|
||||
break ;
|
||||
case kCFStringEncodingWindowsArabic :
|
||||
enc = wxFONTENCODING_CP1256;
|
||||
break ;
|
||||
case kCFStringEncodingWindowsBalticRim :
|
||||
enc =wxFONTENCODING_CP1257 ;
|
||||
break ;
|
||||
case kCFStringEncodingEUC_JP :
|
||||
enc = wxFONTENCODING_EUC_JP;
|
||||
break ;
|
||||
|
||||
case kCFStringEncodingUTF8 :
|
||||
enc = wxFONTENCODING_UTF8;
|
||||
break ;
|
||||
case kCFStringEncodingUTF16BE :
|
||||
enc = wxFONTENCODING_UTF16BE;
|
||||
break ;
|
||||
case kCFStringEncodingUTF16LE :
|
||||
enc = wxFONTENCODING_UTF16LE;
|
||||
break ;
|
||||
case kCFStringEncodingUTF32BE :
|
||||
enc = wxFONTENCODING_UTF32BE;
|
||||
break ;
|
||||
case kCFStringEncodingUTF32LE :
|
||||
enc = wxFONTENCODING_UTF32LE;
|
||||
break ;
|
||||
|
||||
#if 0
|
||||
case wxFONTENCODING_UTF7 :
|
||||
enc = CreateTextEncoding(kCFStringEncodingUnicodeDefault,0,kUnicodeUTF7Format) ;
|
||||
break ;
|
||||
#endif
|
||||
case kCFStringEncodingMacRoman :
|
||||
enc = wxFONTENCODING_MACROMAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacJapanese :
|
||||
enc = wxFONTENCODING_MACJAPANESE ;
|
||||
break ;
|
||||
case kCFStringEncodingMacChineseTrad :
|
||||
enc = wxFONTENCODING_MACCHINESETRAD ;
|
||||
break ;
|
||||
case kCFStringEncodingMacKorean :
|
||||
enc = wxFONTENCODING_MACKOREAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacArabic :
|
||||
enc =wxFONTENCODING_MACARABIC ;
|
||||
break ;
|
||||
case kCFStringEncodingMacHebrew :
|
||||
enc = wxFONTENCODING_MACHEBREW ;
|
||||
break ;
|
||||
case kCFStringEncodingMacGreek :
|
||||
enc = wxFONTENCODING_MACGREEK ;
|
||||
break ;
|
||||
case kCFStringEncodingMacCyrillic :
|
||||
enc = wxFONTENCODING_MACCYRILLIC ;
|
||||
break ;
|
||||
case kCFStringEncodingMacDevanagari :
|
||||
enc = wxFONTENCODING_MACDEVANAGARI ;
|
||||
break ;
|
||||
case kCFStringEncodingMacGurmukhi :
|
||||
enc = wxFONTENCODING_MACGURMUKHI ;
|
||||
break ;
|
||||
case kCFStringEncodingMacGujarati :
|
||||
enc = wxFONTENCODING_MACGUJARATI ;
|
||||
break ;
|
||||
case kCFStringEncodingMacOriya :
|
||||
enc =wxFONTENCODING_MACORIYA ;
|
||||
break ;
|
||||
case kCFStringEncodingMacBengali :
|
||||
enc =wxFONTENCODING_MACBENGALI ;
|
||||
break ;
|
||||
case kCFStringEncodingMacTamil :
|
||||
enc = wxFONTENCODING_MACTAMIL ;
|
||||
break ;
|
||||
case kCFStringEncodingMacTelugu :
|
||||
enc = wxFONTENCODING_MACTELUGU ;
|
||||
break ;
|
||||
case kCFStringEncodingMacKannada :
|
||||
enc = wxFONTENCODING_MACKANNADA ;
|
||||
break ;
|
||||
case kCFStringEncodingMacMalayalam :
|
||||
enc = wxFONTENCODING_MACMALAJALAM ;
|
||||
break ;
|
||||
case kCFStringEncodingMacSinhalese :
|
||||
enc = wxFONTENCODING_MACSINHALESE ;
|
||||
break ;
|
||||
case kCFStringEncodingMacBurmese :
|
||||
enc = wxFONTENCODING_MACBURMESE ;
|
||||
break ;
|
||||
case kCFStringEncodingMacKhmer :
|
||||
enc = wxFONTENCODING_MACKHMER ;
|
||||
break ;
|
||||
case kCFStringEncodingMacThai :
|
||||
enc = wxFONTENCODING_MACTHAI ;
|
||||
break ;
|
||||
case kCFStringEncodingMacLaotian :
|
||||
enc = wxFONTENCODING_MACLAOTIAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacGeorgian :
|
||||
enc = wxFONTENCODING_MACGEORGIAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacArmenian :
|
||||
enc = wxFONTENCODING_MACARMENIAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacChineseSimp :
|
||||
enc = wxFONTENCODING_MACCHINESESIMP ;
|
||||
break ;
|
||||
case kCFStringEncodingMacTibetan :
|
||||
enc = wxFONTENCODING_MACTIBETAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacMongolian :
|
||||
enc = wxFONTENCODING_MACMONGOLIAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacEthiopic :
|
||||
enc = wxFONTENCODING_MACETHIOPIC ;
|
||||
break ;
|
||||
case kCFStringEncodingMacCentralEurRoman:
|
||||
enc = wxFONTENCODING_MACCENTRALEUR ;
|
||||
break ;
|
||||
case kCFStringEncodingMacVietnamese:
|
||||
enc = wxFONTENCODING_MACVIATNAMESE ;
|
||||
break ;
|
||||
case kCFStringEncodingMacExtArabic :
|
||||
enc = wxFONTENCODING_MACARABICEXT ;
|
||||
break ;
|
||||
case kCFStringEncodingMacSymbol :
|
||||
enc = wxFONTENCODING_MACSYMBOL ;
|
||||
break ;
|
||||
case kCFStringEncodingMacDingbats :
|
||||
enc = wxFONTENCODING_MACDINGBATS ;
|
||||
break ;
|
||||
case kCFStringEncodingMacTurkish :
|
||||
enc = wxFONTENCODING_MACTURKISH ;
|
||||
break ;
|
||||
case kCFStringEncodingMacCroatian :
|
||||
enc = wxFONTENCODING_MACCROATIAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacIcelandic :
|
||||
enc = wxFONTENCODING_MACICELANDIC ;
|
||||
break ;
|
||||
case kCFStringEncodingMacRomanian :
|
||||
enc = wxFONTENCODING_MACROMANIAN ;
|
||||
break ;
|
||||
case kCFStringEncodingMacCeltic :
|
||||
enc = wxFONTENCODING_MACCELTIC ;
|
||||
break ;
|
||||
case kCFStringEncodingMacGaelic :
|
||||
enc = wxFONTENCODING_MACGAELIC ;
|
||||
break ;
|
||||
case 41 /* kTextEncodingMacKeyboardGlyphs */ :
|
||||
enc = wxFONTENCODING_MACKEYBOARD ;
|
||||
break ;
|
||||
} ;
|
||||
return enc ;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CFStringRefs
|
||||
//
|
||||
|
||||
// converts this string into a core foundation string with optional pc 2 mac encoding
|
||||
|
||||
wxCFStringRef::wxCFStringRef( const wxString &st , wxFontEncoding WXUNUSED_IN_UNICODE(encoding) )
|
||||
{
|
||||
if (st.IsEmpty())
|
||||
{
|
||||
reset( wxCFRetain( CFSTR("") ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString str = st ;
|
||||
wxMacConvertNewlines13To10( &str ) ;
|
||||
#if wxUSE_UNICODE
|
||||
#if SIZEOF_WCHAR_T == 2
|
||||
reset( CFStringCreateWithCharacters( kCFAllocatorDefault,
|
||||
(UniChar*)str.wc_str() , str.Len() ) );
|
||||
#else
|
||||
wxMBConvUTF16 converter ;
|
||||
size_t unicharbytes = converter.FromWChar( NULL , 0 , str.wc_str() , str.Length() ) ;
|
||||
wxASSERT( unicharbytes != wxCONV_FAILED );
|
||||
if ( unicharbytes == wxCONV_FAILED )
|
||||
{
|
||||
// create an empty string
|
||||
reset( wxCFRetain( CFSTR("") ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// unicharbytes: number of bytes needed for UTF-16 encoded string (without terminating null)
|
||||
// unichars: number of UTF-16 characters (without terminating null)
|
||||
size_t unichars = unicharbytes / sizeof(UniChar) ;
|
||||
UniChar *unibuf = new UniChar[ unichars ] ;
|
||||
converter.FromWChar( (char*)unibuf , unicharbytes , str.wc_str() , str.Length() ) ;
|
||||
reset( CFStringCreateWithCharacters( kCFAllocatorDefault , unibuf , unichars ) ) ;
|
||||
delete[] unibuf ;
|
||||
}
|
||||
#endif
|
||||
#else // not wxUSE_UNICODE
|
||||
reset( CFStringCreateWithCString( kCFAllocatorSystemDefault , str.c_str() ,
|
||||
wxMacGetSystemEncFromFontEnc( encoding ) ) );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
wxString wxCFStringRef::AsString(wxFontEncoding WXUNUSED_IN_UNICODE(encoding))
|
||||
{
|
||||
if ( !get() )
|
||||
return wxEmptyString ;
|
||||
|
||||
Size cflen = CFStringGetLength( get() ) ;
|
||||
size_t noChars ;
|
||||
wxChar* buf = NULL ;
|
||||
|
||||
#if wxUSE_UNICODE
|
||||
#if SIZEOF_WCHAR_T == 2
|
||||
buf = new wxChar[ cflen + 1 ] ;
|
||||
CFStringGetCharacters( get() , CFRangeMake( 0 , cflen ) , (UniChar*) buf ) ;
|
||||
noChars = cflen ;
|
||||
#else
|
||||
UniChar* unibuf = new UniChar[ cflen + 1 ] ;
|
||||
CFStringGetCharacters( get() , CFRangeMake( 0 , cflen ) , (UniChar*) unibuf ) ;
|
||||
unibuf[cflen] = 0 ;
|
||||
wxMBConvUTF16 converter ;
|
||||
noChars = converter.MB2WC( NULL , (const char*)unibuf , 0 ) ;
|
||||
wxASSERT_MSG( noChars != wxCONV_FAILED, _T("Unable to count the number of characters in this string!") );
|
||||
buf = new wxChar[ noChars + 1 ] ;
|
||||
noChars = converter.MB2WC( buf , (const char*)unibuf , noChars + 1 ) ;
|
||||
wxASSERT_MSG( noChars != wxCONV_FAILED, _T("Conversion of string failed!") );
|
||||
delete[] unibuf ;
|
||||
#endif
|
||||
#else
|
||||
CFIndex cStrLen ;
|
||||
CFStringGetBytes( get() , CFRangeMake(0, cflen) , wxMacGetSystemEncFromFontEnc( encoding ) ,
|
||||
'?' , false , NULL , 0 , &cStrLen ) ;
|
||||
buf = new wxChar[ cStrLen + 1 ] ;
|
||||
CFStringGetBytes( get() , CFRangeMake(0, cflen) , wxMacGetSystemEncFromFontEnc( encoding ) ,
|
||||
'?' , false , (unsigned char*) buf , cStrLen , &cStrLen) ;
|
||||
noChars = cStrLen ;
|
||||
#endif
|
||||
|
||||
buf[noChars] = 0 ;
|
||||
wxString result(buf) ;
|
||||
delete[] buf ;
|
||||
wxMacConvertNewlines10To13( &result);
|
||||
return result ;
|
||||
}
|
||||
|
||||
//
|
||||
// wxMacUniCharBuffer
|
||||
//
|
||||
|
||||
wxMacUniCharBuffer::wxMacUniCharBuffer( const wxString &str )
|
||||
{
|
||||
m_chars = str.length() ;
|
||||
m_ubuf = NULL ;
|
||||
|
||||
#if SIZEOF_WCHAR_T == 4
|
||||
wxMBConvUTF16 converter ;
|
||||
#if wxUSE_UNICODE
|
||||
size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
|
||||
m_ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
|
||||
converter.WC2MB( (char*) m_ubuf , str.wc_str(), unicharlen + 2 ) ;
|
||||
#else
|
||||
const wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
|
||||
size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
|
||||
m_ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
|
||||
converter.WC2MB( (char*) m_ubuf , wchar.data() , unicharlen + 2 ) ;
|
||||
#endif
|
||||
m_chars = unicharlen / 2 ;
|
||||
#else // SIZEOF_WCHAR_T is then 2
|
||||
#if wxUSE_UNICODE
|
||||
m_ubuf = malloc( m_chars * 2 + 2 ) ;
|
||||
memcpy( m_ubuf , (UniChar*) str.wc_str() , m_chars * 2 + 2 ) ;
|
||||
#else
|
||||
wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
|
||||
m_chars = wxWcslen( wchar.data() ) ;
|
||||
m_ubuf = malloc( m_chars * 2 + 2 ) ;
|
||||
memcpy( m_ubuf , (UniChar*) wchar.data() , m_chars * 2 + 2 ) ;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
wxMacUniCharBuffer::~wxMacUniCharBuffer()
|
||||
{
|
||||
free( m_ubuf ) ;
|
||||
}
|
||||
|
||||
UniCharPtr wxMacUniCharBuffer::GetBuffer()
|
||||
{
|
||||
return m_ubuf ;
|
||||
}
|
||||
|
||||
UniCharCount wxMacUniCharBuffer::GetChars()
|
||||
{
|
||||
return m_chars ;
|
||||
}
|
318
src/mac/core/gsockosx.cpp
Normal file
318
src/mac/core/gsockosx.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
/* -------------------------------------------------------------------------
|
||||
* Project: GSocket (Generic Socket) for WX
|
||||
* Name: src/mac/corefoundation/gsockosx.c
|
||||
* Purpose: GSocket: Mac OS X mach-o part
|
||||
* CVSID: $Id$
|
||||
* Mac code by Brian Victor, February 2002. Email comments to bhv1@psu.edu
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if wxUSE_SOCKETS
|
||||
|
||||
#include "wx/gsocket.h"
|
||||
#include "wx/apptrait.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Mac-specific data associated with each socket by GSocketCFManager
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class MacGSocketData
|
||||
{
|
||||
public:
|
||||
// default ctor creates the object in uninitialized state, use Initialize()
|
||||
// later to make it usable
|
||||
MacGSocketData()
|
||||
{
|
||||
m_socket = NULL;
|
||||
m_source = NULL;
|
||||
}
|
||||
|
||||
// initialize the data associated with the given socket
|
||||
bool Initialize(GSocket *socket)
|
||||
{
|
||||
wxASSERT_MSG( !IsInitialized(), "shouldn't be called twice" );
|
||||
|
||||
// we need a valid Unix socket to create a CFSocket
|
||||
if ( socket->m_fd < 0 )
|
||||
return false;
|
||||
|
||||
CFSocketContext cont;
|
||||
cont.version = 0; // this currently must be 0
|
||||
cont.info = socket; // pointer passed to our callback
|
||||
cont.retain = NULL; // no need to retain/release/copy the
|
||||
cont.release = NULL; // socket pointer, so all callbacks
|
||||
cont.copyDescription = NULL; // can be left NULL
|
||||
|
||||
m_socket = CFSocketCreateWithNative
|
||||
(
|
||||
NULL, // default allocator
|
||||
socket->m_fd,
|
||||
kCFSocketReadCallBack |
|
||||
kCFSocketWriteCallBack |
|
||||
kCFSocketConnectCallBack,
|
||||
SocketCallback,
|
||||
&cont
|
||||
);
|
||||
if ( !m_socket )
|
||||
return false;
|
||||
|
||||
m_source = CFSocketCreateRunLoopSource(NULL, m_socket, 0);
|
||||
|
||||
return m_source != NULL;
|
||||
}
|
||||
|
||||
// free the objects created by Initialize()
|
||||
~MacGSocketData()
|
||||
{
|
||||
if ( m_source )
|
||||
CFRelease(m_source);
|
||||
if ( m_socket )
|
||||
CFRelease(m_socket);
|
||||
}
|
||||
|
||||
// return true if Initialize() had already been called successfully
|
||||
bool IsInitialized() const { return m_source && m_socket; }
|
||||
|
||||
|
||||
// accessors: should only be called if IsInitialized()
|
||||
CFSocketRef GetSocket() const
|
||||
{
|
||||
wxASSERT( IsInitialized() );
|
||||
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
CFRunLoopSourceRef GetSource() const
|
||||
{
|
||||
wxASSERT( IsInitialized() );
|
||||
|
||||
return m_source;
|
||||
}
|
||||
|
||||
private:
|
||||
static void SocketCallback(CFSocketRef WXUNUSED(s),
|
||||
CFSocketCallBackType callbackType,
|
||||
CFDataRef WXUNUSED(address),
|
||||
const void* data,
|
||||
void* info)
|
||||
{
|
||||
GSocket * const socket = wx_static_cast(GSocket *, info);
|
||||
MacGSocketData * const
|
||||
macdata = wx_static_cast(MacGSocketData *, socket->m_gui_dependent);
|
||||
if ( !macdata )
|
||||
return;
|
||||
|
||||
switch (callbackType)
|
||||
{
|
||||
case kCFSocketConnectCallBack:
|
||||
wxASSERT(!socket->m_server);
|
||||
// KH: If data is non-NULL, the connect failed, do not call Detected_Write,
|
||||
// which will only end up creating a spurious connect event because the
|
||||
// call to getsocketopt SO_ERROR inexplicably returns no error.
|
||||
// The change in behavior cannot be traced to any particular commit or
|
||||
// timeframe so I'm not sure what to think, but after so many hours,
|
||||
// this seems to address the issue and it's time to move on.
|
||||
if (data == NULL)
|
||||
socket->Detected_Write();
|
||||
break;
|
||||
|
||||
case kCFSocketReadCallBack:
|
||||
socket->Detected_Read();
|
||||
break;
|
||||
|
||||
case kCFSocketWriteCallBack:
|
||||
socket->Detected_Write();
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "unexpected socket callback" );
|
||||
}
|
||||
}
|
||||
|
||||
CFSocketRef m_socket;
|
||||
CFRunLoopSourceRef m_source;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(MacGSocketData);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CoreFoundation implementation of GSocketManager
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class GSocketCFManager : public GSocketManager
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit();
|
||||
virtual void OnExit();
|
||||
|
||||
virtual bool Init_Socket(GSocket *socket);
|
||||
virtual void Destroy_Socket(GSocket *socket);
|
||||
|
||||
virtual void Install_Callback(GSocket *socket, GSocketEvent event);
|
||||
virtual void Uninstall_Callback(GSocket *socket, GSocketEvent event);
|
||||
|
||||
virtual void Enable_Events(GSocket *socket);
|
||||
virtual void Disable_Events(GSocket *socket);
|
||||
|
||||
private:
|
||||
// retrieve our custom data associated with the given socket
|
||||
//
|
||||
// this is a low level function, use GetInitializedData() instead if the
|
||||
// data pointer should also be correctly initialized if it hadn't been done
|
||||
// yet
|
||||
//
|
||||
// may return NULL if we hadn't created the data for this socket yet
|
||||
MacGSocketData *GetData(GSocket *socket) const
|
||||
{
|
||||
return wx_static_cast(MacGSocketData *, socket->m_gui_dependent);
|
||||
}
|
||||
|
||||
// return the custom data pointer initializing it if it hadn't been done
|
||||
// yet
|
||||
//
|
||||
// may return NULL if there is no associated data
|
||||
MacGSocketData *GetInitializedData(GSocket *socket) const
|
||||
{
|
||||
MacGSocketData * const data = GetData(socket);
|
||||
if ( data && !data->IsInitialized() )
|
||||
{
|
||||
if ( !data->Initialize(socket) )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// return CFSocket callback mask corresponding to the given event (the
|
||||
// socket parameter is needed because some events are interpreted
|
||||
// differently depending on whether they happen on a server or on a client
|
||||
// socket)
|
||||
static int GetCFCallback(GSocket *socket, GSocketEvent event);
|
||||
|
||||
|
||||
// Sockets must use the event loop on the main thread so we store a
|
||||
// reference to the main loop here in OnInit()
|
||||
static CFRunLoopRef ms_mainRunLoop;
|
||||
};
|
||||
|
||||
CFRunLoopRef GSocketCFManager::ms_mainRunLoop = NULL;
|
||||
|
||||
bool GSocketCFManager::OnInit()
|
||||
{
|
||||
// No need to store the main loop again
|
||||
if (ms_mainRunLoop != NULL)
|
||||
return true;
|
||||
|
||||
// Get the loop for the main thread so our events will actually fire.
|
||||
// The common socket.cpp code will assert if initialize is called from a
|
||||
// secondary thread, otherwise Mac would have the same problems as MSW
|
||||
ms_mainRunLoop = CFRunLoopGetCurrent();
|
||||
if ( !ms_mainRunLoop )
|
||||
return false;
|
||||
|
||||
CFRetain(ms_mainRunLoop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSocketCFManager::OnExit()
|
||||
{
|
||||
// Release the reference count, and set the reference back to NULL
|
||||
CFRelease(ms_mainRunLoop);
|
||||
ms_mainRunLoop = NULL;
|
||||
}
|
||||
|
||||
bool GSocketCFManager::Init_Socket(GSocket *socket)
|
||||
{
|
||||
socket->m_gui_dependent = new MacGSocketData;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSocketCFManager::Destroy_Socket(GSocket *socket)
|
||||
{
|
||||
MacGSocketData * const data = GetData(socket);
|
||||
if ( data )
|
||||
{
|
||||
delete data;
|
||||
socket->m_gui_dependent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
int GSocketCFManager::GetCFCallback(GSocket *socket, GSocketEvent event)
|
||||
{
|
||||
switch ( event )
|
||||
{
|
||||
case GSOCK_CONNECTION:
|
||||
return socket->m_server ? kCFSocketReadCallBack
|
||||
: kCFSocketConnectCallBack;
|
||||
|
||||
case GSOCK_LOST:
|
||||
case GSOCK_INPUT:
|
||||
return kCFSocketReadCallBack;
|
||||
|
||||
case GSOCK_OUTPUT:
|
||||
return kCFSocketWriteCallBack;
|
||||
|
||||
case GSOCK_MAX_EVENT:
|
||||
wxFAIL_MSG( "invalid GSocketEvent" );
|
||||
return 0;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "unknown GSocketEvent" );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GSocketCFManager::Install_Callback(GSocket *socket, GSocketEvent event)
|
||||
{
|
||||
const MacGSocketData * const data = GetInitializedData(socket);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
CFSocketEnableCallBacks(data->GetSocket(), GetCFCallback(socket, event));
|
||||
}
|
||||
|
||||
void GSocketCFManager::Uninstall_Callback(GSocket *socket, GSocketEvent event)
|
||||
{
|
||||
const MacGSocketData * const data = GetInitializedData(socket);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
CFSocketDisableCallBacks(data->GetSocket(), GetCFCallback(socket, event));
|
||||
}
|
||||
|
||||
void GSocketCFManager::Enable_Events(GSocket *socket)
|
||||
{
|
||||
const MacGSocketData * const data = GetInitializedData(socket);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
CFRunLoopAddSource(ms_mainRunLoop, data->GetSource(), kCFRunLoopCommonModes);
|
||||
}
|
||||
|
||||
void GSocketCFManager::Disable_Events(GSocket *socket)
|
||||
{
|
||||
const MacGSocketData * const data = GetInitializedData(socket);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
// CFSocketInvalidate does CFRunLoopRemoveSource anyway
|
||||
CFRunLoopRemoveSource(ms_mainRunLoop, data->GetSource(), kCFRunLoopCommonModes);
|
||||
CFSocketInvalidate(data->GetSocket());
|
||||
|
||||
// CFSocketInvalidate has closed the socket so we want to make sure GSocket knows this
|
||||
socket->m_fd = -1;
|
||||
}
|
||||
|
||||
GSocketManager *wxAppTraits::GetSocketManager()
|
||||
{
|
||||
static GSocketCFManager s_manager;
|
||||
|
||||
return &s_manager;
|
||||
};
|
||||
|
||||
#endif // wxUSE_SOCKETS
|
741
src/mac/core/hid.cpp
Normal file
741
src/mac/core/hid.cpp
Normal file
@@ -0,0 +1,741 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/mac/corefoundation/hid.cpp
|
||||
// Purpose: DARWIN HID layer for WX Implementation
|
||||
// Author: Ryan Norton
|
||||
// Modified by:
|
||||
// Created: 11/11/2003
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Ryan Norton
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ===========================================================================
|
||||
// declarations
|
||||
// ===========================================================================
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// headers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
//DARWIN _ONLY_
|
||||
#ifdef __DARWIN__
|
||||
|
||||
#include "wx/mac/corefoundation/hid.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/string.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/module.h"
|
||||
#endif
|
||||
|
||||
#include "wx/mac/corefoundation/cfstring.h"
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxHIDDevice
|
||||
//
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice::Create
|
||||
//
|
||||
// nClass is the HID Page such as
|
||||
// kHIDPage_GenericDesktop
|
||||
// nType is the HID Usage such as
|
||||
// kHIDUsage_GD_Joystick,kHIDUsage_GD_Mouse,kHIDUsage_GD_Keyboard
|
||||
// nDev is the device number to use
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
bool wxHIDDevice::Create (int nClass, int nType, int nDev)
|
||||
{
|
||||
//Create the mach port
|
||||
if(IOMasterPort(bootstrap_port, &m_pPort) != kIOReturnSuccess)
|
||||
{
|
||||
wxLogSysError(wxT("Could not create mach port"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//Dictionary that will hold first
|
||||
//the matching dictionary for determining which kind of devices we want,
|
||||
//then later some registry properties from an iterator (see below)
|
||||
//
|
||||
//The call to IOServiceMatching filters down the
|
||||
//the services we want to hid services (and also eats the
|
||||
//dictionary up for us (consumes one reference))
|
||||
CFMutableDictionaryRef pDictionary = IOServiceMatching(kIOHIDDeviceKey);
|
||||
if(pDictionary == NULL)
|
||||
{
|
||||
wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") );
|
||||
return false;
|
||||
}
|
||||
|
||||
//Here we'll filter down the services to what we want
|
||||
if (nType != -1)
|
||||
{
|
||||
CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberIntType, &nType);
|
||||
CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
|
||||
CFRelease(pType);
|
||||
}
|
||||
if (nClass != -1)
|
||||
{
|
||||
CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberIntType, &nClass);
|
||||
CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
|
||||
CFRelease(pClass);
|
||||
}
|
||||
|
||||
//Now get the maching services
|
||||
io_iterator_t pIterator;
|
||||
if( IOServiceGetMatchingServices(m_pPort,
|
||||
pDictionary, &pIterator) != kIOReturnSuccess )
|
||||
{
|
||||
wxLogSysError(_T("No Matching HID Services"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//Were there any devices matched?
|
||||
if(pIterator == 0)
|
||||
return false; // No devices found
|
||||
|
||||
//Now we iterate through them
|
||||
io_object_t pObject;
|
||||
while ( (pObject = IOIteratorNext(pIterator)) != 0)
|
||||
{
|
||||
if(--nDev != 0)
|
||||
{
|
||||
IOObjectRelease(pObject);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( IORegistryEntryCreateCFProperties
|
||||
(
|
||||
pObject,
|
||||
&pDictionary,
|
||||
kCFAllocatorDefault,
|
||||
kNilOptions
|
||||
) != KERN_SUCCESS )
|
||||
{
|
||||
wxLogDebug(_T("IORegistryEntryCreateCFProperties failed"));
|
||||
}
|
||||
|
||||
//
|
||||
// Now we get the attributes of each "product" in the iterator
|
||||
//
|
||||
|
||||
//Get [product] name
|
||||
CFStringRef cfsProduct = (CFStringRef)
|
||||
CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey));
|
||||
m_szProductName =
|
||||
wxCFStringRef( wxCFRetain(cfsProduct)
|
||||
).AsString();
|
||||
|
||||
//Get the Product ID Key
|
||||
CFNumberRef cfnProductId = (CFNumberRef)
|
||||
CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey));
|
||||
if (cfnProductId)
|
||||
{
|
||||
CFNumberGetValue(cfnProductId, kCFNumberIntType, &m_nProductId);
|
||||
}
|
||||
|
||||
//Get the Vendor ID Key
|
||||
CFNumberRef cfnVendorId = (CFNumberRef)
|
||||
CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey));
|
||||
if (cfnVendorId)
|
||||
{
|
||||
CFNumberGetValue(cfnVendorId, kCFNumberIntType, &m_nManufacturerId);
|
||||
}
|
||||
|
||||
//
|
||||
// End attribute getting
|
||||
//
|
||||
|
||||
//Create the interface (good grief - long function names!)
|
||||
SInt32 nScore;
|
||||
IOCFPlugInInterface** ppPlugin;
|
||||
if(IOCreatePlugInInterfaceForService(pObject,
|
||||
kIOHIDDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID, &ppPlugin,
|
||||
&nScore) != kIOReturnSuccess)
|
||||
{
|
||||
wxLogSysError(wxT("Could not create HID Interface for product"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//Now, the final thing we can check before we fall back to asserts
|
||||
//(because the dtor only checks if the device is ok, so if anything
|
||||
//fails from now on the dtor will delete the device anyway, so we can't break from this).
|
||||
|
||||
//Get the HID interface from the plugin to the mach port
|
||||
if((*ppPlugin)->QueryInterface(ppPlugin,
|
||||
CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
|
||||
(void**) &m_ppDevice) != S_OK)
|
||||
{
|
||||
wxLogSysError(wxT("Could not get device interface from HID interface"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//release the plugin
|
||||
(*ppPlugin)->Release(ppPlugin);
|
||||
|
||||
//open the HID interface...
|
||||
if ( (*m_ppDevice)->open(m_ppDevice, 0) != S_OK )
|
||||
wxLogDebug(_T("HID device: open failed"));
|
||||
|
||||
//
|
||||
//Now the hard part - in order to scan things we need "cookies"
|
||||
//
|
||||
CFArrayRef cfaCookies = (CFArrayRef)CFDictionaryGetValue(pDictionary,
|
||||
CFSTR(kIOHIDElementKey));
|
||||
BuildCookies(cfaCookies);
|
||||
|
||||
//cleanup
|
||||
CFRelease(pDictionary);
|
||||
IOObjectRelease(pObject);
|
||||
|
||||
//iterator cleanup
|
||||
IOObjectRelease(pIterator);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//iterator cleanup
|
||||
IOObjectRelease(pIterator);
|
||||
|
||||
return false; //no device
|
||||
}//end Create()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice::GetCount [static]
|
||||
//
|
||||
// Obtains the number of devices on a system for a given HID Page (nClass)
|
||||
// and HID Usage (nType).
|
||||
// ----------------------------------------------------------------------------
|
||||
size_t wxHIDDevice::GetCount (int nClass, int nType)
|
||||
{
|
||||
//Create the mach port
|
||||
mach_port_t pPort;
|
||||
if(IOMasterPort(bootstrap_port, &pPort) != kIOReturnSuccess)
|
||||
{
|
||||
wxLogSysError(wxT("Could not create mach port"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//Dictionary that will hold first
|
||||
//the matching dictionary for determining which kind of devices we want,
|
||||
//then later some registry properties from an iterator (see below)
|
||||
CFMutableDictionaryRef pDictionary = IOServiceMatching(kIOHIDDeviceKey);
|
||||
if(pDictionary == NULL)
|
||||
{
|
||||
wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") );
|
||||
return false;
|
||||
}
|
||||
|
||||
//Here we'll filter down the services to what we want
|
||||
if (nType != -1)
|
||||
{
|
||||
CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberIntType, &nType);
|
||||
CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
|
||||
CFRelease(pType);
|
||||
}
|
||||
if (nClass != -1)
|
||||
{
|
||||
CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberIntType, &nClass);
|
||||
CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
|
||||
CFRelease(pClass);
|
||||
}
|
||||
|
||||
//Now get the maching services
|
||||
io_iterator_t pIterator;
|
||||
if( IOServiceGetMatchingServices(pPort,
|
||||
pDictionary, &pIterator) != kIOReturnSuccess )
|
||||
{
|
||||
wxLogSysError(_T("No Matching HID Services"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//If the iterator doesn't exist there are no devices :)
|
||||
if ( !pIterator )
|
||||
return 0;
|
||||
|
||||
//Now we iterate through them
|
||||
size_t nCount = 0;
|
||||
io_object_t pObject;
|
||||
while ( (pObject = IOIteratorNext(pIterator)) != 0)
|
||||
{
|
||||
++nCount;
|
||||
IOObjectRelease(pObject);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
IOObjectRelease(pIterator);
|
||||
mach_port_deallocate(mach_task_self(), pPort);
|
||||
|
||||
return nCount;
|
||||
}//end Create()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice::AddCookie
|
||||
//
|
||||
// Adds a cookie to the internal cookie array from a CFType
|
||||
// ----------------------------------------------------------------------------
|
||||
void wxHIDDevice::AddCookie(CFTypeRef Data, int i)
|
||||
{
|
||||
CFNumberGetValue(
|
||||
(CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data
|
||||
, CFSTR(kIOHIDElementCookieKey)
|
||||
),
|
||||
kCFNumberIntType,
|
||||
&m_pCookies[i]
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice::AddCookieInQueue
|
||||
//
|
||||
// Adds a cookie to the internal cookie array from a CFType and additionally
|
||||
// adds it to the internal HID Queue
|
||||
// ----------------------------------------------------------------------------
|
||||
void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, int i)
|
||||
{
|
||||
//3rd Param flags (none yet)
|
||||
AddCookie(Data, i);
|
||||
if ( (*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) != S_OK )
|
||||
wxLogDebug(_T("HID device: adding element failed"));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice::InitCookies
|
||||
//
|
||||
// Create the internal cookie array, optionally creating a HID Queue
|
||||
// ----------------------------------------------------------------------------
|
||||
void wxHIDDevice::InitCookies(size_t dwSize, bool bQueue)
|
||||
{
|
||||
m_pCookies = new IOHIDElementCookie[dwSize];
|
||||
if (bQueue)
|
||||
{
|
||||
wxASSERT( m_ppQueue == NULL);
|
||||
m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice);
|
||||
if ( !m_ppQueue )
|
||||
{
|
||||
wxLogDebug(_T("HID device: allocQueue failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
//Param 2, flags, none yet
|
||||
if ( (*m_ppQueue)->create(m_ppQueue, 0, 512) != S_OK )
|
||||
{
|
||||
wxLogDebug(_T("HID device: create failed"));
|
||||
}
|
||||
}
|
||||
|
||||
//make sure that cookie array is clear
|
||||
memset(m_pCookies, 0, sizeof(*m_pCookies) * dwSize);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice::IsActive
|
||||
//
|
||||
// Returns true if a cookie of the device is active - for example if a key is
|
||||
// held down, joystick button pressed, caps lock active, etc..
|
||||
// ----------------------------------------------------------------------------
|
||||
bool wxHIDDevice::IsActive(int nIndex)
|
||||
{
|
||||
if(!HasElement(nIndex))
|
||||
{
|
||||
//cookie at index does not exist - getElementValue
|
||||
//could return true which would be incorrect so we
|
||||
//check here
|
||||
return false;
|
||||
}
|
||||
|
||||
IOHIDEventStruct Event;
|
||||
(*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event);
|
||||
return !!Event.value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice::HasElement
|
||||
//
|
||||
// Returns true if the element in the internal cookie array exists
|
||||
// ----------------------------------------------------------------------------
|
||||
bool wxHIDDevice::HasElement(int nIndex)
|
||||
{
|
||||
return m_pCookies[nIndex] != NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDDevice Destructor
|
||||
//
|
||||
// Frees all memory and objects from the structure
|
||||
// ----------------------------------------------------------------------------
|
||||
wxHIDDevice::~wxHIDDevice()
|
||||
{
|
||||
if (m_ppDevice != NULL)
|
||||
{
|
||||
if (m_ppQueue != NULL)
|
||||
{
|
||||
(*m_ppQueue)->stop(m_ppQueue);
|
||||
(*m_ppQueue)->dispose(m_ppQueue);
|
||||
(*m_ppQueue)->Release(m_ppQueue);
|
||||
}
|
||||
(*m_ppDevice)->close(m_ppDevice);
|
||||
(*m_ppDevice)->Release(m_ppDevice);
|
||||
mach_port_deallocate(mach_task_self(), m_pPort);
|
||||
}
|
||||
|
||||
if (m_pCookies != NULL)
|
||||
{
|
||||
delete [] m_pCookies;
|
||||
}
|
||||
}
|
||||
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxHIDKeyboard
|
||||
//
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
//There are no right shift, alt etc. in the wx headers yet so just sort
|
||||
//of "define our own" for now
|
||||
enum
|
||||
{
|
||||
WXK_RSHIFT = 400,
|
||||
WXK_RALT,
|
||||
WXK_RCONTROL,
|
||||
WXK_RMENU
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDKeyboard::GetCount [static]
|
||||
//
|
||||
// Get number of HID keyboards available
|
||||
// ----------------------------------------------------------------------------
|
||||
int wxHIDKeyboard::GetCount()
|
||||
{
|
||||
return wxHIDDevice::GetCount(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_Keyboard);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDKeyboard::Create
|
||||
//
|
||||
// Create the HID Keyboard
|
||||
// ----------------------------------------------------------------------------
|
||||
bool wxHIDKeyboard::Create(int nDev /* = 1*/)
|
||||
{
|
||||
return wxHIDDevice::Create(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_Keyboard,
|
||||
nDev);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDKeyboard::AddCookie
|
||||
//
|
||||
// Overloaded version of wxHIDDevice::AddCookie that simply does not
|
||||
// add a cookie if a duplicate is found
|
||||
// ----------------------------------------------------------------------------
|
||||
void wxHIDKeyboard::AddCookie(CFTypeRef Data, int i)
|
||||
{
|
||||
if(!HasElement(i))
|
||||
wxHIDDevice::AddCookie(Data, i);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxHIDKeyboard::BuildCookies
|
||||
//
|
||||
// Callback from Create() to build the HID cookies for the internal cookie
|
||||
// array
|
||||
// ----------------------------------------------------------------------------
|
||||
void wxHIDKeyboard::BuildCookies(CFArrayRef Array)
|
||||
{
|
||||
//Create internal cookie array
|
||||
InitCookies(500);
|
||||
|
||||
//Begin recursing in array
|
||||
DoBuildCookies(Array);
|
||||
}
|
||||
|
||||
void wxHIDKeyboard::DoBuildCookies(CFArrayRef Array)
|
||||
{
|
||||
//Now go through each possible cookie
|
||||
int i,
|
||||
nUsage;
|
||||
// bool bEOTriggered = false;
|
||||
for (i = 0; i < CFArrayGetCount(Array); ++i)
|
||||
{
|
||||
const void* ref = CFDictionaryGetValue(
|
||||
(CFDictionaryRef)CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementKey)
|
||||
);
|
||||
|
||||
if (ref != NULL)
|
||||
{
|
||||
DoBuildCookies((CFArrayRef) ref);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//
|
||||
// Get the usage #
|
||||
//
|
||||
CFNumberGetValue(
|
||||
(CFNumberRef)
|
||||
CFDictionaryGetValue((CFDictionaryRef)
|
||||
CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementUsageKey)
|
||||
),
|
||||
kCFNumberLongType,
|
||||
&nUsage);
|
||||
|
||||
//
|
||||
// Now translate the usage # into a wx keycode
|
||||
//
|
||||
|
||||
//
|
||||
// OK, this is strange - basically this kind of strange -
|
||||
// Starting from 0xEO these elements (like shift) appear twice in
|
||||
// the array! The ones at the end are bogus I guess - the funny part
|
||||
// is that besides the fact that the ones at the front have a Unit
|
||||
// and UnitExponent key with a value of 0 and a different cookie value,
|
||||
// there is no discernable difference between the two...
|
||||
//
|
||||
// Will the real shift please stand up?
|
||||
//
|
||||
// Something to spend a support request on, if I had one, LOL.
|
||||
//
|
||||
//if(nUsage == 0xE0)
|
||||
//{
|
||||
// if(bEOTriggered)
|
||||
// break;
|
||||
// bEOTriggered = true;
|
||||
//}
|
||||
//Instead of that though we now just don't add duplicate keys
|
||||
|
||||
if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ)
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), 'A' + (nUsage - kHIDUsage_KeyboardA) );
|
||||
else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9)
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), '1' + (nUsage - kHIDUsage_Keyboard1) );
|
||||
else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12)
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) );
|
||||
else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24)
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) );
|
||||
else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9)
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) );
|
||||
else switch (nUsage)
|
||||
{
|
||||
//0's (wx & ascii go 0-9, but HID goes 1-0)
|
||||
case kHIDUsage_Keyboard0:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), '0');
|
||||
break;
|
||||
case kHIDUsage_Keypad0:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD0);
|
||||
break;
|
||||
|
||||
//Basic
|
||||
case kHIDUsage_KeyboardReturnOrEnter:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RETURN);
|
||||
break;
|
||||
case kHIDUsage_KeyboardEscape:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_ESCAPE);
|
||||
break;
|
||||
case kHIDUsage_KeyboardDeleteOrBackspace:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_BACK);
|
||||
break;
|
||||
case kHIDUsage_KeyboardTab:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_TAB);
|
||||
break;
|
||||
case kHIDUsage_KeyboardSpacebar:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_SPACE);
|
||||
break;
|
||||
case kHIDUsage_KeyboardPageUp:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEUP);
|
||||
break;
|
||||
case kHIDUsage_KeyboardEnd:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_END);
|
||||
break;
|
||||
case kHIDUsage_KeyboardPageDown:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEDOWN);
|
||||
break;
|
||||
case kHIDUsage_KeyboardRightArrow:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RIGHT);
|
||||
break;
|
||||
case kHIDUsage_KeyboardLeftArrow:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_LEFT);
|
||||
break;
|
||||
case kHIDUsage_KeyboardDownArrow:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_DOWN);
|
||||
break;
|
||||
case kHIDUsage_KeyboardUpArrow:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_UP);
|
||||
break;
|
||||
|
||||
//LEDS
|
||||
case kHIDUsage_KeyboardCapsLock:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CAPITAL);
|
||||
break;
|
||||
case kHIDUsage_KeypadNumLock:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_NUMLOCK);
|
||||
break;
|
||||
case kHIDUsage_KeyboardScrollLock:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SCROLL);
|
||||
break;
|
||||
|
||||
//Menu keys, Shift, other specials
|
||||
case kHIDUsage_KeyboardLeftControl:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CONTROL);
|
||||
break;
|
||||
case kHIDUsage_KeyboardLeftShift:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SHIFT);
|
||||
break;
|
||||
case kHIDUsage_KeyboardLeftAlt:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_ALT);
|
||||
break;
|
||||
case kHIDUsage_KeyboardLeftGUI:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_MENU);
|
||||
break;
|
||||
case kHIDUsage_KeyboardRightControl:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RCONTROL);
|
||||
break;
|
||||
case kHIDUsage_KeyboardRightShift:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RSHIFT);
|
||||
break;
|
||||
case kHIDUsage_KeyboardRightAlt:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RALT);
|
||||
break;
|
||||
case kHIDUsage_KeyboardRightGUI:
|
||||
AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RMENU);
|
||||
break;
|
||||
|
||||
//Default
|
||||
default:
|
||||
//not in wx keycodes - do nothing....
|
||||
break;
|
||||
} //end mightly long switch
|
||||
} //end if the current element is not an array...
|
||||
} //end for loop for Array
|
||||
}//end buildcookies
|
||||
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxHIDModule
|
||||
//
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
class wxHIDModule : public wxModule
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxHIDModule)
|
||||
|
||||
public:
|
||||
static wxArrayPtrVoid sm_keyboards;
|
||||
virtual bool OnInit()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual void OnExit()
|
||||
{
|
||||
for(size_t i = 0; i < sm_keyboards.GetCount(); ++i)
|
||||
delete (wxHIDKeyboard*) sm_keyboards[i];
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHIDModule, wxModule)
|
||||
|
||||
wxArrayPtrVoid wxHIDModule::sm_keyboards;
|
||||
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxGetKeyState()
|
||||
//
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
bool wxGetKeyState (wxKeyCode key)
|
||||
{
|
||||
wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key !=
|
||||
WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons"));
|
||||
|
||||
if (wxHIDModule::sm_keyboards.GetCount() == 0)
|
||||
{
|
||||
int nKeyboards = wxHIDKeyboard::GetCount();
|
||||
|
||||
for(int i = 1; i <= nKeyboards; ++i)
|
||||
{
|
||||
wxHIDKeyboard* keyboard = new wxHIDKeyboard();
|
||||
if(keyboard->Create(i))
|
||||
{
|
||||
wxHIDModule::sm_keyboards.Add(keyboard);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete keyboard;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wxASSERT_MSG(wxHIDModule::sm_keyboards.GetCount() != 0,
|
||||
wxT("No keyboards found!"));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < wxHIDModule::sm_keyboards.GetCount(); ++i)
|
||||
{
|
||||
wxHIDKeyboard* keyboard = (wxHIDKeyboard*)
|
||||
wxHIDModule::sm_keyboards[i];
|
||||
|
||||
switch(key)
|
||||
{
|
||||
case WXK_SHIFT:
|
||||
if( keyboard->IsActive(WXK_SHIFT) ||
|
||||
keyboard->IsActive(WXK_RSHIFT) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case WXK_ALT:
|
||||
if( keyboard->IsActive(WXK_ALT) ||
|
||||
keyboard->IsActive(WXK_RALT) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case WXK_CONTROL:
|
||||
if( keyboard->IsActive(WXK_CONTROL) ||
|
||||
keyboard->IsActive(WXK_RCONTROL) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case WXK_MENU:
|
||||
if( keyboard->IsActive(WXK_MENU) ||
|
||||
keyboard->IsActive(WXK_RMENU) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if( keyboard->IsActive(key) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false; //not down/error
|
||||
}
|
||||
|
||||
#endif //__DARWIN__
|
905
src/mac/core/hidjoystick.cpp
Normal file
905
src/mac/core/hidjoystick.cpp
Normal file
@@ -0,0 +1,905 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/mac/corefoundation/joystick.cpp
|
||||
// Purpose: wxJoystick class
|
||||
// Author: Ryan Norton
|
||||
// Modified by:
|
||||
// Created: 2/13/2005
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Ryan Norton
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//===========================================================================
|
||||
// DECLARATIONS
|
||||
//===========================================================================
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Pre-compiled header stuff
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Guard
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
//we only support HID on OSX (DARWIN), since it requires DARWIN...
|
||||
#if wxUSE_JOYSTICK && wxUSE_THREADS
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Includes
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/event.h" //joystick wxEvents
|
||||
#include "wx/window.h" //for wxWindow to "capture" joystick
|
||||
#endif
|
||||
|
||||
#include "wx/joystick.h" //...
|
||||
#include "wx/thread.h" //wxThread for polling thread/ wxCriticalSection
|
||||
|
||||
//private headers
|
||||
#include "wx/mac/corefoundation/hid.h" //private mac hid stuff
|
||||
|
||||
//mac headers
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Definitions/Enumerations
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define wxJS_MAX_AXES 10 /*max number of axes*/
|
||||
#define wxJS_MAX_BUTTONS 40 /*max number of buttons*/
|
||||
|
||||
enum
|
||||
{
|
||||
//These are positions within the cookie array
|
||||
//in wxHIDJoystick that the cookies that store the axis' are
|
||||
wxJS_AXIS_X = 40,
|
||||
wxJS_AXIS_Y,
|
||||
wxJS_AXIS_Z,
|
||||
wxJS_AXIS_RUDDER,
|
||||
wxJS_AXIS_U,
|
||||
wxJS_AXIS_V,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxHIDJoystick
|
||||
//---------------------------------------------------------------------------
|
||||
class wxHIDJoystick : public wxHIDDevice
|
||||
{
|
||||
public:
|
||||
wxHIDJoystick();
|
||||
virtual ~wxHIDJoystick();
|
||||
|
||||
bool Create(int nWhich);
|
||||
virtual void BuildCookies(CFArrayRef Array);
|
||||
void MakeCookies(CFArrayRef Array);
|
||||
IOHIDElementCookie* GetCookies();
|
||||
IOHIDQueueInterface** GetQueue();
|
||||
|
||||
int m_nXMax, m_nYMax, m_nZMax, m_nRudderMax, m_nUMax, m_nVMax,
|
||||
m_nXMin, m_nYMin, m_nZMin, m_nRudderMin, m_nUMin, m_nVMin;
|
||||
|
||||
friend class wxJoystick;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystickThread
|
||||
//---------------------------------------------------------------------------
|
||||
class wxJoystickThread : public wxThread
|
||||
{
|
||||
public:
|
||||
wxJoystickThread(wxHIDJoystick* hid, int joystick);
|
||||
void* Entry();
|
||||
static void HIDCallback(void* target, IOReturn res, void* context, void* sender);
|
||||
|
||||
private:
|
||||
wxHIDJoystick* m_hid;
|
||||
int m_joystick;
|
||||
wxPoint m_lastposition;
|
||||
int m_axe[wxJS_MAX_AXES];
|
||||
int m_buttons;
|
||||
wxWindow* m_catchwin;
|
||||
int m_polling;
|
||||
|
||||
friend class wxJoystick;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// IMPLEMENTATION
|
||||
//===========================================================================
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// wxGetIntFromCFDictionary
|
||||
//
|
||||
// Helper function that gets a integer from a dictionary key
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
void wxGetIntFromCFDictionary(CFTypeRef cfDict, CFStringRef key, int* pOut)
|
||||
{
|
||||
CFNumberGetValue(
|
||||
(CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) cfDict,
|
||||
key),
|
||||
kCFNumberIntType, pOut);
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxJoystick
|
||||
//
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick Constructor
|
||||
//
|
||||
// 1) Initializes member variables
|
||||
// 2) Attempts to create the native HID joystick implementation - if none
|
||||
// could be found (no joysticks, etc.) then it sets it to NULL
|
||||
//---------------------------------------------------------------------------
|
||||
wxJoystick::wxJoystick(int joystick)
|
||||
: m_joystick(joystick),
|
||||
m_thread(NULL)
|
||||
{
|
||||
m_hid = new wxHIDJoystick();
|
||||
|
||||
if (m_hid->Create(m_joystick+1)) //wxHIDDevice is 1-based while this is 0
|
||||
{
|
||||
m_thread = new wxJoystickThread(m_hid, m_joystick);
|
||||
m_thread->Create();
|
||||
m_thread->Run();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete m_hid;
|
||||
m_hid = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick Destructor
|
||||
//
|
||||
// Releases the capture of the thread, deletes it, and deletes
|
||||
// the native implementation.
|
||||
//---------------------------------------------------------------------------
|
||||
wxJoystick::~wxJoystick()
|
||||
{
|
||||
ReleaseCapture();
|
||||
if (m_thread)
|
||||
m_thread->Delete(); // It's detached so it will delete itself
|
||||
|
||||
if (m_hid)
|
||||
delete m_hid;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::Get[XXX]Position
|
||||
//
|
||||
// Returns the value of an axis that was polled from the thread. In the
|
||||
// case of GetPosition returns the X and Y values in a wxPoint
|
||||
//---------------------------------------------------------------------------
|
||||
wxPoint wxJoystick::GetPosition() const
|
||||
{
|
||||
wxPoint pos(wxDefaultPosition);
|
||||
if (m_thread) pos = m_thread->m_lastposition;
|
||||
return pos;
|
||||
}
|
||||
int wxJoystick::GetZPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_Z];
|
||||
return 0;
|
||||
}
|
||||
int wxJoystick::GetRudderPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_RUDDER];
|
||||
return 0;
|
||||
}
|
||||
int wxJoystick::GetUPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_U];
|
||||
return 0;
|
||||
}
|
||||
int wxJoystick::GetVPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_V];
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::GetButtonState
|
||||
//
|
||||
// Returns the state of the buttons in a bitmask as dictated by the
|
||||
// wx manual (the real work takes place in the thread, as always)
|
||||
//---------------------------------------------------------------------------
|
||||
int wxJoystick::GetButtonState() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_buttons;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::IsOk
|
||||
//
|
||||
// Returns whether the joystick initialized successfully - in this case
|
||||
// if the native implementation doesn't exist (in constructor)
|
||||
//---------------------------------------------------------------------------
|
||||
bool wxJoystick::IsOk() const
|
||||
{
|
||||
return m_hid != NULL;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::Get[XXX](Id/Name)
|
||||
//
|
||||
// Simple accessors to the native HID implementation
|
||||
//---------------------------------------------------------------------------
|
||||
int wxJoystick::GetManufacturerId() const
|
||||
{
|
||||
return m_hid->m_nManufacturerId;
|
||||
}
|
||||
|
||||
int wxJoystick::GetProductId() const
|
||||
{
|
||||
return m_hid->m_nProductId;
|
||||
}
|
||||
|
||||
wxString wxJoystick::GetProductName() const
|
||||
{
|
||||
return m_hid->m_szProductName;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::GetNumberButtons
|
||||
// wxJoystick::GetNumberAxes
|
||||
//
|
||||
// Queries the joystick for an active number of buttons/axes.
|
||||
//
|
||||
// In the native HID implementation, the cookies:
|
||||
// 0-40 are the buttons of the joystick
|
||||
// 40-50 are the axes of the joystick
|
||||
//
|
||||
// These just query the native HID implementation as above.
|
||||
//---------------------------------------------------------------------------
|
||||
int wxJoystick::GetNumberButtons() const
|
||||
{
|
||||
int nCount = 0;
|
||||
|
||||
for(int nIndex = 0; nIndex < 40; ++nIndex)
|
||||
{
|
||||
if(m_hid->HasElement(nIndex))
|
||||
++nCount;
|
||||
}
|
||||
|
||||
return nCount;
|
||||
}
|
||||
int wxJoystick::GetNumberAxes() const
|
||||
{
|
||||
int nCount = 0;
|
||||
|
||||
for(int nIndex = 40; nIndex < 50; ++nIndex)
|
||||
{
|
||||
if(m_hid->HasElement(nIndex))
|
||||
++nCount;
|
||||
}
|
||||
|
||||
return nCount;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::GetNumberJoysticks
|
||||
//
|
||||
// Gets the number of joysticks on the system. In HID that
|
||||
// is all devices with the kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad
|
||||
// identifiers.
|
||||
//---------------------------------------------------------------------------
|
||||
int wxJoystick::GetNumberJoysticks()
|
||||
{
|
||||
return
|
||||
wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) +
|
||||
wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::SetCapture
|
||||
//
|
||||
// Stops sending events from the thread to the window set in
|
||||
// SetCapture and stops polling the joystick
|
||||
//---------------------------------------------------------------------------
|
||||
bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
m_thread->m_catchwin = win;
|
||||
m_thread->m_polling = pollingFreq;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::ReleaseCapture
|
||||
//
|
||||
// Stops sending events from the thread to the window set in
|
||||
// SetCapture and stops polling the joystick
|
||||
//---------------------------------------------------------------------------
|
||||
bool wxJoystick::ReleaseCapture()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
m_thread->m_catchwin = NULL;
|
||||
m_thread->m_polling = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::Get[XXX]
|
||||
//
|
||||
// Gets the minimum and maximum values for each axis, returning 0 if the
|
||||
// axis doesn't exist.
|
||||
//---------------------------------------------------------------------------
|
||||
int wxJoystick::GetXMin() const
|
||||
{
|
||||
return m_hid->m_nXMin;
|
||||
}
|
||||
|
||||
int wxJoystick::GetYMin() const
|
||||
{
|
||||
return m_hid->m_nYMin;
|
||||
}
|
||||
|
||||
int wxJoystick::GetZMin() const
|
||||
{
|
||||
return m_hid->m_nZMin;
|
||||
}
|
||||
|
||||
int wxJoystick::GetRudderMin() const
|
||||
{
|
||||
return m_hid->m_nRudderMin;
|
||||
}
|
||||
|
||||
int wxJoystick::GetUMin() const
|
||||
{
|
||||
return m_hid->m_nUMin;
|
||||
}
|
||||
|
||||
int wxJoystick::GetVMin() const
|
||||
{
|
||||
return m_hid->m_nVMin;
|
||||
}
|
||||
|
||||
int wxJoystick::GetXMax() const
|
||||
{
|
||||
return m_hid->m_nXMax;
|
||||
}
|
||||
|
||||
int wxJoystick::GetYMax() const
|
||||
{
|
||||
return m_hid->m_nYMax;
|
||||
}
|
||||
|
||||
int wxJoystick::GetZMax() const
|
||||
{
|
||||
return m_hid->m_nZMax;
|
||||
}
|
||||
|
||||
int wxJoystick::GetRudderMax() const
|
||||
{
|
||||
return m_hid->m_nRudderMax;
|
||||
}
|
||||
|
||||
int wxJoystick::GetUMax() const
|
||||
{
|
||||
return m_hid->m_nUMax;
|
||||
}
|
||||
|
||||
int wxJoystick::GetVMax() const
|
||||
{
|
||||
return m_hid->m_nVMax;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::Get[XXX]
|
||||
//
|
||||
// Min/Max values for buttons, axes, etc.. Polling in this case is just
|
||||
// what the linux port has.
|
||||
//---------------------------------------------------------------------------
|
||||
int wxJoystick::GetMaxButtons() const
|
||||
{
|
||||
return wxJS_MAX_BUTTONS;
|
||||
}
|
||||
|
||||
int wxJoystick::GetMaxAxes() const
|
||||
{
|
||||
return wxJS_MAX_AXES;
|
||||
}
|
||||
|
||||
int wxJoystick::GetPollingMin() const
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
int wxJoystick::GetPollingMax() const
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystick::Has[XXX]
|
||||
//
|
||||
// Just queries the native hid implementation if the cookie was found
|
||||
// when enumerating the cookies of the joystick device
|
||||
//---------------------------------------------------------------------------
|
||||
bool wxJoystick::HasZ() const
|
||||
{
|
||||
return m_hid->HasElement(wxJS_AXIS_Z);
|
||||
}
|
||||
|
||||
bool wxJoystick::HasRudder() const
|
||||
{
|
||||
return m_hid->HasElement(wxJS_AXIS_RUDDER);
|
||||
}
|
||||
|
||||
bool wxJoystick::HasU() const
|
||||
{
|
||||
return m_hid->HasElement(wxJS_AXIS_U);
|
||||
}
|
||||
|
||||
bool wxJoystick::HasV() const
|
||||
{
|
||||
return m_hid->HasElement(wxJS_AXIS_V);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// UNSUPPORTED
|
||||
//---------------------------------------------------------------------------
|
||||
int wxJoystick::GetPOVPosition() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int wxJoystick::GetPOVCTSPosition() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int wxJoystick::GetMovementThreshold() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wxJoystick::SetMovementThreshold(int WXUNUSED(threshold))
|
||||
{
|
||||
}
|
||||
|
||||
bool wxJoystick::HasPOV() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasPOV4Dir() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasPOVCTS() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxHIDJoystick
|
||||
//
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxHIDJoystick ctor
|
||||
//
|
||||
// Initializes the min/max members
|
||||
//---------------------------------------------------------------------------
|
||||
wxHIDJoystick::wxHIDJoystick() :
|
||||
m_nXMax(0), m_nYMax(0), m_nZMax(0), m_nRudderMax(0), m_nUMax(0), m_nVMax(0),
|
||||
m_nXMin(0), m_nYMin(0), m_nZMin(0), m_nRudderMin(0), m_nUMin(0), m_nVMin(0)
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxHIDJoystick dtor
|
||||
//
|
||||
// Nothing...
|
||||
//---------------------------------------------------------------------------
|
||||
wxHIDJoystick::~wxHIDJoystick()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxHIDJoystick::Create
|
||||
//
|
||||
// Creates the native HID device (joysticks are of either
|
||||
// kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)
|
||||
//---------------------------------------------------------------------------
|
||||
bool wxHIDJoystick::Create(int nWhich)
|
||||
{
|
||||
int nJoysticks = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
|
||||
|
||||
if (nWhich <= nJoysticks)
|
||||
return wxHIDDevice::Create(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_Joystick,
|
||||
nWhich);
|
||||
else
|
||||
nWhich -= nJoysticks;
|
||||
|
||||
int nGamePads = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
|
||||
|
||||
if (nWhich <= nGamePads)
|
||||
return wxHIDDevice::Create(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_GamePad,
|
||||
nWhich);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxHIDJoystick::BuildCookies
|
||||
// wxHIDJoystick::MakeCookies
|
||||
//
|
||||
// Sets up the cookies for the HID device (called from Create) - as
|
||||
// mentioned 0-40 are the buttons and 40-50 are the axes.
|
||||
//
|
||||
// MakeCookies is just a recursive function for each array within
|
||||
// BuildCookies.
|
||||
//---------------------------------------------------------------------------
|
||||
void wxHIDJoystick::BuildCookies(CFArrayRef Array)
|
||||
{
|
||||
InitCookies(50, true);
|
||||
|
||||
//
|
||||
// I wasted two hours of my life on this line :(
|
||||
// accidently removed it during some source cleaning...
|
||||
//
|
||||
MakeCookies(Array);
|
||||
|
||||
//paranoid debugging stuff
|
||||
#if 0
|
||||
for(int i = 0; i < 50; ++i)
|
||||
wxPrintf(wxT("\nVAL #%i:[%i]"), i, m_pCookies[i]);
|
||||
#endif
|
||||
}//end buildcookies
|
||||
|
||||
void wxHIDJoystick::MakeCookies(CFArrayRef Array)
|
||||
{
|
||||
int i, nUsage, nPage;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(Array); ++i)
|
||||
{
|
||||
const void* ref = CFDictionaryGetValue(
|
||||
(CFDictionaryRef)CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementKey)
|
||||
);
|
||||
|
||||
if (ref != NULL)
|
||||
{
|
||||
MakeCookies((CFArrayRef) ref);
|
||||
}
|
||||
else
|
||||
{
|
||||
CFNumberGetValue(
|
||||
(CFNumberRef)
|
||||
CFDictionaryGetValue(
|
||||
(CFDictionaryRef) CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementUsageKey)
|
||||
),
|
||||
kCFNumberIntType,
|
||||
&nUsage );
|
||||
|
||||
CFNumberGetValue(
|
||||
(CFNumberRef)
|
||||
CFDictionaryGetValue(
|
||||
(CFDictionaryRef) CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementUsagePageKey)
|
||||
),
|
||||
kCFNumberIntType,
|
||||
&nPage );
|
||||
|
||||
#if 0
|
||||
wxLogSysError(wxT("[%i][%i]"), nUsage, nPage);
|
||||
#endif
|
||||
if (nPage == kHIDPage_Button && nUsage <= 40)
|
||||
AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), nUsage-1 );
|
||||
else if (nPage == kHIDPage_GenericDesktop)
|
||||
{
|
||||
//axis...
|
||||
switch(nUsage)
|
||||
{
|
||||
case kHIDUsage_GD_X:
|
||||
AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_X);
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMaxKey),
|
||||
&m_nXMax);
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMinKey),
|
||||
&m_nXMin);
|
||||
break;
|
||||
case kHIDUsage_GD_Y:
|
||||
AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Y);
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMaxKey),
|
||||
&m_nYMax);
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMinKey),
|
||||
&m_nYMin);
|
||||
break;
|
||||
case kHIDUsage_GD_Z:
|
||||
AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Z);
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMaxKey),
|
||||
&m_nZMax);
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMinKey),
|
||||
&m_nZMin);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder)
|
||||
{
|
||||
//rudder...
|
||||
AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_RUDDER );
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMaxKey),
|
||||
&m_nRudderMax);
|
||||
wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
|
||||
CFSTR(kIOHIDElementMinKey),
|
||||
&m_nRudderMin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxHIDJoystick::Get[XXX]
|
||||
//
|
||||
// Simple accessors so that the HID callback and the thread procedure
|
||||
// can access members from wxHIDDevice (our parent here).
|
||||
//---------------------------------------------------------------------------
|
||||
IOHIDElementCookie* wxHIDJoystick::GetCookies()
|
||||
{ return m_pCookies; }
|
||||
IOHIDQueueInterface** wxHIDJoystick::GetQueue()
|
||||
{ return m_ppQueue; }
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxJoystickThread
|
||||
//
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystickThread Constructor
|
||||
//
|
||||
// Just initializes members
|
||||
//---------------------------------------------------------------------------
|
||||
wxJoystickThread::wxJoystickThread(wxHIDJoystick* hid, int joystick)
|
||||
: m_hid(hid),
|
||||
m_joystick(joystick),
|
||||
m_lastposition(127,127),
|
||||
m_buttons(0),
|
||||
m_catchwin(NULL),
|
||||
m_polling(0)
|
||||
{
|
||||
memset(m_axe, 0, sizeof(int) * wxJS_MAX_AXES);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystickThread::Entry
|
||||
//
|
||||
// Thread procedure
|
||||
//
|
||||
// Runs a CFRunLoop for polling. Basically, it sets the HID queue to
|
||||
// call wxJoystickThread::HIDCallback in the context of this thread
|
||||
// when something changes on the device. It polls as long as the user
|
||||
// wants, or a certain amount if the user wants to "block". Note that
|
||||
// we don't actually block here since this is in a secondary thread.
|
||||
//---------------------------------------------------------------------------
|
||||
void* wxJoystickThread::Entry()
|
||||
{
|
||||
CFRunLoopSourceRef pRLSource = NULL;
|
||||
|
||||
if ((*m_hid->GetQueue())->createAsyncEventSource(
|
||||
m_hid->GetQueue(), &pRLSource) != kIOReturnSuccess )
|
||||
{
|
||||
wxLogSysError(wxT("Couldn't create async event source"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wxASSERT(pRLSource != NULL);
|
||||
|
||||
//attach runloop source to main run loop in thread
|
||||
CFRunLoopRef pRL = CFRunLoopGetCurrent();
|
||||
CFRunLoopAddSource(pRL, pRLSource, kCFRunLoopDefaultMode);
|
||||
wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
|
||||
|
||||
|
||||
if( (*m_hid->GetQueue())->setEventCallout(m_hid->GetQueue(),
|
||||
wxJoystickThread::HIDCallback, this, this) != kIOReturnSuccess )
|
||||
{
|
||||
wxLogSysError(wxT("Could not set event callout for queue"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( (*m_hid->GetQueue())->start(m_hid->GetQueue()) != kIOReturnSuccess )
|
||||
{
|
||||
wxLogSysError(wxT("Could not start queue"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double dTime;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if (TestDestroy())
|
||||
break;
|
||||
|
||||
if (m_polling)
|
||||
dTime = 0.0001 * m_polling;
|
||||
else
|
||||
dTime = 0.0001 * 10; // check at least every 10 msec in "blocking" case
|
||||
|
||||
//true just "handles and returns" - false forces it to stay the time
|
||||
//amount
|
||||
#if 1
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, true);
|
||||
#else
|
||||
IOReturn ret = NULL;
|
||||
HIDCallback(this, ret, this, this);
|
||||
Sleep(3000);
|
||||
#endif
|
||||
}
|
||||
|
||||
wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
|
||||
|
||||
CFRunLoopRemoveSource(pRL, pRLSource, kCFRunLoopDefaultMode);
|
||||
CFRelease(pRLSource);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// wxJoystickThread::HIDCallback (static)
|
||||
//
|
||||
// Callback for the native HID device when it recieves input.
|
||||
//
|
||||
// This is where the REAL dirty work gets done.
|
||||
//
|
||||
// 1) Loops through each event the queue has recieved
|
||||
// 2) First, checks if the thread that is running the loop for
|
||||
// the polling has ended - if so it breaks out
|
||||
// 3) Next, it checks if there was an error getting this event from
|
||||
// the HID queue, if there was, it logs an error and returns
|
||||
// 4) Now it does the real dirty work by getting the button states
|
||||
// from cookies 0-40 and axes positions/states from cookies 40-50
|
||||
// in the native HID device by quering cookie values.
|
||||
// 5) Sends the event to the polling window (if any)
|
||||
// 6) Gets the next event and goes back to (1)
|
||||
//---------------------------------------------------------------------------
|
||||
/*static*/ void wxJoystickThread::HIDCallback(void* WXUNUSED(target),
|
||||
IOReturn WXUNUSED(res),
|
||||
void* context,
|
||||
void* WXUNUSED(sender))
|
||||
{
|
||||
IOHIDEventStruct hidevent;
|
||||
AbsoluteTime bogustime = {0,0};
|
||||
IOReturn ret;
|
||||
wxJoystickThread* pThis = (wxJoystickThread*) context;
|
||||
wxHIDJoystick* m_hid = pThis->m_hid;
|
||||
|
||||
//Get the "first" event from the queue
|
||||
//bogustime tells it we don't care at what time to start
|
||||
//where it gets the next from
|
||||
ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
|
||||
&hidevent, bogustime, 0);
|
||||
|
||||
while (ret != kIOReturnUnderrun)
|
||||
{
|
||||
if (pThis->TestDestroy())
|
||||
break;
|
||||
|
||||
if(ret != kIOReturnSuccess)
|
||||
{
|
||||
wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret));
|
||||
return;
|
||||
}
|
||||
|
||||
wxJoystickEvent wxevent;
|
||||
|
||||
//Find the cookie that changed
|
||||
int nIndex = 0;
|
||||
IOHIDElementCookie* pCookies = m_hid->GetCookies();
|
||||
while(nIndex < 50)
|
||||
{
|
||||
if(hidevent.elementCookie == pCookies[nIndex])
|
||||
break;
|
||||
|
||||
++nIndex;
|
||||
}
|
||||
|
||||
//debugging stuff
|
||||
#if 0
|
||||
if(nIndex == 50)
|
||||
{
|
||||
wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error")));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
//is the cookie a button?
|
||||
if (nIndex < 40)
|
||||
{
|
||||
if (hidevent.value)
|
||||
{
|
||||
pThis->m_buttons |= (1 << nIndex);
|
||||
wxevent.SetEventType(wxEVT_JOY_BUTTON_DOWN);
|
||||
}
|
||||
else
|
||||
{
|
||||
pThis->m_buttons &= ~(1 << nIndex);
|
||||
wxevent.SetEventType(wxEVT_JOY_BUTTON_UP);
|
||||
}
|
||||
|
||||
wxevent.SetButtonChange(nIndex+1);
|
||||
}
|
||||
else if (nIndex == wxJS_AXIS_X)
|
||||
{
|
||||
pThis->m_lastposition.x = hidevent.value;
|
||||
wxevent.SetEventType(wxEVT_JOY_MOVE);
|
||||
pThis->m_axe[0] = hidevent.value;
|
||||
}
|
||||
else if (nIndex == wxJS_AXIS_Y)
|
||||
{
|
||||
pThis->m_lastposition.y = hidevent.value;
|
||||
wxevent.SetEventType(wxEVT_JOY_MOVE);
|
||||
pThis->m_axe[1] = hidevent.value;
|
||||
}
|
||||
else if (nIndex == wxJS_AXIS_Z)
|
||||
{
|
||||
wxevent.SetEventType(wxEVT_JOY_ZMOVE);
|
||||
pThis->m_axe[2] = hidevent.value;
|
||||
}
|
||||
else
|
||||
wxevent.SetEventType(wxEVT_JOY_MOVE);
|
||||
|
||||
Nanoseconds timestamp = AbsoluteToNanoseconds(hidevent.timestamp);
|
||||
|
||||
wxULongLong llTime(timestamp.hi, timestamp.lo);
|
||||
|
||||
llTime /= 1000000;
|
||||
|
||||
wxevent.SetTimestamp(llTime.GetValue());
|
||||
wxevent.SetJoystick(pThis->m_joystick);
|
||||
wxevent.SetButtonState(pThis->m_buttons);
|
||||
wxevent.SetPosition(pThis->m_lastposition);
|
||||
wxevent.SetZPosition(pThis->m_axe[2]);
|
||||
wxevent.SetEventObject(pThis->m_catchwin);
|
||||
|
||||
if (pThis->m_catchwin)
|
||||
pThis->m_catchwin->AddPendingEvent(wxevent);
|
||||
|
||||
ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
|
||||
&hidevent, bogustime, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // wxUSE_JOYSTICK
|
217
src/mac/core/stdpaths_cf.cpp
Normal file
217
src/mac/core/stdpaths_cf.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: mac/corefoundation/stdpaths.cpp
|
||||
// Purpose: wxStandardPaths implementation for CoreFoundation systems
|
||||
// Author: David Elliott
|
||||
// Modified by:
|
||||
// Created: 2004-10-27
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2004 David Elliott <dfe@cox.net>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if wxUSE_STDPATHS
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/intl.h"
|
||||
#endif //ndef WX_PRECOMP
|
||||
|
||||
#include "wx/stdpaths.h"
|
||||
#include "wx/filename.h"
|
||||
#ifdef __WXMAC__
|
||||
#include "wx/mac/private.h"
|
||||
#endif
|
||||
#include "wx/mac/corefoundation/cfstring.h"
|
||||
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#include <CoreFoundation/CFURL.h>
|
||||
|
||||
#define kDefaultPathStyle kCFURLPOSIXPathStyle
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxStandardPathsCF ctors/dtor
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxStandardPathsCF::wxStandardPathsCF()
|
||||
: m_bundle(CFBundleGetMainBundle())
|
||||
{
|
||||
CFRetain(m_bundle);
|
||||
UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
|
||||
}
|
||||
|
||||
wxStandardPathsCF::wxStandardPathsCF(wxCFBundleRef bundle)
|
||||
: m_bundle(bundle)
|
||||
{
|
||||
CFRetain(m_bundle);
|
||||
UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
|
||||
}
|
||||
|
||||
wxStandardPathsCF::~wxStandardPathsCF()
|
||||
{
|
||||
CFRelease(m_bundle);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxStandardPathsCF Mac-specific methods
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxStandardPathsCF::SetBundle(wxCFBundleRef bundle)
|
||||
{
|
||||
CFRetain(bundle);
|
||||
CFRelease(m_bundle);
|
||||
m_bundle = bundle;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// generic functions in terms of which the other ones are implemented
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static wxString BundleRelativeURLToPath(CFURLRef relativeURL)
|
||||
{
|
||||
CFURLRef absoluteURL = CFURLCopyAbsoluteURL(relativeURL);
|
||||
wxCHECK_MSG(absoluteURL, wxEmptyString, wxT("Failed to resolve relative URL to absolute URL"));
|
||||
CFStringRef cfStrPath = CFURLCopyFileSystemPath(absoluteURL,kDefaultPathStyle);
|
||||
CFRelease(absoluteURL);
|
||||
return wxCFStringRef(cfStrPath).AsString(wxLocale::GetSystemEncoding());
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetFromFunc(wxCFURLRef (*func)(wxCFBundleRef)) const
|
||||
{
|
||||
wxCHECK_MSG(m_bundle, wxEmptyString,
|
||||
wxT("wxStandardPaths for CoreFoundation only works with bundled apps"));
|
||||
CFURLRef relativeURL = (*func)(m_bundle);
|
||||
wxCHECK_MSG(relativeURL, wxEmptyString, wxT("Couldn't get URL"));
|
||||
wxString ret(BundleRelativeURLToPath(relativeURL));
|
||||
CFRelease(relativeURL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetDocumentsDir() const
|
||||
{
|
||||
#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
|
||||
return wxMacFindFolderNoSeparator
|
||||
(
|
||||
kUserDomain,
|
||||
kDocumentsFolderType,
|
||||
kCreateFolder
|
||||
);
|
||||
#else
|
||||
return wxFileName::GetHomeDir() + wxT("/Documents");
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxStandardPathsCF public API
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxString wxStandardPathsCF::GetConfigDir() const
|
||||
{
|
||||
#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
|
||||
return wxMacFindFolder((short)kLocalDomain, kPreferencesFolderType, kCreateFolder);
|
||||
#else
|
||||
return wxT("/Library/Preferences");
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetUserConfigDir() const
|
||||
{
|
||||
#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
|
||||
return wxMacFindFolder((short)kUserDomain, kPreferencesFolderType, kCreateFolder);
|
||||
#else
|
||||
return wxFileName::GetHomeDir() + wxT("/Library/Preferences");
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetDataDir() const
|
||||
{
|
||||
return GetFromFunc(CFBundleCopySharedSupportURL);
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetExecutablePath() const
|
||||
{
|
||||
#ifdef __WXMAC__
|
||||
#if 1
|
||||
return GetFromFunc(CFBundleCopyBundleURL);
|
||||
#else
|
||||
// TODO remove if cf implementation ok
|
||||
ProcessInfoRec processinfo;
|
||||
ProcessSerialNumber procno ;
|
||||
#ifdef __LP64__
|
||||
FSRef fsRef;
|
||||
#else
|
||||
FSSpec fsSpec;
|
||||
#endif
|
||||
|
||||
procno.highLongOfPSN = 0 ;
|
||||
procno.lowLongOfPSN = kCurrentProcess ;
|
||||
processinfo.processInfoLength = sizeof(ProcessInfoRec);
|
||||
processinfo.processName = NULL;
|
||||
#ifdef __LP64__
|
||||
processinfo.processAppRef = &fsRef;
|
||||
#else
|
||||
processinfo.processAppSpec = &fsSpec;
|
||||
#endif
|
||||
|
||||
GetProcessInformation( &procno , &processinfo ) ;
|
||||
#ifdef __LP64__
|
||||
return wxMacFSRefToPath(&fsRef);
|
||||
#else
|
||||
return wxMacFSSpec2MacFilename(&fsSpec);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
return wxStandardPathsBase::GetExecutablePath();
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetLocalDataDir() const
|
||||
{
|
||||
#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
|
||||
return AppendAppInfo(wxMacFindFolder((short)kLocalDomain, kApplicationSupportFolderType, kCreateFolder));
|
||||
#else
|
||||
return AppendAppInfo(wxT("/Library/Application Support"));
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetUserDataDir() const
|
||||
{
|
||||
#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
|
||||
return AppendAppInfo(wxMacFindFolder((short)kUserDomain, kApplicationSupportFolderType, kCreateFolder));
|
||||
#else
|
||||
return AppendAppInfo(wxFileName::GetHomeDir() + _T("/Library/Application Support"));
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetPluginsDir() const
|
||||
{
|
||||
return GetFromFunc(CFBundleCopyBuiltInPlugInsURL);
|
||||
}
|
||||
|
||||
wxString wxStandardPathsCF::GetResourcesDir() const
|
||||
{
|
||||
return GetFromFunc(CFBundleCopyResourcesDirectoryURL);
|
||||
}
|
||||
|
||||
wxString
|
||||
wxStandardPathsCF::GetLocalizedResourcesDir(const wxString& lang,
|
||||
ResourceCat category) const
|
||||
{
|
||||
return wxStandardPathsBase::
|
||||
GetLocalizedResourcesDir(lang, category) + _T(".lproj");
|
||||
}
|
||||
|
||||
#endif // wxUSE_STDPATHS
|
228
src/mac/core/strconv_cf.cpp
Normal file
228
src/mac/core/strconv_cf.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/mac/corefoundation/strconv.cpp
|
||||
// Purpose: Unicode conversion classes
|
||||
// Author: David Elliott
|
||||
// Modified by:
|
||||
// Created: 2007-07-06
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2007 David Elliott
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/string.h"
|
||||
#endif
|
||||
|
||||
#include "wx/strconv.h"
|
||||
#include "wx/fontmap.h"
|
||||
|
||||
#ifdef __DARWIN__
|
||||
|
||||
#include "wx/mac/corefoundation/private/strconv_cf.h"
|
||||
#include "wx/mac/corefoundation/cfref.h"
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// CoreFoundation conversion classes
|
||||
// ============================================================================
|
||||
|
||||
/* Provide factory functions for unit tests. Not in any header. Do not
|
||||
* assume ABI compatibility even within a given wxWidgets release.
|
||||
*/
|
||||
|
||||
WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_cf( const char* name)
|
||||
{
|
||||
wxMBConv_cf *result = new wxMBConv_cf(name);
|
||||
if(!result->IsOk())
|
||||
{
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_cf(wxFontEncoding encoding)
|
||||
{
|
||||
wxMBConv_cf *result = new wxMBConv_cf(encoding);
|
||||
if(!result->IsOk())
|
||||
{
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
// Provide a constant for the wchat_t encoding used by the host platform.
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
static const CFStringEncoding wxCFStringEncodingWcharT = kCFStringEncodingUTF32BE;
|
||||
#else
|
||||
static const CFStringEncoding wxCFStringEncodingWcharT = kCFStringEncodingUTF32LE;
|
||||
#endif
|
||||
|
||||
size_t wxMBConv_cf::ToWChar(wchar_t * dst, size_t dstSize, const char * src, size_t srcSize) const
|
||||
{
|
||||
wxCHECK(src, wxCONV_FAILED);
|
||||
|
||||
/* NOTE: This is wrong if the source encoding has an element size
|
||||
* other than char (e.g. it's kCFStringEncodingUnicode)
|
||||
* If the user specifies it, it's presumably right though.
|
||||
* Right now we don't support UTF-16 in anyway since wx can do a better job.
|
||||
*/
|
||||
if(srcSize == wxNO_LEN)
|
||||
srcSize = strlen(src) + 1;
|
||||
|
||||
// First create the temporary CFString
|
||||
wxCFRef<CFStringRef> theString( CFStringCreateWithBytes (
|
||||
NULL, //the allocator
|
||||
(const UInt8*)src,
|
||||
srcSize,
|
||||
m_encoding,
|
||||
false //no BOM/external representation
|
||||
));
|
||||
|
||||
wxCHECK(theString != NULL, wxCONV_FAILED);
|
||||
|
||||
/* NOTE: The string content includes the NULL element if the source string did
|
||||
* That means we have to do nothing special because the destination will have
|
||||
* the NULL element iff the source did and the NULL element will be included
|
||||
* in the count iff it was included in the source count.
|
||||
*/
|
||||
|
||||
|
||||
/* If we're compiling against Tiger headers we can support direct conversion
|
||||
* to UTF32. If we are then run against a pre-Tiger system, the encoding
|
||||
* won't be available so we'll defer to the string->UTF-16->UTF-32 conversion.
|
||||
*/
|
||||
if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT))
|
||||
{
|
||||
CFRange fullStringRange = CFRangeMake(0, CFStringGetLength(theString));
|
||||
CFIndex usedBufLen;
|
||||
|
||||
CFIndex charsConverted = CFStringGetBytes(
|
||||
theString,
|
||||
fullStringRange,
|
||||
wxCFStringEncodingWcharT,
|
||||
0,
|
||||
false,
|
||||
// if dstSize is 0 then pass NULL to get required length in usedBufLen
|
||||
dstSize != 0?(UInt8*)dst:NULL,
|
||||
dstSize * sizeof(wchar_t),
|
||||
&usedBufLen);
|
||||
|
||||
// charsConverted is > 0 iff conversion succeeded
|
||||
if(charsConverted <= 0)
|
||||
return wxCONV_FAILED;
|
||||
|
||||
/* usedBufLen is the number of bytes written, so we divide by
|
||||
* sizeof(wchar_t) to get the number of elements written.
|
||||
*/
|
||||
wxASSERT( (usedBufLen % sizeof(wchar_t)) == 0 );
|
||||
|
||||
// CFStringGetBytes does exactly the right thing when buffer
|
||||
// pointer is NULL and returns the number of bytes required
|
||||
return usedBufLen / sizeof(wchar_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: Includes NULL iff source did
|
||||
/* NOTE: This is an approximation. The eventual UTF-32 will
|
||||
* possibly have less elements but certainly not more.
|
||||
*/
|
||||
size_t returnSize = CFStringGetLength(theString);
|
||||
|
||||
if (dstSize == 0 || dst == NULL)
|
||||
{
|
||||
return returnSize;
|
||||
}
|
||||
|
||||
// Convert the entire string.. too hard to figure out how many UTF-16 we'd need
|
||||
// for an undersized UTF-32 destination buffer.
|
||||
CFRange fullStringRange = CFRangeMake(0, CFStringGetLength(theString));
|
||||
UniChar *szUniCharBuffer = new UniChar[fullStringRange.length];
|
||||
|
||||
CFStringGetCharacters(theString, fullStringRange, szUniCharBuffer);
|
||||
|
||||
wxMBConvUTF16 converter;
|
||||
returnSize = converter.ToWChar( dst, dstSize, (const char*)szUniCharBuffer, fullStringRange.length );
|
||||
delete [] szUniCharBuffer;
|
||||
|
||||
return returnSize;
|
||||
}
|
||||
// NOTREACHED
|
||||
}
|
||||
|
||||
size_t wxMBConv_cf::FromWChar(char *dst, size_t dstSize, const wchar_t *src, size_t srcSize) const
|
||||
{
|
||||
wxCHECK(src, wxCONV_FAILED);
|
||||
|
||||
if(srcSize == wxNO_LEN)
|
||||
srcSize = wxStrlen(src) + 1;
|
||||
|
||||
// Temporary CFString
|
||||
wxCFRef<CFStringRef> theString;
|
||||
|
||||
/* If we're compiling against Tiger headers we can support direct conversion
|
||||
* from UTF32. If we are then run against a pre-Tiger system, the encoding
|
||||
* won't be available so we'll defer to the UTF-32->UTF-16->string conversion.
|
||||
*/
|
||||
if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT))
|
||||
{
|
||||
theString = wxCFRef<CFStringRef>(CFStringCreateWithBytes(
|
||||
kCFAllocatorDefault,
|
||||
(UInt8*)src,
|
||||
srcSize * sizeof(wchar_t),
|
||||
wxCFStringEncodingWcharT,
|
||||
false));
|
||||
}
|
||||
else
|
||||
{
|
||||
wxMBConvUTF16 converter;
|
||||
size_t cbUniBuffer = converter.FromWChar( NULL, 0, src, srcSize );
|
||||
wxASSERT(cbUniBuffer % sizeof(UniChar));
|
||||
|
||||
// Will be free'd by kCFAllocatorMalloc when CFString is released
|
||||
UniChar *tmpUniBuffer = (UniChar*)malloc(cbUniBuffer);
|
||||
|
||||
cbUniBuffer = converter.FromWChar( (char*) tmpUniBuffer, cbUniBuffer, src, srcSize );
|
||||
wxASSERT(cbUniBuffer % sizeof(UniChar));
|
||||
|
||||
theString = wxCFRef<CFStringRef>(CFStringCreateWithCharactersNoCopy(
|
||||
kCFAllocatorDefault,
|
||||
tmpUniBuffer,
|
||||
cbUniBuffer / sizeof(UniChar),
|
||||
kCFAllocatorMalloc
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
wxCHECK(theString != NULL, wxCONV_FAILED);
|
||||
|
||||
CFIndex usedBufLen;
|
||||
|
||||
CFIndex charsConverted = CFStringGetBytes(
|
||||
theString,
|
||||
CFRangeMake(0, CFStringGetLength(theString)),
|
||||
m_encoding,
|
||||
0, // FAIL on unconvertible characters
|
||||
false, // not an external representation
|
||||
// if dstSize is 0 then pass NULL to get required length in usedBufLen
|
||||
(dstSize != 0)?(UInt8*)dst:NULL,
|
||||
dstSize,
|
||||
&usedBufLen
|
||||
);
|
||||
|
||||
// charsConverted is > 0 iff conversion succeeded
|
||||
if(charsConverted <= 0)
|
||||
return wxCONV_FAILED;
|
||||
|
||||
return usedBufLen;
|
||||
}
|
||||
|
||||
#endif // __DARWIN__
|
||||
|
||||
|
229
src/mac/core/utilsexc_base.cpp
Normal file
229
src/mac/core/utilsexc_base.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: mac/corefoundation/utilsexc_base.cpp
|
||||
// Purpose: wxMacLaunch
|
||||
// Author: Ryan Norton
|
||||
// Modified by:
|
||||
// Created: 2005-06-21
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Ryan Norton
|
||||
// Licence: wxWindows licence
|
||||
// Notes: Source was originally in utilsexc_cf.cpp,1.6 then moved
|
||||
// to totally unrelated hid.cpp,1.8.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//===========================================================================
|
||||
// DECLARATIONS
|
||||
//===========================================================================
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Pre-compiled header stuff
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
// WX includes
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/string.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/wxcrt.h"
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
// Mac Includes
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#ifndef __WXOSX_IPHONE__
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
// More WX Includes
|
||||
#include "wx/filename.h"
|
||||
#include "wx/mac/corefoundation/cfstring.h"
|
||||
|
||||
// Default path style
|
||||
#define kDefaultPathStyle kCFURLPOSIXPathStyle
|
||||
|
||||
//===========================================================================
|
||||
// IMPLEMENTATION
|
||||
//===========================================================================
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//
|
||||
// wxMacLaunch
|
||||
//
|
||||
// argv is the command line split up, with the application path first
|
||||
// flags are the flags from wxExecute
|
||||
// process is the process passed from wxExecute for pipe streams etc.
|
||||
// returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
bool wxMacLaunch(char **argv)
|
||||
{
|
||||
// Obtains the number of arguments for determining the size of
|
||||
// the CFArray used to hold them
|
||||
CFIndex cfiCount = 0;
|
||||
for(char** argvcopy = argv; *argvcopy != NULL ; ++argvcopy)
|
||||
{
|
||||
++cfiCount;
|
||||
}
|
||||
|
||||
// If there is not a single argument then there is no application
|
||||
// to launch
|
||||
if(cfiCount == 0)
|
||||
{
|
||||
wxLogDebug(wxT("wxMacLaunch No file to launch!"));
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Path to bundle
|
||||
wxString path = *argv++;
|
||||
|
||||
// Create a CFURL for the application path
|
||||
// Created this way because we are opening a bundle which is a directory
|
||||
CFURLRef cfurlApp =
|
||||
CFURLCreateWithFileSystemPath(
|
||||
kCFAllocatorDefault,
|
||||
wxCFStringRef(path),
|
||||
kDefaultPathStyle,
|
||||
true); //false == not a directory
|
||||
|
||||
// Check for error from the CFURL
|
||||
if(!cfurlApp)
|
||||
{
|
||||
wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path.c_str());
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Create a CFBundle from the CFURL created earlier
|
||||
CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp);
|
||||
|
||||
// Check to see if CFBundleCreate returned an error,
|
||||
// and if it did this was an invalid bundle or not a bundle
|
||||
// at all (maybe a simple directory etc.)
|
||||
if(!cfbApp)
|
||||
{
|
||||
wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path.c_str());
|
||||
CFRelease(cfurlApp);
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Get the bundle type and make sure its an 'APPL' bundle
|
||||
// Otherwise we're dealing with something else here...
|
||||
UInt32 dwBundleType, dwBundleCreator;
|
||||
CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator);
|
||||
if(dwBundleType != 'APPL')
|
||||
{
|
||||
wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str());
|
||||
CFRelease(cfbApp);
|
||||
CFRelease(cfurlApp);
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Create a CFArray for dealing with the command line
|
||||
// arguments to the bundle
|
||||
CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||
cfiCount-1, &kCFTypeArrayCallBacks);
|
||||
if(!cfaFiles) //This should never happen
|
||||
{
|
||||
wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray"));
|
||||
CFRelease(cfbApp);
|
||||
CFRelease(cfurlApp);
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Loop through command line arguments to the bundle,
|
||||
// turn them into CFURLs and then put them in cfaFiles
|
||||
// For use to launch services call
|
||||
for( ; *argv != NULL ; ++argv)
|
||||
{
|
||||
// Check for '<' as this will ring true for
|
||||
// CFURLCreateWithString but is generally not considered
|
||||
// typical on mac but is usually passed here from wxExecute
|
||||
if (wxStrcmp(*argv, wxT("<")) == 0)
|
||||
continue;
|
||||
|
||||
|
||||
CFURLRef cfurlCurrentFile; // CFURL to hold file path
|
||||
wxFileName argfn(*argv); // Filename for path
|
||||
|
||||
if(argfn.DirExists())
|
||||
{
|
||||
// First, try creating as a directory
|
||||
cfurlCurrentFile = CFURLCreateWithFileSystemPath(
|
||||
kCFAllocatorDefault,
|
||||
wxCFStringRef(*argv),
|
||||
kDefaultPathStyle,
|
||||
true); //true == directory
|
||||
}
|
||||
else if(argfn.FileExists())
|
||||
{
|
||||
// And if it isn't a directory try creating it
|
||||
// as a regular file
|
||||
cfurlCurrentFile = CFURLCreateWithFileSystemPath(
|
||||
kCFAllocatorDefault,
|
||||
wxCFStringRef(*argv),
|
||||
kDefaultPathStyle,
|
||||
false); //false == regular file
|
||||
}
|
||||
else
|
||||
{
|
||||
// Argument did not refer to
|
||||
// an entry in the local filesystem,
|
||||
// so try creating it through CFURLCreateWithString
|
||||
cfurlCurrentFile = CFURLCreateWithString(
|
||||
kCFAllocatorDefault,
|
||||
wxCFStringRef(*argv),
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Continue in the loop if the CFURL could not be created
|
||||
if(!cfurlCurrentFile)
|
||||
{
|
||||
wxLogDebug(
|
||||
wxT("wxMacLaunch Could not create CFURL for argument:%s"),
|
||||
*argv);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the valid CFURL to the argument array and then
|
||||
// release it as the CFArray adds a ref count to it
|
||||
CFArrayAppendValue(
|
||||
cfaFiles,
|
||||
cfurlCurrentFile
|
||||
);
|
||||
CFRelease(cfurlCurrentFile); // array has retained it
|
||||
}
|
||||
|
||||
// Create a LSLaunchURLSpec for use with LSOpenFromURLSpec
|
||||
// Note that there are several flag options (launchFlags) such
|
||||
// as kLSLaunchDontSwitch etc. and maybe we could be more
|
||||
// picky about the flags we choose
|
||||
LSLaunchURLSpec launchspec;
|
||||
launchspec.appURL = cfurlApp;
|
||||
launchspec.itemURLs = cfaFiles;
|
||||
launchspec.passThruParams = NULL; //AEDesc*
|
||||
launchspec.launchFlags = kLSLaunchDefaults;
|
||||
launchspec.asyncRefCon = NULL;
|
||||
|
||||
// Finally, call LSOpenFromURL spec with our arguments
|
||||
// 2nd parameter is a pointer to a CFURL that gets
|
||||
// the actual path launched by the function
|
||||
OSStatus status = LSOpenFromURLSpec(&launchspec, NULL);
|
||||
|
||||
// Cleanup corefoundation references
|
||||
CFRelease(cfbApp);
|
||||
CFRelease(cfurlApp);
|
||||
CFRelease(cfaFiles);
|
||||
|
||||
// Check for error from LSOpenFromURLSpec
|
||||
if(status != noErr)
|
||||
{
|
||||
wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"),
|
||||
(int)status);
|
||||
return false ;
|
||||
}
|
||||
|
||||
// No error from LSOpenFromURLSpec, so app was launched
|
||||
return true ;
|
||||
}
|
||||
|
118
src/mac/core/utilsexc_cf.cpp
Normal file
118
src/mac/core/utilsexc_cf.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/mac/corefoundation/utilsexec_cf.cpp
|
||||
// Purpose: Execution-related utilities for Darwin
|
||||
// Author: David Elliott, Ryan Norton (wxMacExecute)
|
||||
// Modified by: Stefan Csomor (added necessary wxT for unicode builds)
|
||||
// Created: 2004-11-04
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) David Elliott, Ryan Norton
|
||||
// Licence: wxWindows licence
|
||||
// Notes: This code comes from src/mac/carbon/utilsexc.cpp,1.11
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/utils.h"
|
||||
#endif //ndef WX_PRECOMP
|
||||
#include "wx/unix/execute.h"
|
||||
#include "wx/stdpaths.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/apptrait.h"
|
||||
#include "wx/thread.h"
|
||||
#include "wx/process.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <CoreFoundation/CFSocket.h>
|
||||
|
||||
/*!
|
||||
Called due to source signal detected by the CFRunLoop.
|
||||
This is nearly identical to the wxGTK equivalent.
|
||||
*/
|
||||
extern "C" void WXCF_EndProcessDetector(CFSocketRef s,
|
||||
CFSocketCallBackType WXUNUSED(callbackType),
|
||||
CFDataRef WXUNUSED(address),
|
||||
void const *WXUNUSED(data),
|
||||
void *info)
|
||||
{
|
||||
/*
|
||||
Either our pipe was closed or the process ended successfully. Either way,
|
||||
we're done. It's not if waitpid is going to magically succeed when
|
||||
we get fired again. CFSocketInvalidate closes the fd for us and also
|
||||
invalidates the run loop source for us which should cause it to
|
||||
release the CFSocket (thus causing it to be deallocated) and remove
|
||||
itself from the runloop which should release it and cause it to also
|
||||
be deallocated. Of course, it's possible the RunLoop hangs onto
|
||||
one or both of them by retaining/releasing them within its stack
|
||||
frame. However, that shouldn't be depended on. Assume that s is
|
||||
deallocated due to the following call.
|
||||
*/
|
||||
CFSocketInvalidate(s);
|
||||
|
||||
// Now tell wx that the process has ended.
|
||||
wxHandleProcessTermination(static_cast<wxEndProcessData *>(info));
|
||||
}
|
||||
|
||||
/*!
|
||||
Implements the GUI-specific AddProcessCallback() for both wxMac and
|
||||
wxCocoa using the CFSocket/CFRunLoop API which is available to both.
|
||||
Takes advantage of the fact that sockets on UNIX are just regular
|
||||
file descriptors and thus even a non-socket file descriptor can
|
||||
apparently be used with CFSocket so long as you only tell CFSocket
|
||||
to do things with it that would be valid for a non-socket fd.
|
||||
*/
|
||||
int wxGUIAppTraits::AddProcessCallback(wxEndProcessData *proc_data, int fd)
|
||||
{
|
||||
static int s_last_tag = 0;
|
||||
CFSocketContext context =
|
||||
{ 0
|
||||
, static_cast<void*>(proc_data)
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
};
|
||||
CFSocketRef cfSocket = CFSocketCreateWithNative(kCFAllocatorDefault,fd,kCFSocketReadCallBack,&WXCF_EndProcessDetector,&context);
|
||||
if(cfSocket == NULL)
|
||||
{
|
||||
wxLogError(wxT("Failed to create socket for end process detection"));
|
||||
return 0;
|
||||
}
|
||||
CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, cfSocket, /*highest priority:*/0);
|
||||
if(runLoopSource == NULL)
|
||||
{
|
||||
wxLogError(wxT("Failed to create CFRunLoopSource from CFSocket for end process detection"));
|
||||
// closes the fd.. we can't really stop it, nor do we necessarily want to.
|
||||
CFSocketInvalidate(cfSocket);
|
||||
CFRelease(cfSocket);
|
||||
return 0;
|
||||
}
|
||||
// Now that the run loop source has the socket retained and we no longer
|
||||
// need to refer to it within this method, we can release it.
|
||||
CFRelease(cfSocket);
|
||||
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
|
||||
// Now that the run loop has the source retained we can release it.
|
||||
CFRelease(runLoopSource);
|
||||
|
||||
/*
|
||||
Feed wx some bullshit.. we don't use it since CFSocket helpfully passes
|
||||
itself into our callback and that's enough to be able to
|
||||
CFSocketInvalidate it which is all we need to do to get everything we
|
||||
just created to be deallocated.
|
||||
*/
|
||||
return ++s_last_tag;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// NOTE: This doesn't really belong here but this was a handy file to
|
||||
// put it in because it's already compiled for wxCocoa and wxMac GUI lib.
|
||||
#if wxUSE_STDPATHS
|
||||
static wxStandardPathsCF gs_stdPaths;
|
||||
wxStandardPathsBase& wxGUIAppTraits::GetStandardPaths()
|
||||
{
|
||||
return gs_stdPaths;
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user