diff --git a/widget/src/mac/nsClipboard.cpp b/widget/src/mac/nsClipboard.cpp index 0458fab963b..55e0f4cdb4b 100644 --- a/widget/src/mac/nsClipboard.cpp +++ b/widget/src/mac/nsClipboard.cpp @@ -68,11 +68,16 @@ #include "nsStylClipboardUtils.h" #include "nsLinebreakConverter.h" #include "nsAutoPtr.h" +#include "nsIServiceManager.h" +#include "nsIMacUtils.h" #include #include #include +static const PRUint32 kPrivateFlavorMask = 0xffff0000; +static const PRUint32 kPrivateFlavorTag = 'MZ..' & kPrivateFlavorMask; + // @@ -330,10 +335,30 @@ nsresult nsClipboard :: PutOnClipboard ( ResType inFlavor, const void* inData, PRInt32 inLen ) { nsresult errCode = NS_OK; + + void* data = (void*) inData; + if ((inFlavor & kPrivateFlavorMask) == kPrivateFlavorTag) { + // Byte-swap private flavors if running translated + nsCOMPtr macUtils = + do_GetService("@mozilla.org/xpcom/mac-utils;1"); + PRBool isTranslated; + if (macUtils && + NS_SUCCEEDED(macUtils->GetIsTranslated(&isTranslated)) && + isTranslated) { + data = nsMemory::Alloc(inLen); + if (!data) + return NS_ERROR_OUT_OF_MEMORY; + + swab(inData, data, inLen); + } + } ScrapRef scrap; ::GetCurrentScrap(&scrap); - ::PutScrapFlavor( scrap, inFlavor, kScrapFlavorMaskNone, inLen, inData ); + ::PutScrapFlavor( scrap, inFlavor, kScrapFlavorMaskNone, inLen, data ); + + if (data != inData) + nsMemory::Free(data); return errCode; @@ -557,6 +582,26 @@ nsClipboard :: GetDataOffClipboard ( ResType inMacFlavor, void** outData, PRInt3 return NS_ERROR_FAILURE; } + if ((inMacFlavor & kPrivateFlavorMask) == kPrivateFlavorTag) { + // Byte-swap private flavors if running translated + nsCOMPtr macUtils = + do_GetService("@mozilla.org/xpcom/mac-utils;1"); + PRBool isTranslated; + if (macUtils && + NS_SUCCEEDED(macUtils->GetIsTranslated(&isTranslated)) && + isTranslated) { + char* swappedData = (char*) nsMemory::Alloc(dataSize); + if (!swappedData) { + nsMemory::Free(dataBuff); + return NS_ERROR_OUT_OF_MEMORY; + } + + swab(dataBuff, swappedData, dataSize); + nsMemory::Free(dataBuff); + dataBuff = swappedData; + } + } + // put it into the transferable if ( outDataSize ) *outDataSize = dataSize; diff --git a/widget/src/mac/nsDragService.cpp b/widget/src/mac/nsDragService.cpp index b7bcd12acc0..ebbd5dea56a 100644 --- a/widget/src/mac/nsDragService.cpp +++ b/widget/src/mac/nsDragService.cpp @@ -60,6 +60,7 @@ #include "nsCRT.h" #include "nsPrimitiveHelpers.h" #include "nsLinebreakConverter.h" +#include "nsIMacUtils.h" #include "nsIContent.h" #include "nsIDOMNode.h" @@ -104,6 +105,9 @@ GetPrimaryFrameFor(nsIContent* aContent) return result; } +static const PRUint32 kPrivateFlavorMask = 0xffff0000; +static const PRUint32 kPrivateFlavorTag = 'MZ..' & kPrivateFlavorMask; + static void SetPortToKnownGoodPort() @@ -793,6 +797,26 @@ nsDragService::DragSendDataProc(FlavorType inFlavor, void* inRefCon, ItemReferen PRUint32 dataSize = 0; retVal = dragService->GetDataForFlavor(dragService->mDataItems, inDragRef, inItemRef, inFlavor, &data, &dataSize); if ( retVal == noErr ) { + if ((inFlavor & kPrivateFlavorMask) == kPrivateFlavorTag) { + // Byte-swap private flavors if running translated + nsCOMPtr macUtils = + do_GetService("@mozilla.org/xpcom/mac-utils;1"); + PRBool isTranslated; + if (macUtils && + NS_SUCCEEDED(macUtils->GetIsTranslated(&isTranslated)) && + isTranslated) { + char* swappedData = (char*) nsMemory::Alloc(dataSize); + if (!swappedData) { + nsMemory::Free(data); + return notEnoughMemoryErr; + } + else { + swab(data, swappedData, dataSize); + nsMemory::Free(data); + data = swappedData; + } + } + } // make the data accessible to the DragManager retVal = ::SetDragItemFlavorData ( inDragRef, inItemRef, inFlavor, data, dataSize, 0 ); NS_ASSERTION ( retVal == noErr, "SDIFD failed in DragSendDataProc" ); @@ -1095,7 +1119,27 @@ nsDragService::ExtractDataFromOS ( DragReference inDragRef, ItemReference inItem buff = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(buffSize + 1)); if ( buff ) { err = ::GetFlavorData ( inDragRef, inItemRef, inFlavor, buff, &buffSize, 0 ); - if ( err ) { + if (err == noErr) { + if ((inFlavor & kPrivateFlavorMask) == kPrivateFlavorTag) { + // Byte-swap private flavors if running translated + nsCOMPtr macUtils = + do_GetService("@mozilla.org/xpcom/mac-utils;1"); + PRBool isTranslated; + if (macUtils && + NS_SUCCEEDED(macUtils->GetIsTranslated(&isTranslated)) && + isTranslated) { + char* swappedData = (char*) nsMemory::Alloc(buffSize); + if (!swappedData) + retval = NS_ERROR_OUT_OF_MEMORY; + else { + swab(buff, swappedData, buffSize); + nsMemory::Free(buff); + buff = swappedData; + } + } + } + } + else { #ifdef NS_DEBUG printf("nsDragService: Error getting data out of drag manager, #%d\n", err); #endif diff --git a/xpcom/base/nsIMacUtils.idl b/xpcom/base/nsIMacUtils.idl index e0ae0991e4b..5c5fe56699d 100644 --- a/xpcom/base/nsIMacUtils.idl +++ b/xpcom/base/nsIMacUtils.idl @@ -41,7 +41,7 @@ * nsIMacUtils: Generic globally-available Mac-specific utilities. */ -[scriptable, uuid(59BE3453-873B-450D-8DB8-2643E08A00BE)] +[scriptable, uuid(F6FC107C-5CBA-4C5C-A35E-B69D580D1DB6)] interface nsIMacUtils : nsISupports { /** @@ -49,4 +49,9 @@ interface nsIMacUtils : nsISupports * ppc and x86 (universal binary). */ readonly attribute boolean isUniversalBinary; + + /** + * True when running under binary translation (Rosetta). + */ + readonly attribute boolean isTranslated; }; diff --git a/xpcom/base/nsMacUtilsImpl.cpp b/xpcom/base/nsMacUtilsImpl.cpp index 0a6c0f00aee..8eead37b9c6 100644 --- a/xpcom/base/nsMacUtilsImpl.cpp +++ b/xpcom/base/nsMacUtilsImpl.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include NS_IMPL_ISUPPORTS1(nsMacUtilsImpl, nsIMacUtils) @@ -123,3 +124,31 @@ done: return NS_OK; } + +/* readonly attribute boolean isTranslated; */ +// True when running under binary translation (Rosetta). +NS_IMETHODIMP nsMacUtilsImpl::GetIsTranslated(PRBool *aIsTranslated) +{ +#ifdef __ppc__ + static PRBool sInitialized = PR_FALSE; + + // Initialize sIsNative to 1. If the sysctl fails because it doesn't + // exist, then translation is not possible, so the process must not be + // running translated. + static PRInt32 sIsNative = 1; + + if (!sInitialized) { + size_t sz = sizeof(sIsNative); + sysctlbyname("sysctl.proc_native", &sIsNative, &sz, NULL, 0); + sInitialized = PR_TRUE; + } + + *aIsTranslated = !sIsNative; +#else + // Translation only exists for ppc code. Other architectures aren't + // translated. + *aIsTranslated = PR_FALSE; +#endif + + return NS_OK; +}