LLWindow V3 partial merge. Includes Most everything sans new LLMouseHandler which requires some messy changes in llviewerwindow that are best left for a dedicated commit. Also, some translation fluff was skipped for now.

This commit is contained in:
Shyotl
2011-08-29 03:44:17 -05:00
parent c129a1a923
commit baddb47c44
58 changed files with 1937 additions and 504 deletions

View File

@@ -32,19 +32,21 @@
#include "linden_common.h"
#include <Carbon/Carbon.h>
#include <OpenGL/OpenGL.h>
#include "llwindowmacosx.h"
#include "llkeyboardmacosx.h"
#include "llwindowcallbacks.h"
#include "llwindowmacosx-objc.h"
#include "llpreeditor.h"
#include "llerror.h"
#include "llgl.h"
#include "llstring.h"
#include "lldir.h"
#include "indra_constants.h"
#include "llwindowmacosx-objc.h"
#include "llpreeditor.h"
#include <Carbon/Carbon.h>
#include <OpenGL/OpenGL.h>
extern BOOL gDebugWindowProc;
@@ -112,9 +114,6 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key);
static EventTypeSpec WindowHandlerEventList[] =
{
// Window-related events
// { kEventClassWindow, kEventWindowCollapsing },
// { kEventClassWindow, kEventWindowCollapsed },
// { kEventClassWindow, kEventWindowShown },
{ kEventClassWindow, kEventWindowActivated },
{ kEventClassWindow, kEventWindowDeactivated },
{ kEventClassWindow, kEventWindowShown },
@@ -125,8 +124,7 @@ static EventTypeSpec WindowHandlerEventList[] =
{ kEventClassWindow, kEventWindowClose },
{ kEventClassWindow, kEventWindowBoundsChanging },
{ kEventClassWindow, kEventWindowBoundsChanged },
// { kEventClassWindow, kEventWindowZoomed },
// { kEventClassWindow, kEventWindowDrawContent },
{ kEventClassWindow, kEventWindowGetIdealSize },
// Mouse events
{ kEventClassMouse, kEventMouseDown },
@@ -214,19 +212,27 @@ static LLWindowMacOSX *gWindowImplementation = NULL;
LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth,
U32 fsaa_samples)
: LLWindow(fullscreen, flags)
: LLWindow(NULL, fullscreen, flags)
{
// *HACK: During window construction we get lots of OS events for window
// reshape, activate, etc. that the viewer isn't ready to handle.
// Route them to a dummy callback structure until the end of constructor.
LLWindowCallbacks null_callbacks;
mCallbacks = &null_callbacks;
// Voodoo for calling cocoa from carbon (see llwindowmacosx-objc.mm).
setupCocoa();
// Initialize the keyboard
gKeyboard = new LLKeyboardMacOSX();
gKeyboard->setCallbacks(callbacks);
// Ignore use_gl for now, only used for drones on PC
mWindow = NULL;
@@ -244,12 +250,14 @@ LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name
mCursorIgnoreNextDelta = FALSE;
mNeedsResize = FALSE;
mOverrideAspectRatio = 0.f;
mMaximized = FALSE;
mMinimized = FALSE;
mTSMDocument = NULL; // Just in case.
mLanguageTextInputAllowed = FALSE;
mTSMScriptCode = 0;
mTSMLangCode = 0;
mPreeditor = NULL;
mRawKeyEvent = NULL;
mFSAASamples = fsaa_samples;
mForceRebuild = FALSE;
@@ -268,6 +276,8 @@ LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name
mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator);
mGlobalHandlerRef = NULL;
mWindowHandlerRef = NULL;
mDragOverrideCursor = -1;
// We're not clipping yet
SetRect( &mOldMouseClip, 0, 0, 0, 0 );
@@ -315,6 +325,7 @@ LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name
setCursor( UI_CURSOR_ARROW );
}
mCallbacks = callbacks;
stop_glerror();
}
@@ -447,24 +458,23 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
if(!mFullscreen && (mWindow == NULL))
{
Rect window_rect;
//int displayWidth = CGDisplayPixelsWide(mDisplay);
//int displayHeight = CGDisplayPixelsHigh(mDisplay);
//const int menuBarPlusTitleBar = 44; // Ugly magic number.
LL_DEBUGS("Window") << "createContext: creating window" << LL_ENDL;
window_rect.left = (long) x;
window_rect.right = (long) x + width;
window_rect.top = (long) y;
window_rect.bottom = (long) y + height;
mPreviousWindowRect.left = (long) x;
mPreviousWindowRect.right = (long) x + width;
mPreviousWindowRect.top = (long) y;
mPreviousWindowRect.bottom = (long) y + height;
//-----------------------------------------------------------------------
// Create the window
//-----------------------------------------------------------------------
mWindow = NewCWindow(
NULL,
&window_rect,
&mPreviousWindowRect,
mWindowTitle,
false, // Create the window invisible. Whoever calls createContext() should show it after any moving/resizing.
// noGrowDocProc, // Window with no grow box and no zoom box
@@ -488,8 +498,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
// Set up window event handlers (some window-related events ONLY go to window handlers.)
InstallStandardEventHandler(GetWindowEventTarget(mWindow));
InstallWindowEventHandler (mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
#if LL_OS_DRAGDROP_ENABLED
InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this );
InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this );
#endif // LL_OS_DRAGDROP_ENABLED
}
{
@@ -511,7 +524,6 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
if (mTSMDocument)
{
ActivateTSMDocument(mTSMDocument);
UseInputWindow(mTSMDocument, FALSE);
allowLanguageTextInput(NULL, FALSE);
}
}
@@ -531,20 +543,20 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
GLint fullscreenAttrib[] =
{
AGL_RGBA,
AGL_FULLSCREEN,
// AGL_NO_RECOVERY, // MBW -- XXX -- Not sure if we want this attribute
AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
AGL_SAMPLES_ARB, mFSAASamples,
AGL_DOUBLEBUFFER,
AGL_CLOSEST_POLICY,
AGL_ACCELERATED,
AGL_RED_SIZE, 8,
AGL_GREEN_SIZE, 8,
AGL_BLUE_SIZE, 8,
AGL_ALPHA_SIZE, 8,
AGL_DEPTH_SIZE, 24,
AGL_STENCIL_SIZE, 8,
AGL_NONE
AGL_FULLSCREEN,
AGL_NO_RECOVERY,
AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
AGL_SAMPLES_ARB, mFSAASamples,
AGL_DOUBLEBUFFER,
AGL_CLOSEST_POLICY,
AGL_ACCELERATED,
AGL_RED_SIZE, 8,
AGL_GREEN_SIZE, 8,
AGL_BLUE_SIZE, 8,
AGL_ALPHA_SIZE, 8,
AGL_DEPTH_SIZE, 24,
AGL_STENCIL_SIZE, 8,
AGL_NONE
};
LL_DEBUGS("Window") << "createContext: creating fullscreen pixelformat" << LL_ENDL;
@@ -557,11 +569,18 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
}
else
{
// NOTE from Leslie:
//
// AGL_NO_RECOVERY, when combined with AGL_ACCELERATED prevents software rendering
// fallback which means we won't hvae shaders that compile and link but then don't
// work. The drawback is that our shader compilation will be a bit more finicky though.
GLint windowedAttrib[] =
{
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_CLOSEST_POLICY,
AGL_NO_RECOVERY,
AGL_DOUBLEBUFFER,
AGL_CLOSEST_POLICY,
AGL_ACCELERATED,
AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
AGL_SAMPLES_ARB, mFSAASamples,
@@ -1081,31 +1100,22 @@ BOOL LLWindowMacOSX::getVisible()
BOOL LLWindowMacOSX::getMinimized()
{
BOOL result = FALSE;
// Since the set of states where we want to act "minimized" is non-trivial, it's easier to
// track things locally than to try and retrieve the state from the window manager.
result = mMinimized;
return(result);
return mMinimized;
}
BOOL LLWindowMacOSX::getMaximized()
{
BOOL result = FALSE;
if (mWindow)
{
// TODO
}
return(result);
return mMaximized;
}
BOOL LLWindowMacOSX::maximize()
{
// TODO
return FALSE;
if (mWindow && !mMaximized)
{
ZoomWindow(mWindow, inContent, true);
}
return mMaximized;
}
BOOL LLWindowMacOSX::getFullscreen()
@@ -1261,6 +1271,7 @@ BOOL LLWindowMacOSX::setSize(const LLCoordScreen size)
void LLWindowMacOSX::swapBuffers()
{
glFinish();
aglSwapBuffers(mContext);
}
@@ -2005,7 +2016,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
// Although the spec. is unclear, replace range should
// not present when there is an active preedit. We just
// ignore the case. markAsPreedit will detect the case and warn it.
const LLWString & text = mPreeditor->getWText();
const LLWString & text = mPreeditor->getPreeditString();
const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location);
const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length);
mPreeditor->markAsPreedit(location, length);
@@ -2125,8 +2136,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
// First, process the raw event.
{
EventRef rawEvent;
EventRef rawEvent = NULL;
// Get the original event and extract the modifier keys, so we can ignore command-key events.
if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr)
{
@@ -2135,6 +2146,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
// and call this function recursively to handle the raw key event.
eventHandler (myHandler, rawEvent);
// save the raw event until we're done processing the unicode input as well.
mRawKeyEvent = rawEvent;
}
}
@@ -2162,11 +2176,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
}
else
{
MASK mask = 0;
if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
if(modifiers & optionKey) { mask |= MASK_ALT; }
MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
llassert( actualType == typeUnicodeText );
// The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar.
@@ -2188,6 +2199,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
delete[] buffer;
}
mRawKeyEvent = NULL;
result = err;
}
break;
@@ -2203,7 +2215,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
const LLWString & text = mPreeditor->getWText();
const LLWString & text = mPreeditor->getPreeditString();
LLCoordGL caret_coord;
LLRect preedit_bounds;
@@ -2240,7 +2252,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
mPreeditor->getSelectionRange(&selection, &selection_length);
if (selection_length)
{
const LLWString text = mPreeditor->getWText().substr(selection, selection_length);
const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length);
const llutf16string text_utf16 = wstring_to_utf16str(text);
result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText,
text_utf16.length() * sizeof(U16), text_utf16.c_str());
@@ -2262,6 +2274,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
// save the raw event so getNativeKeyData can use it.
mRawKeyEvent = event;
// printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers);
// fflush(stdout);
@@ -2357,6 +2372,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
result = eventNotHandledErr;
break;
}
mRawKeyEvent = NULL;
}
break;
@@ -2527,31 +2544,92 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
}
mCallbacks->handleFocusLost(this);
break;
case kEventWindowBoundsChanging:
{
// This is where we would constrain move/resize to a particular screen
const S32 MIN_WIDTH = 320;
const S32 MIN_HEIGHT = 240;
Rect currentBounds;
Rect previousBounds;
GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &currentBounds);
GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds);
// This is where we would constrain move/resize to a particular screen
if(0)
// Put an offset into window un-maximize operation since the kEventWindowGetIdealSize
// event only allows the specification of size and not position.
if (mMaximized)
{
SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &currentBounds);
short leftOffset = mPreviousWindowRect.left - currentBounds.left;
currentBounds.left += leftOffset;
currentBounds.right += leftOffset;
short topOffset = mPreviousWindowRect.top - currentBounds.top;
currentBounds.top += topOffset;
currentBounds.bottom += topOffset;
}
else
{
// Store off the size for future un-maximize operations
mPreviousWindowRect = previousBounds;
}
if ((currentBounds.right - currentBounds.left) < MIN_WIDTH)
{
currentBounds.right = currentBounds.left + MIN_WIDTH;
}
if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT)
{
currentBounds.bottom = currentBounds.top + MIN_HEIGHT;
}
SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &currentBounds);
result = noErr;
}
break;
case kEventWindowBoundsChanged:
{
// Get new window bounds
Rect newBounds;
GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds);
// Get previous window bounds
Rect oldBounds;
GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds);
// Determine if the new size is larger than the old
bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left));
newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top));
// Check to see if this is a zoom event (+ button on window pane)
unsigned int eventParams;
GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams);
bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0);
// Maximized flag is if zoom event and increasing window size
mMaximized = (isZoomEvent && newBoundsLarger);
aglUpdateContext(mContext);
mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
}
break;
case kEventWindowGetIdealSize:
// Only recommend a new ideal size when un-maximizing
if (mMaximized == TRUE)
{
Point nonMaximizedSize;
nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top;
nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left;
SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize);
result = noErr;
}
break;
@@ -2597,7 +2675,6 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
// BringToFront(mWindow);
// result = noErr;
break;
}
break;
@@ -2613,7 +2690,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
const LLWString & text = mPreeditor->getWText();
const LLWString & text = mPreeditor->getPreeditString();
const CFIndex length = wstring_utf16_length(text, 0, preedit)
+ wstring_utf16_length(text, preedit + preedit_length, text.length());
result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length);
@@ -2630,7 +2707,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
const LLWString & text = mPreeditor->getWText();
const LLWString & text = mPreeditor->getPreeditString();
CFRange range;
if (preedit_length)
@@ -2664,7 +2741,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
const LLWString & text = mPreeditor->getWText();
const LLWString & text = mPreeditor->getPreeditString();
// The GetCharacters event of TSMDA has a fundamental flaw;
// An input method need to decide the starting offset and length
@@ -2739,14 +2816,14 @@ const char* cursorIDToName(int id)
case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY";
case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
case UI_CURSOR_TOOLMEDIAOPEN: return "UI_CURSOR_TOOLMEDIAOPEN";
case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE";
case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY";
}
llerrs << "cursorIDToName: unknown cursor id" << id << llendl;
@@ -2774,6 +2851,14 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
{
OSStatus result = noErr;
if (mDragOverrideCursor != -1)
{
// A drag is in progress...remember the requested cursor and we'll
// restore it when it is done
mCurrentCursor = cursor;
return;
}
if (cursor == UI_CURSOR_ARROW
&& mBusyCount > 0)
{
@@ -2838,13 +2923,13 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
case UI_CURSOR_TOOLPAN:
case UI_CURSOR_TOOLZOOMIN:
case UI_CURSOR_TOOLPICKOBJECT3:
case UI_CURSOR_TOOLSIT:
case UI_CURSOR_TOOLBUY:
case UI_CURSOR_TOOLPAY:
case UI_CURSOR_TOOLOPEN:
case UI_CURSOR_TOOLPLAY:
case UI_CURSOR_TOOLPAUSE:
case UI_CURSOR_TOOLMEDIAOPEN:
case UI_CURSOR_TOOLSIT:
case UI_CURSOR_TOOLBUY:
case UI_CURSOR_TOOLOPEN:
case UI_CURSOR_TOOLPAY:
result = setImageCursor(gCursors[cursor]);
break;
@@ -2883,13 +2968,13 @@ void LLWindowMacOSX::initCursors()
initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1);
initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10);
initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10);
@@ -3135,7 +3220,7 @@ S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32
// Open a URL with the user's default web browser.
// Must begin with protocol identifier.
void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url)
void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
{
bool found = false;
S32 i;
@@ -3188,8 +3273,62 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url)
}
}
LLSD LLWindowMacOSX::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();
if(mRawKeyEvent)
{
char char_code = 0;
UInt32 key_code = 0;
UInt32 modifiers = 0;
UInt32 keyboard_type = 0;
GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code);
GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code);
GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
GetEventParameter (mRawKeyEvent, kEventParamKeyboardType, typeUInt32, NULL, sizeof(UInt32), NULL, &keyboard_type);
BOOL LLWindowMacOSX::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
result["char_code"] = (S32)char_code;
result["key_code"] = (S32)key_code;
result["modifiers"] = (S32)modifiers;
result["keyboard_type"] = (S32)keyboard_type;
#if 0
// This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc)
// cause llsd serialization to create XML that the llsd deserializer won't parse!
std::string unicode;
OSStatus err = noErr;
EventParamType actualType = typeUTF8Text;
UInt32 actualSize = 0;
char *buffer = NULL;
err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL);
if(err == noErr)
{
// allocate a buffer and get the actual data.
buffer = new char[actualSize];
err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, actualSize, &actualSize, buffer);
if(err == noErr)
{
unicode.assign(buffer, actualSize);
}
delete[] buffer;
}
result["unicode"] = unicode;
#endif
}
lldebugs << "native key data is: " << result << llendl;
return result;
}
BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
BOOL retval = FALSE;
OSErr error = noErr;
@@ -3305,6 +3444,8 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
return;
}
UseInputWindow(mTSMDocument, !b);
// Take care of old and new preeditors.
if (preeditor != mPreeditor || !b)
{
@@ -3364,3 +3505,174 @@ std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
return std::vector<std::string>();
}
// static
MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers)
{
MASK mask = 0;
if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
if(modifiers & optionKey) { mask |= MASK_ALT; }
return mask;
}
#if LL_OS_DRAGDROP_ENABLED
OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
void * handlerRefCon, DragRef drag)
{
OSErr result = noErr;
LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
lldebugs << "drag tracking handler, message = " << message << llendl;
switch(message)
{
case kDragTrackingInWindow:
result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_TRACK);
break;
case kDragTrackingEnterHandler:
result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_START_TRACKING);
break;
case kDragTrackingLeaveHandler:
result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_STOP_TRACKING);
break;
default:
break;
}
return result;
}
OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
DragRef drag)
{
LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
}
OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action)
{
OSErr result = dragNotAcceptedErr; // overall function result
OSErr err = noErr; // for local error handling
// Get the mouse position and modifiers of this drag.
SInt16 modifiers, mouseDownModifiers, mouseUpModifiers;
::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers);
MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
Point mouse_point;
// This will return the mouse point in global screen coords
::GetDragMouse(drag, &mouse_point, NULL);
LLCoordScreen screen_coords(mouse_point.h, mouse_point.v);
LLCoordGL gl_pos;
convertCoords(screen_coords, &gl_pos);
// Look at the pasteboard and try to extract an URL from it
PasteboardRef pasteboard;
if(GetDragPasteboard(drag, &pasteboard) == noErr)
{
ItemCount num_items = 0;
// Treat an error here as an item count of 0
(void)PasteboardGetItemCount(pasteboard, &num_items);
// Only deal with single-item drags.
if(num_items == 1)
{
PasteboardItemID item_id = NULL;
CFArrayRef flavors = NULL;
CFDataRef data = NULL;
err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based.
// Try to extract an URL from the pasteboard
if(err == noErr)
{
err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors);
}
if(err == noErr)
{
if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL))
{
// This is an URL.
err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data);
}
else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText))
{
// This is a string that might be an URL.
err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data);
}
}
if(flavors != NULL)
{
CFRelease(flavors);
}
if(data != NULL)
{
std::string url;
url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data));
CFRelease(data);
if(!url.empty())
{
LLWindowCallbacks::DragNDropResult res =
mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
switch (res) {
case LLWindowCallbacks::DND_NONE: // No drop allowed
if (action == LLWindowCallbacks::DNDA_TRACK)
{
mDragOverrideCursor = kThemeNotAllowedCursor;
}
else {
mDragOverrideCursor = -1;
}
break;
case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
mDragOverrideCursor = kThemePointingHandCursor;
result = noErr;
break;
case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
mDragOverrideCursor = kThemeCopyArrowCursor;
result = noErr;
break;
case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation:
mDragOverrideCursor = kThemeAliasArrowCursor;
result = noErr;
break;
default:
mDragOverrideCursor = -1;
break;
}
// This overrides the cursor being set by setCursor.
// This is a bit of a hack workaround because lots of areas
// within the viewer just blindly set the cursor.
if (mDragOverrideCursor == -1)
{
// Restore the cursor
ECursorType temp_cursor = mCurrentCursor;
// get around the "setting the same cursor" code in setCursor()
mCurrentCursor = UI_CURSOR_COUNT;
setCursor(temp_cursor);
}
else {
// Override the cursor
SetThemeCursor(mDragOverrideCursor);
}
}
}
}
}
return result;
}
#endif // LL_OS_DRAGDROP_ENABLED