summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewermacosx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewermacosx.cpp')
-rw-r--r--indra/newview/llappviewermacosx.cpp388
1 files changed, 388 insertions, 0 deletions
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
new file mode 100644
index 0000000000..63e7a6b129
--- /dev/null
+++ b/indra/newview/llappviewermacosx.cpp
@@ -0,0 +1,388 @@
+/**
+ * @file llappviewermacosx.cpp
+ * @brief The LLAppViewerWin32 class definitions
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#if !defined LL_DARWIN
+ #error "Use only with Mac OS X"
+#endif
+
+#include "llappviewermacosx.h"
+#include "llmemtype.h"
+
+#include "llviewernetwork.h"
+#include "llmd5.h"
+#include "llurlsimstring.h"
+#include "llfloaterworldmap.h"
+#include <Carbon/Carbon.h>
+
+
+int main( int argc, char **argv )
+{
+ LLMemType mt1(LLMemType::MTYPE_STARTUP);
+
+#if LL_SOLARIS && defined(__sparc)
+ asm ("ta\t6"); // NOTE: Make sure memory alignment is enforced on SPARC
+#endif
+
+ // Set the working dir to <bundle>/Contents/Resources
+ (void) chdir(gDirUtilp->getAppRODataDir().c_str());
+
+ LLAppViewerMacOSX* viewer_app_ptr = new LLAppViewerMacOSX();
+
+ viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
+
+ bool ok = viewer_app_ptr->tempStoreCommandOptions(argc, argv);
+ if(!ok)
+ {
+ llwarns << "Unable to parse command line." << llendl;
+ return -1;
+ }
+
+ ok = viewer_app_ptr->init();
+ if(!ok)
+ {
+ llwarns << "Application init failed." << llendl;
+ return -1;
+ }
+
+ // Run the application main loop
+ if(!LLApp::isQuitting())
+ {
+ viewer_app_ptr->mainLoop();
+ }
+
+ if (!LLApp::isError())
+ {
+ //
+ // We don't want to do cleanup here if the error handler got called -
+ // the assumption is that the error handler is responsible for doing
+ // app cleanup if there was a problem.
+ //
+ viewer_app_ptr->cleanup();
+ }
+ delete viewer_app_ptr;
+ viewer_app_ptr = NULL;
+ return 0;
+}
+
+LLAppViewerMacOSX::LLAppViewerMacOSX()
+{
+}
+
+LLAppViewerMacOSX::~LLAppViewerMacOSX()
+{
+}
+
+bool LLAppViewerMacOSX::init()
+{
+ return LLAppViewer::init();
+}
+
+void LLAppViewerMacOSX::handleCrashReporting()
+{
+ // Macintosh
+ LLString command_str;
+ command_str = "crashreporter.app/Contents/MacOS/crashreporter ";
+ command_str += "-user ";
+ command_str += gGridName;
+ command_str += " &"; // This backgrounds the command so system() doesn't block until the crashreporter exits.
+ system(command_str.c_str()); /* Flawfinder: ignore */
+
+ // Sometimes signals don't seem to quit the viewer.
+ // Make sure we exit so as to not totally confuse the user.
+ exit(1);
+}
+
+std::string LLAppViewerMacOSX::generateSerialNumber()
+{
+ char serial_md5[MD5HEX_STR_SIZE]; // Flawfinder: ignore
+ serial_md5[0] = 0;
+
+ // JC: Sample code from http://developer.apple.com/technotes/tn/tn1103.html
+ CFStringRef serialNumber = NULL;
+ io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
+ IOServiceMatching("IOPlatformExpertDevice"));
+ if (platformExpert) {
+ serialNumber = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert,
+ CFSTR(kIOPlatformSerialNumberKey),
+ kCFAllocatorDefault, 0);
+ IOObjectRelease(platformExpert);
+ }
+
+ if (serialNumber)
+ {
+ char buffer[MAX_STRING]; // Flawfinder: ignore
+ if (CFStringGetCString(serialNumber, buffer, MAX_STRING, kCFStringEncodingASCII))
+ {
+ LLMD5 md5( (unsigned char*)buffer );
+ md5.hex_digest(serial_md5);
+ }
+ CFRelease(serialNumber);
+ }
+
+ return serial_md5;
+}
+
+OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
+{
+ OSErr result = noErr;
+ DescType actualType;
+ char buffer[1024]; // Flawfinder: ignore
+ Size size;
+
+ result = AEGetParamPtr (
+ messagein,
+ keyDirectObject,
+ typeCString,
+ &actualType,
+ (Ptr)buffer,
+ sizeof(buffer),
+ &size);
+
+ if(result == noErr)
+ {
+ // Got the URL out of the event.
+ // secondlife://
+
+ // Parse it and stash in globals.
+ LLURLSimString::setString(buffer);
+
+ if(gFloaterWorldMap != NULL)
+ {
+ // If the viewer's already logged in, pass it along directly.
+ if (LLURLSimString::parse())
+ {
+ gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName,
+ LLURLSimString::sInstance.mX,
+ LLURLSimString::sInstance.mY,
+ LLURLSimString::sInstance.mZ);
+ LLFloaterWorldMap::show(NULL, TRUE);
+ }
+ }
+ }
+
+ return(result);
+}
+
+OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
+{
+ OSErr result = noErr;
+
+ LLAppViewer::instance()->userQuit();
+
+ return(result);
+}
+
+OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
+{
+ OSStatus result = eventNotHandledErr;
+ OSStatus err;
+ UInt32 evtClass = GetEventClass(event);
+ UInt32 evtKind = GetEventKind(event);
+ WindowRef window = (WindowRef)userdata;
+
+ if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
+ {
+ HICommand cmd;
+ err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
+
+ if(err == noErr)
+ {
+ switch(cmd.commandID)
+ {
+ case kHICommandOK:
+ QuitAppModalLoopForWindow(window);
+ result = noErr;
+ break;
+
+ case kHICommandCancel:
+ QuitAppModalLoopForWindow(window);
+ result = userCanceledErr;
+ break;
+ }
+ }
+ }
+
+ return(result);
+}
+
+OSStatus DisplayReleaseNotes(void)
+{
+ OSStatus err;
+ IBNibRef nib = NULL;
+ WindowRef window = NULL;
+
+ err = CreateNibReference(CFSTR("SecondLife"), &nib);
+
+ if(err == noErr)
+ {
+ CreateWindowFromNib(nib, CFSTR("Release Notes"), &window);
+ }
+
+ if(err == noErr)
+ {
+ // Get the text view control
+ HIViewRef textView;
+ ControlID id;
+
+ id.signature = 'text';
+ id.id = 0;
+
+ LLString releaseNotesText;
+
+ _read_file_into_string(releaseNotesText, "releasenotes.txt"); // Flawfinder: ignore
+
+ err = HIViewFindByID(HIViewGetRoot(window), id, &textView);
+
+ if(err == noErr)
+ {
+ // Convert from the encoding used in the release notes.
+ CFStringRef str = CFStringCreateWithBytes(
+ NULL,
+ (const UInt8*)releaseNotesText.c_str(),
+ releaseNotesText.size(),
+ kCFStringEncodingWindowsLatin1, // This matches the way the Windows version displays the release notes.
+ FALSE);
+
+ if(str != NULL)
+ {
+ int size = CFStringGetLength(str);
+
+ if(size > 0)
+ {
+ UniChar *chars = new UniChar[size + 1];
+ CFStringGetCharacters(str, CFRangeMake(0, size), chars);
+
+ err = TXNSetData(HITextViewGetTXNObject(textView), kTXNUnicodeTextData, chars, size * sizeof(UniChar), kTXNStartOffset, kTXNStartOffset);
+
+ delete[] chars;
+ }
+
+ CFRelease(str);
+ }
+ else
+ {
+ // Creating the string failed. Probably an encoding problem. Display SOMETHING...
+ err = TXNSetData(HITextViewGetTXNObject(textView), kTXNTextData, releaseNotesText.c_str(), releaseNotesText.size(), kTXNStartOffset, kTXNStartOffset);
+ }
+ }
+
+ // Set the selection to the beginning of the text and scroll it into view.
+ if(err == noErr)
+ {
+ err = TXNSetSelection(HITextViewGetTXNObject(textView), kTXNStartOffset, kTXNStartOffset);
+ }
+
+ if(err == noErr)
+ {
+ // This function returns void.
+ TXNShowSelection(HITextViewGetTXNObject(textView), false);
+ }
+ }
+
+ if(err == noErr)
+ {
+ ShowWindow(window);
+ }
+
+ if(err == noErr)
+ {
+ // Set up an event handler for the window.
+ EventHandlerRef handler = NULL;
+ EventTypeSpec handlerEvents[] =
+ {
+ { kEventClassCommand, kEventCommandProcess }
+ };
+
+ InstallWindowEventHandler(
+ window,
+ NewEventHandlerUPP(simpleDialogHandler),
+ GetEventTypeCount (handlerEvents),
+ handlerEvents,
+ (void*)window,
+ &handler);
+ }
+
+ if(err == noErr)
+ {
+ RunAppModalLoopForWindow(window);
+ }
+
+ if(window != NULL)
+ {
+ DisposeWindow(window);
+ }
+
+ if(nib != NULL)
+ {
+ DisposeNibReference(nib);
+ }
+
+ return(err);
+}
+
+void init_apple_menu(const char* product)
+{
+ // Load up a proper menu bar.
+ {
+ OSStatus err;
+ IBNibRef nib = NULL;
+ // NOTE: DO NOT translate or brand this string. It's an internal name in the .nib file, and MUST match exactly.
+ err = CreateNibReference(CFSTR("SecondLife"), &nib);
+
+ if(err == noErr)
+ {
+ // NOTE: DO NOT translate or brand this string. It's an internal name in the .nib file, and MUST match exactly.
+ SetMenuBarFromNib(nib, CFSTR("MenuBar"));
+ }
+
+ if(nib != NULL)
+ {
+ DisposeNibReference(nib);
+ }
+ }
+
+ // Install a handler for 'gurl' AppleEvents. This is how secondlife:// URLs get passed to the viewer.
+
+ if(AEInstallEventHandler('GURL', 'GURL', NewAEEventHandlerUPP(AEGURLHandler),0, false) != noErr)
+ {
+ // Couldn't install AppleEvent handler. This error shouldn't be fatal.
+ llinfos << "Couldn't install 'GURL' AppleEvent handler. Continuing..." << llendl;
+ }
+
+ // Install a handler for 'quit' AppleEvents. This makes quitting the application from the dock work.
+ if(AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(AEQuitHandler),0, false) != noErr)
+ {
+ // Couldn't install AppleEvent handler. This error shouldn't be fatal.
+ llinfos << "Couldn't install Quit AppleEvent handler. Continuing..." << llendl;
+ }
+}