merge changes for 3.6.5-release
commit
c4b070ae00
3
.hgtags
3
.hgtags
|
|
@ -56,11 +56,11 @@ a82e5b1e22c7f90e3c7977d146b80588f004ed0d 2.5.0-start
|
|||
54d772d8687c69b1d773f6ce14bbc7bdc9d6c05f 2.5.0-beta2
|
||||
54d772d8687c69b1d773f6ce14bbc7bdc9d6c05f DRTVWR-33--2.5.0beta2
|
||||
54d772d8687c69b1d773f6ce14bbc7bdc9d6c05f DRTVWR-33_2.5.0-beta2
|
||||
b542f8134a2bb5dd054ff4e509a44b2ee463b1bf nat-eventapi2-base
|
||||
b723921b5c711bd24dbe77dc76ef488b544dac78 2.5.0-beta3
|
||||
b723921b5c711bd24dbe77dc76ef488b544dac78 2.5.0-release
|
||||
b723921b5c711bd24dbe77dc76ef488b544dac78 DRTVWR-31_2.5.0-release
|
||||
b723921b5c711bd24dbe77dc76ef488b544dac78 DRTVWR-34_2.5.0-beta3
|
||||
b542f8134a2bb5dd054ff4e509a44b2ee463b1bf nat-eventapi2-base
|
||||
63a6aedfce785a6c760377bf685b2dae616797d2 2.5.1-start
|
||||
4dede9ae1ec74d41f6887719f6f1de7340d8578d 2.5.1-release
|
||||
4dede9ae1ec74d41f6887719f6f1de7340d8578d DRTVWR-37_2.5.1-release
|
||||
|
|
@ -464,3 +464,4 @@ f6741d5fe8d632651424484df0fe0cb4a01e9fbe 3.6.2-release
|
|||
fe4f7c5e9fd27e09d03deb1cc9ab3e5093f6309e 3.6.3-release
|
||||
83357f31d8dbf048a8bfdc323f363bf4d588aca1 CHOP-951-a
|
||||
91ed595b716f14f07409595b734fda891a59379e 3.6.4-release
|
||||
bf6d453046011a11de2643fac610cc5258650f82 3.6.5-release
|
||||
|
|
|
|||
|
|
@ -689,6 +689,8 @@ Kaimen Takahe
|
|||
Katharine Berry
|
||||
STORM-1900
|
||||
OPEN-149
|
||||
STORM-1940
|
||||
STORM-1941
|
||||
Keklily Longfall
|
||||
Ken Lavender
|
||||
Ken March
|
||||
|
|
|
|||
|
|
@ -134,15 +134,20 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
|||
OUTPUT_VARIABLE XCODE_VERSION )
|
||||
|
||||
# To support a different SDK update these Xcode settings:
|
||||
if (XCODE_VERSION GREATER 4.5)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
|
||||
set(CMAKE_OSX_SYSROOT macosx10.8)
|
||||
else (XCODE_VERSION GREATER 4.5)
|
||||
if (XCODE_VERSION GREATER 4.2)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
set(CMAKE_OSX_SYSROOT macosx10.7)
|
||||
else (XCODE_VERSION GREATER 4.2)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
set(CMAKE_OSX_SYSROOT macosx10.7)
|
||||
endif (XCODE_VERSION GREATER 4.2)
|
||||
endif (XCODE_VERSION GREATER 4.5)
|
||||
|
||||
set(CMAKE_OSX_SYSROOT macosx10.6)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
|
||||
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
|
||||
|
||||
# NOTE: To attempt an i386/PPC Universal build, add this on the configure line:
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ add_executable(llui_libtest ${llui_libtest_SOURCE_FILES})
|
|||
# Link with OS-specific libraries for LLWindow dependency
|
||||
if (DARWIN)
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
set(OS_LIBRARIES ${COCOA_LIBRARY})
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
set(OS_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY})
|
||||
elseif (WINDOWS)
|
||||
#ll_stack_trace needs this now...
|
||||
list(APPEND WINDOWS_LIBRARIES dbghelp)
|
||||
|
|
|
|||
|
|
@ -67,12 +67,18 @@ using namespace llsd;
|
|||
# include <sys/sysctl.h>
|
||||
# include <sys/utsname.h>
|
||||
# include <stdint.h>
|
||||
# include <Carbon/Carbon.h>
|
||||
# include <CoreServices/CoreServices.h>
|
||||
# include <stdexcept>
|
||||
# include <mach/host_info.h>
|
||||
# include <mach/mach_host.h>
|
||||
# include <mach/task.h>
|
||||
# include <mach/task_info.h>
|
||||
|
||||
// disable warnings about Gestalt calls being deprecated
|
||||
// until Apple get's on the ball and provides an alternative
|
||||
//
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#elif LL_LINUX
|
||||
# include <errno.h>
|
||||
# include <sys/utsname.h>
|
||||
|
|
@ -1502,3 +1508,10 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
|
|||
if (dst != NULL) gzclose(dst);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if LL_DARWIN
|
||||
// disable warnings about Gestalt calls being deprecated
|
||||
// until Apple get's on the ball and provides an alternative
|
||||
//
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* @file llversionviewer.h
|
||||
* @brief
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLVERSIONVIEWER_H
|
||||
#define LL_LLVERSIONVIEWER_H
|
||||
|
||||
const S32 LL_VERSION_MAJOR = 3;
|
||||
const S32 LL_VERSION_MINOR = 4;
|
||||
const S32 LL_VERSION_PATCH = 6;
|
||||
const S32 LL_VERSION_BUILD = 0;
|
||||
|
||||
const char * const LL_CHANNEL = "Second Life Developer";
|
||||
|
||||
#if LL_DARWIN
|
||||
const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer";
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1009,12 +1009,7 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
|
|||
}
|
||||
#endif
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED <= 1070
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <AGL/gl.h>
|
||||
#endif
|
||||
|
||||
|
||||
#endif // LL_MESA / LL_WINDOWS / LL_DARWIN
|
||||
|
||||
|
|
|
|||
|
|
@ -252,12 +252,15 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
|||
mTex.push_back(tex);
|
||||
mInternalFormat.push_back(color_fmt);
|
||||
|
||||
#if !LL_DARWIN
|
||||
if (gDebugGL)
|
||||
{ //bind and unbind to validate target
|
||||
bindTarget();
|
||||
flush();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,11 +109,14 @@ if (DARWIN)
|
|||
llkeyboardmacosx.cpp
|
||||
llwindowmacosx.cpp
|
||||
llwindowmacosx-objc.mm
|
||||
llopenglview-objc.mm
|
||||
)
|
||||
list(APPEND llwindow_HEADER_FILES
|
||||
llkeyboardmacosx.h
|
||||
llwindowmacosx.h
|
||||
llwindowmacosx-objc.h
|
||||
llopenglview-objc.h
|
||||
llappdelegate-objc.h
|
||||
)
|
||||
|
||||
# We use a bunch of deprecated system APIs.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* @file llappdelegate-objc.h
|
||||
* @brief Class interface for the Mac version's application delegate.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "llopenglview-objc.h"
|
||||
|
||||
@interface LLAppDelegate : NSObject <NSApplicationDelegate> {
|
||||
LLNSWindow *window;
|
||||
NSWindow *inputWindow;
|
||||
LLNonInlineTextView *inputView;
|
||||
NSTimer *frameTimer;
|
||||
NSString *currentInputLanguage;
|
||||
}
|
||||
|
||||
@property (assign) IBOutlet LLNSWindow *window;
|
||||
@property (assign) IBOutlet NSWindow *inputWindow;
|
||||
@property (assign) IBOutlet LLNonInlineTextView *inputView;
|
||||
|
||||
@property (retain) NSString *currentInputLanguage;
|
||||
|
||||
- (void) mainLoop;
|
||||
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
|
||||
- (void) languageUpdated;
|
||||
- (bool) romanScript;
|
||||
@end
|
||||
|
|
@ -82,6 +82,11 @@ public:
|
|||
|
||||
virtual BOOL handleKeyUp(const U16 key, MASK mask) = 0;
|
||||
virtual BOOL handleKeyDown(const U16 key, MASK mask) = 0;
|
||||
|
||||
#ifdef LL_DARWIN
|
||||
// We only actually use this for OS X.
|
||||
virtual void handleModifier(MASK mask) = 0;
|
||||
#endif // LL_DARWIN
|
||||
|
||||
// Asynchronously poll the control, alt, and shift keys and set the
|
||||
// appropriate internal key masks.
|
||||
|
|
|
|||
|
|
@ -45,6 +45,13 @@ BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask)
|
|||
MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event)
|
||||
{ return MASK_NONE; }
|
||||
|
||||
#ifdef LL_DARWIN
|
||||
void LLKeyboardHeadless::handleModifier(MASK mask)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void LLKeyboardHeadless::scanKeyboard()
|
||||
{
|
||||
for (S32 key = 0; key < KEY_COUNT; key++)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ public:
|
|||
/*virtual*/ void resetMaskKeys();
|
||||
/*virtual*/ MASK currentMask(BOOL for_mouse_event);
|
||||
/*virtual*/ void scanKeyboard();
|
||||
#ifdef LL_DARWIN
|
||||
/*virtual*/ void handleModifier(MASK mask);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "llkeyboardmacosx.h"
|
||||
#include "llwindowcallbacks.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include "llwindowmacosx-objc.h"
|
||||
|
||||
LLKeyboardMacOSX::LLKeyboardMacOSX()
|
||||
{
|
||||
|
|
@ -162,23 +162,25 @@ LLKeyboardMacOSX::LLKeyboardMacOSX()
|
|||
|
||||
void LLKeyboardMacOSX::resetMaskKeys()
|
||||
{
|
||||
U32 mask = GetCurrentEventKeyModifiers();
|
||||
U32 mask = getModifiers();
|
||||
|
||||
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
|
||||
// It looks a bit suspicious, as it won't correct for keys that have been released.
|
||||
// Is this the way it's supposed to work?
|
||||
|
||||
// We apply the modifier masks directly within getModifiers. So check to see which masks we've applied.
|
||||
|
||||
if(mask & shiftKey)
|
||||
if(mask & MAC_SHIFT_KEY)
|
||||
{
|
||||
mKeyLevel[KEY_SHIFT] = TRUE;
|
||||
}
|
||||
|
||||
if(mask & (controlKey))
|
||||
if(mask & MAC_CTRL_KEY)
|
||||
{
|
||||
mKeyLevel[KEY_CONTROL] = TRUE;
|
||||
}
|
||||
|
||||
if(mask & optionKey)
|
||||
if(mask & MAC_ALT_KEY)
|
||||
{
|
||||
mKeyLevel[KEY_ALT] = TRUE;
|
||||
}
|
||||
|
|
@ -196,22 +198,27 @@ static BOOL translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &out
|
|||
}
|
||||
*/
|
||||
|
||||
void LLKeyboardMacOSX::handleModifier(MASK mask)
|
||||
{
|
||||
updateModifiers(mask);
|
||||
}
|
||||
|
||||
MASK LLKeyboardMacOSX::updateModifiers(const U32 mask)
|
||||
{
|
||||
// translate the mask
|
||||
MASK out_mask = 0;
|
||||
|
||||
if(mask & shiftKey)
|
||||
if(mask & MAC_SHIFT_KEY)
|
||||
{
|
||||
out_mask |= MASK_SHIFT;
|
||||
}
|
||||
|
||||
if(mask & (controlKey | cmdKey))
|
||||
if(mask & (MAC_CTRL_KEY | MAC_CMD_KEY))
|
||||
{
|
||||
out_mask |= MASK_CONTROL;
|
||||
}
|
||||
|
||||
if(mask & optionKey)
|
||||
if(mask & MAC_ALT_KEY)
|
||||
{
|
||||
out_mask |= MASK_ALT;
|
||||
}
|
||||
|
|
@ -231,7 +238,7 @@ BOOL LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask)
|
|||
{
|
||||
handled = handleTranslatedKeyDown(translated_key, translated_mask);
|
||||
}
|
||||
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
|
@ -255,18 +262,18 @@ BOOL LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask)
|
|||
MASK LLKeyboardMacOSX::currentMask(BOOL for_mouse_event)
|
||||
{
|
||||
MASK result = MASK_NONE;
|
||||
U32 mask = GetCurrentEventKeyModifiers();
|
||||
U32 mask = getModifiers();
|
||||
|
||||
if (mask & shiftKey) result |= MASK_SHIFT;
|
||||
if (mask & controlKey) result |= MASK_CONTROL;
|
||||
if (mask & optionKey) result |= MASK_ALT;
|
||||
if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT;
|
||||
if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL;
|
||||
if (mask & MAC_ALT_KEY) result |= MASK_ALT;
|
||||
|
||||
// For keyboard events, consider Command equivalent to Control
|
||||
if (!for_mouse_event)
|
||||
{
|
||||
if (mask & cmdKey) result |= MASK_CONTROL;
|
||||
if (mask & MAC_CMD_KEY) result |= MASK_CONTROL;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,15 @@
|
|||
|
||||
#include "llkeyboard.h"
|
||||
|
||||
// These more or less mirror their equivalents in NSEvent.h.
|
||||
enum EMacEventKeys {
|
||||
MAC_SHIFT_KEY = 1 << 17,
|
||||
MAC_CTRL_KEY = 1 << 18,
|
||||
MAC_ALT_KEY = 1 << 19,
|
||||
MAC_CMD_KEY = 1 << 20,
|
||||
MAC_FN_KEY = 1 << 23
|
||||
};
|
||||
|
||||
class LLKeyboardMacOSX : public LLKeyboard
|
||||
{
|
||||
public:
|
||||
|
|
@ -40,6 +49,7 @@ public:
|
|||
/*virtual*/ void resetMaskKeys();
|
||||
/*virtual*/ MASK currentMask(BOOL for_mouse_event);
|
||||
/*virtual*/ void scanKeyboard();
|
||||
/*virtual*/ void handleModifier(MASK mask);
|
||||
|
||||
protected:
|
||||
MASK updateModifiers(const U32 mask);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* @file llopenglview-objc.h
|
||||
* @brief Class interfaces for most of the Mac facing window functionality.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLOpenGLView_H
|
||||
#define LLOpenGLView_H
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <IOKit/IOKitLib.h>
|
||||
#import <CoreFoundation/CFBase.h>
|
||||
#import <CoreFoundation/CFNumber.h>
|
||||
#include <string>
|
||||
|
||||
@interface LLOpenGLView : NSOpenGLView <NSTextInputClient>
|
||||
{
|
||||
std::string mLastDraggedUrl;
|
||||
unsigned int mModifiers;
|
||||
float mMousePos[2];
|
||||
bool mHasMarkedText;
|
||||
unsigned int mMarkedTextLength;
|
||||
bool mMarkedTextAllowed;
|
||||
bool mSimulatedRightClick;
|
||||
}
|
||||
- (id) initWithSamples:(NSUInteger)samples;
|
||||
- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync;
|
||||
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync;
|
||||
|
||||
- (void)commitCurrentPreedit;
|
||||
|
||||
// rebuildContext
|
||||
// Destroys and recreates a context with the view's internal format set via setPixelFormat;
|
||||
// Use this in event of needing to rebuild a context for whatever reason, without needing to assign a new pixel format.
|
||||
- (BOOL) rebuildContext;
|
||||
|
||||
// rebuildContextWithFormat
|
||||
// Destroys and recreates a context with the specified pixel format.
|
||||
- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format;
|
||||
|
||||
// These are mostly just for C++ <-> Obj-C interop. We can manipulate the CGLContext from C++ without reprecussions.
|
||||
- (CGLContextObj) getCGLContextObj;
|
||||
- (CGLPixelFormatObj*)getCGLPixelFormatObj;
|
||||
|
||||
- (unsigned long) getVramSize;
|
||||
|
||||
- (void) allowMarkedTextInput:(bool)allowed;
|
||||
|
||||
@end
|
||||
|
||||
@interface LLUserInputWindow : NSPanel
|
||||
|
||||
@end
|
||||
|
||||
@interface LLNonInlineTextView : NSTextView
|
||||
{
|
||||
LLOpenGLView *glview;
|
||||
}
|
||||
|
||||
- (void) setGLView:(LLOpenGLView*)view;
|
||||
|
||||
@end
|
||||
|
||||
@interface LLNSWindow : NSWindow
|
||||
|
||||
- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view;
|
||||
- (NSPoint)flipPoint:(NSPoint)aPoint;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSScreen (PointConversion)
|
||||
|
||||
/*
|
||||
Returns the screen where the mouse resides
|
||||
*/
|
||||
+ (NSScreen *)currentScreenForMouseLocation;
|
||||
|
||||
/*
|
||||
Allows you to convert a point from global coordinates to the current screen coordinates.
|
||||
*/
|
||||
- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint;
|
||||
|
||||
/*
|
||||
Allows to flip the point coordinates, so y is 0 at the top instead of the bottom. x remains the same
|
||||
*/
|
||||
- (NSPoint)flipPoint:(NSPoint)aPoint;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,686 @@
|
|||
/**
|
||||
* @file llopenglview-objc.mm
|
||||
* @brief Class implementation for most of the Mac facing window functionality.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#import "llopenglview-objc.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
#import "llappdelegate-objc.h"
|
||||
|
||||
@implementation NSScreen (PointConversion)
|
||||
|
||||
+ (NSScreen *)currentScreenForMouseLocation
|
||||
{
|
||||
NSPoint mouseLocation = [NSEvent mouseLocation];
|
||||
|
||||
NSEnumerator *screenEnumerator = [[NSScreen screens] objectEnumerator];
|
||||
NSScreen *screen;
|
||||
while ((screen = [screenEnumerator nextObject]) && !NSMouseInRect(mouseLocation, screen.frame, NO))
|
||||
;
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint
|
||||
{
|
||||
float normalizedX = fabs(fabs(self.frame.origin.x) - fabs(aPoint.x));
|
||||
float normalizedY = aPoint.y - self.frame.origin.y;
|
||||
|
||||
return NSMakePoint(normalizedX, normalizedY);
|
||||
}
|
||||
|
||||
- (NSPoint)flipPoint:(NSPoint)aPoint
|
||||
{
|
||||
return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
attributedStringInfo getSegments(NSAttributedString *str)
|
||||
{
|
||||
attributedStringInfo segments;
|
||||
segment_lengths seg_lengths;
|
||||
segment_standouts seg_standouts;
|
||||
NSRange effectiveRange;
|
||||
NSRange limitRange = NSMakeRange(0, [str length]);
|
||||
|
||||
while (limitRange.length > 0) {
|
||||
NSNumber *attr = [str attribute:NSUnderlineStyleAttributeName atIndex:limitRange.location longestEffectiveRange:&effectiveRange inRange:limitRange];
|
||||
limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
|
||||
|
||||
if (effectiveRange.length <= 0)
|
||||
{
|
||||
effectiveRange.length = 1;
|
||||
}
|
||||
|
||||
if ([attr integerValue] == 2)
|
||||
{
|
||||
seg_lengths.push_back(effectiveRange.length);
|
||||
seg_standouts.push_back(true);
|
||||
} else
|
||||
{
|
||||
seg_lengths.push_back(effectiveRange.length);
|
||||
seg_standouts.push_back(false);
|
||||
}
|
||||
}
|
||||
segments.seg_lengths = seg_lengths;
|
||||
segments.seg_standouts = seg_standouts;
|
||||
return segments;
|
||||
}
|
||||
|
||||
@implementation LLOpenGLView
|
||||
|
||||
- (unsigned long)getVramSize
|
||||
{
|
||||
CGLRendererInfoObj info = 0;
|
||||
GLint vram_bytes = 0;
|
||||
int num_renderers = 0;
|
||||
CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);
|
||||
if(0 == the_err)
|
||||
{
|
||||
CGLDescribeRenderer (info, 0, kCGLRPTextureMemory, &vram_bytes);
|
||||
CGLDestroyRendererInfo (info);
|
||||
}
|
||||
else
|
||||
{
|
||||
vram_bytes = (256 << 20);
|
||||
}
|
||||
|
||||
return (unsigned long)vram_bytes / 1048576; // We need this in megabytes.
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(windowResized:) name:NSWindowDidResizeNotification
|
||||
object:[self window]];
|
||||
}
|
||||
|
||||
- (void)windowResized:(NSNotification *)notification;
|
||||
{
|
||||
NSSize size = [self frame].size;
|
||||
|
||||
callResize(size.width, size.height);
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE];
|
||||
}
|
||||
|
||||
- (id) initWithSamples:(NSUInteger)samples
|
||||
{
|
||||
return [self initWithFrame:[self bounds] withSamples:samples andVsync:TRUE];
|
||||
}
|
||||
|
||||
- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync
|
||||
{
|
||||
return [self initWithFrame:[self bounds] withSamples:samples andVsync:vsync];
|
||||
}
|
||||
|
||||
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync
|
||||
{
|
||||
[self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]];
|
||||
[self initWithFrame:frame];
|
||||
|
||||
// Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6.
|
||||
// Any specialized pixel formats, i.e. a core profile pixel format, should be initialized through rebuildContextWithFormat.
|
||||
// 10.7 and 10.8 don't really care if we're defining a profile or not. If we don't explicitly request a core or legacy profile, it'll always assume a legacy profile (for compatibility reasons).
|
||||
NSOpenGLPixelFormatAttribute attrs[] = {
|
||||
NSOpenGLPFANoRecovery,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFAClosestPolicy,
|
||||
NSOpenGLPFAAccelerated,
|
||||
NSOpenGLPFASampleBuffers, (samples > 0 ? 1 : 0),
|
||||
NSOpenGLPFASamples, samples,
|
||||
NSOpenGLPFAStencilSize, 8,
|
||||
NSOpenGLPFADepthSize, 24,
|
||||
NSOpenGLPFAAlphaSize, 8,
|
||||
NSOpenGLPFAColorSize, 24,
|
||||
0
|
||||
};
|
||||
|
||||
NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease];
|
||||
|
||||
if (pixelFormat == nil)
|
||||
{
|
||||
NSLog(@"Failed to create pixel format!", nil);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSOpenGLContext *glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
|
||||
|
||||
if (glContext == nil)
|
||||
{
|
||||
NSLog(@"Failed to create OpenGL context!", nil);
|
||||
return nil;
|
||||
}
|
||||
|
||||
[self setPixelFormat:pixelFormat];
|
||||
|
||||
[self setOpenGLContext:glContext];
|
||||
|
||||
[glContext setView:self];
|
||||
|
||||
[glContext makeCurrentContext];
|
||||
|
||||
if (vsync)
|
||||
{
|
||||
[glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval];
|
||||
} else {
|
||||
[glContext setValues:(const GLint*)0 forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL) rebuildContext
|
||||
{
|
||||
return [self rebuildContextWithFormat:[self pixelFormat]];
|
||||
}
|
||||
|
||||
- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format
|
||||
{
|
||||
NSOpenGLContext *ctx = [self openGLContext];
|
||||
|
||||
[ctx clearDrawable];
|
||||
[ctx initWithFormat:format shareContext:nil];
|
||||
|
||||
if (ctx == nil)
|
||||
{
|
||||
NSLog(@"Failed to create OpenGL context!", nil);
|
||||
return false;
|
||||
}
|
||||
|
||||
[self setOpenGLContext:ctx];
|
||||
[ctx setView:self];
|
||||
[ctx makeCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
- (CGLContextObj)getCGLContextObj
|
||||
{
|
||||
NSOpenGLContext *ctx = [self openGLContext];
|
||||
return (CGLContextObj)[ctx CGLContextObj];
|
||||
}
|
||||
|
||||
- (CGLPixelFormatObj*)getCGLPixelFormatObj
|
||||
{
|
||||
NSOpenGLPixelFormat *fmt = [self pixelFormat];
|
||||
return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj];
|
||||
}
|
||||
|
||||
// Various events can be intercepted by our view, thus not reaching our window.
|
||||
// Intercept these events, and pass them to the window as needed. - Geenz
|
||||
|
||||
- (void) mouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
// Apparently people still use this?
|
||||
if ([theEvent modifierFlags] & NSCommandKeyMask &&
|
||||
!([theEvent modifierFlags] & NSControlKeyMask) &&
|
||||
!([theEvent modifierFlags] & NSShiftKeyMask) &&
|
||||
!([theEvent modifierFlags] & NSAlternateKeyMask) &&
|
||||
!([theEvent modifierFlags] & NSAlphaShiftKeyMask) &&
|
||||
!([theEvent modifierFlags] & NSFunctionKeyMask) &&
|
||||
!([theEvent modifierFlags] & NSHelpKeyMask))
|
||||
{
|
||||
callRightMouseDown(mMousePos, mModifiers);
|
||||
mSimulatedRightClick = true;
|
||||
} else {
|
||||
if ([theEvent clickCount] >= 2)
|
||||
{
|
||||
callDoubleClick(mMousePos, mModifiers);
|
||||
} else if ([theEvent clickCount] == 1) {
|
||||
callLeftMouseDown(mMousePos, mModifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) mouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
if (mSimulatedRightClick)
|
||||
{
|
||||
callRightMouseUp(mMousePos, mModifiers);
|
||||
mSimulatedRightClick = false;
|
||||
} else {
|
||||
callLeftMouseUp(mMousePos, mModifiers);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) rightMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
callRightMouseDown(mMousePos, mModifiers);
|
||||
}
|
||||
|
||||
- (void) rightMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
callRightMouseUp(mMousePos, mModifiers);
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent *)theEvent
|
||||
{
|
||||
float mouseDeltas[2] = {
|
||||
[theEvent deltaX],
|
||||
[theEvent deltaY]
|
||||
};
|
||||
|
||||
callDeltaUpdate(mouseDeltas, 0);
|
||||
|
||||
NSPoint mPoint = [theEvent locationInWindow];
|
||||
mMousePos[0] = mPoint.x;
|
||||
mMousePos[1] = mPoint.y;
|
||||
callMouseMoved(mMousePos, 0);
|
||||
}
|
||||
|
||||
// NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged.
|
||||
// Use mouseDragged for situations like this to trigger our movement callback instead.
|
||||
|
||||
- (void) mouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
// Trust the deltas supplied by NSEvent.
|
||||
// The old CoreGraphics APIs we previously relied on are now flagged as obsolete.
|
||||
// NSEvent isn't obsolete, and provides us with the correct deltas.
|
||||
float mouseDeltas[2] = {
|
||||
[theEvent deltaX],
|
||||
[theEvent deltaY]
|
||||
};
|
||||
|
||||
callDeltaUpdate(mouseDeltas, 0);
|
||||
|
||||
NSPoint mPoint = [theEvent locationInWindow];
|
||||
mMousePos[0] = mPoint.x;
|
||||
mMousePos[1] = mPoint.y;
|
||||
callMouseMoved(mMousePos, 0);
|
||||
}
|
||||
|
||||
- (void) otherMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
callMiddleMouseDown(mMousePos, mModifiers);
|
||||
}
|
||||
|
||||
- (void) otherMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
callMiddleMouseUp(mMousePos, mModifiers);
|
||||
}
|
||||
|
||||
- (void) otherMouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void) scrollWheel:(NSEvent *)theEvent
|
||||
{
|
||||
callScrollMoved(-[theEvent deltaY]);
|
||||
}
|
||||
|
||||
- (void) mouseExited:(NSEvent *)theEvent
|
||||
{
|
||||
callMouseExit();
|
||||
}
|
||||
|
||||
- (void) keyUp:(NSEvent *)theEvent
|
||||
{
|
||||
callKeyUp([theEvent keyCode], mModifiers);
|
||||
}
|
||||
|
||||
- (void) keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
uint keycode = [theEvent keyCode];
|
||||
bool acceptsText = mHasMarkedText ? false : callKeyDown(keycode, mModifiers);
|
||||
if (acceptsText &&
|
||||
!mMarkedTextAllowed &&
|
||||
![(LLAppDelegate*)[NSApp delegate] romanScript] &&
|
||||
[[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter &&
|
||||
[[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter &&
|
||||
[[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDownArrowFunctionKey &&
|
||||
[[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSUpArrowFunctionKey &&
|
||||
[[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSLeftArrowFunctionKey &&
|
||||
[[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSRightArrowFunctionKey)
|
||||
{
|
||||
[(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent];
|
||||
} else
|
||||
{
|
||||
[[self inputContext] handleEvent:theEvent];
|
||||
}
|
||||
|
||||
if ([[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSCarriageReturnCharacter ||
|
||||
[[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSEnterCharacter)
|
||||
{
|
||||
// callKeyDown won't return the value we expect for enter or return. Handle them as a separate case.
|
||||
[[self inputContext] handleEvent:theEvent];
|
||||
}
|
||||
|
||||
// OS X intentionally does not send us key-up information on cmd-key combinations.
|
||||
// This behaviour is not a bug, and only applies to cmd-combinations (no others).
|
||||
// Since SL assumes we receive those, we fake it here.
|
||||
if (mModifiers & NSCommandKeyMask && !mHasMarkedText)
|
||||
{
|
||||
callKeyUp([theEvent keyCode], mModifiers);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)theEvent {
|
||||
mModifiers = [theEvent modifierFlags];
|
||||
callModifier([theEvent modifierFlags]);
|
||||
}
|
||||
|
||||
- (BOOL) acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender
|
||||
{
|
||||
NSPasteboard *pboard;
|
||||
NSDragOperation sourceDragMask;
|
||||
|
||||
sourceDragMask = [sender draggingSourceOperationMask];
|
||||
|
||||
pboard = [sender draggingPasteboard];
|
||||
|
||||
if ([[pboard types] containsObject:NSURLPboardType])
|
||||
{
|
||||
if (sourceDragMask & NSDragOperationLink) {
|
||||
NSURL *fileUrl = [[pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:[NSDictionary dictionary]] objectAtIndex:0];
|
||||
mLastDraggedUrl = [[fileUrl absoluteString] UTF8String];
|
||||
return NSDragOperationLink;
|
||||
}
|
||||
}
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
callHandleDragUpdated(mLastDraggedUrl);
|
||||
|
||||
return NSDragOperationLink;
|
||||
}
|
||||
|
||||
- (void) draggingExited:(id<NSDraggingInfo>)sender
|
||||
{
|
||||
callHandleDragExited(mLastDraggedUrl);
|
||||
}
|
||||
|
||||
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) performDragOperation:(id<NSDraggingInfo>)sender
|
||||
{
|
||||
callHandleDragDropped(mLastDraggedUrl);
|
||||
return true;
|
||||
}
|
||||
|
||||
- (BOOL)hasMarkedText
|
||||
{
|
||||
return mHasMarkedText;
|
||||
}
|
||||
|
||||
- (NSRange)markedRange
|
||||
{
|
||||
int range[2];
|
||||
getPreeditMarkedRange(&range[0], &range[1]);
|
||||
return NSMakeRange(range[0], range[1]);
|
||||
}
|
||||
|
||||
- (NSRange)selectedRange
|
||||
{
|
||||
int range[2];
|
||||
getPreeditSelectionRange(&range[0], &range[1]);
|
||||
return NSMakeRange(range[0], range[1]);
|
||||
}
|
||||
|
||||
- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString"))
|
||||
{
|
||||
if (mMarkedTextAllowed)
|
||||
{
|
||||
unsigned int selected[2] = {
|
||||
selectedRange.location,
|
||||
selectedRange.length
|
||||
};
|
||||
|
||||
unsigned int replacement[2] = {
|
||||
replacementRange.location,
|
||||
replacementRange.length
|
||||
};
|
||||
|
||||
unichar text[[aString length]];
|
||||
[[aString mutableString] getCharacters:text range:NSMakeRange(0, [aString length])];
|
||||
attributedStringInfo segments = getSegments((NSAttributedString *)aString);
|
||||
setMarkedText(text, selected, replacement, [aString length], segments);
|
||||
mHasMarkedText = TRUE;
|
||||
mMarkedTextLength = [aString length];
|
||||
} else {
|
||||
if (mHasMarkedText)
|
||||
{
|
||||
[self unmarkText];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)commitCurrentPreedit
|
||||
{
|
||||
if (mHasMarkedText)
|
||||
{
|
||||
if ([[self inputContext] respondsToSelector:@selector(commitEditing)])
|
||||
{
|
||||
[[self inputContext] commitEditing];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unmarkText
|
||||
{
|
||||
[[self inputContext] discardMarkedText];
|
||||
resetPreedit();
|
||||
mHasMarkedText = FALSE;
|
||||
}
|
||||
|
||||
// We don't support attributed strings.
|
||||
- (NSArray *)validAttributesForMarkedText
|
||||
{
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
// See above.
|
||||
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)insertText:(id)insertString
|
||||
{
|
||||
if (insertString != nil)
|
||||
{
|
||||
[self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
if (!mHasMarkedText)
|
||||
{
|
||||
for (NSInteger i = 0; i < [aString length]; i++)
|
||||
{
|
||||
callUnicodeCallback([aString characterAtIndex:i], mModifiers);
|
||||
}
|
||||
} else {
|
||||
resetPreedit();
|
||||
// We may never get this point since unmarkText may be called before insertText ever gets called once we submit our text.
|
||||
// But just in case...
|
||||
|
||||
for (NSInteger i = 0; i < [aString length]; i++)
|
||||
{
|
||||
handleUnicodeCharacter([aString characterAtIndex:i]);
|
||||
}
|
||||
mHasMarkedText = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) insertNewline:(id)sender
|
||||
{
|
||||
if (!(mModifiers & NSCommandKeyMask) &&
|
||||
!(mModifiers & NSShiftKeyMask) &&
|
||||
!(mModifiers & NSAlternateKeyMask))
|
||||
{
|
||||
callUnicodeCallback(13, 0);
|
||||
} else {
|
||||
callUnicodeCallback(13, mModifiers);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
|
||||
{
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
float pos[4] = {0, 0, 0, 0};
|
||||
getPreeditLocation(pos, mMarkedTextLength);
|
||||
return NSMakeRect(pos[0], pos[1], pos[2], pos[3]);
|
||||
}
|
||||
|
||||
- (void)doCommandBySelector:(SEL)aSelector
|
||||
{
|
||||
if (aSelector == @selector(insertNewline:))
|
||||
{
|
||||
[self insertNewline:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) allowMarkedTextInput:(bool)allowed
|
||||
{
|
||||
mMarkedTextAllowed = allowed;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LLUserInputWindow
|
||||
|
||||
- (void) close
|
||||
{
|
||||
[self orderOut:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LLNonInlineTextView
|
||||
|
||||
- (void) setGLView:(LLOpenGLView *)view
|
||||
{
|
||||
glview = view;
|
||||
}
|
||||
|
||||
- (void) insertText:(id)insertString
|
||||
{
|
||||
[[self inputContext] discardMarkedText];
|
||||
[self setString:@""];
|
||||
[_window orderOut:_window];
|
||||
[self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])];
|
||||
}
|
||||
|
||||
- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
[glview insertText:aString replacementRange:replacementRange];
|
||||
}
|
||||
|
||||
- (void) insertNewline:(id)sender
|
||||
{
|
||||
[[self textStorage] setValue:@""];
|
||||
[[self inputContext] discardMarkedText];
|
||||
[self setString:@""];
|
||||
}
|
||||
|
||||
- (void)doCommandBySelector:(SEL)aSelector
|
||||
{
|
||||
if (aSelector == @selector(insertNewline:))
|
||||
{
|
||||
[self insertNewline:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LLNSWindow
|
||||
|
||||
- (id) init
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view
|
||||
{
|
||||
NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation];
|
||||
if(currentScreen)
|
||||
{
|
||||
NSPoint windowPoint = [view convertPoint:point toView:nil];
|
||||
NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
|
||||
NSPoint flippedScreenPoint = [currentScreen flipPoint:screenPoint];
|
||||
flippedScreenPoint.y += [currentScreen frame].origin.y;
|
||||
|
||||
return flippedScreenPoint;
|
||||
}
|
||||
|
||||
return NSZeroPoint;
|
||||
}
|
||||
|
||||
- (NSPoint)flipPoint:(NSPoint)aPoint
|
||||
{
|
||||
return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y);
|
||||
}
|
||||
|
||||
- (BOOL) becomeFirstResponder
|
||||
{
|
||||
callFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
- (BOOL) resignFirstResponder
|
||||
{
|
||||
callFocusLost();
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
callQuitHandler();
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -25,13 +25,121 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<std::pair<int, bool> > segment_t;
|
||||
|
||||
typedef std::vector<int> segment_lengths;
|
||||
typedef std::vector<int> segment_standouts;
|
||||
|
||||
struct attributedStringInfo {
|
||||
segment_lengths seg_lengths;
|
||||
segment_standouts seg_standouts;
|
||||
};
|
||||
|
||||
// This will actually hold an NSCursor*, but that type is only available in objective C.
|
||||
typedef void *CursorRef;
|
||||
typedef void *NSWindowRef;
|
||||
typedef void *GLViewRef;
|
||||
|
||||
// These are defined in llappviewermacosx.cpp.
|
||||
bool initViewer();
|
||||
void handleQuit();
|
||||
bool runMainLoop();
|
||||
void initMainLoop();
|
||||
void cleanupViewer();
|
||||
|
||||
/* Defined in llwindowmacosx-objc.mm: */
|
||||
int createNSApp(int argc, const char **argv);
|
||||
void setupCocoa();
|
||||
bool pasteBoardAvailable();
|
||||
bool copyToPBoard(const unsigned short *str, unsigned int len);
|
||||
const unsigned short *copyFromPBoard();
|
||||
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY);
|
||||
OSErr releaseImageCursor(CursorRef ref);
|
||||
OSErr setImageCursor(CursorRef ref);
|
||||
short releaseImageCursor(CursorRef ref);
|
||||
short setImageCursor(CursorRef ref);
|
||||
void setArrowCursor();
|
||||
void setIBeamCursor();
|
||||
void setPointingHandCursor();
|
||||
void setCopyCursor();
|
||||
void setCrossCursor();
|
||||
void setNotAllowedCursor();
|
||||
void hideNSCursor();
|
||||
void showNSCursor();
|
||||
void hideNSCursorTillMove(bool hide);
|
||||
void requestUserAttention();
|
||||
long showAlert(std::string title, std::string text, int type);
|
||||
|
||||
NSWindowRef createNSWindow(int x, int y, int width, int height);
|
||||
|
||||
#include <OpenGL/OpenGL.h>
|
||||
GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync);
|
||||
void glSwapBuffers(void* context);
|
||||
CGLContextObj getCGLContextObj(GLViewRef view);
|
||||
unsigned long getVramSize(GLViewRef view);
|
||||
void getContentViewBounds(NSWindowRef window, float* bounds);
|
||||
void getWindowSize(NSWindowRef window, float* size);
|
||||
void setWindowSize(NSWindowRef window, int width, int height);
|
||||
void getCursorPos(NSWindowRef window, float* pos);
|
||||
void makeWindowOrderFront(NSWindowRef window);
|
||||
void convertScreenToWindow(NSWindowRef window, float *coord);
|
||||
void convertWindowToScreen(NSWindowRef window, float *coord);
|
||||
void convertScreenToView(NSWindowRef window, float *coord);
|
||||
void convertRectToScreen(NSWindowRef window, float *coord);
|
||||
void convertRectFromScreen(NSWindowRef window, float *coord);
|
||||
void setWindowPos(NSWindowRef window, float* pos);
|
||||
void closeWindow(NSWindowRef window);
|
||||
void removeGLView(GLViewRef view);
|
||||
void makeFirstResponder(NSWindowRef window, GLViewRef view);
|
||||
void setupInputWindow(NSWindowRef window, GLViewRef view);
|
||||
|
||||
// These are all implemented in llwindowmacosx.cpp.
|
||||
// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict)
|
||||
bool callKeyUp(unsigned short key, unsigned int mask);
|
||||
bool callKeyDown(unsigned short key, unsigned int mask);
|
||||
void callResetKeys();
|
||||
bool callUnicodeCallback(wchar_t character, unsigned int mask);
|
||||
void callRightMouseDown(float *pos, unsigned int mask);
|
||||
void callRightMouseUp(float *pos, unsigned int mask);
|
||||
void callLeftMouseDown(float *pos, unsigned int mask);
|
||||
void callLeftMouseUp(float *pos, unsigned int mask);
|
||||
void callDoubleClick(float *pos, unsigned int mask);
|
||||
void callResize(unsigned int width, unsigned int height);
|
||||
void callMouseMoved(float *pos, unsigned int mask);
|
||||
void callScrollMoved(float delta);
|
||||
void callMouseExit();
|
||||
void callWindowFocus();
|
||||
void callWindowUnfocus();
|
||||
void callDeltaUpdate(float *delta, unsigned int mask);
|
||||
void callMiddleMouseDown(float *pos, unsigned int mask);
|
||||
void callMiddleMouseUp(float *pos, unsigned int mask);
|
||||
void callFocus();
|
||||
void callFocusLost();
|
||||
void callModifier(unsigned int mask);
|
||||
void callQuitHandler();
|
||||
void commitCurrentPreedit(GLViewRef glView);
|
||||
|
||||
#include <string>
|
||||
void callHandleDragEntered(std::string url);
|
||||
void callHandleDragExited(std::string url);
|
||||
void callHandleDragUpdated(std::string url);
|
||||
void callHandleDragDropped(std::string url);
|
||||
|
||||
// LLPreeditor C bindings.
|
||||
std::basic_string<wchar_t> getPreeditString();
|
||||
void getPreeditSelectionRange(int *position, int *length);
|
||||
void getPreeditMarkedRange(int *position, int *length);
|
||||
bool handleUnicodeCharacter(wchar_t c);
|
||||
void updatePreeditor(unsigned short *str);
|
||||
void setPreeditMarkedRange(int position, int length);
|
||||
void resetPreedit();
|
||||
int wstring_length(const std::basic_string<wchar_t> & wstr, const int woffset, const int utf16_length, int *unaligned);
|
||||
void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments);
|
||||
void getPreeditLocation(float *location, unsigned int length);
|
||||
void allowDirectMarkedTextInput(bool allow, GLViewRef glView);
|
||||
|
||||
NSWindowRef getMainAppWindow();
|
||||
GLViewRef getGLView();
|
||||
|
||||
unsigned int getModifiers();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file llwindowmacosx-objc.mm
|
||||
* @brief Definition of functions shared between llwindowmacosx.cpp
|
||||
* and llwindowmacosx-objc.mm.
|
||||
|
|
@ -6,26 +6,30 @@
|
|||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "llopenglview-objc.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
#include "llappdelegate-objc.h"
|
||||
|
||||
/*
|
||||
* These functions are broken out into a separate file because the
|
||||
|
|
@ -34,7 +38,10 @@
|
|||
* linden headers with any objective-C++ source.
|
||||
*/
|
||||
|
||||
#include "llwindowmacosx-objc.h"
|
||||
int createNSApp(int argc, const char *argv[])
|
||||
{
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
||||
|
||||
void setupCocoa()
|
||||
{
|
||||
|
|
@ -45,44 +52,122 @@ void setupCocoa()
|
|||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
|
||||
// ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
|
||||
// when init'ing the Cocoa App window.
|
||||
// ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
|
||||
// when init'ing the Cocoa App window.
|
||||
[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
|
||||
|
||||
// This is a bit of voodoo taken from the Apple sample code "CarbonCocoa_PictureCursor":
|
||||
// http://developer.apple.com/samplecode/CarbonCocoa_PictureCursor/index.html
|
||||
|
||||
// Needed for Carbon based applications which call into Cocoa
|
||||
NSApplicationLoad();
|
||||
|
||||
// Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image
|
||||
[[[NSWindow alloc] init] release];
|
||||
|
||||
[pool release];
|
||||
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool copyToPBoard(const unsigned short *str, unsigned int len)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
|
||||
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
|
||||
[pboard clearContents];
|
||||
|
||||
NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil];
|
||||
[pool release];
|
||||
return [pboard writeObjects:contentsToPaste];
|
||||
}
|
||||
|
||||
bool pasteBoardAvailable()
|
||||
{
|
||||
NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
|
||||
return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
|
||||
}
|
||||
|
||||
const unsigned short *copyFromPBoard()
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
|
||||
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
|
||||
NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
|
||||
NSString *str = NULL;
|
||||
BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
|
||||
if (ok)
|
||||
{
|
||||
NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
|
||||
str = [objToPaste objectAtIndex:0];
|
||||
}
|
||||
unichar* temp = (unichar*)calloc([str length], sizeof(unichar));
|
||||
[str getCharacters:temp];
|
||||
[pool release];
|
||||
return temp;
|
||||
}
|
||||
|
||||
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
// extra retain on the NSCursor since we want it to live for the lifetime of the app.
|
||||
NSCursor *cursor =
|
||||
[[[NSCursor alloc]
|
||||
initWithImage:
|
||||
[[[NSImage alloc] initWithContentsOfFile:
|
||||
[NSString stringWithFormat:@"%s", fullpath]
|
||||
]autorelease]
|
||||
hotSpot:NSMakePoint(hotspotX, hotspotY)
|
||||
]retain];
|
||||
|
||||
[[[NSCursor alloc]
|
||||
initWithImage:
|
||||
[[[NSImage alloc] initWithContentsOfFile:
|
||||
[NSString stringWithFormat:@"%s", fullpath]
|
||||
]autorelease]
|
||||
hotSpot:NSMakePoint(hotspotX, hotspotY)
|
||||
]retain];
|
||||
|
||||
[pool release];
|
||||
|
||||
return (CursorRef)cursor;
|
||||
}
|
||||
|
||||
void setArrowCursor()
|
||||
{
|
||||
NSCursor *cursor = [NSCursor arrowCursor];
|
||||
[NSCursor unhide];
|
||||
[cursor set];
|
||||
}
|
||||
|
||||
void setIBeamCursor()
|
||||
{
|
||||
NSCursor *cursor = [NSCursor IBeamCursor];
|
||||
[cursor set];
|
||||
}
|
||||
|
||||
void setPointingHandCursor()
|
||||
{
|
||||
NSCursor *cursor = [NSCursor pointingHandCursor];
|
||||
[cursor set];
|
||||
}
|
||||
|
||||
void setCopyCursor()
|
||||
{
|
||||
NSCursor *cursor = [NSCursor dragCopyCursor];
|
||||
[cursor set];
|
||||
}
|
||||
|
||||
void setCrossCursor()
|
||||
{
|
||||
NSCursor *cursor = [NSCursor crosshairCursor];
|
||||
[cursor set];
|
||||
}
|
||||
|
||||
void setNotAllowedCursor()
|
||||
{
|
||||
NSCursor *cursor = [NSCursor operationNotAllowedCursor];
|
||||
[cursor set];
|
||||
}
|
||||
|
||||
void hideNSCursor()
|
||||
{
|
||||
[NSCursor hide];
|
||||
}
|
||||
|
||||
void showNSCursor()
|
||||
{
|
||||
[NSCursor unhide];
|
||||
}
|
||||
|
||||
void hideNSCursorTillMove(bool hide)
|
||||
{
|
||||
[NSCursor setHiddenUntilMouseMoves:hide];
|
||||
}
|
||||
|
||||
// This is currently unused, since we want all our cursors to persist for the life of the app, but I've included it for completeness.
|
||||
OSErr releaseImageCursor(CursorRef ref)
|
||||
{
|
||||
|
|
@ -118,3 +203,250 @@ OSErr setImageCursor(CursorRef ref)
|
|||
return noErr;
|
||||
}
|
||||
|
||||
// Now for some unholy juggling between generic pointers and casting them to Obj-C objects!
|
||||
// Note: things can get a bit hairy from here. This is not for the faint of heart.
|
||||
|
||||
NSWindowRef createNSWindow(int x, int y, int width, int height)
|
||||
{
|
||||
LLNSWindow *window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height)
|
||||
styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO];
|
||||
[window makeKeyAndOrderFront:nil];
|
||||
[window setAcceptsMouseMovedEvents:TRUE];
|
||||
return window;
|
||||
}
|
||||
|
||||
GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync)
|
||||
{
|
||||
LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:samples andVsync:vsync];
|
||||
[(LLNSWindow*)window setContentView:glview];
|
||||
return glview;
|
||||
}
|
||||
|
||||
void glSwapBuffers(void* context)
|
||||
{
|
||||
[(NSOpenGLContext*)context flushBuffer];
|
||||
}
|
||||
|
||||
CGLContextObj getCGLContextObj(GLViewRef view)
|
||||
{
|
||||
return [(LLOpenGLView *)view getCGLContextObj];
|
||||
}
|
||||
|
||||
CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window)
|
||||
{
|
||||
LLOpenGLView *glview = [(LLNSWindow*)window contentView];
|
||||
return [glview getCGLPixelFormatObj];
|
||||
}
|
||||
|
||||
unsigned long getVramSize(GLViewRef view)
|
||||
{
|
||||
return [(LLOpenGLView *)view getVramSize];
|
||||
}
|
||||
|
||||
void getContentViewBounds(NSWindowRef window, float* bounds)
|
||||
{
|
||||
bounds[0] = [[(LLNSWindow*)window contentView] bounds].origin.x;
|
||||
bounds[1] = [[(LLNSWindow*)window contentView] bounds].origin.y;
|
||||
bounds[2] = [[(LLNSWindow*)window contentView] bounds].size.width;
|
||||
bounds[3] = [[(LLNSWindow*)window contentView] bounds].size.height;
|
||||
}
|
||||
|
||||
void getWindowSize(NSWindowRef window, float* size)
|
||||
{
|
||||
NSRect frame = [(LLNSWindow*)window frame];
|
||||
size[0] = frame.origin.x;
|
||||
size[1] = frame.origin.y;
|
||||
size[2] = frame.size.width;
|
||||
size[3] = frame.size.height;
|
||||
}
|
||||
|
||||
void setWindowSize(NSWindowRef window, int width, int height)
|
||||
{
|
||||
NSRect frame = [(LLNSWindow*)window frame];
|
||||
frame.size.width = width;
|
||||
frame.size.height = height;
|
||||
[(LLNSWindow*)window setFrame:frame display:TRUE];
|
||||
}
|
||||
|
||||
void setWindowPos(NSWindowRef window, float* pos)
|
||||
{
|
||||
NSPoint point;
|
||||
point.x = pos[0];
|
||||
point.y = pos[1];
|
||||
[(LLNSWindow*)window setFrameOrigin:point];
|
||||
}
|
||||
|
||||
void getCursorPos(NSWindowRef window, float* pos)
|
||||
{
|
||||
NSPoint mLoc;
|
||||
mLoc = [(LLNSWindow*)window mouseLocationOutsideOfEventStream];
|
||||
pos[0] = mLoc.x;
|
||||
pos[1] = mLoc.y;
|
||||
}
|
||||
|
||||
void makeWindowOrderFront(NSWindowRef window)
|
||||
{
|
||||
[(LLNSWindow*)window makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
void convertScreenToWindow(NSWindowRef window, float *coord)
|
||||
{
|
||||
NSRect point;
|
||||
point.origin.x = coord[0];
|
||||
point.origin.y = coord[1];
|
||||
point = [(LLNSWindow*)window convertRectFromScreen:point];
|
||||
coord[0] = point.origin.x;
|
||||
coord[1] = point.origin.y;
|
||||
}
|
||||
|
||||
void convertRectToScreen(NSWindowRef window, float *coord)
|
||||
{
|
||||
NSRect point;
|
||||
point.origin.x = coord[0];
|
||||
point.origin.y = coord[1];
|
||||
point.size.width = coord[2];
|
||||
point.size.height = coord[3];
|
||||
|
||||
point = [(LLNSWindow*)window convertRectToScreen:point];
|
||||
|
||||
coord[0] = point.origin.x;
|
||||
coord[1] = point.origin.y;
|
||||
coord[2] = point.size.width;
|
||||
coord[3] = point.size.height;
|
||||
}
|
||||
|
||||
void convertRectFromScreen(NSWindowRef window, float *coord)
|
||||
{
|
||||
NSRect point;
|
||||
point.origin.x = coord[0];
|
||||
point.origin.y = coord[1];
|
||||
point.size.width = coord[2];
|
||||
point.size.height = coord[3];
|
||||
|
||||
point = [(LLNSWindow*)window convertRectFromScreen:point];
|
||||
|
||||
coord[0] = point.origin.x;
|
||||
coord[1] = point.origin.y;
|
||||
coord[2] = point.size.width;
|
||||
coord[3] = point.size.height;
|
||||
}
|
||||
|
||||
void convertScreenToView(NSWindowRef window, float *coord)
|
||||
{
|
||||
NSRect point;
|
||||
point.origin.x = coord[0];
|
||||
point.origin.y = coord[1];
|
||||
point.origin = [(LLNSWindow*)window convertScreenToBase:point.origin];
|
||||
point.origin = [[(LLNSWindow*)window contentView] convertPoint:point.origin fromView:nil];
|
||||
}
|
||||
|
||||
void convertWindowToScreen(NSWindowRef window, float *coord)
|
||||
{
|
||||
NSPoint point;
|
||||
point.x = coord[0];
|
||||
point.y = coord[1];
|
||||
point = [(LLNSWindow*)window convertToScreenFromLocalPoint:point relativeToView:[(LLNSWindow*)window contentView]];
|
||||
coord[0] = point.x;
|
||||
coord[1] = point.y;
|
||||
}
|
||||
|
||||
void closeWindow(NSWindowRef window)
|
||||
{
|
||||
[(LLNSWindow*)window close];
|
||||
[(LLNSWindow*)window release];
|
||||
}
|
||||
|
||||
void removeGLView(GLViewRef view)
|
||||
{
|
||||
[(LLOpenGLView*)view removeFromSuperview];
|
||||
[(LLOpenGLView*)view release];
|
||||
}
|
||||
|
||||
void setupInputWindow(NSWindowRef window, GLViewRef glview)
|
||||
{
|
||||
[[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview];
|
||||
}
|
||||
|
||||
void commitCurrentPreedit(GLViewRef glView)
|
||||
{
|
||||
[(LLOpenGLView*)glView commitCurrentPreedit];
|
||||
}
|
||||
|
||||
void allowDirectMarkedTextInput(bool allow, GLViewRef glView)
|
||||
{
|
||||
[(LLOpenGLView*)glView allowMarkedTextInput:allow];
|
||||
}
|
||||
|
||||
NSWindowRef getMainAppWindow()
|
||||
{
|
||||
LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window];
|
||||
|
||||
[winRef setAcceptsMouseMovedEvents:TRUE];
|
||||
return winRef;
|
||||
}
|
||||
|
||||
void makeFirstResponder(NSWindowRef window, GLViewRef view)
|
||||
{
|
||||
[(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view];
|
||||
}
|
||||
|
||||
void requestUserAttention()
|
||||
{
|
||||
[[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
|
||||
}
|
||||
|
||||
long showAlert(std::string text, std::string title, int type)
|
||||
{
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
|
||||
[alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
|
||||
[alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
|
||||
if (type == 0)
|
||||
{
|
||||
[alert addButtonWithTitle:@"Okay"];
|
||||
} else if (type == 1)
|
||||
{
|
||||
[alert addButtonWithTitle:@"Okay"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
} else if (type == 2)
|
||||
{
|
||||
[alert addButtonWithTitle:@"Yes"];
|
||||
[alert addButtonWithTitle:@"No"];
|
||||
}
|
||||
long ret = [alert runModal];
|
||||
[alert dealloc];
|
||||
|
||||
if (ret == NSAlertFirstButtonReturn)
|
||||
{
|
||||
if (type == 1)
|
||||
{
|
||||
ret = 3;
|
||||
} else if (type == 2)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
} else if (ret == NSAlertSecondButtonReturn)
|
||||
{
|
||||
if (type == 0 || type == 1)
|
||||
{
|
||||
ret = 2;
|
||||
} else if (type == 2)
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
GLViewRef getGLView()
|
||||
{
|
||||
return [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] glview];
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned int getModifiers()
|
||||
{
|
||||
return [NSEvent modifierFlags];
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -29,11 +29,12 @@
|
|||
|
||||
#include "llwindow.h"
|
||||
#include "llwindowcallbacks.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <AGL/agl.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
|
||||
// AssertMacros.h does bad things.
|
||||
#include "fix_macros.h"
|
||||
|
|
@ -106,7 +107,6 @@ public:
|
|||
/*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
|
||||
|
||||
/*virtual*/ void *getPlatformWindow();
|
||||
/*virtual*/ void *getMediaWindow();
|
||||
/*virtual*/ void bringToFront() {};
|
||||
|
||||
/*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b);
|
||||
|
|
@ -117,7 +117,17 @@ public:
|
|||
|
||||
// Provide native key event data
|
||||
/*virtual*/ LLSD getNativeKeyData();
|
||||
|
||||
|
||||
void* getWindow() { return mWindow; }
|
||||
LLWindowCallbacks* getCallbacks() { return mCallbacks; }
|
||||
LLPreeditor* getPreeditor() { return mPreeditor; }
|
||||
|
||||
void updateMouseDeltas(float* deltas);
|
||||
void getMouseDeltas(float* delta);
|
||||
|
||||
void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action);
|
||||
|
||||
bool allowsLanguageInput() { return mLanguageTextInputAllowed; }
|
||||
|
||||
protected:
|
||||
LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
|
|
@ -153,40 +163,33 @@ protected:
|
|||
BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync);
|
||||
void destroyContext();
|
||||
void setupFailure(const std::string& text, const std::string& caption, U32 type);
|
||||
static pascal OSStatus staticEventHandler (EventHandlerCallRef myHandler, EventRef event, void* userData);
|
||||
static pascal Boolean staticMoveEventComparator( EventRef event, void* data);
|
||||
OSStatus eventHandler (EventHandlerCallRef myHandler, EventRef event);
|
||||
void adjustCursorDecouple(bool warpingMouse = false);
|
||||
void stopDockTileBounce();
|
||||
static MASK modifiersToMask(SInt16 modifiers);
|
||||
static MASK modifiersToMask(S16 modifiers);
|
||||
|
||||
#if LL_OS_DRAGDROP_ENABLED
|
||||
static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
|
||||
void * handlerRefCon, DragRef theDrag);
|
||||
static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
|
||||
OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action);
|
||||
|
||||
//static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
|
||||
//static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
|
||||
|
||||
|
||||
#endif // LL_OS_DRAGDROP_ENABLED
|
||||
|
||||
//
|
||||
// Platform specific variables
|
||||
//
|
||||
WindowRef mWindow;
|
||||
AGLContext mContext;
|
||||
AGLPixelFormat mPixelFormat;
|
||||
CGDirectDisplayID mDisplay;
|
||||
CFDictionaryRef mOldDisplayMode;
|
||||
EventLoopTimerRef mTimer;
|
||||
EventHandlerUPP mEventHandlerUPP;
|
||||
EventHandlerRef mGlobalHandlerRef;
|
||||
EventHandlerRef mWindowHandlerRef;
|
||||
EventComparatorUPP mMoveEventCampartorUPP;
|
||||
|
||||
Rect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
|
||||
Rect mPreviousWindowRect; // Save previous window for un-maximize event
|
||||
Str255 mWindowTitle;
|
||||
// Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise.
|
||||
NSWindowRef mWindow;
|
||||
GLViewRef mGLView;
|
||||
CGLContextObj mContext;
|
||||
CGLPixelFormatObj mPixelFormat;
|
||||
CGDirectDisplayID mDisplay;
|
||||
|
||||
LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
|
||||
std::string mWindowTitle;
|
||||
double mOriginalAspectRatio;
|
||||
BOOL mSimulatedRightClick;
|
||||
UInt32 mLastModifiers;
|
||||
U32 mLastModifiers;
|
||||
BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing.
|
||||
// Used to allow event processing when putting up dialogs in fullscreen mode.
|
||||
BOOL mCursorDecoupled;
|
||||
|
|
@ -201,25 +204,16 @@ protected:
|
|||
U32 mFSAASamples;
|
||||
BOOL mForceRebuild;
|
||||
|
||||
S32 mDragOverrideCursor;
|
||||
|
||||
F32 mBounceTime;
|
||||
NMRec mBounceRec;
|
||||
LLTimer mBounceTimer;
|
||||
S32 mDragOverrideCursor;
|
||||
|
||||
// Input method management through Text Service Manager.
|
||||
TSMDocumentID mTSMDocument;
|
||||
BOOL mLanguageTextInputAllowed;
|
||||
ScriptCode mTSMScriptCode;
|
||||
LangCode mTSMLangCode;
|
||||
LLPreeditor* mPreeditor;
|
||||
|
||||
static BOOL sUseMultGL;
|
||||
|
||||
friend class LLWindowManager;
|
||||
static WindowRef sMediaWindow;
|
||||
EventRef mRawKeyEvent;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -232,12 +232,8 @@ private:
|
|||
mMovieHandle = NULL;
|
||||
};
|
||||
|
||||
if ( mGWorldHandle )
|
||||
{
|
||||
DisposeGWorld( mGWorldHandle );
|
||||
mGWorldHandle = NULL;
|
||||
};
|
||||
|
||||
mGWorldHandle = NULL;
|
||||
|
||||
setStatus(STATUS_NONE);
|
||||
|
||||
return true;
|
||||
|
|
@ -273,6 +269,7 @@ private:
|
|||
//std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sanitize destination size
|
||||
Rect dest_rect = rectFromSize(mWidth, mHeight);
|
||||
|
|
@ -281,12 +278,10 @@ private:
|
|||
int depth_bits = mDepth * 8;
|
||||
long rowbytes = mDepth * mTextureWidth;
|
||||
|
||||
GWorldPtr old_gworld_handle = mGWorldHandle;
|
||||
|
||||
if(mPixels != NULL)
|
||||
{
|
||||
// We have pixels. Set up a GWorld pointing at the texture.
|
||||
OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
|
||||
OSErr result = QTNewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
|
||||
if ( noErr != result )
|
||||
{
|
||||
// TODO: unrecoverable?? throw exception? return something?
|
||||
|
|
@ -297,7 +292,7 @@ private:
|
|||
{
|
||||
// We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
|
||||
Rect tempRect = rectFromSize(1, 1);
|
||||
OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
|
||||
OSErr result = QTNewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
|
||||
if ( noErr != result )
|
||||
{
|
||||
// TODO: unrecoverable?? throw exception? return something?
|
||||
|
|
@ -305,14 +300,8 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) );
|
||||
|
||||
// If the GWorld was already set up, delete it.
|
||||
if(old_gworld_handle != NULL)
|
||||
{
|
||||
DisposeGWorld( old_gworld_handle );
|
||||
}
|
||||
|
||||
SetMovieGWorld( mMovieHandle, mGWorldHandle, NULL );
|
||||
|
||||
// Set up the movie display matrix
|
||||
{
|
||||
// scale movie to fit rect and invert vertically to match opengl image format
|
||||
|
|
@ -579,28 +568,7 @@ private:
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
int getDataWidth() const
|
||||
{
|
||||
if ( mGWorldHandle )
|
||||
{
|
||||
int depth = mDepth;
|
||||
|
||||
if (depth < 1)
|
||||
depth = 1;
|
||||
|
||||
// ALWAYS use the row bytes from the PixMap if we have a GWorld because
|
||||
// sometimes it's not the same as mMediaDepth * mMediaWidth !
|
||||
PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle );
|
||||
return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO : return LLMediaImplCommon::getaDataWidth();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void seek( F64 time )
|
||||
{
|
||||
if ( mMovieController )
|
||||
|
|
|
|||
|
|
@ -35,10 +35,13 @@
|
|||
|
||||
#include "volume_catcher.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <QuickTime/QuickTime.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
#if LL_DARWIN
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
struct VolumeCatcherStorage;
|
||||
|
||||
class VolumeCatcherImpl
|
||||
|
|
@ -266,3 +269,6 @@ void VolumeCatcher::pump()
|
|||
// No periodic tasks are necessary for this implementation.
|
||||
}
|
||||
|
||||
#if LL_DARWIN
|
||||
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1272,6 +1272,11 @@ set_source_files_properties(
|
|||
|
||||
if (DARWIN)
|
||||
LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp)
|
||||
LIST(APPEND viewer_SOURCE_FILES llfilepicker_mac.mm)
|
||||
LIST(APPEND viewer_HEADER_FILES llfilepicker_mac.h)
|
||||
|
||||
# This should be compiled with the viewer.
|
||||
LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm)
|
||||
|
||||
find_library(AGL_LIBRARY AGL)
|
||||
find_library(APPKIT_LIBRARY AppKit)
|
||||
|
|
@ -1292,7 +1297,7 @@ if (DARWIN)
|
|||
macview.r
|
||||
gpu_table.txt
|
||||
Info-SecondLife.plist
|
||||
SecondLife.nib/
|
||||
SecondLife.xib/
|
||||
# CMake doesn't seem to support Xcode language variants well just yet
|
||||
English.lproj/InfoPlist.strings
|
||||
English.lproj/language.txt
|
||||
|
|
@ -1972,20 +1977,25 @@ if (LINUX)
|
|||
endif (LINUX)
|
||||
|
||||
if (DARWIN)
|
||||
# These all get set with PROPERTIES
|
||||
set(product "Second Life")
|
||||
|
||||
set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer")
|
||||
set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007")
|
||||
set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib")
|
||||
set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication")
|
||||
|
||||
set_target_properties(
|
||||
${VIEWER_BINARY_NAME}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "${product}"
|
||||
MACOSX_BUNDLE_INFO_STRING "Second Life Viewer"
|
||||
MACOSX_BUNDLE_ICON_FILE "secondlife.icns"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer"
|
||||
MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "Second Life"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}"
|
||||
MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007"
|
||||
MACOSX_BUNDLE_INFO_PLIST
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist"
|
||||
)
|
||||
|
||||
configure_file(
|
||||
|
|
|
|||
|
|
@ -5,19 +5,33 @@
|
|||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Second Life</string>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>secondlife.icns</string>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.secondlife.indra.viewer</string>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Second Life</string>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
|
@ -59,9 +73,9 @@
|
|||
<true/>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>${MACOSX_BUNDLE_NSPRINCIPAL_CLASS}</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>${MACOSX_BUNDLE_NSMAIN_NIB_FILE}</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
IBClasses = ();
|
||||
IBVersion = 1;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>85 13 356 240 0 0 1280 1002 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>29</key>
|
||||
<string>27 314 247 44 0 0 1280 1002 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>362.0</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>191</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>7D24</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCarbonFramework</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
<?xml version="1.0" standalone="yes"?>
|
||||
<object class="NSIBObjectData">
|
||||
<string name="targetFramework">IBCarbonFramework</string>
|
||||
<object name="rootObject" class="NSCustomObject" id="1">
|
||||
<string name="customClass">NSApplication</string>
|
||||
</object>
|
||||
<array count="31" name="allObjects">
|
||||
<object class="IBCarbonMenu" id="29">
|
||||
<string name="title">SecondLife</string>
|
||||
<array count="4" name="items">
|
||||
<object class="IBCarbonMenuItem" id="182">
|
||||
<string name="title">Second Life</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="181">
|
||||
<string name="title">Second Life</string>
|
||||
<array count="1" name="items">
|
||||
<object class="IBCarbonMenuItem" id="183">
|
||||
<boolean name="disabled">TRUE</boolean>
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">About Second Life</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">abou</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSAppleMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="127">
|
||||
<string name="title">File</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="131">
|
||||
<string name="title">File</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="152">
|
||||
<string name="title">Edit</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="147">
|
||||
<string name="title">Edit</string>
|
||||
<array count="10" name="items">
|
||||
<object class="IBCarbonMenuItem" id="141">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Undo</string>
|
||||
<string name="keyEquivalent">z</string>
|
||||
<ostype name="command">undo</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="146">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Redo</string>
|
||||
<string name="keyEquivalent">Z</string>
|
||||
<ostype name="command">redo</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="142">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="143">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Cut</string>
|
||||
<string name="keyEquivalent">x</string>
|
||||
<ostype name="command">cut </ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="149">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Copy</string>
|
||||
<string name="keyEquivalent">c</string>
|
||||
<ostype name="command">copy</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="144">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Paste</string>
|
||||
<string name="keyEquivalent">v</string>
|
||||
<ostype name="command">past</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="151">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Delete</string>
|
||||
<ostype name="command">clea</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="148">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Select All</string>
|
||||
<string name="keyEquivalent">a</string>
|
||||
<ostype name="command">sall</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="188">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="187">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Special Characters…</string>
|
||||
<ostype name="command">chrp</ostype>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="153">
|
||||
<string name="title">Window</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="154">
|
||||
<string name="title">Window</string>
|
||||
<array count="6" name="items">
|
||||
<object class="IBCarbonMenuItem" id="155">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Minimize Window</string>
|
||||
<string name="keyEquivalent">m</string>
|
||||
<ostype name="command">mini</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="184">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Minimize All Windows</string>
|
||||
<string name="keyEquivalent">m</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">mina</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="186">
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Zoom</string>
|
||||
<ostype name="command">zoom</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="156">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="157">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Bring All to Front</string>
|
||||
<ostype name="command">bfrt</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="185">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<boolean name="updateSingleItem">TRUE</boolean>
|
||||
<string name="title">Arrange in Front</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">frnt</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSWindowsMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSMainMenu</string>
|
||||
</object>
|
||||
<reference idRef="127"/>
|
||||
<reference idRef="131"/>
|
||||
<reference idRef="141"/>
|
||||
<reference idRef="142"/>
|
||||
<reference idRef="143"/>
|
||||
<reference idRef="144"/>
|
||||
<reference idRef="146"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="148"/>
|
||||
<reference idRef="149"/>
|
||||
<reference idRef="151"/>
|
||||
<reference idRef="152"/>
|
||||
<reference idRef="153"/>
|
||||
<reference idRef="154"/>
|
||||
<reference idRef="155"/>
|
||||
<reference idRef="156"/>
|
||||
<reference idRef="157"/>
|
||||
<reference idRef="181"/>
|
||||
<reference idRef="182"/>
|
||||
<reference idRef="183"/>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="185"/>
|
||||
<reference idRef="186"/>
|
||||
<reference idRef="187"/>
|
||||
<reference idRef="188"/>
|
||||
<object class="IBCarbonRootControl" id="190">
|
||||
<string name="bounds">0 0 482 694 </string>
|
||||
<string name="viewFrame">0 0 694 482 </string>
|
||||
<array count="2" name="subviews">
|
||||
<object class="IBCarbonButton" id="192">
|
||||
<string name="bounds">442 604 462 674 </string>
|
||||
<string name="viewFrame">604 442 70 20 </string>
|
||||
<string name="title">OK</string>
|
||||
<ostype name="command">ok </ostype>
|
||||
<object name="layoutInfo" class="IBCarbonHILayoutInfo">
|
||||
<int name="bindingBottomKind">2</int>
|
||||
<int name="bindingRightKind">2</int>
|
||||
</object>
|
||||
<int name="buttonType">1</int>
|
||||
</object>
|
||||
<object class="IBCarbonScrollView" id="201">
|
||||
<string name="bounds">20 20 422 674 </string>
|
||||
<string name="viewFrame">20 20 654 402 </string>
|
||||
<array count="1" name="subviews">
|
||||
<object class="IBCarbonTextView" id="200">
|
||||
<string name="bounds">20 20 422 659 </string>
|
||||
<string name="viewFrame">0 0 639 402 </string>
|
||||
<ostype name="controlSignature">text</ostype>
|
||||
<int name="fontStyle">5</int>
|
||||
<boolean name="readOnly">TRUE</boolean>
|
||||
</object>
|
||||
</array>
|
||||
<boolean name="scrollHorizontally">FALSE</boolean>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<object class="IBCarbonWindow" id="191">
|
||||
<string name="windowRect">84 72 566 766 </string>
|
||||
<string name="title">Release Notes</string>
|
||||
<reference name="rootControl" idRef="190"/>
|
||||
<boolean name="receiveUpdates">FALSE</boolean>
|
||||
<boolean name="hasCloseBox">FALSE</boolean>
|
||||
<boolean name="hasCollapseBox">FALSE</boolean>
|
||||
<boolean name="hasHorizontalZoom">FALSE</boolean>
|
||||
<boolean name="isResizable">FALSE</boolean>
|
||||
<boolean name="hasVerticalZoom">FALSE</boolean>
|
||||
<boolean name="liveResize">TRUE</boolean>
|
||||
<boolean name="compositing">TRUE</boolean>
|
||||
<int name="carbonWindowClass">4</int>
|
||||
<int name="windowPosition">1</int>
|
||||
<boolean name="isConstrained">FALSE</boolean>
|
||||
</object>
|
||||
<reference idRef="192"/>
|
||||
<reference idRef="200"/>
|
||||
<reference idRef="201"/>
|
||||
</array>
|
||||
<array count="31" name="allParents">
|
||||
<reference idRef="1"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="127"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="152"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="153"/>
|
||||
<reference idRef="154"/>
|
||||
<reference idRef="154"/>
|
||||
<reference idRef="154"/>
|
||||
<reference idRef="182"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="181"/>
|
||||
<reference idRef="154"/>
|
||||
<reference idRef="154"/>
|
||||
<reference idRef="154"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="147"/>
|
||||
<reference idRef="191"/>
|
||||
<reference idRef="1"/>
|
||||
<reference idRef="190"/>
|
||||
<reference idRef="201"/>
|
||||
<reference idRef="190"/>
|
||||
</array>
|
||||
<dictionary count="3" name="nameTable">
|
||||
<string>Files Owner</string>
|
||||
<reference idRef="1"/>
|
||||
<string>MenuBar</string>
|
||||
<reference idRef="29"/>
|
||||
<string>Release Notes</string>
|
||||
<reference idRef="191"/>
|
||||
</dictionary>
|
||||
<unsigned_int name="nextObjectID">202</unsigned_int>
|
||||
</object>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1 +1 @@
|
|||
3.6.5
|
||||
3.6.6
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ out vec4 frag_color;
|
|||
//class 1 -- no shadows
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
|
||||
uniform sampler2DRect diffuseRect;
|
||||
uniform sampler2DRect specularRect;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@
|
|||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
|
|
@ -31,6 +32,8 @@ out vec4 frag_color;
|
|||
#define frag_color gl_FragColor
|
||||
#endif
|
||||
|
||||
//class 1 -- no shadows
|
||||
|
||||
uniform sampler2DRect diffuseRect;
|
||||
uniform sampler2DRect specularRect;
|
||||
uniform sampler2DRect depthMap;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
#extension GL_ARB_shader_texture_lod : enable
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
* @file llappdelegate-objc.mm
|
||||
* @brief Class implementation for the Mac version's application delegate.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#import "llappdelegate-objc.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
#include <Carbon/Carbon.h> // Used for Text Input Services ("Safe" API - it's supported)
|
||||
|
||||
@implementation LLAppDelegate
|
||||
|
||||
@synthesize window;
|
||||
@synthesize inputWindow;
|
||||
@synthesize inputView;
|
||||
@synthesize currentInputLanguage;
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) applicationDidFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
frameTimer = nil;
|
||||
|
||||
[self languageUpdated];
|
||||
|
||||
if (initViewer())
|
||||
{
|
||||
frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
|
||||
} else {
|
||||
handleQuit();
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];
|
||||
}
|
||||
|
||||
- (void) applicationDidBecomeActive:(NSNotification *)notification
|
||||
{
|
||||
callWindowFocus();
|
||||
}
|
||||
|
||||
- (void) applicationDidResignActive:(NSNotification *)notification
|
||||
{
|
||||
callWindowUnfocus();
|
||||
}
|
||||
|
||||
- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
if (!runMainLoop())
|
||||
{
|
||||
handleQuit();
|
||||
return NSTerminateCancel;
|
||||
} else {
|
||||
[frameTimer release];
|
||||
cleanupViewer();
|
||||
return NSTerminateNow;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) mainLoop
|
||||
{
|
||||
bool appExiting = runMainLoop();
|
||||
if (appExiting)
|
||||
{
|
||||
[frameTimer release];
|
||||
[[NSApplication sharedApplication] terminate:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent
|
||||
{
|
||||
if (![self romanScript])
|
||||
{
|
||||
if (show)
|
||||
{
|
||||
NSLog(@"Showing input window.");
|
||||
[inputWindow makeKeyAndOrderFront:inputWindow];
|
||||
if (textEvent != nil)
|
||||
{
|
||||
[[inputView inputContext] discardMarkedText];
|
||||
[[inputView inputContext] handleEvent:textEvent];
|
||||
}
|
||||
} else {
|
||||
NSLog(@"Hiding input window.");
|
||||
[inputWindow orderOut:inputWindow];
|
||||
[window makeKeyAndOrderFront:window];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will get called multiple times by NSNotificationCenter.
|
||||
// It will be called every time that the window focus changes, and every time that the input language gets changed.
|
||||
// The primary use case for this selector is to update our current input language when the user, for whatever reason, changes the input language.
|
||||
// This is the more elegant way of handling input language changes instead of checking every time we want to use the input window.
|
||||
|
||||
- (void) languageUpdated
|
||||
{
|
||||
TISInputSourceRef currentInput = TISCopyCurrentKeyboardInputSource();
|
||||
CFArrayRef languages = (CFArrayRef)TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages);
|
||||
|
||||
#if 0 // In the event of ever needing to add new language sources, change this to 1 and watch the terminal for "languages:"
|
||||
NSLog(@"languages: %@", TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages));
|
||||
#endif
|
||||
|
||||
// Typically the language we want is going to be the very first result in the array.
|
||||
currentInputLanguage = (NSString*)CFArrayGetValueAtIndex(languages, 0);
|
||||
}
|
||||
|
||||
- (bool) romanScript
|
||||
{
|
||||
// How to add support for new languages with the input window:
|
||||
// Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.)
|
||||
NSArray *nonRomanScript = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil];
|
||||
if ([nonRomanScript containsObject:currentInputLanguage])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -728,6 +728,11 @@ bool LLAppViewer::init()
|
|||
// we run the "program crashed last time" error handler below.
|
||||
//
|
||||
LLFastTimer::reset();
|
||||
|
||||
|
||||
#ifdef LL_DARWIN
|
||||
mMainLoopInitialized = false;
|
||||
#endif
|
||||
|
||||
// initialize LLWearableType translation bridge.
|
||||
// Memory will be cleaned up in ::cleanupClass()
|
||||
|
|
@ -1258,40 +1263,57 @@ LLFastTimer::DeclareTimer FTM_FRAME("Frame", true);
|
|||
|
||||
bool LLAppViewer::mainLoop()
|
||||
{
|
||||
mMainloopTimeout = new LLWatchdogTimeout();
|
||||
#ifdef LL_DARWIN
|
||||
if (!mMainLoopInitialized)
|
||||
#endif
|
||||
{
|
||||
mMainloopTimeout = new LLWatchdogTimeout();
|
||||
|
||||
//-------------------------------------------
|
||||
// Run main loop until time to quit
|
||||
//-------------------------------------------
|
||||
|
||||
// Create IO Pump to use for HTTP Requests.
|
||||
gServicePump = new LLPumpIO(gAPRPoolp);
|
||||
LLHTTPClient::setPump(*gServicePump);
|
||||
LLCurl::setCAFile(gDirUtilp->getCAFile());
|
||||
|
||||
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
|
||||
|
||||
LLVoiceChannel::initClass();
|
||||
LLVoiceClient::getInstance()->init(gServicePump);
|
||||
LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
|
||||
|
||||
joystick = LLViewerJoystick::getInstance();
|
||||
joystick->setNeedsReset(true);
|
||||
|
||||
#ifdef LL_DARWIN
|
||||
// Ensure that this section of code never gets called again on OS X.
|
||||
mMainLoopInitialized = true;
|
||||
#endif
|
||||
}
|
||||
// As we do not (yet) send data on the mainloop LLEventPump that varies
|
||||
// with each frame, no need to instantiate a new LLSD event object each
|
||||
// time. Obviously, if that changes, just instantiate the LLSD at the
|
||||
// point of posting.
|
||||
|
||||
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
|
||||
|
||||
LLSD newFrame;
|
||||
|
||||
//-------------------------------------------
|
||||
// Run main loop until time to quit
|
||||
//-------------------------------------------
|
||||
|
||||
// Create IO Pump to use for HTTP Requests.
|
||||
gServicePump = new LLPumpIO(gAPRPoolp);
|
||||
LLHTTPClient::setPump(*gServicePump);
|
||||
LLCurl::setCAFile(gDirUtilp->getCAFile());
|
||||
|
||||
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
|
||||
|
||||
LLVoiceChannel::initClass();
|
||||
LLVoiceClient::getInstance()->init(gServicePump);
|
||||
LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
|
||||
LLTimer frameTimer,idleTimer;
|
||||
LLTimer debugTime;
|
||||
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
|
||||
joystick->setNeedsReset(true);
|
||||
|
||||
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
|
||||
// As we do not (yet) send data on the mainloop LLEventPump that varies
|
||||
// with each frame, no need to instantiate a new LLSD event object each
|
||||
// time. Obviously, if that changes, just instantiate the LLSD at the
|
||||
// point of posting.
|
||||
LLSD newFrame;
|
||||
|
||||
|
||||
//LLPrivateMemoryPoolTester::getInstance()->run(false) ;
|
||||
//LLPrivateMemoryPoolTester::getInstance()->run(true) ;
|
||||
//LLPrivateMemoryPoolTester::destroy() ;
|
||||
|
||||
// Handle messages
|
||||
#ifdef LL_DARWIN
|
||||
if (!LLApp::isExiting())
|
||||
#else
|
||||
while (!LLApp::isExiting())
|
||||
#endif
|
||||
{
|
||||
LLFastTimer _(FTM_FRAME);
|
||||
LLFastTimer::nextFrame();
|
||||
|
|
@ -1567,34 +1589,37 @@ bool LLAppViewer::mainLoop()
|
|||
}
|
||||
}
|
||||
|
||||
// Save snapshot for next time, if we made it through initialization
|
||||
if (STATE_STARTED == LLStartUp::getStartupState())
|
||||
if (LLApp::isExiting())
|
||||
{
|
||||
try
|
||||
// Save snapshot for next time, if we made it through initialization
|
||||
if (STATE_STARTED == LLStartUp::getStartupState())
|
||||
{
|
||||
saveFinalSnapshot();
|
||||
}
|
||||
catch(std::bad_alloc)
|
||||
{
|
||||
llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
|
||||
|
||||
//stop memory leaking simulation
|
||||
LLFloaterMemLeak* mem_leak_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
|
||||
if(mem_leak_instance)
|
||||
try
|
||||
{
|
||||
mem_leak_instance->stop() ;
|
||||
}
|
||||
saveFinalSnapshot();
|
||||
}
|
||||
catch(std::bad_alloc)
|
||||
{
|
||||
llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
|
||||
|
||||
//stop memory leaking simulation
|
||||
LLFloaterMemLeak* mem_leak_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
|
||||
if(mem_leak_instance)
|
||||
{
|
||||
mem_leak_instance->stop() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete gServicePump;
|
||||
|
||||
destroyMainloopTimeout();
|
||||
|
||||
llinfos << "Exiting main_loop" << llendflush;
|
||||
}
|
||||
|
||||
delete gServicePump;
|
||||
|
||||
destroyMainloopTimeout();
|
||||
|
||||
llinfos << "Exiting main_loop" << llendflush;
|
||||
|
||||
return true;
|
||||
return LLApp::isExiting();
|
||||
}
|
||||
|
||||
void LLAppViewer::flushVFSIO()
|
||||
|
|
@ -2674,8 +2699,6 @@ bool LLAppViewer::initConfiguration()
|
|||
//}
|
||||
|
||||
#if LL_DARWIN
|
||||
// Initialize apple menubar and various callbacks
|
||||
init_apple_menu(LLTrans::getString("APP_NAME").c_str());
|
||||
|
||||
#if __ppc__
|
||||
// If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ class LLImageDecodeThread;
|
|||
class LLTextureFetch;
|
||||
class LLWatchdogTimeout;
|
||||
class LLUpdaterService;
|
||||
class LLViewerJoystick;
|
||||
|
||||
extern LLFastTimer::DeclareTimer FTM_FRAME;
|
||||
|
||||
|
|
@ -255,6 +256,8 @@ private:
|
|||
std::string mSerialNumber;
|
||||
bool mPurgeCache;
|
||||
bool mPurgeOnExit;
|
||||
bool mMainLoopInitialized;
|
||||
LLViewerJoystick* joystick;
|
||||
|
||||
bool mSavedFinalSnapshot;
|
||||
bool mSavePerAccountSettings; // only save per account settings if login succeeded
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@
|
|||
#error "Use only with Mac OS X"
|
||||
#endif
|
||||
|
||||
#define LL_CARBON_CRASH_HANDLER 1
|
||||
|
||||
#include "llappviewermacosx.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
#include "llcommandlineparser.h"
|
||||
|
||||
#include "llviewernetwork.h"
|
||||
|
|
@ -38,7 +41,10 @@
|
|||
#include "llmd5.h"
|
||||
#include "llfloaterworldmap.h"
|
||||
#include "llurldispatcher.h"
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#ifdef LL_CARBON_CRASH_HANDLER
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
#include "lldir.h"
|
||||
#include <signal.h>
|
||||
#include <CoreAudio/CoreAudio.h> // for systemwide mute
|
||||
|
|
@ -50,9 +56,9 @@ namespace
|
|||
// They are not used immediately by the app.
|
||||
int gArgC;
|
||||
char** gArgV;
|
||||
|
||||
bool sCrashReporterIsRunning = false;
|
||||
|
||||
LLAppViewerMacOSX* gViewerAppPtr;
|
||||
#ifdef LL_CARBON_CRASH_HANDLER
|
||||
OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
|
||||
{
|
||||
OSErr result = noErr;
|
||||
|
|
@ -61,9 +67,10 @@ namespace
|
|||
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
bool initViewer()
|
||||
{
|
||||
#if LL_SOLARIS && defined(__sparc)
|
||||
asm ("ta\t6"); // NOTE: Make sure memory alignment is enforced on SPARC
|
||||
|
|
@ -73,43 +80,60 @@ int main( int argc, char **argv )
|
|||
if (chdir(gDirUtilp->getAppRODataDir().c_str()) == -1)
|
||||
{
|
||||
llwarns << "Could not change directory to "
|
||||
<< gDirUtilp->getAppRODataDir() << ": " << strerror(errno)
|
||||
<< llendl;
|
||||
<< gDirUtilp->getAppRODataDir() << ": " << strerror(errno)
|
||||
<< llendl;
|
||||
}
|
||||
|
||||
LLAppViewerMacOSX* viewer_app_ptr = new LLAppViewerMacOSX();
|
||||
|
||||
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
|
||||
// Store off the command line args for use later.
|
||||
gArgC = argc;
|
||||
gArgV = argv;
|
||||
|
||||
bool ok = viewer_app_ptr->init();
|
||||
gViewerAppPtr = new LLAppViewerMacOSX();
|
||||
|
||||
gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
|
||||
|
||||
|
||||
bool ok = gViewerAppPtr->init();
|
||||
if(!ok)
|
||||
{
|
||||
llwarns << "Application init failed." << llendl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Run the application main loop
|
||||
if(!LLApp::isQuitting())
|
||||
{
|
||||
viewer_app_ptr->mainLoop();
|
||||
}
|
||||
void handleQuit()
|
||||
{
|
||||
LLAppViewer::instance()->userQuit();
|
||||
}
|
||||
|
||||
if (!LLApp::isError())
|
||||
bool runMainLoop()
|
||||
{
|
||||
bool ret = LLApp::isQuitting();
|
||||
if (!ret && gViewerAppPtr != NULL)
|
||||
{
|
||||
//
|
||||
// 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();
|
||||
ret = gViewerAppPtr->mainLoop();
|
||||
} else {
|
||||
ret = true;
|
||||
}
|
||||
delete viewer_app_ptr;
|
||||
viewer_app_ptr = NULL;
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cleanupViewer()
|
||||
{
|
||||
if(!LLApp::isError())
|
||||
{
|
||||
gViewerAppPtr->cleanup();
|
||||
}
|
||||
|
||||
delete gViewerAppPtr;
|
||||
gViewerAppPtr = NULL;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// Store off the command line args for use later.
|
||||
gArgC = argc;
|
||||
gArgV = argv;
|
||||
return createNSApp(argc, (const char**)argv);
|
||||
}
|
||||
|
||||
LLAppViewerMacOSX::LLAppViewerMacOSX()
|
||||
|
|
@ -239,23 +263,24 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
|
|||
return reset_count == 0;
|
||||
}
|
||||
|
||||
static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
|
||||
EventRef inEvent,
|
||||
#ifdef LL_CARBON_CRASH_HANDLER
|
||||
static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
|
||||
EventRef inEvent,
|
||||
void* inUserData)
|
||||
{
|
||||
ProcessSerialNumber psn;
|
||||
|
||||
GetEventParameter(inEvent,
|
||||
kEventParamProcessID,
|
||||
typeProcessSerialNumber,
|
||||
NULL,
|
||||
sizeof(psn),
|
||||
NULL,
|
||||
GetEventParameter(inEvent,
|
||||
kEventParamProcessID,
|
||||
typeProcessSerialNumber,
|
||||
NULL,
|
||||
sizeof(psn),
|
||||
NULL,
|
||||
&psn);
|
||||
|
||||
if( GetEventKind(inEvent) == kEventAppTerminated )
|
||||
if( GetEventKind(inEvent) == kEventAppTerminated )
|
||||
{
|
||||
Boolean matching_psn = FALSE;
|
||||
Boolean matching_psn = FALSE;
|
||||
OSErr os_result = SameProcess(&psn, (ProcessSerialNumber*)inUserData, &matching_psn);
|
||||
if(os_result >= 0 && matching_psn)
|
||||
{
|
||||
|
|
@ -265,48 +290,58 @@ static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
|
|||
}
|
||||
return noErr;
|
||||
}
|
||||
#endif
|
||||
|
||||
void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
|
||||
{
|
||||
// This used to use fork&exec, but is switched to LSOpenApplication to
|
||||
#ifdef LL_CARBON_CRASH_HANDLER
|
||||
// This used to use fork&exec, but is switched to LSOpenApplication to
|
||||
// Make sure the crash reporter launches in front of the SL window.
|
||||
|
||||
std::string command_str;
|
||||
//command_str = "open Second Life.app/Contents/Resources/mac-crash-logger.app";
|
||||
command_str = "mac-crash-logger.app/Contents/MacOS/mac-crash-logger";
|
||||
|
||||
CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)command_str.c_str(), strlen(command_str.c_str()), FALSE);
|
||||
|
||||
// FSRef apparently isn't deprecated.
|
||||
// There's other funcitonality that depends on it existing as well that isn't deprecated.
|
||||
// There doesn't seem to be much to directly verify what the status of FSRef is, outside of some documentation pointing at FSRef being valid, and other documentation pointing to everything in Files.h being deprecated.
|
||||
// We'll assume it isn't for now, since all non-deprecated functions that use it seem to assume similar.
|
||||
|
||||
FSRef appRef;
|
||||
Boolean isDir = 0;
|
||||
OSStatus os_result = FSPathMakeRef((UInt8*)command_str.c_str(),
|
||||
&appRef,
|
||||
&isDir);
|
||||
if(os_result >= 0)
|
||||
Boolean pathstatus = CFURLGetFSRef(urlRef, &appRef);
|
||||
|
||||
OSStatus os_result = noErr;
|
||||
|
||||
if(pathstatus == true)
|
||||
{
|
||||
LSApplicationParameters appParams;
|
||||
memset(&appParams, 0, sizeof(appParams));
|
||||
appParams.version = 0;
|
||||
appParams.flags = kLSLaunchNoParams | kLSLaunchStartClassic;
|
||||
|
||||
appParams.application = &appRef;
|
||||
|
||||
if(reportFreeze)
|
||||
{
|
||||
// Make sure freeze reporting launches the crash logger synchronously, lest
|
||||
// Make sure freeze reporting launches the crash logger synchronously, lest
|
||||
// Log files get changed by SL while the logger is running.
|
||||
|
||||
|
||||
// *NOTE:Mani A better way - make a copy of the data that the crash reporter will send
|
||||
// and let SL go about its business. This way makes the mac work like windows and linux
|
||||
// and is the smallest patch for the issue.
|
||||
// and is the smallest patch for the issue.
|
||||
sCrashReporterIsRunning = false;
|
||||
ProcessSerialNumber o_psn;
|
||||
|
||||
|
||||
static EventHandlerRef sCarbonEventsRef = NULL;
|
||||
static const EventTypeSpec kEvents[] =
|
||||
static const EventTypeSpec kEvents[] =
|
||||
{
|
||||
{ kEventClassApplication, kEventAppTerminated }
|
||||
};
|
||||
|
||||
// Install the handler to detect crash logger termination
|
||||
InstallEventHandler(GetApplicationEventTarget(),
|
||||
InstallEventHandler(GetApplicationEventTarget(),
|
||||
(EventHandlerUPP) CarbonEventHandler,
|
||||
GetEventTypeCount(kEvents),
|
||||
kEvents,
|
||||
|
|
@ -314,31 +349,31 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
|
|||
&sCarbonEventsRef
|
||||
);
|
||||
|
||||
// Remove, temporarily the quit handler - which has *crash* behavior before
|
||||
// Remove, temporarily the quit handler - which has *crash* behavior before
|
||||
// the mainloop gets running!
|
||||
AERemoveEventHandler(kCoreEventClass,
|
||||
kAEQuitApplication,
|
||||
AERemoveEventHandler(kCoreEventClass,
|
||||
kAEQuitApplication,
|
||||
NewAEEventHandlerUPP(AEQuitHandler),
|
||||
false);
|
||||
|
||||
|
||||
// Launch the crash reporter.
|
||||
os_result = LSOpenApplication(&appParams, &o_psn);
|
||||
|
||||
if(os_result >= 0)
|
||||
{
|
||||
{
|
||||
sCrashReporterIsRunning = true;
|
||||
}
|
||||
|
||||
|
||||
while(sCrashReporterIsRunning)
|
||||
{
|
||||
RunApplicationEventLoop();
|
||||
}
|
||||
|
||||
|
||||
// Re-install the apps quit handler.
|
||||
AEInstallEventHandler(kCoreEventClass,
|
||||
kAEQuitApplication,
|
||||
AEInstallEventHandler(kCoreEventClass,
|
||||
kAEQuitApplication,
|
||||
NewAEEventHandlerUPP(AEQuitHandler),
|
||||
0,
|
||||
0,
|
||||
false);
|
||||
|
||||
// Remove the crash reporter quit handler.
|
||||
|
|
@ -348,12 +383,12 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
|
|||
{
|
||||
appParams.flags |= kLSLaunchAsync;
|
||||
clear_signals();
|
||||
|
||||
|
||||
ProcessSerialNumber o_psn;
|
||||
os_result = LSOpenApplication(&appParams, &o_psn);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string LLAppViewerMacOSX::generateSerialNumber()
|
||||
|
|
@ -486,73 +521,3 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include "llwindow.h" // beforeDialog()
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
#if LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||
# include "llfilepicker.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -147,152 +147,36 @@ std::string LLDirPicker::getDirName()
|
|||
#elif LL_DARWIN
|
||||
|
||||
LLDirPicker::LLDirPicker() :
|
||||
mFileName(NULL),
|
||||
mLocked(false)
|
||||
mFileName(NULL),
|
||||
mLocked(false)
|
||||
{
|
||||
mFilePicker = new LLFilePicker();
|
||||
reset();
|
||||
|
||||
memset(&mNavOptions, 0, sizeof(mNavOptions));
|
||||
OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
|
||||
if (error == noErr)
|
||||
{
|
||||
mNavOptions.modality = kWindowModalityAppModal;
|
||||
}
|
||||
}
|
||||
|
||||
LLDirPicker::~LLDirPicker()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
//static
|
||||
pascal void LLDirPicker::doNavCallbackEvent(NavEventCallbackMessage callBackSelector,
|
||||
NavCBRecPtr callBackParms, void* callBackUD)
|
||||
{
|
||||
switch(callBackSelector)
|
||||
{
|
||||
case kNavCBStart:
|
||||
{
|
||||
if (!sInstance.mFileName) break;
|
||||
|
||||
OSStatus error = noErr;
|
||||
AEDesc theLocation = {typeNull, NULL};
|
||||
FSSpec outFSSpec;
|
||||
|
||||
//Convert string to a FSSpec
|
||||
FSRef myFSRef;
|
||||
|
||||
const char* filename=sInstance.mFileName->c_str();
|
||||
|
||||
error = FSPathMakeRef ((UInt8*)filename, &myFSRef, NULL);
|
||||
|
||||
if (error != noErr) break;
|
||||
|
||||
error = FSGetCatalogInfo (&myFSRef, kFSCatInfoNone, NULL, NULL, &outFSSpec, NULL);
|
||||
|
||||
if (error != noErr) break;
|
||||
|
||||
error = AECreateDesc(typeFSS, &outFSSpec, sizeof(FSSpec), &theLocation);
|
||||
|
||||
if (error != noErr) break;
|
||||
|
||||
error = NavCustomControl(callBackParms->context,
|
||||
kNavCtlSetLocation, (void*)&theLocation);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OSStatus LLDirPicker::doNavChooseDialog()
|
||||
{
|
||||
OSStatus error = noErr;
|
||||
NavDialogRef navRef = NULL;
|
||||
NavReplyRecord navReply;
|
||||
|
||||
memset(&navReply, 0, sizeof(navReply));
|
||||
|
||||
// NOTE: we are passing the address of a local variable here.
|
||||
// This is fine, because the object this call creates will exist for less than the lifetime of this function.
|
||||
// (It is destroyed by NavDialogDispose() below.)
|
||||
|
||||
error = NavCreateChooseFolderDialog(&mNavOptions, &doNavCallbackEvent, NULL, NULL, &navRef);
|
||||
|
||||
gViewerWindow->getWindow()->beforeDialog();
|
||||
|
||||
if (error == noErr)
|
||||
error = NavDialogRun(navRef);
|
||||
|
||||
gViewerWindow->getWindow()->afterDialog();
|
||||
|
||||
if (error == noErr)
|
||||
error = NavDialogGetReply(navRef, &navReply);
|
||||
|
||||
if (navRef)
|
||||
NavDialogDispose(navRef);
|
||||
|
||||
if (error == noErr && navReply.validRecord)
|
||||
{
|
||||
FSRef fsRef;
|
||||
AEKeyword theAEKeyword;
|
||||
DescType typeCode;
|
||||
Size actualSize = 0;
|
||||
char path[LL_MAX_PATH]; /*Flawfinder: ignore*/
|
||||
|
||||
memset(&fsRef, 0, sizeof(fsRef));
|
||||
error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
|
||||
|
||||
if (error == noErr)
|
||||
error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
|
||||
|
||||
if (error == noErr)
|
||||
mDir = path;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
BOOL LLDirPicker::getDir(std::string* filename)
|
||||
{
|
||||
if( mLocked ) return FALSE;
|
||||
BOOL success = FALSE;
|
||||
OSStatus error = noErr;
|
||||
|
||||
// if local file browsing is turned off, return without opening dialog
|
||||
if ( check_local_file_access_enabled() == false )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mFileName = filename;
|
||||
|
||||
// mNavOptions.saveFileName
|
||||
|
||||
// Modal, so pause agent
|
||||
send_agent_pause();
|
||||
{
|
||||
error = doNavChooseDialog();
|
||||
}
|
||||
send_agent_resume();
|
||||
if (error == noErr)
|
||||
{
|
||||
if (mDir.length() > 0)
|
||||
success = true;
|
||||
}
|
||||
|
||||
// Account for the fact that the app has been stalled.
|
||||
LLFrameTimer::updateFrameTime();
|
||||
return success;
|
||||
}
|
||||
|
||||
std::string LLDirPicker::getDirName()
|
||||
{
|
||||
return mDir;
|
||||
delete mFilePicker;
|
||||
}
|
||||
|
||||
void LLDirPicker::reset()
|
||||
{
|
||||
mLocked = false;
|
||||
mDir.clear();
|
||||
if (mFilePicker)
|
||||
mFilePicker->reset();
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
BOOL LLDirPicker::getDir(std::string* filename)
|
||||
{
|
||||
LLFilePicker::ELoadFilter filter=LLFilePicker::FFLOAD_DIRECTORY;
|
||||
|
||||
return mFilePicker->getOpenFile(filter, true);
|
||||
}
|
||||
|
||||
std::string LLDirPicker::getDirName()
|
||||
{
|
||||
return mFilePicker->getFirstFile();
|
||||
}
|
||||
|
||||
#elif LL_LINUX || LL_SOLARIS
|
||||
|
|
|
|||
|
|
@ -34,11 +34,10 @@
|
|||
#include "stdtypes.h"
|
||||
|
||||
#if LL_DARWIN
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
// AssertMacros.h does bad things.
|
||||
#include "fix_macros.h"
|
||||
#undef verify
|
||||
#undef check
|
||||
#undef require
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -77,15 +76,7 @@ private:
|
|||
void buildDirname( void );
|
||||
bool check_local_file_access_enabled();
|
||||
|
||||
#if LL_DARWIN
|
||||
NavDialogCreationOptions mNavOptions;
|
||||
static pascal void doNavCallbackEvent(NavEventCallbackMessage callBackSelector,
|
||||
NavCBRecPtr callBackParms, void* callBackUD);
|
||||
OSStatus doNavChooseDialog();
|
||||
|
||||
#endif
|
||||
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
#if LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||
// On Linux we just implement LLDirPicker on top of LLFilePicker
|
||||
LLFilePicker *mFilePicker;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ LLFilePicker LLFilePicker::sInstance;
|
|||
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
|
||||
#endif
|
||||
|
||||
#ifdef LL_DARWIN
|
||||
#include "llfilepicker_mac.h"
|
||||
//#include <boost/algorithm/string/predicate.hpp>
|
||||
#endif
|
||||
|
||||
//
|
||||
// Implementation
|
||||
//
|
||||
|
|
@ -94,14 +99,6 @@ LLFilePicker::LLFilePicker()
|
|||
mFilesW[0] = '\0';
|
||||
#endif
|
||||
|
||||
#if LL_DARWIN
|
||||
memset(&mNavOptions, 0, sizeof(mNavOptions));
|
||||
OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
|
||||
if (error == noErr)
|
||||
{
|
||||
mNavOptions.modality = kWindowModalityAppModal;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
LLFilePicker::~LLFilePicker()
|
||||
|
|
@ -546,369 +543,197 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
|
|||
|
||||
#elif LL_DARWIN
|
||||
|
||||
Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
|
||||
std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
|
||||
{
|
||||
Boolean result = true;
|
||||
ELoadFilter filter = *((ELoadFilter*) callBackUD);
|
||||
OSStatus error = noErr;
|
||||
|
||||
if (filterMode == kNavFilteringBrowserList && filter != FFLOAD_ALL && (theItem->descriptorType == typeFSRef || theItem->descriptorType == typeFSS))
|
||||
{
|
||||
// navInfo is only valid for typeFSRef and typeFSS
|
||||
NavFileOrFolderInfo *navInfo = (NavFileOrFolderInfo*) info;
|
||||
if (!navInfo->isFolder)
|
||||
{
|
||||
AEDesc desc;
|
||||
error = AECoerceDesc(theItem, typeFSRef, &desc);
|
||||
if (error == noErr)
|
||||
{
|
||||
FSRef fileRef;
|
||||
error = AEGetDescData(&desc, &fileRef, sizeof(fileRef));
|
||||
if (error == noErr)
|
||||
{
|
||||
LSItemInfoRecord fileInfo;
|
||||
error = LSCopyItemInfoForRef(&fileRef, kLSRequestExtension | kLSRequestTypeCreator, &fileInfo);
|
||||
if (error == noErr)
|
||||
{
|
||||
if (filter == FFLOAD_IMAGE)
|
||||
{
|
||||
if (fileInfo.filetype != 'JPEG' && fileInfo.filetype != 'JPG ' &&
|
||||
fileInfo.filetype != 'BMP ' && fileInfo.filetype != 'TGA ' &&
|
||||
fileInfo.filetype != 'BMPf' && fileInfo.filetype != 'TPIC' &&
|
||||
fileInfo.filetype != 'PNG ' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("jpeg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
|
||||
CFStringCompare(fileInfo.extension, CFSTR("jpg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
|
||||
CFStringCompare(fileInfo.extension, CFSTR("bmp"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
|
||||
CFStringCompare(fileInfo.extension, CFSTR("tga"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
|
||||
CFStringCompare(fileInfo.extension, CFSTR("png"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else if (filter == FFLOAD_WAV)
|
||||
{
|
||||
if (fileInfo.filetype != 'WAVE' && fileInfo.filetype != 'WAV ' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("wave"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
|
||||
CFStringCompare(fileInfo.extension, CFSTR("wav"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else if (filter == FFLOAD_ANIM)
|
||||
{
|
||||
if (fileInfo.filetype != 'BVH ' &&
|
||||
fileInfo.filetype != 'ANIM' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
|
||||
fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("anim"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else if (filter == FFLOAD_COLLADA)
|
||||
{
|
||||
if (fileInfo.filetype != 'DAE ' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dae"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
std::vector<std::string> *allowedv = new std::vector< std::string >;
|
||||
switch(filter)
|
||||
{
|
||||
case FFLOAD_ALL:
|
||||
allowedv->push_back("wav");
|
||||
allowedv->push_back("bvh");
|
||||
allowedv->push_back("anim");
|
||||
allowedv->push_back("dae");
|
||||
allowedv->push_back("raw");
|
||||
allowedv->push_back("lsl");
|
||||
allowedv->push_back("dic");
|
||||
allowedv->push_back("xcu");
|
||||
case FFLOAD_IMAGE:
|
||||
allowedv->push_back("jpg");
|
||||
allowedv->push_back("jpeg");
|
||||
allowedv->push_back("bmp");
|
||||
allowedv->push_back("tga");
|
||||
allowedv->push_back("bmpf");
|
||||
allowedv->push_back("tpic");
|
||||
allowedv->push_back("png");
|
||||
break;
|
||||
case FFLOAD_WAV:
|
||||
allowedv->push_back("wav");
|
||||
break;
|
||||
case FFLOAD_ANIM:
|
||||
allowedv->push_back("bvh");
|
||||
allowedv->push_back("anim");
|
||||
break;
|
||||
case FFLOAD_COLLADA:
|
||||
allowedv->push_back("dae");
|
||||
break;
|
||||
#ifdef _CORY_TESTING
|
||||
else if (filter == FFLOAD_GEOMETRY)
|
||||
{
|
||||
if (fileInfo.filetype != 'SLG ' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("slg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
case FFLOAD_GEOMETRY:
|
||||
allowedv->push_back("slg");
|
||||
break;
|
||||
#endif
|
||||
else if (filter == FFLOAD_SLOBJECT)
|
||||
{
|
||||
llwarns << "*** navOpenFilterProc: FFLOAD_SLOBJECT NOT IMPLEMENTED ***" << llendl;
|
||||
}
|
||||
else if (filter == FFLOAD_RAW)
|
||||
{
|
||||
if (fileInfo.filetype != '\?\?\?\?' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("raw"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else if (filter == FFLOAD_SCRIPT)
|
||||
{
|
||||
if (fileInfo.filetype != 'LSL ' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("lsl"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) )
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else if (filter == FFLOAD_DICTIONARY)
|
||||
{
|
||||
if (fileInfo.filetype != 'DIC ' &&
|
||||
fileInfo.filetype != 'XCU ' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
|
||||
fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xcu"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileInfo.extension)
|
||||
{
|
||||
CFRelease(fileInfo.extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
AEDisposeDesc(&desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
case FFLOAD_RAW:
|
||||
allowedv->push_back("raw");
|
||||
break;
|
||||
case FFLOAD_SCRIPT:
|
||||
allowedv->push_back("lsl");
|
||||
break;
|
||||
case FFLOAD_DICTIONARY:
|
||||
allowedv->push_back("dic");
|
||||
allowedv->push_back("xcu");
|
||||
break;
|
||||
case FFLOAD_DIRECTORY:
|
||||
break;
|
||||
default:
|
||||
llwarns << "Unsupported format." << llendl;
|
||||
}
|
||||
|
||||
return allowedv;
|
||||
}
|
||||
|
||||
OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter)
|
||||
bool LLFilePicker::doNavChooseDialog(ELoadFilter filter)
|
||||
{
|
||||
OSStatus error = noErr;
|
||||
NavDialogRef navRef = NULL;
|
||||
NavReplyRecord navReply;
|
||||
|
||||
// if local file browsing is turned off, return without opening dialog
|
||||
if ( check_local_file_access_enabled() == false )
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&navReply, 0, sizeof(navReply));
|
||||
|
||||
// NOTE: we are passing the address of a local variable here.
|
||||
// This is fine, because the object this call creates will exist for less than the lifetime of this function.
|
||||
// (It is destroyed by NavDialogDispose() below.)
|
||||
error = NavCreateChooseFileDialog(&mNavOptions, NULL, NULL, NULL, navOpenFilterProc, (void*)(&filter), &navRef);
|
||||
|
||||
|
||||
gViewerWindow->getWindow()->beforeDialog();
|
||||
|
||||
if (error == noErr)
|
||||
error = NavDialogRun(navRef);
|
||||
|
||||
std::vector<std::string> *allowed_types=navOpenFilterProc(filter);
|
||||
|
||||
std::vector<std::string> *filev = doLoadDialog(allowed_types,
|
||||
mPickOptions);
|
||||
|
||||
gViewerWindow->getWindow()->afterDialog();
|
||||
|
||||
if (error == noErr)
|
||||
error = NavDialogGetReply(navRef, &navReply);
|
||||
|
||||
if (navRef)
|
||||
NavDialogDispose(navRef);
|
||||
|
||||
if (error == noErr && navReply.validRecord)
|
||||
{
|
||||
SInt32 count = 0;
|
||||
SInt32 index;
|
||||
|
||||
// AE indexes are 1 based...
|
||||
error = AECountItems(&navReply.selection, &count);
|
||||
for (index = 1; index <= count; index++)
|
||||
{
|
||||
FSRef fsRef;
|
||||
AEKeyword theAEKeyword;
|
||||
DescType typeCode;
|
||||
Size actualSize = 0;
|
||||
char path[MAX_PATH]; /*Flawfinder: ignore*/
|
||||
|
||||
memset(&fsRef, 0, sizeof(fsRef));
|
||||
error = AEGetNthPtr(&navReply.selection, index, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
|
||||
|
||||
if (error == noErr)
|
||||
error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
|
||||
|
||||
if (error == noErr)
|
||||
mFiles.push_back(std::string(path));
|
||||
}
|
||||
}
|
||||
if (filev && filev->size() > 0)
|
||||
{
|
||||
mFiles.insert(mFiles.end(), filev->begin(), filev->end());
|
||||
return true;
|
||||
}
|
||||
|
||||
return error;
|
||||
return false;
|
||||
}
|
||||
|
||||
OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
|
||||
bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
|
||||
{
|
||||
OSStatus error = noErr;
|
||||
NavDialogRef navRef = NULL;
|
||||
NavReplyRecord navReply;
|
||||
|
||||
memset(&navReply, 0, sizeof(navReply));
|
||||
|
||||
// Setup the type, creator, and extension
|
||||
OSType type, creator;
|
||||
CFStringRef extension = NULL;
|
||||
std::string extension, type, creator;
|
||||
|
||||
switch (filter)
|
||||
{
|
||||
case FFSAVE_WAV:
|
||||
type = 'WAVE';
|
||||
creator = 'TVOD';
|
||||
extension = CFSTR(".wav");
|
||||
type = "WAVE";
|
||||
creator = "TVOD";
|
||||
extension = "wav";
|
||||
break;
|
||||
|
||||
case FFSAVE_TGA:
|
||||
type = 'TPIC';
|
||||
creator = 'prvw';
|
||||
extension = CFSTR(".tga");
|
||||
type = "TPIC";
|
||||
creator = "prvw";
|
||||
extension = "tga";
|
||||
break;
|
||||
|
||||
case FFSAVE_BMP:
|
||||
type = 'BMPf';
|
||||
creator = 'prvw';
|
||||
extension = CFSTR(".bmp");
|
||||
type = "BMPf";
|
||||
creator = "prvw";
|
||||
extension = "bmp";
|
||||
break;
|
||||
case FFSAVE_JPEG:
|
||||
type = 'JPEG';
|
||||
creator = 'prvw';
|
||||
extension = CFSTR(".jpeg");
|
||||
type = "JPEG";
|
||||
creator = "prvw";
|
||||
extension = "jpeg";
|
||||
break;
|
||||
case FFSAVE_PNG:
|
||||
type = 'PNG ';
|
||||
creator = 'prvw';
|
||||
extension = CFSTR(".png");
|
||||
type = "PNG ";
|
||||
creator = "prvw";
|
||||
extension = "png";
|
||||
break;
|
||||
case FFSAVE_AVI:
|
||||
type = '\?\?\?\?';
|
||||
creator = '\?\?\?\?';
|
||||
extension = CFSTR(".mov");
|
||||
type = "\?\?\?\?";
|
||||
creator = "\?\?\?\?";
|
||||
extension = "mov";
|
||||
break;
|
||||
|
||||
case FFSAVE_ANIM:
|
||||
type = '\?\?\?\?';
|
||||
creator = '\?\?\?\?';
|
||||
extension = CFSTR(".xaf");
|
||||
type = "\?\?\?\?";
|
||||
creator = "\?\?\?\?";
|
||||
extension = "xaf";
|
||||
break;
|
||||
|
||||
#ifdef _CORY_TESTING
|
||||
case FFSAVE_GEOMETRY:
|
||||
type = '\?\?\?\?';
|
||||
creator = '\?\?\?\?';
|
||||
extension = CFSTR(".slg");
|
||||
type = "\?\?\?\?";
|
||||
creator = "\?\?\?\?";
|
||||
extension = "slg";
|
||||
break;
|
||||
#endif
|
||||
case FFSAVE_RAW:
|
||||
type = '\?\?\?\?';
|
||||
creator = '\?\?\?\?';
|
||||
extension = CFSTR(".raw");
|
||||
type = "\?\?\?\?";
|
||||
creator = "\?\?\?\?";
|
||||
extension = "raw";
|
||||
break;
|
||||
|
||||
case FFSAVE_J2C:
|
||||
type = '\?\?\?\?';
|
||||
creator = 'prvw';
|
||||
extension = CFSTR(".j2c");
|
||||
type = "\?\?\?\?";
|
||||
creator = "prvw";
|
||||
extension = "j2c";
|
||||
break;
|
||||
|
||||
case FFSAVE_SCRIPT:
|
||||
type = 'LSL ';
|
||||
creator = '\?\?\?\?';
|
||||
extension = CFSTR(".lsl");
|
||||
type = "LSL ";
|
||||
creator = "\?\?\?\?";
|
||||
extension = "lsl";
|
||||
break;
|
||||
|
||||
case FFSAVE_ALL:
|
||||
default:
|
||||
type = '\?\?\?\?';
|
||||
creator = '\?\?\?\?';
|
||||
extension = CFSTR("");
|
||||
type = "\?\?\?\?";
|
||||
creator = "\?\?\?\?";
|
||||
extension = "";
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the dialog
|
||||
error = NavCreatePutFileDialog(&mNavOptions, type, creator, NULL, NULL, &navRef);
|
||||
if (error == noErr)
|
||||
{
|
||||
CFStringRef nameString = NULL;
|
||||
bool hasExtension = true;
|
||||
|
||||
// Create a CFString of the initial file name
|
||||
if (!filename.empty())
|
||||
nameString = CFStringCreateWithCString(NULL, filename.c_str(), kCFStringEncodingUTF8);
|
||||
else
|
||||
nameString = CFSTR("Untitled");
|
||||
|
||||
// Add the extension if one was not provided
|
||||
if (nameString && !CFStringHasSuffix(nameString, extension))
|
||||
{
|
||||
CFStringRef tempString = nameString;
|
||||
hasExtension = false;
|
||||
nameString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), tempString, extension);
|
||||
CFRelease(tempString);
|
||||
}
|
||||
|
||||
// Set the name in the dialog
|
||||
if (nameString)
|
||||
{
|
||||
error = NavDialogSetSaveFileName(navRef, nameString);
|
||||
CFRelease(nameString);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = paramErr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string namestring = filename;
|
||||
if (namestring.empty()) namestring="Untitled";
|
||||
|
||||
// if (! boost::algorithm::ends_with(namestring, extension) )
|
||||
// {
|
||||
// namestring = namestring + "." + extension;
|
||||
//
|
||||
// }
|
||||
|
||||
gViewerWindow->getWindow()->beforeDialog();
|
||||
|
||||
// Run the dialog
|
||||
if (error == noErr)
|
||||
error = NavDialogRun(navRef);
|
||||
std::string* filev = doSaveDialog(&namestring,
|
||||
&type,
|
||||
&creator,
|
||||
&extension,
|
||||
mPickOptions);
|
||||
|
||||
gViewerWindow->getWindow()->afterDialog();
|
||||
|
||||
if (error == noErr)
|
||||
error = NavDialogGetReply(navRef, &navReply);
|
||||
|
||||
if (navRef)
|
||||
NavDialogDispose(navRef);
|
||||
|
||||
if (error == noErr && navReply.validRecord)
|
||||
if ( filev && !filev->empty() )
|
||||
{
|
||||
SInt32 count = 0;
|
||||
|
||||
// AE indexes are 1 based...
|
||||
error = AECountItems(&navReply.selection, &count);
|
||||
if (count > 0)
|
||||
{
|
||||
// Get the FSRef to the containing folder
|
||||
FSRef fsRef;
|
||||
AEKeyword theAEKeyword;
|
||||
DescType typeCode;
|
||||
Size actualSize = 0;
|
||||
|
||||
memset(&fsRef, 0, sizeof(fsRef));
|
||||
error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
|
||||
|
||||
if (error == noErr)
|
||||
{
|
||||
char path[PATH_MAX]; /*Flawfinder: ignore*/
|
||||
char newFileName[SINGLE_FILENAME_BUFFER_SIZE]; /*Flawfinder: ignore*/
|
||||
|
||||
error = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX);
|
||||
if (error == noErr)
|
||||
{
|
||||
if (CFStringGetCString(navReply.saveFileName, newFileName, sizeof(newFileName), kCFStringEncodingUTF8))
|
||||
{
|
||||
mFiles.push_back(std::string(path) + "/" + std::string(newFileName));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = paramErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = paramErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mFiles.push_back(*filev);
|
||||
return true;
|
||||
}
|
||||
|
||||
return error;
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
|
||||
|
|
@ -924,16 +749,21 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
OSStatus error = noErr;
|
||||
|
||||
reset();
|
||||
|
||||
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
|
||||
mPickOptions &= ~F_MULTIPLE;
|
||||
mPickOptions |= F_FILE;
|
||||
|
||||
if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
|
||||
{
|
||||
|
||||
mPickOptions |= ( F_NAV_SUPPORT | F_DIRECTORY );
|
||||
mPickOptions &= ~F_FILE;
|
||||
}
|
||||
|
||||
if(filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
|
||||
{
|
||||
// mNavOptions.optionFlags |= kNavAllowOpenPackages;
|
||||
mNavOptions.optionFlags |= kNavSupportPackages;
|
||||
mPickOptions &= F_NAV_SUPPORT;
|
||||
}
|
||||
|
||||
if (blocking)
|
||||
|
|
@ -942,14 +772,13 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
|
|||
send_agent_pause();
|
||||
}
|
||||
|
||||
|
||||
success = doNavChooseDialog(filter);
|
||||
|
||||
if (success)
|
||||
{
|
||||
error = doNavChooseDialog(filter);
|
||||
}
|
||||
|
||||
if (error == noErr)
|
||||
{
|
||||
if (getFileCount())
|
||||
success = true;
|
||||
if (!getFileCount())
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (blocking)
|
||||
|
|
@ -975,21 +804,22 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
OSStatus error = noErr;
|
||||
|
||||
reset();
|
||||
|
||||
mNavOptions.optionFlags |= kNavAllowMultipleFiles;
|
||||
|
||||
mPickOptions |= F_FILE;
|
||||
|
||||
mPickOptions |= F_MULTIPLE;
|
||||
// Modal, so pause agent
|
||||
send_agent_pause();
|
||||
|
||||
success = doNavChooseDialog(filter);
|
||||
|
||||
send_agent_resume();
|
||||
|
||||
if (success)
|
||||
{
|
||||
error = doNavChooseDialog(filter);
|
||||
}
|
||||
send_agent_resume();
|
||||
if (error == noErr)
|
||||
{
|
||||
if (getFileCount())
|
||||
success = true;
|
||||
if (!getFileCount())
|
||||
success = false;
|
||||
if (getFileCount() > 1)
|
||||
mLocked = true;
|
||||
}
|
||||
|
|
@ -1001,37 +831,37 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
|
|||
|
||||
BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
|
||||
{
|
||||
|
||||
if( mLocked )
|
||||
return FALSE;
|
||||
BOOL success = FALSE;
|
||||
OSStatus error = noErr;
|
||||
return false;
|
||||
BOOL success = false;
|
||||
|
||||
// if local file browsing is turned off, return without opening dialog
|
||||
if ( check_local_file_access_enabled() == false )
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
|
||||
mPickOptions &= ~F_MULTIPLE;
|
||||
|
||||
// Modal, so pause agent
|
||||
send_agent_pause();
|
||||
|
||||
success = doNavSaveDialog(filter, filename);
|
||||
|
||||
if (success)
|
||||
{
|
||||
error = doNavSaveDialog(filter, filename);
|
||||
}
|
||||
send_agent_resume();
|
||||
if (error == noErr)
|
||||
{
|
||||
if (getFileCount())
|
||||
success = true;
|
||||
if (!getFileCount())
|
||||
success = false;
|
||||
}
|
||||
|
||||
// Account for the fact that the app has been stalled.
|
||||
LLFrameTimer::updateFrameTime();
|
||||
return success;
|
||||
}
|
||||
//END LL_DARWIN
|
||||
|
||||
#elif LL_LINUX || LL_SOLARIS
|
||||
|
||||
|
|
@ -1537,4 +1367,4 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // LL_LINUX || LL_SOLARIS
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@
|
|||
#include <Carbon/Carbon.h>
|
||||
|
||||
// AssertMacros.h does bad things.
|
||||
#include "fix_macros.h"
|
||||
#undef verify
|
||||
#undef check
|
||||
#undef require
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -85,7 +85,8 @@ public:
|
|||
FFLOAD_MODEL = 9,
|
||||
FFLOAD_COLLADA = 10,
|
||||
FFLOAD_SCRIPT = 11,
|
||||
FFLOAD_DICTIONARY = 12
|
||||
FFLOAD_DICTIONARY = 12,
|
||||
FFLOAD_DIRECTORY = 13 //To call from lldirpicker.
|
||||
};
|
||||
|
||||
enum ESaveFilter
|
||||
|
|
@ -158,15 +159,14 @@ private:
|
|||
#endif
|
||||
|
||||
#if LL_DARWIN
|
||||
NavDialogCreationOptions mNavOptions;
|
||||
S32 mPickOptions;
|
||||
std::vector<std::string> mFileVector;
|
||||
UInt32 mFileIndex;
|
||||
|
||||
OSStatus doNavChooseDialog(ELoadFilter filter);
|
||||
OSStatus doNavSaveDialog(ESaveFilter filter, const std::string& filename);
|
||||
void getFilePath(SInt32 index);
|
||||
void getFileName(SInt32 index);
|
||||
static Boolean navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode);
|
||||
bool doNavChooseDialog(ELoadFilter filter);
|
||||
bool doNavSaveDialog(ESaveFilter filter, const std::string& filename);
|
||||
//static Boolean navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode);
|
||||
std::vector<std::string>* navOpenFilterProc(ELoadFilter filter);
|
||||
#endif
|
||||
|
||||
#if LL_GTK
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* @file llfilepicker_mac.h
|
||||
* @brief OS-specific file picker
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// OS specific file selection dialog. This is implemented as a
|
||||
// singleton class, so call the instance() method to get the working
|
||||
// instance. When you call getMultipleOpenFile(), it locks the picker
|
||||
// until you iterate to the end of the list of selected files with
|
||||
// getNextFile() or call reset().
|
||||
|
||||
#ifndef LL_LLFILEPICKER_MAC_H
|
||||
#define LL_LLFILEPICKER_MAC_H
|
||||
|
||||
#if LL_DARWIN
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//void modelessPicker();
|
||||
std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,
|
||||
unsigned int flags);
|
||||
std::string* doSaveDialog(const std::string* file,
|
||||
const std::string* type,
|
||||
const std::string* creator,
|
||||
const std::string* extension,
|
||||
unsigned int flags);
|
||||
enum {
|
||||
F_FILE = 0x00000001,
|
||||
F_DIRECTORY = 0x00000002,
|
||||
F_MULTIPLE = 0x00000004,
|
||||
F_NAV_SUPPORT=0x00000008
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* @file llfilepicker_mac.cpp
|
||||
* @brief OS-specific file picker
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifdef LL_DARWIN
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <iostream>
|
||||
#include "llfilepicker_mac.h"
|
||||
|
||||
std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,
|
||||
unsigned int flags)
|
||||
{
|
||||
int i, result;
|
||||
|
||||
//Aura TODO: We could init a small window and release it at the end of this routine
|
||||
//for a modeless interface.
|
||||
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
//NSString *fileName = nil;
|
||||
NSMutableArray *fileTypes = nil;
|
||||
|
||||
|
||||
if ( allowed_types && !allowed_types->empty())
|
||||
{
|
||||
fileTypes = [[NSMutableArray alloc] init];
|
||||
|
||||
for (i=0;i<allowed_types->size();++i)
|
||||
{
|
||||
[fileTypes addObject:
|
||||
[NSString stringWithCString:(*allowed_types)[i].c_str()
|
||||
encoding:[NSString defaultCStringEncoding]]];
|
||||
}
|
||||
}
|
||||
|
||||
//[panel setMessage:@"Import one or more files or directories."];
|
||||
[panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ];
|
||||
[panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ];
|
||||
[panel setCanCreateDirectories: true];
|
||||
[panel setResolvesAliases: true];
|
||||
[panel setCanChooseFiles: ( (flags & F_FILE)?true:false )];
|
||||
[panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
|
||||
|
||||
std::vector<std::string>* outfiles = NULL;
|
||||
|
||||
if (fileTypes)
|
||||
{
|
||||
[panel setAllowedFileTypes:fileTypes];
|
||||
result = [panel runModal];
|
||||
}
|
||||
else
|
||||
{
|
||||
// I suggest it's better to open the last path and let this default to home dir as necessary
|
||||
// for consistency with other OS X apps
|
||||
//
|
||||
//[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ];
|
||||
result = [panel runModal];
|
||||
}
|
||||
|
||||
if (result == NSOKButton)
|
||||
{
|
||||
NSArray *filesToOpen = [panel URLs];
|
||||
int i, count = [filesToOpen count];
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
outfiles = new std::vector<std::string>;
|
||||
}
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
NSString *aFile = [[filesToOpen objectAtIndex:i] path];
|
||||
std::string *afilestr = new std::string([aFile UTF8String]);
|
||||
outfiles->push_back(*afilestr);
|
||||
}
|
||||
}
|
||||
return outfiles;
|
||||
}
|
||||
|
||||
|
||||
std::string* doSaveDialog(const std::string* file,
|
||||
const std::string* type,
|
||||
const std::string* creator,
|
||||
const std::string* extension,
|
||||
unsigned int flags)
|
||||
{
|
||||
NSSavePanel *panel = [NSSavePanel savePanel];
|
||||
|
||||
NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]];
|
||||
NSArray *fileType = [[NSArray alloc] initWithObjects:extensionns,nil];
|
||||
|
||||
//[panel setMessage:@"Save Image File"];
|
||||
[panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
|
||||
[panel setCanSelectHiddenExtension:true];
|
||||
[panel setAllowedFileTypes:fileType];
|
||||
NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]];
|
||||
|
||||
std::string *outfile = NULL;
|
||||
NSURL* url = [NSURL fileURLWithPath:fileName];
|
||||
[panel setDirectoryURL: url];
|
||||
if([panel runModal] ==
|
||||
NSFileHandlingPanelOKButton)
|
||||
{
|
||||
NSURL* url = [panel URL];
|
||||
NSString* p = [url path];
|
||||
outfile = new std::string( [p UTF8String] );
|
||||
// write the file
|
||||
}
|
||||
return outfile;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -89,8 +89,10 @@ void LLFloaterHardwareSettings::refresh()
|
|||
|
||||
void LLFloaterHardwareSettings::refreshEnabledState()
|
||||
{
|
||||
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
|
||||
|
||||
S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
|
||||
S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting();
|
||||
S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);
|
||||
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem);
|
||||
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem);
|
||||
|
||||
|
|
@ -149,12 +151,17 @@ BOOL LLFloaterHardwareSettings::postBuild()
|
|||
{
|
||||
childSetAction("OK", onBtnOK, this);
|
||||
|
||||
// Don't do this on Mac as their braindead GL versioning
|
||||
// sets this when 8x and 16x are indeed available
|
||||
//
|
||||
#if !LL_DARWIN
|
||||
if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f)
|
||||
{ //remove FSAA settings above "4x"
|
||||
LLComboBox* combo = getChild<LLComboBox>("fsaa");
|
||||
combo->remove("8x");
|
||||
combo->remove("16x");
|
||||
}
|
||||
#endif
|
||||
|
||||
refresh();
|
||||
center();
|
||||
|
|
|
|||
|
|
@ -676,6 +676,7 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL
|
|||
if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end())
|
||||
{
|
||||
mKeyHandledByUI[translated_key] = FALSE;
|
||||
LL_INFOS("Keyboard Handling") << "Key wasn't handled by UI!" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1237,7 +1237,7 @@ S32 LLViewerTextureList::getMinVideoRamSetting()
|
|||
|
||||
//static
|
||||
// Returns max setting for TextureMemory (in MB)
|
||||
S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
|
||||
S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier)
|
||||
{
|
||||
S32 max_texmem;
|
||||
if (gGLManager.mVRAM != 0)
|
||||
|
|
@ -1281,7 +1281,10 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
|
|||
max_texmem = llmin(max_texmem, (S32)(system_ram/2));
|
||||
else
|
||||
max_texmem = llmin(max_texmem, (S32)(system_ram));
|
||||
|
||||
|
||||
// limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
|
||||
max_texmem = llmin(max_texmem, (S32) (mem_multiplier * (F32) max_texmem));
|
||||
|
||||
max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES);
|
||||
|
||||
return max_texmem;
|
||||
|
|
@ -1294,7 +1297,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
|
|||
// Initialize the image pipeline VRAM settings
|
||||
S32 cur_mem = gSavedSettings.getS32("TextureMemory");
|
||||
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
|
||||
S32 default_mem = getMaxVideoRamSetting(true); // recommended default
|
||||
S32 default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default
|
||||
if (mem == 0)
|
||||
{
|
||||
mem = cur_mem > 0 ? cur_mem : default_mem;
|
||||
|
|
@ -1304,10 +1307,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
|
|||
mem = default_mem;
|
||||
}
|
||||
|
||||
// limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
|
||||
mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem));
|
||||
|
||||
mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting());
|
||||
mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier));
|
||||
if (mem != cur_mem)
|
||||
{
|
||||
gSavedSettings.setS32("TextureMemory", mem);
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ public:
|
|||
void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
|
||||
|
||||
static S32 getMinVideoRamSetting();
|
||||
static S32 getMaxVideoRamSetting(bool get_recommended = false);
|
||||
static S32 getMaxVideoRamSetting(bool get_recommended, float mem_multiplier);
|
||||
|
||||
private:
|
||||
void updateImagesDecodePriorities();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include "fix_macros.h"
|
||||
|
||||
#undef verify
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBas
|
|||
std::string const & platform_version,
|
||||
unsigned char uniqueid[MD5HEX_STR_SIZE],
|
||||
bool willing_to_test)
|
||||
{
|
||||
{
|
||||
LLSD path;
|
||||
path.append(mProtocol);
|
||||
path.append(channel);
|
||||
|
|
|
|||
Loading…
Reference in New Issue