diff options
Diffstat (limited to 'indra')
29 files changed, 1612 insertions, 520 deletions
diff --git a/indra/cmake/DragDrop.cmake b/indra/cmake/DragDrop.cmake new file mode 100644 index 0000000000..c0424396e5 --- /dev/null +++ b/indra/cmake/DragDrop.cmake @@ -0,0 +1,23 @@ +# -*- cmake -*- + +if (VIEWER) + + set(OS_DRAG_DROP ON CACHE BOOL "Build the viewer with OS level drag and drop turned on or off") + + if (OS_DRAG_DROP) + + if (WINDOWS) + add_definitions(-DLL_OS_DRAGDROP_ENABLED=1) + endif (WINDOWS) + + if (DARWIN) + add_definitions(-DLL_OS_DRAGDROP_ENABLED=1) + endif (DARWIN) + + if (LINUX) + add_definitions(-DLL_OS_DRAGDROP_ENABLED=0) + endif (LINUX) + + endif (OS_DRAG_DROP) + +endif (VIEWER) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index a12b7793f7..259522a932 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -312,7 +312,6 @@ void LLTextBase::drawSelectionBackground() // Draw selection even if we don't have keyboard focus for search/replace if( hasSelection() && !mLineInfoList.empty()) { - LLWString text = getWText(); std::vector<LLRect> selection_rects; S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); @@ -411,7 +410,7 @@ void LLTextBase::drawCursor() && gFocusMgr.getAppHasFocus() && !mReadOnly) { - LLWString wtext = getWText(); + const LLWString &wtext = getWText(); const llwchar* text = wtext.c_str(); LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos); @@ -497,7 +496,6 @@ void LLTextBase::drawCursor() void LLTextBase::drawText() { - LLWString text = getWText(); const S32 text_len = getLength(); if( text_len <= 0 ) { @@ -1116,7 +1114,6 @@ void LLTextBase::reflow(S32 start_index) S32 line_start_index = 0; const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin S32 remaining_pixels = text_available_width; - LLWString text(getWText()); S32 line_count = 0; // find and erase line info structs starting at start_index and going to end of document @@ -1759,7 +1756,7 @@ void LLTextBase::setWText(const LLWString& text) setText(wstring_to_utf8str(text)); } -LLWString LLTextBase::getWText() const +const LLWString& LLTextBase::getWText() const { return getViewModel()->getDisplay(); } @@ -2454,7 +2451,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt if (num_chars > 0) { height = mFontHeight; - LLWString text = mEditor.getWText(); + const LLWString &text = mEditor.getWText(); // if last character is a newline, then return true, forcing line break llwchar last_char = text[mStart + first_char + num_chars - 1]; if (last_char == '\n') @@ -2481,7 +2478,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { - LLWString text = mEditor.getWText(); + const LLWString &text = mEditor.getWText(); return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset, (F32)segment_local_x_coord, F32_MAX, @@ -2491,7 +2488,7 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { - LLWString text = mEditor.getWText(); + const LLWString &text = mEditor.getWText(); LLUIImagePtr image = mStyle->getImage(); if( image.notNull()) diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 48d5478088..b5c7fab67a 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -145,7 +145,7 @@ public: // wide-char versions void setWText(const LLWString& text); - LLWString getWText() const; + const LLWString& getWText() const; void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params()); // force reflow of text diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index c8a9b52cca..992365d44d 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -107,7 +107,8 @@ public: // New functions /// Get the stored value in string form - LLWString getDisplay() const { return mDisplay; } + const LLWString& getDisplay() const { return mDisplay; } + /** * Set the display string directly (see LLTextEditor). What the user is * editing is actually the LLWString value rather than the underlying diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 7b1cab696f..77c6fa57b6 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -12,6 +12,7 @@ project(llwindow) include(00-Common) include(DirectX) +include(DragDrop) include(LLCommon) include(LLImage) include(LLMath) @@ -102,11 +103,13 @@ if (WINDOWS) llwindowwin32.cpp lldxhardware.cpp llkeyboardwin32.cpp + lldragdropwin32.cpp ) list(APPEND llwindow_HEADER_FILES llwindowwin32.h lldxhardware.h llkeyboardwin32.h + lldragdropwin32.h ) list(APPEND llwindow_LINK_LIBRARIES comdlg32 # Common Dialogs for ChooseColor diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp new file mode 100644 index 0000000000..9b80fe0a84 --- /dev/null +++ b/indra/llwindow/lldragdropwin32.cpp @@ -0,0 +1,370 @@ +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_WINDOWS + +#if LL_OS_DRAGDROP_ENABLED + +#include "linden_common.h" + +#include "llwindowwin32.h" +#include "llkeyboardwin32.h" +#include "llwindowcallbacks.h" +#include "lldragdropwin32.h" + +class LLDragDropWin32Target: + public IDropTarget +{ + public: + //////////////////////////////////////////////////////////////////////////////// + // + LLDragDropWin32Target( HWND hWnd ) : + mRefCount( 1 ), + mAppWindowHandle( hWnd ), + mAllowDrop( false) + { + }; + + virtual ~LLDragDropWin32Target() + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall AddRef( void ) + { + return InterlockedIncrement( &mRefCount ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall Release( void ) + { + LONG count = InterlockedDecrement( &mRefCount ); + + if ( count == 0 ) + { + delete this; + return 0; + } + else + { + return count; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject ) + { + if ( iid == IID_IUnknown || iid == IID_IDropTarget ) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + *ppvObject = 0; + return E_NOINTERFACE; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + + // support CF_TEXT using a HGLOBAL? + if ( S_OK == pDataObject->QueryGetData( &fmtetc ) ) + { + mAllowDrop = true; + mDropUrl = std::string(); + mIsSlurl = false; + + STGMEDIUM stgmed; + if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) + { + PVOID data = GlobalLock( stgmed.hGlobal ); + mDropUrl = std::string( (char*)data ); + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + + GlobalUnlock( stgmed.hGlobal ); + ReleaseStgMedium( &stgmed ); + }; + SetFocus( mAppWindowHandle ); + } + else + { + mAllowDrop = false; + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + if ( mAllowDrop ) + { + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_TRACK, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + } + else + { + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragLeave( void ) + { + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl ); + }; + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + if ( mAllowDrop ) + { + // window impl stored in Window data (neat!) + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); + if ( NULL != window_imp ) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt_client; + pt_client.x = pt.x; + pt_client.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt_client ); + + LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + llinfos << "### (Drop) URL is: " << mDropUrl << llendl; + llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; + llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; + llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; + llinfos << llendl; + + // no keyboard modifier option yet but we could one day + MASK mask = gKeyboard->currentMask( TRUE ); + + // actually do the drop + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_DROPPED, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + } + else + { + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + private: + LONG mRefCount; + HWND mAppWindowHandle; + bool mAllowDrop; + std::string mDropUrl; + bool mIsSlurl; + friend class LLWindowWin32; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::LLDragDropWin32() : + mDropTarget( NULL ), + mDropWindowHandle( NULL ) + +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::~LLDragDropWin32() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLDragDropWin32::init( HWND hWnd ) +{ + if ( NOERROR != OleInitialize( NULL ) ) + return FALSE; + + mDropTarget = new LLDragDropWin32Target( hWnd ); + if ( mDropTarget ) + { + HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE ); + if ( S_OK == result ) + { + result = RegisterDragDrop( hWnd, mDropTarget ); + if ( S_OK != result ) + { + // RegisterDragDrop failed + return false; + }; + + // all ok + mDropWindowHandle = hWnd; + } + else + { + // Unable to lock OLE object + return false; + }; + }; + + // success + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLDragDropWin32::reset() +{ + if ( mDropTarget ) + { + RevokeDragDrop( mDropWindowHandle ); + CoLockObjectExternal( mDropTarget, FALSE, TRUE ); + mDropTarget->Release(); + }; + + OleUninitialize(); +} + +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS + diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h new file mode 100644 index 0000000000..9686626d7c --- /dev/null +++ b/indra/llwindow/lldragdropwin32.h @@ -0,0 +1,80 @@ +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_WINDOWS + +#if LL_OS_DRAGDROP_ENABLED + +#ifndef LL_LLDRAGDROP32_H +#define LL_LLDRAGDROP32_H + +#include <windows.h> +#include <ole2.h> + +class LLDragDropWin32 +{ + public: + LLDragDropWin32(); + ~LLDragDropWin32(); + + bool init( HWND hWnd ); + void reset(); + + private: + IDropTarget* mDropTarget; + HWND mDropWindowHandle; +}; +#endif // LL_LLDRAGDROP32_H + +#else // LL_OS_DRAGDROP_ENABLED + +#ifndef LL_LLDRAGDROP32_H +#define LL_LLDRAGDROP32_H + +#include <windows.h> +#include <ole2.h> + +// imposter class that does nothing +class LLDragDropWin32 +{ + public: + LLDragDropWin32() {}; + ~LLDragDropWin32() {}; + + bool init( HWND hWnd ) { return false; }; + void reset() { }; +}; +#endif // LL_LLDRAGDROP32_H + +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index 72f9997149..6d9f012cc3 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -163,6 +163,11 @@ void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *da { } +LLWindowCallbacks::DragNDropResult LLWindowCallbacks::handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data ) +{ + return LLWindowCallbacks::DND_NONE; +} + BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window) { return FALSE; diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index abc66c42a2..42add8dde0 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -71,6 +71,21 @@ public: virtual BOOL handleTimerEvent(LLWindow *window); virtual BOOL handleDeviceChange(LLWindow *window); + enum DragNDropAction { + DNDA_START_TRACKING = 0,// Start tracking an incoming drag + DNDA_TRACK, // User is dragging an incoming drag around the window + DNDA_STOP_TRACKING, // User is no longer dragging an incoming drag around the window (may have either cancelled or dropped on the window) + DNDA_DROPPED // User dropped an incoming drag on the window (this is the "commit" event) + }; + + enum DragNDropResult { + DND_NONE = 0, // No drop allowed + DND_MOVE, // Drop accepted would result in a "move" operation + DND_COPY, // Drop accepted would result in a "copy" operation + DND_LINK // Drop accepted would result in a "link" operation + }; + virtual DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data); + virtual void handlePingWatchdog(LLWindow *window, const char * msg); virtual void handlePauseWatchdog(LLWindow *window); virtual void handleResumeWatchdog(LLWindow *window); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index ed62faece6..9ccd4c7f97 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -278,6 +278,8 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator); mGlobalHandlerRef = NULL; mWindowHandlerRef = NULL; + + mDragOverrideCursor = -1; // We're not clipping yet SetRect( &mOldMouseClip, 0, 0, 0, 0 ); @@ -499,8 +501,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 } { @@ -2174,11 +2179,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. @@ -2795,6 +2797,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) { @@ -3379,3 +3389,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 diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index fbfa07fab4..377f10b6d4 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -34,6 +34,7 @@ #define LL_LLWINDOWMACOSX_H #include "llwindow.h" +#include "llwindowcallbacks.h" #include "lltimer.h" @@ -159,8 +160,15 @@ protected: void adjustCursorDecouple(bool warpingMouse = false); void fixWindowSize(void); void stopDockTileBounce(); - - + static MASK modifiersToMask(SInt16 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); +#endif // LL_OS_DRAGDROP_ENABLED + // // Platform specific variables // @@ -193,11 +201,13 @@ protected: U32 mFSAASamples; BOOL mForceRebuild; + S32 mDragOverrideCursor; + F32 mBounceTime; NMRec mBounceRec; LLTimer mBounceTimer; - // Imput method management through Text Service Manager. + // Input method management through Text Service Manager. TSMDocumentID mTSMDocument; BOOL mLanguageTextInputAllowed; ScriptCode mTSMScriptCode; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b591111b75..57a4921d92 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -38,6 +38,7 @@ // LLWindow library includes #include "llkeyboardwin32.h" +#include "lldragdropwin32.h" #include "llpreeditor.h" #include "llwindowcallbacks.h" @@ -52,6 +53,7 @@ #include <mapi.h> #include <process.h> // for _spawn #include <shellapi.h> +#include <fstream> #include <Imm.h> // Require DirectInput version 8 @@ -383,6 +385,9 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, gKeyboard = new LLKeyboardWin32(); gKeyboard->setCallbacks(callbacks); + // Initialize the Drag and Drop functionality + mDragDrop = new LLDragDropWin32; + // Initialize (boot strap) the Language text input management, // based on the system's (user's) default settings. allowLanguageTextInput(mPreeditor, FALSE); @@ -620,6 +625,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, LLWindowWin32::~LLWindowWin32() { + delete mDragDrop; + delete [] mWindowTitle; mWindowTitle = NULL; @@ -671,6 +678,8 @@ void LLWindowWin32::close() return; } + mDragDrop->reset(); + // Make sure cursor is visible and we haven't mangled the clipping state. setMouseClipping(FALSE); showCursor(); @@ -1349,6 +1358,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO } SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this); + + // register this window as handling drag/drop events from the OS + DragAcceptFiles( mWindowHandle, TRUE ); + + mDragDrop->init( mWindowHandle ); //register joystick timer callback SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer @@ -2354,11 +2368,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ return 0; case WM_COPYDATA: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); - // received a URL - PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; - window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); + { + window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); + // received a URL + PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; + window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); + }; return 0; + + break; } window_imp->mCallbacks->handlePauseWatchdog(window_imp); @@ -3528,6 +3546,13 @@ static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_leng return wtext.substr(start, end - start); } +// final stage of handling drop requests - both from WM_DROPFILES message +// for files and via IDropTarget interface requests. +LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ) +{ + return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url ); +} + // Handle WM_IME_REQUEST message. // If it handled the message, returns TRUE. Otherwise, FALSE. // When it handled the message, the value to be returned from diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index e4e9179db7..6aca31b63e 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -39,6 +39,8 @@ #include <windows.h> #include "llwindow.h" +#include "llwindowcallbacks.h" +#include "lldragdropwin32.h" // Hack for async host by name #define LL_WM_HOST_RESOLVED (WM_APP + 1) @@ -114,6 +116,8 @@ public: /*virtual*/ void interruptLanguageTextInput(); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url); + LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ); + static std::vector<std::string> getDynamicFallbackFontList(); protected: @@ -205,6 +209,8 @@ protected: LLPreeditor *mPreeditor; + LLDragDropWin32* mDragDrop; + friend class LLWindowManager; }; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1c32c690a8..cd7c002096 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -7,6 +7,7 @@ include(Boost) include(BuildVersion) include(DBusGlib) include(DirectX) +include(DragDrop) include(ELFIO) include(FMOD) include(OPENAL) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2a7c3b0f74..62197406b6 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5527,6 +5527,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>PrimMediaDragNDrop</key> + <map> + <key>Comment</key> + <string>Enable drag and drop of URLs onto prim faces</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>PrimMediaMaxRetries</key> <map> <key>Comment</key> @@ -10820,6 +10831,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>SLURLDragNDrop</key> + <map> + <key>Comment</key> + <string>Enable drag and drop of SLURLs onto the viewer</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>soundsbeacon</key> <map> <key>Comment</key> diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 0ad283d7c6..8cd63deebe 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -427,8 +427,26 @@ BOOL LLPanelLandGeneral::postBuild() mBtnBuyLand = getChild<LLButton>("Buy Land..."); mBtnBuyLand->setClickedCallback(onClickBuyLand, (void*)&BUY_PERSONAL_LAND); - mBtnScriptLimits = getChild<LLButton>("Scripts..."); - mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this); + // note: on region change this will not be re checked, should not matter on Agni as + // 99% of the time all regions will return the same caps. In case of an erroneous setting + // to enabled the floater will just throw an error when trying to get it's cap + std::string url = gAgent.getRegion()->getCapability("LandResources"); + if (!url.empty()) + { + mBtnScriptLimits = getChild<LLButton>("Scripts..."); + if(mBtnScriptLimits) + { + mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this); + } + } + else + { + mBtnScriptLimits = getChild<LLButton>("Scripts..."); + if(mBtnScriptLimits) + { + mBtnScriptLimits->setVisible(false); + } + } mBtnBuyGroupLand = getChild<LLButton>("Buy For Group..."); mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND); diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 8875e35821..4194416a01 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -59,10 +59,30 @@ /// LLFloaterScriptLimits ///---------------------------------------------------------------------------- -// due to server side bugs the full summary display is not possible -// until they are fixed this define creates a simple version of the -// summary which only shows available & correct information -#define USE_SIMPLE_SUMMARY +// debug switches, won't work in release +#ifndef LL_RELEASE_FOR_DOWNLOAD + +// dump responder replies to llinfos for debugging +//#define DUMP_REPLIES_TO_LLINFOS + +#ifdef DUMP_REPLIES_TO_LLINFOS +#include "llsdserialize.h" +#include "llwindow.h" +#endif + +// use fake LLSD responses to check the viewer side is working correctly +// I'm syncing this with the server side efforts so hopfully we can keep +// the to-ing and fro-ing between the two teams to a minimum +//#define USE_FAKE_RESPONSES + +#ifdef USE_FAKE_RESPONSES +const S32 FAKE_NUMBER_OF_URLS = 329; +const S32 FAKE_AVAILABLE_URLS = 731; +const S32 FAKE_AMOUNT_OF_MEMORY = 66741; +const S32 FAKE_AVAILABLE_MEMORY = 895577; +#endif + +#endif const S32 SIZE_OF_ONE_KB = 1024; @@ -87,32 +107,41 @@ BOOL LLFloaterScriptLimits::postBuild() } mTab = getChild<LLTabContainer>("scriptlimits_panels"); + + if(!mTab) + { + llinfos << "Error! couldn't get scriptlimits_panels, aborting Script Information setup" << llendl; + return FALSE; + } // contruct the panels - LLPanelScriptLimitsRegionMemory* panel_memory; - panel_memory = new LLPanelScriptLimitsRegionMemory; - mInfoPanels.push_back(panel_memory); + std::string land_url = gAgent.getRegion()->getCapability("LandResources"); + if (!land_url.empty()) + { + LLPanelScriptLimitsRegionMemory* panel_memory; + panel_memory = new LLPanelScriptLimitsRegionMemory; + mInfoPanels.push_back(panel_memory); + LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml"); + mTab->addTabPanel(panel_memory); + } - LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml"); - mTab->addTabPanel(panel_memory); - - LLPanelScriptLimitsRegionURLs* panel_urls = new LLPanelScriptLimitsRegionURLs; - mInfoPanels.push_back(panel_urls); - LLUICtrlFactory::getInstance()->buildPanel(panel_urls, "panel_script_limits_region_urls.xml"); - mTab->addTabPanel(panel_urls); - - LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment; - mInfoPanels.push_back(panel_attachments); - LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml"); - mTab->addTabPanel(panel_attachments); - - if(selectParcelPanel) + std::string attachment_url = gAgent.getRegion()->getCapability("AttachmentResources"); + if (!attachment_url.empty()) + { + LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment; + mInfoPanels.push_back(panel_attachments); + LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml"); + mTab->addTabPanel(panel_attachments); + } + + if(mInfoPanels.size() > 0) { mTab->selectTab(0); } - else + + if(!selectParcelPanel && (mInfoPanels.size() > 1)) { - mTab->selectTab(2); + mTab->selectTab(1); } return TRUE; @@ -160,6 +189,20 @@ void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr) void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) { + //we don't need to test with a fake respose here (shouldn't anyway) + +#ifdef DUMP_REPLIES_TO_LLINFOS + + LLSDNotationStreamer notation_streamer(content); + std::ostringstream nice_llsd; + nice_llsd << notation_streamer; + + OSMessageBox(nice_llsd.str(), "main cap response:", 0); + + llinfos << "main cap response:" << content << llendl; + +#endif + // at this point we have an llsd which should contain ether one or two urls to the services we want. // first we look for the details service: if(content.has("ScriptResourceDetails")) @@ -173,24 +216,6 @@ void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) { llinfos << "Failed to get llfloaterscriptlimits instance" << llendl; } - else - { - -// temp - only show info if we get details - there's nothing to show if not until the sim gets fixed -#ifdef USE_SIMPLE_SUMMARY - - LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - std::string msg = LLTrans::getString("ScriptLimitsRequestDontOwnParcel"); - panel_memory->childSetValue("loading_text", LLSD(msg)); - LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); - panel_urls->childSetValue("loading_text", LLSD(msg)); - - // intentional early out as we dont want the resource summary if we are using the "simple summary" - // and the details are missing - return; -#endif - } } // then the summary service: @@ -205,8 +230,61 @@ void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string& llinfos << "Error from responder " << reason << llendl; } -void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content) +void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) { +#ifdef USE_FAKE_RESPONSES + + LLSD fake_content; + LLSD summary = LLSD::emptyMap(); + LLSD available = LLSD::emptyArray(); + LLSD available_urls = LLSD::emptyMap(); + LLSD available_memory = LLSD::emptyMap(); + LLSD used = LLSD::emptyArray(); + LLSD used_urls = LLSD::emptyMap(); + LLSD used_memory = LLSD::emptyMap(); + + used_urls["type"] = "urls"; + used_urls["amount"] = FAKE_NUMBER_OF_URLS; + available_urls["type"] = "urls"; + available_urls["amount"] = FAKE_AVAILABLE_URLS; + used_memory["type"] = "memory"; + used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY; + available_memory["type"] = "memory"; + available_memory["amount"] = FAKE_AVAILABLE_MEMORY; + +//summary response:{'summary':{'available':[{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'},{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'}],'used':[{'amount':i329,'type':'urls'},{'amount':i66741,'type':'memory'}]}} + + used.append(used_urls); + used.append(used_memory); + available.append(available_urls); + available.append(available_memory); + + summary["available"] = available; + summary["used"] = used; + + fake_content["summary"] = summary; + + const LLSD& content = fake_content; + +#else + + const LLSD& content = content_ref; + +#endif + + +#ifdef DUMP_REPLIES_TO_LLINFOS + + LLSDNotationStreamer notation_streamer(content); + std::ostringstream nice_llsd; + nice_llsd << notation_streamer; + + OSMessageBox(nice_llsd.str(), "summary response:", 0); + + llinfos << "summary response:" << *content << llendl; + +#endif + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); if(!instance) { @@ -217,8 +295,6 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content) LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); panel_memory->setRegionSummary(content); - LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); - panel_urls->setRegionSummary(content); } } @@ -227,8 +303,82 @@ void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::strin llinfos << "Error from responder " << reason << llendl; } -void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content) +void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref) { +#ifdef USE_FAKE_RESPONSES +/* +Updated detail service, ** denotes field added: + +result (map) ++-parcels (array of maps) + +-id (uuid) + +-local_id (S32)** + +-name (string) + +-owner_id (uuid) (in ERS as owner, but owner_id in code) + +-objects (array of maps) + +-id (uuid) + +-name (string) + +-owner_id (uuid) (in ERS as owner, in code as owner_id) + +-owner_name (sting)** + +-location (map)** + +-x (float) + +-y (float) + +-z (float) + +-resources (map) (this is wrong in the ERS but right in code) + +-type (string) + +-amount (int) +*/ + LLSD fake_content; + LLSD resource = LLSD::emptyMap(); + LLSD location = LLSD::emptyMap(); + LLSD object = LLSD::emptyMap(); + LLSD objects = LLSD::emptyArray(); + LLSD parcel = LLSD::emptyMap(); + LLSD parcels = LLSD::emptyArray(); + + resource["urls"] = FAKE_NUMBER_OF_URLS; + resource["memory"] = FAKE_AMOUNT_OF_MEMORY; + + location["x"] = 128.0f; + location["y"] = 128.0f; + location["z"] = 0.0f; + + object["id"] = LLUUID("d574a375-0c6c-fe3d-5733-da669465afc7"); + object["name"] = "Gabs fake Object!"; + object["owner_id"] = LLUUID("8dbf2d41-69a0-4e5e-9787-0c9d297bc570"); + object["owner_name"] = "Gabs Linden"; + object["location"] = location; + object["resources"] = resource; + + objects.append(object); + + parcel["id"] = LLUUID("da05fb28-0d20-e593-2728-bddb42dd0160"); + parcel["local_id"] = 42; + parcel["name"] = "Gabriel Linden\'s Sub Plot"; + parcel["objects"] = objects; + parcels.append(parcel); + + fake_content["parcels"] = parcels; + const LLSD& content = fake_content; + +#else + + const LLSD& content = content_ref; + +#endif + +#ifdef DUMP_REPLIES_TO_LLINFOS + + LLSDNotationStreamer notation_streamer(content); + std::ostringstream nice_llsd; + nice_llsd << notation_streamer; + + OSMessageBox(nice_llsd.str(), "details response:", 0); + + llinfos << "details response:" << content << llendl; + +#endif + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); if(!instance) @@ -238,11 +388,22 @@ void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content) else { LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - panel_memory->setRegionDetails(content); - - LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); - panel_urls->setRegionDetails(content); + if(tab) + { + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + if(panel_memory) + { + panel_memory->setRegionDetails(content); + } + else + { + llinfos << "Failed to get scriptlimits memory panel" << llendl; + } + } + else + { + llinfos << "Failed to get scriptlimits_panels" << llendl; + } } } @@ -251,8 +412,61 @@ void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::strin llinfos << "Error from responder " << reason << llendl; } -void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content) +void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) { + +#ifdef USE_FAKE_RESPONSES + + // just add the summary, as that's all I'm testing currently! + LLSD fake_content = LLSD::emptyMap(); + LLSD summary = LLSD::emptyMap(); + LLSD available = LLSD::emptyArray(); + LLSD available_urls = LLSD::emptyMap(); + LLSD available_memory = LLSD::emptyMap(); + LLSD used = LLSD::emptyArray(); + LLSD used_urls = LLSD::emptyMap(); + LLSD used_memory = LLSD::emptyMap(); + + used_urls["type"] = "urls"; + used_urls["amount"] = FAKE_NUMBER_OF_URLS; + available_urls["type"] = "urls"; + available_urls["amount"] = FAKE_AVAILABLE_URLS; + used_memory["type"] = "memory"; + used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY; + available_memory["type"] = "memory"; + available_memory["amount"] = FAKE_AVAILABLE_MEMORY; + + used.append(used_urls); + used.append(used_memory); + available.append(available_urls); + available.append(available_memory); + + summary["available"] = available; + summary["used"] = used; + + fake_content["summary"] = summary; + fake_content["attachments"] = content_ref["attachments"]; + + const LLSD& content = fake_content; + +#else + + const LLSD& content = content_ref; + +#endif + +#ifdef DUMP_REPLIES_TO_LLINFOS + + LLSDNotationStreamer notation_streamer(content); + std::ostringstream nice_llsd; + nice_llsd << notation_streamer; + + OSMessageBox(nice_llsd.str(), "attachment response:", 0); + + llinfos << "attachment response:" << content << llendl; + +#endif + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); if(!instance) @@ -262,8 +476,22 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content) else { LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel"); - panel->setAttachmentDetails(content); + if(tab) + { + LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel"); + if(panel) + { + panel->setAttachmentDetails(content); + } + else + { + llinfos << "Failed to get script_limits_my_avatar_panel" << llendl; + } + } + else + { + llinfos << "Failed to get scriptlimits_panels" << llendl; + } } } @@ -309,7 +537,7 @@ void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parc { std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting"); childSetValue("loading_text", LLSD(msg_waiting)); - } + } } void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id) @@ -341,6 +569,11 @@ void LLPanelScriptLimitsRegionMemory::onNameCache( std::string name = first_name + " " + last_name; LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + if(!list) + { + return; + } + std::vector<LLSD>::iterator id_itor; for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) { @@ -351,33 +584,8 @@ void LLPanelScriptLimitsRegionMemory::onNameCache( if(item) { - item->getColumn(2)->setValue(LLSD(name)); - element["columns"][2]["value"] = name; - } - } - } - - // fill in the url's tab if needed, all urls must have memory so we can do it all here - LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); - if(instance) - { - LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); - - LLScrollListCtrl *list = panel->getChild<LLScrollListCtrl>("scripts_list"); - std::vector<LLSD>::iterator id_itor; - for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) - { - LLSD element = *id_itor; - if(element["owner_id"].asUUID() == id) - { - LLScrollListItem* item = list->getItem(element["id"].asUUID()); - - if(item) - { - item->getColumn(2)->setValue(LLSD(name)); - element["columns"][2]["value"] = name; - } + item->getColumn(3)->setValue(LLSD(name)); + element["columns"][3]["value"] = name; } } } @@ -386,6 +594,12 @@ void LLPanelScriptLimitsRegionMemory::onNameCache( void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) { LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + + if(!list) + { + llinfos << "Error getting the scripts_list control" << llendl; + return; + } S32 number_parcels = content["parcels"].size(); @@ -394,130 +608,197 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels); childSetValue("parcels_listed", LLSD(msg_parcels)); - S32 total_objects = 0; - S32 total_size = 0; - std::vector<LLUUID> names_requested; + // This makes the assumption that all objects will have the same set + // of attributes, ie they will all have, or none will have locations + // This is a pretty safe assumption as it's reliant on server version. + bool has_locations = false; + bool has_local_ids = false; + for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); LLUUID parcel_id = content["parcels"][i]["id"].asUUID(); S32 number_objects = content["parcels"][i]["objects"].size(); + + S32 local_id = 0; + if(content["parcels"][i].has("local_id")) + { + // if any locations are found flag that we can use them and turn on the highlight button + has_local_ids = true; + local_id = content["parcels"][i]["local_id"].asInteger(); + } + for(S32 j = 0; j < number_objects; j++) { S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB; - total_size += size; + + S32 urls = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger(); std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); - + + F32 location_x = 0.0f; + F32 location_y = 0.0f; + F32 location_z = 0.0f; + + if(content["parcels"][i]["objects"][j].has("location")) + { + // if any locations are found flag that we can use them and turn on the highlight button + LLVector3 vec = ll_vector3_from_sd(content["parcels"][i]["objects"][j]["location"]); + has_locations = true; + location_x = vec.mV[0]; + location_y = vec.mV[1]; + location_z = vec.mV[2]; + } + std::string owner_buf; - - BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf); - if(!name_is_cached) + + // in the future the server will give us owner names, so see if we're there yet: + if(content["parcels"][i]["objects"][j].has("owner_name")) + { + owner_buf = content["parcels"][i]["objects"][j]["owner_name"].asString(); + } + // ...and if not use the slightly more painful method of disovery: + else { - if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end()) + BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf); + if(!name_is_cached) { - names_requested.push_back(owner_id); - gCacheName->get(owner_id, TRUE, - boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache, - this, _1, _2, _3)); + if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end()) + { + names_requested.push_back(owner_id); + gCacheName->get(owner_id, TRUE, + boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache, + this, _1, _2, _3)); + } } } LLSD element; element["id"] = task_id; - element["owner_id"] = owner_id; element["columns"][0]["column"] = "size"; element["columns"][0]["value"] = llformat("%d", size); element["columns"][0]["font"] = "SANSSERIF"; - element["columns"][1]["column"] = "name"; - element["columns"][1]["value"] = name_buf; + element["columns"][1]["column"] = "urls"; + element["columns"][1]["value"] = llformat("%d", urls); element["columns"][1]["font"] = "SANSSERIF"; - element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = owner_buf; + element["columns"][2]["column"] = "name"; + element["columns"][2]["value"] = name_buf; element["columns"][2]["font"] = "SANSSERIF"; - element["columns"][3]["column"] = "location"; - element["columns"][3]["value"] = parcel_name; + element["columns"][3]["column"] = "owner"; + element["columns"][3]["value"] = owner_buf; element["columns"][3]["font"] = "SANSSERIF"; + element["columns"][4]["column"] = "parcel"; + element["columns"][4]["value"] = parcel_name; + element["columns"][4]["font"] = "SANSSERIF"; + element["columns"][5]["column"] = "location"; + if(has_locations) + { + element["columns"][5]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z); + } + else + { + element["columns"][5]["value"] = ""; + } + element["columns"][5]["font"] = "SANSSERIF"; list->addElement(element, ADD_SORTED); + + element["owner_id"] = owner_id; + element["local_id"] = local_id; mObjectListItems.push_back(element); - total_objects++; } } - mParcelMemoryUsed =total_size; - mGotParcelMemoryUsed = TRUE; - populateParcelMemoryText(); -} + if (has_locations) + { + LLButton* btn = getChild<LLButton>("highlight_btn"); + if(btn) + { + btn->setVisible(true); + } + } -void LLPanelScriptLimitsRegionMemory::populateParcelMemoryText() -{ - if(mGotParcelMemoryUsed && mGotParcelMemoryMax) + if (has_local_ids) { -#ifdef USE_SIMPLE_SUMMARY - LLStringUtil::format_map_t args_parcel_memory; - args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed); - std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsedSimple", args_parcel_memory); - childSetValue("memory_used", LLSD(msg_parcel_memory)); -#else - S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed; + LLButton* btn = getChild<LLButton>("return_btn"); + if(btn) + { + btn->setVisible(true); + } + } - LLStringUtil::format_map_t args_parcel_memory; - args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed); - args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax); - args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available); - std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory); - childSetValue("memory_used", LLSD(msg_parcel_memory)); -#endif + // save the structure to make object return easier + mContent = content; - childSetValue("loading_text", LLSD(std::string(""))); - } + childSetValue("loading_text", LLSD(std::string(""))); } void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content) { - if(content["summary"]["available"][0]["type"].asString() == std::string("memory")) + if(content["summary"]["used"][0]["type"].asString() == std::string("memory")) { - mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger(); - mGotParcelMemoryMax = TRUE; + mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB; + mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB; + mGotParcelMemoryUsed = TRUE; } - else if(content["summary"]["available"][1]["type"].asString() == std::string("memory")) + else if(content["summary"]["used"][1]["type"].asString() == std::string("memory")) { - mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger(); - mGotParcelMemoryMax = TRUE; + mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB; + mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB; + mGotParcelMemoryUsed = TRUE; } else { llinfos << "summary doesn't contain memory info" << llendl; return; } -/* - currently this is broken on the server, so we get this value from the details section - and update via populateParcelMemoryText() when both sets of information have been returned - - when the sim is fixed this should be used instead: - if(content["summary"]["used"][0]["type"].asString() == std::string("memory")) + + if(content["summary"]["used"][0]["type"].asString() == std::string("urls")) { - mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger(); - mGotParcelMemoryUsed = TRUE; + mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger(); + mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger(); + mGotParcelURLsUsed = TRUE; } - else if(content["summary"]["used"][1]["type"].asString() == std::string("memory")) + else if(content["summary"]["used"][1]["type"].asString() == std::string("urls")) { - mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger(); - mGotParcelMemoryUsed = TRUE; + mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger(); + mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger(); + mGotParcelURLsUsed = TRUE; } else { - //ERROR!!! + llinfos << "summary doesn't contain urls info" << llendl; return; - }*/ + } - populateParcelMemoryText(); + if((mParcelMemoryUsed >= 0) && (mParcelMemoryMax >= 0)) + { + S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed; + + LLStringUtil::format_map_t args_parcel_memory; + args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed); + args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax); + args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available); + std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory); + childSetValue("memory_used", LLSD(msg_parcel_memory)); + } + + if((mParcelURLsUsed >= 0) && (mParcelURLsMax >= 0)) + { + S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed; + + LLStringUtil::format_map_t args_parcel_urls; + args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed); + args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax); + args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available); + std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls); + childSetValue("urls_used", LLSD(msg_parcel_urls)); + } } BOOL LLPanelScriptLimitsRegionMemory::postBuild() @@ -530,6 +811,10 @@ BOOL LLPanelScriptLimitsRegionMemory::postBuild() childSetValue("loading_text", LLSD(msg_waiting)); LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + if(!list) + { + return FALSE; + } //set all columns to resizable mode even if some columns will be empty for(S32 column = 0; column < list->getNumColumns(); column++) @@ -548,18 +833,11 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain() LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land"); if(!instance) { - //this isnt really an error... -// llinfos << "Failed to get about land instance" << llendl; -// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); childSetValue("loading_text", LLSD(std::string(""))); //might have to do parent post build here //if not logic below could use early outs return FALSE; } - - LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); - LLParcel* parcel = instance->getCurrentSelectedParcel(); LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); @@ -575,7 +853,6 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain() { std::string msg_wrong_region = LLTrans::getString("ScriptLimitsRequestWrongRegion"); childSetValue("loading_text", LLSD(msg_wrong_region)); - panel_urls->childSetValue("loading_text", LLSD(msg_wrong_region)); return FALSE; } @@ -605,14 +882,12 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain() std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); childSetValue("loading_text", LLSD(msg_waiting)); - panel_urls->childSetValue("loading_text", LLSD(msg_waiting)); } } else { - std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestNoParcelSelected"); childSetValue("loading_text", LLSD(msg_waiting)); - panel_urls->childSetValue("loading_text", LLSD(msg_waiting)); } return LLPanelScriptLimitsInfo::postBuild(); @@ -629,10 +904,13 @@ void LLPanelScriptLimitsRegionMemory::clearList() mGotParcelMemoryUsed = FALSE; mGotParcelMemoryMax = FALSE; + mGotParcelURLsUsed = FALSE; + mGotParcelURLsMax = FALSE; LLStringUtil::format_map_t args_parcel_memory; std::string msg_empty_string(""); childSetValue("memory_used", LLSD(msg_empty_string)); + childSetValue("urls_used", LLSD(msg_empty_string)); childSetValue("parcels_listed", LLSD(msg_empty_string)); mObjectListItems.clear(); @@ -647,13 +925,16 @@ void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata) if(instance) { LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - panel_memory->clearList(); - - LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); - panel_urls->clearList(); + if(tab) + { + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + if(panel_memory) + { + panel_memory->clearList(); - panel_memory->StartRequestChain(); + panel_memory->StartRequestChain(); + } + } return; } else @@ -665,78 +946,80 @@ void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata) void LLPanelScriptLimitsRegionMemory::showBeacon() { -/* LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list"); + LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list"); if (!list) return; LLScrollListItem* first_selected = list->getFirstSelected(); if (!first_selected) return; - std::string name = first_selected->getColumn(1)->getValue().asString(); - std::string pos_string = first_selected->getColumn(3)->getValue().asString(); + std::string name = first_selected->getColumn(2)->getValue().asString(); + std::string pos_string = first_selected->getColumn(5)->getValue().asString(); - llinfos << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" <<llendl; - llinfos << "name = " << name << " pos = " << pos_string << llendl; - F32 x, y, z; S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z); if (matched != 3) return; LLVector3 pos_agent(x, y, z); LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); - llinfos << "name = " << name << " pos = " << pos_string << llendl; + std::string tooltip(""); - LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);*/ + LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM); } // static void LLPanelScriptLimitsRegionMemory::onClickHighlight(void* userdata) { -/* llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl; + llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl; LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); if(instance) { LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - panel->showBeacon(); + if(tab) + { + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + if(panel) + { + panel->showBeacon(); + } + } return; } else { llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; -// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); -// panel->childSetValue("loading_text", LLSD(msg_waiting)); return; - }*/ + } } -void LLPanelScriptLimitsRegionMemory::returnObjects() +void LLPanelScriptLimitsRegionMemory::returnObjectsFromParcel(S32 local_id) { -/* llinfos << "started" << llendl; LLMessageSystem *msg = gMessageSystem; LLViewerRegion* region = gAgent.getRegion(); if (!region) return; - llinfos << "got region" << llendl; LLCtrlListInterface *list = childGetListInterface("scripts_list"); if (!list || list->getItemCount() == 0) return; - llinfos << "got list" << llendl; - std::vector<LLUUID>::iterator id_itor; + std::vector<LLSD>::iterator id_itor; bool start_message = true; - for (id_itor = mObjectListIDs.begin(); id_itor != mObjectListIDs.end(); ++id_itor) + for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) { - LLUUID task_id = *id_itor; - llinfos << task_id << llendl; - if (!list->isSelected(task_id)) + LLSD element = *id_itor; + if (!list->isSelected(element["id"].asUUID())) { - llinfos << "not selected" << llendl; // Selected only continue; } - llinfos << "selected" << llendl; + + if(element["local_id"].asInteger() != local_id) + { + // Not the parcel we are looking for + continue; + } + if (start_message) { msg->newMessageFast(_PREHASH_ParcelReturnObjects); @@ -744,285 +1027,74 @@ void LLPanelScriptLimitsRegionMemory::returnObjects() msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ParcelData); - msg->addS32Fast(_PREHASH_LocalID, -1); // Whole region - msg->addS32Fast(_PREHASH_ReturnType, RT_LIST); + msg->addS32Fast(_PREHASH_LocalID, element["local_id"].asInteger()); + msg->addU32Fast(_PREHASH_ReturnType, RT_LIST); start_message = false; - llinfos << "start message" << llendl; } msg->nextBlockFast(_PREHASH_TaskIDs); - msg->addUUIDFast(_PREHASH_TaskID, task_id); - llinfos << "added id" << llendl; + msg->addUUIDFast(_PREHASH_TaskID, element["id"].asUUID()); if (msg->isSendFullFast(_PREHASH_TaskIDs)) { msg->sendReliable(region->getHost()); start_message = true; - llinfos << "sent 1" << llendl; } } if (!start_message) { msg->sendReliable(region->getHost()); - llinfos << "sent 2" << llendl; - }*/ + } } -// static -void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata) +void LLPanelScriptLimitsRegionMemory::returnObjects() { -/* llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl; - LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); - if(instance) + if(!mContent.has("parcels")) { - LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - panel->returnObjects(); return; } - else - { - llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; -// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); -// panel->childSetValue("loading_text", LLSD(msg_waiting)); - return; - }*/ -} - -///---------------------------------------------------------------------------- -// URLs Panel -///---------------------------------------------------------------------------- - -void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) -{ - LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); - - S32 number_parcels = content["parcels"].size(); - - LLStringUtil::format_map_t args_parcels; - args_parcels["[PARCELS]"] = llformat ("%d", number_parcels); - std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels); - childSetValue("parcels_listed", LLSD(msg_parcels)); - - S32 total_objects = 0; - S32 total_size = 0; + S32 number_parcels = mContent["parcels"].size(); + + // a message per parcel containing all objects to be returned from that parcel for(S32 i = 0; i < number_parcels; i++) { - std::string parcel_name = content["parcels"][i]["name"].asString(); - llinfos << parcel_name << llendl; - - S32 number_objects = content["parcels"][i]["objects"].size(); - for(S32 j = 0; j < number_objects; j++) + S32 local_id = 0; + if(mContent["parcels"][i].has("local_id")) { - if(content["parcels"][i]["objects"][j]["resources"].has("urls")) - { - S32 size = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger(); - total_size += size; - - std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); - LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); - LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); - - std::string owner_buf; - gCacheName->getFullName(owner_id, owner_buf); //dont care if this fails as the memory tab will request and fill the field - - LLSD element; - - element["id"] = task_id; - element["columns"][0]["column"] = "urls"; - element["columns"][0]["value"] = llformat("%d", size); - element["columns"][0]["font"] = "SANSSERIF"; - element["columns"][1]["column"] = "name"; - element["columns"][1]["value"] = name_buf; - element["columns"][1]["font"] = "SANSSERIF"; - element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = owner_buf; - element["columns"][2]["font"] = "SANSSERIF"; - element["columns"][3]["column"] = "location"; - element["columns"][3]["value"] = parcel_name; - element["columns"][3]["font"] = "SANSSERIF"; - - list->addElement(element); - mObjectListItems.push_back(element); - total_objects++; - } + local_id = mContent["parcels"][i]["local_id"].asInteger(); + returnObjectsFromParcel(local_id); } } - - mParcelURLsUsed =total_size; - mGotParcelURLsUsed = TRUE; - populateParcelURLsText(); -} - -void LLPanelScriptLimitsRegionURLs::populateParcelURLsText() -{ - if(mGotParcelURLsUsed && mGotParcelURLsMax) - { - -#ifdef USE_SIMPLE_SUMMARY - LLStringUtil::format_map_t args_parcel_urls; - args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed); - std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsedSimple", args_parcel_urls); - childSetValue("urls_used", LLSD(msg_parcel_urls)); -#else - S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed; - LLStringUtil::format_map_t args_parcel_urls; - args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed); - args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax); - args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available); - std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls); - childSetValue("urls_used", LLSD(msg_parcel_urls)); -#endif - - childSetValue("loading_text", LLSD(std::string(""))); - - } + onClickRefresh(NULL); } -void LLPanelScriptLimitsRegionURLs::setRegionSummary(LLSD content) -{ - if(content["summary"]["available"][0]["type"].asString() == std::string("urls")) - { - mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger(); - mGotParcelURLsMax = TRUE; - } - else if(content["summary"]["available"][1]["type"].asString() == std::string("urls")) - { - mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger(); - mGotParcelURLsMax = TRUE; - } - else - { - llinfos << "summary contains no url info" << llendl; - return; - } -/* - currently this is broken on the server, so we get this value from the details section - and update via populateParcelMemoryText() when both sets of information have been returned - - when the sim is fixed this should be used instead: - if(content["summary"]["used"][0]["type"].asString() == std::string("urls")) - { - mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger(); - mGotParcelURLsUsed = TRUE; - } - else if(content["summary"]["used"][1]["type"].asString() == std::string("urls")) - { - mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger(); - mGotParcelURLsUsed = TRUE; - } - else - { - //ERROR!!! - return; - }*/ - - populateParcelURLsText(); -} - -BOOL LLPanelScriptLimitsRegionURLs::postBuild() -{ - childSetAction("refresh_list_btn", onClickRefresh, this); - childSetAction("highlight_btn", onClickHighlight, this); - childSetAction("return_btn", onClickReturn, this); - - std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting"); - childSetValue("loading_text", LLSD(msg_waiting)); - return FALSE; -} - -void LLPanelScriptLimitsRegionURLs::clearList() -{ - LLCtrlListInterface *list = childGetListInterface("scripts_list"); - - if (list) - { - list->operateOnAll(LLCtrlListInterface::OP_DELETE); - } - - mGotParcelURLsUsed = FALSE; - mGotParcelURLsMax = FALSE; - - LLStringUtil::format_map_t args_parcel_urls; - std::string msg_empty_string(""); - childSetValue("urls_used", LLSD(msg_empty_string)); - childSetValue("parcels_listed", LLSD(msg_empty_string)); - - mObjectListItems.clear(); -} - -// static -void LLPanelScriptLimitsRegionURLs::onClickRefresh(void* userdata) -{ - llinfos << "Refresh clicked" << llendl; - - LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); - if(instance) - { - LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - // use the memory panel to re-request all the info - panel_memory->clearList(); - - LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); - // but the urls panel to clear itself - panel_urls->clearList(); - - panel_memory->StartRequestChain(); - return; - } - else - { - llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl; - return; - } -} // static -void LLPanelScriptLimitsRegionURLs::onClickHighlight(void* userdata) +void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata) { -/* llinfos << "Highlight clicked" << llendl; + llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl; LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); if(instance) { LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - // use the beacon function from the memory panel - panel->showBeacon(); + if(tab) + { + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + if(panel) + { + panel->returnObjects(); + } + } return; } else { llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; -// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); -// panel->childSetValue("loading_text", LLSD(msg_waiting)); - return; - }*/ -} - -// static -void LLPanelScriptLimitsRegionURLs::onClickReturn(void* userdata) -{ -/* llinfos << "Return clicked" << llendl; - LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); - if(instance) - { - LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); - LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); - // use the return function from the memory panel - panel->returnObjects(); return; } - else - { - llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; -// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); -// panel->childSetValue("loading_text", LLSD(msg_waiting)); - return; - }*/ } ///---------------------------------------------------------------------------- @@ -1047,6 +1119,12 @@ BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails() void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content) { LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + + if(!list) + { + return; + } + S32 number_attachments = content["attachments"].size(); for(int i = 0; i < number_attachments; i++) @@ -1096,6 +1174,8 @@ void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content) list->addElement(element); } } + + setAttachmentSummary(content); childSetValue("loading_text", LLSD(std::string(""))); } @@ -1122,6 +1202,69 @@ void LLPanelScriptLimitsAttachment::clearList() childSetValue("loading_text", LLSD(msg_waiting)); } +void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content) +{ + if(content["summary"]["used"][0]["type"].asString() == std::string("memory")) + { + mAttachmentMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB; + mAttachmentMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB; + mGotAttachmentMemoryUsed = TRUE; + } + else if(content["summary"]["used"][1]["type"].asString() == std::string("memory")) + { + mAttachmentMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB; + mAttachmentMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB; + mGotAttachmentMemoryUsed = TRUE; + } + else + { + llinfos << "attachment details don't contain memory summary info" << llendl; + return; + } + + if(content["summary"]["used"][0]["type"].asString() == std::string("urls")) + { + mAttachmentURLsUsed = content["summary"]["used"][0]["amount"].asInteger(); + mAttachmentURLsMax = content["summary"]["available"][0]["amount"].asInteger(); + mGotAttachmentURLsUsed = TRUE; + } + else if(content["summary"]["used"][1]["type"].asString() == std::string("urls")) + { + mAttachmentURLsUsed = content["summary"]["used"][1]["amount"].asInteger(); + mAttachmentURLsMax = content["summary"]["available"][1]["amount"].asInteger(); + mGotAttachmentURLsUsed = TRUE; + } + else + { + llinfos << "attachment details don't contain urls summary info" << llendl; + return; + } + + if((mAttachmentMemoryUsed >= 0) && (mAttachmentMemoryMax >= 0)) + { + S32 attachment_memory_available = mAttachmentMemoryMax - mAttachmentMemoryUsed; + + LLStringUtil::format_map_t args_attachment_memory; + args_attachment_memory["[COUNT]"] = llformat ("%d", mAttachmentMemoryUsed); + args_attachment_memory["[MAX]"] = llformat ("%d", mAttachmentMemoryMax); + args_attachment_memory["[AVAILABLE]"] = llformat ("%d", attachment_memory_available); + std::string msg_attachment_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_attachment_memory); + childSetValue("memory_used", LLSD(msg_attachment_memory)); + } + + if((mAttachmentURLsUsed >= 0) && (mAttachmentURLsMax >= 0)) + { + S32 attachment_urls_available = mAttachmentURLsMax - mAttachmentURLsUsed; + + LLStringUtil::format_map_t args_attachment_urls; + args_attachment_urls["[COUNT]"] = llformat ("%d", mAttachmentURLsUsed); + args_attachment_urls["[MAX]"] = llformat ("%d", mAttachmentURLsMax); + args_attachment_urls["[AVAILABLE]"] = llformat ("%d", attachment_urls_available); + std::string msg_attachment_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_attachment_urls); + childSetValue("urls_used", LLSD(msg_attachment_urls)); + } +} + // static void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata) { diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index e675d14515..4c1ecc1019 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -166,10 +166,10 @@ public: BOOL StartRequestChain(); - void populateParcelMemoryText(); BOOL getLandScriptResources(); void clearList(); void showBeacon(); + void returnObjectsFromParcel(S32 local_id); void returnObjects(); private: @@ -178,69 +178,30 @@ private: const std::string& first_name, const std::string& last_name); + LLSD mContent; LLUUID mParcelId; BOOL mGotParcelMemoryUsed; + BOOL mGotParcelMemoryUsedDetails; BOOL mGotParcelMemoryMax; S32 mParcelMemoryMax; S32 mParcelMemoryUsed; + S32 mParcelMemoryUsedDetails; - std::vector<LLSD> mObjectListItems; - -protected: - -// LLRemoteParcelInfoObserver interface: -/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); -/*virtual*/ void setParcelID(const LLUUID& parcel_id); -/*virtual*/ void setErrorStatus(U32 status, const std::string& reason); - - static void onClickRefresh(void* userdata); - static void onClickHighlight(void* userdata); - static void onClickReturn(void* userdata); -}; - -///////////////////////////////////////////////////////////////////////////// -// URLs panel -///////////////////////////////////////////////////////////////////////////// - -class LLPanelScriptLimitsRegionURLs : public LLPanelScriptLimitsInfo -{ - -public: - LLPanelScriptLimitsRegionURLs() - : LLPanelScriptLimitsInfo(), - - mParcelId(LLUUID()), - mGotParcelURLsUsed(FALSE), - mGotParcelURLsMax(FALSE), - mParcelURLsMax(0), - mParcelURLsUsed(0) - { - }; - - ~LLPanelScriptLimitsRegionURLs() - { - }; - - // LLPanel - virtual BOOL postBuild(); - - void setRegionDetails(LLSD content); - void setRegionSummary(LLSD content); - - void populateParcelURLsText(); - void clearList(); - -private: - - LLUUID mParcelId; BOOL mGotParcelURLsUsed; + BOOL mGotParcelURLsUsedDetails; BOOL mGotParcelURLsMax; S32 mParcelURLsMax; S32 mParcelURLsUsed; + S32 mParcelURLsUsedDetails; std::vector<LLSD> mObjectListItems; protected: + +// LLRemoteParcelInfoObserver interface: +/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); +/*virtual*/ void setParcelID(const LLUUID& parcel_id); +/*virtual*/ void setErrorStatus(U32 status, const std::string& reason); static void onClickRefresh(void* userdata); static void onClickHighlight(void* userdata); @@ -266,11 +227,26 @@ public: void setAttachmentDetails(LLSD content); + void setAttachmentSummary(LLSD content); BOOL requestAttachmentDetails(); void clearList(); private: + BOOL mGotAttachmentMemoryUsed; + BOOL mGotAttachmentMemoryUsedDetails; + BOOL mGotAttachmentMemoryMax; + S32 mAttachmentMemoryMax; + S32 mAttachmentMemoryUsed; + S32 mAttachmentMemoryUsedDetails; + + BOOL mGotAttachmentURLsUsed; + BOOL mGotAttachmentURLsUsedDetails; + BOOL mGotAttachmentURLsMax; + S32 mAttachmentURLsMax; + S32 mAttachmentURLsUsed; + S32 mAttachmentURLsUsedDetails; + protected: static void onClickRefresh(void* userdata); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 87d101b00f..af9e791223 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -689,6 +689,23 @@ void LLPanelLogin::refreshLocation( bool force_visible ) } // static +void LLPanelLogin::updateLocationUI() +{ + if (!sInstance) return; + + std::string sim_string = LLURLSimString::sInstance.mSimString; + if (!sim_string.empty()) + { + // Replace "<Type region name>" with this region name + LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo"); + combo->remove(2); + combo->add( sim_string ); + combo->setTextEntry(sim_string); + combo->setCurrentByIndex( 2 ); + } +} + +// static void LLPanelLogin::closePanel() { if (sInstance) diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 97350ce5c7..1fdc3a9361 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -71,6 +71,7 @@ public: static void addServer(const std::string& server, S32 domain_name); static void refreshLocation( bool force_visible ); + static void updateLocationUI(); static void getFields(std::string *firstname, std::string *lastname, std::string *password); @@ -102,7 +103,7 @@ private: static void onPassKey(LLLineEditor* caller, void* user_data); static void onSelectServer(LLUICtrl*, void*); static void onServerComboLostFocus(LLFocusableElement*); - + private: LLPointer<LLUIImage> mLogoImage; boost::scoped_ptr<LLPanelLoginListener> mListener; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index fccf71f3cb..7bcbe334ff 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1904,7 +1904,7 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, const LLUUID& item_id, BOOL is_running) { - llinfos << "Update Task Inventory via capability" << llendl; + llinfos << "Update Task Inventory via capability " << url << llendl; LLSD body; body["task_id"] = task_id; body["item_id"] = item_id; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9240833632..b0952dd698 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -870,8 +870,7 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f //////////////////////////////////////////////////////////////////////////////// // Don't highlight if it's in certain "quiet" folders which don't need UI // notification (e.g. trash, cof, lost-and-found). - const BOOL user_is_away = gAwayTimer.getStarted(); - if(!user_is_away) + if(!gAgent.getAFK()) { const LLViewerInventoryCategory *parent = gInventory.getFirstNondefaultParent(item_id); if (parent) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index cd6b9e2c50..fdc6675db1 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -51,6 +51,7 @@ #include "llviewquery.h" #include "llxmltree.h" +#include "llslurl.h" //#include "llviewercamera.h" #include "llrender.h" @@ -80,6 +81,9 @@ #include "timing.h" #include "llviewermenu.h" #include "lltooltip.h" +#include "llmediaentry.h" +#include "llurldispatcher.h" +#include "llurlsimstring.h" // newview includes #include "llagent.h" @@ -795,6 +799,137 @@ BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MAS // Always handled as far as the OS is concerned. return TRUE; } + +LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data) +{ + LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE; + + const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop"); + const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop"); + + if ( prim_media_dnd_enabled || slurl_dnd_enabled ) + { + switch(action) + { + // Much of the handling for these two cases is the same. + case LLWindowCallbacks::DNDA_TRACK: + case LLWindowCallbacks::DNDA_DROPPED: + case LLWindowCallbacks::DNDA_START_TRACKING: + { + bool drop = (LLWindowCallbacks::DNDA_DROPPED == action); + + if (slurl_dnd_enabled) + { + // special case SLURLs + if ( LLSLURL::isSLURL( data ) ) + { + if (drop) + { + LLURLDispatcher::dispatch( data, NULL, true ); + LLURLSimString::setStringRaw( LLSLURL::stripProtocol( data ) ); + LLPanelLogin::refreshLocation( true ); + LLPanelLogin::updateLocationUI(); + } + return LLWindowCallbacks::DND_MOVE; + }; + } + + if (prim_media_dnd_enabled) + { + LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, TRUE /*BOOL pick_transparent*/ ); + + LLUUID object_id = pick_info.getObjectID(); + S32 object_face = pick_info.mObjectFace; + std::string url = data; + + lldebugs << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl; + + LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject())); + + if (obj && obj->permModify() && !obj->getRegion()->getCapability("ObjectMedia").empty()) + { + LLTextureEntry *te = obj->getTE(object_face); + if (te) + { + if (drop) + { + if (! te->hasMedia()) + { + // Create new media entry + LLSD media_data; + // XXX Should we really do Home URL too? + media_data[LLMediaEntry::HOME_URL_KEY] = url; + media_data[LLMediaEntry::CURRENT_URL_KEY] = url; + media_data[LLMediaEntry::AUTO_PLAY_KEY] = true; + obj->syncMediaData(object_face, media_data, true, true); + // XXX This shouldn't be necessary, should it ?!? + if (obj->getMediaImpl(object_face)) + obj->getMediaImpl(object_face)->navigateReload(); + obj->sendMediaDataUpdate(); + + result = LLWindowCallbacks::DND_COPY; + } + else { + // Check the whitelist + if (te->getMediaData()->checkCandidateUrl(url)) + { + // just navigate to the URL + if (obj->getMediaImpl(object_face)) + { + obj->getMediaImpl(object_face)->navigateTo(url); + } + else { + // This is very strange. Navigation should + // happen via the Impl, but we don't have one. + // This sends it to the server, which /should/ + // trigger us getting it. Hopefully. + LLSD media_data; + media_data[LLMediaEntry::CURRENT_URL_KEY] = url; + obj->syncMediaData(object_face, media_data, true, true); + obj->sendMediaDataUpdate(); + } + result = LLWindowCallbacks::DND_LINK; + } + } + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = NULL; + + } + else { + // Check the whitelist, if there's media (otherwise just show it) + if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) + { + if ( obj != mDragHoveredObject) + { + // Highlight the dragged object + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = obj; + LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject); + } + result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK; + } + } + } + } + } + } + break; + + case LLWindowCallbacks::DNDA_STOP_TRACKING: + // The cleanup case below will make sure things are unhilighted if necessary. + break; + } + + if (prim_media_dnd_enabled && + result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull()) + { + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = NULL; + } + } + + return result; +} BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) { diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index c0a9180b53..98d2958d9a 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -166,7 +166,8 @@ public: /*virtual*/ BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ LLWindowCallbacks::DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data); + void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ void handleMouseLeave(LLWindow *window); /*virtual*/ void handleResize(LLWindow *window, S32 x, S32 y); /*virtual*/ void handleFocus(LLWindow *window); @@ -472,6 +473,10 @@ protected: static std::string sSnapshotDir; static std::string sMovieBaseName; + +private: + // Object temporarily hovered over while dragging + LLPointer<LLViewerObject> mDragHoveredObject; }; void toggle_flying(void*); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index c062dd1732..3914064d72 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1258,7 +1258,6 @@ LLVoiceClient::LLVoiceClient() : mEarLocation(0), mSpeakerVolumeDirty(true), mSpeakerMuteDirty(true), - mSpeakerVolume(0), mMicVolume(0), mMicVolumeDirty(true), @@ -1271,6 +1270,8 @@ LLVoiceClient::LLVoiceClient() : mAPIVersion = LLTrans::getString("NotConnected"); + mSpeakerVolume = scale_speaker_volume(0); + #if LL_DARWIN || LL_LINUX || LL_SOLARIS // HACK: THIS DOES NOT BELONG HERE // When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us. @@ -3525,7 +3526,7 @@ void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream) if(mSpeakerMuteDirty) { - const char *muteval = ((mSpeakerVolume == 0)?"true":"false"); + const char *muteval = ((mSpeakerVolume <= scale_speaker_volume(0))?"true":"false"); mSpeakerMuteDirty = false; @@ -6062,7 +6063,8 @@ void LLVoiceClient::setVoiceVolume(F32 volume) if(scaled_volume != mSpeakerVolume) { - if((scaled_volume == 0) || (mSpeakerVolume == 0)) + int min_volume = scale_speaker_volume(0); + if((scaled_volume == min_volume) || (mSpeakerVolume == min_volume)) { mSpeakerMuteDirty = true; } diff --git a/indra/newview/skins/default/xui/en/floater_script_limits.xml b/indra/newview/skins/default/xui/en/floater_script_limits.xml index 98c44ad1b3..6b36cdfcc5 100644 --- a/indra/newview/skins/default/xui/en/floater_script_limits.xml +++ b/indra/newview/skins/default/xui/en/floater_script_limits.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" + can_resize="true" height="570" help_topic="scriptlimits" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml index d98f690339..629d8567d1 100644 --- a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml +++ b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml @@ -9,7 +9,44 @@ name="script_limits_my_avatar_panel" top="0" width="480"> - <text + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="script_memory" + top_pad="24" + text_color="White" + width="480"> + Avatar Script Usage + </text> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="30" + name="memory_used" + top_delta="18" + width="480"> + + </text> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="30" + name="urls_used" + top_delta="18" + width="480"> + + </text> + <text type="string" length="1" follows="left|top" @@ -17,7 +54,7 @@ layout="topleft" left="10" name="loading_text" - top="10" + top="80" text_color="EmphasisColor" width="480"> Loading... @@ -25,12 +62,12 @@ <scroll_list draw_heading="true" follows="all" - height="500" + height="415" layout="topleft" left_delta="0" multi_select="true" name="scripts_list" - top_delta="17" + top="100" width="460"> <scroll_list.columns label="Size (kb)" diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml index 0fa3c1cf2e..9dff00fa0b 100644 --- a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml +++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml @@ -33,7 +33,7 @@ top_delta="18" visible="true" width="480"> - Parcels Owned: + </text> <text type="string" @@ -45,7 +45,19 @@ name="memory_used" top_delta="18" width="480"> - Memory used: + </text> + + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="30" + name="urls_used" + top_delta="18" + width="480"> + </text> <text type="string" @@ -55,7 +67,7 @@ layout="topleft" left="10" name="loading_text" - top_delta="32" + top_delta="12" text_color="EmphasisColor" width="480"> Loading... @@ -73,7 +85,11 @@ <scroll_list.columns label="Size (kb)" name="size" - width="70" /> + width="72" /> + <scroll_list.columns + label="URLs" + name="urls" + width="48" /> <scroll_list.columns label="Object Name" name="name" @@ -83,11 +99,13 @@ name="owner" width="100" /> <scroll_list.columns - label="Parcel / Location" - name="location" + label="Parcel" + name="parcel" width="130" /> -<!-- <scroll_list.commit_callback - function="TopObjects.CommitObjectsList" />--> + <scroll_list.columns + label="Location" + name="location" + width="80" /> </scroll_list> <button follows="bottom|left" @@ -102,8 +120,8 @@ <button follows="bottom|right" height="19" - visible="false" label="Highlight" + visible="false" layout="bottomright" left="370" name="highlight_btn" @@ -112,8 +130,8 @@ <button follows="bottom|right" height="19" - visible="false" label="Return" + visible="false" layout="bottomright" name="return_btn" top="34" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b378944e48..b4a12cfb32 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2051,6 +2051,7 @@ this texture in your inventory <string name="ScriptLimitsURLsUsed">URLs used: [COUNT] out of [MAX]; [AVAILABLE] available</string> <string name="ScriptLimitsURLsUsedSimple">URLs used: [COUNT]</string> <string name="ScriptLimitsRequestError">Error requesting information</string> + <string name="ScriptLimitsRequestNoParcelSelected">No Parcel Selected</string> <string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string> <string name="ScriptLimitsRequestWaiting">Retrieving information...</string> <string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string> |