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:
@@ -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, ¤tBounds);
|
||||
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), ¤tBounds);
|
||||
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), ¤tBounds);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user