diff options
72 files changed, 1768 insertions, 336 deletions
| diff --git a/BuildParams b/BuildParams index 9752e5298d..31e7e841ad 100755 --- a/BuildParams +++ b/BuildParams @@ -27,9 +27,6 @@ Linux.distcc_version =  Linux.gcc_version = /usr/bin/gcc-4.6  Linux.cxx_version = /usr/bin/g++-4.6 -# Setup default sourceid so Windows can pick up the TeamCity override -sourceid = "" -  ################################################################  ####      Examples of how to set the viewer_channel         ####  # @@ -50,6 +47,18 @@ sourceid = ""  ################################################################  viewer_channel = "Second Life Test" +# Setup default packaging parameters. +sourceid = "" +additional_packages = "Amazon Desura B C" +Amazon_sourceid = "1207v_Amazon" +Amazon_viewer_channel_suffix = " Amazon" +Desura_sourceid = "1208_desura" +Desura_viewer_channel_suffix = " Desura" +B_sourceid = "1301_B" +B_viewer_channel_suffix = " B" +C_sourceid = "1302_C" +C_viewer_channel_suffix = " C" +  # Report changes since...  viewer-development.show_changes_since = last_sprint diff --git a/autobuild.xml b/autobuild.xml index b1478a46b2..8194b3d4eb 100755 --- a/autobuild.xml +++ b/autobuild.xml @@ -1965,11 +1965,11 @@      <key>package_description</key>      <map>        <key>description</key> -      <string>Spell checking dictionaries</string> +      <string>Second Life Viewer</string>        <key>license</key> -      <string>various open</string> +      <string>LGPL</string>        <key>name</key> -      <string>dictionaries</string> +      <string>Second Life Viewer</string>        <key>platforms</key>        <map>          <key>common</key> @@ -38,22 +38,22 @@ build_dir_CYGWIN()  installer_Darwin()  { -  ls -1td "$(build_dir_Darwin ${last_built_variant:-Release})/newview/"*.dmg 2>/dev/null | sed 1q +  ls -1tr "$(build_dir_Darwin ${last_built_variant:-Release})/newview/"*"$additional_package_name"*.dmg 2>/dev/null | sed 1q  }  installer_Linux()  { -  ls -1td "$(build_dir_Linux ${last_built_variant:-Release})/newview/"*.tar.bz2 2>/dev/null | sed 1q +  ls -1tr "$(build_dir_Linux ${last_built_variant:-Release})/newview/"*"$additional_package_name"*.tar.bz2 2>/dev/null | grep -v symbols | sed 1q  }  installer_CYGWIN()  {    v=${last_built_variant:-Release}    d=$(build_dir_CYGWIN $v) -  if [ -r "$d/newview/$v/touched.bat" ] +  if [ -r "$d/newview/$additional_package_name$v/touched.bat" ]    then -    p=$(sed 's:.*=::' "$d/newview/$v/touched.bat") -    echo "$d/newview/$v/$p" +    p=$(sed 's:.*=::' "$d/newview/$additional_package_name$v/touched.bat") +    echo "$d/newview/$additional_package_name$v/$p"    fi  } @@ -355,10 +355,28 @@ then        # Coverity doesn't package, so it's ok, anything else is fail        succeeded=$build_coverity      else +      # Upload base package.        upload_item installer "$package" binary/octet-stream        upload_item quicklink "$package" binary/octet-stream        [ -f $build_dir/summary.json ] && upload_item installer $build_dir/summary.json text/plain +      # Upload additional packages. +      for package_id in $additional_packages +      do +        case $arch in +        CYGWIN) export additional_package_name="$package_id/" ;; +        *) export additional_package_name=$package_id ;; +        esac +        package=$(installer_$arch) +        if [ x"$package" != x ] +        then +          upload_item installer "$package" binary/octet-stream +        else +          record_failure "Failed to upload $package_id package." +        fi +      done +      export additional_package_name="" +        case "$last_built_variant" in        Release)          # Upload crash reporter files diff --git a/doc/contributions.txt b/doc/contributions.txt index 931211f622..198ebe145e 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -175,8 +175,11 @@ Ansariel Hiller  	STORM-1685  	STORM-1713  	STORM-1899 +	STORM-1932 +	STORM-1933  	MAINT-2368  	STORM-1931 +	MAINT-2773  Aralara Rajal  Arare Chantilly  	CHUIBUG-191 @@ -304,9 +307,13 @@ Christopher  Organiser  Ciaran Laval  Cinder Roxley      BUG-2326 +    OPEN-185      STORM-1703  	STORM-1948 +    STORM-1888 +    STORM-1958      STORM-1952 +    STORM-1951  Clara Young  Coaldust Numbers      VWR-1095 @@ -652,7 +659,7 @@ Jonathan Yap  	STORM-1809  	STORM-1793  	STORM-1810 -	STORM-1877 +	STORM-1838  	STORM-1892  	STORM-1894  	STORM-1860 @@ -662,8 +669,11 @@ Jonathan Yap  	STORM-1858  	STORM-1862  	STORM-1918 +	STORM-1929  	STORM-1953  	OPEN-161 +	STORM-1953 +	STORM-1957  Kadah Coba  	STORM-1060      STORM-1843 @@ -679,6 +689,7 @@ Kagehi Kohn  Kaimen Takahe  Katharine Berry  	STORM-1900 +    OPEN-149  	STORM-1940  	STORM-1941  Keklily Longfall @@ -928,6 +939,7 @@ Nicky Dasmijn  	STORM-1936  	BUG-3605  	CHUIBUG-197 +	OPEN-187  	STORM-1937  Nicky Perian  	OPEN-1 @@ -1125,6 +1137,7 @@ Slee Mayo  snowy Sidran  Sovereign Engineer      MAINT-2334 +    OPEN-189  SpacedOut Frye  	VWR-34  	VWR-45 @@ -1293,6 +1306,7 @@ Westley Streeter  Whimsy Winx  Whirly Fizzle  	STORM-1895 +	VWR-29543  	MAINT-873  	STORM-1930  Whoops Babii @@ -1356,6 +1370,7 @@ YongYong Francois  Zak Westminster  Zai Lynch  	VWR-19505 +    STORM-1902  Zana Kohime  Zaren Alexander  Zarkonnen Decosta diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake index af2063ce6d..e4b63dc7cb 100755 --- a/indra/cmake/BuildVersion.cmake +++ b/indra/cmake/BuildVersion.cmake @@ -16,22 +16,26 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n          else (DEFINED ENV{revision})             find_program(MERCURIAL hg) -           if (DEFINED MERCURIAL) +           find_program(WORDCOUNT wc) +           find_program(SED sed) +           if (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED)                execute_process( -                 COMMAND ${MERCURIAL} log -r tip --template "{rev}" +                 COMMAND ${MERCURIAL} log -r tip:0 --template '\\n' +                 COMMAND ${WORDCOUNT} -l +                 COMMAND ${SED} "s/ //g"                   OUTPUT_VARIABLE VIEWER_VERSION_REVISION                   OUTPUT_STRIP_TRAILING_WHITESPACE                   )                if ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")                   message("Revision (from hg) ${VIEWER_VERSION_REVISION}")                else ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$") +                 message("Revision not set (repository not found?); using 0")                   set(VIEWER_VERSION_REVISION 0 ) -                 message("Revision not set, repository not found, using ${VIEWER_VERSION_REVISION}")                endif ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$") -           else (DEFINED MERCURIAL) +           else (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED) +              message("Revision not set: 'hg', 'wc' or 'sed' not found; using 0")                set(VIEWER_VERSION_REVISION 0) -              message("Revision not set, 'hg' not found (${MERCURIAL}), using ${VIEWER_VERSION_REVISION}") -           endif (DEFINED MERCURIAL) +           endif (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED)          endif (DEFINED ENV{revision})          message("Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")      else ( EXISTS ${VIEWER_VERSION_BASE_FILE} ) diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 54049b5545..52b4acbc94 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -224,15 +224,98 @@ def main():      for opt in args:          print "Option:", opt, "=", args[opt] +    # pass in sourceid as an argument now instead of an environment variable +    try: +        args['sourceid'] = os.environ["sourceid"] +    except KeyError: +        args['sourceid'] = "" + +    # Build base package. +    touch = args.get('touch') +    if touch: +        print 'Creating base package' +    args['package_id'] = "" # base package has no package ID      wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)      wm.do(*args['actions']) - +    # Store package file for later if making touched file. +    base_package_file = "" +    if touch: +        print 'Created base package ', wm.package_file +        base_package_file = "" + wm.package_file + +    # handle multiple packages if set +    try: +        additional_packages = os.environ["additional_packages"] +    except KeyError: +        additional_packages = "" +    if additional_packages: +        # Determine destination prefix / suffix for additional packages. +        base_dest_postfix = args['dest'] +        base_dest_prefix = "" +        base_dest_parts = args['dest'].split(os.sep) +        if len(base_dest_parts) > 1: +            base_dest_postfix = base_dest_parts[len(base_dest_parts) - 1] +            base_dest_prefix = base_dest_parts[0] +            i = 1 +            while i < len(base_dest_parts) - 1: +                base_dest_prefix = base_dest_prefix + os.sep + base_dest_parts[i] +                i = i + 1 +        # Determine touched prefix / suffix for additional packages. +        base_touch_postfix = "" +        base_touch_prefix = "" +        if touch: +            base_touch_postfix = touch +            base_touch_parts = touch.split('/') +            if "arwin" in args['platform']: +                if len(base_touch_parts) > 1: +                    base_touch_postfix = base_touch_parts[len(base_touch_parts) - 1] +                    base_touch_prefix = base_touch_parts[0] +                    i = 1 +                    while i < len(base_touch_parts) - 1: +                        base_touch_prefix = base_touch_prefix + '/' + base_touch_parts[i] +                        i = i + 1 +            else: +                if len(base_touch_parts) > 2: +                    base_touch_postfix = base_touch_parts[len(base_touch_parts) - 2] + '/' + base_touch_parts[len(base_touch_parts) - 1] +                    base_touch_prefix = base_touch_parts[0] +                    i = 1 +                    while i < len(base_touch_parts) - 2: +                        base_touch_prefix = base_touch_prefix + '/' + base_touch_parts[i] +                        i = i + 1 +        # Store base channel name. +        base_channel_name = args['channel'] +        # Build each additional package. +        package_id_list = additional_packages.split(" ") +        for package_id in package_id_list: +            try: +                args['package_id'] = package_id +                args['channel'] = base_channel_name + os.environ[package_id + "_viewer_channel_suffix"] +                if package_id + "_sourceid" in os.environ: +                    args['sourceid'] = os.environ[package_id + "_sourceid"] +                else: +                    args['sourceid'] = "" +                args['dest'] = base_dest_prefix + os.sep + package_id + os.sep + base_dest_postfix +            except KeyError: +                sys.stderr.write("Failed to create package for package_id: %s" % package_id) +                sys.stderr.flush() +                continue +            if touch: +                print 'Creating additional package for ', package_id, ' in ', args['dest'] +            wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args) +            wm.do(*args['actions']) +            if touch: +                print 'Created additional package ', wm.package_file, ' for ', package_id +                faketouch = base_touch_prefix + '/' + package_id + '/' + base_touch_postfix +                fp = open(faketouch, 'w') +                fp.write('set package_file=%s\n' % wm.package_file) +                fp.close() +          # Write out the package file in this format, so that it can easily be called      # and used in a .bat file - yeah, it sucks, but this is the simplest...      touch = args.get('touch')      if touch:          fp = open(touch, 'w') -        fp.write('set package_file=%s\n' % wm.package_file) +        fp.write('set package_file=%s\n' % base_package_file)          fp.close()          print 'touched', touch      return 0 diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h deleted file mode 100644 index 6a5ff314e4..0000000000 --- a/indra/llcommon/llversionviewer.h +++ /dev/null @@ -1,41 +0,0 @@ -/**  - * @file llversionviewer.h - * @brief - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLVERSIONVIEWER_H -#define LL_LLVERSIONVIEWER_H - -const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 4; -const S32 LL_VERSION_PATCH = 6; -const S32 LL_VERSION_BUILD = 0; - -const char * const LL_CHANNEL = "Second Life Developer"; - -#if LL_DARWIN -const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer"; -#endif - -#endif diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index b047f86e6e..8c8c315808 100755 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -50,7 +50,7 @@ class LLColor4  		LLColor4(F32 r, F32 g, F32 b);		// Initializes LLColor4 to (r, g, b, 1)  		LLColor4(F32 r, F32 g, F32 b, F32 a);		// Initializes LLColor4 to (r. g, b, a)  		LLColor4(U32 clr);							// Initializes LLColor4 to (r=clr>>24, etc)) -		LLColor4(const F32 *vec);			// Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1) +		LLColor4(const F32 *vec);			// Initializes LLColor4 to (vec[0]. vec[1], vec[2], vec[3])  		LLColor4(const LLColor3 &vec, F32 a = 1.f);	// Initializes LLColor4 to (vec, a)  		explicit LLColor4(const LLSD& sd);  		explicit LLColor4(const LLColor4U& color4u);  // "explicit" to avoid automatic conversion diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index db4a38ea9e..f7118f8ccf 100755 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -126,7 +126,7 @@ enum EInstantMessage  	IM_LURE_ACCEPTED = 23,  	IM_LURE_DECLINED = 24,  	IM_GODLIKE_LURE_USER = 25, -	IM_YET_TO_BE_USED = 26, +	IM_TELEPORT_REQUEST = 26,  	// IM that notifie of a new group election.  	// Name is name of person who called vote. diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 34a08603fa..589ceac501 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -75,6 +75,7 @@ set(llui_SOURCE_FILES      llmultislider.cpp      llmultisliderctrl.cpp      llnotifications.cpp +    llnotificationslistener.cpp      llnotificationsutil.cpp      llpanel.cpp      llprogressbar.cpp @@ -128,6 +129,7 @@ set(llui_SOURCE_FILES      llviewmodel.cpp      llview.cpp      llviewquery.cpp +    llviewereventrecorder.cpp      llwindowshade.cpp      llxuiparser.cpp      ) @@ -183,6 +185,7 @@ set(llui_HEADER_FILES      llmultislider.h      llnotificationptr.h      llnotifications.h +    llnotificationslistener.h      llnotificationsutil.h      llnotificationtemplate.h      llnotificationvisibilityrule.h @@ -240,6 +243,7 @@ set(llui_HEADER_FILES      llviewinject.h      llviewmodel.h      llview.h +    llviewereventrecorder.h      llviewquery.h      llwindowshade.h      llxuiparser.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 44f2c1efe9..50ac511d18 100755 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -49,6 +49,7 @@  #include "lluictrlfactory.h"  #include "llhelp.h"  #include "lldockablefloater.h" +#include "llviewereventrecorder.h"  static LLDefaultChildRegistry::Register<LLButton> r("button"); @@ -443,6 +444,8 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)  		 */  		LLUICtrl::handleMouseDown(x, y, mask); +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); +  		if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD());  		mMouseDownTimer.start(); @@ -473,6 +476,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)  		 * by calling LLUICtrl::mMouseUpSignal(x, y, mask);  		 */  		LLUICtrl::handleMouseUp(x, y, mask); +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());   		// Regardless of where mouseup occurs, handle callback  		if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 273ceb4038..d44b1ad51a 100755 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -29,7 +29,7 @@  // mini-map floater, etc.  #include "linden_common.h" - +#include "llviewereventrecorder.h"  #include "llfloater.h"  #include "llfocusmgr.h" @@ -642,7 +642,10 @@ void LLFloater::handleVisibilityChange ( BOOL new_visibility )  void LLFloater::openFloater(const LLSD& key)  { -	llinfos << "Opening floater " << getName() << llendl; +    llinfos << "Opening floater " << getName() << " full path: " << getPathname() << llendl; + +	LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), true,"floater"); // Last param is event subtype or empty string +  	mKey = key; // in case we need to open ourselves again  	if (getSoundFlags() != SILENT  @@ -696,6 +699,7 @@ void LLFloater::openFloater(const LLSD& key)  void LLFloater::closeFloater(bool app_quitting)  {  	llinfos << "Closing floater " << getName() << llendl; +	LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), false,"floater"); // Last param is event subtype or empty string  	if (app_quitting)  	{  		LLFloater::sQuitting = true; @@ -1543,6 +1547,17 @@ BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks)  }  // virtual +BOOL LLFloater::handleMouseUp(S32 x, S32 y, MASK mask) +{ +	lldebugs << "LLFloater::handleMouseUp calling LLPanel (really LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; +	BOOL handled = LLPanel::handleMouseUp(x,y,mask); // Not implemented in LLPanel so this actually calls LLView +	if (handled) { +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); +	} +	return handled; +} + +// virtual  BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)  {  	if( mMinimized ) @@ -1562,7 +1577,11 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)  	else  	{  		bringToFront( x, y ); -		return LLPanel::handleMouseDown( x, y, mask ); +		BOOL handled = LLPanel::handleMouseDown( x, y, mask );  +		if (handled) { +			LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());  +		} +		return handled;  	}  } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 59448530d9..953689498f 100755 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -289,6 +289,7 @@ public:  	S32				getHeaderHeight() const { return mHeaderHeight; }  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);  	virtual BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMiddleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 3186c5460a..5c288c3f03 100755 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1206,6 +1206,7 @@ LLNotifications::LLNotifications()  :	LLNotificationChannelBase(LLNotificationFilters::includeEverything),  	mIgnoreAllNotifications(false)  { +        mListener.reset(new LLNotificationsListener(*this));  	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));  } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 3b620084ee..6ac4a98806 100755 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -98,6 +98,8 @@  #include "llrefcount.h"  #include "llsdparam.h" +#include "llnotificationslistener.h" +  class LLAvatarName;  typedef enum e_notification_priority  { @@ -978,6 +980,8 @@ private:  	bool mIgnoreAllNotifications; +	boost::scoped_ptr<LLNotificationsListener> mListener; +  	std::vector<LLNotificationChannelPtr> mDefaultChannels;  }; diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp new file mode 100644 index 0000000000..9e8e943ee6 --- /dev/null +++ b/indra/llui/llnotificationslistener.cpp @@ -0,0 +1,359 @@ +/** + * @file   llnotificationslistener.cpp + * @author Brad Kittenbrink + * @date   2009-07-08 + * @brief  Implementation for llnotificationslistener. + *  + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llnotificationslistener.h" +#include "llnotifications.h" +#include "llnotificationtemplate.h" +#include "llsd.h" +#include "llui.h" + +LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) : +    LLEventAPI("LLNotifications", +               "LLNotifications listener to (e.g.) pop up a notification"), +    mNotifications(notifications) +{ +    add("requestAdd", +        "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n" +        "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.", +        &LLNotificationsListener::requestAdd); +    /*    add("listChannels", +        "Post to [\"reply\"] a map of info on existing channels", +        &LLNotificationsListener::listChannels, +        LLSD().with("reply", LLSD())); +    */ +    add("listChannelNotifications", +        "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]", +        &LLNotificationsListener::listChannelNotifications, +        LLSD().with("reply", LLSD()).with("channel", LLSD())); +    add("respond", +        "Respond to notification [\"uuid\"] with data in [\"response\"]", +        &LLNotificationsListener::respond, +        LLSD().with("uuid", LLSD())); +    add("cancel", +        "Cancel notification [\"uuid\"]", +        &LLNotificationsListener::cancel, +        LLSD().with("uuid", LLSD())); +    add("ignore", +        "Ignore future notification [\"name\"]\n" +        "(from <notification name= > in notifications.xml)\n" +        "according to boolean [\"ignore\"].\n" +        "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n" +        "Note that ignored notifications are not forwarded unless intercepted before\n" +        "the \"Ignore\" channel.", +        &LLNotificationsListener::ignore); +    add("forward", +        "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n" +        "according to boolean [\"forward\"]. When enabled, only types matching\n" +        "[\"types\"] are forwarded, as follows:\n" +        "omitted or undefined: forward all notifications\n" +        "string: forward only the specific named [sig]type\n" +        "array of string: forward any notification matching any named [sig]type.\n" +        "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n" +        "notification.", +        &LLNotificationsListener::forward, +        LLSD().with("channel", LLSD())); +} + +// This is here in the .cpp file so we don't need the definition of class +// Forwarder in the header file. +LLNotificationsListener::~LLNotificationsListener() +{ +} + +void LLNotificationsListener::requestAdd(const LLSD& event_data) const +{ +	if(event_data.has("reply")) +	{ +		mNotifications.add(event_data["name"],  +						   event_data["substitutions"],  +						   event_data["payload"], +						   boost::bind(&LLNotificationsListener::NotificationResponder,  +									   this,  +									   event_data["reply"].asString(),  +									   _1, _2 +									   ) +						   ); +	} +	else +	{ +		mNotifications.add(event_data["name"],  +						   event_data["substitutions"],  +						   event_data["payload"]); +	} +} + +void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,  +										const LLSD& notification,  +										const LLSD& response) const +{ +	LLSD reponse_event; +	reponse_event["notification"] = notification; +	reponse_event["response"] = response; +	LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); +} +/* +void LLNotificationsListener::listChannels(const LLSD& params) const +{ +    LLReqID reqID(params); +    LLSD response(reqID.makeResponse()); +    for (LLNotifications:: + + + +    for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), +                                                     cmend(mNotifications.mChannels.end()); +         cmi != cmend; ++cmi) +    { +        LLSD channelInfo; +        channelInfo["parent"] = cmi->second->getParentChannelName(); +        response[cmi->first] = channelInfo; +    } +    LLEventPumps::instance().obtain(params["reply"]).post(response); +} +*/ +void LLNotificationsListener::listChannelNotifications(const LLSD& params) const +{ +    LLReqID reqID(params); +    LLSD response(reqID.makeResponse()); +    LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"])); +    if (channel) +    { +        LLSD notifications(LLSD::emptyArray()); +        for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end()); +             ni != nend; ++ni) +        { +            notifications.append(asLLSD(*ni)); +        } +        response["notifications"] = notifications; +    } +    LLEventPumps::instance().obtain(params["reply"]).post(response); +} + +void LLNotificationsListener::respond(const LLSD& params) const +{ +    LLNotificationPtr notification(mNotifications.find(params["uuid"])); +    if (notification) +    { +        notification->respond(params["response"]); +    } +} + +void LLNotificationsListener::cancel(const LLSD& params) const +{ +    LLNotificationPtr notification(mNotifications.find(params["uuid"])); +    if (notification) +    { +        mNotifications.cancel(notification); +    } +} + +void LLNotificationsListener::ignore(const LLSD& params) const +{ +    // Calling a method named "ignore", but omitting its "ignore" Boolean +    // argument, should by default cause something to be ignored. Explicitly +    // pass ["ignore"] = false to cancel ignore. +    bool ignore = true; +    if (params.has("ignore")) +    { +        ignore = params["ignore"].asBoolean(); +    } +    // This method can be used to affect either a single notification name or +    // all future notifications. The two use substantially different mechanisms. +    if (params["name"].isDefined()) +    { +        // ["name"] was passed: ignore just that notification +		LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]); +		if (templatep) +		{ +			templatep->mForm->setIgnored(ignore); +		} +    } +    else +    { +        // no ["name"]: ignore all future notifications +        mNotifications.setIgnoreAllNotifications(ignore); +    } +} + +class LLNotificationsListener::Forwarder: public LLEventTrackable +{ +    LOG_CLASS(LLNotificationsListener::Forwarder); +public: +    Forwarder(LLNotifications& llnotifications, const std::string& channel): +        mNotifications(llnotifications), +        mRespond(false) +    { +        // Connect to the specified channel on construction. Because +        // LLEventTrackable is a base, we should automatically disconnect when +        // destroyed. +        LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel)); +        if (channelptr) +        { +            // Insert our processing as a "passed filter" listener. This way +            // we get to run before all the "changed" listeners, and we get to +            // swipe it (hide it from the other listeners) if desired. +            channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1)); +        } +    } + +    void setPumpName(const std::string& name) { mPumpName = name; } +    void setTypes(const LLSD& types) { mTypes = types; } +    void setRespond(bool respond) { mRespond = respond; } + +private: +    bool handle(const LLSD& notification) const; +    bool matchType(const LLSD& filter, const std::string& type) const; + +    LLNotifications& mNotifications; +    std::string mPumpName; +    LLSD mTypes; +    bool mRespond; +}; + +void LLNotificationsListener::forward(const LLSD& params) +{ +    std::string channel(params["channel"]); +    // First decide whether we're supposed to start forwarding or stop it. +    // Default to true. +    bool forward = true; +    if (params.has("forward")) +    { +        forward = params["forward"].asBoolean(); +    } +    if (! forward) +    { +        // This is a request to stop forwarding notifications on the specified +        // channel. The rest of the params don't matter. +        // Because mForwarders contains scoped_ptrs, erasing the map entry +        // DOES delete the heap Forwarder object. Because Forwarder derives +        // from LLEventTrackable, destroying it disconnects it from the +        // channel. +        mForwarders.erase(channel); +        return; +    } +    // From here on, we know we're being asked to start (or modify) forwarding +    // on the specified channel. Find or create an appropriate Forwarder. +    ForwarderMap::iterator +        entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first); +    if (! entry->second) +    { +        entry->second.reset(new Forwarder(mNotifications, channel)); +    } +    // Now, whether this Forwarder is brand-new or not, update it with the new +    // request info. +    Forwarder& fwd(*entry->second); +    fwd.setPumpName(params["pump"]); +    fwd.setTypes(params["types"]); +    fwd.setRespond(params["respond"]); +} + +bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const +{ +    LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL; +    if (notification["sigtype"].asString() == "delete") +    { +        LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL; +        // let other listeners see the "delete" operation +        return false; +    } +    LLNotificationPtr note(mNotifications.find(notification["id"])); +    if (! note) +    { +        LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL; +        return false; +    } +    if (! matchType(mTypes, note->getType())) +    { +        LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL; +        // We're not supposed to intercept this particular notification. Let +        // other listeners process it. +        return false; +    } +    LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL; +    // This is a notification we care about. Forward it through specified +    // LLEventPump. +    LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note)); +    // Are we also being asked to auto-respond? +    if (mRespond) +    { +        LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL; +        note->respond(LLSD::emptyMap()); +        // Did that succeed in removing the notification? Only cancel() if +        // it's still around -- otherwise we get an LL_ERRS crash! +        note = mNotifications.find(notification["id"]); +        if (note) +        { +            LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL; +            mNotifications.cancel(note); +        } +    } +    // If we've auto-responded to this notification, then it's going to be +    // deleted. Other listeners would get the change operation, try to look it +    // up and be baffled by lookup failure. So when we auto-respond, suppress +    // this notification: don't pass it to other listeners. +    return mRespond; +} + +bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const +{ +    // Decide whether this notification matches filter: +    // undefined: forward all notifications +    if (filter.isUndefined()) +    { +        return true; +    } +    // array of string: forward any notification matching any named type +    if (filter.isArray()) +    { +        for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray()); +             ti != tend; ++ti) +        { +            if (ti->asString() == type) +            { +                return true; +            } +        } +        // Didn't match any entry in the array +        return false; +    } +    // string: forward only the specific named type +    return (filter.asString() == type); +} + +LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note) +{ +    LLSD notificationInfo(note->asLLSD()); +    // For some reason the following aren't included in LLNotification::asLLSD(). +    notificationInfo["summary"] = note->summarize(); +    notificationInfo["id"]      = note->id(); +    notificationInfo["type"]    = note->getType(); +    notificationInfo["message"] = note->getMessage(); +    notificationInfo["label"]   = note->getLabel(); +    return notificationInfo; +} diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h new file mode 100644 index 0000000000..f9f7641de6 --- /dev/null +++ b/indra/llui/llnotificationslistener.h @@ -0,0 +1,69 @@ +/** + * @file   llnotificationslistener.h + * @author Brad Kittenbrink + * @date   2009-07-08 + * @brief  Wrap subset of LLNotifications API in event API for test scripts. + *  + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLNOTIFICATIONSLISTENER_H +#define LL_LLNOTIFICATIONSLISTENER_H + +#include "lleventapi.h" +#include "llnotificationptr.h" +#include <boost/shared_ptr.hpp> +#include <map> +#include <string> + +class LLNotifications; +class LLSD; + +class LLNotificationsListener : public LLEventAPI +{ +public: +    LLNotificationsListener(LLNotifications & notifications); +    ~LLNotificationsListener(); + +private: +    void requestAdd(LLSD const & event_data) const; + +	void NotificationResponder(const std::string& replypump,  +							   const LLSD& notification,  +							   const LLSD& response) const; + +    void listChannels(const LLSD& params) const; +    void listChannelNotifications(const LLSD& params) const; +    void respond(const LLSD& params) const; +    void cancel(const LLSD& params) const; +    void ignore(const LLSD& params) const; +    void forward(const LLSD& params); + +    static LLSD asLLSD(LLNotificationPtr); + +    class Forwarder; +    typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap; +    ForwarderMap mForwarders; +	LLNotifications & mNotifications; +}; + +#endif // LL_LLNOTIFICATIONSLISTENER_H diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index fd98155704..76ba53ec32 100755 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -27,7 +27,7 @@  #include "linden_common.h"  #include "lltabcontainer.h" - +#include "llviewereventrecorder.h"  #include "llfocusmgr.h"  #include "lllocalcliprect.h"  #include "llrect.h" @@ -578,6 +578,11 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )  			tab_button->setFocus(TRUE);  		}  	} +	if (handled) { +		// Note: May need to also capture local coords right here ? +		LLViewerEventRecorder::instance().update_xui(getPathname( )); +	} +  	return handled;  } @@ -629,30 +634,33 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )  	BOOL handled = FALSE;  	BOOL has_scroll_arrows = (getMaxScrollPos() > 0)  && !getTabsHidden(); +	S32 local_x = x - getRect().mLeft; +	S32 local_y = y - getRect().mBottom; +  	if (has_scroll_arrows)  	{  		if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))  		{ -			S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft; -			S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom; +			local_x = x - mJumpPrevArrowBtn->getRect().mLeft; +			local_y = y - mJumpPrevArrowBtn->getRect().mBottom;  			handled = mJumpPrevArrowBtn->handleMouseUp(local_x, local_y, mask);  		}  		else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x,	y))  		{ -			S32	local_x	= x	- mJumpNextArrowBtn->getRect().mLeft; -			S32	local_y	= y	- mJumpNextArrowBtn->getRect().mBottom; +			local_x	= x	- mJumpNextArrowBtn->getRect().mLeft; +			local_y	= y	- mJumpNextArrowBtn->getRect().mBottom;  			handled = mJumpNextArrowBtn->handleMouseUp(local_x,	local_y, mask);  		}  		else if (mPrevArrowBtn && mPrevArrowBtn->getRect().pointInRect(x, y))  		{ -			S32 local_x = x - mPrevArrowBtn->getRect().mLeft; -			S32 local_y = y - mPrevArrowBtn->getRect().mBottom; +			local_x = x - mPrevArrowBtn->getRect().mLeft; +			local_y = y - mPrevArrowBtn->getRect().mBottom;  			handled = mPrevArrowBtn->handleMouseUp(local_x, local_y, mask);  		}  		else if (mNextArrowBtn && mNextArrowBtn->getRect().pointInRect(x, y))  		{ -			S32 local_x = x - mNextArrowBtn->getRect().mLeft; -			S32 local_y = y - mNextArrowBtn->getRect().mBottom; +			local_x = x - mNextArrowBtn->getRect().mLeft; +			local_y = y - mNextArrowBtn->getRect().mBottom;  			handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask);  		}  	} @@ -676,6 +684,10 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )  		}  		gFocusMgr.setMouseCapture(NULL);  	} +	if (handled) { +		// Note: may need to capture local coords here +		LLViewerEventRecorder::instance().update_xui(getPathname( )); +	}  	return handled;  } @@ -1059,21 +1071,21 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)  		if (mIsVertical)  		{ -			p.name(std::string("vert tab button")); -			p.image_unselected(mMiddleTabParams.tab_left_image_unselected); -			p.image_selected(mMiddleTabParams.tab_left_image_selected); -			p.follows.flags = p.follows.flags() | FOLLOWS_TOP; +		  p.name("vtab_"+std::string(child->getName())); +		  p.image_unselected(mMiddleTabParams.tab_left_image_unselected); +		  p.image_selected(mMiddleTabParams.tab_left_image_selected); +		  p.follows.flags = p.follows.flags() | FOLLOWS_TOP;  		}  		else -		{ -			p.name(std::string(child->getName()) + " tab"); -			p.visible(false); -			p.image_unselected(tab_img); -			p.image_selected(tab_selected_img); -			p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM); -			// Try to squeeze in a bit more text -			p.pad_left( mLabelPadLeft ); -			p.pad_right(2); +		  {  +		    p.name("htab_"+std::string(child->getName())); +		    p.visible(false); +		    p.image_unselected(tab_img); +		    p.image_selected(tab_selected_img); +		    p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM); +		    // Try to squeeze in a bit more text +		    p.pad_left( mLabelPadLeft ); +		    p.pad_right(2);  		}  		// *TODO : It seems wrong not to use p in both cases considering the way p is initialized diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index b9c843e931..1722bf27bd 100755 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -29,7 +29,7 @@  #define LLUICTRL_CPP  #include "lluictrl.h" - +#include "llviewereventrecorder.h"  #include "llfocusmgr.h"  #include "llpanel.h"  #include "lluictrlfactory.h" @@ -308,22 +308,40 @@ void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask)  //virtual   BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask)  { + +	lldebugs << "LLUICtrl::handleMouseDown calling	LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; +    	BOOL handled  = LLView::handleMouseDown(x,y,mask); +	  	if (mMouseDownSignal)  	{  		(*mMouseDownSignal)(this,x,y,mask);  	} +	lldebugs << "LLUICtrl::handleMousedown - handled is returning as: " << handled << "	  " << llendl; +	 +	if (handled) { +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname()); +	}  	return handled;  }  //virtual  BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask)  { + +	lldebugs << "LLUICtrl::handleMouseUp calling LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; +  	BOOL handled  = LLView::handleMouseUp(x,y,mask); +	if (handled) { +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname());  +	}  	if (mMouseUpSignal)  	{  		(*mMouseUpSignal)(this,x,y,mask);  	} + +	lldebugs << "LLUICtrl::handleMouseUp - handled for xui " << getPathname() << "  -  is returning as: " << handled << "   " << llendl; +  	return handled;  } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 3613a40e2c..20015dca1a 100755 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -48,7 +48,9 @@  #include "lluictrlfactory.h"  #include "lltooltip.h"  #include "llsdutil.h" - +#include "llsdserialize.h" +#include "llviewereventrecorder.h" +#include "llkeyboard.h"  // for ui edit hack  #include "llbutton.h"  #include "lllineeditor.h" @@ -642,13 +644,27 @@ void LLView::setVisible(BOOL visible)  // virtual  void LLView::handleVisibilityChange ( BOOL new_visibility )  { +	BOOL old_visibility;  	BOOST_FOREACH(LLView* viewp, mChildList)  	{  		// only views that are themselves visible will have their overall visibility affected by their ancestors -		if (viewp->getVisible()) +		old_visibility=viewp->getVisible(); + +		if (old_visibility!=new_visibility) +		{ +			LLViewerEventRecorder::instance().logVisibilityChange( viewp->getPathname(), viewp->getName(), new_visibility,"widget"); +		} + +		if (old_visibility)  		{  			viewp->handleVisibilityChange ( new_visibility );  		} + +		// Consider changing returns to confirm success and know which widget grabbed it +		// For now assume success and log at highest xui possible  +		// NOTE we log actual state - which may differ if it somehow failed to set visibility +		lldebugs << "LLView::handleVisibilityChange	 - now: " << getVisible()  << " xui: " << viewp->getPathname() << " name: " << viewp->getName() << llendl; +		  	}  } @@ -697,6 +713,7 @@ bool LLView::visibleEnabledAndContains(S32 local_x, S32 local_y)  		&& getEnabled();  } +// This is NOT event recording related  void LLView::logMouseEvent()  {  	if (sDebugMouseHandling) @@ -743,7 +760,14 @@ LLView* LLView::childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDA  		if ((viewp->*method)( local_x, local_y, extra )  			|| (allow_mouse_block && viewp->blockMouseEvent( local_x, local_y )))  		{ +			lldebugs << "LLView::childrenHandleMouseEvent calling updatemouseeventinfo - local_x|global x  "<< local_x << " " << x	<< "local/global y " << local_y << " " << y << llendl; +			lldebugs << "LLView::childrenHandleMouseEvent  getPathname for viewp result: " << viewp->getPathname() << "for this view: " << getPathname() << llendl; + +			LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());  + +			// This is NOT event recording related  			viewp->logMouseEvent(); +  			return viewp;  		}  	} @@ -766,6 +790,7 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)  		if (viewp->handleToolTip(local_x, local_y, mask)   			|| viewp->blockMouseEvent(local_x, local_y))  		{ +			// This is NOT event recording related  			viewp->logMouseEvent();  			return viewp;  		} @@ -824,6 +849,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)  		if (viewp->handleHover(local_x, local_y, mask)  			|| viewp->blockMouseEvent(local_x, local_y))  		{ +			// This is NOT event recording related  			viewp->logMouseEvent();  			return viewp;  		} @@ -907,10 +933,12 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)  		if (!handled)  		{ +			// For event logging we don't care which widget handles it +			// So we capture the key at the end of this function once we know if it was handled  			handled = handleKeyHere( key, mask ); -			if (handled && LLView::sDebugKeys) +			if (handled)  			{ -				llinfos << "Key handled by " << getName() << llendl; +				llwarns << "Key handled by " << getName() << llendl;  			}  		}  	} @@ -958,6 +986,11 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)  		handled = mParentView->handleUnicodeChar(uni_char, FALSE);  	} +	if (handled) +	{ +		LLViewerEventRecorder::instance().logKeyUnicodeEvent(uni_char); +	} +	  	return handled;  } @@ -987,12 +1020,16 @@ BOOL LLView::hasMouseCapture()  BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)  { -	return childrenHandleMouseUp( x, y, mask ) != NULL; +	LLView* r = childrenHandleMouseUp( x, y, mask ); + +	return (r!=NULL);  }  BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)  { -	return childrenHandleMouseDown( x, y, mask ) != NULL; +	LLView* r= childrenHandleMouseDown(x, y, mask ); + +	return (r!=NULL);  }  BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -1065,7 +1102,7 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)  LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)  { -	return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask); +	return	childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask);  }  LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask) diff --git a/indra/llui/llviewereventrecorder.cpp b/indra/llui/llviewereventrecorder.cpp new file mode 100644 index 0000000000..a352f621eb --- /dev/null +++ b/indra/llui/llviewereventrecorder.cpp @@ -0,0 +1,296 @@ +/** + * @file llviewereventrecorder.cpp + * @brief Viewer event recording and playback support for mouse and keyboard events + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + *  + * Copyright (c) 2013, Linden Research, Inc. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + +#include "llviewereventrecorder.h" +#include "llui.h" +#include "llleap.h" + +LLViewerEventRecorder::LLViewerEventRecorder() { + +  clear(UNDEFINED); + +  // Remove any previous event log file +  std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.old"); +  LLFile::remove(old_log_ui_events_to_llsd_file); +   + +  mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.llsd"); +  LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file); + +} + + +bool LLViewerEventRecorder::displayViewerEventRecorderMenuItems() { +  return LLUI::sSettingGroups["config"]->getBOOL("ShowEventRecorderMenuItems"); +} + + +void LLViewerEventRecorder::setEventLoggingOn() { +  if (! mLog.is_open()) { +    mLog.open(mLogFilename, llofstream::out); +  } +  logEvents=true;  +  lldebugs << "LLViewerEventRecorder::setEventLoggingOn event logging turned on" << llendl; +} + +void LLViewerEventRecorder::setEventLoggingOff() { +  logEvents=false; +  mLog.flush(); +  mLog.close(); +  lldebugs << "LLViewerEventRecorder::setEventLoggingOff event logging turned off" << llendl; +} + + + LLViewerEventRecorder::~LLViewerEventRecorder() { +  if (mLog.is_open()) { +      mLog.close(); +    } +} + +void LLViewerEventRecorder::clear_xui() { +  xui.clear(); +} + +void LLViewerEventRecorder::clear(S32 r) { + +  xui.clear(); + +  local_x=r; +  local_y=r; + +  global_x=r; +  global_y=r; +     + +} + +void LLViewerEventRecorder::setMouseLocalCoords(S32 x, S32 y) { +  local_x=x; +  local_y=y; +} + +void LLViewerEventRecorder::setMouseGlobalCoords(S32 x, S32 y) { +  global_x=x; +  global_y=y; +} + +void LLViewerEventRecorder::updateMouseEventInfo(S32 local_x, S32 local_y, S32 global_x, S32 global_y, std::string mName) { + +  LLView * target_view = LLUI::resolvePath(LLUI::getRootView(), xui); +  if (! target_view) { +    lldebugs << "LLViewerEventRecorder::updateMouseEventInfo - xui path on file at moment is NOT valid - so DO NOT record these local coords" << llendl; +    return; +  } +  lldebugs << "LLViewerEventRecorder::updateMouseEventInfo b4 updatemouseeventinfo - local_x|global x   "<< this->local_x << " " << this->global_x  << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl; + + +  if (this->local_x < 1 && this->local_y<1 && local_x && local_y) { +    this->local_x=local_x; +    this->local_y=local_y; +  } +  this->global_x=global_x; +  this->global_y=global_y; + +  // ONLY record deepest xui path for hierarchy searches - or first/only xui for floaters/panels reached via mouse captor - and llmousehandler +  if (mName!="" &&  mName!="/" && xui=="") {  +    //	xui=std::string("/")+mName+xui;  +    //xui=mName+xui;  +    xui = mName; // TODO review confirm we never call with partial path - also cAN REMOVE CHECK FOR "" - ON OTHER HAND IT'S PRETTY HARMLESS +  } + +  lldebugs << "LLViewerEventRecorder::updateMouseEventInfo after updatemouseeventinfo - local_x|global x   "<< this->local_x << " " << this->global_x  << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl; +} + +void LLViewerEventRecorder::logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype) { + +  LLSD  event=LLSD::emptyMap(); + +  event.insert("event",LLSD(std::string("visibility"))); + +  if (visibility) { +    event.insert("visibility",LLSD(true)); +  } else { +    event.insert("visibility",LLSD(false)); +  } + +  if (event_subtype!="") { +    event.insert("event_subtype", LLSD(event_subtype)); +  } + +  if(name!="") { +    event.insert("name",LLSD(name)); +  } + +  if (xui!="") { +    event.insert("path",LLSD(xui)); +  } + +  event.insert("timestamp",LLSD(LLDate::now().asString()));  +  recordEvent(event); +} + + +std::string LLViewerEventRecorder::get_xui() { +  return xui; +} +void LLViewerEventRecorder::update_xui(std::string xui) { +  if (xui!="" && this->xui=="" ) { +    lldebugs << "LLViewerEventRecorder::update_xui to " << xui << llendl; +    this->xui=xui; +  } else { +    lldebugs << "LLViewerEventRecorder::update_xui called with empty string" << llendl; +  } +} + +void LLViewerEventRecorder::logKeyEvent(KEY key, MASK mask) { + +  // NOTE: Event recording only logs keydown events - the viewer itself hides keyup events at a fairly low level in the code and does not appear to care about them anywhere + +  LLSD event = LLSD::emptyMap(); + +  event.insert("event",LLSD("type")); + +  // keysym ...or +  // keycode...or +  // char +  event.insert("keysym",LLSD(LLKeyboard::stringFromKey(key))); + +  // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps +  // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might +  // break the test script and it would be useful to have more context to make these sorts of edits safer +  +  // TODO  replace this with a call which extracts to an array of names of masks (just like vita expects during playback) +  // This is looking more and more like an object is a good idea, for this part a handy method call to setMask(mask) would be nice :-) +  // call the func - llkeyboard::llsdStringarrayFromMask + +  LLSD key_mask=LLSD::emptyArray(); + +  if (mask & MASK_CONTROL)     { key_mask.append(LLSD("CTL")); }  // Mac command key - has code of 0x1  in llcommon/indra_contstants +  if (mask & MASK_ALT)         { key_mask.append(LLSD("ALT")); } +  if (mask & MASK_SHIFT)       { key_mask.append(LLSD("SHIFT")); } +  if (mask & MASK_MAC_CONTROL) { key_mask.append(LLSD("MAC_CONTROL")); } + +  event.insert("mask",key_mask);  +  event.insert("timestamp",LLSD(LLDate::now().asString()));  + +  // Although vita has keyDown and keyUp requests it does not have type as a high-level concept  +  // (maybe it should) - instead it has a convenience method that generates the keydown and keyup events  +  // Here  we will use  "type" as  our event type + +  lldebugs << "LLVIewerEventRecorder::logKeyEvent Serialized LLSD for event " << event.asString() << "\n" << llendl; + + +  //lldebugs  << "[VITA] key_name: "  << LLKeyboard::stringFromKey(key) << "mask: "<< mask  << "handled by " << getName() << llendl; +  lldebugs  << "LLVIewerEventRecorder::logKeyEvent  key_name: "  << LLKeyboard::stringFromKey(key) << "mask: "<< mask  << llendl; + + +  recordEvent(event); + +} + +void LLViewerEventRecorder::playbackRecording() { + +  LLSD LeapCommand; + +  // ivita sets this on startup, it also sends commands to the viewer to make start, stop, and playback menu items visible in viewer +  LeapCommand =LLUI::sSettingGroups["config"]->getLLSD("LeapPlaybackEventsCommand"); +   +  lldebugs << "[VITA] launching playback - leap command is: " << LLSDXMLStreamer(LeapCommand) << llendl; +  LLLeap::create("", LeapCommand, false); // exception=false +   +} + + +void LLViewerEventRecorder::recordEvent(LLSD event) { +  lldebugs << "LLViewerEventRecorder::recordEvent event written to log: " << LLSDXMLStreamer(event) << llendl; +  mLog << event << std::endl; +   +} +void LLViewerEventRecorder::logKeyUnicodeEvent(llwchar uni_char) { +  if (! logEvents) return; + +  // Note: keyUp is not captured since the viewer seems to not care about keyUp events + +  LLSD event=LLSD::emptyMap(); + +  event.insert("timestamp",LLSD(LLDate::now().asString())); + +   +  // keysym ...or +  // keycode...or +  // char + +  lldebugs << "Wrapped in conversion to wstring " <<  wstring_to_utf8str(LLWString( 1, uni_char)) << "\n" << llendl; +   +  event.insert("char", +	       LLSD(  wstring_to_utf8str(LLWString( 1,uni_char))  ) +	       );  + +  // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps +  // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might +  // break the test script and it would be useful to have more context to make these sorts of edits safer + +  // TODO need to consider mask keys too? Doesn't seem possible - at least not easily at this point + +  event.insert("event",LLSD("keyDown"));  + +  lldebugs  << "[VITA] unicode key: " << uni_char   << llendl; +  lldebugs  << "[VITA] dumpxml " << LLSDXMLStreamer(event) << "\n" << llendl; + + +  recordEvent(event); + +} + +void LLViewerEventRecorder::logMouseEvent(std::string button_state,std::string button_name) +{ +  if (! logEvents) return;  + +  LLSD  event=LLSD::emptyMap(); + +  event.insert("event",LLSD(std::string("mouse"+ button_state))); +  event.insert("button",LLSD(button_name)); +  if (xui!="") { +    event.insert("path",LLSD(xui)); +  } + +  if (local_x>0 && local_y>0) { +    event.insert("local_x",LLSD(local_x)); +    event.insert("local_y",LLSD(local_y)); +  } + +  if (global_x>0 && global_y>0) { +    event.insert("global_x",LLSD(global_x)); +    event.insert("global_y",LLSD(global_y)); +  } +  event.insert("timestamp",LLSD(LLDate::now().asString()));  +  recordEvent(event); + + +  clear(UNDEFINED); +    + +} diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h new file mode 100644 index 0000000000..72ca643ced --- /dev/null +++ b/indra/llui/llviewereventrecorder.h @@ -0,0 +1,103 @@ +/** + * @file llviewereventrecorder.h + * @brief Viewer event recording and playback support for mouse and keyboard events + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + *  + * Copyright (c) 2013, Linden Research, Inc. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_VIEWER_EVENT_RECORDER +#define LL_VIEWER_EVENT_RECORDER + + +#include "linden_common.h"  + +#include "lldir.h"  +#include "llsd.h"   +#include "llfile.h" +#include "llvfile.h" +#include "lldate.h" +#include "llsdserialize.h" +#include "llkeyboard.h" +#include "llstring.h" + +#include <sstream> + +#include "llsingleton.h" // includes llerror which we need here so we can skip the include here + +class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder> +{ + + public: + +  LLViewerEventRecorder(); // TODO Protect constructor better if we can (not happy in private section) - could add a factory... - we are singleton +  ~LLViewerEventRecorder(); + + +  void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y,  std::string mName); +  void setMouseLocalCoords(S32 x,S32 y); +  void setMouseGlobalCoords(S32 x,S32 y); + +  void logMouseEvent(std::string button_state, std::string button_name ); +  void logKeyEvent(KEY key, MASK mask); +  void logKeyUnicodeEvent(llwchar uni_char); + +  void logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype); + +  void clear_xui(); +  std::string get_xui(); +  void update_xui(std::string xui); + +  bool getLoggingStatus(); +  void setEventLoggingOn(); +  void setEventLoggingOff(); + +  void playbackRecording(); + +  bool displayViewerEventRecorderMenuItems(); + + + protected: +  // On if we wish to log events at the moment - toggle via Develop/Recorder submenu +  bool logEvents; + +  std::string mLogFilename; +  llofstream  mLog;  + + + private: + +  // Mouse event info  +  S32 global_x; +  S32 global_y; +  S32 local_x; +  S32 local_y; + +  // XUI path of UI element +  std::string xui; + +  // Actually write the event out to llsd log file +  void recordEvent(LLSD event); + +  void clear(S32 r);  + +  static const S32 UNDEFINED=-1; +}; +#endif diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 2cae6f3f72..81b25601a9 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -25,6 +25,9 @@   * $/LicenseInfo$   */ +#ifndef LL_LLWINDOWMACOSX_OBJC_H +#define LL_LLWINDOWMACOSX_OBJC_H +  #include <map>  #include <vector> @@ -144,3 +147,5 @@ NSWindowRef getMainAppWindow();  GLViewRef getGLView();  unsigned int getModifiers(); + +#endif // LL_LLWINDOWMACOSX_OBJC_H diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 56472e6b45..d5b62bd3a7 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1300,6 +1300,8 @@ void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& ca  	OSMessageBox(text, caption, type);  } +			// Note on event recording - QUIT is a known special case and we are choosing NOT to record it for the record and playback feature  +			// it is handled at a very low-level  const char* cursorIDToName(int id)  {  	switch (id) diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 16f2290787..97fad7feb0 100755 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -391,7 +391,7 @@ LLControlVariable* LLControlGroup::declareControl(const std::string& name, eCont  		}  		else  		{ -			llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl; +			LL_WARNS("Settings") << "Control named " << name << " already exists, ignoring new declaration." << LL_ENDL;  		}   		return existing_control;  	} @@ -630,14 +630,14 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require  	if (!xml_controls.parseFile(filename))  	{ -		llwarns << "Unable to open control file " << filename << llendl; +		LL_WARNS("Settings") << "Unable to open control file " << filename << LL_ENDL;  		return 0;  	}  	LLXmlTreeNode* rootp = xml_controls.getRoot();  	if (!rootp || !rootp->hasAttribute("version"))  	{ -		llwarns << "No valid settings header found in control file " << filename << llendl; +		LL_WARNS("Settings") << "No valid settings header found in control file " << filename << LL_ENDL;  		return 0;  	} @@ -650,7 +650,7 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require  	// Check file version  	if (version != CURRENT_VERSION)  	{ -		llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl; +		LL_INFOS("Settings") << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << LL_ENDL;  		return 0;  	} @@ -668,7 +668,7 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require  			if (!name.empty())  			{  				//read in to end of line -				llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl; +				LL_WARNS("Settings") << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << LL_ENDL;  			}  			child_nodep = rootp->getNextChild();  			continue; @@ -822,7 +822,7 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only  		LLControlVariable* control = iter->second;  		if (!control)  		{ -			llwarns << "Tried to save invalid control: " << iter->first << llendl; +			LL_WARNS("Settings") << "Tried to save invalid control: " << iter->first << LL_ENDL;  		}  		else if( control->shouldSave(nondefault_only) )  		{ @@ -838,12 +838,12 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only  	{  		LLSDSerialize::toPrettyXML(settings, file);  		file.close(); -		llinfos << "Saved to " << filename << llendl; +		LL_INFOS("Settings") << "Saved to " << filename << LL_ENDL;  	}  	else  	{          // This is a warning because sometime we want to use settings files which can't be written... -		llwarns << "Unable to open settings file: " << filename << llendl; +		LL_WARNS("Settings") << "Unable to open settings file: " << filename << LL_ENDL;  		return 0;  	}  	return num_saved; @@ -856,14 +856,14 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  	infile.open(filename);  	if(!infile.is_open())  	{ -		llwarns << "Cannot find file " << filename << " to load." << llendl; +		LL_WARNS("Settings") << "Cannot find file " << filename << " to load." << LL_ENDL;  		return 0;  	}  	if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(settings, infile))  	{  		infile.close(); -		llwarns << "Unable to parse LLSD control file " << filename << ". Trying Legacy Method." << llendl; +		LL_WARNS("Settings") << "Unable to parse LLSD control file " << filename << ". Trying Legacy Method." << LL_ENDL;  		return loadFromFileLegacy(filename, TRUE, TYPE_STRING);  	} @@ -976,6 +976,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  		++validitems;  	} +	LL_DEBUGS("Settings") << "Loaded " << validitems << " settings from " << filename << LL_ENDL;  	return validitems;  } @@ -1012,7 +1013,7 @@ void main()  	BOOL_CONTROL baz;  	U32 count = gGlobals.loadFromFile("controls.ini"); -	llinfos << "Loaded " << count << " controls" << llendl; +	LL_INFOS("Settings") << "Loaded " << count << " controls" << LL_ENDL;  	// test insertion  	foo = new LLControlVariable<F32>("gFoo", 5.f, 1.f, 20.f); @@ -1273,19 +1274,19 @@ LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const st  		LLColor4 color(sd);  		if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)  		{ -			llwarns << "Color " << control_name << " red value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " red value out of range: " << color << LL_ENDL;  		}  		else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)  		{ -			llwarns << "Color " << control_name << " green value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " green value out of range: " << color << LL_ENDL;  		}  		else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)  		{ -			llwarns << "Color " << control_name << " blue value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " blue value out of range: " << color << LL_ENDL;  		}  		else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)  		{ -			llwarns << "Color " << control_name << " alpha value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " alpha value out of range: " << color << LL_ENDL;  		}  		return LLColor4(sd); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index eeed12499d..523429c2e2 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4941,6 +4941,16 @@        <key>Value</key>        <array />      </map> +    <key>LeapPlaybackEventsCommand</key> +    <map> +      <key>Comment</key> +      <string>Command line to use leap to launch playback of event recordings</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>LLSD</string> +      <key>Value</key> +    </map>      <key>LSLFindCaseInsensitivity</key>          <map>          <key>Comment</key> @@ -10444,6 +10454,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>ShowEventRecorderMenuItems</key> +    <map> +      <key>Comment</key> +      <string>Whether or not Event Recorder menu choices - Start / Stop event recording should appear in the (currently) Develop menu</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>ShowGestureButton</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f67142d1ed..e39f2616ae 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -223,6 +223,10 @@  #include "llmachineid.h"  #include "llmainlooprepeater.h" + +#include "llviewereventrecorder.h" + +  // *FIX: These extern globals should be cleaned up.  // The globals either represent state/config/resource-storage of either   // this app, or another 'component' of the viewer. App globals should be  @@ -696,6 +700,7 @@ LLAppViewer::LLAppViewer() :  LLAppViewer::~LLAppViewer()  {  	delete mSettingsLocationList; +	LLViewerEventRecorder::instance().~LLViewerEventRecorder();  	LLLoginInstance::instance().setUpdaterService(0); @@ -2250,13 +2255,13 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,  		BOOST_FOREACH(const SettingsFile& file, group.files)  		{ -			llinfos << "Attempting to load settings for the group " << file.name() -			    << " - from location " << location_key << llendl; +			LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name() +			    << " - from location " << location_key << LL_ENDL;  			LLControlGroup* settings_group = LLControlGroup::getInstance(file.name);  			if(!settings_group)  			{ -				llwarns << "No matching settings group for name " << file.name() << llendl; +				LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL;  				continue;  			} @@ -2285,7 +2290,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,  			if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))  			{	// success! -				llinfos << "Loaded settings file " << full_settings_path << llendl; +				LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL;  			}  			else  			{	// failed to load @@ -2299,7 +2304,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,  					// only complain if we actually have a filename at this point  					if (!full_settings_path.empty())  					{ -						llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl; +						LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL;  					}  				}  			} @@ -2395,8 +2400,6 @@ bool LLAppViewer::initConfiguration()  	gSavedSettings.setString("ClientSettingsFile",           gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global"))); -	gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel()); -  #ifndef	LL_RELEASE_FOR_DOWNLOAD  	// provide developer build only overrides for these control variables that are not  	// persisted to settings.xml @@ -2460,8 +2463,8 @@ bool LLAppViewer::initConfiguration()  			gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,   										   clp.getOption("settings")[0]);		  		gSavedSettings.setString("ClientSettingsFile", user_settings_filename); -		llinfos	<< "Using command line specified settings filename: "  -			<< user_settings_filename << llendl; +		LL_INFOS("Settings")	<< "Using command line specified settings filename: "  +			<< user_settings_filename << LL_ENDL;  	}  	// - load overrides from user_settings  @@ -2477,8 +2480,8 @@ bool LLAppViewer::initConfiguration()  	{  		std::string session_settings_filename = clp.getOption("sessionsettings")[0];		  		gSavedSettings.setString("SessionSettingsFile", session_settings_filename); -		llinfos	<< "Using session settings filename: "  -			<< session_settings_filename << llendl; +		LL_INFOS("Settings")	<< "Using session settings filename: "  +			<< session_settings_filename << LL_ENDL;  	}  	loadSettingsFromDirectory("Session"); @@ -2486,8 +2489,8 @@ bool LLAppViewer::initConfiguration()  	{  		std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];		  		gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename); -		llinfos	<< "Using user session settings filename: "  -			<< user_session_settings_filename << llendl; +		LL_INFOS("Settings") << "Using user session settings filename: "  +			<< user_session_settings_filename << LL_ENDL;  	}  	loadSettingsFromDirectory("UserSession"); @@ -2575,6 +2578,10 @@ bool LLAppViewer::initConfiguration()          }      } +    if  (clp.hasOption("logevents")) { +	LLViewerEventRecorder::instance().setEventLoggingOn(); +    } +  	std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));  	if(! CmdLineChannel.empty())  	{ diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 3cf3c739d9..80a80f4298 100755 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -172,21 +172,20 @@ void ll_nvapi_init(NvDRSSessionHandle hSession)  			nvapi_error(status);  			return;  		} + +        // (5) Now we apply (or save) our changes to the system +        status = NvAPI_DRS_SaveSettings(hSession); +        if (status != NVAPI_OK)  +        { +            nvapi_error(status); +            return; +        }  	}  	else if (status != NVAPI_OK)  	{  		nvapi_error(status);  		return;  	} - -	 - -	// (5) Now we apply (or save) our changes to the system -	status = NvAPI_DRS_SaveSettings(hSession); -	if (status != NVAPI_OK)  -	{ -		nvapi_error(status); -	}  }  //#define DEBUGGING_SEH_FILTER 1 diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index b513a52ff7..70cc48f12b 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -73,6 +73,8 @@  #include "llcallingcard.h"  #include "llslurl.h"			// IDEVO  #include "llsidepanelinventory.h" +#include "llavatarname.h" +#include "llagentui.h"  // static  void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name) @@ -391,6 +393,72 @@ void LLAvatarActions::pay(const LLUUID& id)  	}  } +void LLAvatarActions::teleport_request_callback(const LLSD& notification, const LLSD& response) +{ +	S32 option; +	if (response.isInteger())  +	{ +		option = response.asInteger(); +	} +	else +	{ +		option = LLNotificationsUtil::getSelectedOption(notification, response); +	} + +	if (0 == option) +	{ +		LLMessageSystem* msg = gMessageSystem; + +		msg->newMessageFast(_PREHASH_ImprovedInstantMessage); +		msg->nextBlockFast(_PREHASH_AgentData); +		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + +		msg->nextBlockFast(_PREHASH_MessageBlock); +		msg->addBOOLFast(_PREHASH_FromGroup, FALSE); +		msg->addUUIDFast(_PREHASH_ToAgentID, notification["substitutions"]["uuid"] ); +		msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); +		msg->addU8Fast(_PREHASH_Dialog, IM_TELEPORT_REQUEST); +		msg->addUUIDFast(_PREHASH_ID, LLUUID::null); +		msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary + +		std::string name; +		LLAgentUI::buildFullname(name); + +		msg->addStringFast(_PREHASH_FromAgentName, name); +		msg->addStringFast(_PREHASH_Message, response["message"]); +		msg->addU32Fast(_PREHASH_ParentEstateID, 0); +		msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); +		msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); + +		gMessageSystem->addBinaryDataFast( +				_PREHASH_BinaryBucket, +				EMPTY_BINARY_BUCKET, +				EMPTY_BINARY_BUCKET_SIZE); + +		gAgent.sendReliableMessage(); +	} +} + +// static +void LLAvatarActions::teleportRequest(const LLUUID& id) +{ +	LLSD notification; +	notification["uuid"] = id; +	LLAvatarName av_name; +	if (!LLAvatarNameCache::get(id, &av_name)) +	{ +		// unlikely ... they just picked this name from somewhere... +		LLAvatarNameCache::get(id, boost::bind(&LLAvatarActions::teleportRequest, id)); +		return; // reinvoke this when the name resolves +	} +	notification["NAME"] = av_name.getCompleteName(); + +	LLSD payload; + +	LLNotificationsUtil::add("TeleportRequestPrompt", notification, payload, teleport_request_callback); +} +  // static  void LLAvatarActions::kick(const LLUUID& id)  { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 6e1198cd09..403414558e 100755 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -111,6 +111,12 @@ public:  	static void pay(const LLUUID& id);  	/** +	 * Request teleport from other avatar +	 */ +	static void teleportRequest(const LLUUID& id); +	static void teleport_request_callback(const LLSD& notification, const LLSD& response); + +	/**  	 * Share items with the avatar.  	 */  	static void share(const LLUUID& id); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 88884042d4..131aea9da3 100755 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -220,18 +220,25 @@ void LLNotificationChiclet::setCounter(S32 counter)  bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification )  { -	if (notification->getName() == "ScriptDialog") +	bool displayNotification; +	if (   (notification->getName() == "ScriptDialog") // special case for scripts +		// if there is no toast window for the notification, filter it +		|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID())) +		)  	{ -		return false; +		displayNotification = false;  	} - -	if( !(notification->canLogToIM() && notification->hasFormElements()) -		&& (!notification->getPayload().has("give_inventory_notification") -			|| notification->getPayload()["give_inventory_notification"])) +	else if( !(notification->canLogToIM() && notification->hasFormElements()) +			&& (!notification->getPayload().has("give_inventory_notification") +				|| notification->getPayload()["give_inventory_notification"]))  	{ -		return true; +		displayNotification = true;  	} -	return false; +	else +	{ +		displayNotification = false; +	} +	return displayNotification;  }  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 5ab108b39f..44212298cf 100755 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -313,6 +313,10 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)  	{  		LLAvatarActions::offerTeleport(selected_conversation_participant_id);  	} +	else if ("request_teleport" == command_name) +	{ +		LLAvatarActions::teleportRequest(selected_conversation_participant_id); +	}  	else if("add_friend" == command_name)  	{  		if (!LLAvatarActions::isFriend(selected_conversation_participant_id)) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 192a594c9d..affa24f78c 100755 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -132,6 +132,7 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32  		items.push_back(std::string("view_profile"));  		items.push_back(std::string("im"));  		items.push_back(std::string("offer_teleport")); +		items.push_back(std::string("request_teleport"));  		items.push_back(std::string("voice_call"));  		items.push_back(std::string("chat_history"));  		items.push_back(std::string("separator_chat_history")); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2c3b34e128..92c44f7ee1 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1080,6 +1080,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec  		{  			LLAvatarActions::offerTeleport(selectedIDS);  		} +		else if ("request_teleport" == command) +		{ +			LLAvatarActions::teleportRequest(selectedIDS.front()); +		}  		else if ("voice_call" == command)  		{  			LLAvatarActions::startCall(userID); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 6ef4d8717d..8f20d4e082 100755 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2097,7 +2097,6 @@ void LLPanelLandOptions::refresh()  // virtual  void LLPanelLandOptions::draw()  { -	refreshSearch();	// Is this necessary?  JC  	LLPanel::draw();  } @@ -2111,9 +2110,8 @@ void LLPanelLandOptions::refreshSearch()  		mCheckShowDirectory->set(FALSE);  		mCheckShowDirectory->setEnabled(FALSE); -		// *TODO:Translate -		const std::string& none_string = LLParcel::getCategoryUIString(LLParcel::C_NONE); -		mCategoryCombo->setSimple(none_string); +		const std::string& none_string = LLParcel::getCategoryString(LLParcel::C_NONE); +		mCategoryCombo->setValue(none_string);  		mCategoryCombo->setEnabled(FALSE);  		return;  	} @@ -2140,10 +2138,9 @@ void LLPanelLandOptions::refreshSearch()  	mCheckShowDirectory	->set(show_directory);  	// Set by string in case the order in UI doesn't match the order by index. -	// *TODO:Translate  	LLParcel::ECategory cat = parcel->getCategory(); -	const std::string& category_string = LLParcel::getCategoryUIString(cat); -	mCategoryCombo->setSimple(category_string); +	const std::string& category_string = LLParcel::getCategoryString(cat); +	mCategoryCombo->setValue(category_string);  	std::string tooltip;  	bool enable_show_directory = false; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 1969435ba1..87ae36716d 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -618,9 +618,12 @@ void LLFloaterPreference::cancel()  	// hide translation settings floater  	LLFloaterReg::hideInstance("prefs_translation"); -	// hide translation settings floater +	// hide autoreplace settings floater  	LLFloaterReg::hideInstance("prefs_autoreplace"); +	// hide spellchecker settings folder +	LLFloaterReg::hideInstance("prefs_spellchecker"); +	  	// cancel hardware menu  	LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance<LLFloaterHardwareSettings>("prefs_hardware_settings");  	if (hardware_settings) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 50c013a49d..66bf49331b 100755 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1734,7 +1734,7 @@ void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)  			LLSD args;  			args["NUM_ADDED"] = llformat("%d",ids.size());  			args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); -			args["LIST_TYPE"] = "Allowed Residents"; +			args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents");  			args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);  			LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);  			delete change_info; @@ -1750,7 +1750,7 @@ void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)  			LLSD args;  			args["NUM_ADDED"] = llformat("%d",ids.size());  			args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); -			args["LIST_TYPE"] = "Banned Residents"; +			args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");  			args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);  			LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);  			delete change_info; @@ -2815,9 +2815,10 @@ bool LLDispatchSetEstateAccess::operator()(  		} -		std::string msg = llformat("Banned residents: (%d, max %d)", -									totalBannedAgents, -									ESTATE_MAX_ACCESS_IDS); +		LLStringUtil::format_map_t args; +		args["[BANNEDAGENTS]"] = llformat("%d", totalBannedAgents); +		args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); +		std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);  		panel->getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));  		if (banned_agent_name_list) @@ -2837,9 +2838,10 @@ bool LLDispatchSetEstateAccess::operator()(  	if (access_flags & ESTATE_ACCESS_MANAGERS)  	{ -		std::string msg = llformat("Estate Managers: (%d, max %d)", -									num_estate_managers, -									ESTATE_MAX_MANAGERS); +		LLStringUtil::format_map_t args; +		args["[ESTATEMANAGERS]"] = llformat("%d", num_estate_managers); +		args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS); +		std::string msg = LLTrans::getString("RegionInfoEstateManagers", args);  		panel->getChild<LLUICtrl>("estate_manager_label")->setValue(LLSD(msg));  		LLNameListCtrl* estate_manager_name_list = diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e4fc469bb7..80ef506272 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4739,6 +4739,16 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act  			LLAvatarActions::offerTeleport(item->getCreatorUUID());  		}  	} +	else if ("request_lure" == action) +	{ +		LLViewerInventoryItem *item = getItem(); +		if (item && (item->getCreatorUUID() != gAgent.getID()) && +			(!item->getCreatorUUID().isNull())) +		{ +			LLAvatarActions::teleportRequest(item->getCreatorUUID()); +		} +	} +  	else LLItemBridge::performAction(model, action);  } @@ -4825,6 +4835,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		items.push_back(std::string("Send Instant Message Separator"));  		items.push_back(std::string("Send Instant Message"));  		items.push_back(std::string("Offer Teleport...")); +		items.push_back(std::string("Request Teleport..."));  		items.push_back(std::string("Conference Chat"));  		if (!good_card) @@ -4834,6 +4845,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		if (!good_card || !user_online)  		{  			disabled_items.push_back(std::string("Offer Teleport...")); +			disabled_items.push_back(std::string("Request Teleport..."));  			disabled_items.push_back(std::string("Conference Chat"));  		}  	} diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index dea90b9042..08b5eaedbb 100755 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -343,8 +343,11 @@ void LLNetMap::draw()  		// Draw avatars  		for (U32 i = 0; i < avatar_ids.size(); i++)  		{ -			pos_map = globalPosToView(positions[i]);  			LLUUID uuid = avatar_ids[i]; +			// Skip self, we'll draw it later +			if (uuid == gAgent.getID()) continue; + +			pos_map = globalPosToView(positions[i]);  			bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 08c98e4f28..56ed1044e9 100755 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -87,7 +87,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)  	{  		LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());  	} -	else +	else if (notification->canShowToast())  	{  		LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 49f7361c4a..0b2bf1d2c8 100755 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -74,6 +74,7 @@ LLContextMenu* PeopleContextMenu::createMenu()  		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));  		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id));  		registrar.add("Avatar.InviteToGroup",	boost::bind(&LLAvatarActions::inviteToGroup,			id)); +		registrar.add("Avatar.TeleportRequest",	boost::bind(&PeopleContextMenu::requestTeleport,		this));  		registrar.add("Avatar.Calllog",			boost::bind(&LLAvatarActions::viewChatHistory,			id));  		enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2)); @@ -125,6 +126,7 @@ void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)  		items.push_back(std::string("view_profile"));  		items.push_back(std::string("im"));  		items.push_back(std::string("offer_teleport")); +		items.push_back(std::string("request_teleport"));  		items.push_back(std::string("voice_call"));  		items.push_back(std::string("chat_history"));  		items.push_back(std::string("separator_chat_history")); @@ -255,6 +257,13 @@ bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)  	return false;  } +void PeopleContextMenu::requestTeleport() +{ +	// boost::bind cannot recognize overloaded method LLAvatarActions::teleportRequest(), +	// so we have to use a wrapper. +	LLAvatarActions::teleportRequest(mUUIDs.front()); +} +  void PeopleContextMenu::offerTeleport()  {  	// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(), @@ -284,6 +293,7 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)  		items.push_back(std::string("view_profile"));  		items.push_back(std::string("im"));  		items.push_back(std::string("offer_teleport")); +		items.push_back(std::string("request_teleport"));  		items.push_back(std::string("voice_call"));  		items.push_back(std::string("chat_history"));  		items.push_back(std::string("separator_chat_history")); diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h index 0a1dcef303..abf5fa05e4 100755 --- a/indra/newview/llpanelpeoplemenus.h +++ b/indra/newview/llpanelpeoplemenus.h @@ -47,6 +47,7 @@ private:  	bool enableContextMenuItem(const LLSD& userdata);  	bool checkContextMenuItem(const LLSD& userdata);  	void offerTeleport(); +	void requestTeleport();  };  /** diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 928d26646b..c4d5450e2b 100755 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -207,6 +207,7 @@ LLSD _basic_constraints_ext(X509* cert)  			}  		} +		BASIC_CONSTRAINTS_free( bs );  	}  	return result;  } @@ -268,6 +269,8 @@ LLSD _ext_key_usage_ext(X509* cert)  				ASN1_OBJECT_free(usage);  			}  		} + +		EXTENDED_KEY_USAGE_free( eku );  	}  	return result;  } @@ -280,6 +283,8 @@ LLSD _subject_key_identifier_ext(X509 *cert)  	if(skeyid)  	{  		result = cert_string_from_octet_string(skeyid); + +		ASN1_OCTET_STRING_free( skeyid );  	}  	return result;  } @@ -300,6 +305,9 @@ LLSD _authority_key_identifier_ext(X509* cert)  		{  			result[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL] = cert_string_from_asn1_integer(akeyid->serial);  		}	 + + +		AUTHORITY_KEYID_free( akeyid );  	}  	// we ignore the issuer name in the authority key identifier, we check the issue name via @@ -1049,6 +1057,8 @@ void LLBasicCertificateStore::validate(int validation_policy,  		throw LLInvalidCertificate((*current_cert));			  	}  	std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH); +	X509_free( cert_x509 ); +	cert_x509 = NULL;  	t_cert_cache::iterator cache_entry = mTrustedCertCache.find(sha1_hash);  	if(cache_entry != mTrustedCertCache.end())  	{ diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 1a3add2bfb..626d69aca4 100755 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -118,6 +118,11 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)  	}  } + LLPanel * LLSysWellWindow::findItemByID(const LLUUID& id) +{ +       return mMessageList->getItemByValue(id); +} +  //---------------------------------------------------------------------------------  //---------------------------------------------------------------------------------  void LLSysWellWindow::initChannel()  diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index cc5c057d8b..71b41476f5 100755 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -55,6 +55,7 @@ public:  	// Operating with items  	void removeItemByID(const LLUUID& id); +	LLPanel * findItemByID(const LLUUID& id);  	// Operating with outfit  	virtual void setVisible(BOOL visible); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 2fbb3bf868..aa9de076b8 100755 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -687,7 +687,10 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key,  MASK translated_mask, BOOL  	{  		// it is sufficient to set this value once per call to handlekey  		// without clearing it, as it is only used in the subsequent call to scanKey -		mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask); +		mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);  +		// mKeyHandledByUI is not what you think ... this indicates whether the UI has handled this keypress yet (any keypress) +		// NOT whether some UI shortcut wishes to handle the keypress +	    	}  	return mKeyHandledByUI[translated_key];  } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9468a2d542..e1e6b18aeb 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -40,6 +40,7 @@  #include "llinventorypanel.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" +#include "llviewereventrecorder.h"  // newview includes  #include "llagent.h" @@ -1952,6 +1953,43 @@ class LLAdvancedDropPacket : public view_listener_t  }; +//////////////////// +// EVENT Recorder // +/////////////////// + + +class LLAdvancedViewerEventRecorder : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		std::string command = userdata.asString(); +		if ("start playback" == command) +		{ +			llinfos << "Event Playback starting" << llendl; +			LLViewerEventRecorder::instance().playbackRecording(); +			llinfos << "Event Playback completed" << llendl; +		} +		else if ("stop playback" == command) +		{ +			// Future +		} +		else if ("start recording" == command) +		{ +			LLViewerEventRecorder::instance().setEventLoggingOn(); +			llinfos << "Event recording started" << llendl; +		} +		else if ("stop recording" == command) +		{ +			LLViewerEventRecorder::instance().setEventLoggingOff(); +			llinfos << "Event recording stopped" << llendl; +		}  + +		return true; +	}		 +}; + + +  /////////////////  // AGENT PILOT // @@ -8420,6 +8458,8 @@ void initialize_menus()  	// Don't prepend MenuName.Foo because these can be used in any menu.  	enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service)); +	enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance())); +  	view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts");  	enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); @@ -8678,6 +8718,7 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");  	view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop");  	view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop"); +	view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder");  	// Advanced > Debugging  	view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c38af1f990..ab9ea5618e 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2220,7 +2220,7 @@ static std::string clean_name_from_im(const std::string& name, EInstantMessage t  	case IM_LURE_ACCEPTED:  	case IM_LURE_DECLINED:  	case IM_GODLIKE_LURE_USER: -	case IM_YET_TO_BE_USED: +	case IM_TELEPORT_REQUEST:  	case IM_GROUP_ELECTION_DEPRECATED:  	//IM_GOTO_URL  	//IM_FROM_TASK_AS_ALERT @@ -2988,6 +2988,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  		break;  	case IM_LURE_USER: +	case IM_TELEPORT_REQUEST:  		{  			if (is_muted)  			{  @@ -3010,7 +3011,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				bool canUserAccessDstRegion = true;  				bool doesUserRequireMaturityIncrease = false; -				if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) +				// Do not parse the (empty) lure bucket for TELEPORT_REQUEST +				if (IM_TELEPORT_REQUEST != dialog && parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))  				{  					region_access_str = LLViewerRegion::accessToString(region_access);  					region_access_icn = LLViewerRegion::getAccessIcon(region_access); @@ -3082,12 +3084,22 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				}  				else  				{ -			    LLNotification::Params params("TeleportOffered"); +					LLNotification::Params params; +					if (IM_LURE_USER == dialog) +					{ +						params.name = "TeleportOffered"; +						params.functor.name = "TeleportOffered"; +					} +					else if (IM_TELEPORT_REQUEST == dialog) +					{ +						params.name = "TeleportRequest"; +						params.functor.name = "TeleportRequest"; +					} +  			    params.substitutions = args;  			    params.payload = payload;  			    LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);  			} -  			}  		}  		break; @@ -6873,6 +6885,51 @@ void send_group_notice(const LLUUID& group_id,  			bin_bucket_size);  } +void send_lures(const LLSD& notification, const LLSD& response) +{ +	std::string text = response["message"].asString(); +	LLSLURL slurl; +	LLAgentUI::buildSLURL(slurl); +	text.append("\r\n").append(slurl.getSLURLString()); + +	LLMessageSystem* msg = gMessageSystem; +	msg->newMessageFast(_PREHASH_StartLure); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +	msg->nextBlockFast(_PREHASH_Info); +	msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. +	msg->addStringFast(_PREHASH_Message, text); +	for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); +		it != notification["payload"]["ids"].endArray(); +		++it) +	{ +		LLUUID target_id = it->asUUID(); + +		msg->nextBlockFast(_PREHASH_TargetData); +		msg->addUUIDFast(_PREHASH_TargetID, target_id); + +		// Record the offer. +		{ +			std::string target_name; +			gCacheName->getFullName(target_id, target_name);  // for im log filenames +			LLSD args; +			args["TO_NAME"] = LLSLURL("agent", target_id, "displayname").getSLURLString();; +	 +			LLSD payload; +				 +			//*TODO please rewrite all keys to the same case, lower or upper +			payload["from_id"] = target_id; +			payload["SUPPRESS_TOAST"] = true; +			LLNotificationsUtil::add("TeleportOfferSent", args, payload); + +			// Add the recepient to the recent people list. +			LLRecentPeople::instance().add(target_id); +		} +	} +	gAgent.sendReliableMessage(); +} +  bool handle_lure_callback(const LLSD& notification, const LLSD& response)  {  	static const unsigned OFFER_RECIPIENT_LIMIT = 250; @@ -6886,50 +6943,12 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  		LLNotificationsUtil::add("TooManyTeleportOffers", args);  		return false;  	} -	 -	std::string text = response["message"].asString(); -	LLSLURL slurl; -	LLAgentUI::buildSLURL(slurl); -	text.append("\r\n").append(slurl.getSLURLString()); +  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	if(0 == option)  	{ -		LLMessageSystem* msg = gMessageSystem; -		msg->newMessageFast(_PREHASH_StartLure); -		msg->nextBlockFast(_PREHASH_AgentData); -		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -		msg->nextBlockFast(_PREHASH_Info); -		msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. -		msg->addStringFast(_PREHASH_Message, text); -		for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); -			it != notification["payload"]["ids"].endArray(); -			++it) -		{ -			LLUUID target_id = it->asUUID(); - -			msg->nextBlockFast(_PREHASH_TargetData); -			msg->addUUIDFast(_PREHASH_TargetID, target_id); - -			// Record the offer. -			{ -				std::string target_name; -				gCacheName->getFullName(target_id, target_name);  // for im log filenames -				LLSD args; -				args["TO_NAME"] = LLSLURL("agent", target_id, "displayname").getSLURLString();; -	 -				LLSD payload; -				 -				//*TODO please rewrite all keys to the same case, lower or upper -				payload["from_id"] = target_id; -				LLNotificationsUtil::add("TeleportOfferSent", args, payload); - -				// Add the recepient to the recent people list. -				LLRecentPeople::instance().add(target_id); -			} -		} -		gAgent.sendReliableMessage(); +		send_lures(notification, response);  	}  	return false; @@ -6969,6 +6988,58 @@ void handle_lure(const uuid_vec_t& ids)  	}  } +bool teleport_request_callback(const LLSD& notification, const LLSD& response) +{ +	LLUUID from_id = notification["payload"]["from_id"].asUUID(); +	if(from_id.isNull()) +	{ +		llwarns << "from_id is NULL" << llendl; +		return false; +	} + +	std::string from_name; +	gCacheName->getFullName(from_id, from_name); + +	if(LLMuteList::getInstance()->isMuted(from_id) && !LLMuteList::getInstance()->isLinden(from_name)) +	{ +		return false; +	} + +	S32 option = 0; +	if (response.isInteger())  +	{ +		option = response.asInteger(); +	} +	else +	{ +		option = LLNotificationsUtil::getSelectedOption(notification, response); +	} + +	switch(option) +	{ +	// Yes +	case 0: +		{ +			LLSD dummy_notification; +			dummy_notification["payload"]["ids"][0] = from_id; + +			LLSD dummy_response; +			dummy_response["message"] = response["message"]; + +			send_lures(dummy_notification, dummy_response); +		} +		break; + +	// No +	case 1: +	default: +		break; +	} + +	return false; +} + +static LLNotificationFunctorRegistration teleport_request_callback_reg("TeleportRequest", teleport_request_callback);  void send_improved_im(const LLUUID& to_id,  							const std::string& name, diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 66615657d8..b4e287c446 100755 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -954,15 +954,17 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  			objectp = *idle_iter;  			llassert(objectp->isActive());  			objectp->idleUpdate(agent, world, frame_time); - -			} +		}  		//update flexible objects  		LLVolumeImplFlexible::updateClass();  		//update animated textures -		LLViewerTextureAnim::updateClass(); -			} +		if (gAnimateTextures) +		{ +			LLViewerTextureAnim::updateClass(); +		} +	} diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index bf11bce3da..ff7642a773 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -198,6 +198,8 @@  #include "llagentui.h"  #include "llwearablelist.h" +#include "llviewereventrecorder.h" +  #include "llnotifications.h"  #include "llnotificationsutil.h"  #include "llnotificationmanager.h" @@ -954,27 +956,18 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK  			{  				llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl;  			} -			return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); -		} -		// Topmost view gets a chance before the hierarchy -		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); -		//if (top_ctrl) -		//{ -		//	S32 local_x, local_y; -		//	top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); -		//		if (top_ctrl->pointInView(local_x, local_y)) -		//		{ -		//			return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down)	; -		//		} -		//		else -		//		{ -		//		if (down) -		//		{ -		//			gFocusMgr.setTopCtrl(NULL); -		//		} -		//	} -		//} +			BOOL r = mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down);  +			if (r) { + +				lldebugs << "LLViewerWindow::handleAnyMouseClick viewer with mousecaptor calling updatemouseeventinfo - local_x|global x  "<< local_x << " " << x  << "local/global y " << local_y << " " << y << llendl; + +				LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); +				LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname));  + +			} +			return r; +		}  		// Mark the click as handled and return if we aren't within the root view to avoid spurious bugs  		if( !mRootView->pointInView(x, y) ) @@ -982,27 +975,44 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK  			return TRUE;  		}  		// Give the UI views a chance to process the click -		if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ) + +		BOOL r= mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ; +		if (r)   		{ + +			lldebugs << "LLViewerWindow::handleAnyMouseClick calling updatemouseeventinfo - global x  "<< " " << x	<< "global y " << y	 << "buttonstate: " << buttonstatestr << " buttonname " << buttonname << llendl; + +			LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + +			// Clear local coords - this was a click on root window so these are not needed +			// By not including them, this allows the test skeleton generation tool to be smarter when generating code +			// the code generator can be smarter because when local coords are present it can try the xui path with local coords +			// and fallback to global coordinates only if needed.  +			// The drawback to this approach is sometimes a valid xui path will appear to work fine, but NOT interact with the UI element +			// (VITA support not implemented yet or not visible to VITA due to widget further up xui path not being visible to VITA) +			// For this reason it's best to provide hints where possible here by leaving out local coordinates +			LLViewerEventRecorder::instance().setMouseLocalCoords(-1,-1); +			LLViewerEventRecorder::instance().logMouseEvent(buttonstatestr,buttonname);  +  			if (LLView::sDebugMouseHandling)  			{ -				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl; -			} +				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLViewerEventRecorder::instance().get_xui()	<< llendl; +			}   			return TRUE; -		} -		else if (LLView::sDebugMouseHandling) -		{ -			llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl; -		} +		} else if (LLView::sDebugMouseHandling) +			{ +				llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl; +			}  	}  	// Do not allow tool manager to handle mouseclicks if we have disconnected	  	if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )  	{ +		LLViewerEventRecorder::instance().clear_xui();   		return TRUE;  	} -	 +	  	// If we got this far on a down-click, it wasn't handled.  	// Up-clicks, though, are always handled as far as the OS is concerned.  	BOOL default_rtn = !down; @@ -1373,7 +1383,8 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)  void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)  {  	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); -	return gViewerKeyboard.scanKey(key, key_down, key_up, key_level); +	gViewerKeyboard.scanKey(key, key_down, key_up, key_level); +	return; // Be clear this function returns nothing  } @@ -2519,6 +2530,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  		||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))  		||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE)))  	{ +		lldebugs << "LLviewerWindow::handleKey handle nav keys for nav" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2533,12 +2546,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  			&& keyboard_focus   			&& keyboard_focus->handleKey(key,mask,FALSE))  		{ +			LLViewerEventRecorder::instance().logKeyEvent(key,mask);  			return TRUE;  		}  		if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))  			||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))  		{ +			LLViewerEventRecorder::instance().logKeyEvent(key,mask);  			return TRUE;  		}  	} @@ -2548,6 +2563,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// if nothing has focus, go to first or last UI element as appropriate  	if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))  	{ +		llwarns << "LLviewerWindow::handleKey give floaters first chance at tab key " << llendl;  		if (gMenuHolder) gMenuHolder->hideMenus();  		// if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode @@ -2562,11 +2578,13 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  		{  			mRootView->focusNextRoot();  		} +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	}  	// hidden edit menu for cut/copy/paste  	if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask))  	{ +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2606,18 +2624,27 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  		if (keyboard_focus->handleKey(key, mask, FALSE))  		{ + +			lldebugs << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned true" << llendl; +			LLViewerEventRecorder::instance().logKeyEvent(key,mask);   			return TRUE; +		} else { +			lldebugs << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned FALSE" << llendl;  		}  	}  	if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )  	{ +		lldebugs << "LLviewerWindow::handleKey toolbar handling?" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	}  	// Try for a new-format gesture  	if (LLGestureMgr::instance().triggerGesture(key, mask))  	{ +		lldebugs << "LLviewerWindow::handleKey new gesture feature" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2625,6 +2652,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// don't pass it down to the menus.  	if (gGestureList.trigger(key, mask))  	{ +		lldebugs << "LLviewerWindow::handleKey check gesture trigger" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2673,7 +2702,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  	// HACK: Numeric keypad <enter> on Mac is Unicode 3  	// HACK: Control-M on Windows is Unicode 13  	if ((uni_char == 13 && mask != MASK_CONTROL) -		|| (uni_char == 3 && mask == MASK_NONE)) +	    || (uni_char == 3 && mask == MASK_NONE) )  	{  		if (mask != MASK_ALT)  		{ @@ -2696,14 +2725,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  			return TRUE;  		} -		//// Topmost view gets a chance before the hierarchy -		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); -		//if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) ) -		//{ -		//	return TRUE; -		//} - -		return TRUE; +        return TRUE;  	}  	return FALSE; @@ -2712,8 +2734,6 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  void LLViewerWindow::handleScrollWheel(S32 clicks)  { -	LLView::sMouseHandlerMessage.clear(); -  	LLUI::resetMouseIdleTimer();  	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp index 28f959eb71..a8e06511d7 100755 --- a/indra/newview/llwindowlistener.cpp +++ b/indra/newview/llwindowlistener.cpp @@ -265,7 +265,9 @@ void LLWindowListener::getPaths(LLSD const & request)  void LLWindowListener::keyDown(LLSD const & evt)  {  	Response response(LLSD(), evt); -	 +	KEY key = getKEY(evt); +	MASK mask = getMask(evt); +  	if (evt.has("path"))  	{  		std::string path(evt["path"]); @@ -280,8 +282,6 @@ void LLWindowListener::keyDown(LLSD const & evt)  			response.setResponse(target_view->getInfo());  			gFocusMgr.setKeyboardFocus(target_view); -			KEY key = getKEY(evt); -			MASK mask = getMask(evt);  			gViewerKeyboard.handleKey(key, mask, false);  			if(key < 0x80) mWindow->handleUnicodeChar(key, mask);  		} @@ -294,7 +294,8 @@ void LLWindowListener::keyDown(LLSD const & evt)  	}  	else   	{ -		mKbGetter()->handleTranslatedKeyDown(getKEY(evt), getMask(evt)); +		gViewerKeyboard.handleKey(key, mask, false);  +		if(key < 0x80) mWindow->handleUnicodeChar(key, mask);  	}  } diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 5fa380e0e3..bfae142812 100755 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -522,6 +522,17 @@ bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID&  			tooltip_fmt.setArg("[AREA]",  llformat("%d", extra));  			tooltip_fmt.setArg("[PRICE]", llformat("%d", extra2)); + +			// Check for division by zero +			if (extra != 0) +			{ +				tooltip_fmt.setArg("[SQMPRICE]", llformat("%.1f", (F32)extra2 / (F32)extra)); +			} +			else +			{ +				tooltip_fmt.setArg("[SQMPRICE]",  LLTrans::getString("Unknown")); +			} +  			new_item.setTooltip(tooltip_fmt.getString());  			if (type == MAP_ITEM_LAND_FOR_SALE) diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index c8c20424e1..4268b95370 100755 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -1274,7 +1274,7 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 793a6e6fa1..a660e812cc 100755 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1365,7 +1365,7 @@ Only large parcels can be listed in search.                  <combo_box.item                   label="Any Category"                   name="item0" -                 value="any" /> +                 value="none" />                  <combo_box.item                   label="Linden Location"                   name="item1" diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index b3d28788da..31b1d091ee 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -53,6 +53,13 @@          <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/>      </menu_item_call>      <menu_item_call +     label="Request teleport" +     layout="topleft" +     name="request_teleport"> +        <on_click function="Avatar.DoToSelected" parameter="request_teleport"/> +        <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call       label="Voice call"       layout="topleft"       name="voice_call"> diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml index 8796b87955..a1a3afbf68 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -56,6 +56,16 @@        function="Calllog.Enable"        parameter="can_offer_teleport"/>      </menu_item_call> +    <menu_item_call +    label="Request Teleport" +    name="request_teleport"> +      <on_click +       function="Calllog.Action" +       parameter="request_teleport"/> +      <on_enable +      function="Calllog.Enable" +      parameter="can_offer_teleport"/> +    </menu_item_call>      <menu_item_separator />      <menu_item_call       label="Add Friend" diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 13dc0b941a..512205ba43 100755 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -591,6 +591,14 @@           parameter="lure" />      </menu_item_call>      <menu_item_call +     label="Request Teleport..." +     layout="topleft" +     name="Request Teleport..."> +        <menu_item_call.on_click +        function="Inventory.DoToSelected" +        parameter="request_lure" /> +    </menu_item_call> +    <menu_item_call       label="Start Conference Chat"       layout="topleft"       name="Conference Chat"> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index 3abb5f7bc8..f12226ebeb 100755 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -29,6 +29,15 @@        parameter="can_offer_teleport"/>      </menu_item_call>      <menu_item_call +    label="Request Teleport" +    name="request_teleport"> +      <menu_item_call.on_click +       function="Avatar.TeleportRequest"/> +      <menu_item_call.on_enable +      function="Avatar.EnableItem" +      parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call       label="Voice call"       layout="topleft"       name="voice_call"> @@ -134,5 +143,4 @@           function="Avatar.EnableItem"           parameter="can_block" />      </menu_item_check> -    <menu_item_separator />  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 2d65052def..cbff8097be 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -189,7 +189,7 @@           name="Preferences"           shortcut="control|P">              <menu_item_call.on_click -             function="Floater.Show" +             function="Floater.Toggle"               parameter="preferences" />          </menu_item_call>           <menu_item_call @@ -2947,6 +2947,34 @@           label="Recorder"           name="Recorder"           tear_off="true"> +            <menu_item_call visible="false" +             label="Start event recording" +             name="Start event recording"> +	      <menu_item_call.on_visible +		 function="displayViewerEventRecorderMenuItems" /> +                <menu_item_call.on_click +                 function="Advanced.EventRecorder" +                 parameter="start recording" /> +            </menu_item_call> +            <menu_item_call visible="false" +             label="Stop event recording" +             name="Stop event recording"> +	      <menu_item_call.on_visible +		 function="displayViewerEventRecorderMenuItems" /> +                <menu_item_call.on_click +                 function="Advanced.EventRecorder" +                 parameter="stop recording" /> +            </menu_item_call> +            <menu_item_call visible="false" +             label="Playback event recording" +             name="Playback event recording"> +	      <menu_item_call.on_visible +		 function="displayViewerEventRecorderMenuItems" /> +                <menu_item_call.on_click +                 function="Advanced.EventRecorder" +                 parameter="start playback" /> +            </menu_item_call> +              <menu_item_call               label="Start Playback"               name="Start Playback"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 69b7fe5a75..1a4a1b9048 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4071,6 +4071,27 @@ Join me in [REGION]    <notification     icon="alertmodal.tga" +   name="TeleportRequestPrompt" +   type="alertmodal"> +Request a teleport to [NAME] with the following message +    <tag>confirm</tag> +    <form name="form"> +      <input name="message" type="text"> + +      </input> +      <button +       default="true" +       index="0" +       name="OK" +       text="OK"/> +      <button +       index="1" +       name="Cancel" +       text="Cancel"/> +    </form> +  </notification> +  <notification +   icon="alertmodal.tga"     name="TooManyTeleportOffers"     type="alertmodal">  You attempted to make [OFFERS] teleport offers @@ -6637,7 +6658,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th     sound="UISndNewIncomingIMSession">  [NAME_SLURL] has offered to teleport you to their location: -“[MESSAGE]” +"[MESSAGE]”  <icon>[MATURITY_ICON]</icon> - [MATURITY_STR]      <tag>confirm</tag>      <form name="form"> @@ -6702,6 +6723,27 @@ However, this region contains content accessible to adults only.  	Teleport offer sent to [TO_NAME]    </notification> +  <notification +   icon="notify.tga" +   name="TeleportRequest" +   log_to_im="true" +   type="offer"> +[NAME_SLURL] is requesting to be teleported to your location. +[MESSAGE] + +Offer a teleport? +    <tag>confirm</tag> +    <form name="form"> +      <button +       index="0" +       name="Yes" +       text="Yes"/> +      <button +       index="1" +       name="No" +       text="No"/> +    </form> +  </notification>    <notification     icon="notify.tga" @@ -6750,7 +6792,6 @@ However, this region contains content accessible to adults only.     icon="notify.tga"     name="FriendshipOffered"     log_to_im="true"    -   show_toast="false"        type="notify">      <tag>friendship</tag>  	You have offered friendship to [TO_NAME] @@ -6800,7 +6841,6 @@ However, this region contains content accessible to adults only.     icon="notify.tga"     name="FriendshipAcceptedByMe"     log_to_im="true"    -   show_toast="false"     type="notify">      <tag>friendship</tag>  Friendship offer accepted. @@ -6810,7 +6850,6 @@ Friendship offer accepted.     icon="notify.tga"     name="FriendshipDeclinedByMe"     log_to_im="true"    -   show_toast="false"        type="notify">      <tag>friendship</tag>  Friendship offer declined. diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml index d9067b41c7..8794e3bf95 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml @@ -129,6 +129,16 @@     name="tap_tap_hold_to_run"     width="237"     top_pad="0"/> +  <check_box +   control_name="AutomaticFly" +   follows="left|top" +   height="20" +   label="Hold jump or crouch key to start or stop flying" +   layout="topleft" +   left_delta="0" +   name="automatic_fly" +   width="237" +   top_pad="0"/>    <text     follows="left|top"     type="string" @@ -260,4 +270,4 @@       function="Floater.Show"       parameter="pref_joystick" />    </button> -</panel>
\ No newline at end of file +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index dd2a0c6627..064ece6e4b 100755 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -113,7 +113,7 @@       image_pressed="Pause_Press"       image_pressed_selected="Play_Press"       is_toggle="true" -     left_pad="15" +     left_pad="5"       top="1"       name="media_toggle_btn"       tool_tip="Start/Stop All Media (Music, Video, Web pages)" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 1c46cec479..5ba96a9ddb 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -379,7 +379,7 @@ Please try logging in again in a minute.</string>  	<!-- world map -->  	<string name="texture_loading">Loading...</string>  	<string name="worldmap_offline">Offline</string> -	<string name="worldmap_item_tooltip_format">[AREA] m² L$[PRICE]</string> +	<string name="worldmap_item_tooltip_format">[AREA] m² L$[PRICE] ([SQMPRICE] L$/m²)</string>  	<string name="worldmap_results_none_found">None found.</string>  	<!-- animations uploading status codes --> @@ -2185,7 +2185,7 @@ For AI Character: Get the closest navigable point to the point provided.  	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>  	<string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string>  	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string> -	<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string> +	<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3</string>  	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string>  	<string name="MarketplaceURL_Imports">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports</string>  	<string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string> @@ -2464,7 +2464,11 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale  		all estates that you manage for [OWNER]  	</string>  	<string name="RegionInfoAllowedResidents">Allowed Residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string> -	<string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string> +	<string name="RegionInfoAllowedGroups">Allowed Groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string> +	<string name="RegionInfoEstateManagers">Estate Managers: ([ESTATEMANAGERS], max [MAXMANAGERS])</string> +	<string name="RegionInfoBannedResidents">Banned Residents: ([BANNEDAGENTS], max [MAXBANNED])</string> +	<string name="RegionInfoListTypeAllowedAgents">Allowed Residents</string> +	<string name="RegionInfoListTypeBannedAgents">Banned Residents</string>  	<!-- script limits floater -->  	<string name="ScriptLimitsParcelScriptMemory">Parcel Script Memory</string> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 4686d1ed3a..484511a08b 100755 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -1256,7 +1256,7 @@ Intenta iniciar sesión de nuevo en unos instantes.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 346fa62351..78d846ff4f 100755 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -1274,7 +1274,7 @@ Veuillez réessayer de vous connecter dans une minute.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 160df911d3..60ed2b0929 100755 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -1265,7 +1265,7 @@ Prova ad accedere nuovamente tra un minuto.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index ab2fd461ab..a0f45e5a55 100755 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -1274,7 +1274,7 @@ support@secondlife.com にお問い合わせください。  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index adc3ee14e0..2eb4c0a02e 100755 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -1220,7 +1220,7 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 49ce33ec96..0f71edcee0 100755 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -1271,7 +1271,7 @@ support@secondlife.com.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index 5a809ea783..c4b1530b2b 100755 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -1271,7 +1271,7 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 19863dd845..894e368427 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -104,26 +104,37 @@ class ViewerManifest(LLManifest):                      self.path("dictionaries")                      self.end_prefix(pkgdir) -                # CHOP-955: If we have "sourceid" in the build process -                # environment, generate it into settings_install.xml. -                try: -                    sourceid = os.environ["sourceid"] -                except KeyError: -                    # no sourceid, no settings_install.xml file -                    pass -                else: -                    if sourceid: -                        # Single-entry subset of the LLSD content of settings.xml -                        content = dict(sourceid=dict(Comment='Identify referring agency to Linden web servers', -                                                     Persist=1, -                                                     Type='String', -                                                     Value=sourceid)) -                        # put_in_file(src=) need not be an actual pathname; it -                        # only needs to be non-empty -                        settings_install = self.put_in_file(llsd.format_pretty_xml(content), -                                                            "settings_install.xml", -                                                            src="environment") -                        print "Put sourceid '%s' in %s" % (sourceid, settings_install) +                # CHOP-955: If we have "sourceid" or "viewer_channel" in the +                # build process environment, generate it into +                # settings_install.xml. +                settings_template = dict( +                    sourceid=dict(Comment='Identify referring agency to Linden web servers', +                                  Persist=1, +                                  Type='String', +                                  Value=''), +                    CmdLineChannel=dict(Comment='Command line specified channel name', +                                        Persist=0, +                                        Type='String', +                                        Value='')) +                settings_install = {} +                for key, setting in (("sourceid", "sourceid"), +                                     ("channel", "CmdLineChannel")): +                    if key in self.args: +                        # only set if value is non-empty +                        if self.args[key]: +                            # copy corresponding setting from settings_template +                            settings_install[setting] = settings_template[setting].copy() +                            # then fill in Value +                            settings_install[setting]["Value"] = self.args[key] +                            print "Put %s '%s' in settings_install.xml" % (setting, self.args[key]) + +                # did we actually copy anything into settings_install dict? +                if settings_install: +                    # put_in_file(src=) need not be an actual pathname; it +                    # only needs to be non-empty +                    self.put_in_file(llsd.format_pretty_xml(settings_install), +                                     "settings_install.xml", +                                     src="environment")                  self.end_prefix("app_settings") @@ -611,6 +622,9 @@ class WindowsManifest(ViewerManifest):              installer_file = self.args['installer_name']          else:              installer_file = installer_file % substitution_strings +        if len(self.args['package_id']) > 0: +            installer_file = installer_file.replace(self.args['package_id'], "") +            installer_file = installer_file.replace(".exe", self.args['package_id'] + ".exe")          substitution_strings['installer_file'] = installer_file          tempfile = "secondlife_setup_tmp.nsi" @@ -838,7 +852,9 @@ class DarwinManifest(ViewerManifest):          volname="Second Life Installer"  # DO NOT CHANGE without understanding comment above -        if self.default_channel(): +        if len(self.args['package_id']) > 0: +            imagename = imagename + self.args['package_id'] +        elif self.default_channel():              if not self.default_grid():                  # beta case                  imagename = imagename + '_' + self.args['grid'].upper() @@ -851,7 +867,7 @@ class DarwinManifest(ViewerManifest):          # make sure we don't have stale files laying about          self.remove(sparsename, finalname) -        self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % { +        self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 1000 -layout SPUD' % {                  'sparse':sparsename,                  'vol':volname}) @@ -926,6 +942,7 @@ class DarwinManifest(ViewerManifest):          print "Converting temp disk image to final disk image"          self.run_command('hdiutil convert %(sparse)r -format UDZO -imagekey zlib-level=9 -o %(final)r' % {'sparse':sparsename, 'final':finalname}) +        self.run_command('hdiutil internet-enable -yes %(final)r' % {'final':finalname})          # get rid of the temp file          self.package_file = finalname          self.remove(sparsename) @@ -998,6 +1015,7 @@ class LinuxManifest(ViewerManifest):                      installer_name += '_' + self.args['grid'].upper()              else:                  installer_name += '_' + self.channel_oneword().upper() +        installer_name = installer_name + self.args['package_id']          self.strip_binaries() diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index d6e06e5316..dc8ff2f644 100755 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -79,7 +79,6 @@ void LLUpdateChecker::checkVersion(std::string const & urlBase,  //----------------------------------------------------------------------------- -const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0";  const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1"; @@ -150,40 +149,11 @@ void LLUpdateChecker::Implementation::completed(U32 status,  			server_error += content["error_text"].asString();  		} -		if (status == 404) -		{ -			if (mProtocol == sProtocolVersion) -			{ -				mProtocol = sLegacyProtocolVersion; -				std::string retryUrl = buildUrl(mUrlBase, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); - -				LL_WARNS("UpdaterService") -					<< "update response using " << sProtocolVersion -					<< " was HTTP 404 (" << server_error -					<< "); retry with legacy protocol " << mProtocol -					<< "\n at " << retryUrl -					<< LL_ENDL; -	 -				mHttpClient.get(retryUrl, this); -			} -			else -			{ -				LL_WARNS("UpdaterService") -					<< "update response using " << sLegacyProtocolVersion -					<< " was 404 (" << server_error -					<< "); request failed" -					<< LL_ENDL; -				mClient.error(reason); -			} -		} -		else -		{ -			LL_WARNS("UpdaterService") << "response error " << status -									   << " " << reason -									   << " (" << server_error << ")" -									   << LL_ENDL; -			mClient.error(reason); -		} +		LL_WARNS("UpdaterService") << "response error " << status +								   << " " << reason +								   << " (" << server_error << ")" +								   << LL_ENDL; +		mClient.error(reason);  	}  	else  	{ @@ -213,11 +183,8 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBas  	path.append(channel);  	path.append(version);  	path.append(platform); -	if (mProtocol != sLegacyProtocolVersion) -	{ -		path.append(platform_version); -		path.append(willing_to_test ? "testok" : "testno"); -		path.append((char*)uniqueid); -	} +	path.append(platform_version); +	path.append(willing_to_test ? "testok" : "testno"); +	path.append((char*)uniqueid);  	return LLURI::buildHTTP(urlBase, path).asString();  } | 
