Merge latest viewer-release with FBC
commit
64c5afa196
1
.hgtags
1
.hgtags
|
|
@ -467,3 +467,4 @@ fe4f7c5e9fd27e09d03deb1cc9ab3e5093f6309e 3.6.3-release
|
|||
bf6d453046011a11de2643fac610cc5258650f82 3.6.5-release
|
||||
ae457ece77001767ae9613148c495e7b98cc0f4a 3.6.7-release
|
||||
d40c66e410741de7e90b1ed6dac28dd8a2d7e1f6 3.6.8-release
|
||||
70eda3721d36df3e00730629c42a1304e5bc65b8 3.6.9-release
|
||||
|
|
|
|||
15
BuildParams
15
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
28
build.sh
28
build.sh
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,7 +689,9 @@ Kagehi Kohn
|
|||
Kaimen Takahe
|
||||
Katharine Berry
|
||||
STORM-1900
|
||||
OPEN-149
|
||||
STORM-1940
|
||||
OPEN-149
|
||||
STORM-1941
|
||||
Keklily Longfall
|
||||
Ken Lavender
|
||||
|
|
@ -928,7 +940,9 @@ Nicky Dasmijn
|
|||
STORM-1936
|
||||
BUG-3605
|
||||
CHUIBUG-197
|
||||
OPEN-187
|
||||
STORM-1937
|
||||
OPEN-187
|
||||
Nicky Perian
|
||||
OPEN-1
|
||||
STORM-1087
|
||||
|
|
@ -1125,6 +1139,7 @@ Slee Mayo
|
|||
snowy Sidran
|
||||
Sovereign Engineer
|
||||
MAINT-2334
|
||||
OPEN-189
|
||||
SpacedOut Frye
|
||||
VWR-34
|
||||
VWR-45
|
||||
|
|
@ -1293,6 +1308,7 @@ Westley Streeter
|
|||
Whimsy Winx
|
||||
Whirly Fizzle
|
||||
STORM-1895
|
||||
VWR-29543
|
||||
MAINT-873
|
||||
STORM-1930
|
||||
Whoops Babii
|
||||
|
|
@ -1356,6 +1372,7 @@ YongYong Francois
|
|||
Zak Westminster
|
||||
Zai Lynch
|
||||
VWR-19505
|
||||
STORM-1902
|
||||
Zana Kohime
|
||||
Zaren Alexander
|
||||
Zarkonnen Decosta
|
||||
|
|
|
|||
|
|
@ -63,10 +63,11 @@ add_subdirectory(${VIEWER_PREFIX}test)
|
|||
# viewer media plugins
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
|
||||
|
||||
# llplugin testbed code (is this the right way to include it?)
|
||||
if (LL_TESTS AND NOT LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
|
||||
endif (LL_TESTS AND NOT LINUX)
|
||||
# llplugin testbed code (is this the right way to include it?)
|
||||
if (LL_TESTS AND NOT LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
|
||||
add_subdirectory(${VIEWER_PREFIX}test_apps/llfbconnecttest)
|
||||
endif (LL_TESTS AND NOT LINUX)
|
||||
|
||||
if (LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
|
||||
|
|
|
|||
|
|
@ -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} )
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -217,7 +217,8 @@ static void request(
|
|||
Injector* body_injector,
|
||||
LLCurl::ResponderPtr responder,
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
|
||||
const LLSD& headers = LLSD()
|
||||
const LLSD& headers = LLSD(),
|
||||
bool follow_redirects = true
|
||||
)
|
||||
{
|
||||
if (!LLHTTPClient::hasPump())
|
||||
|
|
@ -231,7 +232,7 @@ static void request(
|
|||
}
|
||||
LLPumpIO::chain_t chain;
|
||||
|
||||
LLURLRequest* req = new LLURLRequest(method, url);
|
||||
LLURLRequest* req = new LLURLRequest(method, url, follow_redirects);
|
||||
if(!req->isValid())//failed
|
||||
{
|
||||
if (responder)
|
||||
|
|
@ -334,7 +335,8 @@ void LLHTTPClient::getByteRange(
|
|||
S32 bytes,
|
||||
ResponderPtr responder,
|
||||
const LLSD& hdrs,
|
||||
const F32 timeout)
|
||||
const F32 timeout,
|
||||
bool follow_redirects /* = true */)
|
||||
{
|
||||
LLSD headers = hdrs;
|
||||
if(offset > 0 || bytes > 0)
|
||||
|
|
@ -342,37 +344,42 @@ void LLHTTPClient::getByteRange(
|
|||
std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
|
||||
headers["Range"] = range;
|
||||
}
|
||||
request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers);
|
||||
request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
|
||||
}
|
||||
|
||||
void LLHTTPClient::head(
|
||||
const std::string& url,
|
||||
ResponderPtr responder,
|
||||
const LLSD& headers,
|
||||
const F32 timeout)
|
||||
const F32 timeout,
|
||||
bool follow_redirects /* = true */)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers);
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
|
||||
}
|
||||
|
||||
void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout)
|
||||
void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout,
|
||||
bool follow_redirects /* = true */)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers);
|
||||
request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
|
||||
}
|
||||
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout)
|
||||
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers,
|
||||
const F32 timeout, bool follow_redirects /* = true */)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers);
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
|
||||
}
|
||||
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout)
|
||||
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout,
|
||||
bool follow_redirects /* = true */)
|
||||
{
|
||||
getHeaderOnly(url, responder, LLSD(), timeout);
|
||||
getHeaderOnly(url, responder, LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
|
||||
void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers, const F32 timeout)
|
||||
void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers,
|
||||
const F32 timeout, bool follow_redirects /* = true */)
|
||||
{
|
||||
LLURI uri;
|
||||
|
||||
uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query);
|
||||
get(uri.asString(), responder, headers, timeout);
|
||||
get(uri.asString(), responder, headers, timeout, follow_redirects);
|
||||
}
|
||||
|
||||
// A simple class for managing data returned from a curl http request.
|
||||
|
|
|
|||
|
|
@ -63,10 +63,15 @@ public:
|
|||
const std::string& url,
|
||||
ResponderPtr,
|
||||
const LLSD& headers = LLSD(),
|
||||
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
|
||||
static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr, const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
|
||||
static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
|
||||
static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
|
||||
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
|
||||
bool follow_redirects = true);
|
||||
static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr,
|
||||
const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
|
||||
bool follow_redirects = true);
|
||||
static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(),
|
||||
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);
|
||||
static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(),
|
||||
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);
|
||||
|
||||
static void put(
|
||||
const std::string& url,
|
||||
|
|
@ -74,8 +79,10 @@ public:
|
|||
ResponderPtr,
|
||||
const LLSD& headers = LLSD(),
|
||||
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
|
||||
static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
|
||||
static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
|
||||
static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
|
||||
bool follow_redirects = true);
|
||||
static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers,
|
||||
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);
|
||||
|
||||
static void post(
|
||||
const std::string& url,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -150,16 +150,19 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
|
|||
return VERBS[action];
|
||||
}
|
||||
|
||||
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) :
|
||||
mAction(action)
|
||||
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, bool follow_redirects /* = true */) :
|
||||
mAction(action),
|
||||
mFollowRedirects(follow_redirects)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
LLURLRequest::LLURLRequest(
|
||||
LLURLRequest::ERequestAction action,
|
||||
const std::string& url) :
|
||||
mAction(action)
|
||||
const std::string& url,
|
||||
bool follow_redirects /* = true */) :
|
||||
mAction(action),
|
||||
mFollowRedirects(follow_redirects)
|
||||
{
|
||||
initialize();
|
||||
setURL(url);
|
||||
|
|
@ -479,12 +482,18 @@ bool LLURLRequest::configure()
|
|||
case HTTP_HEAD:
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_HEADER, 1);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_NOBODY, 1);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
if (mFollowRedirects)
|
||||
{
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
}
|
||||
rv = true;
|
||||
break;
|
||||
case HTTP_GET:
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_HTTPGET, 1);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
if (mFollowRedirects)
|
||||
{
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
}
|
||||
|
||||
// Set Accept-Encoding to allow response compression
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public:
|
|||
*
|
||||
* @param action One of the ERequestAction enumerations.
|
||||
*/
|
||||
LLURLRequest(ERequestAction action);
|
||||
LLURLRequest(ERequestAction action, bool follow_redirects = true);
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
|
|
@ -103,7 +103,7 @@ public:
|
|||
* @param action One of the ERequestAction enumerations.
|
||||
* @param url The url of the request. It should already be encoded.
|
||||
*/
|
||||
LLURLRequest(ERequestAction action, const std::string& url);
|
||||
LLURLRequest(ERequestAction action, const std::string& url, bool follow_redirects = true);
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
|
|
@ -219,10 +219,11 @@ protected:
|
|||
};
|
||||
EState mState;
|
||||
ERequestAction mAction;
|
||||
bool mFollowRedirects;
|
||||
LLURLRequestDetail* mDetail;
|
||||
LLIOPipe::ptr_t mCompletionCallback;
|
||||
S32 mRequestTransferedBytes;
|
||||
S32 mResponseTransferedBytes;
|
||||
S32 mRequestTransferedBytes;
|
||||
S32 mResponseTransferedBytes;
|
||||
|
||||
static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param);
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,16 @@ std::string LLPluginCookieStore::Cookie::getKey() const
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::Cookie::getDomain() const
|
||||
{
|
||||
std::string result;
|
||||
if(mDomainEnd > mDomainStart)
|
||||
{
|
||||
result += mCookie.substr(mDomainStart, mDomainEnd - mDomainStart);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LLPluginCookieStore::Cookie::parse(const std::string &host)
|
||||
{
|
||||
bool first_field = true;
|
||||
|
|
@ -662,3 +672,21 @@ void LLPluginCookieStore::removeCookie(const std::string &key)
|
|||
}
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::removeCookiesByDomain(const std::string &domain)
|
||||
{
|
||||
cookie_map_t::iterator iter = mCookies.begin();
|
||||
while(iter != mCookies.end())
|
||||
{
|
||||
if(iter->second->getDomain() == domain)
|
||||
{
|
||||
cookie_map_t::iterator doErase = iter;
|
||||
iter++;
|
||||
delete doErase->second;
|
||||
mCookies.erase(doErase);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ public:
|
|||
// quote or unquote a string as per the definition of 'quoted-string' in rfc2616
|
||||
static std::string quoteString(const std::string &s);
|
||||
static std::string unquoteString(const std::string &s);
|
||||
|
||||
void removeCookiesByDomain(const std::string &domain);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -79,6 +81,7 @@ private:
|
|||
|
||||
// Construct a string from the cookie that uniquely represents it, to be used as a key in a std::map.
|
||||
std::string getKey() const;
|
||||
std::string getDomain() const;
|
||||
|
||||
const std::string &getCookie() const { return mCookie; };
|
||||
bool isSessionCookie() const { return mDate.isNull(); };
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ public:
|
|||
|
||||
virtual void draw();
|
||||
virtual void onCommit();
|
||||
/*virtual*/ void onFocusReceived();
|
||||
/*virtual*/ void onFocusLost();
|
||||
/*virtual*/ void onFocusReceived();
|
||||
/*virtual*/ void onFocusLost();
|
||||
|
||||
void enableSingleLineMode(bool single_line_mode);
|
||||
boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
// mini-map floater, etc.
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llviewereventrecorder.h"
|
||||
#include "llfloater.h"
|
||||
|
||||
#include "llfocusmgr.h"
|
||||
|
|
@ -509,8 +509,8 @@ LLFloater::~LLFloater()
|
|||
|
||||
if( gFocusMgr.childHasKeyboardFocus(this))
|
||||
{
|
||||
// Just in case we might still have focus here, release it.
|
||||
releaseFocus();
|
||||
// Just in case we might still have focus here, release it.
|
||||
releaseFocus();
|
||||
}
|
||||
|
||||
// This is important so that floaters with persistent rects (i.e., those
|
||||
|
|
@ -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;
|
||||
|
|
@ -1335,7 +1339,7 @@ void LLFloater::setFocus( BOOL b )
|
|||
{
|
||||
return;
|
||||
}
|
||||
LLUICtrl* last_focus = gFocusMgr.getLastFocusForGroup(this);
|
||||
LLView* last_focus = gFocusMgr.getLastFocusForGroup(this);
|
||||
// a descendent already has focus
|
||||
BOOL child_had_focus = hasFocus();
|
||||
|
||||
|
|
@ -1542,6 +1546,17 @@ BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks)
|
|||
return TRUE;//always
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ void LLFocusMgr::setAppHasFocus(BOOL focus)
|
|||
mAppHasFocus = focus;
|
||||
}
|
||||
|
||||
LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const
|
||||
LLView* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const
|
||||
{
|
||||
if (subtree_root)
|
||||
{
|
||||
|
|
@ -477,7 +477,7 @@ LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const
|
|||
if (found_it != mImpl->mFocusHistory.end())
|
||||
{
|
||||
// found last focus for this subtree
|
||||
return static_cast<LLUICtrl*>(found_it->second.get());
|
||||
return found_it->second.get();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ public:
|
|||
void triggerFocusFlash();
|
||||
BOOL getAppHasFocus() const { return mAppHasFocus; }
|
||||
void setAppHasFocus(BOOL focus);
|
||||
LLUICtrl* getLastFocusForGroup(LLView* subtree_root) const;
|
||||
LLView* getLastFocusForGroup(LLView* subtree_root) const;
|
||||
void clearLastFocusForGroup(LLView* subtree_root);
|
||||
|
||||
// If setKeyboardFocus(NULL) is called, and there is a non-NULL default
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ LLFolderView::LLFolderView(const Params& p)
|
|||
mAutoOpenCandidate = NULL;
|
||||
mAutoOpenTimer.stop();
|
||||
mKeyboardSelection = FALSE;
|
||||
mIndentation = p.folder_indentation;
|
||||
mIndentation = getParentFolder() ? getParentFolder()->getIndentation() + mLocalIndentation : 0;
|
||||
|
||||
//clear label
|
||||
// go ahead and render root folder as usual
|
||||
|
|
@ -1613,7 +1613,7 @@ void LLFolderView::update()
|
|||
{
|
||||
getFolderViewModel()->getFilter().clearModified();
|
||||
}
|
||||
|
||||
|
||||
// automatically show matching items, and select first one if we had a selection
|
||||
if (mNeedsAutoSelect)
|
||||
{
|
||||
|
|
@ -1653,13 +1653,13 @@ void LLFolderView::update()
|
|||
|
||||
BOOL is_visible = isInVisibleChain();
|
||||
|
||||
// Puts folders/items in proper positions
|
||||
//Puts folders/items in proper positions
|
||||
// arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849)
|
||||
// It also handles the open/close folder animation
|
||||
if (is_visible)
|
||||
if ( is_visible )
|
||||
{
|
||||
sanitizeSelection();
|
||||
if (needsArrange())
|
||||
if( needsArrange() )
|
||||
{
|
||||
S32 height = 0;
|
||||
S32 width = 0;
|
||||
|
|
|
|||
|
|
@ -307,7 +307,12 @@ std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const
|
|||
// addToFolder() returns TRUE if it succeeds. FALSE otherwise
|
||||
void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder)
|
||||
{
|
||||
folder->addItem(this);
|
||||
folder->addItem(this);
|
||||
|
||||
// Compute indentation since parent folder changed
|
||||
mIndentation = (getParentFolder())
|
||||
? getParentFolder()->getIndentation() + mLocalIndentation
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -940,6 +945,11 @@ LLFolderViewFolder::~LLFolderViewFolder( void )
|
|||
void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)
|
||||
{
|
||||
folder->addFolder(this);
|
||||
|
||||
// Compute indentation since parent folder changed
|
||||
mIndentation = (getParentFolder())
|
||||
? getParentFolder()->getIndentation() + mLocalIndentation
|
||||
: 0;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
|
||||
|
|
@ -1109,7 +1119,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
|
|||
|
||||
BOOL LLFolderViewFolder::needsArrange()
|
||||
{
|
||||
return mLastArrangeGeneration < getRoot()->getArrangeGeneration();
|
||||
return mLastArrangeGeneration < getRoot()->getArrangeGeneration();
|
||||
}
|
||||
|
||||
// Passes selection information on to children and record selection
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
#include "linden_common.h"
|
||||
|
||||
#include "lltabcontainer.h"
|
||||
|
||||
#include "llviewereventrecorder.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "lllocalcliprect.h"
|
||||
#include "llrect.h"
|
||||
|
|
@ -583,6 +583,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;
|
||||
}
|
||||
|
||||
|
|
@ -634,30 +639,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -681,6 +689,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;
|
||||
}
|
||||
|
||||
|
|
@ -1076,21 +1088,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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ set(viewer_SOURCE_FILES
|
|||
llexpandabletextbox.cpp
|
||||
llexternaleditor.cpp
|
||||
llface.cpp
|
||||
llfacebookconnect.cpp
|
||||
llfasttimerview.cpp
|
||||
llfavoritesbar.cpp
|
||||
llfeaturemanager.cpp
|
||||
|
|
@ -273,6 +274,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloatersettingsdebug.cpp
|
||||
llfloatersidepanelcontainer.cpp
|
||||
llfloatersnapshot.cpp
|
||||
llfloatersocial.cpp
|
||||
llfloatersounddevices.cpp
|
||||
llfloaterspellchecksettings.cpp
|
||||
llfloatertelehub.cpp
|
||||
|
|
@ -508,6 +510,7 @@ set(viewer_SOURCE_FILES
|
|||
llsidetraypanelcontainer.cpp
|
||||
llsky.cpp
|
||||
llslurl.cpp
|
||||
llsnapshotlivepreview.cpp
|
||||
llspatialpartition.cpp
|
||||
llspeakers.cpp
|
||||
llspeakingindicatormanager.cpp
|
||||
|
|
@ -776,6 +779,7 @@ set(viewer_HEADER_FILES
|
|||
llexpandabletextbox.h
|
||||
llexternaleditor.h
|
||||
llface.h
|
||||
llfacebookconnect.h
|
||||
llfasttimerview.h
|
||||
llfavoritesbar.h
|
||||
llfeaturemanager.h
|
||||
|
|
@ -858,6 +862,7 @@ set(viewer_HEADER_FILES
|
|||
llfloatersettingsdebug.h
|
||||
llfloatersidepanelcontainer.h
|
||||
llfloatersnapshot.h
|
||||
llfloatersocial.h
|
||||
llfloatersounddevices.h
|
||||
llfloaterspellchecksettings.h
|
||||
llfloatertelehub.h
|
||||
|
|
@ -1082,6 +1087,7 @@ set(viewer_HEADER_FILES
|
|||
llsidetraypanelcontainer.h
|
||||
llsky.h
|
||||
llslurl.h
|
||||
llsnapshotlivepreview.h
|
||||
llspatialpartition.h
|
||||
llspeakers.h
|
||||
llspeakingindicatormanager.h
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.6.9
|
||||
3.6.10
|
||||
|
|
|
|||
|
|
@ -260,6 +260,16 @@
|
|||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="snapshot"
|
||||
/>
|
||||
<command name="social"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Social_Icon"
|
||||
label_ref="Command_Social_Label"
|
||||
tooltip_ref="Command_Social_Tooltip"
|
||||
execute_function="Floater.ToggleOrBringToFront"
|
||||
execute_parameters="social"
|
||||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="social"
|
||||
/>
|
||||
<command name="speak"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Speak_Icon"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -10455,6 +10465,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>
|
||||
|
|
@ -13095,6 +13116,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SocialPhotoResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Default resolution when sharing photo using the social floater</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>[i800,i600]</string>
|
||||
</map>
|
||||
<key>sourceid</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
<command name="speak"/>
|
||||
<command name="destinations"/>
|
||||
<command name="people"/>
|
||||
<command name="social"/>
|
||||
<command name="profile"/>
|
||||
<command name="move"/>
|
||||
<command name="view"/>
|
||||
|
|
|
|||
|
|
@ -112,6 +112,11 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const
|
|||
case LOCATION_FORMAT_NORMAL:
|
||||
buffer = llformat("%s", region_name.c_str());
|
||||
break;
|
||||
case LOCATION_FORMAT_NORMAL_COORDS:
|
||||
buffer = llformat("%s (%d, %d, %d)",
|
||||
region_name.c_str(),
|
||||
pos_x, pos_y, pos_z);
|
||||
break;
|
||||
case LOCATION_FORMAT_NO_COORDS:
|
||||
buffer = llformat("%s%s%s",
|
||||
region_name.c_str(),
|
||||
|
|
@ -143,6 +148,11 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const
|
|||
case LOCATION_FORMAT_NORMAL:
|
||||
buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str());
|
||||
break;
|
||||
case LOCATION_FORMAT_NORMAL_COORDS:
|
||||
buffer = llformat("%s (%d, %d, %d)",
|
||||
parcel_name.c_str(),
|
||||
pos_x, pos_y, pos_z);
|
||||
break;
|
||||
case LOCATION_FORMAT_NO_MATURITY:
|
||||
buffer = llformat("%s, %s (%d, %d, %d)",
|
||||
parcel_name.c_str(),
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public:
|
|||
enum ELocationFormat
|
||||
{
|
||||
LOCATION_FORMAT_NORMAL, // Parcel
|
||||
LOCATION_FORMAT_NORMAL_COORDS, // Parcel (x, y, z)
|
||||
LOCATION_FORMAT_LANDMARK, // Parcel, Region
|
||||
LOCATION_FORMAT_NO_MATURITY, // Parcel, Region (x, y, z)
|
||||
LOCATION_FORMAT_NO_COORDS, // Parcel, Region - Maturity
|
||||
|
|
|
|||
|
|
@ -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,9 +2578,13 @@ bool LLAppViewer::initConfiguration()
|
|||
}
|
||||
}
|
||||
|
||||
if (clp.hasOption("logevents")) {
|
||||
LLViewerEventRecorder::instance().setEventLoggingOn();
|
||||
}
|
||||
|
||||
std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
|
||||
if(! CmdLineChannel.empty())
|
||||
{
|
||||
{
|
||||
LLVersionInfo::resetChannel(CmdLineChannel);
|
||||
}
|
||||
|
||||
|
|
@ -2589,16 +2596,16 @@ bool LLAppViewer::initConfiguration()
|
|||
LLFastTimer::sLog = TRUE;
|
||||
LLFastTimer::sLogName = std::string("performance");
|
||||
}
|
||||
|
||||
|
||||
std::string test_name(gSavedSettings.getString("LogMetrics"));
|
||||
if (! test_name.empty())
|
||||
{
|
||||
LLFastTimer::sMetricLog = TRUE ;
|
||||
{
|
||||
LLFastTimer::sMetricLog = TRUE ;
|
||||
// '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test
|
||||
// In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)
|
||||
llinfos << "'--logmetrics' argument : " << test_name << llendl;
|
||||
LLFastTimer::sLogName = test_name;
|
||||
}
|
||||
LLFastTimer::sLogName = test_name;
|
||||
}
|
||||
|
||||
if (clp.hasOption("graphicslevel"))
|
||||
{
|
||||
|
|
@ -2607,14 +2614,14 @@ bool LLAppViewer::initConfiguration()
|
|||
// that value for validity.
|
||||
U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance");
|
||||
if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel))
|
||||
{
|
||||
{
|
||||
// graphicslevel is valid: save it and engage it later. Capture
|
||||
// the requested value separately from the settings variable
|
||||
// because, if this is the first run, LLViewerWindow's constructor
|
||||
// will call LLFeatureManager::applyRecommendedSettings(), which
|
||||
// overwrites this settings variable!
|
||||
mForceGraphicsLevel = graphicslevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance");
|
||||
|
|
@ -2645,16 +2652,32 @@ bool LLAppViewer::initConfiguration()
|
|||
// What can happen is that someone can use IE (or potentially
|
||||
// other browsers) and do the rough equivalent of command
|
||||
// injection and steal passwords. Phoenix. SL-55321
|
||||
LLSLURL start_slurl;
|
||||
std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation"));
|
||||
if(! CmdLineLoginLocation.empty())
|
||||
{
|
||||
LLSLURL start_slurl(CmdLineLoginLocation);
|
||||
{
|
||||
start_slurl = CmdLineLoginLocation;
|
||||
LLStartUp::setStartSLURL(start_slurl);
|
||||
if(start_slurl.getType() == LLSLURL::LOCATION)
|
||||
{
|
||||
LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
|
||||
}
|
||||
}
|
||||
|
||||
//RN: if we received a URL, hand it off to the existing instance.
|
||||
// don't call anotherInstanceRunning() when doing URL handoff, as
|
||||
// it relies on checking a marker file which will not work when running
|
||||
// out of different directories
|
||||
|
||||
if (start_slurl.isValid() &&
|
||||
(gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
|
||||
{
|
||||
if (sendURLToOtherInstance(start_slurl.getSLURLString()))
|
||||
{
|
||||
// successfully handed off URL to existing instance, exit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
|
||||
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
|
||||
|
|
@ -2795,7 +2818,7 @@ bool LLAppViewer::initConfiguration()
|
|||
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
|
||||
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
|
||||
}
|
||||
else if ((clp.hasOption("login") || clp.hasOption("autologin"))
|
||||
else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
|
||||
&& gSavedSettings.getString("CmdLineLoginLocation").empty())
|
||||
{
|
||||
// If automatic login from command line with --login switch
|
||||
|
|
@ -3179,7 +3202,7 @@ bool LLAppViewer::initWindow()
|
|||
LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);
|
||||
gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);
|
||||
}
|
||||
|
||||
|
||||
// Set this flag in case we crash while initializing GL
|
||||
gSavedSettings.setBOOL("RenderInitError", TRUE);
|
||||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -110,6 +110,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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,577 @@
|
|||
/**
|
||||
* @file llfacebookconnect.h
|
||||
* @author Merov, Cho, Gil
|
||||
* @brief Connection to Facebook Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* 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 "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfacebookconnect.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
#include "llcommandhandler.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llimagejpeg.h"
|
||||
#include "lltrans.h"
|
||||
#include "llevents.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
#include "llfloaterwebcontent.h"
|
||||
#include "llfloaterreg.h"
|
||||
|
||||
boost::scoped_ptr<LLEventPump> LLFacebookConnect::sStateWatcher(new LLEventStream("FacebookConnectState"));
|
||||
boost::scoped_ptr<LLEventPump> LLFacebookConnect::sInfoWatcher(new LLEventStream("FacebookConnectInfo"));
|
||||
boost::scoped_ptr<LLEventPump> LLFacebookConnect::sContentWatcher(new LLEventStream("FacebookConnectContent"));
|
||||
|
||||
// Local functions
|
||||
void log_facebook_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
|
||||
{
|
||||
// Note: 302 (redirect) is *not* an error that warrants logging
|
||||
if (status != 302)
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void toast_user_for_success()
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("facebook_post_success");
|
||||
LLNotificationsUtil::add("FacebookConnect", args);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookConnectHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
LLFacebookConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { }
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
|
||||
{
|
||||
if (tokens.size() > 0)
|
||||
{
|
||||
if (tokens[0].asString() == "connect")
|
||||
{
|
||||
// this command probably came from the fbc_web browser, so close it
|
||||
LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
|
||||
if (fbc_web)
|
||||
{
|
||||
fbc_web->closeFloater();
|
||||
}
|
||||
|
||||
// connect to facebook
|
||||
if (query_map.has("code"))
|
||||
{
|
||||
LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
LLFacebookConnectHandler gFacebookConnectHandler;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookConnectResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFacebookConnectResponder);
|
||||
public:
|
||||
|
||||
LLFacebookConnectResponder()
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
|
||||
}
|
||||
|
||||
virtual void completed(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (isGoodStatus(status))
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Connect successful. content: " << content << LL_ENDL;
|
||||
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
|
||||
}
|
||||
else if (status != 302)
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
|
||||
log_facebook_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
void completedHeader(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (status == 302)
|
||||
{
|
||||
LLFacebookConnect::instance().openFacebookWeb(content["location"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookShareResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFacebookShareResponder);
|
||||
public:
|
||||
|
||||
LLFacebookShareResponder()
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTING);
|
||||
}
|
||||
|
||||
virtual void completed(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (isGoodStatus(status))
|
||||
{
|
||||
toast_user_for_success();
|
||||
LL_DEBUGS("FacebookConnect") << "Post successful. content: " << content << LL_ENDL;
|
||||
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED);
|
||||
}
|
||||
else if (status == 404)
|
||||
{
|
||||
LLFacebookConnect::instance().connectToFacebook();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POST_FAILED);
|
||||
log_facebook_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
void completedHeader(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (status == 302)
|
||||
{
|
||||
LLFacebookConnect::instance().openFacebookWeb(content["location"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookDisconnectResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFacebookDisconnectResponder);
|
||||
public:
|
||||
|
||||
LLFacebookDisconnectResponder()
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECTING);
|
||||
}
|
||||
|
||||
void setUserDisconnected()
|
||||
{
|
||||
// Clear data
|
||||
LLFacebookConnect::instance().clearInfo();
|
||||
LLFacebookConnect::instance().clearContent();
|
||||
//Notify state change
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
virtual void completed(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (isGoodStatus(status))
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Disconnect successful. content: " << content << LL_ENDL;
|
||||
setUserDisconnected();
|
||||
|
||||
}
|
||||
//User not found so already disconnected
|
||||
else if(status == 404)
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Already disconnected. content: " << content << LL_ENDL;
|
||||
setUserDisconnected();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
|
||||
log_facebook_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookConnectedResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFacebookConnectedResponder);
|
||||
public:
|
||||
|
||||
LLFacebookConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
|
||||
}
|
||||
|
||||
virtual void completed(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (isGoodStatus(status))
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Connect successful. content: " << content << LL_ENDL;
|
||||
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// show the facebook login page if not connected yet
|
||||
if (status == 404)
|
||||
{
|
||||
if (mAutoConnect)
|
||||
{
|
||||
LLFacebookConnect::instance().connectToFacebook();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
|
||||
log_facebook_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool mAutoConnect;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookInfoResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFacebookInfoResponder);
|
||||
public:
|
||||
|
||||
virtual void completed(U32 status, const std::string& reason, const LLSD& info)
|
||||
{
|
||||
if (isGoodStatus(status))
|
||||
{
|
||||
llinfos << "Facebook: Info received" << llendl;
|
||||
LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << info << LL_ENDL;
|
||||
LLFacebookConnect::instance().storeInfo(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_facebook_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
void completedHeader(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (status == 302)
|
||||
{
|
||||
LLFacebookConnect::instance().openFacebookWeb(content["location"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookFriendsResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFacebookFriendsResponder);
|
||||
public:
|
||||
|
||||
virtual void completed(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (isGoodStatus(status))
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Getting Facebook friends successful. content: " << content << LL_ENDL;
|
||||
LLFacebookConnect::instance().storeContent(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_facebook_connect_error("Friends", status, reason, content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
void completedHeader(U32 status, const std::string& reason, const LLSD& content)
|
||||
{
|
||||
if (status == 302)
|
||||
{
|
||||
LLFacebookConnect::instance().openFacebookWeb(content["location"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
LLFacebookConnect::LLFacebookConnect()
|
||||
: mConnectionState(FB_NOT_CONNECTED),
|
||||
mConnected(false),
|
||||
mInfo(),
|
||||
mContent(),
|
||||
mRefreshInfo(false),
|
||||
mRefreshContent(false),
|
||||
mReadFromMaster(false)
|
||||
{
|
||||
}
|
||||
|
||||
void LLFacebookConnect::openFacebookWeb(std::string url)
|
||||
{
|
||||
// Open the URL in an internal browser window without navigation UI
|
||||
LLFloaterWebContent::Params p;
|
||||
p.url(url).show_chrome(true);
|
||||
p.url(url).allow_address_entry(false);
|
||||
p.url(url).allow_back_forward_navigation(false);
|
||||
p.url(url).trusted_content(true);
|
||||
LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
|
||||
//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
|
||||
//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event
|
||||
//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
|
||||
//fbc_web floater contains the "webbrowser" panel. JIRA: ACME-744
|
||||
gFocusMgr.setKeyboardFocus( floater );
|
||||
|
||||
//LLUrlAction::openURLExternal(url);
|
||||
}
|
||||
|
||||
std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, bool include_read_from_master)
|
||||
{
|
||||
std::string url = gAgent.getRegion()->getCapability("FacebookConnect");
|
||||
url += route;
|
||||
|
||||
if (include_read_from_master && mReadFromMaster)
|
||||
{
|
||||
url += "?read_from_master=true";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state)
|
||||
{
|
||||
LLSD body;
|
||||
if (!auth_code.empty())
|
||||
body["code"] = auth_code;
|
||||
if (!auth_state.empty())
|
||||
body["state"] = auth_state;
|
||||
|
||||
LLHTTPClient::put(getFacebookConnectURL("/connection"), body, new LLFacebookConnectResponder());
|
||||
}
|
||||
|
||||
void LLFacebookConnect::disconnectFromFacebook()
|
||||
{
|
||||
LLHTTPClient::del(getFacebookConnectURL("/connection"), new LLFacebookDisconnectResponder());
|
||||
}
|
||||
|
||||
void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect)
|
||||
{
|
||||
const bool follow_redirects = false;
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
|
||||
LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect),
|
||||
LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
|
||||
void LLFacebookConnect::loadFacebookInfo()
|
||||
{
|
||||
if(mRefreshInfo)
|
||||
{
|
||||
const bool follow_redirects = false;
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
|
||||
LLHTTPClient::get(getFacebookConnectURL("/info", true), new LLFacebookInfoResponder(),
|
||||
LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFacebookConnect::loadFacebookFriends()
|
||||
{
|
||||
if(mRefreshContent)
|
||||
{
|
||||
const bool follow_redirects = false;
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
|
||||
LLHTTPClient::get(getFacebookConnectURL("/friends", true), new LLFacebookFriendsResponder(),
|
||||
LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name, const std::string& description, const std::string& image, const std::string& message)
|
||||
{
|
||||
LLSD body;
|
||||
if (!location.empty())
|
||||
body["location"] = location;
|
||||
if (!name.empty())
|
||||
body["name"] = name;
|
||||
if (!description.empty())
|
||||
body["description"] = description;
|
||||
if (!image.empty())
|
||||
body["image"] = image;
|
||||
if (!message.empty())
|
||||
body["message"] = message;
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::post(getFacebookConnectURL("/share/checkin", true), body, new LLFacebookShareResponder());
|
||||
}
|
||||
|
||||
void LLFacebookConnect::sharePhoto(const std::string& image_url, const std::string& caption)
|
||||
{
|
||||
LLSD body;
|
||||
body["image"] = image_url;
|
||||
body["caption"] = caption;
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::post(getFacebookConnectURL("/share/photo", true), body, new LLFacebookShareResponder());
|
||||
}
|
||||
|
||||
void LLFacebookConnect::sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption)
|
||||
{
|
||||
std::string imageFormat;
|
||||
if (dynamic_cast<LLImagePNG*>(image.get()))
|
||||
{
|
||||
imageFormat = "png";
|
||||
}
|
||||
else if (dynamic_cast<LLImageJPEG*>(image.get()))
|
||||
{
|
||||
imageFormat = "jpg";
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Image to upload is not a PNG or JPEG" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
// All this code is mostly copied from LLWebProfile::post()
|
||||
const std::string boundary = "----------------------------0123abcdefab";
|
||||
|
||||
LLSD headers;
|
||||
headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
|
||||
|
||||
std::ostringstream body;
|
||||
|
||||
// *NOTE: The order seems to matter.
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"caption\"\r\n\r\n"
|
||||
<< caption << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n"
|
||||
<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
|
||||
|
||||
// Insert the image data.
|
||||
// *FIX: Treating this as a string will probably screw it up ...
|
||||
U8* image_data = image->getData();
|
||||
for (S32 i = 0; i < image->getDataSize(); ++i)
|
||||
{
|
||||
body << image_data[i];
|
||||
}
|
||||
|
||||
body << "\r\n--" << boundary << "--\r\n";
|
||||
|
||||
// postRaw() takes ownership of the buffer and releases it later.
|
||||
size_t size = body.str().size();
|
||||
U8 *data = new U8[size];
|
||||
memcpy(data, body.str().data(), size);
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::postRaw(getFacebookConnectURL("/share/photo", true), data, size, new LLFacebookShareResponder(), headers);
|
||||
}
|
||||
|
||||
void LLFacebookConnect::updateStatus(const std::string& message)
|
||||
{
|
||||
LLSD body;
|
||||
body["message"] = message;
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::post(getFacebookConnectURL("/share/wall", true), body, new LLFacebookShareResponder());
|
||||
}
|
||||
|
||||
void LLFacebookConnect::storeInfo(const LLSD& info)
|
||||
{
|
||||
mInfo = info;
|
||||
mRefreshInfo = false;
|
||||
|
||||
sInfoWatcher->post(info);
|
||||
}
|
||||
|
||||
const LLSD& LLFacebookConnect::getInfo() const
|
||||
{
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::clearInfo()
|
||||
{
|
||||
mInfo = LLSD();
|
||||
}
|
||||
|
||||
void LLFacebookConnect::storeContent(const LLSD& content)
|
||||
{
|
||||
mContent = content;
|
||||
mRefreshContent = false;
|
||||
|
||||
sContentWatcher->post(content);
|
||||
}
|
||||
|
||||
const LLSD& LLFacebookConnect::getContent() const
|
||||
{
|
||||
return mContent;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::clearContent()
|
||||
{
|
||||
mContent = LLSD();
|
||||
}
|
||||
|
||||
void LLFacebookConnect::setDataDirty()
|
||||
{
|
||||
mRefreshInfo = true;
|
||||
mRefreshContent = true;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::setConnectionState(LLFacebookConnect::EConnectionState connection_state)
|
||||
{
|
||||
if(connection_state == FB_CONNECTED)
|
||||
{
|
||||
mReadFromMaster = true;
|
||||
setConnected(true);
|
||||
setDataDirty();
|
||||
}
|
||||
else if(connection_state == FB_NOT_CONNECTED)
|
||||
{
|
||||
setConnected(false);
|
||||
}
|
||||
else if(connection_state == FB_POSTED)
|
||||
{
|
||||
mReadFromMaster = false;
|
||||
}
|
||||
|
||||
if (mConnectionState != connection_state)
|
||||
{
|
||||
LLSD state_info;
|
||||
state_info["enum"] = connection_state;
|
||||
sStateWatcher->post(state_info);
|
||||
}
|
||||
|
||||
mConnectionState = connection_state;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::setConnected(bool connected)
|
||||
{
|
||||
mConnected = connected;
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* @file llfacebookconnect.h
|
||||
* @author Merov, Cho, Gil
|
||||
* @brief Connection to Facebook Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* 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_LLFACEBOOKCONNECT_H
|
||||
#define LL_LLFACEBOOKCONNECT_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
#include "llimage.h"
|
||||
|
||||
class LLEventPump;
|
||||
|
||||
/**
|
||||
* @class LLFacebookConnect
|
||||
*
|
||||
* Manages authentication to, and interaction with, a web service allowing the
|
||||
* the viewer to get Facebook OpenGraph data.
|
||||
*/
|
||||
class LLFacebookConnect : public LLSingleton<LLFacebookConnect>
|
||||
{
|
||||
LOG_CLASS(LLFacebookConnect);
|
||||
public:
|
||||
enum EConnectionState
|
||||
{
|
||||
FB_NOT_CONNECTED = 0,
|
||||
FB_CONNECTION_IN_PROGRESS = 1,
|
||||
FB_CONNECTED = 2,
|
||||
FB_CONNECTION_FAILED = 3,
|
||||
FB_POSTING = 4,
|
||||
FB_POSTED = 5,
|
||||
FB_POST_FAILED = 6,
|
||||
FB_DISCONNECTING = 7,
|
||||
FB_DISCONNECT_FAILED = 8
|
||||
};
|
||||
|
||||
void connectToFacebook(const std::string& auth_code = "", const std::string& auth_state = ""); // Initiate the complete FB connection. Please use checkConnectionToFacebook() in normal use.
|
||||
void disconnectFromFacebook(); // Disconnect from the FBC service.
|
||||
void checkConnectionToFacebook(bool auto_connect = false); // Check if an access token is available on the FBC service. If not, call connectToFacebook().
|
||||
|
||||
void loadFacebookInfo();
|
||||
void loadFacebookFriends();
|
||||
void postCheckin(const std::string& location, const std::string& name, const std::string& description, const std::string& picture, const std::string& message);
|
||||
void sharePhoto(const std::string& image_url, const std::string& caption);
|
||||
void sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption);
|
||||
void updateStatus(const std::string& message);
|
||||
|
||||
void storeInfo(const LLSD& info);
|
||||
const LLSD& getInfo() const;
|
||||
void clearInfo();
|
||||
void storeContent(const LLSD& content);
|
||||
const LLSD& getContent() const;
|
||||
void clearContent();
|
||||
void setDataDirty();
|
||||
|
||||
void setConnectionState(EConnectionState connection_state);
|
||||
void setConnected(bool connected);
|
||||
bool isConnected() { return mConnected; }
|
||||
bool isTransactionOngoing() { return ((mConnectionState == FB_CONNECTION_IN_PROGRESS) || (mConnectionState == FB_POSTING) || (mConnectionState == FB_DISCONNECTING)); }
|
||||
EConnectionState getConnectionState() { return mConnectionState; }
|
||||
|
||||
void openFacebookWeb(std::string url);
|
||||
|
||||
private:
|
||||
friend class LLSingleton<LLFacebookConnect>;
|
||||
|
||||
LLFacebookConnect();
|
||||
~LLFacebookConnect() {};
|
||||
std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false);
|
||||
|
||||
EConnectionState mConnectionState;
|
||||
BOOL mConnected;
|
||||
LLSD mInfo;
|
||||
LLSD mContent;
|
||||
bool mRefreshInfo;
|
||||
bool mRefreshContent;
|
||||
bool mReadFromMaster;
|
||||
|
||||
static boost::scoped_ptr<LLEventPump> sStateWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sInfoWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sContentWatcher;
|
||||
};
|
||||
|
||||
#endif // LL_LLFACEBOOKCONNECT_H
|
||||
|
|
@ -668,10 +668,10 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
|
|||
LLFloater* session_floater = widget->getSessionFloater();
|
||||
if (session_floater != nearby_chat)
|
||||
{
|
||||
widget->setVisibleIfDetached(visible);
|
||||
}
|
||||
widget->setVisibleIfDetached(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, do the normal multifloater show/hide
|
||||
LLMultiFloater::setVisible(visible);
|
||||
|
|
@ -706,13 +706,13 @@ void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& k
|
|||
// Only select other sessions
|
||||
if (!getSelectedSession().isNull())
|
||||
{
|
||||
selectConversationPair(getSelectedSession(), false, take_focus);
|
||||
selectConversationPair(getSelectedSession(), false, take_focus);
|
||||
}
|
||||
if (mInitialized && mIsFirstLaunch)
|
||||
{
|
||||
collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
|
||||
mIsFirstLaunch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::updateResizeLimits()
|
||||
|
|
@ -850,7 +850,7 @@ void LLFloaterIMContainer::assignResizeLimits()
|
|||
|
||||
S32 conv_pane_target_width = is_conv_pane_expanded
|
||||
? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() )
|
||||
: mConversationsPane->getMinDim();
|
||||
: mConversationsPane->getMinDim();
|
||||
|
||||
S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;
|
||||
S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders;
|
||||
|
|
@ -1011,7 +1011,7 @@ void LLFloaterIMContainer::setSortOrder(const LLConversationSort& order)
|
|||
conversation_floater->setSortOrder(order);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gSavedSettings.setU32("ConversationSortOrder", (U32)order);
|
||||
}
|
||||
|
||||
|
|
@ -1096,6 +1096,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);
|
||||
|
|
@ -1198,7 +1202,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
|
|||
}
|
||||
else if("chat_history" == command)
|
||||
{
|
||||
if (selectedIDS.size() > 0)
|
||||
if (selectedIDS.size() > 0)
|
||||
{
|
||||
LLAvatarActions::viewChatHistory(selectedIDS.front());
|
||||
}
|
||||
|
|
@ -1220,7 +1224,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
|
|||
{
|
||||
LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1251,7 +1255,7 @@ void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata)
|
|||
|
||||
if (action == "group_profile")
|
||||
{
|
||||
LLGroupActions::show(mSelectedSession);
|
||||
LLGroupActions::show(mSelectedSession);
|
||||
}
|
||||
else if (action == "activate_group")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,7 +27,6 @@
|
|||
#ifndef LL_LLFLOATERSNAPSHOT_H
|
||||
#define LL_LLFLOATERSNAPSHOT_H
|
||||
|
||||
#include "llimage.h"
|
||||
#include "llfloater.h"
|
||||
|
||||
class LLSpinCtrl;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,920 @@
|
|||
/**
|
||||
* @file llfloatersocial.cpp
|
||||
* @brief Implementation of llfloatersocial
|
||||
* @author Gilbert@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* 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 "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloatersocial.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentui.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lliconctrl.h"
|
||||
#include "llresmgr.h" // LLLocale
|
||||
#include "llsdserialize.h"
|
||||
#include "llloadingindicator.h"
|
||||
#include "llplugincookiestore.h"
|
||||
#include "llslurl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewermedia.h"
|
||||
|
||||
static LLRegisterPanelClassWrapper<LLSocialStatusPanel> t_panel_status("llsocialstatuspanel");
|
||||
static LLRegisterPanelClassWrapper<LLSocialPhotoPanel> t_panel_photo("llsocialphotopanel");
|
||||
static LLRegisterPanelClassWrapper<LLSocialCheckinPanel> t_panel_checkin("llsocialcheckinpanel");
|
||||
static LLRegisterPanelClassWrapper<LLSocialAccountPanel> t_panel_account("llsocialaccountpanel");
|
||||
|
||||
const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
|
||||
const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/";
|
||||
const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazonaws.com/map_placeholder.png";
|
||||
const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare";
|
||||
const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare";
|
||||
|
||||
std::string get_map_url()
|
||||
{
|
||||
LLVector3d center_agent;
|
||||
if (gAgent.getRegion())
|
||||
{
|
||||
center_agent = gAgent.getRegion()->getCenterGlobal();
|
||||
}
|
||||
int x_pos = center_agent[0] / 256.0;
|
||||
int y_pos = center_agent[1] / 256.0;
|
||||
std::string map_url = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-1-%d-%d-objects.jpg", x_pos, y_pos);
|
||||
return map_url;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//LLSocialStatusPanel//////
|
||||
///////////////////////////
|
||||
|
||||
LLSocialStatusPanel::LLSocialStatusPanel() :
|
||||
mMessageTextEditor(NULL),
|
||||
mPostButton(NULL),
|
||||
mCancelButton(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLSocialStatusPanel::onSend, this));
|
||||
}
|
||||
|
||||
BOOL LLSocialStatusPanel::postBuild()
|
||||
{
|
||||
mMessageTextEditor = getChild<LLUICtrl>("status_message");
|
||||
mPostButton = getChild<LLUICtrl>("post_status_btn");
|
||||
mCancelButton = getChild<LLUICtrl>("cancel_status_btn");
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
void LLSocialStatusPanel::draw()
|
||||
{
|
||||
if (mMessageTextEditor && mPostButton && mCancelButton)
|
||||
{
|
||||
bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
|
||||
std::string message = mMessageTextEditor->getValue().asString();
|
||||
mMessageTextEditor->setEnabled(no_ongoing_connection);
|
||||
mCancelButton->setEnabled(no_ongoing_connection);
|
||||
mPostButton->setEnabled(no_ongoing_connection && !message.empty());
|
||||
}
|
||||
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
void LLSocialStatusPanel::onSend()
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialStatusPanel", boost::bind(&LLSocialStatusPanel::onFacebookConnectStateChange, this, _1));
|
||||
|
||||
// Connect to Facebook if necessary and then post
|
||||
if (LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
sendStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLSocialStatusPanel::onFacebookConnectStateChange(const LLSD& data)
|
||||
{
|
||||
switch (data.get("enum").asInteger())
|
||||
{
|
||||
case LLFacebookConnect::FB_CONNECTED:
|
||||
sendStatus();
|
||||
break;
|
||||
|
||||
case LLFacebookConnect::FB_POSTED:
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel");
|
||||
clearAndClose();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLSocialStatusPanel::sendStatus()
|
||||
{
|
||||
std::string message = mMessageTextEditor->getValue().asString();
|
||||
if (!message.empty())
|
||||
{
|
||||
LLFacebookConnect::instance().updateStatus(message);
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocialStatusPanel::clearAndClose()
|
||||
{
|
||||
mMessageTextEditor->setValue("");
|
||||
|
||||
LLFloater* floater = getParentByType<LLFloater>();
|
||||
if (floater)
|
||||
{
|
||||
floater->closeFloater();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//LLSocialPhotoPanel///////
|
||||
///////////////////////////
|
||||
|
||||
LLSocialPhotoPanel::LLSocialPhotoPanel() :
|
||||
mSnapshotPanel(NULL),
|
||||
mResolutionComboBox(NULL),
|
||||
mRefreshBtn(NULL),
|
||||
mWorkingLabel(NULL),
|
||||
mThumbnailPlaceholder(NULL),
|
||||
mCaptionTextBox(NULL),
|
||||
mLocationCheckbox(NULL),
|
||||
mPostButton(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLSocialPhotoPanel::onSend, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLSocialPhotoPanel::onClickNewSnapshot, this));
|
||||
}
|
||||
|
||||
LLSocialPhotoPanel::~LLSocialPhotoPanel()
|
||||
{
|
||||
if(mPreviewHandle.get())
|
||||
{
|
||||
mPreviewHandle.get()->die();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLSocialPhotoPanel::postBuild()
|
||||
{
|
||||
setVisibleCallback(boost::bind(&LLSocialPhotoPanel::onVisibilityChange, this, _2));
|
||||
|
||||
mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
|
||||
mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
|
||||
mResolutionComboBox->setCommitCallback(boost::bind(&LLSocialPhotoPanel::updateResolution, this, TRUE));
|
||||
mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
|
||||
mWorkingLabel = getChild<LLUICtrl>("working_lbl");
|
||||
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
|
||||
mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
|
||||
mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
|
||||
mPostButton = getChild<LLUICtrl>("post_photo_btn");
|
||||
mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::draw()
|
||||
{
|
||||
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
|
||||
|
||||
// Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
|
||||
bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
|
||||
mCancelButton->setEnabled(no_ongoing_connection);
|
||||
mCaptionTextBox->setEnabled(no_ongoing_connection);
|
||||
mResolutionComboBox->setEnabled(no_ongoing_connection);
|
||||
mRefreshBtn->setEnabled(no_ongoing_connection);
|
||||
mLocationCheckbox->setEnabled(no_ongoing_connection);
|
||||
|
||||
// Display the preview if one is available
|
||||
if (previewp && previewp->getThumbnailImage())
|
||||
{
|
||||
const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
|
||||
const S32 thumbnail_w = previewp->getThumbnailWidth();
|
||||
const S32 thumbnail_h = previewp->getThumbnailHeight();
|
||||
|
||||
// calc preview offset within the preview rect
|
||||
const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
|
||||
const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
|
||||
|
||||
// calc preview offset within the floater rect
|
||||
// Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater.
|
||||
// This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity.
|
||||
// *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time.
|
||||
S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1;
|
||||
S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39;
|
||||
|
||||
mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>());
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
// Apply floater transparency to the texture unless the floater is focused.
|
||||
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
|
||||
LLColor4 color = LLColor4::white;
|
||||
gl_draw_scaled_image(offset_x, offset_y,
|
||||
thumbnail_w, thumbnail_h,
|
||||
previewp->getThumbnailImage(), color % alpha);
|
||||
|
||||
previewp->drawPreviewRect(offset_x, offset_y) ;
|
||||
}
|
||||
|
||||
// Update the visibility of the working (computing preview) label
|
||||
mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
|
||||
|
||||
// Enable Post if we have a preview to send and no on going connection being processed
|
||||
mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
|
||||
|
||||
// Draw the rest of the panel on top of it
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
LLSnapshotLivePreview* LLSocialPhotoPanel::getPreviewView()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
|
||||
return previewp;
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
|
||||
{
|
||||
bool visible = new_visibility.asBoolean();
|
||||
if (visible)
|
||||
{
|
||||
if (mPreviewHandle.get())
|
||||
{
|
||||
LLSnapshotLivePreview* preview = getPreviewView();
|
||||
if(preview)
|
||||
{
|
||||
lldebugs << "opened, updating snapshot" << llendl;
|
||||
preview->updateSnapshot(TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLRect full_screen_rect = getRootView()->getRect();
|
||||
LLSnapshotLivePreview::Params p;
|
||||
p.rect(full_screen_rect);
|
||||
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
|
||||
mPreviewHandle = previewp->getHandle();
|
||||
|
||||
previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
|
||||
previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
|
||||
//previewp->setSnapshotQuality(98);
|
||||
previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
|
||||
|
||||
updateControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::onClickNewSnapshot()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
if (previewp)
|
||||
{
|
||||
//setStatus(Impl::STATUS_READY);
|
||||
lldebugs << "updating snapshot" << llendl;
|
||||
previewp->updateSnapshot(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::onSend()
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialPhotoPanel", boost::bind(&LLSocialPhotoPanel::onFacebookConnectStateChange, this, _1));
|
||||
|
||||
// Connect to Facebook if necessary and then post
|
||||
if (LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
sendPhoto();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLSocialPhotoPanel::onFacebookConnectStateChange(const LLSD& data)
|
||||
{
|
||||
switch (data.get("enum").asInteger())
|
||||
{
|
||||
case LLFacebookConnect::FB_CONNECTED:
|
||||
sendPhoto();
|
||||
break;
|
||||
|
||||
case LLFacebookConnect::FB_POSTED:
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel");
|
||||
clearAndClose();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::sendPhoto()
|
||||
{
|
||||
// Get the caption
|
||||
std::string caption = mCaptionTextBox->getValue().asString();
|
||||
|
||||
// Add the location if required
|
||||
bool add_location = mLocationCheckbox->getValue().asBoolean();
|
||||
if (add_location)
|
||||
{
|
||||
// Get the SLURL for the location
|
||||
LLSLURL slurl;
|
||||
LLAgentUI::buildSLURL(slurl);
|
||||
std::string slurl_string = slurl.getSLURLString();
|
||||
|
||||
// Add query parameters so Google Analytics can track incoming clicks!
|
||||
slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
|
||||
|
||||
// Add it to the caption (pretty crude, but we don't have a better option with photos)
|
||||
if (caption.empty())
|
||||
caption = slurl_string;
|
||||
else
|
||||
caption = caption + " " + slurl_string;
|
||||
}
|
||||
|
||||
// Get the image
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
|
||||
// Post to Facebook
|
||||
LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption);
|
||||
|
||||
updateControls();
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::clearAndClose()
|
||||
{
|
||||
mCaptionTextBox->setValue("");
|
||||
|
||||
LLFloater* floater = getParentByType<LLFloater>();
|
||||
if (floater)
|
||||
{
|
||||
floater->closeFloater();
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::updateControls()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
BOOL got_bytes = previewp && previewp->getDataSize() > 0;
|
||||
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
|
||||
LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
|
||||
|
||||
// *TODO: Separate maximum size for Web images from postcards
|
||||
lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
|
||||
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
std::string bytes_string;
|
||||
if (got_snap)
|
||||
{
|
||||
LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
|
||||
}
|
||||
|
||||
//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
|
||||
getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
|
||||
getChild<LLUICtrl>("file_size_label")->setColor(
|
||||
shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD
|
||||
&& got_bytes
|
||||
&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
|
||||
|
||||
updateResolution(FALSE);
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::updateResolution(BOOL do_update)
|
||||
{
|
||||
LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
|
||||
|
||||
std::string sdstring = combobox->getSelectedValue();
|
||||
LLSD sdres;
|
||||
std::stringstream sstream(sdstring);
|
||||
LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
|
||||
|
||||
S32 width = sdres[0];
|
||||
S32 height = sdres[1];
|
||||
|
||||
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
|
||||
if (previewp && combobox->getCurrentIndex() >= 0)
|
||||
{
|
||||
S32 original_width = 0 , original_height = 0 ;
|
||||
previewp->getSize(original_width, original_height) ;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
// take resolution from current window size
|
||||
lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
|
||||
previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the resolution from the selected pre-canned drop-down choice
|
||||
lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
|
||||
previewp->setSize(width, height);
|
||||
}
|
||||
|
||||
checkAspectRatio(width);
|
||||
|
||||
previewp->getSize(width, height);
|
||||
|
||||
if(original_width != width || original_height != height)
|
||||
{
|
||||
previewp->setSize(width, height);
|
||||
|
||||
// hide old preview as the aspect ratio could be wrong
|
||||
lldebugs << "updating thumbnail" << llendl;
|
||||
|
||||
previewp->updateSnapshot(FALSE, TRUE);
|
||||
if(do_update)
|
||||
{
|
||||
lldebugs << "Will update controls" << llendl;
|
||||
updateControls();
|
||||
LLSocialPhotoPanel::onClickNewSnapshot();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocialPhotoPanel::checkAspectRatio(S32 index)
|
||||
{
|
||||
LLSnapshotLivePreview *previewp = getPreviewView() ;
|
||||
|
||||
BOOL keep_aspect = FALSE;
|
||||
|
||||
if (0 == index) // current window size
|
||||
{
|
||||
keep_aspect = TRUE;
|
||||
}
|
||||
else // predefined resolution
|
||||
{
|
||||
keep_aspect = FALSE;
|
||||
}
|
||||
|
||||
if (previewp)
|
||||
{
|
||||
previewp->mKeepAspectRatio = keep_aspect;
|
||||
}
|
||||
}
|
||||
|
||||
LLUICtrl* LLSocialPhotoPanel::getRefreshBtn()
|
||||
{
|
||||
return mRefreshBtn;
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//LLSocialCheckinPanel//
|
||||
////////////////////////
|
||||
|
||||
LLSocialCheckinPanel::LLSocialCheckinPanel() :
|
||||
mMapUrl(""),
|
||||
mReloadingMapTexture(false)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLSocialCheckinPanel::onSend, this));
|
||||
}
|
||||
|
||||
BOOL LLSocialCheckinPanel::postBuild()
|
||||
{
|
||||
// Keep pointers to widgets so we don't traverse the UI hierarchy too often
|
||||
mPostButton = getChild<LLUICtrl>("post_place_btn");
|
||||
mCancelButton = getChild<LLUICtrl>("cancel_place_btn");
|
||||
mMessageTextEditor = getChild<LLUICtrl>("place_caption");
|
||||
mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator");
|
||||
mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder");
|
||||
mMapDefault = getChild<LLIconCtrl>("map_default");
|
||||
mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb");
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
void LLSocialCheckinPanel::draw()
|
||||
{
|
||||
bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
|
||||
mPostButton->setEnabled(no_ongoing_connection);
|
||||
mCancelButton->setEnabled(no_ongoing_connection);
|
||||
mMessageTextEditor->setEnabled(no_ongoing_connection);
|
||||
mMapCheckBox->setEnabled(no_ongoing_connection);
|
||||
|
||||
std::string map_url = get_map_url();
|
||||
// Did we change location?
|
||||
if (map_url != mMapUrl)
|
||||
{
|
||||
mMapUrl = map_url;
|
||||
// Load the map tile
|
||||
mMapTexture = LLViewerTextureManager::getFetchedTextureFromUrl(mMapUrl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
|
||||
mMapTexture->setBoostLevel(LLGLTexture::BOOST_MAP);
|
||||
mReloadingMapTexture = true;
|
||||
// In the meantime, put the "loading" indicator on, hide the tile map and disable the checkbox
|
||||
mMapLoadingIndicator->setVisible(true);
|
||||
mMapPlaceholder->setVisible(false);
|
||||
}
|
||||
// Are we done loading the map tile?
|
||||
if (mReloadingMapTexture && mMapTexture->isFullyLoaded())
|
||||
{
|
||||
// Don't do it again next time around
|
||||
mReloadingMapTexture = false;
|
||||
// Convert the map texture to the appropriate image object
|
||||
LLPointer<LLUIImage> ui_image = new LLUIImage(mMapUrl, mMapTexture);
|
||||
// Load the map widget with the correct map tile image
|
||||
mMapPlaceholder->setImage(ui_image);
|
||||
// Now hide the loading indicator, bring the tile in view and reenable the checkbox with its previous value
|
||||
mMapLoadingIndicator->setVisible(false);
|
||||
mMapPlaceholder->setVisible(true);
|
||||
}
|
||||
// Show the default icon if that's the checkbox value (the real one...)
|
||||
// This will hide/show the loading indicator and/or tile underneath
|
||||
mMapDefault->setVisible(!(mMapCheckBox->get()));
|
||||
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
void LLSocialCheckinPanel::onSend()
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialCheckinPanel", boost::bind(&LLSocialCheckinPanel::onFacebookConnectStateChange, this, _1));
|
||||
|
||||
// Connect to Facebook if necessary and then post
|
||||
if (LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
sendCheckin();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLSocialCheckinPanel::onFacebookConnectStateChange(const LLSD& data)
|
||||
{
|
||||
switch (data.get("enum").asInteger())
|
||||
{
|
||||
case LLFacebookConnect::FB_CONNECTED:
|
||||
sendCheckin();
|
||||
break;
|
||||
|
||||
case LLFacebookConnect::FB_POSTED:
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel");
|
||||
clearAndClose();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLSocialCheckinPanel::sendCheckin()
|
||||
{
|
||||
// Get the location SLURL
|
||||
LLSLURL slurl;
|
||||
LLAgentUI::buildSLURL(slurl);
|
||||
std::string slurl_string = slurl.getSLURLString();
|
||||
|
||||
// Use a valid http:// URL if the scheme is secondlife://
|
||||
LLURI slurl_uri(slurl_string);
|
||||
if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
|
||||
{
|
||||
slurl_string = DEFAULT_CHECKIN_LOCATION_URL;
|
||||
}
|
||||
|
||||
// Add query parameters so Google Analytics can track incoming clicks!
|
||||
slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
|
||||
|
||||
// Get the region name
|
||||
std::string region_name = gAgent.getRegion()->getName();
|
||||
|
||||
// Get the region description
|
||||
std::string description;
|
||||
LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent());
|
||||
|
||||
// Optionally add the region map view
|
||||
bool add_map_view = mMapCheckBox->getValue().asBoolean();
|
||||
std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL);
|
||||
|
||||
// Get the caption
|
||||
std::string caption = mMessageTextEditor->getValue().asString();
|
||||
|
||||
// Post to Facebook
|
||||
LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);
|
||||
}
|
||||
|
||||
void LLSocialCheckinPanel::clearAndClose()
|
||||
{
|
||||
mMessageTextEditor->setValue("");
|
||||
|
||||
LLFloater* floater = getParentByType<LLFloater>();
|
||||
if (floater)
|
||||
{
|
||||
floater->closeFloater();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//LLSocialAccountPanel//////
|
||||
///////////////////////////
|
||||
|
||||
LLSocialAccountPanel::LLSocialAccountPanel() :
|
||||
mAccountCaptionLabel(NULL),
|
||||
mAccountNameLabel(NULL),
|
||||
mPanelButtons(NULL),
|
||||
mConnectButton(NULL),
|
||||
mDisconnectButton(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLSocialAccountPanel::onConnect, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLSocialAccountPanel::onDisconnect, this));
|
||||
|
||||
setVisibleCallback(boost::bind(&LLSocialAccountPanel::onVisibilityChange, this, _2));
|
||||
}
|
||||
|
||||
BOOL LLSocialAccountPanel::postBuild()
|
||||
{
|
||||
mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
|
||||
mAccountNameLabel = getChild<LLTextBox>("account_name_label");
|
||||
mPanelButtons = getChild<LLUICtrl>("panel_buttons");
|
||||
mConnectButton = getChild<LLUICtrl>("connect_btn");
|
||||
mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::draw()
|
||||
{
|
||||
LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
|
||||
|
||||
//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
|
||||
bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING;
|
||||
mDisconnectButton->setEnabled(!disconnecting);
|
||||
|
||||
//Disable the 'connect' button when a connection is in progress
|
||||
bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS;
|
||||
mConnectButton->setEnabled(!connecting);
|
||||
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::onVisibilityChange(const LLSD& new_visibility)
|
||||
{
|
||||
bool visible = new_visibility.asBoolean();
|
||||
|
||||
if(visible)
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialAccountPanel");
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::onFacebookConnectStateChange, this, _1));
|
||||
|
||||
LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel");
|
||||
LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::onFacebookConnectInfoChange, this));
|
||||
|
||||
//Connected
|
||||
if(LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
showConnectedLayout();
|
||||
}
|
||||
//Check if connected (show disconnected layout in meantime)
|
||||
else
|
||||
{
|
||||
showDisconnectedLayout();
|
||||
}
|
||||
if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
|
||||
(LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialAccountPanel");
|
||||
LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel");
|
||||
}
|
||||
}
|
||||
|
||||
bool LLSocialAccountPanel::onFacebookConnectStateChange(const LLSD& data)
|
||||
{
|
||||
if(LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
//In process of disconnecting so leave the layout as is
|
||||
if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING)
|
||||
{
|
||||
showConnectedLayout();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showDisconnectedLayout();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLSocialAccountPanel::onFacebookConnectInfoChange()
|
||||
{
|
||||
LLSD info = LLFacebookConnect::instance().getInfo();
|
||||
std::string clickable_name;
|
||||
|
||||
//Strings of format [http://www.somewebsite.com Click Me] become clickable text
|
||||
if(info.has("link") && info.has("name"))
|
||||
{
|
||||
clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
|
||||
}
|
||||
|
||||
mAccountNameLabel->setText(clickable_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::showConnectButton()
|
||||
{
|
||||
if(!mConnectButton->getVisible())
|
||||
{
|
||||
mConnectButton->setVisible(TRUE);
|
||||
mDisconnectButton->setVisible(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::hideConnectButton()
|
||||
{
|
||||
if(mConnectButton->getVisible())
|
||||
{
|
||||
mConnectButton->setVisible(FALSE);
|
||||
mDisconnectButton->setVisible(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::showDisconnectedLayout()
|
||||
{
|
||||
mAccountCaptionLabel->setText(getString("facebook_disconnected"));
|
||||
mAccountNameLabel->setText(std::string(""));
|
||||
showConnectButton();
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::showConnectedLayout()
|
||||
{
|
||||
LLFacebookConnect::instance().loadFacebookInfo();
|
||||
|
||||
mAccountCaptionLabel->setText(getString("facebook_connected"));
|
||||
hideConnectButton();
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::onConnect()
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook(true);
|
||||
|
||||
//Clear only the facebook browser cookies so that the facebook login screen appears
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
|
||||
}
|
||||
|
||||
void LLSocialAccountPanel::onDisconnect()
|
||||
{
|
||||
LLFacebookConnect::instance().disconnectFromFacebook();
|
||||
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//LLFloaterSocial///////
|
||||
////////////////////////
|
||||
|
||||
LLFloaterSocial::LLFloaterSocial(const LLSD& key) : LLFloater(key),
|
||||
mSocialPhotoPanel(NULL),
|
||||
mStatusErrorText(NULL),
|
||||
mStatusLoadingText(NULL),
|
||||
mStatusLoadingIndicator(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterSocial::onCancel, this));
|
||||
}
|
||||
|
||||
void LLFloaterSocial::onCancel()
|
||||
{
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
BOOL LLFloaterSocial::postBuild()
|
||||
{
|
||||
// Keep tab of the Photo Panel
|
||||
mSocialPhotoPanel = static_cast<LLSocialPhotoPanel*>(getChild<LLUICtrl>("panel_social_photo"));
|
||||
// Connection status widgets
|
||||
mStatusErrorText = getChild<LLTextBox>("connection_error_text");
|
||||
mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
|
||||
mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
|
||||
return LLFloater::postBuild();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterSocial::preUpdate()
|
||||
{
|
||||
LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
|
||||
if (instance)
|
||||
{
|
||||
//Will set file size text to 'unknown'
|
||||
instance->mSocialPhotoPanel->updateControls();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterSocial::postUpdate()
|
||||
{
|
||||
LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
|
||||
if (instance)
|
||||
{
|
||||
//Will set the file size text
|
||||
instance->mSocialPhotoPanel->updateControls();
|
||||
|
||||
// The refresh button is initially hidden. We show it after the first update,
|
||||
// i.e. after snapshot is taken
|
||||
LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn();
|
||||
|
||||
if (!refresh_button->getVisible())
|
||||
{
|
||||
refresh_button->setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterSocial::draw()
|
||||
{
|
||||
if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
|
||||
{
|
||||
mStatusErrorText->setVisible(false);
|
||||
mStatusLoadingText->setVisible(false);
|
||||
mStatusLoadingIndicator->setVisible(false);
|
||||
LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
|
||||
std::string status_text;
|
||||
|
||||
switch (connection_state)
|
||||
{
|
||||
case LLFacebookConnect::FB_NOT_CONNECTED:
|
||||
// No status displayed when first opening the panel and no connection done
|
||||
case LLFacebookConnect::FB_CONNECTED:
|
||||
// When successfully connected, no message is displayed
|
||||
case LLFacebookConnect::FB_POSTED:
|
||||
// No success message to show since we actually close the floater after successful posting completion
|
||||
break;
|
||||
case LLFacebookConnect::FB_CONNECTION_IN_PROGRESS:
|
||||
// Connection loading indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFacebookConnecting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLFacebookConnect::FB_POSTING:
|
||||
// Posting indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFacebookPosting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLFacebookConnect::FB_CONNECTION_FAILED:
|
||||
// Error connecting to the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFacebookErrorConnecting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
case LLFacebookConnect::FB_POST_FAILED:
|
||||
// Error posting to the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFacebookErrorPosting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
case LLFacebookConnect::FB_DISCONNECTING:
|
||||
// Disconnecting loading indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFacebookDisconnecting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLFacebookConnect::FB_DISCONNECT_FAILED:
|
||||
// Error disconnecting from the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFacebookErrorDisconnecting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LLFloater::draw();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* @file llfloatersocial.h
|
||||
* @brief Header file for llfloatersocial
|
||||
* @author Gilbert@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* 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_LLFLOATERSOCIAL_H
|
||||
#define LL_LLFLOATERSOCIAL_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lltextbox.h"
|
||||
#include "llviewertexture.h"
|
||||
|
||||
class LLIconCtrl;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLSnapshotLivePreview;
|
||||
|
||||
class LLSocialStatusPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLSocialStatusPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onSend();
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendStatus();
|
||||
void clearAndClose();
|
||||
|
||||
private:
|
||||
LLUICtrl* mMessageTextEditor;
|
||||
LLUICtrl* mPostButton;
|
||||
LLUICtrl* mCancelButton;
|
||||
};
|
||||
|
||||
class LLSocialPhotoPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLSocialPhotoPanel();
|
||||
~LLSocialPhotoPanel();
|
||||
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
LLSnapshotLivePreview* getPreviewView();
|
||||
void onVisibilityChange(const LLSD& new_visibility);
|
||||
void onClickNewSnapshot();
|
||||
void onSend();
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendPhoto();
|
||||
void clearAndClose();
|
||||
|
||||
void updateControls();
|
||||
void updateResolution(BOOL do_update);
|
||||
void checkAspectRatio(S32 index);
|
||||
LLUICtrl* getRefreshBtn();
|
||||
|
||||
private:
|
||||
LLHandle<LLView> mPreviewHandle;
|
||||
|
||||
LLUICtrl * mSnapshotPanel;
|
||||
LLUICtrl * mResolutionComboBox;
|
||||
LLUICtrl * mRefreshBtn;
|
||||
LLUICtrl * mWorkingLabel;
|
||||
LLUICtrl * mThumbnailPlaceholder;
|
||||
LLUICtrl * mCaptionTextBox;
|
||||
LLUICtrl * mLocationCheckbox;
|
||||
LLUICtrl * mPostButton;
|
||||
LLUICtrl* mCancelButton;
|
||||
};
|
||||
|
||||
class LLSocialCheckinPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLSocialCheckinPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onSend();
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendCheckin();
|
||||
void clearAndClose();
|
||||
|
||||
private:
|
||||
std::string mMapUrl;
|
||||
LLPointer<LLViewerFetchedTexture> mMapTexture;
|
||||
LLUICtrl* mPostButton;
|
||||
LLUICtrl* mCancelButton;
|
||||
LLUICtrl* mMessageTextEditor;
|
||||
LLUICtrl* mMapLoadingIndicator;
|
||||
LLIconCtrl* mMapPlaceholder;
|
||||
LLIconCtrl* mMapDefault;
|
||||
LLCheckBoxCtrl* mMapCheckBox;
|
||||
bool mReloadingMapTexture;
|
||||
};
|
||||
|
||||
class LLSocialAccountPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLSocialAccountPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
private:
|
||||
void onVisibilityChange(const LLSD& new_visibility);
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
bool onFacebookConnectInfoChange();
|
||||
void onConnect();
|
||||
void onUseAnotherAccount();
|
||||
void onDisconnect();
|
||||
|
||||
void showConnectButton();
|
||||
void hideConnectButton();
|
||||
void showDisconnectedLayout();
|
||||
void showConnectedLayout();
|
||||
|
||||
LLTextBox * mAccountCaptionLabel;
|
||||
LLTextBox * mAccountNameLabel;
|
||||
LLUICtrl * mPanelButtons;
|
||||
LLUICtrl * mConnectButton;
|
||||
LLUICtrl * mDisconnectButton;
|
||||
};
|
||||
|
||||
|
||||
class LLFloaterSocial : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterSocial(const LLSD& key);
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onCancel();
|
||||
|
||||
static void preUpdate();
|
||||
static void postUpdate();
|
||||
|
||||
private:
|
||||
LLSocialPhotoPanel* mSocialPhotoPanel;
|
||||
LLTextBox* mStatusErrorText;
|
||||
LLTextBox* mStatusLoadingText;
|
||||
LLUICtrl* mStatusLoadingIndicator;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERSOCIAL_H
|
||||
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
#include "llcombobox.h"
|
||||
#include "lliconctrl.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "lllayoutstack.h"
|
||||
#include "llpluginclassmedia.h"
|
||||
#include "llprogressbar.h"
|
||||
|
|
@ -46,7 +47,8 @@ LLFloaterWebContent::_Params::_Params()
|
|||
id("id"),
|
||||
window_class("window_class", "web_content"),
|
||||
show_chrome("show_chrome", true),
|
||||
allow_address_entry("allow_address_entry", true),
|
||||
allow_address_entry("allow_address_entry", true),
|
||||
allow_back_forward_navigation("allow_back_forward_navigation", true),
|
||||
preferred_media_size("preferred_media_size"),
|
||||
trusted_content("trusted_content", false),
|
||||
show_page_title("show_page_title", true)
|
||||
|
|
@ -65,7 +67,11 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params )
|
|||
mBtnReload(NULL),
|
||||
mBtnStop(NULL),
|
||||
mUUID(params.id()),
|
||||
mShowPageTitle(params.show_page_title)
|
||||
mShowPageTitle(params.show_page_title),
|
||||
mAllowNavigation(true),
|
||||
mCurrentURL(""),
|
||||
mDisplayURL(""),
|
||||
mSecureURL(false)
|
||||
{
|
||||
mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
|
||||
mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
|
||||
|
|
@ -97,7 +103,7 @@ BOOL LLFloaterWebContent::postBuild()
|
|||
|
||||
// cache image for secure browsing
|
||||
mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag");
|
||||
|
||||
|
||||
// initialize the URL history using the system URL History manager
|
||||
initializeURLHistory();
|
||||
|
||||
|
|
@ -243,6 +249,7 @@ void LLFloaterWebContent::open_media(const Params& p)
|
|||
getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome);
|
||||
getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome);
|
||||
bool address_entry_enabled = p.allow_address_entry && !p.trusted_content;
|
||||
mAllowNavigation = p.allow_back_forward_navigation;
|
||||
getChildView("address")->setEnabled(address_entry_enabled);
|
||||
getChildView("popexternal")->setEnabled(address_entry_enabled);
|
||||
|
||||
|
|
@ -287,6 +294,16 @@ void LLFloaterWebContent::onOpen(const LLSD& key)
|
|||
//virtual
|
||||
void LLFloaterWebContent::onClose(bool app_quitting)
|
||||
{
|
||||
// If we close the web browsing window showing the facebook login, we need to signal to this object that the connection will not happen
|
||||
LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
|
||||
if (fbc_web == this)
|
||||
{
|
||||
if (!LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerMedia::proxyWindowClosed(mUUID);
|
||||
destroy();
|
||||
}
|
||||
|
|
@ -295,8 +312,11 @@ void LLFloaterWebContent::onClose(bool app_quitting)
|
|||
void LLFloaterWebContent::draw()
|
||||
{
|
||||
// this is asynchronous so we need to keep checking
|
||||
mBtnBack->setEnabled( mWebBrowser->canNavigateBack() );
|
||||
mBtnForward->setEnabled( mWebBrowser->canNavigateForward() );
|
||||
mBtnBack->setEnabled( mWebBrowser->canNavigateBack() && mAllowNavigation);
|
||||
mBtnForward->setEnabled( mWebBrowser->canNavigateForward() && mAllowNavigation);
|
||||
|
||||
// Show/hide the lock icon
|
||||
mSecureLockIcon->setVisible(mSecureURL && !mAddressCombo->hasFocus());
|
||||
|
||||
LLFloater::draw();
|
||||
}
|
||||
|
|
@ -342,21 +362,8 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
|
|||
// we populate the status bar with URLs as they change so clear it now we're done
|
||||
const std::string end_str = "";
|
||||
mStatusBarText->setText( end_str );
|
||||
|
||||
// decide if secure browsing icon should be displayed
|
||||
std::string prefix = std::string("https://");
|
||||
std::string test_prefix = mCurrentURL.substr(0, prefix.length());
|
||||
LLStringUtil::toLower(test_prefix);
|
||||
if(test_prefix == prefix)
|
||||
{
|
||||
mSecureLockIcon->setVisible(true);
|
||||
mAddressCombo->setLeftTextPadding(22);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSecureLockIcon->setVisible(false);
|
||||
mAddressCombo->setLeftTextPadding(2);
|
||||
}
|
||||
}
|
||||
else if(event == MEDIA_EVENT_CLOSE_REQUEST)
|
||||
{
|
||||
|
|
@ -399,15 +406,40 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
|
|||
|
||||
void LLFloaterWebContent::set_current_url(const std::string& url)
|
||||
{
|
||||
mCurrentURL = url;
|
||||
if (!url.empty())
|
||||
{
|
||||
if (!mCurrentURL.empty())
|
||||
{
|
||||
// Clean up the current browsing list to show true URL
|
||||
mAddressCombo->remove(mDisplayURL);
|
||||
mAddressCombo->add(mCurrentURL);
|
||||
}
|
||||
|
||||
// serialize url history into the system URL History manager
|
||||
LLURLHistory::removeURL("browser", mCurrentURL);
|
||||
LLURLHistory::addURL("browser", mCurrentURL);
|
||||
// Update current URL
|
||||
mCurrentURL = url;
|
||||
LLStringUtil::trim(mCurrentURL);
|
||||
|
||||
mAddressCombo->remove( mCurrentURL );
|
||||
mAddressCombo->add( mCurrentURL );
|
||||
mAddressCombo->selectByValue( mCurrentURL );
|
||||
// Serialize url history into the system URL History manager
|
||||
LLURLHistory::removeURL("browser", mCurrentURL);
|
||||
LLURLHistory::addURL("browser", mCurrentURL);
|
||||
|
||||
// Check if this is a secure URL
|
||||
static const std::string secure_prefix = std::string("https://");
|
||||
std::string prefix = mCurrentURL.substr(0, secure_prefix.length());
|
||||
LLStringUtil::toLower(prefix);
|
||||
mSecureURL = (prefix == secure_prefix);
|
||||
|
||||
// Hack : we move the text a bit to make space for the lock icon in the secure URL case
|
||||
mDisplayURL = (mSecureURL ? " " + mCurrentURL : mCurrentURL);
|
||||
|
||||
// Clean up browsing list (prevent dupes) and add/select the new URL to it
|
||||
mAddressCombo->remove(mCurrentURL);
|
||||
mAddressCombo->add(mDisplayURL);
|
||||
mAddressCombo->selectByValue(mDisplayURL);
|
||||
|
||||
// Set the focus back to the web page. When setting the url, there's no point to leave the focus anywhere else.
|
||||
mWebBrowser->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterWebContent::onClickForward()
|
||||
|
|
@ -451,6 +483,7 @@ void LLFloaterWebContent::onEnterAddress()
|
|||
// make sure there is at least something there.
|
||||
// (perhaps this test should be for minimum length of a URL)
|
||||
std::string url = mAddressCombo->getValue().asString();
|
||||
LLStringUtil::trim(url);
|
||||
if ( url.length() > 0 )
|
||||
{
|
||||
mWebBrowser->navigateTo( url, "text/html");
|
||||
|
|
@ -462,6 +495,7 @@ void LLFloaterWebContent::onPopExternal()
|
|||
// make sure there is at least something there.
|
||||
// (perhaps this test should be for minimum length of a URL)
|
||||
std::string url = mAddressCombo->getValue().asString();
|
||||
LLStringUtil::trim(url);
|
||||
if ( url.length() > 0 )
|
||||
{
|
||||
LLWeb::loadURLExternal( url );
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
id;
|
||||
Optional<bool> show_chrome,
|
||||
allow_address_entry,
|
||||
allow_back_forward_navigation,
|
||||
trusted_content,
|
||||
show_page_title;
|
||||
Optional<LLRect> preferred_media_size;
|
||||
|
|
@ -106,9 +107,12 @@ protected:
|
|||
LLView* mBtnReload;
|
||||
LLView* mBtnStop;
|
||||
|
||||
std::string mCurrentURL;
|
||||
std::string mCurrentURL; // Current URL
|
||||
std::string mDisplayURL; // URL being displayed in the address bar (can differ by trailing / leading space)
|
||||
std::string mUUID;
|
||||
bool mShowPageTitle;
|
||||
bool mAllowNavigation;
|
||||
bool mSecureURL; // true when the current url is prefixed "https://"
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERWEBCONTENT_H
|
||||
|
|
|
|||
|
|
@ -130,10 +130,10 @@ void process_dnd_im(const LLSD& notification)
|
|||
fromID,
|
||||
false,
|
||||
false); //will need slight refactor to retrieve whether offline message or not (assume online for now)
|
||||
}
|
||||
}
|
||||
|
||||
notify_of_message(data, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -155,22 +155,22 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
|
|||
|
||||
void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
||||
{
|
||||
std::string user_preferences;
|
||||
std::string user_preferences;
|
||||
LLUUID participant_id = msg[is_dnd_msg ? "FROM_ID" : "from_id"].asUUID();
|
||||
LLUUID session_id = msg[is_dnd_msg ? "SESSION_ID" : "session_id"].asUUID();
|
||||
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
|
||||
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
|
||||
|
||||
// do not show notification which goes from agent
|
||||
if (gAgent.getID() == participant_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// do not show notification which goes from agent
|
||||
if (gAgent.getID() == participant_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// determine state of conversations floater
|
||||
enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
|
||||
// determine state of conversations floater
|
||||
enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
|
||||
|
||||
|
||||
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
|
||||
bool store_dnd_message = false; // flag storage of a dnd message
|
||||
bool is_session_focused = session_floater->isTornOff() && session_floater->hasFocus();
|
||||
|
|
@ -179,23 +179,23 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
conversations_floater_status = CLOSED;
|
||||
}
|
||||
else if (!im_box->hasFocus() &&
|
||||
!(session_floater && LLFloater::isVisible(session_floater)
|
||||
&& !session_floater->isMinimized() && session_floater->hasFocus()))
|
||||
!(session_floater && LLFloater::isVisible(session_floater)
|
||||
&& !session_floater->isMinimized() && session_floater->hasFocus()))
|
||||
{
|
||||
conversations_floater_status = NOT_ON_TOP;
|
||||
}
|
||||
else if (im_box->getSelectedSession() != session_id)
|
||||
{
|
||||
conversations_floater_status = ON_TOP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;
|
||||
}
|
||||
|
||||
// determine user prefs for this session
|
||||
if (session_id.isNull())
|
||||
{
|
||||
// determine user prefs for this session
|
||||
if (session_id.isNull())
|
||||
{
|
||||
if (msg["source_type"].asInteger() == CHAT_SOURCE_OBJECT)
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationObjectIMOptions");
|
||||
|
|
@ -206,50 +206,50 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
}
|
||||
else
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
|
||||
user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM") == TRUE))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(session->isP2PSessionType())
|
||||
{
|
||||
if (LLAvatarTracker::instance().isBuddy(participant_id))
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
|
||||
else if(session->isP2PSessionType())
|
||||
{
|
||||
if (LLAvatarTracker::instance().isBuddy(participant_id))
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM") == TRUE))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
|
||||
}
|
||||
else
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNonFriendIM") == TRUE))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(session->isAdHocSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
|
||||
else if(session->isAdHocSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM") == TRUE))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(session->isGroupSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
|
||||
else if(session->isGroupSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundGroupChatIM") == TRUE))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actions:
|
||||
// actions:
|
||||
|
||||
// 0. nothing - exit
|
||||
if (("noaction" == user_preferences ||
|
||||
|
|
@ -287,23 +287,23 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else
|
||||
{
|
||||
store_dnd_message = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Flash line item
|
||||
if ("openconversations" == user_preferences
|
||||
|| ON_TOP == conversations_floater_status
|
||||
|| ("toast" == user_preferences && ON_TOP != conversations_floater_status)
|
||||
// 2. Flash line item
|
||||
if ("openconversations" == user_preferences
|
||||
|| ON_TOP == conversations_floater_status
|
||||
|| ("toast" == user_preferences && ON_TOP != conversations_floater_status)
|
||||
|| ("flash" == user_preferences && (CLOSED == conversations_floater_status
|
||||
|| NOT_ON_TOP == conversations_floater_status))
|
||||
|| is_dnd_msg)
|
||||
{
|
||||
if(!LLMuteList::getInstance()->isMuted(participant_id))
|
||||
{
|
||||
{
|
||||
if(!LLMuteList::getInstance()->isMuted(participant_id))
|
||||
{
|
||||
if(gAgent.isDoNotDisturb())
|
||||
{
|
||||
store_dnd_message = true;
|
||||
|
|
@ -318,43 +318,43 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
}
|
||||
else
|
||||
{
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
}
|
||||
}
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Flash FUI button
|
||||
if (("toast" == user_preferences || "flash" == user_preferences) &&
|
||||
(CLOSED == conversations_floater_status
|
||||
// 3. Flash FUI button
|
||||
if (("toast" == user_preferences || "flash" == user_preferences) &&
|
||||
(CLOSED == conversations_floater_status
|
||||
|| NOT_ON_TOP == conversations_floater_status)
|
||||
&& !is_session_focused
|
||||
&& !is_dnd_msg) //prevent flashing FUI button because the conversation floater will have already opened
|
||||
{
|
||||
if(!LLMuteList::getInstance()->isMuted(participant_id))
|
||||
{
|
||||
{
|
||||
if(!gAgent.isDoNotDisturb())
|
||||
{
|
||||
{
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true, im_box->isMinimized());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
store_dnd_message = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Toast
|
||||
if ((("toast" == user_preferences) &&
|
||||
// 4. Toast
|
||||
if ((("toast" == user_preferences) &&
|
||||
(ON_TOP_AND_ITEM_IS_SELECTED != conversations_floater_status) &&
|
||||
(!session_floater->isTornOff() || !LLFloater::isVisible(session_floater)))
|
||||
|| !session_floater->isMessagePaneExpanded())
|
||||
|| !session_floater->isMessagePaneExpanded())
|
||||
|
||||
{
|
||||
//Show IM toasts (upper right toasts)
|
||||
// Skip toasting for system messages and for nearby chat
|
||||
if(session_id.notNull() && participant_id.notNull())
|
||||
{
|
||||
{
|
||||
//Show IM toasts (upper right toasts)
|
||||
// Skip toasting for system messages and for nearby chat
|
||||
if(session_id.notNull() && participant_id.notNull())
|
||||
{
|
||||
if(!is_dnd_msg)
|
||||
{
|
||||
if(gAgent.isDoNotDisturb())
|
||||
|
|
@ -363,10 +363,10 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
}
|
||||
else
|
||||
{
|
||||
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (store_dnd_message)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@
|
|||
#include "llnotificationmanager.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llscriptfloater.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llavatarname.h"
|
||||
#include "llavatarnamecache.h"
|
||||
|
||||
using namespace LLNotificationsUI;
|
||||
|
||||
|
|
@ -87,7 +90,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)
|
|||
{
|
||||
LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());
|
||||
}
|
||||
else
|
||||
else if (notification->canShowToast())
|
||||
{
|
||||
LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
// libs
|
||||
#include "llavatarname.h"
|
||||
#include "llconversationview.h"
|
||||
#include "llfloaterimcontainer.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloatersidepanelcontainer.h"
|
||||
#include "llmenubutton.h"
|
||||
|
|
@ -48,15 +50,19 @@
|
|||
#include "llavataractions.h"
|
||||
#include "llavatarlist.h"
|
||||
#include "llavatarlistitem.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
#include "llcallbacklist.h"
|
||||
#include "llerror.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llfloateravatarpicker.h"
|
||||
//#include "llfloaterminiinspector.h"
|
||||
#include "llfriendcard.h"
|
||||
#include "llgroupactions.h"
|
||||
#include "llgrouplist.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llnetmap.h"
|
||||
#include "llpanelpeoplemenus.h"
|
||||
#include "llparticipantlist.h"
|
||||
#include "llsidetraypanelcontainer.h"
|
||||
#include "llrecentpeople.h"
|
||||
#include "llviewercontrol.h" // for gSavedSettings
|
||||
|
|
@ -64,6 +70,10 @@
|
|||
#include "llvoiceclient.h"
|
||||
#include "llworld.h"
|
||||
#include "llspeakers.h"
|
||||
#include "llfloaterwebcontent.h"
|
||||
|
||||
#include "llagentui.h"
|
||||
#include "llslurl.h"
|
||||
|
||||
#define FRIEND_LIST_UPDATE_TIMEOUT 0.5
|
||||
#define NEARBY_LIST_UPDATE_INTERVAL 1
|
||||
|
|
@ -73,9 +83,9 @@ static const std::string FRIENDS_TAB_NAME = "friends_panel";
|
|||
static const std::string GROUP_TAB_NAME = "groups_panel";
|
||||
static const std::string RECENT_TAB_NAME = "recent_panel";
|
||||
static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars
|
||||
|
||||
static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
|
||||
|
||||
|
||||
extern S32 gMaxAgentGroups;
|
||||
|
||||
/** Comparator for comparing avatar items by last interaction date */
|
||||
|
|
@ -495,6 +505,7 @@ public:
|
|||
|
||||
LLPanelPeople::LLPanelPeople()
|
||||
: LLPanel(),
|
||||
mTryToConnectToFbc(true),
|
||||
mTabContainer(NULL),
|
||||
mOnlineFriendList(NULL),
|
||||
mAllFriendList(NULL),
|
||||
|
|
@ -573,6 +584,7 @@ BOOL LLPanelPeople::postBuild()
|
|||
getChild<LLFilterEditor>("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
|
||||
getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
|
||||
getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
|
||||
getChild<LLFilterEditor>("fbc_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
|
||||
|
||||
mTabContainer = getChild<LLTabContainer>("tabs");
|
||||
mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2));
|
||||
|
|
@ -583,8 +595,11 @@ BOOL LLPanelPeople::postBuild()
|
|||
// updater is active only if panel is visible to user.
|
||||
friends_tab->setVisibleCallback(boost::bind(&Updater::setActive, mFriendListUpdater, _2));
|
||||
friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::removePicker, this));
|
||||
friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::updateFacebookList, this, _2));
|
||||
|
||||
mOnlineFriendList = friends_tab->getChild<LLAvatarList>("avatars_online");
|
||||
mAllFriendList = friends_tab->getChild<LLAvatarList>("avatars_all");
|
||||
mSuggestedFriends = friends_tab->getChild<LLAvatarList>("suggested_friends");
|
||||
mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
|
||||
mOnlineFriendList->setShowIcons("FriendsListShowIcons");
|
||||
mOnlineFriendList->showPermissions("FriendsListShowPermissions");
|
||||
|
|
@ -617,6 +632,7 @@ BOOL LLPanelPeople::postBuild()
|
|||
mRecentList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
|
||||
mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
|
||||
mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
|
||||
mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
|
||||
|
||||
setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
|
||||
setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
|
||||
|
|
@ -695,7 +711,7 @@ void LLPanelPeople::updateFriendListHelpText()
|
|||
|
||||
// Seems sometimes all_friends can be empty because of issue with Inventory loading (clear cache, slow connection...)
|
||||
// So, lets check all lists to avoid overlapping the text with online list. See EXT-6448.
|
||||
bool any_friend_exists = mAllFriendList->filterHasMatches() || mOnlineFriendList->filterHasMatches();
|
||||
bool any_friend_exists = mAllFriendList->filterHasMatches() || mOnlineFriendList->filterHasMatches() || mSuggestedFriends->filterHasMatches();
|
||||
no_friends_text->setVisible(!any_friend_exists);
|
||||
if (no_friends_text->getVisible())
|
||||
{
|
||||
|
|
@ -762,9 +778,40 @@ void LLPanelPeople::updateFriendList()
|
|||
mAllFriendList->setDirty(true, !mAllFriendList->filterHasMatches());
|
||||
//update trash and other buttons according to a selected item
|
||||
updateButtons();
|
||||
updateSuggestedFriendList();
|
||||
showFriendsAccordionsIfNeeded();
|
||||
}
|
||||
|
||||
bool LLPanelPeople::updateSuggestedFriendList()
|
||||
{
|
||||
const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
|
||||
uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
|
||||
suggested_friends.clear();
|
||||
|
||||
//Add suggested friends
|
||||
LLSD friends = LLFacebookConnect::instance().getContent();
|
||||
for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
|
||||
{
|
||||
LLUUID agent_id = (*i).asUUID();
|
||||
bool second_life_buddy = agent_id.notNull() ? av_tracker.isBuddy(agent_id) : false;
|
||||
|
||||
if(!second_life_buddy)
|
||||
{
|
||||
//FB+SL but not SL friend
|
||||
if (agent_id.notNull())
|
||||
{
|
||||
suggested_friends.push_back(agent_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
|
||||
mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
|
||||
showFriendsAccordionsIfNeeded();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLPanelPeople::updateNearbyList()
|
||||
{
|
||||
if (!mNearbyList)
|
||||
|
|
@ -788,6 +835,51 @@ void LLPanelPeople::updateRecentList()
|
|||
mRecentList->setDirty();
|
||||
}
|
||||
|
||||
bool LLPanelPeople::onConnectedToFacebook(const LLSD& data)
|
||||
{
|
||||
LLSD::Integer connection_state = data.get("enum").asInteger();
|
||||
|
||||
if (connection_state == LLFacebookConnect::FB_CONNECTED)
|
||||
{
|
||||
LLFacebookConnect::instance().loadFacebookFriends();
|
||||
}
|
||||
else if(connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
|
||||
{
|
||||
updateSuggestedFriendList();
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLPanelPeople::updateFacebookList(bool visible)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLPanelPeople", boost::bind(&LLPanelPeople::updateSuggestedFriendList, this));
|
||||
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").listen("LLPanelPeople", boost::bind(&LLPanelPeople::onConnectedToFacebook, this, _1));
|
||||
|
||||
if (LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
LLFacebookConnect::instance().loadFacebookFriends();
|
||||
}
|
||||
else if(mTryToConnectToFbc)
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook();
|
||||
mTryToConnectToFbc = false;
|
||||
}
|
||||
|
||||
updateSuggestedFriendList();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople");
|
||||
LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople");
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelPeople::updateButtons()
|
||||
{
|
||||
std::string cur_tab = getActiveTabName();
|
||||
|
|
@ -993,23 +1085,25 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
|
|||
{
|
||||
// store accordion tabs opened/closed state before any manipulation with accordion tabs
|
||||
if (!saved_filter.empty())
|
||||
{
|
||||
notifyChildren(LLSD().with("action","store_state"));
|
||||
}
|
||||
{
|
||||
notifyChildren(LLSD().with("action","store_state"));
|
||||
}
|
||||
|
||||
mOnlineFriendList->setNameFilter(filter);
|
||||
mAllFriendList->setNameFilter(filter);
|
||||
mSuggestedFriends->setNameFilter(filter);
|
||||
|
||||
setAccordionCollapsedByUser("tab_online", false);
|
||||
setAccordionCollapsedByUser("tab_all", false);
|
||||
showFriendsAccordionsIfNeeded();
|
||||
setAccordionCollapsedByUser("tab_online", false);
|
||||
setAccordionCollapsedByUser("tab_all", false);
|
||||
setAccordionCollapsedByUser("tab_suggested_friends", false);
|
||||
showFriendsAccordionsIfNeeded();
|
||||
|
||||
// restore accordion tabs state _after_ all manipulations
|
||||
if(saved_filter.empty())
|
||||
{
|
||||
notifyChildren(LLSD().with("action","restore_state"));
|
||||
}
|
||||
}
|
||||
{
|
||||
notifyChildren(LLSD().with("action","restore_state"));
|
||||
}
|
||||
}
|
||||
else if (cur_tab == GROUP_TAB_NAME)
|
||||
{
|
||||
mGroupList->setNameFilter(filter);
|
||||
|
|
@ -1229,7 +1323,7 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
|
|||
mAllFriendList->showPermissions(show_permissions);
|
||||
mOnlineFriendList->showPermissions(show_permissions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata)
|
||||
{
|
||||
|
|
@ -1387,6 +1481,7 @@ void LLPanelPeople::showFriendsAccordionsIfNeeded()
|
|||
// Expand and show accordions if needed, else - hide them
|
||||
showAccordion("tab_online", mOnlineFriendList->filterHasMatches());
|
||||
showAccordion("tab_all", mAllFriendList->filterHasMatches());
|
||||
showAccordion("tab_suggested_friends", mSuggestedFriends->filterHasMatches());
|
||||
|
||||
// Rearrange accordions
|
||||
LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
|
||||
|
|
@ -1450,4 +1545,5 @@ bool LLPanelPeople::isAccordionCollapsedByUser(const std::string& name)
|
|||
return isAccordionCollapsedByUser(getChild<LLUICtrl>(name));
|
||||
}
|
||||
|
||||
|
||||
// EOF
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef LL_LLPANELPEOPLE_H
|
||||
#define LL_LLPANELPEOPLE_H
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
#include <llpanel.h>
|
||||
|
||||
#include "llcallingcard.h" // for avatar tracker
|
||||
#include "llfloaterwebcontent.h"
|
||||
#include "llvoiceclient.h"
|
||||
|
||||
class LLAvatarList;
|
||||
|
|
@ -55,6 +56,8 @@ public:
|
|||
// when voice is available
|
||||
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
|
||||
|
||||
bool mTryToConnectToFbc;
|
||||
|
||||
// internals
|
||||
class Updater;
|
||||
|
||||
|
|
@ -73,8 +76,10 @@ private:
|
|||
// methods indirectly called by the updaters
|
||||
void updateFriendListHelpText();
|
||||
void updateFriendList();
|
||||
bool updateSuggestedFriendList();
|
||||
void updateNearbyList();
|
||||
void updateRecentList();
|
||||
void updateFacebookList(bool visible);
|
||||
|
||||
bool isItemsFreeOfFriends(const uuid_vec_t& uuids);
|
||||
|
||||
|
|
@ -121,6 +126,8 @@ private:
|
|||
|
||||
void onFriendListRefreshComplete(LLUICtrl*ctrl, const LLSD& param);
|
||||
|
||||
bool onConnectedToFacebook(const LLSD& data);
|
||||
|
||||
void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);
|
||||
void setAccordionCollapsedByUser(const std::string& name, bool collapsed);
|
||||
bool isAccordionCollapsedByUser(LLUICtrl* acc_tab);
|
||||
|
|
@ -129,6 +136,7 @@ private:
|
|||
LLTabContainer* mTabContainer;
|
||||
LLAvatarList* mOnlineFriendList;
|
||||
LLAvatarList* mAllFriendList;
|
||||
LLAvatarList* mSuggestedFriends;
|
||||
LLAvatarList* mNearbyList;
|
||||
LLAvatarList* mRecentList;
|
||||
LLGroupList* mGroupList;
|
||||
|
|
@ -140,6 +148,7 @@ private:
|
|||
Updater* mFriendListUpdater;
|
||||
Updater* mNearbyListUpdater;
|
||||
Updater* mRecentListUpdater;
|
||||
Updater* mFacebookListUpdater;
|
||||
Updater* mButtonsUpdater;
|
||||
LLHandle< LLFloater > mPicker;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ namespace LLPanelPeopleMenus
|
|||
|
||||
PeopleContextMenu gPeopleContextMenu;
|
||||
NearbyPeopleContextMenu gNearbyPeopleContextMenu;
|
||||
SuggestedFriendsContextMenu gSuggestedFriendsContextMenu;
|
||||
|
||||
//== PeopleContextMenu ===============================================================
|
||||
|
||||
|
|
@ -74,6 +75,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 +127,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 +258,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 +294,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"));
|
||||
|
|
@ -301,4 +312,36 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
|
|||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
//== SuggestedFriendsContextMenu ===============================================================
|
||||
|
||||
LLContextMenu* SuggestedFriendsContextMenu::createMenu()
|
||||
{
|
||||
// set up the callbacks for all of the avatar menu items
|
||||
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
|
||||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
LLContextMenu* menu;
|
||||
|
||||
// Set up for one person selected menu
|
||||
const LLUUID& id = mUUIDs.front();
|
||||
registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, id));
|
||||
registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, id));
|
||||
|
||||
// create the context menu from the XUI
|
||||
menu = createFromFile("menu_people_nearby.xml");
|
||||
buildContextMenu(*menu, 0x0);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void SuggestedFriendsContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
|
||||
{
|
||||
menuentry_vec_t items;
|
||||
menuentry_vec_t disabled_items;
|
||||
|
||||
items.push_back(std::string("view_profile"));
|
||||
items.push_back(std::string("add_friend"));
|
||||
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
} // namespace LLPanelPeopleMenus
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ private:
|
|||
bool enableContextMenuItem(const LLSD& userdata);
|
||||
bool checkContextMenuItem(const LLSD& userdata);
|
||||
void offerTeleport();
|
||||
void requestTeleport();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -58,8 +59,21 @@ protected:
|
|||
/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);
|
||||
};
|
||||
|
||||
/**
|
||||
* Menu used in the suggested friends list.
|
||||
*/
|
||||
class SuggestedFriendsContextMenu : public PeopleContextMenu
|
||||
{
|
||||
public:
|
||||
/*virtual*/ LLContextMenu * createMenu();
|
||||
|
||||
protected:
|
||||
/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);
|
||||
};
|
||||
|
||||
extern PeopleContextMenu gPeopleContextMenu;
|
||||
extern NearbyPeopleContextMenu gNearbyPeopleContextMenu;
|
||||
extern SuggestedFriendsContextMenu gSuggestedFriendsContextMenu;
|
||||
|
||||
} // namespace LLPanelPeopleMenus
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
|
|||
mZoomObjectFace(0),
|
||||
mVolumeSliderVisible(0),
|
||||
mWindowShade(NULL),
|
||||
mHideImmediately(false)
|
||||
mHideImmediately(false),
|
||||
mSecureURL(false)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
|
||||
mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
|
||||
|
|
@ -345,7 +346,7 @@ void LLPanelPrimMediaControls::updateShape()
|
|||
// Disable zoom if HUD
|
||||
mZoomCtrl->setEnabled(!is_hud);
|
||||
mUnzoomCtrl->setEnabled(!is_hud);
|
||||
mSecureLockIcon->setVisible(false);
|
||||
mSecureURL = false;
|
||||
mCurrentURL = media_impl->getCurrentMediaURL();
|
||||
|
||||
mBackCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate);
|
||||
|
|
@ -382,7 +383,7 @@ void LLPanelPrimMediaControls::updateShape()
|
|||
mVolumeSliderCtrl->setVisible(has_focus && shouldVolumeSliderBeVisible());
|
||||
|
||||
mWhitelistIcon->setVisible(false);
|
||||
mSecureLockIcon->setVisible(false);
|
||||
mSecureURL = false;
|
||||
if (mMediaPanelScroll)
|
||||
{
|
||||
mMediaPanelScroll->setVisible(false);
|
||||
|
|
@ -416,7 +417,7 @@ void LLPanelPrimMediaControls::updateShape()
|
|||
mMediaPlaySliderCtrl->setEnabled(true);
|
||||
}
|
||||
|
||||
// video vloume
|
||||
// video volume
|
||||
if(volume <= 0.0)
|
||||
{
|
||||
mMuteBtn->setToggleState(true);
|
||||
|
|
@ -492,10 +493,8 @@ void LLPanelPrimMediaControls::updateShape()
|
|||
std::string prefix = std::string("https://");
|
||||
std::string test_prefix = mCurrentURL.substr(0, prefix.length());
|
||||
LLStringUtil::toLower(test_prefix);
|
||||
if(test_prefix == prefix)
|
||||
{
|
||||
mSecureLockIcon->setVisible(has_focus);
|
||||
}
|
||||
mSecureURL = has_focus && (test_prefix == prefix);
|
||||
mCurrentURL = (mSecureURL ? " " + mCurrentURL : mCurrentURL);
|
||||
|
||||
if(mCurrentURL!=mPreviousURL)
|
||||
{
|
||||
|
|
@ -746,6 +745,9 @@ void LLPanelPrimMediaControls::draw()
|
|||
clearFaceOnFade();
|
||||
}
|
||||
}
|
||||
|
||||
// Show/hide the lock icon for secure browsing
|
||||
mSecureLockIcon->setVisible(mSecureURL && !mMediaAddress->hasFocus());
|
||||
|
||||
// Build rect for icon area in coord system of this panel
|
||||
// Assumes layout_stack is a direct child of this panel
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ private:
|
|||
bool mUpdateSlider;
|
||||
bool mClearFaceOnFade;
|
||||
bool mHideImmediately;
|
||||
bool mSecureURL;
|
||||
|
||||
LLMatrix4 mLastCameraMat;
|
||||
EZoomLevel mCurrentZoom;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llerror.h"
|
||||
#include "llimview.h"
|
||||
#include "llfloaterimcontainer.h"
|
||||
#include "llparticipantlist.h"
|
||||
|
|
@ -401,6 +402,8 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
|
|||
adjustParticipant(avatar_id);
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_FOLDERVIEW_TEST("add test avatar agents");
|
||||
|
||||
void LLParticipantList::adjustParticipant(const LLUUID& speaker_id)
|
||||
{
|
||||
LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id);
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,874 @@
|
|||
/**
|
||||
* @file llsnapshotlivepreview.cpp
|
||||
* @brief Implementation of llsnapshotlivepreview
|
||||
* @author Gilbert@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* 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 "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llagentui.h"
|
||||
#include "llcombobox.h"
|
||||
#include "lleconomy.h"
|
||||
#include "llfloaterperms.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloatersocial.h"
|
||||
#include "llimagebmp.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llimagejpeg.h"
|
||||
#include "llimagepng.h"
|
||||
#include "lllandmarkactions.h"
|
||||
#include "lllocalcliprect.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llslurl.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
#include "lltoolfocus.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewermenufile.h" // upload_new_resource()
|
||||
#include "llviewerstats.h"
|
||||
#include "llvfile.h"
|
||||
#include "llvfs.h"
|
||||
#include "llwebsharing.h"
|
||||
#include "llwindow.h"
|
||||
#include "llworld.h"
|
||||
|
||||
const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
|
||||
|
||||
F32 SHINE_TIME = 0.5f;
|
||||
F32 SHINE_WIDTH = 0.6f;
|
||||
F32 SHINE_OPACITY = 0.3f;
|
||||
F32 FALL_TIME = 0.6f;
|
||||
S32 BORDER_WIDTH = 6;
|
||||
|
||||
const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
|
||||
|
||||
std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
|
||||
|
||||
LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p)
|
||||
: LLView(p),
|
||||
mColor(1.f, 0.f, 0.f, 0.5f),
|
||||
mCurImageIndex(0),
|
||||
mPreviewImage(NULL),
|
||||
mThumbnailImage(NULL) ,
|
||||
mThumbnailWidth(0),
|
||||
mThumbnailHeight(0),
|
||||
mPreviewImageEncoded(NULL),
|
||||
mFormattedImage(NULL),
|
||||
mShineCountdown(0),
|
||||
mFlashAlpha(0.f),
|
||||
mNeedsFlash(TRUE),
|
||||
mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
|
||||
mDataSize(0),
|
||||
mSnapshotType(SNAPSHOT_POSTCARD),
|
||||
mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
|
||||
mSnapshotUpToDate(FALSE),
|
||||
mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
|
||||
mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
|
||||
mSnapshotActive(FALSE),
|
||||
mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
|
||||
{
|
||||
setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
|
||||
mSnapshotDelayTimer.setTimerExpirySec(0.0f);
|
||||
mSnapshotDelayTimer.start();
|
||||
// gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
|
||||
sList.insert(this);
|
||||
setFollowsAll();
|
||||
mWidth[0] = gViewerWindow->getWindowWidthRaw();
|
||||
mWidth[1] = gViewerWindow->getWindowWidthRaw();
|
||||
mHeight[0] = gViewerWindow->getWindowHeightRaw();
|
||||
mHeight[1] = gViewerWindow->getWindowHeightRaw();
|
||||
mImageScaled[0] = FALSE;
|
||||
mImageScaled[1] = FALSE;
|
||||
|
||||
mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
|
||||
mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
|
||||
mThumbnailUpdateLock = FALSE ;
|
||||
mThumbnailUpToDate = FALSE ;
|
||||
}
|
||||
|
||||
LLSnapshotLivePreview::~LLSnapshotLivePreview()
|
||||
{
|
||||
// delete images
|
||||
mPreviewImage = NULL;
|
||||
mPreviewImageEncoded = NULL;
|
||||
mFormattedImage = NULL;
|
||||
|
||||
// gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
|
||||
sList.erase(this);
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::setMaxImageSize(S32 size)
|
||||
{
|
||||
if(size < MAX_SNAPSHOT_IMAGE_SIZE)
|
||||
{
|
||||
mMaxImageSize = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
|
||||
{
|
||||
return mViewerImage[mCurImageIndex];
|
||||
}
|
||||
|
||||
F32 LLSnapshotLivePreview::getAspect()
|
||||
{
|
||||
F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
|
||||
F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
|
||||
|
||||
if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
|
||||
{
|
||||
return image_aspect_ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
return window_aspect_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
F32 LLSnapshotLivePreview::getImageAspect()
|
||||
{
|
||||
if (!getCurrentImage())
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
return getAspect() ;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
|
||||
{
|
||||
// Invalidate current image.
|
||||
lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
|
||||
if (getSnapshotUpToDate())
|
||||
{
|
||||
S32 old_image_index = mCurImageIndex;
|
||||
mCurImageIndex = (mCurImageIndex + 1) % 2;
|
||||
setSize(mWidth[old_image_index], mHeight[old_image_index]);
|
||||
mFallAnimTimer.start();
|
||||
}
|
||||
mSnapshotUpToDate = FALSE;
|
||||
|
||||
// Update snapshot source rect depending on whether we keep the aspect ratio.
|
||||
LLRect& rect = mImageRect[mCurImageIndex];
|
||||
rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
|
||||
F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
|
||||
F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
|
||||
|
||||
if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
|
||||
{
|
||||
if (image_aspect_ratio > window_aspect_ratio)
|
||||
{
|
||||
// trim off top and bottom
|
||||
S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio);
|
||||
rect.mBottom += (getRect().getHeight() - new_height) / 2;
|
||||
rect.mTop -= (getRect().getHeight() - new_height) / 2;
|
||||
}
|
||||
else if (image_aspect_ratio < window_aspect_ratio)
|
||||
{
|
||||
// trim off left and right
|
||||
S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio);
|
||||
rect.mLeft += (getRect().getWidth() - new_width) / 2;
|
||||
rect.mRight -= (getRect().getWidth() - new_width) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop shining animation.
|
||||
mShineAnimTimer.stop();
|
||||
|
||||
// Update snapshot if requested.
|
||||
if (new_snapshot)
|
||||
{
|
||||
mSnapshotDelayTimer.start();
|
||||
mSnapshotDelayTimer.setTimerExpirySec(delay);
|
||||
LLFloaterSnapshot::preUpdate();
|
||||
LLFloaterSocial::preUpdate();
|
||||
}
|
||||
|
||||
// Update thumbnail if requested.
|
||||
if(new_thumbnail)
|
||||
{
|
||||
mThumbnailUpToDate = FALSE ;
|
||||
}
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
|
||||
{
|
||||
llclamp(quality, 0, 100);
|
||||
if (quality != mSnapshotQuality)
|
||||
{
|
||||
mSnapshotQuality = quality;
|
||||
gSavedSettings.setS32("SnapshotQuality", quality);
|
||||
mSnapshotUpToDate = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
|
||||
{
|
||||
F32 line_width ;
|
||||
glGetFloatv(GL_LINE_WIDTH, &line_width) ;
|
||||
glLineWidth(2.0f * line_width) ;
|
||||
LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
|
||||
gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
|
||||
mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
|
||||
glLineWidth(line_width) ;
|
||||
|
||||
//draw four alpha rectangles to cover areas outside of the snapshot image
|
||||
if(!mKeepAspectRatio)
|
||||
{
|
||||
LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
|
||||
S32 dwl = 0, dwr = 0 ;
|
||||
if(mThumbnailWidth > mPreviewRect.getWidth())
|
||||
{
|
||||
dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
|
||||
dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
|
||||
|
||||
gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
|
||||
mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
|
||||
gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
|
||||
mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
|
||||
}
|
||||
|
||||
if(mThumbnailHeight > mPreviewRect.getHeight())
|
||||
{
|
||||
S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
|
||||
gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
|
||||
mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
|
||||
|
||||
dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
|
||||
gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
|
||||
mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//called when the frame is frozen.
|
||||
void LLSnapshotLivePreview::draw()
|
||||
{
|
||||
if (getCurrentImage() &&
|
||||
mPreviewImageEncoded.notNull() &&
|
||||
getSnapshotUpToDate())
|
||||
{
|
||||
LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
|
||||
gl_rect_2d(getRect(), bg_color);
|
||||
const LLRect& rect = getImageRect();
|
||||
LLRect shadow_rect = rect;
|
||||
shadow_rect.stretch(BORDER_WIDTH);
|
||||
gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10);
|
||||
|
||||
LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
|
||||
gGL.color4fv(image_color.mV);
|
||||
gGL.getTexUnit(0)->bind(getCurrentImage());
|
||||
// calculate UV scale
|
||||
F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
|
||||
F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
gGL.texCoord2f(uv_width, uv_height);
|
||||
gGL.vertex2i(rect.getWidth(), rect.getHeight() );
|
||||
|
||||
gGL.texCoord2f(0.f, uv_height);
|
||||
gGL.vertex2i(0, rect.getHeight() );
|
||||
|
||||
gGL.texCoord2f(0.f, 0.f);
|
||||
gGL.vertex2i(0, 0);
|
||||
|
||||
gGL.texCoord2f(uv_width, 0.f);
|
||||
gGL.vertex2i(rect.getWidth(), 0);
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
gGL.popMatrix();
|
||||
|
||||
gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
|
||||
gl_rect_2d(getRect());
|
||||
if (mNeedsFlash)
|
||||
{
|
||||
if (mFlashAlpha < 1.f)
|
||||
{
|
||||
mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
|
||||
}
|
||||
else
|
||||
{
|
||||
mNeedsFlash = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
|
||||
}
|
||||
|
||||
// Draw shining animation if appropriate.
|
||||
if (mShineCountdown > 0)
|
||||
{
|
||||
mShineCountdown--;
|
||||
if (mShineCountdown == 0)
|
||||
{
|
||||
mShineAnimTimer.start();
|
||||
}
|
||||
}
|
||||
else if (mShineAnimTimer.getStarted())
|
||||
{
|
||||
lldebugs << "Drawing shining animation" << llendl;
|
||||
F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
|
||||
|
||||
// draw "shine" effect
|
||||
LLLocalClipRect clip(getLocalRect());
|
||||
{
|
||||
// draw diagonal stripe with gradient that passes over screen
|
||||
S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
|
||||
S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
|
||||
S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
|
||||
S32 y1 = 0;
|
||||
S32 y2 = gViewerWindow->getWindowHeightScaled();
|
||||
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
gGL.color4f(1.f, 1.f, 1.f, 0.f);
|
||||
gGL.vertex2i(x1, y1);
|
||||
gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
|
||||
gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
|
||||
gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
|
||||
gGL.vertex2i(x2, y1);
|
||||
|
||||
gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
|
||||
gGL.vertex2i(x2, y1);
|
||||
gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
|
||||
gGL.color4f(1.f, 1.f, 1.f, 0.f);
|
||||
gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
|
||||
gGL.vertex2i(x3, y1);
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
|
||||
// if we're at the end of the animation, stop
|
||||
if (shine_interp >= 1.f)
|
||||
{
|
||||
mShineAnimTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw framing rectangle
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.color4f(1.f, 1.f, 1.f, 1.f);
|
||||
const LLRect& outline_rect = getImageRect();
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
|
||||
gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
|
||||
gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
|
||||
gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
|
||||
|
||||
gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
|
||||
gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
|
||||
gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
|
||||
gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
|
||||
|
||||
gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
|
||||
gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
|
||||
gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
|
||||
gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
|
||||
|
||||
gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
|
||||
gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
|
||||
gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
|
||||
gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
|
||||
// draw old image dropping away
|
||||
if (mFallAnimTimer.getStarted())
|
||||
{
|
||||
S32 old_image_index = (mCurImageIndex + 1) % 2;
|
||||
if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
|
||||
{
|
||||
lldebugs << "Drawing fall animation" << llendl;
|
||||
F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
|
||||
F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
|
||||
LLColor4 image_color(1.f, 1.f, 1.f, alpha);
|
||||
gGL.color4fv(image_color.mV);
|
||||
gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]);
|
||||
// calculate UV scale
|
||||
// *FIX get this to work with old image
|
||||
BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
|
||||
F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
|
||||
F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
LLRect& rect = mImageRect[old_image_index];
|
||||
gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
|
||||
gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
gGL.texCoord2f(uv_width, uv_height);
|
||||
gGL.vertex2i(rect.getWidth(), rect.getHeight() );
|
||||
|
||||
gGL.texCoord2f(0.f, uv_height);
|
||||
gGL.vertex2i(0, rect.getHeight() );
|
||||
|
||||
gGL.texCoord2f(0.f, 0.f);
|
||||
gGL.vertex2i(0, 0);
|
||||
|
||||
gGL.texCoord2f(uv_width, 0.f);
|
||||
gGL.vertex2i(rect.getWidth(), 0);
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
gGL.popMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
LLRect old_rect = getRect();
|
||||
LLView::reshape(width, height, called_from_parent);
|
||||
if (old_rect.getWidth() != width || old_rect.getHeight() != height)
|
||||
{
|
||||
lldebugs << "window reshaped, updating thumbnail" << llendl;
|
||||
updateSnapshot(FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLSnapshotLivePreview::setThumbnailImageSize()
|
||||
{
|
||||
if(getWidth() < 10 || getHeight() < 10)
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
S32 window_width = gViewerWindow->getWindowWidthRaw() ;
|
||||
S32 window_height = gViewerWindow->getWindowHeightRaw() ;
|
||||
|
||||
F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
|
||||
|
||||
// UI size for thumbnail
|
||||
// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
|
||||
const LLRect& thumbnail_rect = mThumbnailPlaceholderRect;
|
||||
S32 max_width = thumbnail_rect.getWidth();
|
||||
S32 max_height = thumbnail_rect.getHeight();
|
||||
|
||||
if (window_aspect_ratio > (F32)max_width / max_height)
|
||||
{
|
||||
// image too wide, shrink to width
|
||||
mThumbnailWidth = max_width;
|
||||
mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
// image too tall, shrink to height
|
||||
mThumbnailHeight = max_height;
|
||||
mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
|
||||
}
|
||||
|
||||
if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
|
||||
{
|
||||
return FALSE ;//if the window is too small, ignore thumbnail updating.
|
||||
}
|
||||
|
||||
S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
|
||||
if(!mKeepAspectRatio)
|
||||
{
|
||||
F32 ratio_x = (F32)getWidth() / window_width ;
|
||||
F32 ratio_y = (F32)getHeight() / window_height ;
|
||||
|
||||
//if(getWidth() > window_width ||
|
||||
// getHeight() > window_height )
|
||||
{
|
||||
if(ratio_x > ratio_y)
|
||||
{
|
||||
top = (S32)(top * ratio_y / ratio_x) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = (S32)(right * ratio_x / ratio_y) ;
|
||||
}
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// right = (S32)(right * ratio_x) ;
|
||||
// top = (S32)(top * ratio_y) ;
|
||||
//}
|
||||
left = (S32)((mThumbnailWidth - right) * 0.5f) ;
|
||||
bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
|
||||
top += bottom ;
|
||||
right += left ;
|
||||
}
|
||||
mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
|
||||
|
||||
return TRUE ;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
|
||||
{
|
||||
if(mThumbnailUpdateLock) //in the process of updating
|
||||
{
|
||||
return ;
|
||||
}
|
||||
if(getThumbnailUpToDate() && !force_update)//already updated
|
||||
{
|
||||
return ;
|
||||
}
|
||||
if(getWidth() < 10 || getHeight() < 10)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
////lock updating
|
||||
mThumbnailUpdateLock = TRUE ;
|
||||
|
||||
if(!setThumbnailImageSize())
|
||||
{
|
||||
mThumbnailUpdateLock = FALSE ;
|
||||
mThumbnailUpToDate = TRUE ;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(mThumbnailImage)
|
||||
{
|
||||
resetThumbnailImage() ;
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
if(!gViewerWindow->thumbnailSnapshot(raw,
|
||||
mThumbnailWidth, mThumbnailHeight,
|
||||
gSavedSettings.getBOOL("RenderUIInSnapshot"),
|
||||
FALSE,
|
||||
mSnapshotBufferType) )
|
||||
{
|
||||
raw = NULL ;
|
||||
}
|
||||
|
||||
if(raw)
|
||||
{
|
||||
raw->expandToPowerOfTwo();
|
||||
mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
|
||||
mThumbnailUpToDate = TRUE ;
|
||||
}
|
||||
|
||||
//unlock updating
|
||||
mThumbnailUpdateLock = FALSE ;
|
||||
}
|
||||
|
||||
|
||||
// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
|
||||
// Returns TRUE if new snapshot generated, FALSE otherwise.
|
||||
//static
|
||||
BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
|
||||
if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
|
||||
{
|
||||
llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// If we're in freeze-frame mode and camera has moved, update snapshot.
|
||||
LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
|
||||
LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
|
||||
if (gSavedSettings.getBOOL("FreezeTime") &&
|
||||
(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
|
||||
{
|
||||
previewp->mCameraPos = new_camera_pos;
|
||||
previewp->mCameraRot = new_camera_rot;
|
||||
// request a new snapshot whenever the camera moves, with a time delay
|
||||
BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot");
|
||||
lldebugs << "camera moved, updating thumbnail" << llendl;
|
||||
previewp->updateSnapshot(
|
||||
autosnap, // whether a new snapshot is needed or merely invalidate the existing one
|
||||
FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
|
||||
autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true.
|
||||
}
|
||||
|
||||
// see if it's time yet to snap the shot and bomb out otherwise.
|
||||
previewp->mSnapshotActive =
|
||||
(previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired())
|
||||
&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
|
||||
if ( ! previewp->mSnapshotActive)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// time to produce a snapshot
|
||||
previewp->setThumbnailImageSize();
|
||||
|
||||
lldebugs << "producing snapshot" << llendl;
|
||||
if (!previewp->mPreviewImage)
|
||||
{
|
||||
previewp->mPreviewImage = new LLImageRaw;
|
||||
}
|
||||
|
||||
if (!previewp->mPreviewImageEncoded)
|
||||
{
|
||||
previewp->mPreviewImageEncoded = new LLImageRaw;
|
||||
}
|
||||
|
||||
previewp->setVisible(FALSE);
|
||||
previewp->setEnabled(FALSE);
|
||||
|
||||
previewp->getWindow()->incBusyCount();
|
||||
previewp->setImageScaled(FALSE);
|
||||
|
||||
// grab the raw image and encode it into desired format
|
||||
if(gViewerWindow->rawSnapshot(
|
||||
previewp->mPreviewImage,
|
||||
previewp->getWidth(),
|
||||
previewp->getHeight(),
|
||||
previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
|
||||
previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
|
||||
gSavedSettings.getBOOL("RenderUIInSnapshot"),
|
||||
FALSE,
|
||||
previewp->mSnapshotBufferType,
|
||||
previewp->getMaxImageSize()))
|
||||
{
|
||||
previewp->mPreviewImageEncoded->resize(
|
||||
previewp->mPreviewImage->getWidth(),
|
||||
previewp->mPreviewImage->getHeight(),
|
||||
previewp->mPreviewImage->getComponents());
|
||||
|
||||
if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
|
||||
{
|
||||
lldebugs << "Encoding new image of format J2C" << llendl;
|
||||
LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
|
||||
LLPointer<LLImageRaw> scaled = new LLImageRaw(
|
||||
previewp->mPreviewImage->getData(),
|
||||
previewp->mPreviewImage->getWidth(),
|
||||
previewp->mPreviewImage->getHeight(),
|
||||
previewp->mPreviewImage->getComponents());
|
||||
|
||||
scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
|
||||
previewp->setImageScaled(TRUE);
|
||||
if (formatted->encode(scaled, 0.f))
|
||||
{
|
||||
previewp->mDataSize = formatted->getDataSize();
|
||||
formatted->decode(previewp->mPreviewImageEncoded, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete any existing image
|
||||
previewp->mFormattedImage = NULL;
|
||||
// now create the new one of the appropriate format.
|
||||
LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
|
||||
lldebugs << "Encoding new image of format " << format << llendl;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
|
||||
previewp->mFormattedImage = new LLImagePNG();
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
|
||||
previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality);
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
|
||||
previewp->mFormattedImage = new LLImageBMP();
|
||||
break;
|
||||
}
|
||||
if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
|
||||
{
|
||||
previewp->mDataSize = previewp->mFormattedImage->getDataSize();
|
||||
// special case BMP to copy instead of decode otherwise decode will crash.
|
||||
if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
|
||||
{
|
||||
previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> scaled = new LLImageRaw(
|
||||
previewp->mPreviewImageEncoded->getData(),
|
||||
previewp->mPreviewImageEncoded->getWidth(),
|
||||
previewp->mPreviewImageEncoded->getHeight(),
|
||||
previewp->mPreviewImageEncoded->getComponents());
|
||||
|
||||
if(!scaled->isBufferInvalid())
|
||||
{
|
||||
// leave original image dimensions, just scale up texture buffer
|
||||
if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
|
||||
{
|
||||
// go ahead and shrink image to appropriate power of 2 for display
|
||||
scaled->biasedScaleToPowerOfTwo(1024);
|
||||
previewp->setImageScaled(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// expand image but keep original image data intact
|
||||
scaled->expandToPowerOfTwo(1024, FALSE);
|
||||
}
|
||||
|
||||
previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
|
||||
LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
|
||||
gGL.getTexUnit(0)->bind(curr_preview_image);
|
||||
if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
|
||||
{
|
||||
curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
|
||||
}
|
||||
curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
|
||||
previewp->mSnapshotUpToDate = TRUE;
|
||||
previewp->generateThumbnailImage(TRUE) ;
|
||||
|
||||
previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
|
||||
previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
|
||||
}
|
||||
}
|
||||
previewp->getWindow()->decBusyCount();
|
||||
// only show fullscreen preview when in freeze frame mode
|
||||
previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
|
||||
previewp->mSnapshotDelayTimer.stop();
|
||||
previewp->mSnapshotActive = FALSE;
|
||||
|
||||
if(!previewp->getThumbnailUpToDate())
|
||||
{
|
||||
previewp->generateThumbnailImage() ;
|
||||
}
|
||||
lldebugs << "done creating snapshot" << llendl;
|
||||
LLFloaterSnapshot::postUpdate();
|
||||
LLFloaterSocial::postUpdate();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::setSize(S32 w, S32 h)
|
||||
{
|
||||
lldebugs << "setSize(" << w << ", " << h << ")" << llendl;
|
||||
setWidth(w);
|
||||
setHeight(h);
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
|
||||
{
|
||||
w = getWidth();
|
||||
h = getHeight();
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::saveTexture()
|
||||
{
|
||||
lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl;
|
||||
// gen a new uuid for this asset
|
||||
LLTransactionID tid;
|
||||
tid.generate();
|
||||
LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
|
||||
|
||||
LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
|
||||
LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(),
|
||||
mPreviewImage->getWidth(),
|
||||
mPreviewImage->getHeight(),
|
||||
mPreviewImage->getComponents());
|
||||
|
||||
scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
|
||||
lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl;
|
||||
|
||||
if (formatted->encode(scaled, 0.0f))
|
||||
{
|
||||
LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
|
||||
std::string pos_string;
|
||||
LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
|
||||
std::string who_took_it;
|
||||
LLAgentUI::buildFullname(who_took_it);
|
||||
LLAssetStorage::LLStoreAssetCallback callback = NULL;
|
||||
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
|
||||
void *userdata = NULL;
|
||||
upload_new_resource(tid, // tid
|
||||
LLAssetType::AT_TEXTURE,
|
||||
"Snapshot : " + pos_string,
|
||||
"Taken by " + who_took_it + " at " + pos_string,
|
||||
0,
|
||||
LLFolderType::FT_SNAPSHOT_CATEGORY,
|
||||
LLInventoryType::IT_SNAPSHOT,
|
||||
PERM_ALL, // Note: Snapshots to inventory is a special case of content upload
|
||||
LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads
|
||||
LLFloaterPerms::getEveryonePerms(),
|
||||
"Snapshot : " + pos_string,
|
||||
callback, expected_upload_cost, userdata);
|
||||
gViewerWindow->playSnapshotAnimAndSound();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("ErrorEncodingSnapshot");
|
||||
llwarns << "Error encoding snapshot" << llendl;
|
||||
}
|
||||
|
||||
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );
|
||||
|
||||
mDataSize = 0;
|
||||
}
|
||||
|
||||
BOOL LLSnapshotLivePreview::saveLocal()
|
||||
{
|
||||
BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
|
||||
|
||||
if(success)
|
||||
{
|
||||
gViewerWindow->playSnapshotAnimAndSound();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::saveWeb()
|
||||
{
|
||||
// *FIX: Will break if the window closes because of CloseSnapshotOnKeep!
|
||||
// Needs to pass on ownership of the image.
|
||||
LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
|
||||
if(!jpg)
|
||||
{
|
||||
llwarns << "Formatted image not a JPEG" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD metadata;
|
||||
metadata["description"] = getChild<LLLineEditor>("description")->getText();
|
||||
|
||||
LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(),
|
||||
boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4));
|
||||
|
||||
gViewerWindow->playSnapshotAnimAndSound();
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z)
|
||||
{
|
||||
metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString();
|
||||
|
||||
LLWebSharing::instance().shareSnapshot(snapshot, metadata);
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* @file llsnapshotlivepreview.h
|
||||
* @brief Header file for llsnapshotlivepreview
|
||||
* @author Gilbert@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* 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_LLSNAPSHOTLIVEPREVIEW_H
|
||||
#define LL_LLSNAPSHOTLIVEPREVIEW_H
|
||||
|
||||
#include "llpanelsnapshot.h"
|
||||
#include "llviewerwindow.h"
|
||||
|
||||
class LLImageJPEG;
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLSnapshotLivePreview
|
||||
///----------------------------------------------------------------------------
|
||||
class LLSnapshotLivePreview : public LLView
|
||||
{
|
||||
LOG_CLASS(LLSnapshotLivePreview);
|
||||
public:
|
||||
enum ESnapshotType
|
||||
{
|
||||
SNAPSHOT_POSTCARD,
|
||||
SNAPSHOT_TEXTURE,
|
||||
SNAPSHOT_LOCAL,
|
||||
SNAPSHOT_WEB
|
||||
};
|
||||
|
||||
|
||||
struct Params : public LLInitParam::Block<Params, LLView::Params>
|
||||
{
|
||||
Params()
|
||||
{
|
||||
name = "snapshot_live_preview";
|
||||
mouse_opaque = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
|
||||
~LLSnapshotLivePreview();
|
||||
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
|
||||
|
||||
void setSize(S32 w, S32 h);
|
||||
void setWidth(S32 w) { mWidth[mCurImageIndex] = w; }
|
||||
void setHeight(S32 h) { mHeight[mCurImageIndex] = h; }
|
||||
void getSize(S32& w, S32& h) const;
|
||||
S32 getWidth() const { return mWidth[mCurImageIndex]; }
|
||||
S32 getHeight() const { return mHeight[mCurImageIndex]; }
|
||||
S32 getDataSize() const { return mDataSize; }
|
||||
void setMaxImageSize(S32 size) ;
|
||||
S32 getMaxImageSize() {return mMaxImageSize ;}
|
||||
|
||||
ESnapshotType getSnapshotType() const { return mSnapshotType; }
|
||||
LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
|
||||
BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
|
||||
BOOL isSnapshotActive() { return mSnapshotActive; }
|
||||
LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
|
||||
S32 getThumbnailWidth() const { return mThumbnailWidth ; }
|
||||
S32 getThumbnailHeight() const { return mThumbnailHeight ; }
|
||||
BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
|
||||
BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
|
||||
LLViewerTexture* getCurrentImage();
|
||||
F32 getImageAspect();
|
||||
F32 getAspect() ;
|
||||
const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
|
||||
BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
|
||||
void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
|
||||
const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
|
||||
|
||||
void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
|
||||
void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
|
||||
void setSnapshotQuality(S32 quality);
|
||||
void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
|
||||
void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
|
||||
void saveWeb();
|
||||
void saveTexture();
|
||||
BOOL saveLocal();
|
||||
|
||||
LLPointer<LLImageFormatted> getFormattedImage() const { return mFormattedImage; }
|
||||
LLPointer<LLImageRaw> getEncodedImage() const { return mPreviewImageEncoded; }
|
||||
|
||||
/// Sets size of preview thumbnail image and thhe surrounding rect.
|
||||
void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; }
|
||||
BOOL setThumbnailImageSize() ;
|
||||
void generateThumbnailImage(BOOL force_update = FALSE) ;
|
||||
void resetThumbnailImage() { mThumbnailImage = NULL ; }
|
||||
void drawPreviewRect(S32 offset_x, S32 offset_y) ;
|
||||
|
||||
// Returns TRUE when snapshot generated, FALSE otherwise.
|
||||
static BOOL onIdle( void* snapshot_preview );
|
||||
|
||||
// callback for region name resolve
|
||||
void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z);
|
||||
|
||||
private:
|
||||
LLColor4 mColor;
|
||||
LLPointer<LLViewerTexture> mViewerImage[2]; //used to represent the scene when the frame is frozen.
|
||||
LLRect mImageRect[2];
|
||||
S32 mWidth[2];
|
||||
S32 mHeight[2];
|
||||
BOOL mImageScaled[2];
|
||||
S32 mMaxImageSize ;
|
||||
|
||||
//thumbnail image
|
||||
LLPointer<LLViewerTexture> mThumbnailImage ;
|
||||
S32 mThumbnailWidth ;
|
||||
S32 mThumbnailHeight ;
|
||||
LLRect mPreviewRect ;
|
||||
BOOL mThumbnailUpdateLock ;
|
||||
BOOL mThumbnailUpToDate ;
|
||||
LLRect mThumbnailPlaceholderRect;
|
||||
|
||||
S32 mCurImageIndex;
|
||||
LLPointer<LLImageRaw> mPreviewImage;
|
||||
LLPointer<LLImageRaw> mPreviewImageEncoded;
|
||||
LLPointer<LLImageFormatted> mFormattedImage;
|
||||
LLFrameTimer mSnapshotDelayTimer;
|
||||
S32 mShineCountdown;
|
||||
LLFrameTimer mShineAnimTimer;
|
||||
F32 mFlashAlpha;
|
||||
BOOL mNeedsFlash;
|
||||
LLVector3d mPosTakenGlobal;
|
||||
S32 mSnapshotQuality;
|
||||
S32 mDataSize;
|
||||
ESnapshotType mSnapshotType;
|
||||
LLFloaterSnapshot::ESnapshotFormat mSnapshotFormat;
|
||||
BOOL mSnapshotUpToDate;
|
||||
LLFrameTimer mFallAnimTimer;
|
||||
LLVector3 mCameraPos;
|
||||
LLQuaternion mCameraRot;
|
||||
BOOL mSnapshotActive;
|
||||
LLViewerWindow::ESnapshotType mSnapshotBufferType;
|
||||
|
||||
public:
|
||||
static std::set<LLSnapshotLivePreview*> sList;
|
||||
BOOL mKeepAspectRatio ;
|
||||
};
|
||||
|
||||
#endif // LL_LLSNAPSHOTLIVEPREVIEW_H
|
||||
|
||||
|
|
@ -118,6 +118,11 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)
|
|||
}
|
||||
}
|
||||
|
||||
LLPanel * LLSysWellWindow::findItemByID(const LLUUID& id)
|
||||
{
|
||||
return mMessageList->getItemByValue(id);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------
|
||||
void LLSysWellWindow::initChannel()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
|
|||
|
||||
if(!mIsGroupMsg)
|
||||
{
|
||||
mAvatarName->setValue(p.from);
|
||||
mAvatarName->setValue(p.from);
|
||||
}
|
||||
mTime->setValue(p.time);
|
||||
mSessionID = p.session_id;
|
||||
|
|
@ -164,7 +164,7 @@ void LLToastIMPanel::spawnNameToolTip()
|
|||
params.background_visible(false);
|
||||
if(!mIsGroupMsg)
|
||||
{
|
||||
params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
|
||||
params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,22 +103,29 @@ LLSD LLURLHistory::getURLHistory(const std::string& collection)
|
|||
// static
|
||||
void LLURLHistory::addURL(const std::string& collection, const std::string& url)
|
||||
{
|
||||
if(! url.empty())
|
||||
if(!url.empty())
|
||||
{
|
||||
sHistorySD[collection].insert(0, url);
|
||||
LLURI u(url);
|
||||
std::string simplified_url = u.scheme() + "://" + u.authority() + u.path();
|
||||
sHistorySD[collection].insert(0, simplified_url);
|
||||
LLURLHistory::limitSize(collection);
|
||||
}
|
||||
}
|
||||
// static
|
||||
void LLURLHistory::removeURL(const std::string& collection, const std::string& url)
|
||||
{
|
||||
for(int index = 0; index < sHistorySD[collection].size(); index++)
|
||||
if(!url.empty())
|
||||
{
|
||||
if(sHistorySD[collection].get(index).asString() == url)
|
||||
{
|
||||
sHistorySD[collection].erase(index);
|
||||
}
|
||||
}
|
||||
LLURI u(url);
|
||||
std::string simplified_url = u.scheme() + "://" + u.authority() + u.path();
|
||||
for(int index = 0; index < sHistorySD[collection].size(); index++)
|
||||
{
|
||||
if(sHistorySD[collection].get(index).asString() == simplified_url)
|
||||
{
|
||||
sHistorySD[collection].erase(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
#include "llfloatersettingsdebug.h"
|
||||
#include "llfloatersidepanelcontainer.h"
|
||||
#include "llfloatersnapshot.h"
|
||||
#include "llfloatersocial.h"
|
||||
#include "llfloatersounddevices.h"
|
||||
#include "llfloaterspellchecksettings.h"
|
||||
#include "llfloatertelehub.h"
|
||||
|
|
@ -303,6 +304,7 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
|
||||
LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
|
||||
LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
|
||||
LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSocial>);
|
||||
LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
|
||||
LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
|
||||
LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
|
||||
|
|
@ -311,7 +313,7 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
|
||||
LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
|
||||
LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
|
||||
LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
|
||||
LLFloaterUIPreviewUtil::registerFloater();
|
||||
LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2000,7 +2000,12 @@ void LLViewerMediaImpl::loadURI()
|
|||
"<>#%"
|
||||
";/?:@&=",
|
||||
false);
|
||||
llinfos << "Asking media source to load URI: " << uri << llendl;
|
||||
{
|
||||
// Do not log the query parts
|
||||
LLURI u(uri);
|
||||
std::string sanitized_uri = (u.query().empty() ? uri : u.scheme() + "://" + u.authority() + u.path());
|
||||
llinfos << "Asking media source to load URI: " << sanitized_uri << llendl;
|
||||
}
|
||||
|
||||
mMediaSource->loadURI( uri );
|
||||
|
||||
|
|
@ -2567,7 +2572,12 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
|
|||
if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
|
||||
{
|
||||
// Helpful to have media urls in log file. Shouldn't be spammy.
|
||||
llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
|
||||
{
|
||||
// Do not log the query parts
|
||||
LLURI u(url);
|
||||
std::string sanitized_url = (u.query().empty() ? url : u.scheme() + "://" + u.authority() + u.path());
|
||||
llinfos << "NOT LOADING media id= " << mTextureId << " url=" << sanitized_url << ", mime_type=" << mime_type << llendl;
|
||||
}
|
||||
|
||||
// This impl should not be loaded at this time.
|
||||
LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
|
||||
|
|
@ -2582,7 +2592,12 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
|
|||
void LLViewerMediaImpl::navigateInternal()
|
||||
{
|
||||
// Helpful to have media urls in log file. Shouldn't be spammy.
|
||||
llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
|
||||
{
|
||||
// Do not log the query parts
|
||||
LLURI u(mMediaURL);
|
||||
std::string sanitized_url = (u.query().empty() ? mMediaURL : u.scheme() + "://" + u.authority() + u.path());
|
||||
llinfos << "media id= " << mTextureId << " url=" << sanitized_url << ", mime_type=" << mMimeType << llendl;
|
||||
}
|
||||
|
||||
if(mNavigateSuspended)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,11 +40,13 @@
|
|||
#include "llinventorypanel.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llviewereventrecorder.h"
|
||||
|
||||
// newview includes
|
||||
#include "llagent.h"
|
||||
#include "llagentaccess.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llagentui.h"
|
||||
#include "llagentwearables.h"
|
||||
#include "llagentpilot.h"
|
||||
#include "llcompilequeue.h"
|
||||
|
|
@ -52,6 +54,7 @@
|
|||
#include "lldaycyclemanager.h"
|
||||
#include "lldebugview.h"
|
||||
#include "llenvmanager.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llfilepicker.h"
|
||||
#include "llfirstuse.h"
|
||||
#include "llfloaterbuy.h"
|
||||
|
|
@ -1952,6 +1955,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 +8460,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 +8720,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");
|
||||
|
|
|
|||
|
|
@ -2221,7 +2221,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
|
||||
|
|
@ -2989,6 +2989,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
|
|||
break;
|
||||
|
||||
case IM_LURE_USER:
|
||||
case IM_TELEPORT_REQUEST:
|
||||
{
|
||||
if (is_muted)
|
||||
{
|
||||
|
|
@ -3011,7 +3012,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);
|
||||
|
|
@ -3083,12 +3085,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;
|
||||
|
|
@ -6866,6 +6878,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;
|
||||
|
|
@ -6879,50 +6936,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;
|
||||
|
|
@ -6962,6 +6981,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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1587,6 +1587,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
|||
capabilityNames.append("EnvironmentSettings");
|
||||
capabilityNames.append("EstateChangeInfo");
|
||||
capabilityNames.append("EventQueueGet");
|
||||
capabilityNames.append("FacebookConnect");
|
||||
//capabilityNames.append("FacebookRedirect");
|
||||
|
||||
if (gSavedSettings.getBOOL("UseHTTPInventory"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -148,9 +148,6 @@ public:
|
|||
LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << llendl;
|
||||
LLWebProfile::reportImageUploadStatus(true);
|
||||
}
|
||||
|
||||
private:
|
||||
LLPointer<LLImageFormatted> mImagep;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -172,7 +169,7 @@ public:
|
|||
headers["Cookie"] = LLWebProfile::getAuthCookie();
|
||||
const std::string& redir_url = content["location"];
|
||||
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl;
|
||||
LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
|
||||
LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder(), headers);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -518,17 +518,21 @@ bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID&
|
|||
case MAP_ITEM_LAND_FOR_SALE: // land for sale
|
||||
case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale
|
||||
{
|
||||
F32 cost_per_sqm = 0.0f;
|
||||
if ((F32)extra > 0)
|
||||
{
|
||||
cost_per_sqm = (F32)extra2 / (F32)extra;
|
||||
}
|
||||
|
||||
static LLUIString tooltip_fmt = LLTrans::getString("worldmap_item_tooltip_format");
|
||||
|
||||
tooltip_fmt.setArg("[AREA]", llformat("%d", extra));
|
||||
tooltip_fmt.setArg("[PRICE]", llformat("%d", extra2));
|
||||
tooltip_fmt.setArg("[PRICE_PER_SQM]", llformat("%.1f", cost_per_sqm));
|
||||
|
||||
// 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)
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 365 B |
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
|
|
@ -148,6 +148,7 @@ with the same filename but different name
|
|||
<texture name="Command_Preferences_Icon" file_name="toolbar_icons/preferences.png" preload="true" />
|
||||
<texture name="Command_Profile_Icon" file_name="toolbar_icons/profile.png" preload="true" />
|
||||
<texture name="Command_Search_Icon" file_name="toolbar_icons/search.png" preload="true" />
|
||||
<texture name="Command_Social_Icon" file_name="toolbar_icons/facebook.png" preload="true" />
|
||||
<texture name="Command_Snapshot_Icon" file_name="toolbar_icons/snapshot.png" preload="true" />
|
||||
<texture name="Command_Speak_Icon" file_name="toolbar_icons/speak.png" preload="true" />
|
||||
<texture name="Command_View_Icon" file_name="toolbar_icons/view.png" preload="true" />
|
||||
|
|
@ -202,6 +203,8 @@ with the same filename but different name
|
|||
<texture name="ExternalBrowser_Off" file_name="icons/ExternalBrowser_Off.png" preload="false" />
|
||||
<texture name="Edit_Wrench" file_name="icons/Edit_Wrench.png" preload="false" />
|
||||
|
||||
<texture name="Facebook_Icon" file_name="icons/Facebook.png" preload="false" />
|
||||
|
||||
<texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" />
|
||||
<texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" />
|
||||
<texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />
|
||||
|
|
@ -326,6 +329,8 @@ with the same filename but different name
|
|||
|
||||
<texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" />
|
||||
|
||||
<texture name="Map_Placeholder_Icon" file_name="icons/map_placeholder.png" preload="true" />
|
||||
|
||||
<texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
|
||||
<texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
|
||||
|
||||
|
|
@ -568,6 +573,7 @@ with the same filename but different name
|
|||
<texture name="Snapshot_Email" file_name="snapshot_email.png" preload="false" />
|
||||
<texture name="Snapshot_Inventory" file_name="toolbar_icons/inventory.png" preload="false" />
|
||||
<texture name="Snapshot_Profile" file_name="toolbar_icons/profile.png" preload="false" />
|
||||
<texture name="Snapshot_Facebook" file_name="toolbar_icons/facebook.png" preload="false" />
|
||||
|
||||
<texture name="startup_logo" file_name="windows/startup_logo.png" preload="true" />
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater name="floater_fbc_web"
|
||||
help_topic="fbc_web"
|
||||
width="780"
|
||||
height="775"
|
||||
save_rect="true"
|
||||
single_instance="true"
|
||||
reuse_instance="false"
|
||||
filename="floater_web_content.xml"/>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue