summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags6
-rwxr-xr-xBuildParams14
-rwxr-xr-xautobuild.xml6
-rwxr-xr-xdoc/contributions.txt39
-rwxr-xr-xindra/cmake/BuildVersion.cmake16
-rw-r--r--[-rwxr-xr-x]indra/cmake/LLAddBuildTest.cmake0
-rwxr-xr-xindra/cmake/Variables.cmake11
-rwxr-xr-xindra/edit-me-to-trigger-new-build.txt1
-rwxr-xr-xindra/integration_tests/llui_libtest/CMakeLists.txt3
-rwxr-xr-xindra/lib/python/indra/util/llmanifest.py18
-rwxr-xr-xindra/llcommon/llsys.cpp15
-rw-r--r--indra/llcommon/llversionviewer.h41
-rwxr-xr-xindra/llcommon/tests/llprocess_test.cpp14
-rwxr-xr-xindra/llimage/llimage.cpp11
-rwxr-xr-xindra/llimage/llimage.h4
-rwxr-xr-xindra/llmath/llcamera.cpp86
-rwxr-xr-xindra/llmath/llcamera.h37
-rwxr-xr-xindra/llmath/v4color.h2
-rwxr-xr-xindra/llmessage/llcurl.cpp4
-rwxr-xr-xindra/llmessage/llinstantmessage.h2
-rwxr-xr-xindra/llprimitive/llmodel.cpp20
-rwxr-xr-xindra/llrender/llgl.cpp3
-rwxr-xr-xindra/llrender/llgl.h1
-rwxr-xr-xindra/llrender/llglheaders.h5
-rwxr-xr-x[-rw-r--r--]indra/llrender/llimagegl.cpp0
-rwxr-xr-xindra/llrender/llrendertarget.cpp9
-rwxr-xr-xindra/llui/CMakeLists.txt4
-rwxr-xr-xindra/llui/llbutton.cpp9
-rwxr-xr-xindra/llui/llbutton.h4
-rwxr-xr-xindra/llui/llchatentry.cpp10
-rwxr-xr-xindra/llui/llchatentry.h6
-rwxr-xr-xindra/llui/llfloater.cpp58
-rwxr-xr-xindra/llui/llfloater.h6
-rwxr-xr-xindra/llui/llfloaterreg.cpp12
-rwxr-xr-xindra/llui/llfolderview.cpp26
-rwxr-xr-xindra/llui/llfolderviewitem.cpp30
-rwxr-xr-xindra/llui/llfolderviewitem.h1
-rwxr-xr-xindra/llui/llfolderviewmodel.cpp2
-rwxr-xr-xindra/llui/llfolderviewmodel.h31
-rwxr-xr-xindra/llui/lllayoutstack.cpp102
-rwxr-xr-xindra/llui/lllayoutstack.h10
-rwxr-xr-xindra/llui/llmenugl.cpp12
-rwxr-xr-xindra/llui/llnotifications.cpp3
-rwxr-xr-xindra/llui/llnotifications.h4
-rw-r--r--indra/llui/llnotificationslistener.cpp359
-rw-r--r--indra/llui/llnotificationslistener.h69
-rwxr-xr-xindra/llui/llresizebar.cpp110
-rwxr-xr-xindra/llui/llresizebar.h52
-rwxr-xr-xindra/llui/llscrolllistcolumn.cpp3
-rwxr-xr-xindra/llui/llscrolllistctrl.cpp18
-rwxr-xr-xindra/llui/llscrolllistctrl.h4
-rwxr-xr-xindra/llui/lltabcontainer.cpp56
-rwxr-xr-xindra/llui/lltextbase.cpp89
-rwxr-xr-xindra/llui/lltextbase.h8
-rwxr-xr-xindra/llui/lltexteditor.cpp82
-rwxr-xr-xindra/llui/lltexteditor.h3
-rwxr-xr-xindra/llui/lltoolbar.cpp4
-rwxr-xr-xindra/llui/lltoolbar.h2
-rwxr-xr-xindra/llui/lluictrl.cpp20
-rwxr-xr-xindra/llui/llurlaction.cpp42
-rwxr-xr-xindra/llui/llurlaction.h4
-rwxr-xr-xindra/llui/llurlentry.cpp4
-rwxr-xr-xindra/llui/llview.cpp51
-rw-r--r--indra/llui/llviewereventrecorder.cpp296
-rw-r--r--indra/llui/llviewereventrecorder.h103
-rwxr-xr-xindra/llvfs/lldir.h2
-rwxr-xr-xindra/llwindow/CMakeLists.txt3
-rw-r--r--indra/llwindow/llappdelegate-objc.h48
-rwxr-xr-xindra/llwindow/llkeyboard.h5
-rwxr-xr-xindra/llwindow/llkeyboardheadless.cpp7
-rwxr-xr-xindra/llwindow/llkeyboardheadless.h3
-rwxr-xr-xindra/llwindow/llkeyboardmacosx.cpp37
-rwxr-xr-xindra/llwindow/llkeyboardmacosx.h10
-rw-r--r--indra/llwindow/llopenglview-objc.h110
-rw-r--r--indra/llwindow/llopenglview-objc.mm686
-rwxr-xr-xindra/llwindow/llwindowmacosx-objc.h112
-rwxr-xr-xindra/llwindow/llwindowmacosx-objc.mm384
-rwxr-xr-xindra/llwindow/llwindowmacosx.cpp2756
-rwxr-xr-xindra/llwindow/llwindowmacosx.h68
-rwxr-xr-xindra/llwindow/llwindowwin32.cpp19
-rwxr-xr-xindra/llxml/llcontrol.cpp162
-rwxr-xr-xindra/llxml/llcontrol.h49
-rwxr-xr-xindra/llxml/tests/llcontrol_test.cpp6
-rwxr-xr-xindra/lscript/lscript_compile/indra.l2
-rw-r--r--indra/mac_updater/mac_updater.cpp1266
-rwxr-xr-xindra/media_plugins/quicktime/media_plugin_quicktime.cpp48
-rwxr-xr-xindra/media_plugins/webkit/mac_volume_catcher.cpp8
-rwxr-xr-xindra/newview/CMakeLists.txt32
-rwxr-xr-xindra/newview/Info-SecondLife.plist30
-rw-r--r--indra/newview/SecondLife.nibbin0 -> 12348 bytes
-rwxr-xr-xindra/newview/SecondLife.nib/classes.nib4
-rwxr-xr-xindra/newview/SecondLife.nib/info.nib23
-rwxr-xr-xindra/newview/SecondLife.nib/objects.xib259
-rw-r--r--indra/newview/SecondLife.xib1136
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/app_settings/cmd_line.xml21
-rwxr-xr-xindra/newview/app_settings/keywords.ini3
-rwxr-xr-xindra/newview/app_settings/settings.xml302
-rwxr-xr-xindra/newview/app_settings/settings_files.xml3
-rwxr-xr-xindra/newview/app_settings/settings_minimal.xml5
-rwxr-xr-xindra/newview/app_settings/settings_per_account.xml13
-rwxr-xr-xindra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl1
-rwxr-xr-xindra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl1
-rwxr-xr-xindra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl1
-rwxr-xr-xindra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl1
-rwxr-xr-xindra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl5
-rwxr-xr-xindra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl1
-rwxr-xr-xindra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl1
-rwxr-xr-xindra/newview/gpu_table.txt576
-rwxr-xr-xindra/newview/linux_tools/wrapper.sh34
-rwxr-xr-xindra/newview/llagent.cpp15
-rw-r--r--indra/newview/llappdelegate-objc.mm144
-rwxr-xr-xindra/newview/llappviewer.cpp348
-rwxr-xr-xindra/newview/llappviewer.h6
-rwxr-xr-xindra/newview/llappviewermacosx.cpp248
-rwxr-xr-xindra/newview/llappviewerwin32.cpp17
-rwxr-xr-xindra/newview/llavataractions.cpp68
-rwxr-xr-xindra/newview/llavataractions.h6
-rwxr-xr-xindra/newview/llchannelmanager.cpp2
-rwxr-xr-xindra/newview/llchatbar.cpp2
-rwxr-xr-xindra/newview/llchathistory.cpp1
-rwxr-xr-xindra/newview/llchatitemscontainerctrl.cpp5
-rwxr-xr-xindra/newview/llchiclet.cpp23
-rwxr-xr-xindra/newview/llcommandlineparser.cpp198
-rwxr-xr-xindra/newview/llcommandlineparser.h2
-rwxr-xr-xindra/newview/llconversationloglist.cpp4
-rwxr-xr-xindra/newview/llconversationmodel.cpp10
-rwxr-xr-xindra/newview/llconversationmodel.h9
-rwxr-xr-xindra/newview/llconversationview.cpp49
-rwxr-xr-xindra/newview/llconversationview.h4
-rwxr-xr-xindra/newview/lldirpicker.cpp142
-rwxr-xr-xindra/newview/lldirpicker.h13
-rwxr-xr-xindra/newview/lldonotdisturbnotificationstorage.cpp19
-rwxr-xr-xindra/newview/lldrawpoolavatar.cpp139
-rwxr-xr-xindra/newview/lldrawpoolavatar.h1
-rwxr-xr-xindra/newview/llface.cpp112
-rwxr-xr-xindra/newview/llface.h2
-rwxr-xr-xindra/newview/llfavoritesbar.cpp7
-rwxr-xr-xindra/newview/llfavoritesbar.h1
-rwxr-xr-xindra/newview/llfeaturemanager.cpp117
-rwxr-xr-xindra/newview/llfeaturemanager.h14
-rwxr-xr-xindra/newview/llfilepicker.cpp510
-rwxr-xr-xindra/newview/llfilepicker.h16
-rw-r--r--indra/newview/llfilepicker_mac.h58
-rw-r--r--indra/newview/llfilepicker_mac.mm132
-rwxr-xr-xindra/newview/llfloaterabout.cpp12
-rwxr-xr-xindra/newview/llfloateravatarpicker.cpp8
-rwxr-xr-xindra/newview/llfloaterbulkpermission.cpp36
-rwxr-xr-xindra/newview/llfloaterbulkpermission.h16
-rwxr-xr-xindra/newview/llfloaterconversationpreview.cpp47
-rwxr-xr-xindra/newview/llfloaterconversationpreview.h3
-rw-r--r--indra/newview/llfloatergotoline.cpp160
-rw-r--r--indra/newview/llfloatergotoline.h66
-rwxr-xr-xindra/newview/llfloaterhardwaresettings.cpp9
-rwxr-xr-xindra/newview/llfloaterimcontainer.cpp235
-rwxr-xr-xindra/newview/llfloaterimcontainer.h17
-rwxr-xr-xindra/newview/llfloaterimnearbychat.cpp48
-rwxr-xr-xindra/newview/llfloaterimnearbychathandler.cpp1
-rwxr-xr-xindra/newview/llfloaterimnearbychatlistener.cpp4
-rwxr-xr-xindra/newview/llfloaterimsession.cpp30
-rwxr-xr-xindra/newview/llfloaterimsessiontab.cpp58
-rwxr-xr-xindra/newview/llfloaterimsessiontab.h8
-rwxr-xr-xindra/newview/llfloaterland.cpp13
-rwxr-xr-xindra/newview/llfloaterpreference.cpp4
-rwxr-xr-xindra/newview/llfloaterregioninfo.cpp18
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.cpp69
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.h3
-rwxr-xr-xindra/newview/llgroupactions.cpp125
-rwxr-xr-xindra/newview/llgroupactions.h8
-rwxr-xr-xindra/newview/llimview.cpp300
-rwxr-xr-xindra/newview/llinventorybridge.cpp12
-rwxr-xr-xindra/newview/llinventoryfilter.cpp42
-rwxr-xr-xindra/newview/llinventoryfilter.h17
-rwxr-xr-xindra/newview/llinventorypanel.cpp3
-rwxr-xr-xindra/newview/lllogchat.cpp300
-rwxr-xr-xindra/newview/lllogchat.h24
-rwxr-xr-xindra/newview/llmaniprotate.cpp232
-rwxr-xr-xindra/newview/llmenuoptionpathfindingrebakenavmesh.cpp2
-rwxr-xr-xindra/newview/llmeshrepository.h2
-rwxr-xr-xindra/newview/llnamelistctrl.cpp4
-rwxr-xr-xindra/newview/llnamelistctrl.h2
-rwxr-xr-xindra/newview/llnetmap.cpp5
-rwxr-xr-xindra/newview/llnotificationscripthandler.cpp2
-rwxr-xr-xindra/newview/llnotificationstorage.h1
-rwxr-xr-xindra/newview/llnotificationtiphandler.cpp7
-rwxr-xr-xindra/newview/llpanelgroupinvite.cpp35
-rwxr-xr-xindra/newview/llpanelgrouproles.cpp66
-rwxr-xr-xindra/newview/llpanelgrouproles.h1
-rwxr-xr-xindra/newview/llpanellogin.cpp33
-rwxr-xr-xindra/newview/llpanelmaininventory.cpp7
-rwxr-xr-xindra/newview/llpanelmaininventory.h1
-rwxr-xr-xindra/newview/llpanelpeople.cpp4
-rwxr-xr-xindra/newview/llpanelpeoplemenus.cpp10
-rwxr-xr-xindra/newview/llpanelpeoplemenus.h1
-rwxr-xr-xindra/newview/llpanelprofile.cpp20
-rwxr-xr-xindra/newview/llpersistentnotificationstorage.cpp24
-rwxr-xr-xindra/newview/llpersistentnotificationstorage.h3
-rwxr-xr-xindra/newview/llpreviewscript.cpp21
-rwxr-xr-xindra/newview/llpreviewscript.h3
-rwxr-xr-xindra/newview/llsechandler_basic.cpp10
-rwxr-xr-xindra/newview/llspatialpartition.cpp76
-rwxr-xr-xindra/newview/llstartup.cpp6
-rwxr-xr-xindra/newview/llsyswellwindow.cpp16
-rwxr-xr-xindra/newview/llsyswellwindow.h1
-rwxr-xr-xindra/newview/lltexturecache.cpp15
-rw-r--r--[-rwxr-xr-x]indra/newview/lltexturefetch.cpp0
-rwxr-xr-xindra/newview/lltoastimpanel.cpp26
-rwxr-xr-xindra/newview/lltoastimpanel.h2
-rwxr-xr-xindra/newview/lltoolbarview.cpp23
-rwxr-xr-xindra/newview/lltoolbarview.h2
-rwxr-xr-xindra/newview/lltoolpie.cpp9
-rwxr-xr-xindra/newview/llviewercontrol.cpp4
-rwxr-xr-xindra/newview/llviewerkeyboard.cpp6
-rwxr-xr-xindra/newview/llviewermenu.cpp86
-rwxr-xr-xindra/newview/llviewermenu.h1
-rwxr-xr-xindra/newview/llviewermessage.cpp209
-rwxr-xr-xindra/newview/llviewernetwork.cpp32
-rwxr-xr-xindra/newview/llviewernetwork.h9
-rwxr-xr-xindra/newview/llviewerobjectlist.cpp11
-rwxr-xr-xindra/newview/llviewerobjectlist.h1
-rwxr-xr-xindra/newview/llviewerpartsim.cpp11
-rwxr-xr-xindra/newview/llviewertexture.cpp23
-rwxr-xr-xindra/newview/llviewertexture.h1
-rwxr-xr-xindra/newview/llviewertexturelist.cpp14
-rwxr-xr-xindra/newview/llviewertexturelist.h2
-rwxr-xr-xindra/newview/llviewerwindow.cpp162
-rwxr-xr-xindra/newview/llviewerwindow.h11
-rwxr-xr-xindra/newview/llvopartgroup.cpp124
-rwxr-xr-xindra/newview/llvopartgroup.h15
-rwxr-xr-xindra/newview/llvovolume.cpp19
-rwxr-xr-xindra/newview/llwindowlistener.cpp9
-rwxr-xr-xindra/newview/llworldmap.cpp11
-rwxr-xr-xindra/newview/macutil_Prefix.h1
-rwxr-xr-xindra/newview/noise.h5
-rwxr-xr-xindra/newview/pipeline.cpp113
-rwxr-xr-xindra/newview/pipeline.h8
-rwxr-xr-xindra/newview/skins/default/colors.xml15
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml3
-rw-r--r--indra/newview/skins/default/textures/widgets/horizontal_drag_handle.pngbin0 -> 197 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/vertical_drag_handle.pngbin0 -> 196 bytes
-rwxr-xr-xindra/newview/skins/default/xui/da/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/de/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_about.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_about_land.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_bulk_perms.xml19
-rw-r--r--indra/newview/skins/default/xui/en/floater_goto_line.xml44
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_im_container.xml103
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_im_session.xml100
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_attachment_other.xml11
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_attachment_self.xml11
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_avatar_other.xml11
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_avatar_self.xml12
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_conversation.xml15
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_conversation_log_gear.xml10
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_inventory.xml8
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_land.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_mute_particle.xml15
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_object.xml11
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_people_friends_view.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_people_nearby.xml10
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_url_agent.xml9
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_url_objectim.xml7
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_viewer.xml39
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml105
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_group_notices.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_people.xml14
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_advanced.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_chat.xml144
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_graphics1.xml17
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_script_ed.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_status_bar.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/role_actions.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/strings.xml16
-rwxr-xr-xindra/newview/skins/default/xui/es/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/fr/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/it/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ja/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pt/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ru/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/tr/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/zh/floater_about.xml2
-rwxr-xr-xindra/newview/tests/llagentaccess_test.cpp14
-rwxr-xr-xindra/newview/tests/lllogininstance_test.cpp23
-rwxr-xr-xindra/newview/tests/llsecapi_test.cpp4
-rwxr-xr-xindra/newview/tests/llsechandler_basic_test.cpp4
-rwxr-xr-xindra/newview/tests/llslurl_test.cpp4
-rwxr-xr-xindra/newview/tests/llviewerhelputil_test.cpp4
-rwxr-xr-xindra/newview/tests/llviewernetwork_test.cpp14
-rwxr-xr-xindra/newview/tests/llxmlrpclistener_test.cpp4
-rwxr-xr-xindra/newview/viewer_manifest.py99
-rwxr-xr-xindra/viewer_components/updater/llupdatechecker.cpp70
-rwxr-xr-xindra/viewer_components/updater/llupdatechecker.h12
-rwxr-xr-xindra/viewer_components/updater/llupdaterservice.cpp53
-rwxr-xr-xindra/viewer_components/updater/llupdaterservice.h4
-rwxr-xr-xindra/viewer_components/updater/scripts/linux/update_install7
-rwxr-xr-xindra/viewer_components/updater/tests/llupdaterservice_test.cpp24
297 files changed, 11398 insertions, 5770 deletions
diff --git a/.hgtags b/.hgtags
index 9ca419211e..2e94290c50 100755
--- a/.hgtags
+++ b/.hgtags
@@ -458,8 +458,10 @@ a314f1c94374ab1f6633dd2983f7090a68663eb2 3.5.2-beta4
9b1b6f33aa5394b27bb652b31b5cb81ef6060370 3.5.2-release
a277b841729f2a62ba1e34acacc964bc13c1ad6f 3.5.3-release
fb1630153bac5552046ea914af3f14deabc1def8 3.6.0-materials-beta1
-69429d81ae4dd321eda2607901ef0a0fde71b54c 3.6.0-release
-69429d81ae4dd321eda2607901ef0a0fde71b54c 3.6.0-release
0a56f33ad6aa112032b14a41dad759ad377bdde9 3.6.0-release
75cf8e855ae1af6895a35da475314c2b5acf1850 3.6.1-release
f6741d5fe8d632651424484df0fe0cb4a01e9fbe 3.6.2-release
+fe4f7c5e9fd27e09d03deb1cc9ab3e5093f6309e 3.6.3-release
+83357f31d8dbf048a8bfdc323f363bf4d588aca1 CHOP-951-a
+91ed595b716f14f07409595b734fda891a59379e 3.6.4-release
+bf6d453046011a11de2643fac610cc5258650f82 3.6.5-release
diff --git a/BuildParams b/BuildParams
index 84d30f651b..327530934d 100755
--- a/BuildParams
+++ b/BuildParams
@@ -26,6 +26,9 @@ codeticket_since = 3.3.0-release
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 ####
#
@@ -131,17 +134,6 @@ viewer-materials.build_debug_release_separately = true
viewer-materials.build_CYGWIN_Debug = false
viewer-materials.build_viewer_update_version_manager = false
-# viewer-chui
-#
-# ========================================
-
-viewer-chui.viewer_channel = "Project Viewer - CHUI"
-viewer-chui.login_channel = "Project Viewer - CHUI"
-viewer-chui.viewer_grid = agni
-viewer-chui.build_debug_release_separately = true
-viewer-chui.build_CYGWIN_Debug = false
-viewer-chui.build_viewer_update_version_manager = false
-
# =================================================================
# asset delivery 2010 projects
# =================================================================
diff --git a/autobuild.xml b/autobuild.xml
index e047d4d686..3ffe77451f 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1965,11 +1965,11 @@
<key>package_description</key>
<map>
<key>description</key>
- <string>Spell checking dictionaries</string>
+ <string>Second Life Viewer</string>
<key>license</key>
- <string>various open</string>
+ <string>LGPL</string>
<key>name</key>
- <string>dictionaries</string>
+ <string>Second Life Viewer</string>
<key>platforms</key>
<map>
<key>common</key>
diff --git a/doc/contributions.txt b/doc/contributions.txt
index be9ed4e3de..f33cf36ec2 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -175,7 +175,14 @@ Ansariel Hiller
STORM-1685
STORM-1713
STORM-1899
+ STORM-1932
+ STORM-1933
+ MAINT-2368
+ STORM-1931
+ MAINT-2773
Aralara Rajal
+Arare Chantilly
+ CHUIBUG-191
Ardy Lay
STORM-859
VWR-19499
@@ -300,8 +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
@@ -313,6 +325,7 @@ Cron Stardust
VWR-10579
VWR-25120
STORM-1075
+ STORM-1919
Cypren Christenson
STORM-417
Dante Tucker
@@ -405,6 +418,7 @@ Ganymedes Costagravas
Geenz Spad
STORM-1823
STORM-1900
+ STORM-1905
NORSPEC-229
Gene Frostbite
GeneJ Composer
@@ -480,6 +494,7 @@ Hiro Sommambulist
Hitomi Tiponi
STORM-1741
STORM-1862
+ BUG-1067
Holger Gilruth
Horatio Freund
Hoze Menges
@@ -500,6 +515,8 @@ Ima Mechanique
STORM-959
STORM-1175
STORM-1708
+ STORM-1855
+ VWR-20553
Imnotgoing Sideways
Inma Rau
Innula Zenovka
@@ -642,14 +659,21 @@ Jonathan Yap
STORM-1809
STORM-1793
STORM-1810
- STORM-1877
+ STORM-1838
+ STORM-1892
+ STORM-1894
STORM-1860
STORM-1852
STORM-1870
STORM-1872
STORM-1858
STORM-1862
+ STORM-1918
+ STORM-1929
+ STORM-1953
OPEN-161
+ STORM-1953
+ STORM-1957
Kadah Coba
STORM-1060
STORM-1843
@@ -665,6 +689,9 @@ Kagehi Kohn
Kaimen Takahe
Katharine Berry
STORM-1900
+ OPEN-149
+ STORM-1940
+ STORM-1941
Keklily Longfall
Ken Lavender
Ken March
@@ -687,6 +714,7 @@ Kitty Barnett
STORM-800
STORM-1001
STORM-1175
+ STORM-1905
VWR-24217
STORM-1804
Kolor Fall
@@ -696,6 +724,7 @@ Kunnis Basiat
VWR-82
VWR-102
Lance Corrimal
+ STORM-1910
VWR-25269
Latif Khalifa
VWR-5370
@@ -750,9 +779,11 @@ Marianne McCann
Marine Kelley
CHUIBUG-134
STORM-281
+ STORM-1910
MartinRJ Fayray
STORM-1844
STORM-1845
+ STORM-1911
STORM-1934
Matthew Anthony
Matthew Dowd
@@ -904,6 +935,9 @@ Nicky Dasmijn
MAINT-873
SUN-72
BUG-2432
+ BUG-3605
+ CHUIBUG-197
+ OPEN-187
Nicky Perian
OPEN-1
STORM-1087
@@ -1046,6 +1080,7 @@ Satanello Miami
Satomi Ahn
STORM-501
STORM-229
+ VWR-20553
VWR-24502
Scrim Pinion
Scrippy Scofield
@@ -1215,6 +1250,8 @@ Tofu Buzzard
STORM-1684
STORM-1819
Tony Kembia
+Tonya Souther
+ STORM-1905
Torben Trautman
TouchaHoney Perhaps
TraductoresAnonimos Alter
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake
index b9ec8f5266..e4b63dc7cb 100755
--- a/indra/cmake/BuildVersion.cmake
+++ b/indra/cmake/BuildVersion.cmake
@@ -16,22 +16,26 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
else (DEFINED ENV{revision})
find_program(MERCURIAL hg)
- if (DEFINED MERCURIAL)
+ find_program(WORDCOUNT wc)
+ find_program(SED sed)
+ if (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED)
execute_process(
- COMMAND ${MERCURIAL} log -r tip --template "{p1rev}"
+ COMMAND ${MERCURIAL} log -r tip:0 --template '\\n'
+ COMMAND ${WORDCOUNT} -l
+ COMMAND ${SED} "s/ //g"
OUTPUT_VARIABLE VIEWER_VERSION_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
message("Revision (from hg) ${VIEWER_VERSION_REVISION}")
else ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
+ message("Revision not set (repository not found?); using 0")
set(VIEWER_VERSION_REVISION 0 )
- message("Revision not set, repository not found, using ${VIEWER_VERSION_REVISION}")
endif ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
- else (DEFINED MERCURIAL)
+ else (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED)
+ message("Revision not set: 'hg', 'wc' or 'sed' not found; using 0")
set(VIEWER_VERSION_REVISION 0)
- message("Revision not set, 'hg' not found (${MERCURIAL}), using ${VIEWER_VERSION_REVISION}")
- endif (DEFINED MERCURIAL)
+ endif (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED)
endif (DEFINED ENV{revision})
message("Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
else ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 9bb3077797..9bb3077797 100755..100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 7c310ba9c3..22d0a7f0fe 100755
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -134,15 +134,20 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
OUTPUT_VARIABLE XCODE_VERSION )
# To support a different SDK update these Xcode settings:
+ if (XCODE_VERSION GREATER 4.5)
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
+ set(CMAKE_OSX_SYSROOT macosx10.8)
+ else (XCODE_VERSION GREATER 4.5)
if (XCODE_VERSION GREATER 4.2)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
+ set(CMAKE_OSX_SYSROOT macosx10.7)
else (XCODE_VERSION GREATER 4.2)
- set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
+ set(CMAKE_OSX_SYSROOT macosx10.7)
endif (XCODE_VERSION GREATER 4.2)
+ endif (XCODE_VERSION GREATER 4.5)
- set(CMAKE_OSX_SYSROOT macosx10.6)
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
-
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
# NOTE: To attempt an i386/PPC Universal build, add this on the configure line:
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index e003ed7788..774e8c0676 100755
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -3,3 +3,4 @@ Wed Nov 7 00:25:19 UTC 2012
+
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index e83b4e8cd7..34e34c7e47 100755
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -60,7 +60,8 @@ add_executable(llui_libtest ${llui_libtest_SOURCE_FILES})
# Link with OS-specific libraries for LLWindow dependency
if (DARWIN)
find_library(COCOA_LIBRARY Cocoa)
- set(OS_LIBRARIES ${COCOA_LIBRARY})
+ find_library(IOKIT_LIBRARY IOKit)
+ set(OS_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY})
elseif (WINDOWS)
#ll_stack_trace needs this now...
list(APPEND WINDOWS_LIBRARIES dbghelp)
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 9cb830a2db..54049b5545 100755
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -392,11 +392,21 @@ class LLManifest(object):
raise ManifestError, "Should be something at path " + path
self.created_paths.append(path)
- def put_in_file(self, contents, dst):
+ def put_in_file(self, contents, dst, src=None):
# write contents as dst
- f = open(self.dst_path_of(dst), "wb")
- f.write(contents)
- f.close()
+ dst_path = self.dst_path_of(dst)
+ f = open(dst_path, "wb")
+ try:
+ f.write(contents)
+ finally:
+ f.close()
+
+ # Why would we create a file in the destination tree if not to include
+ # it in the installer? The default src=None (plus the fact that the
+ # src param is last) is to preserve backwards compatibility.
+ if src:
+ self.file_list.append([src, dst_path])
+ return dst_path
def replace_in(self, src, dst=None, searchdict={}):
if dst == None:
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 57a6de9060..0730b2ed8b 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -67,12 +67,18 @@ using namespace llsd;
# include <sys/sysctl.h>
# include <sys/utsname.h>
# include <stdint.h>
-# include <Carbon/Carbon.h>
+# include <CoreServices/CoreServices.h>
# include <stdexcept>
# include <mach/host_info.h>
# include <mach/mach_host.h>
# include <mach/task.h>
# include <mach/task_info.h>
+
+// disable warnings about Gestalt calls being deprecated
+// until Apple get's on the ball and provides an alternative
+//
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
#elif LL_LINUX
# include <errno.h>
# include <sys/utsname.h>
@@ -1502,3 +1508,10 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
if (dst != NULL) gzclose(dst);
return retval;
}
+
+#if LL_DARWIN
+// disable warnings about Gestalt calls being deprecated
+// until Apple get's on the ball and provides an alternative
+//
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
new file mode 100644
index 0000000000..6a5ff314e4
--- /dev/null
+++ b/indra/llcommon/llversionviewer.h
@@ -0,0 +1,41 @@
+/**
+ * @file llversionviewer.h
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVERSIONVIEWER_H
+#define LL_LLVERSIONVIEWER_H
+
+const S32 LL_VERSION_MAJOR = 3;
+const S32 LL_VERSION_MINOR = 4;
+const S32 LL_VERSION_PATCH = 6;
+const S32 LL_VERSION_BUILD = 0;
+
+const char * const LL_CHANNEL = "Second Life Developer";
+
+#if LL_DARWIN
+const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer";
+#endif
+
+#endif
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index f188865eb0..3e68ef068e 100755
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -608,9 +608,6 @@ namespace tut
void object::test<5>()
{
set_test_name("exit(2)");
-#if LL_WINDOWS
- skip("MAINT-2302: This frequently (though not always) fails on Windows.");
-#endif
PythonProcessLauncher py(get_test_name(),
"import sys\n"
"sys.exit(2)\n");
@@ -622,10 +619,7 @@ namespace tut
template<> template<>
void object::test<6>()
{
- set_test_name("syntax_error:");
-#if LL_WINDOWS
- skip("MAINT-2302: This frequently (though not always) fails on Windows.");
-#endif
+ set_test_name("syntax_error");
PythonProcessLauncher py(get_test_name(),
"syntax_error:\n");
py.mParams.files.add(LLProcess::FileParam()); // inherit stdin
@@ -647,9 +641,6 @@ namespace tut
void object::test<7>()
{
set_test_name("explicit kill()");
-#if LL_WINDOWS
- skip("MAINT-2302: This frequently (though not always) fails on Windows.");
-#endif
PythonProcessLauncher py(get_test_name(),
"from __future__ import with_statement\n"
"import sys, time\n"
@@ -694,9 +685,6 @@ namespace tut
void object::test<8>()
{
set_test_name("implicit kill()");
-#if LL_WINDOWS
- skip("MAINT-2302: This frequently (though not always) fails on Windows.");
-#endif
NamedTempFile out("out", "not started");
LLProcess::handle phandle(0);
{
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 1c25256e95..c8a05e1fae 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -689,8 +689,17 @@ void LLImageRaw::fill( const LLColor4U& color )
}
}
+LLPointer<LLImageRaw> LLImageRaw::duplicate()
+{
+ if(getNumRefs() < 2)
+ {
+ return this; //nobody else refences to this image, no need to duplicate.
+ }
-
+ //make a duplicate
+ LLPointer<LLImageRaw> dup = new LLImageRaw(getData(), getWidth(), getHeight(), getComponents());
+ return dup;
+}
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 4fc40ecff7..2277afc585 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -30,6 +30,7 @@
#include "lluuid.h"
#include "llstring.h"
#include "llthread.h"
+#include "llpointer.h"
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
const S32 MAX_IMAGE_MIP = 11; // 2048x2048
@@ -214,6 +215,9 @@ public:
// Copy operations
+ //duplicate this raw image if refCount > 1.
+ LLPointer<LLImageRaw> duplicate();
+
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void copy( LLImageRaw* src );
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 22ba26f99b..33cf185196 100755
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -42,6 +42,11 @@ LLCamera::LLCamera() :
mPlaneCount(6),
mFrustumCornerDist(0.f)
{
+ for (U32 i = 0; i < PLANE_MASK_NUM; i++)
+ {
+ mPlaneMask[i] = PLANE_MASK_NONE;
+ }
+
calculateFrustumPlanes();
}
@@ -52,6 +57,11 @@ LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_p
mPlaneCount(6),
mFrustumCornerDist(0.f)
{
+ for (U32 i = 0; i < PLANE_MASK_NUM; i++)
+ {
+ mPlaneMask[i] = PLANE_MASK_NONE;
+ }
+
mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE;
@@ -87,14 +97,14 @@ F32 LLCamera::getMaxView() const
void LLCamera::setUserClipPlane(LLPlane& plane)
{
- mPlaneCount = 7;
- mAgentPlanes[6] = plane;
- mPlaneMask[6] = plane.calcPlaneMask();
+ mPlaneCount = AGENT_PLANE_USER_CLIP_NUM;
+ mAgentPlanes[AGENT_PLANE_USER_CLIP] = plane;
+ mPlaneMask[AGENT_PLANE_USER_CLIP] = plane.calcPlaneMask();
}
void LLCamera::disableUserClipPlane()
{
- mPlaneCount = 6;
+ mPlaneCount = AGENT_PLANE_NO_USER_CLIP_NUM;
}
void LLCamera::setView(F32 vertical_fov_rads)
@@ -161,31 +171,33 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer)
// ---------------- test methods ----------------
-S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
+static const LLVector4a sFrustumScaler[] =
{
- static const LLVector4a scaler[] = {
- LLVector4a(-1,-1,-1),
- LLVector4a( 1,-1,-1),
- LLVector4a(-1, 1,-1),
- LLVector4a( 1, 1,-1),
- LLVector4a(-1,-1, 1),
- LLVector4a( 1,-1, 1),
- LLVector4a(-1, 1, 1),
- LLVector4a( 1, 1, 1)
- };
+ LLVector4a(-1,-1,-1),
+ LLVector4a( 1,-1,-1),
+ LLVector4a(-1, 1,-1),
+ LLVector4a( 1, 1,-1),
+ LLVector4a(-1,-1, 1),
+ LLVector4a( 1,-1, 1),
+ LLVector4a(-1, 1, 1),
+ LLVector4a( 1, 1, 1) // 8 entries
+};
+S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
+{
U8 mask = 0;
bool result = false;
LLVector4a rscale, maxp, minp;
LLSimdScalar d;
- for (U32 i = 0; i < mPlaneCount; i++)
+ U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM); // mAgentPlanes[] size is 7
+ for (U32 i = 0; i < max_planes; i++)
{
mask = mPlaneMask[i];
- if (mask != 0xff)
+ if (mask < PLANE_MASK_NUM)
{
const LLPlane& p(mAgentPlanes[i]);
p.getAt<3>(d);
- rscale.setMul(radius, scaler[mask]);
+ rscale.setMul(radius, sFrustumScaler[mask]);
minp.setSub(center, rscale);
d = -d;
if (p.dot3(minp).getF32() > d)
@@ -207,29 +219,19 @@ S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)
{
- static const LLVector4a scaler[] = {
- LLVector4a(-1,-1,-1),
- LLVector4a( 1,-1,-1),
- LLVector4a(-1, 1,-1),
- LLVector4a( 1, 1,-1),
- LLVector4a(-1,-1, 1),
- LLVector4a( 1,-1, 1),
- LLVector4a(-1, 1, 1),
- LLVector4a( 1, 1, 1)
- };
-
U8 mask = 0;
bool result = false;
LLVector4a rscale, maxp, minp;
LLSimdScalar d;
- for (U32 i = 0; i < mPlaneCount; i++)
+ U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM); // mAgentPlanes[] size is 7
+ for (U32 i = 0; i < max_planes; i++)
{
mask = mPlaneMask[i];
- if ((i != 5) && (mask != 0xff))
+ if ((i != 5) && (mask < PLANE_MASK_NUM))
{
const LLPlane& p(mAgentPlanes[i]);
p.getAt<3>(d);
- rscale.setMul(radius, scaler[mask]);
+ rscale.setMul(radius, sFrustumScaler[mask]);
minp.setSub(center, rscale);
d = -d;
if (p.dot3(minp).getF32() > d)
@@ -369,7 +371,7 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius)
bool res = false;
for (int i = 0; i < 6; i++)
{
- if (mPlaneMask[i] != 0xff)
+ if (mPlaneMask[i] != PLANE_MASK_NONE)
{
float d = mAgentPlanes[i].dist(sphere_center);
@@ -541,14 +543,14 @@ void LLCamera::ignoreAgentFrustumPlane(S32 idx)
return;
}
- mPlaneMask[idx] = 0xff;
+ mPlaneMask[idx] = PLANE_MASK_NONE;
mAgentPlanes[idx].clear();
}
void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
{
- for (int i = 0; i < 8; i++)
+ for (int i = 0; i < AGENT_FRUSTRUM_NUM; i++)
{
mAgentFrustum[i] = frust[i];
}
@@ -560,22 +562,22 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
//order of planes is important, keep most likely to fail in the front of the list
//near - frust[0], frust[1], frust[2]
- mAgentPlanes[2] = planeFromPoints(frust[0], frust[1], frust[2]);
+ mAgentPlanes[AGENT_PLANE_NEAR] = planeFromPoints(frust[0], frust[1], frust[2]);
//far
- mAgentPlanes[5] = planeFromPoints(frust[5], frust[4], frust[6]);
+ mAgentPlanes[AGENT_PLANE_FAR] = planeFromPoints(frust[5], frust[4], frust[6]);
//left
- mAgentPlanes[0] = planeFromPoints(frust[4], frust[0], frust[7]);
+ mAgentPlanes[AGENT_PLANE_LEFT] = planeFromPoints(frust[4], frust[0], frust[7]);
//right
- mAgentPlanes[1] = planeFromPoints(frust[1], frust[5], frust[6]);
+ mAgentPlanes[AGENT_PLANE_RIGHT] = planeFromPoints(frust[1], frust[5], frust[6]);
//top
- mAgentPlanes[4] = planeFromPoints(frust[3], frust[2], frust[6]);
+ mAgentPlanes[AGENT_PLANE_TOP] = planeFromPoints(frust[3], frust[2], frust[6]);
//bottom
- mAgentPlanes[3] = planeFromPoints(frust[1], frust[0], frust[4]);
+ mAgentPlanes[AGENT_PLANE_BOTTOM] = planeFromPoints(frust[1], frust[0], frust[4]);
//cache plane octant facing mask for use in AABBInFrustum
for (U32 i = 0; i < mPlaneCount; i++)
@@ -635,7 +637,7 @@ void LLCamera::calculateWorldFrustumPlanes()
LLVector3 center = mOrigin - mXAxis*mNearPlane;
mWorldPlanePos = center;
LLVector3 pnorm;
- for (int p=0; p<4; p++)
+ for (int p = 0; p < PLANE_NUM; p++)
{
mLocalPlanes[p].getVector3(pnorm);
LLVector3 norm = rotateToAbsolute(pnorm);
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 0b591be622..1283cfb16b 100755
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -76,26 +76,39 @@ public:
PLANE_RIGHT = 1,
PLANE_BOTTOM = 2,
PLANE_TOP = 3,
- PLANE_NUM = 4
+ PLANE_NUM = 4,
+ PLANE_MASK_NONE = 0xff // Disable this plane
};
enum {
PLANE_LEFT_MASK = (1<<PLANE_LEFT),
PLANE_RIGHT_MASK = (1<<PLANE_RIGHT),
PLANE_BOTTOM_MASK = (1<<PLANE_BOTTOM),
PLANE_TOP_MASK = (1<<PLANE_TOP),
- PLANE_ALL_MASK = 0xf
+ PLANE_ALL_MASK = 0xf,
};
enum
- {
+ { // Indexes to mAgentPlanes[] and mPlaneMask[]
AGENT_PLANE_LEFT = 0,
- AGENT_PLANE_RIGHT,
- AGENT_PLANE_NEAR,
- AGENT_PLANE_BOTTOM,
- AGENT_PLANE_TOP,
- AGENT_PLANE_FAR,
+ AGENT_PLANE_RIGHT = 1,
+ AGENT_PLANE_NEAR = 2,
+ AGENT_PLANE_BOTTOM = 3,
+ AGENT_PLANE_TOP = 4,
+ AGENT_PLANE_FAR = 5,
+ AGENT_PLANE_USER_CLIP = 6
+ };
+ enum
+ { // Sizes for mAgentPlanes[]. 7th entry is special case for user clip
+ AGENT_PLANE_NO_USER_CLIP_NUM = 6,
+ AGENT_PLANE_USER_CLIP_NUM = 7,
+ PLANE_MASK_NUM = 8 // 7 actually used, 8 is for alignment
};
+ enum
+ {
+ AGENT_FRUSTRUM_NUM = 8
+ };
+
enum {
HORIZ_PLANE_LEFT = 0,
HORIZ_PLANE_RIGHT = 1,
@@ -108,15 +121,15 @@ public:
};
private:
- LL_ALIGN_16(LLPlane mAgentPlanes[7]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
- U8 mPlaneMask[8]; // 8 for alignment
+ LL_ALIGN_16(LLPlane mAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
+ U8 mPlaneMask[PLANE_MASK_NUM]; // 8 for alignment
F32 mView; // angle between top and bottom frustum planes in radians.
F32 mAspect; // width/height
S32 mViewHeightInPixels; // for ViewHeightInPixels() only
F32 mNearPlane;
F32 mFarPlane;
- LL_ALIGN_16(LLPlane mLocalPlanes[4]);
+ LL_ALIGN_16(LLPlane mLocalPlanes[PLANE_NUM]);
F32 mFixedDistance; // Always return this distance, unless < 0
LLVector3 mFrustCenter; // center of frustum and radius squared for ultra-quick exclusion test
F32 mFrustRadiusSquared;
@@ -128,7 +141,7 @@ private:
LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera)
public:
- LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum
+ LLVector3 mAgentFrustum[AGENT_FRUSTRUM_NUM]; //8 corners of 6-plane frustum
F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
LLPlane& getAgentPlane(U32 idx) { return mAgentPlanes[idx]; }
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index b047f86e6e..8c8c315808 100755
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -50,7 +50,7 @@ class LLColor4
LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1)
LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a)
LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
- LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
+ LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], vec[3])
LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
explicit LLColor4(const LLSD& sd);
explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 47041a2880..f2a3e059ef 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -72,7 +72,8 @@
static const U32 EASY_HANDLE_POOL_SIZE = 5;
static const S32 MULTI_PERFORM_CALL_REPEAT = 5;
-static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation
+static const S32 CURL_REQUEST_TIMEOUT = 120; // seconds per operation
+static const S32 CURL_CONNECT_TIMEOUT = 30; //seconds to wait for a connection
static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
// DEBUG //
@@ -517,6 +518,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
setopt(CURLOPT_SSL_VERIFYHOST, 0);
setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));
+ setopt(CURLOPT_CONNECTTIMEOUT, CURL_CONNECT_TIMEOUT);
setoptString(CURLOPT_URL, url);
diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h
index db4a38ea9e..f7118f8ccf 100755
--- a/indra/llmessage/llinstantmessage.h
+++ b/indra/llmessage/llinstantmessage.h
@@ -126,7 +126,7 @@ enum EInstantMessage
IM_LURE_ACCEPTED = 23,
IM_LURE_DECLINED = 24,
IM_GODLIKE_LURE_USER = 25,
- IM_YET_TO_BE_USED = 26,
+ IM_TELEPORT_REQUEST = 26,
// IM that notifie of a new group election.
// Name is name of person who called vote.
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 28ed051c55..5ed05e2201 100755
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -628,25 +628,41 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
if (v)
{
U32 v_idx = idx[j*stride+v_offset]*3;
+ v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount());
vert.getPosition().set(v->get(v_idx),
v->get(v_idx+1),
v->get(v_idx+2));
}
- if (n)
+ //bounds check n and t lookups because some FBX to DAE converters
+ //use negative indices and empty arrays to indicate data does not exist
+ //for a particular channel
+ if (n && n->getCount() > 0)
{
U32 n_idx = idx[j*stride+n_offset]*3;
+ n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount());
vert.getNormal().set(n->get(n_idx),
n->get(n_idx+1),
n->get(n_idx+2));
}
+ else
+ {
+ vert.getNormal().clear();
+ }
+
- if (t)
+ if (t && t->getCount() > 0)
{
U32 t_idx = idx[j*stride+t_offset]*2;
+ t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
vert.mTexCoord.setVec(t->get(t_idx),
t->get(t_idx+1));
}
+ else
+ {
+ vert.mTexCoord.clear();
+ }
+
verts.push_back(vert);
}
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 088ba95b75..c3005f1722 100755
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -1154,7 +1154,8 @@ void LLGLManager::initExtensions()
// Misc
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
-
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
+
#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS
LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
if (mHasVertexBufferObject)
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 60597fd090..75e5fe86ec 100755
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -155,6 +155,7 @@ public:
S32 mVRAM; // VRAM in MB
S32 mGLMaxVertexRange;
S32 mGLMaxIndexRange;
+ S32 mGLMaxTextureSize;
void getPixelFormat(); // Get the best pixel format
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index dace572953..1bec6d376b 100755
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -1009,12 +1009,7 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
}
#endif
-#if __MAC_OS_X_VERSION_MAX_ALLOWED <= 1070
#include <OpenGL/gl.h>
-#else
-#include <AGL/gl.h>
-#endif
-
#endif // LL_MESA / LL_WINDOWS / LL_DARWIN
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 38764eba23..38764eba23 100644..100755
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 6e22712b94..5ea8387c04 100755
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -117,8 +117,8 @@ void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt)
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
- resx = llmin(resx, (U32) 4096);
- resy = llmin(resy, (U32) 4096);
+ resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
+ resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
stop_glerror();
release();
@@ -252,12 +252,15 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
mTex.push_back(tex);
mInternalFormat.push_back(color_fmt);
+#if !LL_DARWIN
if (gDebugGL)
{ //bind and unbind to validate target
bindTarget();
flush();
}
-
+#endif
+
+
return true;
}
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 34a08603fa..589ceac501 100755
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -75,6 +75,7 @@ set(llui_SOURCE_FILES
llmultislider.cpp
llmultisliderctrl.cpp
llnotifications.cpp
+ llnotificationslistener.cpp
llnotificationsutil.cpp
llpanel.cpp
llprogressbar.cpp
@@ -128,6 +129,7 @@ set(llui_SOURCE_FILES
llviewmodel.cpp
llview.cpp
llviewquery.cpp
+ llviewereventrecorder.cpp
llwindowshade.cpp
llxuiparser.cpp
)
@@ -183,6 +185,7 @@ set(llui_HEADER_FILES
llmultislider.h
llnotificationptr.h
llnotifications.h
+ llnotificationslistener.h
llnotificationsutil.h
llnotificationtemplate.h
llnotificationvisibilityrule.h
@@ -240,6 +243,7 @@ set(llui_HEADER_FILES
llviewinject.h
llviewmodel.h
llview.h
+ llviewereventrecorder.h
llviewquery.h
llwindowshade.h
llxuiparser.h
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index a8149a9a1d..50ac511d18 100755
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -49,6 +49,7 @@
#include "lluictrlfactory.h"
#include "llhelp.h"
#include "lldockablefloater.h"
+#include "llviewereventrecorder.h"
static LLDefaultChildRegistry::Register<LLButton> r("button");
@@ -443,6 +444,8 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
*/
LLUICtrl::handleMouseDown(x, y, mask);
+ LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());
+
if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD());
mMouseDownTimer.start();
@@ -473,6 +476,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
* by calling LLUICtrl::mMouseUpSignal(x, y, mask);
*/
LLUICtrl::handleMouseUp(x, y, mask);
+ LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());
// Regardless of where mouseup occurs, handle callback
if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD());
@@ -644,7 +648,7 @@ void LLButton::draw()
// Cancel sticking of color, if the button is pressed,
// or when a flashing of the previously selected button is ended
if (mFlashingTimer
- && ((selected && !mFlashingTimer->isFlashingInProgress()) || pressed))
+ && ((selected && !mFlashingTimer->isFlashingInProgress() && !mForceFlashing) || pressed))
{
mFlashing = false;
}
@@ -971,8 +975,9 @@ void LLButton::setToggleState(BOOL b)
}
}
-void LLButton::setFlashing(bool b)
+void LLButton::setFlashing(bool b, bool force_flashing/* = false */)
{
+ mForceFlashing = force_flashing;
if (mFlashingTimer)
{
mFlashing = b;
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 060db59a8a..7b4719866d 100755
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -201,7 +201,7 @@ public:
void setToggleState(BOOL b);
void setHighlight(bool b);
- void setFlashing( bool b );
+ void setFlashing( bool b, bool force_flashing = false );
BOOL getFlashing() const { return mFlashing; }
LLFlashTimer* getFlashTimer() {return mFlashingTimer;}
@@ -378,7 +378,7 @@ protected:
LLFrameTimer mFrameTimer;
LLFlashTimer * mFlashingTimer;
-
+ bool mForceFlashing; // Stick flashing color even if button is pressed
bool mHandleRightMouse;
};
diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp
index 6a1b48a08a..c04b70eb64 100755
--- a/indra/llui/llchatentry.cpp
+++ b/indra/llui/llchatentry.cpp
@@ -62,9 +62,9 @@ void LLChatEntry::draw()
{
if(mIsExpandable)
{
+ reflow();
expandText();
}
-
LLTextEditor::draw();
}
@@ -158,19 +158,21 @@ void LLChatEntry::onValueChange(S32 start, S32 end)
resetLabel();
}
-bool LLChatEntry::useLabel()
+bool LLChatEntry::useLabel() const
{
return !getLength() && !mLabel.empty();
}
void LLChatEntry::onFocusReceived()
{
-
+ LLUICtrl::onFocusReceived();
+ updateAllowingLanguageInput();
}
void LLChatEntry::onFocusLost()
{
-
+ LLTextEditor::focusLostHelper();
+ LLUICtrl::onFocusLost();
}
BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h
index 49c8d21450..e67f39b21b 100755
--- a/indra/llui/llchatentry.h
+++ b/indra/llui/llchatentry.h
@@ -56,14 +56,14 @@ protected:
LLChatEntry(const Params& p);
/*virtual*/ void beforeValueChange();
/*virtual*/ void onValueChange(S32 start, S32 end);
- /*virtual*/ bool useLabel();
+ /*virtual*/ bool useLabel() const;
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);
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 09e27a264a..d44b1ad51a 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -29,7 +29,7 @@
// mini-map floater, etc.
#include "linden_common.h"
-
+#include "llviewereventrecorder.h"
#include "llfloater.h"
#include "llfocusmgr.h"
@@ -507,22 +507,11 @@ LLFloater::~LLFloater()
{
LLFloaterReg::removeInstance(mInstanceName, mKey);
-// delete mNotificationContext;
-// mNotificationContext = NULL;
-
- //// am I not hosted by another floater?
- //if (mHostHandle.isDead())
- //{
- // LLFloaterView* parent = (LLFloaterView*) getParent();
-
- // if( parent )
- // {
- // parent->removeChild( this );
- // }
- //}
-
- // Just in case we might still have focus here, release it.
- releaseFocus();
+ if( gFocusMgr.childHasKeyboardFocus(this))
+ {
+ // Just in case we might still have focus here, release it.
+ releaseFocus();
+ }
// This is important so that floaters with persistent rects (i.e., those
// created with rect control rather than an LLRect) are restored in their
@@ -653,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
@@ -707,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;
@@ -1486,6 +1479,7 @@ void LLFloater::moveResizeHandlesToFront()
}
}
+/*virtual*/
BOOL LLFloater::isFrontmost()
{
LLFloaterView* floater_view = getParentByType<LLFloaterView>();
@@ -1504,7 +1498,7 @@ void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition)
floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp));
floaterp->setSnapTarget(getHandle());
}
- gFloaterView->adjustToFitScreen(floaterp, FALSE);
+ gFloaterView->adjustToFitScreen(floaterp, FALSE, TRUE);
if (floaterp->isFrontmost())
{
// make sure to bring self and sibling floaters to front
@@ -1553,6 +1547,17 @@ BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks)
}
// virtual
+BOOL LLFloater::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ lldebugs << "LLFloater::handleMouseUp calling LLPanel (really LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl;
+ BOOL handled = LLPanel::handleMouseUp(x,y,mask); // Not implemented in LLPanel so this actually calls LLView
+ if (handled) {
+ LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());
+ }
+ return handled;
+}
+
+// virtual
BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
{
if( mMinimized )
@@ -1572,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;
}
}
@@ -2735,7 +2744,7 @@ void LLFloaterView::refresh()
const S32 FLOATER_MIN_VISIBLE_PIXELS = 16;
-void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside)
+void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars/* = false*/)
{
if (floater->getParent() != this)
{
@@ -2788,7 +2797,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
}
// move window fully onscreen
- if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))
+ if (floater->translateIntoRect( snap_in_toolbars ? getSnapRect() : gFloaterView->getRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))
{
floater->clearSnapTarget();
}
@@ -3258,6 +3267,11 @@ bool LLFloater::isShown() const
return ! isMinimized() && isInVisibleChain();
}
+bool LLFloater::isDetachedAndNotMinimized()
+{
+ return !getHost() && !isMinimized();
+}
+
/* static */
bool LLFloater::isShown(const LLFloater* floater)
{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 4dba1e645f..b6ff04e000 100755
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -238,6 +238,7 @@ public:
void center();
LLMultiFloater* getHost();
+ bool isDetachedAndNotMinimized();
void applyTitle();
std::string getCurrentTitle() const;
@@ -261,7 +262,7 @@ public:
static bool isVisible(const LLFloater* floater);
static bool isMinimized(const LLFloater* floater);
BOOL isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts
- BOOL isFrontmost();
+ virtual BOOL isFrontmost();
BOOL isDependent() { return !mDependeeHandle.isDead(); }
void setCanMinimize(BOOL can_minimize);
void setCanClose(BOOL can_close);
@@ -285,6 +286,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);
@@ -528,7 +530,7 @@ public:
LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor );
// Given a child of gFloaterView, make sure this view can fit entirely onscreen.
- void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside);
+ void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars = false);
void setMinimizePositionVerticalOffset(S32 offset) { mMinimizePositionVOffset = offset; }
void getMinimizePosition( S32 *left, S32 *bottom);
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 1cdddf0d5b..b1b75776a7 100755
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -356,8 +356,8 @@ std::string LLFloaterReg::declareRectControl(const std::string& name)
{
std::string controlname = getRectControlName(name);
LLFloater::getControlGroup()->declareRect(controlname, LLRect(),
- llformat("Window Size for %s", name.c_str()),
- TRUE);
+ llformat("Window Size for %s", name.c_str()),
+ LLControlVariable::PERSIST_NONDFT);
return controlname;
}
@@ -367,7 +367,7 @@ std::string LLFloaterReg::declarePosXControl(const std::string& name)
LLFloater::getControlGroup()->declareF32(controlname,
10.f,
llformat("Window X Position for %s", name.c_str()),
- TRUE);
+ LLControlVariable::PERSIST_NONDFT);
return controlname;
}
@@ -377,7 +377,7 @@ std::string LLFloaterReg::declarePosYControl(const std::string& name)
LLFloater::getControlGroup()->declareF32(controlname,
10.f,
llformat("Window Y Position for %s", name.c_str()),
- TRUE);
+ LLControlVariable::PERSIST_NONDFT);
return controlname;
}
@@ -404,7 +404,7 @@ std::string LLFloaterReg::declareVisibilityControl(const std::string& name)
std::string controlname = getVisibilityControlName(name);
LLFloater::getControlGroup()->declareBOOL(controlname, FALSE,
llformat("Window Visibility for %s", name.c_str()),
- TRUE);
+ LLControlVariable::PERSIST_NONDFT);
return controlname;
}
@@ -414,7 +414,7 @@ std::string LLFloaterReg::declareDockStateControl(const std::string& name)
std::string controlname = getDockStateControlName(name);
LLFloater::getControlGroup()->declareBOOL(controlname, TRUE,
llformat("Window Docking state for %s", name.c_str()),
- TRUE);
+ LLControlVariable::PERSIST_NONDFT);
return controlname;
}
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 8aa1eb7cd5..cf449217f5 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -323,9 +323,11 @@ static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View");
void LLFolderView::filter( LLFolderViewFilter& filter )
{
+ // Entry point of inventory filtering (CHUI-849)
LLFastTimer t2(FTM_FILTER);
- filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000));
+ filter.resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32(mParentPanel->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100));
+ // Note: we filter the model, not the view
getViewModelItem()->filter(filter);
}
@@ -661,7 +663,7 @@ void LLFolderView::draw()
// get preferable text height...
S32 pixel_height = mStatusTextBox->getTextPixelHeight();
- bool height_changed = local_rect.getHeight() != pixel_height;
+ bool height_changed = (local_rect.getHeight() < pixel_height);
if (height_changed)
{
// ... if it does not match current height, lets rearrange current view.
@@ -1601,15 +1603,17 @@ void LLFolderView::update()
{
mNeedsAutoSelect = TRUE;
}
- // filter to determine visibility before arranging
+
+ // Filter to determine visibility before arranging
filter(getFolderViewModel()->getFilter());
- // Clear the modified setting on the filter only if the filter count is non-zero after running the filter process
- // Note: if the filter count is zero, then the filter most likely halted before completing the entire set of items
- if (getFolderViewModel()->getFilter().isModified() && (getFolderViewModel()->getFilter().getFilterCount() > 0))
+
+ // Clear the modified setting on the filter only if the filter finished after running the filter process
+ // Note: if the filter count has timed out, that means the filter halted before completing the entire set of items
+ if (getFolderViewModel()->getFilter().isModified() && (!getFolderViewModel()->getFilter().isTimedOut()))
{
getFolderViewModel()->getFilter().clearModified();
}
-
+
// automatically show matching items, and select first one if we had a selection
if (mNeedsAutoSelect)
{
@@ -1649,11 +1653,13 @@ void LLFolderView::update()
BOOL is_visible = isInVisibleChain();
- //Puts folders/items in proper positions
- if ( is_visible )
+ // 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)
{
sanitizeSelection();
- if( needsArrange() )
+ if (needsArrange())
{
S32 height = 0;
S32 width = 0;
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index fdb4108afb..6c147ccc12 100755
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -274,6 +274,7 @@ void LLFolderViewItem::refresh()
}
mLabelWidthDirty = true;
+ // Dirty the filter flag of the model from the view (CHUI-849)
vmi.dirtyFilter();
}
@@ -943,11 +944,17 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)
static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
-// Finds width and height of this object and its children. Also
-// makes sure that this view and its children are the right size.
+// Make everything right and in the right place ready for drawing (CHUI-849)
+// * Sort everything correctly if necessary
+// * Turn widgets visible/invisible according to their model filtering state
+// * Takes animation state into account for opening/closing of folders (this makes widgets visible/invisible)
+// * Reposition visible widgets so that they line up correctly with no gap
+// * Compute the width and height of the current folder and its children
+// * Makes sure that this view and its children are the right size
S32 LLFolderViewFolder::arrange( S32* width, S32* height )
{
- // sort before laying out contents
+ // Sort before laying out contents
+ // Note that we sort from the root (CHUI-849)
getRoot()->getFolderViewModel()->sort(this);
LLFastTimer t2(FTM_ARRANGE);
@@ -1613,16 +1620,13 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
}
void LLFolderViewFolder::requestArrange()
-{
- if ( mLastArrangeGeneration != -1)
- {
- mLastArrangeGeneration = -1;
- // flag all items up to root
- if (mParentFolder)
- {
- mParentFolder->requestArrange();
- }
- }
+{
+ mLastArrangeGeneration = -1;
+ // flag all items up to root
+ if (mParentFolder)
+ {
+ mParentFolder->requestArrange();
+ }
}
void LLFolderViewFolder::toggleOpen()
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index ca31931e19..a9b0201236 100755
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -316,7 +316,6 @@ protected:
F32 mAutoOpenCountdown;
S32 mLastArrangeGeneration;
S32 mLastCalculatedWidth;
- S32 mMostFilteredDescendantGeneration;
bool mNeedsSort;
public:
diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp
index 3593804554..3363dc5316 100755
--- a/indra/llui/llfolderviewmodel.cpp
+++ b/indra/llui/llfolderviewmodel.cpp
@@ -48,7 +48,7 @@ std::string LLFolderViewModelCommon::getStatusText()
void LLFolderViewModelCommon::filter()
{
- getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000));
+ getFilter().resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100));
mFolderView->getViewModelItem()->filter(getFilter());
}
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 1b61212c0e..b1bcc8bbb4 100755
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -87,12 +87,11 @@ public:
virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0;
// +-------------------------------------------------------------------+
- // + Count
+ // + Time
// +-------------------------------------------------------------------+
- virtual void setFilterCount(S32 count) = 0;
- virtual S32 getFilterCount() const = 0;
- virtual void decrementFilterCount() = 0;
-
+ virtual void resetTime(S32 timeout) = 0;
+ virtual bool isTimedOut() = 0;
+
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
@@ -308,26 +307,28 @@ public:
virtual bool potentiallyVisible()
{
return passedFilter() // we've passed the filter
- || getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet
+ || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet
|| descendantsPassedFilter();
}
virtual bool passedFilter(S32 filter_generation = -1)
{
- if (filter_generation < 0)
+ if (filter_generation < 0)
+ {
filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
-
- bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation;
- bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation;
- return passed_folder_filter
- && (descendantsPassedFilter(filter_generation)
- || passed_filter);
+ }
+ bool passed_folder_filter = mPassedFolderFilter && (mLastFolderFilterGeneration >= filter_generation);
+ bool passed_filter = mPassedFilter && (mLastFilterGeneration >= filter_generation);
+ return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));
}
virtual bool descendantsPassedFilter(S32 filter_generation = -1)
{
- if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
- return mMostFilteredDescendantGeneration >= filter_generation;
+ if (filter_generation < 0)
+ {
+ filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
+ }
+ return mMostFilteredDescendantGeneration >= filter_generation;
}
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index e33ac1d5c2..c89c0203b4 100755
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -214,8 +214,15 @@ LLLayoutStack::Params::Params()
open_time_constant("open_time_constant", 0.02f),
close_time_constant("close_time_constant", 0.03f),
resize_bar_overlap("resize_bar_overlap", 1),
- border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))
-{}
+ border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)),
+ show_drag_handle("show_drag_handle", false),
+ drag_handle_first_indent("drag_handle_first_indent", 0),
+ drag_handle_second_indent("drag_handle_second_indent", 0),
+ drag_handle_thickness("drag_handle_thickness", 5),
+ drag_handle_shift("drag_handle_shift", 2)
+{
+ addSynonym(border_size, "drag_handle_gap");
+}
LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
: LLView(p),
@@ -227,8 +234,14 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
mClip(p.clip),
mOpenTimeConstant(p.open_time_constant),
mCloseTimeConstant(p.close_time_constant),
- mResizeBarOverlap(p.resize_bar_overlap)
-{}
+ mResizeBarOverlap(p.resize_bar_overlap),
+ mShowDragHandle(p.show_drag_handle),
+ mDragHandleFirstIndent(p.drag_handle_first_indent),
+ mDragHandleSecondIndent(p.drag_handle_second_indent),
+ mDragHandleThickness(p.drag_handle_thickness),
+ mDragHandleShift(p.drag_handle_shift)
+{
+}
LLLayoutStack::~LLLayoutStack()
{
@@ -262,6 +275,26 @@ void LLLayoutStack::draw()
drawChild(panelp, 0, 0, !clip_rect.isEmpty());
}
}
+
+ const LLView::child_list_t * child_listp = getChildList();
+ BOOST_FOREACH(LLView * childp, * child_listp)
+ {
+ LLResizeBar * resize_barp = dynamic_cast<LLResizeBar*>(childp);
+ if (resize_barp && resize_barp->isShowDragHandle() && resize_barp->getVisible() && resize_barp->getRect().isValid())
+ {
+ LLRect screen_rect = resize_barp->calcScreenRect();
+ if (LLUI::getRootView()->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
+ {
+ LLUI::pushMatrix();
+ {
+ const LLRect& rb_rect(resize_barp->getRect());
+ LLUI::translate(rb_rect.mLeft, rb_rect.mBottom);
+ resize_barp->draw();
+ }
+ LLUI::popMatrix();
+ }
+ }
+ }
}
void LLLayoutStack::removeChild(LLView* view)
@@ -390,7 +423,6 @@ void LLLayoutStack::updateLayout()
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
{
F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim);
- F32 panel_visible_dim = panelp->getVisibleDim();
LLRect panel_rect;
if (mOrientation == HORIZONTAL)
@@ -407,27 +439,61 @@ void LLLayoutStack::updateLayout()
getRect().getWidth(),
llround(panel_dim));
}
- panelp->setIgnoreReshape(true);
- panelp->setShape(panel_rect);
- panelp->setIgnoreReshape(false);
LLRect resize_bar_rect(panel_rect);
-
+ LLResizeBar * resize_barp = panelp->getResizeBar();
+ bool show_drag_handle = resize_barp->isShowDragHandle();
F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount();
+ F32 panel_visible_dim = panelp->getVisibleDim();
+ S32 panel_spacing_round = (S32)(llround(panel_spacing));
+
if (mOrientation == HORIZONTAL)
{
- resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
- resize_bar_rect.mRight = panel_rect.mRight + (S32)(llround(panel_spacing)) + mResizeBarOverlap;
-
cur_pos += panel_visible_dim + panel_spacing;
+
+ if (show_drag_handle && panel_spacing_round > mDragHandleThickness)
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight + mDragHandleShift;
+ resize_bar_rect.mRight = resize_bar_rect.mLeft + mDragHandleThickness;
+ }
+ else
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
+ resize_bar_rect.mRight = panel_rect.mRight + panel_spacing_round + mResizeBarOverlap;
+ }
+
+ if (show_drag_handle)
+ {
+ resize_bar_rect.mBottom += mDragHandleSecondIndent;
+ resize_bar_rect.mTop -= mDragHandleFirstIndent;
+ }
+
}
else //VERTICAL
{
- resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
- resize_bar_rect.mBottom = panel_rect.mBottom - (S32)(llround(panel_spacing)) - mResizeBarOverlap;
-
cur_pos -= panel_visible_dim + panel_spacing;
+
+ if (show_drag_handle && panel_spacing_round > mDragHandleThickness)
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom - mDragHandleShift;
+ resize_bar_rect.mBottom = resize_bar_rect.mTop - mDragHandleThickness;
+ }
+ else
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
+ resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing_round - mResizeBarOverlap;
+ }
+
+ if (show_drag_handle)
+ {
+ resize_bar_rect.mLeft += mDragHandleFirstIndent;
+ resize_bar_rect.mRight -= mDragHandleSecondIndent;
+ }
}
+
+ panelp->setIgnoreReshape(true);
+ panelp->setShape(panel_rect);
+ panelp->setIgnoreReshape(false);
panelp->mResizeBar->setShape(resize_bar_rect);
}
@@ -475,14 +541,13 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)
{
if (lp->mResizeBar == NULL)
{
- LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
-
LLResizeBar::Params resize_params;
resize_params.name("resize");
resize_params.resizing_view(lp);
resize_params.min_size(lp->getRelevantMinDim());
- resize_params.side(side);
+ resize_params.side((mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM);
resize_params.snapping_enabled(false);
+ resize_params.show_drag_handle(mShowDragHandle);
LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
lp->mResizeBar = resize_bar;
LLView::addChild(resize_bar, 0);
@@ -864,3 +929,4 @@ void LLLayoutStack::updateResizeBarLimits()
previous_visible_panelp = visible_panelp;
}
}
+
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 02c664f1a0..b570974bd6 100755
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -62,6 +62,11 @@ public:
Optional<F32> open_time_constant,
close_time_constant;
Optional<S32> resize_bar_overlap;
+ Optional<bool> show_drag_handle;
+ Optional<S32> drag_handle_first_indent;
+ Optional<S32> drag_handle_second_indent;
+ Optional<S32> drag_handle_thickness;
+ Optional<S32> drag_handle_shift;
Params();
};
@@ -126,6 +131,11 @@ private:
F32 mCloseTimeConstant;
bool mNeedsLayout;
S32 mResizeBarOverlap;
+ bool mShowDragHandle;
+ S32 mDragHandleFirstIndent;
+ S32 mDragHandleSecondIndent;
+ S32 mDragHandleThickness;
+ S32 mDragHandleShift;
}; // end class LLLayoutStack
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index f7bf39c897..f854e1785d 100755
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3146,6 +3146,13 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
const S32 CURSOR_WIDTH = 12;
+ if (menu->getChildList()->empty())
+ {
+ return;
+ }
+
+ menu->setVisible( TRUE );
+
//Do not show menu if all menu items are disabled
BOOL item_enabled = false;
for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin();
@@ -3156,8 +3163,9 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
item_enabled = item_enabled || menu_item->getEnabled();
}
- if(menu->getChildList()->empty() || !item_enabled)
+ if(!item_enabled)
{
+ menu->setVisible( FALSE );
return;
}
@@ -3173,8 +3181,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
menu->mFirstVisibleItem = NULL;
}
- menu->setVisible( TRUE );
-
// Fix menu rect if needed.
menu->needsArrange();
menu->arrangeAndClear();
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 1789f003b9..26ede21572 100755
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -214,7 +214,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
}
else
{
- LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", TRUE);
+ LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT);
mIgnoreSetting = LLUI::sSettingGroups["ignores"]->getControl(name);
}
}
@@ -1206,6 +1206,7 @@ LLNotifications::LLNotifications()
: LLNotificationChannelBase(LLNotificationFilters::includeEverything),
mIgnoreAllNotifications(false)
{
+ mListener.reset(new LLNotificationsListener(*this));
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 87573c2a56..9037712cc8 100755
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -98,6 +98,8 @@
#include "llrefcount.h"
#include "llsdparam.h"
+#include "llnotificationslistener.h"
+
class LLAvatarName;
typedef enum e_notification_priority
{
@@ -970,6 +972,8 @@ private:
bool mIgnoreAllNotifications;
+ boost::scoped_ptr<LLNotificationsListener> mListener;
+
std::vector<LLNotificationChannelPtr> mDefaultChannels;
};
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
new file mode 100644
index 0000000000..9e8e943ee6
--- /dev/null
+++ b/indra/llui/llnotificationslistener.cpp
@@ -0,0 +1,359 @@
+/**
+ * @file llnotificationslistener.cpp
+ * @author Brad Kittenbrink
+ * @date 2009-07-08
+ * @brief Implementation for llnotificationslistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llnotificationslistener.h"
+#include "llnotifications.h"
+#include "llnotificationtemplate.h"
+#include "llsd.h"
+#include "llui.h"
+
+LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
+ LLEventAPI("LLNotifications",
+ "LLNotifications listener to (e.g.) pop up a notification"),
+ mNotifications(notifications)
+{
+ add("requestAdd",
+ "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"
+ "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",
+ &LLNotificationsListener::requestAdd);
+ /* add("listChannels",
+ "Post to [\"reply\"] a map of info on existing channels",
+ &LLNotificationsListener::listChannels,
+ LLSD().with("reply", LLSD()));
+ */
+ add("listChannelNotifications",
+ "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]",
+ &LLNotificationsListener::listChannelNotifications,
+ LLSD().with("reply", LLSD()).with("channel", LLSD()));
+ add("respond",
+ "Respond to notification [\"uuid\"] with data in [\"response\"]",
+ &LLNotificationsListener::respond,
+ LLSD().with("uuid", LLSD()));
+ add("cancel",
+ "Cancel notification [\"uuid\"]",
+ &LLNotificationsListener::cancel,
+ LLSD().with("uuid", LLSD()));
+ add("ignore",
+ "Ignore future notification [\"name\"]\n"
+ "(from <notification name= > in notifications.xml)\n"
+ "according to boolean [\"ignore\"].\n"
+ "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n"
+ "Note that ignored notifications are not forwarded unless intercepted before\n"
+ "the \"Ignore\" channel.",
+ &LLNotificationsListener::ignore);
+ add("forward",
+ "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n"
+ "according to boolean [\"forward\"]. When enabled, only types matching\n"
+ "[\"types\"] are forwarded, as follows:\n"
+ "omitted or undefined: forward all notifications\n"
+ "string: forward only the specific named [sig]type\n"
+ "array of string: forward any notification matching any named [sig]type.\n"
+ "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n"
+ "notification.",
+ &LLNotificationsListener::forward,
+ LLSD().with("channel", LLSD()));
+}
+
+// This is here in the .cpp file so we don't need the definition of class
+// Forwarder in the header file.
+LLNotificationsListener::~LLNotificationsListener()
+{
+}
+
+void LLNotificationsListener::requestAdd(const LLSD& event_data) const
+{
+ if(event_data.has("reply"))
+ {
+ mNotifications.add(event_data["name"],
+ event_data["substitutions"],
+ event_data["payload"],
+ boost::bind(&LLNotificationsListener::NotificationResponder,
+ this,
+ event_data["reply"].asString(),
+ _1, _2
+ )
+ );
+ }
+ else
+ {
+ mNotifications.add(event_data["name"],
+ event_data["substitutions"],
+ event_data["payload"]);
+ }
+}
+
+void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,
+ const LLSD& notification,
+ const LLSD& response) const
+{
+ LLSD reponse_event;
+ reponse_event["notification"] = notification;
+ reponse_event["response"] = response;
+ LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
+}
+/*
+void LLNotificationsListener::listChannels(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(reqID.makeResponse());
+ for (LLNotifications::
+
+
+
+ for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()),
+ cmend(mNotifications.mChannels.end());
+ cmi != cmend; ++cmi)
+ {
+ LLSD channelInfo;
+ channelInfo["parent"] = cmi->second->getParentChannelName();
+ response[cmi->first] = channelInfo;
+ }
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
+*/
+void LLNotificationsListener::listChannelNotifications(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(reqID.makeResponse());
+ LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"]));
+ if (channel)
+ {
+ LLSD notifications(LLSD::emptyArray());
+ for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end());
+ ni != nend; ++ni)
+ {
+ notifications.append(asLLSD(*ni));
+ }
+ response["notifications"] = notifications;
+ }
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
+
+void LLNotificationsListener::respond(const LLSD& params) const
+{
+ LLNotificationPtr notification(mNotifications.find(params["uuid"]));
+ if (notification)
+ {
+ notification->respond(params["response"]);
+ }
+}
+
+void LLNotificationsListener::cancel(const LLSD& params) const
+{
+ LLNotificationPtr notification(mNotifications.find(params["uuid"]));
+ if (notification)
+ {
+ mNotifications.cancel(notification);
+ }
+}
+
+void LLNotificationsListener::ignore(const LLSD& params) const
+{
+ // Calling a method named "ignore", but omitting its "ignore" Boolean
+ // argument, should by default cause something to be ignored. Explicitly
+ // pass ["ignore"] = false to cancel ignore.
+ bool ignore = true;
+ if (params.has("ignore"))
+ {
+ ignore = params["ignore"].asBoolean();
+ }
+ // This method can be used to affect either a single notification name or
+ // all future notifications. The two use substantially different mechanisms.
+ if (params["name"].isDefined())
+ {
+ // ["name"] was passed: ignore just that notification
+ LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]);
+ if (templatep)
+ {
+ templatep->mForm->setIgnored(ignore);
+ }
+ }
+ else
+ {
+ // no ["name"]: ignore all future notifications
+ mNotifications.setIgnoreAllNotifications(ignore);
+ }
+}
+
+class LLNotificationsListener::Forwarder: public LLEventTrackable
+{
+ LOG_CLASS(LLNotificationsListener::Forwarder);
+public:
+ Forwarder(LLNotifications& llnotifications, const std::string& channel):
+ mNotifications(llnotifications),
+ mRespond(false)
+ {
+ // Connect to the specified channel on construction. Because
+ // LLEventTrackable is a base, we should automatically disconnect when
+ // destroyed.
+ LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));
+ if (channelptr)
+ {
+ // Insert our processing as a "passed filter" listener. This way
+ // we get to run before all the "changed" listeners, and we get to
+ // swipe it (hide it from the other listeners) if desired.
+ channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1));
+ }
+ }
+
+ void setPumpName(const std::string& name) { mPumpName = name; }
+ void setTypes(const LLSD& types) { mTypes = types; }
+ void setRespond(bool respond) { mRespond = respond; }
+
+private:
+ bool handle(const LLSD& notification) const;
+ bool matchType(const LLSD& filter, const std::string& type) const;
+
+ LLNotifications& mNotifications;
+ std::string mPumpName;
+ LLSD mTypes;
+ bool mRespond;
+};
+
+void LLNotificationsListener::forward(const LLSD& params)
+{
+ std::string channel(params["channel"]);
+ // First decide whether we're supposed to start forwarding or stop it.
+ // Default to true.
+ bool forward = true;
+ if (params.has("forward"))
+ {
+ forward = params["forward"].asBoolean();
+ }
+ if (! forward)
+ {
+ // This is a request to stop forwarding notifications on the specified
+ // channel. The rest of the params don't matter.
+ // Because mForwarders contains scoped_ptrs, erasing the map entry
+ // DOES delete the heap Forwarder object. Because Forwarder derives
+ // from LLEventTrackable, destroying it disconnects it from the
+ // channel.
+ mForwarders.erase(channel);
+ return;
+ }
+ // From here on, we know we're being asked to start (or modify) forwarding
+ // on the specified channel. Find or create an appropriate Forwarder.
+ ForwarderMap::iterator
+ entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first);
+ if (! entry->second)
+ {
+ entry->second.reset(new Forwarder(mNotifications, channel));
+ }
+ // Now, whether this Forwarder is brand-new or not, update it with the new
+ // request info.
+ Forwarder& fwd(*entry->second);
+ fwd.setPumpName(params["pump"]);
+ fwd.setTypes(params["types"]);
+ fwd.setRespond(params["respond"]);
+}
+
+bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
+{
+ LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL;
+ if (notification["sigtype"].asString() == "delete")
+ {
+ LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL;
+ // let other listeners see the "delete" operation
+ return false;
+ }
+ LLNotificationPtr note(mNotifications.find(notification["id"]));
+ if (! note)
+ {
+ LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL;
+ return false;
+ }
+ if (! matchType(mTypes, note->getType()))
+ {
+ LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL;
+ // We're not supposed to intercept this particular notification. Let
+ // other listeners process it.
+ return false;
+ }
+ LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL;
+ // This is a notification we care about. Forward it through specified
+ // LLEventPump.
+ LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note));
+ // Are we also being asked to auto-respond?
+ if (mRespond)
+ {
+ LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL;
+ note->respond(LLSD::emptyMap());
+ // Did that succeed in removing the notification? Only cancel() if
+ // it's still around -- otherwise we get an LL_ERRS crash!
+ note = mNotifications.find(notification["id"]);
+ if (note)
+ {
+ LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL;
+ mNotifications.cancel(note);
+ }
+ }
+ // If we've auto-responded to this notification, then it's going to be
+ // deleted. Other listeners would get the change operation, try to look it
+ // up and be baffled by lookup failure. So when we auto-respond, suppress
+ // this notification: don't pass it to other listeners.
+ return mRespond;
+}
+
+bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const
+{
+ // Decide whether this notification matches filter:
+ // undefined: forward all notifications
+ if (filter.isUndefined())
+ {
+ return true;
+ }
+ // array of string: forward any notification matching any named type
+ if (filter.isArray())
+ {
+ for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray());
+ ti != tend; ++ti)
+ {
+ if (ti->asString() == type)
+ {
+ return true;
+ }
+ }
+ // Didn't match any entry in the array
+ return false;
+ }
+ // string: forward only the specific named type
+ return (filter.asString() == type);
+}
+
+LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)
+{
+ LLSD notificationInfo(note->asLLSD());
+ // For some reason the following aren't included in LLNotification::asLLSD().
+ notificationInfo["summary"] = note->summarize();
+ notificationInfo["id"] = note->id();
+ notificationInfo["type"] = note->getType();
+ notificationInfo["message"] = note->getMessage();
+ notificationInfo["label"] = note->getLabel();
+ return notificationInfo;
+}
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
new file mode 100644
index 0000000000..f9f7641de6
--- /dev/null
+++ b/indra/llui/llnotificationslistener.h
@@ -0,0 +1,69 @@
+/**
+ * @file llnotificationslistener.h
+ * @author Brad Kittenbrink
+ * @date 2009-07-08
+ * @brief Wrap subset of LLNotifications API in event API for test scripts.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNOTIFICATIONSLISTENER_H
+#define LL_LLNOTIFICATIONSLISTENER_H
+
+#include "lleventapi.h"
+#include "llnotificationptr.h"
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <string>
+
+class LLNotifications;
+class LLSD;
+
+class LLNotificationsListener : public LLEventAPI
+{
+public:
+ LLNotificationsListener(LLNotifications & notifications);
+ ~LLNotificationsListener();
+
+private:
+ void requestAdd(LLSD const & event_data) const;
+
+ void NotificationResponder(const std::string& replypump,
+ const LLSD& notification,
+ const LLSD& response) const;
+
+ void listChannels(const LLSD& params) const;
+ void listChannelNotifications(const LLSD& params) const;
+ void respond(const LLSD& params) const;
+ void cancel(const LLSD& params) const;
+ void ignore(const LLSD& params) const;
+ void forward(const LLSD& params);
+
+ static LLSD asLLSD(LLNotificationPtr);
+
+ class Forwarder;
+ typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
+ ForwarderMap mForwarders;
+ LLNotifications & mNotifications;
+};
+
+#endif // LL_LLNOTIFICATIONSLISTENER_H
diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 15e56cbfe5..e67b22c977 100755
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -28,14 +28,53 @@
#include "llresizebar.h"
+#include "lllocalcliprect.h"
#include "llmath.h"
#include "llui.h"
#include "llmenugl.h"
#include "llfocusmgr.h"
#include "llwindow.h"
+class LLImagePanel : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<bool> horizontal;
+ Params() : horizontal("horizontal", false) {}
+ };
+ LLImagePanel(const Params& p) : LLPanel(p), mHorizontal(p.horizontal) {}
+ virtual ~LLImagePanel() {}
+
+ void draw()
+ {
+ const LLRect& parent_rect = getParent()->getRect();
+ const LLRect& rect = getRect();
+ LLRect clip_rect( -rect.mLeft, parent_rect.getHeight() - rect.mBottom - 2
+ , parent_rect.getWidth() - rect.mLeft - (mHorizontal ? 2 : 0), -rect.mBottom);
+ LLLocalClipRect clip(clip_rect);
+ LLPanel::draw();
+ }
+
+private:
+ bool mHorizontal;
+};
+
+static LLDefaultChildRegistry::Register<LLImagePanel> t1("resize_bar_image_panel");
+
+LLResizeBar::Params::Params()
+: max_size("max_size", S32_MAX),
+ snapping_enabled("snapping_enabled", true),
+ resizing_view("resizing_view"),
+ side("side"),
+ allow_double_click_snapping("allow_double_click_snapping", true),
+ show_drag_handle("show_drag_handle", false)
+{
+ name = "resize_bar";
+}
+
LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
-: LLView(p),
+: LLPanel(p),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
@@ -46,7 +85,9 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
mSnappingEnabled(p.snapping_enabled),
mAllowDoubleClickSnapping(p.allow_double_click_snapping),
mResizingView(p.resizing_view),
- mResizeListener(NULL)
+ mResizeListener(NULL),
+ mShowDragHandle(p.show_drag_handle),
+ mImagePanel(NULL)
{
setFollowsNone();
// set up some generically good follow code.
@@ -75,8 +116,37 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
default:
break;
}
+
+ if (mShowDragHandle)
+ {
+ LLViewBorder::Params border_params;
+ border_params.border_thickness = 1;
+ border_params.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight");
+ border_params.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark");
+
+ addBorder(border_params);
+ setBorderVisible(TRUE);
+
+ LLImagePanel::Params image_panel;
+ mDragHandleImage = LLUI::getUIImage(LLResizeBar::RIGHT == mSide ? "Vertical Drag Handle" : "Horizontal Drag Handle");
+ image_panel.bg_alpha_image = mDragHandleImage;
+ image_panel.background_visible = true;
+ image_panel.horizontal = (LLResizeBar::BOTTOM == mSide);
+ mImagePanel = LLUICtrlFactory::create<LLImagePanel>(image_panel);
+ setImagePanel(mImagePanel);
+ }
}
+BOOL LLResizeBar::postBuild()
+{
+ if (mShowDragHandle)
+ {
+ setBackgroundVisible(TRUE);
+ setTransparentColor(LLUIColorTable::instance().getColor("ResizebarBody"));
+ }
+
+ return LLPanel::postBuild();
+}
BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -342,3 +412,39 @@ BOOL LLResizeBar::handleDoubleClick(S32 x, S32 y, MASK mask)
return TRUE;
}
+void LLResizeBar::setImagePanel(LLPanel * panelp)
+{
+ const LLView::child_list_t * children = getChildList();
+ if (getChildCount() == 2)
+ {
+ LLPanel * image_panelp = dynamic_cast<LLPanel*>(children->back());
+ if (image_panelp)
+ {
+ removeChild(image_panelp);
+ delete image_panelp;
+ }
+ }
+
+ addChild(panelp);
+ sendChildToBack(panelp);
+}
+
+LLPanel * LLResizeBar::getImagePanel() const
+{
+ return getChildCount() > 0 ? (LLPanel *)getChildList()->back() : NULL;
+}
+
+void LLResizeBar::draw()
+{
+ if (mShowDragHandle)
+ {
+ S32 image_width = mDragHandleImage->getTextureWidth();
+ S32 image_height = mDragHandleImage->getTextureHeight();
+ const LLRect& panel_rect = getRect();
+ S32 image_left = (panel_rect.getWidth() - image_width) / 2 - 1;
+ S32 image_bottom = (panel_rect.getHeight() - image_height) / 2;
+ mImagePanel->setRect(LLRect(image_left, image_bottom + image_height, image_left + image_width, image_bottom));
+ }
+
+ LLPanel::draw();
+}
diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h
index 8190a95a71..bcf8ea0b40 100755
--- a/indra/llui/llresizebar.h
+++ b/indra/llui/llresizebar.h
@@ -27,15 +27,14 @@
#ifndef LL_RESIZEBAR_H
#define LL_RESIZEBAR_H
-#include "llview.h"
-#include "llcoord.h"
+#include "llpanel.h"
-class LLResizeBar : public LLView
+class LLResizeBar : public LLPanel
{
public:
enum Side { LEFT, TOP, RIGHT, BOTTOM };
- struct Params : public LLInitParam::Block<Params, LLView::Params>
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
Mandatory<LLView*> resizing_view;
Mandatory<Side> side;
@@ -44,24 +43,19 @@ public:
Optional<S32> max_size;
Optional<bool> snapping_enabled;
Optional<bool> allow_double_click_snapping;
+ Optional<bool> show_drag_handle;
- Params()
- : max_size("max_size", S32_MAX),
- snapping_enabled("snapping_enabled", true),
- resizing_view("resizing_view"),
- side("side"),
- allow_double_click_snapping("allow_double_click_snapping", true)
- {
- name = "resize_bar";
- }
+ Params();
};
protected:
LLResizeBar(const LLResizeBar::Params& p);
friend class LLUICtrlFactory;
+
+ /*virtual*/ BOOL postBuild();
public:
-// virtual void draw(); No appearance
+ virtual void draw();
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -72,20 +66,26 @@ public:
void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }
bool canResize() { return getEnabled() && mMaxSize > mMinSize; }
void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;}
+ BOOL isShowDragHandle() const { return mShowDragHandle; }
+ void setImagePanel(LLPanel * panelp);
+ LLPanel * getImagePanel() const;
private:
- S32 mDragLastScreenX;
- S32 mDragLastScreenY;
- S32 mLastMouseScreenX;
- S32 mLastMouseScreenY;
- LLCoordGL mLastMouseDir;
- S32 mMinSize;
- S32 mMaxSize;
- const Side mSide;
- BOOL mSnappingEnabled;
- BOOL mAllowDoubleClickSnapping;
- LLView* mResizingView;
- boost::function<void(void*)> mResizeListener;
+ S32 mDragLastScreenX;
+ S32 mDragLastScreenY;
+ S32 mLastMouseScreenX;
+ S32 mLastMouseScreenY;
+ LLCoordGL mLastMouseDir;
+ S32 mMinSize;
+ S32 mMaxSize;
+ const Side mSide;
+ BOOL mSnappingEnabled;
+ BOOL mAllowDoubleClickSnapping;
+ BOOL mShowDragHandle;
+ LLView* mResizingView;
+ boost::function<void(void*)> mResizeListener;
+ LLPointer<LLUIImage> mDragHandleImage;
+ LLPanel * mImagePanel;
};
#endif // LL_RESIZEBAR_H
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
index af124d9826..cc9ff7a487 100755
--- a/indra/llui/llscrolllistcolumn.cpp
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -236,7 +236,8 @@ void LLScrollColumnHeader::handleReshape(const LLRect& new_rect, bool by_user)
// tell scroll list to layout columns again
// do immediate update to get proper feedback to resize handle
// which needs to know how far the resize actually went
- mColumn->mParentCtrl->updateColumns();
+ const bool force_update = true;
+ mColumn->mParentCtrl->updateColumns(force_update);
}
}
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 7f04c92b27..6e03f604a2 100755
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -615,7 +615,6 @@ S32 LLScrollListCtrl::calcMaxContentWidth()
if (mColumnWidthsDirty)
{
- mColumnWidthsDirty = false;
// update max content width for this column, by looking at all items
column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0;
item_list::iterator iter;
@@ -629,6 +628,7 @@ S32 LLScrollListCtrl::calcMaxContentWidth()
}
max_item_width += column->mMaxContentWidth;
}
+ mColumnWidthsDirty = false;
return max_item_width;
}
@@ -643,7 +643,7 @@ bool LLScrollListCtrl::updateColumnWidths()
if (!column) continue;
// update column width
- S32 new_width = column->getWidth();
+ S32 new_width = 0;
if (column->mRelWidth >= 0)
{
new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth());
@@ -652,6 +652,10 @@ bool LLScrollListCtrl::updateColumnWidths()
{
new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns;
}
+ else
+ {
+ new_width = column->getWidth();
+ }
if (column->getWidth() != new_width)
{
@@ -693,9 +697,9 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp)
}
-void LLScrollListCtrl::updateColumns()
+void LLScrollListCtrl::updateColumns(bool force_update)
{
- if (!mColumnsDirty)
+ if (!mColumnsDirty && !force_update)
return;
mColumnsDirty = false;
@@ -749,7 +753,7 @@ void LLScrollListCtrl::updateColumns()
}
// propagate column widths to individual cells
- if (columns_changed_width)
+ if (columns_changed_width || force_update)
{
item_list::iterator iter;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
@@ -1179,10 +1183,10 @@ LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos)
// Selects first enabled item of the given name.
// Returns false if item not found.
// Calls getItemByLabel in order to combine functionality
-BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive, S32 column/* = 0*/)
{
deselectAllItems(TRUE); // ensure that no stale items are selected, even if we don't find a match
- LLScrollListItem* item = getItemByLabel(label, case_sensitive);
+ LLScrollListItem* item = getItemByLabel(label, case_sensitive, column);
bool found = NULL != item;
if(found)
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 8fa06cc499..c61e281a31 100755
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -241,7 +241,7 @@ public:
// one of which can be selected at a time.
virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
- BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE ); // FALSE if item not found
+ BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); // FALSE if item not found
BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE);
BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);
LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );
@@ -342,7 +342,7 @@ public:
static void onClickColumn(void *userdata);
- virtual void updateColumns();
+ virtual void updateColumns(bool force_update = false);
S32 calcMaxContentWidth();
bool updateColumnWidths();
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index fd98155704..76ba53ec32 100755
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -27,7 +27,7 @@
#include "linden_common.h"
#include "lltabcontainer.h"
-
+#include "llviewereventrecorder.h"
#include "llfocusmgr.h"
#include "lllocalcliprect.h"
#include "llrect.h"
@@ -578,6 +578,11 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
tab_button->setFocus(TRUE);
}
}
+ if (handled) {
+ // Note: May need to also capture local coords right here ?
+ LLViewerEventRecorder::instance().update_xui(getPathname( ));
+ }
+
return handled;
}
@@ -629,30 +634,33 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
BOOL handled = FALSE;
BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
+ S32 local_x = x - getRect().mLeft;
+ S32 local_y = y - getRect().mBottom;
+
if (has_scroll_arrows)
{
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
+ local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
+ local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
handled = mJumpPrevArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
+ local_x = x - mJumpNextArrowBtn->getRect().mLeft;
+ local_y = y - mJumpNextArrowBtn->getRect().mBottom;
handled = mJumpNextArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mPrevArrowBtn && mPrevArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
+ local_x = x - mPrevArrowBtn->getRect().mLeft;
+ local_y = y - mPrevArrowBtn->getRect().mBottom;
handled = mPrevArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mNextArrowBtn && mNextArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mNextArrowBtn->getRect().mBottom;
+ local_x = x - mNextArrowBtn->getRect().mLeft;
+ local_y = y - mNextArrowBtn->getRect().mBottom;
handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask);
}
}
@@ -676,6 +684,10 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
}
gFocusMgr.setMouseCapture(NULL);
}
+ if (handled) {
+ // Note: may need to capture local coords here
+ LLViewerEventRecorder::instance().update_xui(getPathname( ));
+ }
return handled;
}
@@ -1059,21 +1071,21 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
if (mIsVertical)
{
- p.name(std::string("vert tab button"));
- p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
- p.image_selected(mMiddleTabParams.tab_left_image_selected);
- p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
+ p.name("vtab_"+std::string(child->getName()));
+ p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
+ p.image_selected(mMiddleTabParams.tab_left_image_selected);
+ p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
}
else
- {
- p.name(std::string(child->getName()) + " tab");
- p.visible(false);
- p.image_unselected(tab_img);
- p.image_selected(tab_selected_img);
- p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM);
- // Try to squeeze in a bit more text
- p.pad_left( mLabelPadLeft );
- p.pad_right(2);
+ {
+ p.name("htab_"+std::string(child->getName()));
+ p.visible(false);
+ p.image_unselected(tab_img);
+ p.image_selected(tab_selected_img);
+ p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM);
+ // Try to squeeze in a bit more text
+ p.pad_left( mLabelPadLeft );
+ p.pad_right(2);
}
// *TODO : It seems wrong not to use p in both cases considering the way p is initialized
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index a45c4ced2e..3c284b3f03 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -180,6 +180,7 @@ LLTextBase::Params::Params()
LLTextBase::LLTextBase(const LLTextBase::Params &p)
: LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
mURLClickSignal(NULL),
+ mIsFriendSignal(NULL),
mMaxTextByteLength( p.max_text_length ),
mFont(p.font),
mFontShadow(p.font_shadow),
@@ -653,6 +654,10 @@ void LLTextBase::drawText()
mSpellCheckEnd = end;
}
}
+ else
+ {
+ mMisspellRanges.clear();
+ }
LLTextSegmentPtr cur_segment = *seg_iter;
@@ -1850,7 +1855,17 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
- if (index > getLength()) { return mSegments.end(); }
+ S32 text_len = 0;
+ if (!useLabel())
+ {
+ text_len = getLength();
+ }
+ else
+ {
+ text_len = mLabel.getWString().length();
+ }
+
+ if (index > text_len) { return mSegments.end(); }
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
@@ -1866,7 +1881,17 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i
{
static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
- if (index > getLength()) { return mSegments.end(); }
+ S32 text_len = 0;
+ if (!useLabel())
+ {
+ text_len = getLength();
+ }
+ else
+ {
+ text_len = mLabel.getWString().length();
+ }
+
+ if (index > text_len) { return mSegments.end(); }
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
@@ -1916,9 +1941,12 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.OpenInternal", boost::bind(&LLUrlAction::openURLInternal, url));
registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));
registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url));
+ registrar.add("Url.Block", boost::bind(&LLUrlAction::blockObject, url));
registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));
registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url));
+ registrar.add("Url.RemoveFriend", boost::bind(&LLUrlAction::removeFriend, url));
+ registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url));
registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));
registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
@@ -1927,6 +1955,19 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
delete mPopupMenu;
mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
LLMenuHolderGL::child_registry_t::instance());
+ if (mIsFriendSignal)
+ {
+ bool isFriend = *(*mIsFriendSignal)(LLUUID(LLUrlAction::getUserID(url)));
+ LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend");
+ LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend");
+
+ if (addFriendButton && removeFriendButton)
+ {
+ addFriendButton->setEnabled(!isFriend);
+ removeFriendButton->setEnabled(isFriend);
+ }
+ }
+
if (mPopupMenu)
{
mPopupMenu->show(x, y);
@@ -2096,7 +2137,7 @@ void LLTextBase::resetLabel()
}
}
-bool LLTextBase::useLabel()
+bool LLTextBase::useLabel() const
{
return !getLength() && !mLabel.empty() && !hasFocus();
}
@@ -2602,21 +2643,18 @@ void LLTextBase::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool
void LLTextBase::changeLine( S32 delta )
{
S32 line = getLineNumFromDocIndex(mCursorPos);
+ S32 max_line_nb = getLineCount() - 1;
+ max_line_nb = (max_line_nb < 0 ? 0 : max_line_nb);
+
+ S32 new_line = llclamp(line + delta, 0, max_line_nb);
- S32 new_line = line;
- if( (delta < 0) && (line > 0 ) )
- {
- new_line = line - 1;
- }
- else if( (delta > 0) && (line < (getLineCount() - 1)) )
- {
- new_line = line + 1;
- }
-
- LLRect visible_region = getVisibleDocumentRect();
-
- S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
- setCursorPos(new_cursor_pos, true);
+ if (new_line != line)
+ {
+ LLRect visible_region = getVisibleDocumentRect();
+ S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel,
+ mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
+ setCursorPos(new_cursor_pos, true);
+ }
}
bool LLTextBase::scrolledToStart()
@@ -2910,6 +2948,15 @@ boost::signals2::connection LLTextBase::setURLClickedCallback(const commit_signa
return mURLClickSignal->connect(cb);
}
+boost::signals2::connection LLTextBase::setIsFriendCallback(const is_friend_signal_t::slot_type& cb)
+{
+ if (!mIsFriendSignal)
+ {
+ mIsFriendSignal = new is_friend_signal_t();
+ }
+ return mIsFriendSignal->connect(cb);
+}
+
//
// LLTextSegment
//
@@ -3203,7 +3250,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
: LLFontGL::ONLY_WORD_BOUNDARIES;
- LLWString offsetString(text.c_str() + segment_offset + mStart);
+ S32 offsetLength = text.length() - (segment_offset + mStart);
if(getLength() < segment_offset + mStart)
{
@@ -3211,13 +3258,13 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
<< segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << "\tmax_chars\t" << max_chars << llendl;
}
- if(offsetString.length() + 1 < max_chars)
+ if( (offsetLength + 1) < max_chars)
{
- llinfos << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetString.length():\t" << offsetString.length() << " getLength() : "
+ llinfos << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetLength:\t" << offsetLength << " getLength() : "
<< getLength() << "\tsegment_offset:\t" << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << llendl;
}
- S32 num_chars = mStyle->getFont()->maxDrawableChars(offsetString.c_str(),
+ S32 num_chars = mStyle->getFont()->maxDrawableChars( text.c_str() + (segment_offset + mStart),
(F32)num_pixels,
max_chars,
word_wrap_style);
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 20a73387b5..a74e97cac8 100755
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -258,6 +258,8 @@ public:
friend class LLNormalTextSegment;
friend class LLUICtrlFactory;
+ typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t;
+
struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>
{
Alternative<F32> multiple;
@@ -434,6 +436,7 @@ public:
virtual void appendImageSegment(const LLStyle::Params& style_params);
virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb);
+ boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
void setWordWrap(bool wrap);
LLScrollContainer* getScrollContainer() const { return mScroller; }
@@ -507,7 +510,7 @@ protected:
void initFromParams(const Params& p);
virtual void beforeValueChange();
virtual void onValueChange(S32 start, S32 end);
- virtual bool useLabel();
+ virtual bool useLabel() const;
// draw methods
void drawSelectionBackground(); // draws the black box behind the selected text
@@ -648,6 +651,9 @@ protected:
// Fired when a URL link is clicked
commit_signal_t* mURLClickSignal;
+ // Used to check if user with given ID is avatar's friend
+ is_friend_signal_t* mIsFriendSignal;
+
LLUIString mLabel; // text label that is visible when no user text provided
};
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 834f213097..0c16e06109 100755
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1125,7 +1125,8 @@ void LLTextEditor::addChar(llwchar wc)
}
}
-void LLTextEditor::addLineBreakChar()
+
+void LLTextEditor::addLineBreakChar(BOOL group_together)
{
if( !getEnabled() )
{
@@ -1143,7 +1144,7 @@ void LLTextEditor::addLineBreakChar()
LLStyleConstSP sp(new LLStyle(LLStyle::Params()));
LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos);
- S32 pos = execute(new TextCmdAddChar(mCursorPos, FALSE, '\n', segment));
+ S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment));
setCursorPos(mCursorPos + pos);
}
@@ -1484,21 +1485,28 @@ void LLTextEditor::pasteTextWithLinebreaks(LLWString & clean_string)
std::basic_string<llwchar>::size_type start = 0;
std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
- while(pos!=-1)
+ while((pos != -1) && (pos != clean_string.length() -1))
{
if(pos!=start)
{
std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start);
- setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
+ setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr()));
}
- addLineBreakChar();
-
+ addLineBreakChar(TRUE); // Add a line break and group with the next addition.
+
start = pos+1;
pos = clean_string.find('\n',start);
}
- std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
- setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
+ if (pos != start)
+ {
+ std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
+ setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
+ }
+ else
+ {
+ addLineBreakChar(FALSE); // Add a line break and end the grouping.
+ }
}
// copy selection to primary
@@ -1964,8 +1972,7 @@ void LLTextEditor::onFocusReceived()
updateAllowingLanguageInput();
}
-// virtual, from LLView
-void LLTextEditor::onFocusLost()
+void LLTextEditor::focusLostHelper()
{
updateAllowingLanguageInput();
@@ -1982,7 +1989,11 @@ void LLTextEditor::onFocusLost()
// Make sure cursor is shown again
getWindow()->showCursorFromMouseMove();
+}
+void LLTextEditor::onFocusLost()
+{
+ focusLostHelper();
LLTextBase::onFocusLost();
}
@@ -2128,12 +2139,17 @@ void LLTextEditor::drawPreeditMarker()
continue;
}
- S32 preedit_left = mVisibleTextRect.mLeft;
+ line_info& line = mLineInfoList[cur_line];
+ LLRect text_rect(line.mRect);
+ text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents
+ text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position
+
+ S32 preedit_left = text_rect.mLeft;
if (left > line_start)
{
preedit_left += mFont->getWidth(text, line_start, left - line_start);
}
- S32 preedit_right = mVisibleTextRect.mLeft;
+ S32 preedit_right = text_rect.mLeft;
if (right < line_end)
{
preedit_right += mFont->getWidth(text, line_start, right - line_start);
@@ -2146,18 +2162,18 @@ void LLTextEditor::drawPreeditMarker()
if (mPreeditStandouts[i])
{
gl_rect_2d(preedit_left + preedit_standout_gap,
- line_y + preedit_standout_position,
- preedit_right - preedit_standout_gap - 1,
- line_y + preedit_standout_position - preedit_standout_thickness,
- (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));
+ text_rect.mBottom + mFont->getDescenderHeight() - 1,
+ preedit_right - preedit_standout_gap - 1,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness,
+ (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));
}
else
{
gl_rect_2d(preedit_left + preedit_marker_gap,
- line_y + preedit_marker_position,
- preedit_right - preedit_marker_gap - 1,
- line_y + preedit_marker_position - preedit_marker_thickness,
- (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));
+ text_rect.mBottom + mFont->getDescenderHeight() - 1,
+ preedit_right - preedit_marker_gap - 1,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness,
+ (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));
}
}
}
@@ -2240,12 +2256,13 @@ void LLTextEditor::draw()
LLRect clip_rect(mVisibleTextRect);
clip_rect.stretch(1);
LLLocalClipRect clip(clip_rect);
- drawPreeditMarker();
}
LLTextBase::draw();
drawLineNumbers();
+ drawPreeditMarker();
+
//RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
// when in readonly mode
mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly);
@@ -2695,14 +2712,20 @@ BOOL LLTextEditor::hasPreeditString() const
void LLTextEditor::resetPreedit()
{
+ if (hasSelection())
+ {
+ if (hasPreeditString())
+ {
+ llwarns << "Preedit and selection!" << llendl;
+ deselect();
+ }
+ else
+ {
+ deleteSelection(TRUE);
+ }
+ }
if (hasPreeditString())
{
- if (hasSelection())
- {
- llwarns << "Preedit and selection!" << llendl;
- deselect();
- }
-
setCursorPos(mPreeditPositions.front());
removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
@@ -2750,7 +2773,10 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
{
mPreeditOverwrittenWString.clear();
}
- insertStringNoUndo(insert_preedit_at, mPreeditWString);
+
+ segment_vec_t segments;
+ //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed.
+ insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments);
mPreeditStandouts = preedit_standouts;
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 969e072704..32b543ec0e 100755
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -248,13 +248,14 @@ protected:
// Undoable operations
void addChar(llwchar c); // at mCursorPos
S32 addChar(S32 pos, llwchar wc);
- void addLineBreakChar();
+ void addLineBreakChar(BOOL group_together = FALSE);
S32 overwriteChar(S32 pos, llwchar wc);
void removeChar();
S32 removeChar(S32 pos);
S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
S32 remove(S32 pos, S32 length, bool group_with_next_op);
+ void focusLostHelper();
void updateAllowingLanguageInput();
BOOL hasPreeditString() const;
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index 3d9f5cbbc2..928e82cb8c 100755
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -381,7 +381,7 @@ bool LLToolBar::stopCommandInProgress(const LLCommandId& commandId)
return (command_button != NULL);
}
-bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash)
+bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */)
{
LLButton * command_button = NULL;
@@ -391,7 +391,7 @@ bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash)
if (it != mButtonMap.end())
{
command_button = it->second;
- command_button->setFlashing(flash ? TRUE : FALSE);
+ command_button->setFlashing((BOOL)(flash),(BOOL)(force_flashing));
}
}
diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h
index 31424a36d4..743951a41f 100755
--- a/indra/llui/lltoolbar.h
+++ b/indra/llui/lltoolbar.h
@@ -192,7 +192,7 @@ public:
bool hasCommand(const LLCommandId& commandId) const; // is this command bound to a button in this toolbar
bool enableCommand(const LLCommandId& commandId, bool enabled); // enable/disable button bound to the specified command, if it exists in this toolbar
bool stopCommandInProgress(const LLCommandId& commandId); // stop command if it is currently active
- bool flashCommand(const LLCommandId& commandId, bool flash); // flash button associated with given command, if in this toolbar
+ bool flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing = false); // flash button associated with given command, if in this toolbar
void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; } // connects drag and drop behavior to external logic
void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; }
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index b9c843e931..1722bf27bd 100755
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -29,7 +29,7 @@
#define LLUICTRL_CPP
#include "lluictrl.h"
-
+#include "llviewereventrecorder.h"
#include "llfocusmgr.h"
#include "llpanel.h"
#include "lluictrlfactory.h"
@@ -308,22 +308,40 @@ void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask)
//virtual
BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask)
{
+
+ lldebugs << "LLUICtrl::handleMouseDown calling LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl;
+
BOOL handled = LLView::handleMouseDown(x,y,mask);
+
if (mMouseDownSignal)
{
(*mMouseDownSignal)(this,x,y,mask);
}
+ lldebugs << "LLUICtrl::handleMousedown - handled is returning as: " << handled << " " << llendl;
+
+ if (handled) {
+ LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname());
+ }
return handled;
}
//virtual
BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask)
{
+
+ lldebugs << "LLUICtrl::handleMouseUp calling LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl;
+
BOOL handled = LLView::handleMouseUp(x,y,mask);
+ if (handled) {
+ LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname());
+ }
if (mMouseUpSignal)
{
(*mMouseUpSignal)(this,x,y,mask);
}
+
+ lldebugs << "LLUICtrl::handleMouseUp - handled for xui " << getPathname() << " - is returning as: " << handled << " " << llendl;
+
return handled;
}
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
index f51aeaec13..23e574cb74 100755
--- a/indra/llui/llurlaction.cpp
+++ b/indra/llui/llurlaction.cpp
@@ -170,6 +170,30 @@ std::string LLUrlAction::getUserID(std::string url)
return id_str;
}
+std::string LLUrlAction::getObjectId(std::string url)
+{
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ std::string id_str;
+ if (path_array.size() >= 3)
+ {
+ id_str = path_array.get(2).asString();
+ }
+ return id_str;
+}
+
+std::string LLUrlAction::getObjectName(std::string url)
+{
+ LLURI uri(url);
+ LLSD query_map = uri.queryMap();
+ std::string name;
+ if (query_map.has("name"))
+ {
+ name = query_map["name"].asString();
+ }
+ return name;
+}
+
void LLUrlAction::sendIM(std::string url)
{
std::string id_str = getUserID(url);
@@ -188,3 +212,21 @@ void LLUrlAction::addFriend(std::string url)
}
}
+void LLUrlAction::removeFriend(std::string url)
+{
+ std::string id_str = getUserID(url);
+ if (LLUUID::validate(id_str))
+ {
+ executeSLURL("secondlife:///app/agent/" + id_str + "/removefriend");
+ }
+}
+
+void LLUrlAction::blockObject(std::string url)
+{
+ std::string object_id = getObjectId(url);
+ std::string object_name = getObjectName(url);
+ if (LLUUID::validate(object_id))
+ {
+ executeSLURL("secondlife:///app/agent/" + object_id + "/block/" + object_name);
+ }
+}
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
index e31cd71a20..e731376b95 100755
--- a/indra/llui/llurlaction.h
+++ b/indra/llui/llurlaction.h
@@ -77,8 +77,12 @@ public:
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url);
static std::string getUserID(std::string url);
+ static std::string getObjectName(std::string url);
+ static std::string getObjectId(std::string url);
static void sendIM(std::string url);
static void addFriend(std::string url);
+ static void removeFriend(std::string url);
+ static void blockObject(std::string url);
/// specify the callbacks to enable this class's functionality
typedef boost::function<void (const std::string&)> url_callback_t;
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 99ee688888..b1cc502c4b 100755
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -504,6 +504,10 @@ std::string localize_slapp_label(const std::string& url, const std::string& full
{
return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
}
+ if (LLStringUtil::endsWith(url, "/removefriend"))
+ {
+ return LLTrans::getString("SLappAgentRemoveFriend") + " " + full_name;
+ }
return full_name;
}
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 3613a40e2c..20015dca1a 100755
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -48,7 +48,9 @@
#include "lluictrlfactory.h"
#include "lltooltip.h"
#include "llsdutil.h"
-
+#include "llsdserialize.h"
+#include "llviewereventrecorder.h"
+#include "llkeyboard.h"
// for ui edit hack
#include "llbutton.h"
#include "lllineeditor.h"
@@ -642,13 +644,27 @@ void LLView::setVisible(BOOL visible)
// virtual
void LLView::handleVisibilityChange ( BOOL new_visibility )
{
+ BOOL old_visibility;
BOOST_FOREACH(LLView* viewp, mChildList)
{
// only views that are themselves visible will have their overall visibility affected by their ancestors
- if (viewp->getVisible())
+ old_visibility=viewp->getVisible();
+
+ if (old_visibility!=new_visibility)
+ {
+ LLViewerEventRecorder::instance().logVisibilityChange( viewp->getPathname(), viewp->getName(), new_visibility,"widget");
+ }
+
+ if (old_visibility)
{
viewp->handleVisibilityChange ( new_visibility );
}
+
+ // Consider changing returns to confirm success and know which widget grabbed it
+ // For now assume success and log at highest xui possible
+ // NOTE we log actual state - which may differ if it somehow failed to set visibility
+ lldebugs << "LLView::handleVisibilityChange - now: " << getVisible() << " xui: " << viewp->getPathname() << " name: " << viewp->getName() << llendl;
+
}
}
@@ -697,6 +713,7 @@ bool LLView::visibleEnabledAndContains(S32 local_x, S32 local_y)
&& getEnabled();
}
+// This is NOT event recording related
void LLView::logMouseEvent()
{
if (sDebugMouseHandling)
@@ -743,7 +760,14 @@ LLView* LLView::childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDA
if ((viewp->*method)( local_x, local_y, extra )
|| (allow_mouse_block && viewp->blockMouseEvent( local_x, local_y )))
{
+ lldebugs << "LLView::childrenHandleMouseEvent calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << llendl;
+ lldebugs << "LLView::childrenHandleMouseEvent getPathname for viewp result: " << viewp->getPathname() << "for this view: " << getPathname() << llendl;
+
+ LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());
+
+ // This is NOT event recording related
viewp->logMouseEvent();
+
return viewp;
}
}
@@ -766,6 +790,7 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)
if (viewp->handleToolTip(local_x, local_y, mask)
|| viewp->blockMouseEvent(local_x, local_y))
{
+ // This is NOT event recording related
viewp->logMouseEvent();
return viewp;
}
@@ -824,6 +849,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
if (viewp->handleHover(local_x, local_y, mask)
|| viewp->blockMouseEvent(local_x, local_y))
{
+ // This is NOT event recording related
viewp->logMouseEvent();
return viewp;
}
@@ -907,10 +933,12 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
if (!handled)
{
+ // For event logging we don't care which widget handles it
+ // So we capture the key at the end of this function once we know if it was handled
handled = handleKeyHere( key, mask );
- if (handled && LLView::sDebugKeys)
+ if (handled)
{
- llinfos << "Key handled by " << getName() << llendl;
+ llwarns << "Key handled by " << getName() << llendl;
}
}
}
@@ -958,6 +986,11 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
handled = mParentView->handleUnicodeChar(uni_char, FALSE);
}
+ if (handled)
+ {
+ LLViewerEventRecorder::instance().logKeyUnicodeEvent(uni_char);
+ }
+
return handled;
}
@@ -987,12 +1020,16 @@ BOOL LLView::hasMouseCapture()
BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
{
- return childrenHandleMouseUp( x, y, mask ) != NULL;
+ LLView* r = childrenHandleMouseUp( x, y, mask );
+
+ return (r!=NULL);
}
BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
{
- return childrenHandleMouseDown( x, y, mask ) != NULL;
+ LLView* r= childrenHandleMouseDown(x, y, mask );
+
+ return (r!=NULL);
}
BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask)
@@ -1065,7 +1102,7 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)
LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)
{
- return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask);
+ return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask);
}
LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
diff --git a/indra/llui/llviewereventrecorder.cpp b/indra/llui/llviewereventrecorder.cpp
new file mode 100644
index 0000000000..a352f621eb
--- /dev/null
+++ b/indra/llui/llviewereventrecorder.cpp
@@ -0,0 +1,296 @@
+/**
+ * @file llviewereventrecorder.cpp
+ * @brief Viewer event recording and playback support for mouse and keyboard events
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ *
+ * Copyright (c) 2013, Linden Research, Inc.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewereventrecorder.h"
+#include "llui.h"
+#include "llleap.h"
+
+LLViewerEventRecorder::LLViewerEventRecorder() {
+
+ clear(UNDEFINED);
+
+ // Remove any previous event log file
+ std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.old");
+ LLFile::remove(old_log_ui_events_to_llsd_file);
+
+
+ mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.llsd");
+ LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file);
+
+}
+
+
+bool LLViewerEventRecorder::displayViewerEventRecorderMenuItems() {
+ return LLUI::sSettingGroups["config"]->getBOOL("ShowEventRecorderMenuItems");
+}
+
+
+void LLViewerEventRecorder::setEventLoggingOn() {
+ if (! mLog.is_open()) {
+ mLog.open(mLogFilename, llofstream::out);
+ }
+ logEvents=true;
+ lldebugs << "LLViewerEventRecorder::setEventLoggingOn event logging turned on" << llendl;
+}
+
+void LLViewerEventRecorder::setEventLoggingOff() {
+ logEvents=false;
+ mLog.flush();
+ mLog.close();
+ lldebugs << "LLViewerEventRecorder::setEventLoggingOff event logging turned off" << llendl;
+}
+
+
+ LLViewerEventRecorder::~LLViewerEventRecorder() {
+ if (mLog.is_open()) {
+ mLog.close();
+ }
+}
+
+void LLViewerEventRecorder::clear_xui() {
+ xui.clear();
+}
+
+void LLViewerEventRecorder::clear(S32 r) {
+
+ xui.clear();
+
+ local_x=r;
+ local_y=r;
+
+ global_x=r;
+ global_y=r;
+
+
+}
+
+void LLViewerEventRecorder::setMouseLocalCoords(S32 x, S32 y) {
+ local_x=x;
+ local_y=y;
+}
+
+void LLViewerEventRecorder::setMouseGlobalCoords(S32 x, S32 y) {
+ global_x=x;
+ global_y=y;
+}
+
+void LLViewerEventRecorder::updateMouseEventInfo(S32 local_x, S32 local_y, S32 global_x, S32 global_y, std::string mName) {
+
+ LLView * target_view = LLUI::resolvePath(LLUI::getRootView(), xui);
+ if (! target_view) {
+ lldebugs << "LLViewerEventRecorder::updateMouseEventInfo - xui path on file at moment is NOT valid - so DO NOT record these local coords" << llendl;
+ return;
+ }
+ lldebugs << "LLViewerEventRecorder::updateMouseEventInfo b4 updatemouseeventinfo - local_x|global x "<< this->local_x << " " << this->global_x << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl;
+
+
+ if (this->local_x < 1 && this->local_y<1 && local_x && local_y) {
+ this->local_x=local_x;
+ this->local_y=local_y;
+ }
+ this->global_x=global_x;
+ this->global_y=global_y;
+
+ // ONLY record deepest xui path for hierarchy searches - or first/only xui for floaters/panels reached via mouse captor - and llmousehandler
+ if (mName!="" && mName!="/" && xui=="") {
+ // xui=std::string("/")+mName+xui;
+ //xui=mName+xui;
+ xui = mName; // TODO review confirm we never call with partial path - also cAN REMOVE CHECK FOR "" - ON OTHER HAND IT'S PRETTY HARMLESS
+ }
+
+ lldebugs << "LLViewerEventRecorder::updateMouseEventInfo after updatemouseeventinfo - local_x|global x "<< this->local_x << " " << this->global_x << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl;
+}
+
+void LLViewerEventRecorder::logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype) {
+
+ LLSD event=LLSD::emptyMap();
+
+ event.insert("event",LLSD(std::string("visibility")));
+
+ if (visibility) {
+ event.insert("visibility",LLSD(true));
+ } else {
+ event.insert("visibility",LLSD(false));
+ }
+
+ if (event_subtype!="") {
+ event.insert("event_subtype", LLSD(event_subtype));
+ }
+
+ if(name!="") {
+ event.insert("name",LLSD(name));
+ }
+
+ if (xui!="") {
+ event.insert("path",LLSD(xui));
+ }
+
+ event.insert("timestamp",LLSD(LLDate::now().asString()));
+ recordEvent(event);
+}
+
+
+std::string LLViewerEventRecorder::get_xui() {
+ return xui;
+}
+void LLViewerEventRecorder::update_xui(std::string xui) {
+ if (xui!="" && this->xui=="" ) {
+ lldebugs << "LLViewerEventRecorder::update_xui to " << xui << llendl;
+ this->xui=xui;
+ } else {
+ lldebugs << "LLViewerEventRecorder::update_xui called with empty string" << llendl;
+ }
+}
+
+void LLViewerEventRecorder::logKeyEvent(KEY key, MASK mask) {
+
+ // NOTE: Event recording only logs keydown events - the viewer itself hides keyup events at a fairly low level in the code and does not appear to care about them anywhere
+
+ LLSD event = LLSD::emptyMap();
+
+ event.insert("event",LLSD("type"));
+
+ // keysym ...or
+ // keycode...or
+ // char
+ event.insert("keysym",LLSD(LLKeyboard::stringFromKey(key)));
+
+ // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps
+ // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might
+ // break the test script and it would be useful to have more context to make these sorts of edits safer
+
+ // TODO replace this with a call which extracts to an array of names of masks (just like vita expects during playback)
+ // This is looking more and more like an object is a good idea, for this part a handy method call to setMask(mask) would be nice :-)
+ // call the func - llkeyboard::llsdStringarrayFromMask
+
+ LLSD key_mask=LLSD::emptyArray();
+
+ if (mask & MASK_CONTROL) { key_mask.append(LLSD("CTL")); } // Mac command key - has code of 0x1 in llcommon/indra_contstants
+ if (mask & MASK_ALT) { key_mask.append(LLSD("ALT")); }
+ if (mask & MASK_SHIFT) { key_mask.append(LLSD("SHIFT")); }
+ if (mask & MASK_MAC_CONTROL) { key_mask.append(LLSD("MAC_CONTROL")); }
+
+ event.insert("mask",key_mask);
+ event.insert("timestamp",LLSD(LLDate::now().asString()));
+
+ // Although vita has keyDown and keyUp requests it does not have type as a high-level concept
+ // (maybe it should) - instead it has a convenience method that generates the keydown and keyup events
+ // Here we will use "type" as our event type
+
+ lldebugs << "LLVIewerEventRecorder::logKeyEvent Serialized LLSD for event " << event.asString() << "\n" << llendl;
+
+
+ //lldebugs << "[VITA] key_name: " << LLKeyboard::stringFromKey(key) << "mask: "<< mask << "handled by " << getName() << llendl;
+ lldebugs << "LLVIewerEventRecorder::logKeyEvent key_name: " << LLKeyboard::stringFromKey(key) << "mask: "<< mask << llendl;
+
+
+ recordEvent(event);
+
+}
+
+void LLViewerEventRecorder::playbackRecording() {
+
+ LLSD LeapCommand;
+
+ // ivita sets this on startup, it also sends commands to the viewer to make start, stop, and playback menu items visible in viewer
+ LeapCommand =LLUI::sSettingGroups["config"]->getLLSD("LeapPlaybackEventsCommand");
+
+ lldebugs << "[VITA] launching playback - leap command is: " << LLSDXMLStreamer(LeapCommand) << llendl;
+ LLLeap::create("", LeapCommand, false); // exception=false
+
+}
+
+
+void LLViewerEventRecorder::recordEvent(LLSD event) {
+ lldebugs << "LLViewerEventRecorder::recordEvent event written to log: " << LLSDXMLStreamer(event) << llendl;
+ mLog << event << std::endl;
+
+}
+void LLViewerEventRecorder::logKeyUnicodeEvent(llwchar uni_char) {
+ if (! logEvents) return;
+
+ // Note: keyUp is not captured since the viewer seems to not care about keyUp events
+
+ LLSD event=LLSD::emptyMap();
+
+ event.insert("timestamp",LLSD(LLDate::now().asString()));
+
+
+ // keysym ...or
+ // keycode...or
+ // char
+
+ lldebugs << "Wrapped in conversion to wstring " << wstring_to_utf8str(LLWString( 1, uni_char)) << "\n" << llendl;
+
+ event.insert("char",
+ LLSD( wstring_to_utf8str(LLWString( 1,uni_char)) )
+ );
+
+ // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps
+ // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might
+ // break the test script and it would be useful to have more context to make these sorts of edits safer
+
+ // TODO need to consider mask keys too? Doesn't seem possible - at least not easily at this point
+
+ event.insert("event",LLSD("keyDown"));
+
+ lldebugs << "[VITA] unicode key: " << uni_char << llendl;
+ lldebugs << "[VITA] dumpxml " << LLSDXMLStreamer(event) << "\n" << llendl;
+
+
+ recordEvent(event);
+
+}
+
+void LLViewerEventRecorder::logMouseEvent(std::string button_state,std::string button_name)
+{
+ if (! logEvents) return;
+
+ LLSD event=LLSD::emptyMap();
+
+ event.insert("event",LLSD(std::string("mouse"+ button_state)));
+ event.insert("button",LLSD(button_name));
+ if (xui!="") {
+ event.insert("path",LLSD(xui));
+ }
+
+ if (local_x>0 && local_y>0) {
+ event.insert("local_x",LLSD(local_x));
+ event.insert("local_y",LLSD(local_y));
+ }
+
+ if (global_x>0 && global_y>0) {
+ event.insert("global_x",LLSD(global_x));
+ event.insert("global_y",LLSD(global_y));
+ }
+ event.insert("timestamp",LLSD(LLDate::now().asString()));
+ recordEvent(event);
+
+
+ clear(UNDEFINED);
+
+
+}
diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h
new file mode 100644
index 0000000000..72ca643ced
--- /dev/null
+++ b/indra/llui/llviewereventrecorder.h
@@ -0,0 +1,103 @@
+/**
+ * @file llviewereventrecorder.h
+ * @brief Viewer event recording and playback support for mouse and keyboard events
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ *
+ * Copyright (c) 2013, Linden Research, Inc.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VIEWER_EVENT_RECORDER
+#define LL_VIEWER_EVENT_RECORDER
+
+
+#include "linden_common.h"
+
+#include "lldir.h"
+#include "llsd.h"
+#include "llfile.h"
+#include "llvfile.h"
+#include "lldate.h"
+#include "llsdserialize.h"
+#include "llkeyboard.h"
+#include "llstring.h"
+
+#include <sstream>
+
+#include "llsingleton.h" // includes llerror which we need here so we can skip the include here
+
+class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder>
+{
+
+ public:
+
+ LLViewerEventRecorder(); // TODO Protect constructor better if we can (not happy in private section) - could add a factory... - we are singleton
+ ~LLViewerEventRecorder();
+
+
+ void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y, std::string mName);
+ void setMouseLocalCoords(S32 x,S32 y);
+ void setMouseGlobalCoords(S32 x,S32 y);
+
+ void logMouseEvent(std::string button_state, std::string button_name );
+ void logKeyEvent(KEY key, MASK mask);
+ void logKeyUnicodeEvent(llwchar uni_char);
+
+ void logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype);
+
+ void clear_xui();
+ std::string get_xui();
+ void update_xui(std::string xui);
+
+ bool getLoggingStatus();
+ void setEventLoggingOn();
+ void setEventLoggingOff();
+
+ void playbackRecording();
+
+ bool displayViewerEventRecorderMenuItems();
+
+
+ protected:
+ // On if we wish to log events at the moment - toggle via Develop/Recorder submenu
+ bool logEvents;
+
+ std::string mLogFilename;
+ llofstream mLog;
+
+
+ private:
+
+ // Mouse event info
+ S32 global_x;
+ S32 global_y;
+ S32 local_x;
+ S32 local_y;
+
+ // XUI path of UI element
+ std::string xui;
+
+ // Actually write the event out to llsd log file
+ void recordEvent(LLSD event);
+
+ void clear(S32 r);
+
+ static const S32 UNDEFINED=-1;
+};
+#endif
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index cc10ed5bbd..e02bf552aa 100755
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -32,7 +32,7 @@
#define MAX_PATH MAXPATHLEN
#endif
-// these numbers *may* get serialized (really??), so we need to be explicit
+// these numbers are read from settings_files.xml, so we need to be explicit
typedef enum ELLPath
{
LL_PATH_NONE = 0,
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 4c6e706119..aec6d7af4a 100755
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -109,11 +109,14 @@ if (DARWIN)
llkeyboardmacosx.cpp
llwindowmacosx.cpp
llwindowmacosx-objc.mm
+ llopenglview-objc.mm
)
list(APPEND llwindow_HEADER_FILES
llkeyboardmacosx.h
llwindowmacosx.h
llwindowmacosx-objc.h
+ llopenglview-objc.h
+ llappdelegate-objc.h
)
# We use a bunch of deprecated system APIs.
diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h
new file mode 100644
index 0000000000..faa5d3abb7
--- /dev/null
+++ b/indra/llwindow/llappdelegate-objc.h
@@ -0,0 +1,48 @@
+/**
+ * @file llappdelegate-objc.h
+ * @brief Class interface for the Mac version's application delegate.
+ *
+ * $LicenseInfo:firstyear=2000&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$
+ */
+
+#import <Cocoa/Cocoa.h>
+#import "llopenglview-objc.h"
+
+@interface LLAppDelegate : NSObject <NSApplicationDelegate> {
+ LLNSWindow *window;
+ NSWindow *inputWindow;
+ LLNonInlineTextView *inputView;
+ NSTimer *frameTimer;
+ NSString *currentInputLanguage;
+}
+
+@property (assign) IBOutlet LLNSWindow *window;
+@property (assign) IBOutlet NSWindow *inputWindow;
+@property (assign) IBOutlet LLNonInlineTextView *inputView;
+
+@property (retain) NSString *currentInputLanguage;
+
+- (void) mainLoop;
+- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
+- (void) languageUpdated;
+- (bool) romanScript;
+@end
diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h
index c155c1b362..92449c123f 100755
--- a/indra/llwindow/llkeyboard.h
+++ b/indra/llwindow/llkeyboard.h
@@ -82,6 +82,11 @@ public:
virtual BOOL handleKeyUp(const U16 key, MASK mask) = 0;
virtual BOOL handleKeyDown(const U16 key, MASK mask) = 0;
+
+#ifdef LL_DARWIN
+ // We only actually use this for OS X.
+ virtual void handleModifier(MASK mask) = 0;
+#endif // LL_DARWIN
// Asynchronously poll the control, alt, and shift keys and set the
// appropriate internal key masks.
diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp
index c87617c9ff..a1b6b294e0 100755
--- a/indra/llwindow/llkeyboardheadless.cpp
+++ b/indra/llwindow/llkeyboardheadless.cpp
@@ -45,6 +45,13 @@ BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask)
MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event)
{ return MASK_NONE; }
+#ifdef LL_DARWIN
+void LLKeyboardHeadless::handleModifier(MASK mask)
+{
+
+}
+#endif
+
void LLKeyboardHeadless::scanKeyboard()
{
for (S32 key = 0; key < KEY_COUNT; key++)
diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h
index 4e666f8ce8..8ed28ace90 100755
--- a/indra/llwindow/llkeyboardheadless.h
+++ b/indra/llwindow/llkeyboardheadless.h
@@ -40,6 +40,9 @@ public:
/*virtual*/ void resetMaskKeys();
/*virtual*/ MASK currentMask(BOOL for_mouse_event);
/*virtual*/ void scanKeyboard();
+#ifdef LL_DARWIN
+ /*virtual*/ void handleModifier(MASK mask);
+#endif
};
#endif
diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp
index 7f8f303517..85bb7b9aeb 100755
--- a/indra/llwindow/llkeyboardmacosx.cpp
+++ b/indra/llwindow/llkeyboardmacosx.cpp
@@ -30,7 +30,7 @@
#include "llkeyboardmacosx.h"
#include "llwindowcallbacks.h"
-#include <Carbon/Carbon.h>
+#include "llwindowmacosx-objc.h"
LLKeyboardMacOSX::LLKeyboardMacOSX()
{
@@ -162,23 +162,25 @@ LLKeyboardMacOSX::LLKeyboardMacOSX()
void LLKeyboardMacOSX::resetMaskKeys()
{
- U32 mask = GetCurrentEventKeyModifiers();
+ U32 mask = getModifiers();
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
// It looks a bit suspicious, as it won't correct for keys that have been released.
// Is this the way it's supposed to work?
+
+ // We apply the modifier masks directly within getModifiers. So check to see which masks we've applied.
- if(mask & shiftKey)
+ if(mask & MAC_SHIFT_KEY)
{
mKeyLevel[KEY_SHIFT] = TRUE;
}
- if(mask & (controlKey))
+ if(mask & MAC_CTRL_KEY)
{
mKeyLevel[KEY_CONTROL] = TRUE;
}
- if(mask & optionKey)
+ if(mask & MAC_ALT_KEY)
{
mKeyLevel[KEY_ALT] = TRUE;
}
@@ -196,22 +198,27 @@ static BOOL translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &out
}
*/
+void LLKeyboardMacOSX::handleModifier(MASK mask)
+{
+ updateModifiers(mask);
+}
+
MASK LLKeyboardMacOSX::updateModifiers(const U32 mask)
{
// translate the mask
MASK out_mask = 0;
- if(mask & shiftKey)
+ if(mask & MAC_SHIFT_KEY)
{
out_mask |= MASK_SHIFT;
}
- if(mask & (controlKey | cmdKey))
+ if(mask & (MAC_CTRL_KEY | MAC_CMD_KEY))
{
out_mask |= MASK_CONTROL;
}
- if(mask & optionKey)
+ if(mask & MAC_ALT_KEY)
{
out_mask |= MASK_ALT;
}
@@ -231,7 +238,7 @@ BOOL LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask)
{
handled = handleTranslatedKeyDown(translated_key, translated_mask);
}
-
+
return handled;
}
@@ -255,18 +262,18 @@ BOOL LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask)
MASK LLKeyboardMacOSX::currentMask(BOOL for_mouse_event)
{
MASK result = MASK_NONE;
- U32 mask = GetCurrentEventKeyModifiers();
+ U32 mask = getModifiers();
- if (mask & shiftKey) result |= MASK_SHIFT;
- if (mask & controlKey) result |= MASK_CONTROL;
- if (mask & optionKey) result |= MASK_ALT;
+ if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT;
+ if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL;
+ if (mask & MAC_ALT_KEY) result |= MASK_ALT;
// For keyboard events, consider Command equivalent to Control
if (!for_mouse_event)
{
- if (mask & cmdKey) result |= MASK_CONTROL;
+ if (mask & MAC_CMD_KEY) result |= MASK_CONTROL;
}
-
+
return result;
}
diff --git a/indra/llwindow/llkeyboardmacosx.h b/indra/llwindow/llkeyboardmacosx.h
index f09ff720ce..f9d014ab70 100755
--- a/indra/llwindow/llkeyboardmacosx.h
+++ b/indra/llwindow/llkeyboardmacosx.h
@@ -29,6 +29,15 @@
#include "llkeyboard.h"
+// These more or less mirror their equivalents in NSEvent.h.
+enum EMacEventKeys {
+ MAC_SHIFT_KEY = 1 << 17,
+ MAC_CTRL_KEY = 1 << 18,
+ MAC_ALT_KEY = 1 << 19,
+ MAC_CMD_KEY = 1 << 20,
+ MAC_FN_KEY = 1 << 23
+};
+
class LLKeyboardMacOSX : public LLKeyboard
{
public:
@@ -40,6 +49,7 @@ public:
/*virtual*/ void resetMaskKeys();
/*virtual*/ MASK currentMask(BOOL for_mouse_event);
/*virtual*/ void scanKeyboard();
+ /*virtual*/ void handleModifier(MASK mask);
protected:
MASK updateModifiers(const U32 mask);
diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h
new file mode 100644
index 0000000000..41837b1eb4
--- /dev/null
+++ b/indra/llwindow/llopenglview-objc.h
@@ -0,0 +1,110 @@
+/**
+ * @file llopenglview-objc.h
+ * @brief Class interfaces for most of the Mac facing window functionality.
+ *
+ * $LicenseInfo:firstyear=2000&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 LLOpenGLView_H
+#define LLOpenGLView_H
+
+#import <Cocoa/Cocoa.h>
+#import <IOKit/IOKitLib.h>
+#import <CoreFoundation/CFBase.h>
+#import <CoreFoundation/CFNumber.h>
+#include <string>
+
+@interface LLOpenGLView : NSOpenGLView <NSTextInputClient>
+{
+ std::string mLastDraggedUrl;
+ unsigned int mModifiers;
+ float mMousePos[2];
+ bool mHasMarkedText;
+ unsigned int mMarkedTextLength;
+ bool mMarkedTextAllowed;
+ bool mSimulatedRightClick;
+}
+- (id) initWithSamples:(NSUInteger)samples;
+- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync;
+- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync;
+
+- (void)commitCurrentPreedit;
+
+// rebuildContext
+// Destroys and recreates a context with the view's internal format set via setPixelFormat;
+// Use this in event of needing to rebuild a context for whatever reason, without needing to assign a new pixel format.
+- (BOOL) rebuildContext;
+
+// rebuildContextWithFormat
+// Destroys and recreates a context with the specified pixel format.
+- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format;
+
+// These are mostly just for C++ <-> Obj-C interop. We can manipulate the CGLContext from C++ without reprecussions.
+- (CGLContextObj) getCGLContextObj;
+- (CGLPixelFormatObj*)getCGLPixelFormatObj;
+
+- (unsigned long) getVramSize;
+
+- (void) allowMarkedTextInput:(bool)allowed;
+
+@end
+
+@interface LLUserInputWindow : NSPanel
+
+@end
+
+@interface LLNonInlineTextView : NSTextView
+{
+ LLOpenGLView *glview;
+}
+
+- (void) setGLView:(LLOpenGLView*)view;
+
+@end
+
+@interface LLNSWindow : NSWindow
+
+- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view;
+- (NSPoint)flipPoint:(NSPoint)aPoint;
+
+@end
+
+@interface NSScreen (PointConversion)
+
+/*
+ Returns the screen where the mouse resides
+ */
++ (NSScreen *)currentScreenForMouseLocation;
+
+/*
+ Allows you to convert a point from global coordinates to the current screen coordinates.
+ */
+- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint;
+
+/*
+ Allows to flip the point coordinates, so y is 0 at the top instead of the bottom. x remains the same
+ */
+- (NSPoint)flipPoint:(NSPoint)aPoint;
+
+@end
+
+#endif
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
new file mode 100644
index 0000000000..5f34d03c35
--- /dev/null
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -0,0 +1,686 @@
+/**
+ * @file llopenglview-objc.mm
+ * @brief Class implementation for most of the Mac facing window functionality.
+ *
+ * $LicenseInfo:firstyear=2000&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$
+ */
+
+#import "llopenglview-objc.h"
+#include "llwindowmacosx-objc.h"
+#import "llappdelegate-objc.h"
+
+@implementation NSScreen (PointConversion)
+
++ (NSScreen *)currentScreenForMouseLocation
+{
+ NSPoint mouseLocation = [NSEvent mouseLocation];
+
+ NSEnumerator *screenEnumerator = [[NSScreen screens] objectEnumerator];
+ NSScreen *screen;
+ while ((screen = [screenEnumerator nextObject]) && !NSMouseInRect(mouseLocation, screen.frame, NO))
+ ;
+
+ return screen;
+}
+
+- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint
+{
+ float normalizedX = fabs(fabs(self.frame.origin.x) - fabs(aPoint.x));
+ float normalizedY = aPoint.y - self.frame.origin.y;
+
+ return NSMakePoint(normalizedX, normalizedY);
+}
+
+- (NSPoint)flipPoint:(NSPoint)aPoint
+{
+ return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y);
+}
+
+@end
+
+attributedStringInfo getSegments(NSAttributedString *str)
+{
+ attributedStringInfo segments;
+ segment_lengths seg_lengths;
+ segment_standouts seg_standouts;
+ NSRange effectiveRange;
+ NSRange limitRange = NSMakeRange(0, [str length]);
+
+ while (limitRange.length > 0) {
+ NSNumber *attr = [str attribute:NSUnderlineStyleAttributeName atIndex:limitRange.location longestEffectiveRange:&effectiveRange inRange:limitRange];
+ limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
+
+ if (effectiveRange.length <= 0)
+ {
+ effectiveRange.length = 1;
+ }
+
+ if ([attr integerValue] == 2)
+ {
+ seg_lengths.push_back(effectiveRange.length);
+ seg_standouts.push_back(true);
+ } else
+ {
+ seg_lengths.push_back(effectiveRange.length);
+ seg_standouts.push_back(false);
+ }
+ }
+ segments.seg_lengths = seg_lengths;
+ segments.seg_standouts = seg_standouts;
+ return segments;
+}
+
+@implementation LLOpenGLView
+
+- (unsigned long)getVramSize
+{
+ CGLRendererInfoObj info = 0;
+ GLint vram_bytes = 0;
+ int num_renderers = 0;
+ CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);
+ if(0 == the_err)
+ {
+ CGLDescribeRenderer (info, 0, kCGLRPTextureMemory, &vram_bytes);
+ CGLDestroyRendererInfo (info);
+ }
+ else
+ {
+ vram_bytes = (256 << 20);
+ }
+
+ return (unsigned long)vram_bytes / 1048576; // We need this in megabytes.
+}
+
+- (void)viewDidMoveToWindow
+{
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(windowResized:) name:NSWindowDidResizeNotification
+ object:[self window]];
+}
+
+- (void)windowResized:(NSNotification *)notification;
+{
+ NSSize size = [self frame].size;
+
+ callResize(size.width, size.height);
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [super dealloc];
+}
+
+- (id) init
+{
+ return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE];
+}
+
+- (id) initWithSamples:(NSUInteger)samples
+{
+ return [self initWithFrame:[self bounds] withSamples:samples andVsync:TRUE];
+}
+
+- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync
+{
+ return [self initWithFrame:[self bounds] withSamples:samples andVsync:vsync];
+}
+
+- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync
+{
+ [self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]];
+ [self initWithFrame:frame];
+
+ // Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6.
+ // Any specialized pixel formats, i.e. a core profile pixel format, should be initialized through rebuildContextWithFormat.
+ // 10.7 and 10.8 don't really care if we're defining a profile or not. If we don't explicitly request a core or legacy profile, it'll always assume a legacy profile (for compatibility reasons).
+ NSOpenGLPixelFormatAttribute attrs[] = {
+ NSOpenGLPFANoRecovery,
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAClosestPolicy,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFASampleBuffers, (samples > 0 ? 1 : 0),
+ NSOpenGLPFASamples, samples,
+ NSOpenGLPFAStencilSize, 8,
+ NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAAlphaSize, 8,
+ NSOpenGLPFAColorSize, 24,
+ 0
+ };
+
+ NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease];
+
+ if (pixelFormat == nil)
+ {
+ NSLog(@"Failed to create pixel format!", nil);
+ return nil;
+ }
+
+ NSOpenGLContext *glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
+
+ if (glContext == nil)
+ {
+ NSLog(@"Failed to create OpenGL context!", nil);
+ return nil;
+ }
+
+ [self setPixelFormat:pixelFormat];
+
+ [self setOpenGLContext:glContext];
+
+ [glContext setView:self];
+
+ [glContext makeCurrentContext];
+
+ if (vsync)
+ {
+ [glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval];
+ } else {
+ [glContext setValues:(const GLint*)0 forParameter:NSOpenGLCPSwapInterval];
+ }
+
+ return self;
+}
+
+- (BOOL) rebuildContext
+{
+ return [self rebuildContextWithFormat:[self pixelFormat]];
+}
+
+- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format
+{
+ NSOpenGLContext *ctx = [self openGLContext];
+
+ [ctx clearDrawable];
+ [ctx initWithFormat:format shareContext:nil];
+
+ if (ctx == nil)
+ {
+ NSLog(@"Failed to create OpenGL context!", nil);
+ return false;
+ }
+
+ [self setOpenGLContext:ctx];
+ [ctx setView:self];
+ [ctx makeCurrentContext];
+ return true;
+}
+
+- (CGLContextObj)getCGLContextObj
+{
+ NSOpenGLContext *ctx = [self openGLContext];
+ return (CGLContextObj)[ctx CGLContextObj];
+}
+
+- (CGLPixelFormatObj*)getCGLPixelFormatObj
+{
+ NSOpenGLPixelFormat *fmt = [self pixelFormat];
+ return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj];
+}
+
+// Various events can be intercepted by our view, thus not reaching our window.
+// Intercept these events, and pass them to the window as needed. - Geenz
+
+- (void) mouseDown:(NSEvent *)theEvent
+{
+ // Apparently people still use this?
+ if ([theEvent modifierFlags] & NSCommandKeyMask &&
+ !([theEvent modifierFlags] & NSControlKeyMask) &&
+ !([theEvent modifierFlags] & NSShiftKeyMask) &&
+ !([theEvent modifierFlags] & NSAlternateKeyMask) &&
+ !([theEvent modifierFlags] & NSAlphaShiftKeyMask) &&
+ !([theEvent modifierFlags] & NSFunctionKeyMask) &&
+ !([theEvent modifierFlags] & NSHelpKeyMask))
+ {
+ callRightMouseDown(mMousePos, mModifiers);
+ mSimulatedRightClick = true;
+ } else {
+ if ([theEvent clickCount] >= 2)
+ {
+ callDoubleClick(mMousePos, mModifiers);
+ } else if ([theEvent clickCount] == 1) {
+ callLeftMouseDown(mMousePos, mModifiers);
+ }
+ }
+}
+
+- (void) mouseUp:(NSEvent *)theEvent
+{
+ if (mSimulatedRightClick)
+ {
+ callRightMouseUp(mMousePos, mModifiers);
+ mSimulatedRightClick = false;
+ } else {
+ callLeftMouseUp(mMousePos, mModifiers);
+ }
+}
+
+- (void) rightMouseDown:(NSEvent *)theEvent
+{
+ callRightMouseDown(mMousePos, mModifiers);
+}
+
+- (void) rightMouseUp:(NSEvent *)theEvent
+{
+ callRightMouseUp(mMousePos, mModifiers);
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+ float mouseDeltas[2] = {
+ [theEvent deltaX],
+ [theEvent deltaY]
+ };
+
+ callDeltaUpdate(mouseDeltas, 0);
+
+ NSPoint mPoint = [theEvent locationInWindow];
+ mMousePos[0] = mPoint.x;
+ mMousePos[1] = mPoint.y;
+ callMouseMoved(mMousePos, 0);
+}
+
+// NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged.
+// Use mouseDragged for situations like this to trigger our movement callback instead.
+
+- (void) mouseDragged:(NSEvent *)theEvent
+{
+ // Trust the deltas supplied by NSEvent.
+ // The old CoreGraphics APIs we previously relied on are now flagged as obsolete.
+ // NSEvent isn't obsolete, and provides us with the correct deltas.
+ float mouseDeltas[2] = {
+ [theEvent deltaX],
+ [theEvent deltaY]
+ };
+
+ callDeltaUpdate(mouseDeltas, 0);
+
+ NSPoint mPoint = [theEvent locationInWindow];
+ mMousePos[0] = mPoint.x;
+ mMousePos[1] = mPoint.y;
+ callMouseMoved(mMousePos, 0);
+}
+
+- (void) otherMouseDown:(NSEvent *)theEvent
+{
+ callMiddleMouseDown(mMousePos, mModifiers);
+}
+
+- (void) otherMouseUp:(NSEvent *)theEvent
+{
+ callMiddleMouseUp(mMousePos, mModifiers);
+}
+
+- (void) otherMouseDragged:(NSEvent *)theEvent
+{
+
+}
+
+- (void) scrollWheel:(NSEvent *)theEvent
+{
+ callScrollMoved(-[theEvent deltaY]);
+}
+
+- (void) mouseExited:(NSEvent *)theEvent
+{
+ callMouseExit();
+}
+
+- (void) keyUp:(NSEvent *)theEvent
+{
+ callKeyUp([theEvent keyCode], mModifiers);
+}
+
+- (void) keyDown:(NSEvent *)theEvent
+{
+ uint keycode = [theEvent keyCode];
+ bool acceptsText = mHasMarkedText ? false : callKeyDown(keycode, mModifiers);
+ if (acceptsText &&
+ !mMarkedTextAllowed &&
+ ![(LLAppDelegate*)[NSApp delegate] romanScript] &&
+ [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter &&
+ [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter &&
+ [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDownArrowFunctionKey &&
+ [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSUpArrowFunctionKey &&
+ [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSLeftArrowFunctionKey &&
+ [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSRightArrowFunctionKey)
+ {
+ [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent];
+ } else
+ {
+ [[self inputContext] handleEvent:theEvent];
+ }
+
+ if ([[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSCarriageReturnCharacter ||
+ [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSEnterCharacter)
+ {
+ // callKeyDown won't return the value we expect for enter or return. Handle them as a separate case.
+ [[self inputContext] handleEvent:theEvent];
+ }
+
+ // OS X intentionally does not send us key-up information on cmd-key combinations.
+ // This behaviour is not a bug, and only applies to cmd-combinations (no others).
+ // Since SL assumes we receive those, we fake it here.
+ if (mModifiers & NSCommandKeyMask && !mHasMarkedText)
+ {
+ callKeyUp([theEvent keyCode], mModifiers);
+ }
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent {
+ mModifiers = [theEvent modifierFlags];
+ callModifier([theEvent modifierFlags]);
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender
+{
+ NSPasteboard *pboard;
+ NSDragOperation sourceDragMask;
+
+ sourceDragMask = [sender draggingSourceOperationMask];
+
+ pboard = [sender draggingPasteboard];
+
+ if ([[pboard types] containsObject:NSURLPboardType])
+ {
+ if (sourceDragMask & NSDragOperationLink) {
+ NSURL *fileUrl = [[pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:[NSDictionary dictionary]] objectAtIndex:0];
+ mLastDraggedUrl = [[fileUrl absoluteString] UTF8String];
+ return NSDragOperationLink;
+ }
+ }
+ return NSDragOperationNone;
+}
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
+{
+ callHandleDragUpdated(mLastDraggedUrl);
+
+ return NSDragOperationLink;
+}
+
+- (void) draggingExited:(id<NSDraggingInfo>)sender
+{
+ callHandleDragExited(mLastDraggedUrl);
+}
+
+- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
+{
+ return YES;
+}
+
+- (BOOL) performDragOperation:(id<NSDraggingInfo>)sender
+{
+ callHandleDragDropped(mLastDraggedUrl);
+ return true;
+}
+
+- (BOOL)hasMarkedText
+{
+ return mHasMarkedText;
+}
+
+- (NSRange)markedRange
+{
+ int range[2];
+ getPreeditMarkedRange(&range[0], &range[1]);
+ return NSMakeRange(range[0], range[1]);
+}
+
+- (NSRange)selectedRange
+{
+ int range[2];
+ getPreeditSelectionRange(&range[0], &range[1]);
+ return NSMakeRange(range[0], range[1]);
+}
+
+- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
+{
+ if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString"))
+ {
+ if (mMarkedTextAllowed)
+ {
+ unsigned int selected[2] = {
+ selectedRange.location,
+ selectedRange.length
+ };
+
+ unsigned int replacement[2] = {
+ replacementRange.location,
+ replacementRange.length
+ };
+
+ unichar text[[aString length]];
+ [[aString mutableString] getCharacters:text range:NSMakeRange(0, [aString length])];
+ attributedStringInfo segments = getSegments((NSAttributedString *)aString);
+ setMarkedText(text, selected, replacement, [aString length], segments);
+ mHasMarkedText = TRUE;
+ mMarkedTextLength = [aString length];
+ } else {
+ if (mHasMarkedText)
+ {
+ [self unmarkText];
+ }
+ }
+ }
+}
+
+- (void)commitCurrentPreedit
+{
+ if (mHasMarkedText)
+ {
+ if ([[self inputContext] respondsToSelector:@selector(commitEditing)])
+ {
+ [[self inputContext] commitEditing];
+ }
+ }
+}
+
+- (void)unmarkText
+{
+ [[self inputContext] discardMarkedText];
+ resetPreedit();
+ mHasMarkedText = FALSE;
+}
+
+// We don't support attributed strings.
+- (NSArray *)validAttributesForMarkedText
+{
+ return [NSArray array];
+}
+
+// See above.
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
+{
+ return nil;
+}
+
+- (void)insertText:(id)insertString
+{
+ if (insertString != nil)
+ {
+ [self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])];
+ }
+}
+
+- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
+{
+ if (!mHasMarkedText)
+ {
+ for (NSInteger i = 0; i < [aString length]; i++)
+ {
+ callUnicodeCallback([aString characterAtIndex:i], mModifiers);
+ }
+ } else {
+ resetPreedit();
+ // We may never get this point since unmarkText may be called before insertText ever gets called once we submit our text.
+ // But just in case...
+
+ for (NSInteger i = 0; i < [aString length]; i++)
+ {
+ handleUnicodeCharacter([aString characterAtIndex:i]);
+ }
+ mHasMarkedText = FALSE;
+ }
+}
+
+- (void) insertNewline:(id)sender
+{
+ if (!(mModifiers & NSCommandKeyMask) &&
+ !(mModifiers & NSShiftKeyMask) &&
+ !(mModifiers & NSAlternateKeyMask))
+ {
+ callUnicodeCallback(13, 0);
+ } else {
+ callUnicodeCallback(13, mModifiers);
+ }
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
+{
+ return NSNotFound;
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
+{
+ float pos[4] = {0, 0, 0, 0};
+ getPreeditLocation(pos, mMarkedTextLength);
+ return NSMakeRect(pos[0], pos[1], pos[2], pos[3]);
+}
+
+- (void)doCommandBySelector:(SEL)aSelector
+{
+ if (aSelector == @selector(insertNewline:))
+ {
+ [self insertNewline:self];
+ }
+}
+
+- (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex
+{
+ return NO;
+}
+
+- (void) allowMarkedTextInput:(bool)allowed
+{
+ mMarkedTextAllowed = allowed;
+}
+
+@end
+
+@implementation LLUserInputWindow
+
+- (void) close
+{
+ [self orderOut:self];
+}
+
+@end
+
+@implementation LLNonInlineTextView
+
+- (void) setGLView:(LLOpenGLView *)view
+{
+ glview = view;
+}
+
+- (void) insertText:(id)insertString
+{
+ [[self inputContext] discardMarkedText];
+ [self setString:@""];
+ [_window orderOut:_window];
+ [self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])];
+}
+
+- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
+{
+ [glview insertText:aString replacementRange:replacementRange];
+}
+
+- (void) insertNewline:(id)sender
+{
+ [[self textStorage] setValue:@""];
+ [[self inputContext] discardMarkedText];
+ [self setString:@""];
+}
+
+- (void)doCommandBySelector:(SEL)aSelector
+{
+ if (aSelector == @selector(insertNewline:))
+ {
+ [self insertNewline:self];
+ }
+}
+
+@end
+
+@implementation LLNSWindow
+
+- (id) init
+{
+ return self;
+}
+
+- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view
+{
+ NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation];
+ if(currentScreen)
+ {
+ NSPoint windowPoint = [view convertPoint:point toView:nil];
+ NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
+ NSPoint flippedScreenPoint = [currentScreen flipPoint:screenPoint];
+ flippedScreenPoint.y += [currentScreen frame].origin.y;
+
+ return flippedScreenPoint;
+ }
+
+ return NSZeroPoint;
+}
+
+- (NSPoint)flipPoint:(NSPoint)aPoint
+{
+ return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y);
+}
+
+- (BOOL) becomeFirstResponder
+{
+ callFocus();
+ return true;
+}
+
+- (BOOL) resignFirstResponder
+{
+ callFocusLost();
+ return true;
+}
+
+- (void) close
+{
+ callQuitHandler();
+}
+
+@end
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index 7893dedda4..32b3bfb078 100755
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -25,13 +25,121 @@
* $/LicenseInfo$
*/
+#include <map>
+#include <vector>
+
+typedef std::vector<std::pair<int, bool> > segment_t;
+
+typedef std::vector<int> segment_lengths;
+typedef std::vector<int> segment_standouts;
+
+struct attributedStringInfo {
+ segment_lengths seg_lengths;
+ segment_standouts seg_standouts;
+};
// This will actually hold an NSCursor*, but that type is only available in objective C.
typedef void *CursorRef;
+typedef void *NSWindowRef;
+typedef void *GLViewRef;
+
+// These are defined in llappviewermacosx.cpp.
+bool initViewer();
+void handleQuit();
+bool runMainLoop();
+void initMainLoop();
+void cleanupViewer();
/* Defined in llwindowmacosx-objc.mm: */
+int createNSApp(int argc, const char **argv);
void setupCocoa();
+bool pasteBoardAvailable();
+bool copyToPBoard(const unsigned short *str, unsigned int len);
+const unsigned short *copyFromPBoard();
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY);
-OSErr releaseImageCursor(CursorRef ref);
-OSErr setImageCursor(CursorRef ref);
+short releaseImageCursor(CursorRef ref);
+short setImageCursor(CursorRef ref);
+void setArrowCursor();
+void setIBeamCursor();
+void setPointingHandCursor();
+void setCopyCursor();
+void setCrossCursor();
+void setNotAllowedCursor();
+void hideNSCursor();
+void showNSCursor();
+void hideNSCursorTillMove(bool hide);
+void requestUserAttention();
+long showAlert(std::string title, std::string text, int type);
+
+NSWindowRef createNSWindow(int x, int y, int width, int height);
+
+#include <OpenGL/OpenGL.h>
+GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync);
+void glSwapBuffers(void* context);
+CGLContextObj getCGLContextObj(GLViewRef view);
+unsigned long getVramSize(GLViewRef view);
+void getContentViewBounds(NSWindowRef window, float* bounds);
+void getWindowSize(NSWindowRef window, float* size);
+void setWindowSize(NSWindowRef window, int width, int height);
+void getCursorPos(NSWindowRef window, float* pos);
+void makeWindowOrderFront(NSWindowRef window);
+void convertScreenToWindow(NSWindowRef window, float *coord);
+void convertWindowToScreen(NSWindowRef window, float *coord);
+void convertScreenToView(NSWindowRef window, float *coord);
+void convertRectToScreen(NSWindowRef window, float *coord);
+void convertRectFromScreen(NSWindowRef window, float *coord);
+void setWindowPos(NSWindowRef window, float* pos);
+void closeWindow(NSWindowRef window);
+void removeGLView(GLViewRef view);
+void makeFirstResponder(NSWindowRef window, GLViewRef view);
+void setupInputWindow(NSWindowRef window, GLViewRef view);
+
+// These are all implemented in llwindowmacosx.cpp.
+// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict)
+bool callKeyUp(unsigned short key, unsigned int mask);
+bool callKeyDown(unsigned short key, unsigned int mask);
+void callResetKeys();
+bool callUnicodeCallback(wchar_t character, unsigned int mask);
+void callRightMouseDown(float *pos, unsigned int mask);
+void callRightMouseUp(float *pos, unsigned int mask);
+void callLeftMouseDown(float *pos, unsigned int mask);
+void callLeftMouseUp(float *pos, unsigned int mask);
+void callDoubleClick(float *pos, unsigned int mask);
+void callResize(unsigned int width, unsigned int height);
+void callMouseMoved(float *pos, unsigned int mask);
+void callScrollMoved(float delta);
+void callMouseExit();
+void callWindowFocus();
+void callWindowUnfocus();
+void callDeltaUpdate(float *delta, unsigned int mask);
+void callMiddleMouseDown(float *pos, unsigned int mask);
+void callMiddleMouseUp(float *pos, unsigned int mask);
+void callFocus();
+void callFocusLost();
+void callModifier(unsigned int mask);
+void callQuitHandler();
+void commitCurrentPreedit(GLViewRef glView);
+
+#include <string>
+void callHandleDragEntered(std::string url);
+void callHandleDragExited(std::string url);
+void callHandleDragUpdated(std::string url);
+void callHandleDragDropped(std::string url);
+
+// LLPreeditor C bindings.
+std::basic_string<wchar_t> getPreeditString();
+void getPreeditSelectionRange(int *position, int *length);
+void getPreeditMarkedRange(int *position, int *length);
+bool handleUnicodeCharacter(wchar_t c);
+void updatePreeditor(unsigned short *str);
+void setPreeditMarkedRange(int position, int length);
+void resetPreedit();
+int wstring_length(const std::basic_string<wchar_t> & wstr, const int woffset, const int utf16_length, int *unaligned);
+void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments);
+void getPreeditLocation(float *location, unsigned int length);
+void allowDirectMarkedTextInput(bool allow, GLViewRef glView);
+
+NSWindowRef getMainAppWindow();
+GLViewRef getGLView();
+unsigned int getModifiers();
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index bebb537cd8..0354c2b717 100755
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -1,4 +1,4 @@
-/**
+/**
* @file llwindowmacosx-objc.mm
* @brief Definition of functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
@@ -6,26 +6,30 @@
* $LicenseInfo:firstyear=2006&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 <AppKit/AppKit.h>
+#include <Cocoa/Cocoa.h>
+#include "llopenglview-objc.h"
+#include "llwindowmacosx-objc.h"
+#include "llappdelegate-objc.h"
/*
* These functions are broken out into a separate file because the
@@ -34,7 +38,10 @@
* linden headers with any objective-C++ source.
*/
-#include "llwindowmacosx-objc.h"
+int createNSApp(int argc, const char *argv[])
+{
+ return NSApplicationMain(argc, argv);
+}
void setupCocoa()
{
@@ -45,44 +52,122 @@ void setupCocoa()
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
- // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
- // when init'ing the Cocoa App window.
+ // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
+ // when init'ing the Cocoa App window.
[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
- // This is a bit of voodoo taken from the Apple sample code "CarbonCocoa_PictureCursor":
- // http://developer.apple.com/samplecode/CarbonCocoa_PictureCursor/index.html
-
- // Needed for Carbon based applications which call into Cocoa
- NSApplicationLoad();
-
- // Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image
- [[[NSWindow alloc] init] release];
-
[pool release];
inited = true;
}
}
+bool copyToPBoard(const unsigned short *str, unsigned int len)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
+ NSPasteboard *pboard = [NSPasteboard generalPasteboard];
+ [pboard clearContents];
+
+ NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil];
+ [pool release];
+ return [pboard writeObjects:contentsToPaste];
+}
+
+bool pasteBoardAvailable()
+{
+ NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
+ return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
+}
+
+const unsigned short *copyFromPBoard()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
+ NSPasteboard *pboard = [NSPasteboard generalPasteboard];
+ NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
+ NSString *str = NULL;
+ BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
+ if (ok)
+ {
+ NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
+ str = [objToPaste objectAtIndex:0];
+ }
+ unichar* temp = (unichar*)calloc([str length], sizeof(unichar));
+ [str getCharacters:temp];
+ [pool release];
+ return temp;
+}
+
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
+
// extra retain on the NSCursor since we want it to live for the lifetime of the app.
NSCursor *cursor =
- [[[NSCursor alloc]
- initWithImage:
- [[[NSImage alloc] initWithContentsOfFile:
- [NSString stringWithFormat:@"%s", fullpath]
- ]autorelease]
- hotSpot:NSMakePoint(hotspotX, hotspotY)
- ]retain];
-
+ [[[NSCursor alloc]
+ initWithImage:
+ [[[NSImage alloc] initWithContentsOfFile:
+ [NSString stringWithFormat:@"%s", fullpath]
+ ]autorelease]
+ hotSpot:NSMakePoint(hotspotX, hotspotY)
+ ]retain];
+
[pool release];
return (CursorRef)cursor;
}
+void setArrowCursor()
+{
+ NSCursor *cursor = [NSCursor arrowCursor];
+ [NSCursor unhide];
+ [cursor set];
+}
+
+void setIBeamCursor()
+{
+ NSCursor *cursor = [NSCursor IBeamCursor];
+ [cursor set];
+}
+
+void setPointingHandCursor()
+{
+ NSCursor *cursor = [NSCursor pointingHandCursor];
+ [cursor set];
+}
+
+void setCopyCursor()
+{
+ NSCursor *cursor = [NSCursor dragCopyCursor];
+ [cursor set];
+}
+
+void setCrossCursor()
+{
+ NSCursor *cursor = [NSCursor crosshairCursor];
+ [cursor set];
+}
+
+void setNotAllowedCursor()
+{
+ NSCursor *cursor = [NSCursor operationNotAllowedCursor];
+ [cursor set];
+}
+
+void hideNSCursor()
+{
+ [NSCursor hide];
+}
+
+void showNSCursor()
+{
+ [NSCursor unhide];
+}
+
+void hideNSCursorTillMove(bool hide)
+{
+ [NSCursor setHiddenUntilMouseMoves:hide];
+}
+
// This is currently unused, since we want all our cursors to persist for the life of the app, but I've included it for completeness.
OSErr releaseImageCursor(CursorRef ref)
{
@@ -118,3 +203,250 @@ OSErr setImageCursor(CursorRef ref)
return noErr;
}
+// Now for some unholy juggling between generic pointers and casting them to Obj-C objects!
+// Note: things can get a bit hairy from here. This is not for the faint of heart.
+
+NSWindowRef createNSWindow(int x, int y, int width, int height)
+{
+ LLNSWindow *window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height)
+ styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO];
+ [window makeKeyAndOrderFront:nil];
+ [window setAcceptsMouseMovedEvents:TRUE];
+ return window;
+}
+
+GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync)
+{
+ LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:samples andVsync:vsync];
+ [(LLNSWindow*)window setContentView:glview];
+ return glview;
+}
+
+void glSwapBuffers(void* context)
+{
+ [(NSOpenGLContext*)context flushBuffer];
+}
+
+CGLContextObj getCGLContextObj(GLViewRef view)
+{
+ return [(LLOpenGLView *)view getCGLContextObj];
+}
+
+CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window)
+{
+ LLOpenGLView *glview = [(LLNSWindow*)window contentView];
+ return [glview getCGLPixelFormatObj];
+}
+
+unsigned long getVramSize(GLViewRef view)
+{
+ return [(LLOpenGLView *)view getVramSize];
+}
+
+void getContentViewBounds(NSWindowRef window, float* bounds)
+{
+ bounds[0] = [[(LLNSWindow*)window contentView] bounds].origin.x;
+ bounds[1] = [[(LLNSWindow*)window contentView] bounds].origin.y;
+ bounds[2] = [[(LLNSWindow*)window contentView] bounds].size.width;
+ bounds[3] = [[(LLNSWindow*)window contentView] bounds].size.height;
+}
+
+void getWindowSize(NSWindowRef window, float* size)
+{
+ NSRect frame = [(LLNSWindow*)window frame];
+ size[0] = frame.origin.x;
+ size[1] = frame.origin.y;
+ size[2] = frame.size.width;
+ size[3] = frame.size.height;
+}
+
+void setWindowSize(NSWindowRef window, int width, int height)
+{
+ NSRect frame = [(LLNSWindow*)window frame];
+ frame.size.width = width;
+ frame.size.height = height;
+ [(LLNSWindow*)window setFrame:frame display:TRUE];
+}
+
+void setWindowPos(NSWindowRef window, float* pos)
+{
+ NSPoint point;
+ point.x = pos[0];
+ point.y = pos[1];
+ [(LLNSWindow*)window setFrameOrigin:point];
+}
+
+void getCursorPos(NSWindowRef window, float* pos)
+{
+ NSPoint mLoc;
+ mLoc = [(LLNSWindow*)window mouseLocationOutsideOfEventStream];
+ pos[0] = mLoc.x;
+ pos[1] = mLoc.y;
+}
+
+void makeWindowOrderFront(NSWindowRef window)
+{
+ [(LLNSWindow*)window makeKeyAndOrderFront:nil];
+}
+
+void convertScreenToWindow(NSWindowRef window, float *coord)
+{
+ NSRect point;
+ point.origin.x = coord[0];
+ point.origin.y = coord[1];
+ point = [(LLNSWindow*)window convertRectFromScreen:point];
+ coord[0] = point.origin.x;
+ coord[1] = point.origin.y;
+}
+
+void convertRectToScreen(NSWindowRef window, float *coord)
+{
+ NSRect point;
+ point.origin.x = coord[0];
+ point.origin.y = coord[1];
+ point.size.width = coord[2];
+ point.size.height = coord[3];
+
+ point = [(LLNSWindow*)window convertRectToScreen:point];
+
+ coord[0] = point.origin.x;
+ coord[1] = point.origin.y;
+ coord[2] = point.size.width;
+ coord[3] = point.size.height;
+}
+
+void convertRectFromScreen(NSWindowRef window, float *coord)
+{
+ NSRect point;
+ point.origin.x = coord[0];
+ point.origin.y = coord[1];
+ point.size.width = coord[2];
+ point.size.height = coord[3];
+
+ point = [(LLNSWindow*)window convertRectFromScreen:point];
+
+ coord[0] = point.origin.x;
+ coord[1] = point.origin.y;
+ coord[2] = point.size.width;
+ coord[3] = point.size.height;
+}
+
+void convertScreenToView(NSWindowRef window, float *coord)
+{
+ NSRect point;
+ point.origin.x = coord[0];
+ point.origin.y = coord[1];
+ point.origin = [(LLNSWindow*)window convertScreenToBase:point.origin];
+ point.origin = [[(LLNSWindow*)window contentView] convertPoint:point.origin fromView:nil];
+}
+
+void convertWindowToScreen(NSWindowRef window, float *coord)
+{
+ NSPoint point;
+ point.x = coord[0];
+ point.y = coord[1];
+ point = [(LLNSWindow*)window convertToScreenFromLocalPoint:point relativeToView:[(LLNSWindow*)window contentView]];
+ coord[0] = point.x;
+ coord[1] = point.y;
+}
+
+void closeWindow(NSWindowRef window)
+{
+ [(LLNSWindow*)window close];
+ [(LLNSWindow*)window release];
+}
+
+void removeGLView(GLViewRef view)
+{
+ [(LLOpenGLView*)view removeFromSuperview];
+ [(LLOpenGLView*)view release];
+}
+
+void setupInputWindow(NSWindowRef window, GLViewRef glview)
+{
+ [[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview];
+}
+
+void commitCurrentPreedit(GLViewRef glView)
+{
+ [(LLOpenGLView*)glView commitCurrentPreedit];
+}
+
+void allowDirectMarkedTextInput(bool allow, GLViewRef glView)
+{
+ [(LLOpenGLView*)glView allowMarkedTextInput:allow];
+}
+
+NSWindowRef getMainAppWindow()
+{
+ LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window];
+
+ [winRef setAcceptsMouseMovedEvents:TRUE];
+ return winRef;
+}
+
+void makeFirstResponder(NSWindowRef window, GLViewRef view)
+{
+ [(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view];
+}
+
+void requestUserAttention()
+{
+ [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
+}
+
+long showAlert(std::string text, std::string title, int type)
+{
+ NSAlert *alert = [[NSAlert alloc] init];
+
+ [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
+ [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
+ if (type == 0)
+ {
+ [alert addButtonWithTitle:@"Okay"];
+ } else if (type == 1)
+ {
+ [alert addButtonWithTitle:@"Okay"];
+ [alert addButtonWithTitle:@"Cancel"];
+ } else if (type == 2)
+ {
+ [alert addButtonWithTitle:@"Yes"];
+ [alert addButtonWithTitle:@"No"];
+ }
+ long ret = [alert runModal];
+ [alert dealloc];
+
+ if (ret == NSAlertFirstButtonReturn)
+ {
+ if (type == 1)
+ {
+ ret = 3;
+ } else if (type == 2)
+ {
+ ret = 0;
+ }
+ } else if (ret == NSAlertSecondButtonReturn)
+ {
+ if (type == 0 || type == 1)
+ {
+ ret = 2;
+ } else if (type == 2)
+ {
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ GLViewRef getGLView()
+ {
+ return [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] glview];
+ }
+ */
+
+unsigned int getModifiers()
+{
+ return [NSEvent modifierFlags];
+}
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 97637c937f..d5b62bd3a7 100755
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -30,7 +30,6 @@
#include "llkeyboardmacosx.h"
#include "llwindowcallbacks.h"
-#include "llwindowmacosx-objc.h"
#include "llpreeditor.h"
#include "llerror.h"
@@ -39,8 +38,8 @@
#include "lldir.h"
#include "indra_constants.h"
-#include <Carbon/Carbon.h>
#include <OpenGL/OpenGL.h>
+#include <CoreServices/CoreServices.h>
extern BOOL gDebugWindowProc;
@@ -58,7 +57,6 @@ const S32 MAX_NUM_RESOLUTIONS = 32;
//
BOOL LLWindowMacOSX::sUseMultGL = FALSE;
-WindowRef LLWindowMacOSX::sMediaWindow = NULL;
// Cross-platform bits:
@@ -98,105 +96,9 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card)
// We may want to base this on the setting of _DEBUG...
#define CAPTURE_ALL_DISPLAYS 0
-static double getDictDouble (CFDictionaryRef refDict, CFStringRef key);
+//static double getDictDouble (CFDictionaryRef refDict, CFStringRef key);
static long getDictLong (CFDictionaryRef refDict, CFStringRef key);
-
-
-
-// CarbonEvents we're interested in.
-static EventTypeSpec WindowHandlerEventList[] =
-{
- // Window-related events
- { kEventClassWindow, kEventWindowActivated },
- { kEventClassWindow, kEventWindowDeactivated },
- { kEventClassWindow, kEventWindowShown },
- { kEventClassWindow, kEventWindowHidden },
- { kEventClassWindow, kEventWindowCollapsed },
- { kEventClassWindow, kEventWindowExpanded },
- { kEventClassWindow, kEventWindowGetClickActivation },
- { kEventClassWindow, kEventWindowClose },
- { kEventClassWindow, kEventWindowBoundsChanging },
- { kEventClassWindow, kEventWindowBoundsChanged },
- { kEventClassWindow, kEventWindowGetIdealSize },
-
- // Mouse events
- { kEventClassMouse, kEventMouseDown },
- { kEventClassMouse, kEventMouseUp },
- { kEventClassMouse, kEventMouseDragged },
- { kEventClassMouse, kEventMouseWheelMoved },
- { kEventClassMouse, kEventMouseMoved },
-
- // Keyboard events
- // No longer handle raw key down events directly.
- // When text input events come in, extract the raw key events from them and process at that point.
- // This allows input methods to eat keystrokes the way they're supposed to.
-// { kEventClassKeyboard, kEventRawKeyDown },
-// { kEventClassKeyboard, kEventRawKeyRepeat },
- { kEventClassKeyboard, kEventRawKeyUp },
- { kEventClassKeyboard, kEventRawKeyModifiersChanged },
-
- // Text input events
- { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
- { kEventClassTextInput, kEventTextInputUpdateActiveInputArea },
- { kEventClassTextInput, kEventTextInputOffsetToPos },
- { kEventClassTextInput, kEventTextInputPosToOffset },
- { kEventClassTextInput, kEventTextInputShowHideBottomWindow },
- { kEventClassTextInput, kEventTextInputGetSelectedText },
- { kEventClassTextInput, kEventTextInputFilterText },
-
- // TSM Document Access events (advanced input method support)
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument }
-};
-
-static EventTypeSpec GlobalHandlerEventList[] =
-{
- // Mouse events
- { kEventClassMouse, kEventMouseDown },
- { kEventClassMouse, kEventMouseUp },
- { kEventClassMouse, kEventMouseDragged },
- { kEventClassMouse, kEventMouseWheelMoved },
- { kEventClassMouse, kEventMouseMoved },
-
- // Keyboard events
- // No longer handle raw key down events directly.
- // When text input events come in, extract the raw key events from them and process at that point.
- // This allows input methods to eat keystrokes the way they're supposed to.
-// { kEventClassKeyboard, kEventRawKeyDown },
-// { kEventClassKeyboard, kEventRawKeyRepeat },
- { kEventClassKeyboard, kEventRawKeyUp },
- { kEventClassKeyboard, kEventRawKeyModifiersChanged },
-
- // Text input events
- { kEventClassTextInput, kEventTextInputUpdateActiveInputArea },
- { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
- { kEventClassTextInput, kEventTextInputOffsetToPos },
- { kEventClassTextInput, kEventTextInputPosToOffset },
- { kEventClassTextInput, kEventTextInputShowHideBottomWindow },
- { kEventClassTextInput, kEventTextInputGetSelectedText },
- { kEventClassTextInput, kEventTextInputFilterText },
-
- // TSM Document Access events (advanced input method support)
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument },
- { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument }
-};
-
-static EventTypeSpec CommandHandlerEventList[] =
-{
- { kEventClassCommand, kEventCommandProcess }
-};
-
// MBW -- HACK ALERT
// On the Mac, to put up an OS dialog in full screen mode, we must first switch OUT of full screen mode.
// The proper way to do this is to bracket the dialog with calls to beforeDialog() and afterDialog(), but these
@@ -204,8 +106,6 @@ static EventTypeSpec CommandHandlerEventList[] =
// This assumes that there will be only one object of this class at any time. Hopefully this is true.
static LLWindowMacOSX *gWindowImplementation = NULL;
-
-
LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
@@ -233,8 +133,6 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
mContext = NULL;
mPixelFormat = NULL;
mDisplay = CGMainDisplayID();
- mOldDisplayMode = NULL;
- mTimer = NULL;
mSimulatedRightClick = FALSE;
mLastModifiers = 0;
mHandsOffEvents = FALSE;
@@ -246,60 +144,31 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
mOverrideAspectRatio = 0.f;
mMaximized = FALSE;
mMinimized = FALSE;
- mTSMDocument = NULL; // Just in case.
mLanguageTextInputAllowed = FALSE;
- mTSMScriptCode = 0;
- mTSMLangCode = 0;
mPreeditor = NULL;
- mRawKeyEvent = NULL;
mFSAASamples = fsaa_samples;
mForceRebuild = FALSE;
- // For reasons that aren't clear to me, LLTimers seem to be created in the "started" state.
- // Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state.
- mBounceTimer.stop();
-
// Get the original aspect ratio of the main device.
mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
// Stash the window title
- strcpy((char*)mWindowTitle + 1, title.c_str()); /* Flawfinder: ignore */
- mWindowTitle[0] = title.length();
-
- mEventHandlerUPP = NewEventHandlerUPP(staticEventHandler);
- mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator);
- mGlobalHandlerRef = NULL;
- mWindowHandlerRef = NULL;
+ mWindowTitle = title;
+ //mWindowTitle[0] = title.length();
mDragOverrideCursor = -1;
- // We're not clipping yet
- SetRect( &mOldMouseClip, 0, 0, 0, 0 );
-
// Set up global event handlers (the fullscreen case needs this)
- InstallStandardEventHandler(GetApplicationEventTarget());
+ //InstallStandardEventHandler(GetApplicationEventTarget());
// Stash an object pointer for OSMessageBox()
gWindowImplementation = this;
-
// Create the GL context and set it up for windowed or fullscreen, as appropriate.
if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
{
if(mWindow != NULL)
{
- // MBW -- XXX -- I think we can now do this here?
- // Constrain the window to the screen it's mostly on, resizing if necessary.
- ConstrainWindowToScreen(
- mWindow,
- kWindowStructureRgn,
- kWindowConstrainMayResize |
- // kWindowConstrainStandardOptions |
- 0,
- NULL,
- NULL);
-
- MacShowWindow(mWindow);
- BringToFront(mWindow);
+ makeWindowOrderFront(mWindow);
}
if (!gGLManager.initGL())
@@ -317,480 +186,390 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
//start with arrow cursor
initCursors();
setCursor( UI_CURSOR_ARROW );
+
+ allowLanguageTextInput(NULL, FALSE);
}
mCallbacks = callbacks;
stop_glerror();
+
+
}
-BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
+// These functions are used as wrappers for our internal event handling callbacks.
+// It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow.
+
+bool callKeyUp(unsigned short key, unsigned int mask)
{
- OSStatus err;
- BOOL glNeedsInit = FALSE;
+ return gKeyboard->handleKeyUp(key, mask);
+}
- if(mGlobalHandlerRef == NULL)
- {
- InstallApplicationEventHandler(mEventHandlerUPP, GetEventTypeCount (CommandHandlerEventList), CommandHandlerEventList, (void*)this, &mGlobalHandlerRef);
- }
+bool callKeyDown(unsigned short key, unsigned int mask)
+{
+ return gKeyboard->handleKeyDown(key, mask);
+}
- mFullscreen = fullscreen;
+void callResetKeys()
+{
+ gKeyboard->resetKeys();
+}
- if (mFullscreen && (mOldDisplayMode == NULL))
- {
- LL_INFOS("Window") << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
+bool callUnicodeCallback(wchar_t character, unsigned int mask)
+{
+ return gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask);
+}
- // NOTE: The refresh rate will be REPORTED AS 0 for many DVI and notebook displays. Plan accordingly.
- double refresh = getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate);
+void callFocus()
+{
+ if (gWindowImplementation)
+ {
+ gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation);
+ }
+}
- // If the requested width or height is 0, find the best default for the monitor.
- if((width == 0) || (height == 0))
- {
- // Scan through the list of modes, looking for one which has:
- // height between 700 and 800
- // aspect ratio closest to the user's original mode
- S32 resolutionCount = 0;
- LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
+void callFocusLost()
+{
+ gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+}
- if(resolutionList != NULL)
- {
- F32 closestAspect = 0;
- U32 closestHeight = 0;
- U32 closestWidth = 0;
- int i;
+void callRightMouseDown(float *pos, MASK mask)
+{
+ if (gWindowImplementation->allowsLanguageInput())
+ {
+ gWindowImplementation->interruptLanguageTextInput();
+ }
+
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+}
- LL_DEBUGS("Window") << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL;
+void callRightMouseUp(float *pos, MASK mask)
+{
+ if (gWindowImplementation->allowsLanguageInput())
+ {
+ gWindowImplementation->interruptLanguageTextInput();
+ }
+
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+}
- for(i=0; i < resolutionCount; i++)
- {
- F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
+void callLeftMouseDown(float *pos, MASK mask)
+{
+ if (gWindowImplementation->allowsLanguageInput())
+ {
+ gWindowImplementation->interruptLanguageTextInput();
+ }
+
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+}
- LL_DEBUGS("Window") << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL;
+void callLeftMouseUp(float *pos, MASK mask)
+{
+ if (gWindowImplementation->allowsLanguageInput())
+ {
+ gWindowImplementation->interruptLanguageTextInput();
+ }
+
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+
+}
- if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
- (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
- {
- LL_DEBUGS("Window") << " (new closest mode) " << LL_ENDL;
+void callDoubleClick(float *pos, MASK mask)
+{
+ if (gWindowImplementation->allowsLanguageInput())
+ {
+ gWindowImplementation->interruptLanguageTextInput();
+ }
+
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+}
- // This is the closest mode we've seen yet.
- closestWidth = resolutionList[i].mWidth;
- closestHeight = resolutionList[i].mHeight;
- closestAspect = aspect;
- }
- }
+void callResize(unsigned int width, unsigned int height)
+{
+ if (gWindowImplementation != NULL)
+ {
+ gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height);
+ }
+}
- width = closestWidth;
- height = closestHeight;
- }
- }
+void callMouseMoved(float *pos, MASK mask)
+{
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ float deltas[2];
+ gWindowImplementation->getMouseDeltas(deltas);
+ outCoords.mX += deltas[0];
+ outCoords.mY += deltas[1];
+ gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ //gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0);
+}
- if((width == 0) || (height == 0))
- {
- // Mode search failed for some reason. Use the old-school default.
- width = 1024;
- height = 768;
- }
+void callScrollMoved(float delta)
+{
+ gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, delta);
+}
- if (true)
- {
- // Fullscreen support
- CFDictionaryRef refDisplayMode = 0;
- boolean_t exactMatch = false;
-
-#if CAPTURE_ALL_DISPLAYS
- // Capture all displays (may want to do this for final build)
- CGCaptureAllDisplays ();
-#else
- // Capture only the main display (useful for debugging)
- CGDisplayCapture (mDisplay);
-#endif
+void callMouseExit()
+{
+ gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation);
+}
- // Switch the display to the desired resolution and refresh
- refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate(
- mDisplay,
- BITS_PER_PIXEL,
- width,
- height,
- refresh,
- &exactMatch);
+void callWindowFocus()
+{
+ gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation);
+}
- if (refDisplayMode)
- {
- LL_DEBUGS("Window") << "createContext: switching display resolution" << LL_ENDL;
- mOldDisplayMode = CGDisplayCurrentMode (mDisplay);
- CGDisplaySwitchToMode (mDisplay, refDisplayMode);
- // CFRelease(refDisplayMode);
+void callWindowUnfocus()
+{
+ gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+}
- AddEventTypesToHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList);
- }
+void callDeltaUpdate(float *delta, MASK mask)
+{
+ gWindowImplementation->updateMouseDeltas(delta);
+}
+void callMiddleMouseDown(float *pos, MASK mask)
+{
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ float deltas[2];
+ gWindowImplementation->getMouseDeltas(deltas);
+ outCoords.mX += deltas[0];
+ outCoords.mY += deltas[1];
+ gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask);
+}
- mFullscreen = TRUE;
- mFullscreenWidth = CGDisplayPixelsWide(mDisplay);
- mFullscreenHeight = CGDisplayPixelsHigh(mDisplay);
- mFullscreenBits = CGDisplayBitsPerPixel(mDisplay);
- mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate));
+void callMiddleMouseUp(float *pos, MASK mask)
+{
+ LLCoordGL outCoords;
+ outCoords.mX = llround(pos[0]);
+ outCoords.mY = llround(pos[1]);
+ float deltas[2];
+ gWindowImplementation->getMouseDeltas(deltas);
+ outCoords.mX += deltas[0];
+ outCoords.mY += deltas[1];
+ gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask);
+}
- LL_INFOS("Window") << "Running at " << mFullscreenWidth
- << "x" << mFullscreenHeight
- << "x" << mFullscreenBits
- << " @ " << mFullscreenRefresh
- << LL_ENDL;
- }
- else
- {
- // No fullscreen support
- mFullscreen = FALSE;
- mFullscreenWidth = -1;
- mFullscreenHeight = -1;
- mFullscreenBits = -1;
- mFullscreenRefresh = -1;
-
- std::string error= llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
- OSMessageBox(error, "Error", OSMB_OK);
- }
- }
+void callModifier(MASK mask)
+{
+ gKeyboard->handleModifier(mask);
+}
- if(!mFullscreen && (mWindow == NULL))
- {
- //int displayWidth = CGDisplayPixelsWide(mDisplay);
- //int displayHeight = CGDisplayPixelsHigh(mDisplay);
- //const int menuBarPlusTitleBar = 44; // Ugly magic number.
+void callHandleDragEntered(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING);
+}
- LL_DEBUGS("Window") << "createContext: creating window" << LL_ENDL;
+void callHandleDragExited(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING);
+}
- mPreviousWindowRect.left = (long) x;
- mPreviousWindowRect.right = (long) x + width;
- mPreviousWindowRect.top = (long) y;
- mPreviousWindowRect.bottom = (long) y + height;
+void callHandleDragUpdated(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK);
+}
- //-----------------------------------------------------------------------
- // Create the window
- //-----------------------------------------------------------------------
- mWindow = NewCWindow(
- NULL,
- &mPreviousWindowRect,
- mWindowTitle,
- false, // Create the window invisible. Whoever calls createContext() should show it after any moving/resizing.
- // noGrowDocProc, // Window with no grow box and no zoom box
- zoomDocProc, // Window with a grow box and a zoom box
- // zoomNoGrow, // Window with a zoom box but no grow box
- kFirstWindowOfClass,
- true,
- (long)this);
+void callHandleDragDropped(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED);
+}
- if (!mWindow)
+void callQuitHandler()
+{
+ if (gWindowImplementation)
+ {
+ if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation))
{
- setupFailure("Window creation error", "Error", OSMB_OK);
- return FALSE;
+ gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation);
}
-
- // Turn on live resize.
- // For this to work correctly, we need to be able to call LLViewerWindow::draw from
- // the event handler for kEventWindowBoundsChanged. It's not clear that we have access from here.
- // err = ChangeWindowAttributes(mWindow, kWindowLiveResizeAttribute, 0);
-
- // Set up window event handlers (some window-related events ONLY go to window handlers.)
- InstallStandardEventHandler(GetWindowEventTarget(mWindow));
- InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
-#if LL_OS_DRAGDROP_ENABLED
- InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this );
- InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this );
-#endif // LL_OS_DRAGDROP_ENABLED
}
+}
+void getPreeditSelectionRange(int *position, int *length)
+{
+ if (gWindowImplementation->getPreeditor())
{
- // Create and initialize our TSM document for language text input.
- // If an error occured, we can do nothing better than simply ignore it.
- // mTSMDocument will be kept NULL in case.
- if (mTSMDocument)
- {
- DeactivateTSMDocument(mTSMDocument);
- DeleteTSMDocument(mTSMDocument);
- mTSMDocument = NULL;
- }
- static InterfaceTypeList types = { kUnicodeDocument };
- err = NewTSMDocument(1, types, &mTSMDocument, 0);
- if (err != noErr)
- {
- LL_WARNS("Window") << "createContext: couldn't create a TSMDocument (" << err << ")" << LL_ENDL;
- }
- if (mTSMDocument)
- {
- ActivateTSMDocument(mTSMDocument);
- allowLanguageTextInput(NULL, FALSE);
- }
+ gWindowImplementation->getPreeditor()->getSelectionRange(position, length);
}
+}
- if(mContext == NULL)
+void getPreeditMarkedRange(int *position, int *length)
+{
+ if (gWindowImplementation->getPreeditor())
{
- AGLRendererInfo rendererInfo = NULL;
-
- //-----------------------------------------------------------------------
- // Create GL drawing context
- //-----------------------------------------------------------------------
-
- if(mPixelFormat == NULL)
- {
- if(mFullscreen)
- {
- GLint fullscreenAttrib[] =
- {
- AGL_RGBA,
- AGL_FULLSCREEN,
- AGL_NO_RECOVERY,
- AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
- AGL_SAMPLES_ARB, mFSAASamples,
- AGL_DOUBLEBUFFER,
- AGL_CLOSEST_POLICY,
- AGL_ACCELERATED,
- AGL_RED_SIZE, 8,
- AGL_GREEN_SIZE, 8,
- AGL_BLUE_SIZE, 8,
- AGL_ALPHA_SIZE, 8,
- AGL_DEPTH_SIZE, 24,
- AGL_STENCIL_SIZE, 8,
- AGL_NONE
- };
-
- LL_DEBUGS("Window") << "createContext: creating fullscreen pixelformat" << LL_ENDL;
-
- GDHandle gdhDisplay = NULL;
- err = DMGetGDeviceByDisplayID ((DisplayIDType)mDisplay, &gdhDisplay, false);
-
- mPixelFormat = aglChoosePixelFormat(&gdhDisplay, 1, fullscreenAttrib);
- rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1);
- }
- else
- {
- // NOTE from Leslie:
- //
- // AGL_NO_RECOVERY, when combined with AGL_ACCELERATED prevents software rendering
- // fallback which means we won't hvae shaders that compile and link but then don't
- // work. The drawback is that our shader compilation will be a bit more finicky though.
-
- GLint windowedAttrib[] =
- {
- AGL_RGBA,
- AGL_NO_RECOVERY,
- AGL_DOUBLEBUFFER,
- AGL_CLOSEST_POLICY,
- AGL_ACCELERATED,
- AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
- AGL_SAMPLES_ARB, mFSAASamples,
- AGL_RED_SIZE, 8,
- AGL_GREEN_SIZE, 8,
- AGL_BLUE_SIZE, 8,
- AGL_ALPHA_SIZE, 8,
- AGL_DEPTH_SIZE, 24,
- AGL_STENCIL_SIZE, 8,
- AGL_NONE
- };
-
- LL_DEBUGS("Window") << "createContext: creating windowed pixelformat" << LL_ENDL;
-
- mPixelFormat = aglChoosePixelFormat(NULL, 0, windowedAttrib);
-
- GDHandle gdhDisplay = GetMainDevice();
- rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1);
- }
-
- // May want to get the real error text like this:
- // (char *) aglErrorString(aglGetError());
-
- if(aglGetError() != AGL_NO_ERROR)
- {
- setupFailure("Can't find suitable pixel format", "Error", OSMB_OK);
- return FALSE;
- }
- }
-
- if(mPixelFormat)
- {
- LL_DEBUGS("Window") << "createContext: creating GL context" << LL_ENDL;
- mContext = aglCreateContext(mPixelFormat, NULL);
- }
-
- if(mContext == NULL)
- {
- setupFailure("Can't make GL context", "Error", OSMB_OK);
- return FALSE;
- }
-
- gGLManager.mVRAM = 0;
-
- if(rendererInfo != NULL)
- {
- GLint result;
-
- if(aglDescribeRenderer(rendererInfo, AGL_VIDEO_MEMORY, &result))
- {
- // llinfos << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) returned " << result << llendl;
- gGLManager.mVRAM = result / (1024 * 1024);
- }
- else
- {
- // llinfos << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) failed." << llendl;
- }
-
- // This could be useful at some point, if it takes into account the memory already used by screen buffers, etc...
- if(aglDescribeRenderer(rendererInfo, AGL_TEXTURE_MEMORY, &result))
- {
- // llinfos << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) returned " << result << llendl;
- }
- else
- {
- // llinfos << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) failed." << llendl;
- }
-
- aglDestroyRendererInfo(rendererInfo);
- }
-
- // Since we just created the context, it needs to be set up.
- glNeedsInit = TRUE;
+ gWindowImplementation->getPreeditor()->getPreeditRange(position, length);
}
+}
- // Hook up the context to a drawable
- if (mFullscreen && (mOldDisplayMode != NULL))
+void setPreeditMarkedRange(int position, int length)
+{
+ if (gWindowImplementation->getPreeditor())
{
- // We successfully captured the display. Use a fullscreen drawable
-
- LL_DEBUGS("Window") << "createContext: attaching fullscreen drawable" << LL_ENDL;
-
-#if CAPTURE_ALL_DISPLAYS
- // Capture all displays (may want to do this for final build)
- aglDisable (mContext, AGL_FS_CAPTURE_SINGLE);
-#else
- // Capture only the main display (useful for debugging)
- aglEnable (mContext, AGL_FS_CAPTURE_SINGLE);
-#endif
-
- if (!aglSetFullScreen (mContext, 0, 0, 0, 0))
- {
- setupFailure("Can't set GL fullscreen", "Error", OSMB_OK);
- return FALSE;
- }
+ gWindowImplementation->getPreeditor()->markAsPreedit(position, length);
}
- else if(!mFullscreen && (mWindow != NULL))
- {
- LL_DEBUGS("Window") << "createContext: attaching windowed drawable" << LL_ENDL;
+}
- // We created a window. Use it as the drawable.
- if(!aglSetDrawable(mContext, GetWindowPort (mWindow)))
- {
- setupFailure("Can't set GL drawable", "Error", OSMB_OK);
- return FALSE;
- }
- }
- else
+bool handleUnicodeCharacter(wchar_t c)
+{
+ bool success = false;
+ if (gWindowImplementation->getPreeditor())
{
- setupFailure("Can't get fullscreen or windowed drawable.", "Error", OSMB_OK);
- return FALSE;
+ success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c);
}
+
+ return success;
+}
- if(mContext != NULL)
+void resetPreedit()
+{
+ if (gWindowImplementation->getPreeditor())
{
- LL_DEBUGS("Window") << "createContext: setting current context" << LL_ENDL;
+ gWindowImplementation->getPreeditor()->resetPreedit();
+ }
+}
- if (!aglSetCurrentContext(mContext))
+// For reasons of convenience, handle IME updates here.
+// This largely mirrors the old implementation, only sans the carbon parameters.
+void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments)
+{
+ if (gWindowImplementation->getPreeditor())
+ {
+ LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
+ preeditor->resetPreedit();
+ // This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter.
+ if (replacementRange[0] < replacementRange[1])
{
- setupFailure("Can't activate GL rendering context", "Error", OSMB_OK);
- return FALSE;
+ const LLWString& text = preeditor->getPreeditString();
+ const S32 location = wstring_wstring_length_from_utf16_length(text, 0, replacementRange[0]);
+ const S32 length = wstring_wstring_length_from_utf16_length(text, location, replacementRange[1]);
+ preeditor->markAsPreedit(location, length);
}
+
+ LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len));
+
+ S32 caret_position = fix_str.length();
+
+ preeditor->updatePreedit(fix_str, segments.seg_lengths, segments.seg_standouts, caret_position);
}
+}
- if(glNeedsInit)
+void getPreeditLocation(float *location, unsigned int length)
+{
+ if (gWindowImplementation->getPreeditor())
{
- // Check for some explicitly unsupported cards.
- const char* RENDERER = (const char*) glGetString(GL_RENDERER);
-
- const char* CARD_LIST[] =
- { "RAGE 128",
- "RIVA TNT2",
- "Intel 810",
- "3Dfx/Voodoo3",
- "Radeon 7000",
- "Radeon 7200",
- "Radeon 7500",
- "Radeon DDR",
- "Radeon VE",
- "GDI Generic" };
- const S32 CARD_COUNT = LL_ARRAY_SIZE(CARD_LIST);
-
- // Future candidates:
- // ProSavage/Twister
- // SuperSavage
+ LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
+ LLCoordGL coord;
+ LLCoordScreen screen;
+ LLRect rect;
+
+ preeditor->getPreeditLocation(length, &coord, &rect, NULL);
+
+ float c[4] = {coord.mX, coord.mY, 0, 0};
+
+ convertRectToScreen(gWindowImplementation->getWindow(), c);
+
+ location[0] = c[0];
+ location[1] = c[1];
+ }
+}
- S32 i;
- for (i = 0; i < CARD_COUNT; i++)
+void LLWindowMacOSX::updateMouseDeltas(float* deltas)
+{
+ if (mCursorDecoupled)
+ {
+ mCursorLastEventDeltaX = llround(deltas[0]);
+ mCursorLastEventDeltaY = llround(-deltas[1]);
+
+ if (mCursorIgnoreNextDelta)
{
- if (check_for_card(RENDERER, CARD_LIST[i]))
- {
- close();
- return FALSE;
- }
+ mCursorLastEventDeltaX = 0;
+ mCursorLastEventDeltaY = 0;
+ mCursorIgnoreNextDelta = FALSE;
}
+ } else {
+ mCursorLastEventDeltaX = 0;
+ mCursorLastEventDeltaY = 0;
}
+}
+
+void LLWindowMacOSX::getMouseDeltas(float* delta)
+{
+ delta[0] = mCursorLastEventDeltaX;
+ delta[1] = mCursorLastEventDeltaY;
+}
- GLint colorBits, alphaBits, depthBits, stencilBits;
+BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
+{
+ BOOL glNeedsInit = FALSE;
- if( !aglDescribePixelFormat(mPixelFormat, AGL_BUFFER_SIZE, &colorBits) ||
- !aglDescribePixelFormat(mPixelFormat, AGL_ALPHA_SIZE, &alphaBits) ||
- !aglDescribePixelFormat(mPixelFormat, AGL_DEPTH_SIZE, &depthBits) ||
- !aglDescribePixelFormat(mPixelFormat, AGL_STENCIL_SIZE, &stencilBits))
+ mFullscreen = fullscreen;
+
+ if (mWindow == NULL)
{
- close();
- setupFailure("Can't get pixel format description", "Error", OSMB_OK);
- return FALSE;
+ mWindow = getMainAppWindow();
}
- LL_INFOS("GLInit") << "GL buffer: Color Bits " << S32(colorBits)
- << " Alpha Bits " << S32(alphaBits)
- << " Depth Bits " << S32(depthBits)
- << " Stencil Bits" << S32(stencilBits)
- << LL_ENDL;
-
- if (colorBits < 32)
+ if(mContext == NULL)
{
- close();
- setupFailure(
- "Second Life requires True Color (32-bit) to run in a window.\n"
- "Please go to Control Panels -> Display -> Settings and\n"
- "set the screen to 32-bit color.\n"
- "Alternately, if you choose to run fullscreen, Second Life\n"
- "will automatically adjust the screen each time it runs.",
- "Error",
- OSMB_OK);
- return FALSE;
+ // Our OpenGL view is already defined within SecondLife.xib.
+ // Get the view instead.
+ mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync);
+ mContext = getCGLContextObj(mGLView);
+
+ // Since we just created the context, it needs to be set up.
+ glNeedsInit = TRUE;
+
+ gGLManager.mVRAM = getVramSize(mGLView);
}
+
+ // This sets up our view to recieve text from our non-inline text input window.
+ setupInputWindow(mWindow, mGLView);
+
+ // Hook up the context to a drawable
- if (alphaBits < 8)
+ if(mContext != NULL)
{
- close();
- setupFailure(
- "Second Life is unable to run because it can't get an 8 bit alpha\n"
- "channel. Usually this is due to video card driver issues.\n"
- "Please make sure you have the latest video card drivers installed.\n"
- "Also be sure your monitor is set to True Color (32-bit) in\n"
- "Control Panels -> Display -> Settings.\n"
- "If you continue to receive this message, contact customer service.",
- "Error",
- OSMB_OK);
- return FALSE;
+
+
+ U32 err = CGLSetCurrentContext(mContext);
+ if (err != kCGLNoError)
+ {
+ setupFailure("Can't activate GL rendering context", "Error", OSMB_OK);
+ return FALSE;
+ }
}
// Disable vertical sync for swap
GLint frames_per_swap = 0;
if (disable_vsync)
{
- LL_DEBUGS("GLInit") << "Disabling vertical sync" << LL_ENDL;
frames_per_swap = 0;
}
else
{
- LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL;
frames_per_swap = 1;
}
- aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap);
+
+ CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap);
//enable multi-threaded OpenGL
if (sUseMultGL)
@@ -809,109 +588,17 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
}
}
-
- // Don't need to get the current gamma, since there's a call that restores it to the system defaults.
+ makeFirstResponder(mWindow, mGLView);
+
return TRUE;
}
-// changing fullscreen resolution, or switching between windowed and fullscreen mode.
+// We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop.
+// This makes this method obsolete.
BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
{
- BOOL needsRebuild = FALSE;
- BOOL result = true;
-
- if(fullscreen)
- {
- if(mFullscreen)
- {
- // Switching resolutions in fullscreen mode. Don't need to rebuild for this.
- // Fullscreen support
- CFDictionaryRef refDisplayMode = 0;
- boolean_t exactMatch = false;
-
- // Switch the display to the desired resolution and refresh
- refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate(
- mDisplay,
- BITS_PER_PIXEL,
- size.mX,
- size.mY,
- getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate),
- &exactMatch);
-
- if (refDisplayMode)
- {
- CGDisplaySwitchToMode (mDisplay, refDisplayMode);
- // CFRelease(refDisplayMode);
- }
-
- mFullscreenWidth = CGDisplayPixelsWide(mDisplay);
- mFullscreenHeight = CGDisplayPixelsHigh(mDisplay);
- mFullscreenBits = CGDisplayBitsPerPixel(mDisplay);
- mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate));
-
- LL_INFOS("Window") << "Switched resolution to " << mFullscreenWidth
- << "x" << mFullscreenHeight
- << "x" << mFullscreenBits
- << " @ " << mFullscreenRefresh
- << LL_ENDL;
-
- // Update the GL context to the new screen size
- if (!aglUpdateContext(mContext))
- {
- setupFailure("Can't set GL fullscreen", "Error", OSMB_OK);
- result = FALSE;
- }
- }
- else
- {
- // Switching from windowed to fullscreen
- needsRebuild = TRUE;
- }
- }
- else
- {
- if(mFullscreen)
- {
- // Switching from fullscreen to windowed
- needsRebuild = TRUE;
- }
- else
- {
- // Windowed to windowed -- not sure why we would be called like this. Just change the window size.
- // The bounds changed event handler will do the rest.
- if(mWindow != NULL)
- {
- ::SizeWindow(mWindow, size.mX, size.mY, true);
- }
- }
- }
-
- stop_glerror();
- if(needsRebuild || mForceRebuild)
- {
- mForceRebuild = FALSE;
- destroyContext();
- result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
- if (result)
- {
- if(mWindow != NULL)
- {
- MacShowWindow(mWindow);
- BringToFront(mWindow);
- }
-
- llverify(gGLManager.initGL());
-
- //start with arrow cursor
- initCursors();
- setCursor( UI_CURSOR_ARROW );
- }
- }
-
- stop_glerror();
-
- return result;
+ return FALSE;
}
void LLWindowMacOSX::destroyContext()
@@ -925,32 +612,7 @@ void LLWindowMacOSX::destroyContext()
if(mContext != NULL)
{
LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL;
-
- aglSetCurrentContext (NULL);
- aglSetDrawable(mContext, NULL);
- }
-
- // Make sure the display resolution gets restored
- if(mOldDisplayMode != NULL)
- {
- LL_DEBUGS("Window") << "destroyContext: restoring display resolution " << LL_ENDL;
-
- CGDisplaySwitchToMode (mDisplay, mOldDisplayMode);
-
-#if CAPTURE_ALL_DISPLAYS
- // Uncapture all displays (may want to do this for final build)
- CGReleaseAllDisplays ();
-#else
- // Uncapture only the main display (useful for debugging)
- CGDisplayRelease (mDisplay);
-#endif
-
- // CFRelease(mOldDisplayMode);
-
- mOldDisplayMode = NULL;
-
- // Remove the global event handlers the fullscreen case needed
- RemoveEventTypesFromHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList);
+ CGLSetCurrentContext(NULL);
}
// Clean up remaining GL state before blowing away window
@@ -959,49 +621,29 @@ void LLWindowMacOSX::destroyContext()
// Clean up the pixel format
if(mPixelFormat != NULL)
{
- LL_DEBUGS("Window") << "destroyContext: destroying pixel format " << LL_ENDL;
- aglDestroyPixelFormat(mPixelFormat);
+ CGLDestroyPixelFormat(mPixelFormat);
mPixelFormat = NULL;
}
- // Remove any Carbon Event handlers we installed
- if(mGlobalHandlerRef != NULL)
- {
- LL_DEBUGS("Window") << "destroyContext: removing global event handler" << LL_ENDL;
- RemoveEventHandler(mGlobalHandlerRef);
- mGlobalHandlerRef = NULL;
- }
-
- if(mWindowHandlerRef != NULL)
+ // Clean up the GL context
+ if(mContext != NULL)
{
- LL_DEBUGS("Window") << "destroyContext: removing window event handler" << LL_ENDL;
- RemoveEventHandler(mWindowHandlerRef);
- mWindowHandlerRef = NULL;
+ CGLDestroyContext(mContext);
}
-
- // Cleanup any TSM document we created.
- if(mTSMDocument != NULL)
+
+ // Destroy our LLOpenGLView
+ if(mGLView != NULL)
{
- LL_DEBUGS("Window") << "destroyContext: deleting TSM document" << LL_ENDL;
- DeactivateTSMDocument(mTSMDocument);
- DeleteTSMDocument(mTSMDocument);
- mTSMDocument = NULL;
+ removeGLView(mGLView);
+ mGLView = NULL;
}
-
+
// Close the window
if(mWindow != NULL)
{
- LL_DEBUGS("Window") << "destroyContext: disposing window" << LL_ENDL;
- DisposeWindow(mWindow);
- mWindow = NULL;
- }
-
- // Clean up the GL context
- if(mContext != NULL)
- {
- LL_DEBUGS("Window") << "destroyContext: destroying GL context" << LL_ENDL;
- aglDestroyContext(mContext);
- mContext = NULL;
+ NSWindowRef dead_window = mWindow;
+ mWindow = NULL;
+ closeWindow(dead_window);
}
}
@@ -1022,17 +664,11 @@ LLWindowMacOSX::~LLWindowMacOSX()
void LLWindowMacOSX::show()
{
- if(IsWindowCollapsed(mWindow))
- CollapseWindow(mWindow, false);
-
- MacShowWindow(mWindow);
- BringToFront(mWindow);
}
void LLWindowMacOSX::hide()
{
setMouseClipping(FALSE);
- HideWindow(mWindow);
}
//virtual
@@ -1040,7 +676,6 @@ void LLWindowMacOSX::minimize()
{
setMouseClipping(FALSE);
showCursor();
- CollapseWindow(mWindow, true);
}
//virtual
@@ -1086,7 +721,6 @@ BOOL LLWindowMacOSX::getVisible()
result = TRUE;
}if (mWindow)
{
- if(MacIsWindowVisible(mWindow))
result = TRUE;
}
@@ -1107,7 +741,6 @@ BOOL LLWindowMacOSX::maximize()
{
if (mWindow && !mMaximized)
{
- ZoomWindow(mWindow, inContent, true);
}
return mMaximized;
@@ -1120,58 +753,13 @@ BOOL LLWindowMacOSX::getFullscreen()
void LLWindowMacOSX::gatherInput()
{
- // stop bouncing icon after fixed period of time
- if (mBounceTimer.getStarted() && mBounceTimer.getElapsedTimeF32() > mBounceTime)
- {
- stopDockTileBounce();
- }
-
- // Use the old-school version so we get AppleEvent handler dispatch and menuselect handling.
- // Anything that has an event handler will get processed inside WaitNextEvent, so we only need to handle
- // the odd stuff here.
- EventRecord evt;
- while(WaitNextEvent(everyEvent, &evt, 0, NULL))
- {
- // printf("WaitNextEvent returned true, event is %d.\n", evt.what);
- switch(evt.what)
- {
- case mouseDown:
- {
- short part;
- WindowRef window;
- long selectResult;
- part = FindWindow(evt.where, &window);
- switch ( part )
- {
- case inMenuBar:
- selectResult = MenuSelect(evt.where);
-
- HiliteMenu(0);
- break;
- }
- }
- break;
-
- case kHighLevelEvent:
- AEProcessAppleEvent (&evt);
- break;
-
- case updateEvt:
- // We shouldn't be getting these regularly (since our window will be buffered), but we need to handle them correctly...
- BeginUpdate((WindowRef)evt.message);
- EndUpdate((WindowRef)evt.message);
- break;
-
- }
- }
-
updateCursor();
}
BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
{
- Rect window_rect;
- OSStatus err = -1;
+ float rect[4];
+ S32 err = -1;
if(mFullscreen)
{
@@ -1181,10 +769,10 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
}
else if(mWindow)
{
- err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect);
+ getContentViewBounds(mWindow, rect);
- position->mX = window_rect.left;
- position->mY = window_rect.top;
+ position->mX = rect[0];
+ position->mY = rect[1];
}
else
{
@@ -1196,8 +784,8 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
{
- Rect window_rect;
- OSStatus err = -1;
+ float rect[4];
+ S32 err = -1;
if(mFullscreen)
{
@@ -1207,10 +795,10 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
}
else if(mWindow)
{
- err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect);
+ getContentViewBounds(mWindow, rect);
- size->mX = window_rect.right - window_rect.left;
- size->mY = window_rect.bottom - window_rect.top;
+ size->mX = rect[2];
+ size->mY = rect[3];
}
else
{
@@ -1222,9 +810,9 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
BOOL LLWindowMacOSX::getSize(LLCoordWindow *size)
{
- Rect window_rect;
- OSStatus err = -1;
-
+ float rect[4];
+ S32 err = -1;
+
if(mFullscreen)
{
size->mX = mFullscreenWidth;
@@ -1233,16 +821,16 @@ BOOL LLWindowMacOSX::getSize(LLCoordWindow *size)
}
else if(mWindow)
{
- err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect);
-
- size->mX = window_rect.right - window_rect.left;
- size->mY = window_rect.bottom - window_rect.top;
+ getContentViewBounds(mWindow, rect);
+
+ size->mX = rect[2];
+ size->mY = rect[3];
}
else
{
llerrs << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << llendl;
}
-
+
return (err == noErr);
}
@@ -1250,7 +838,8 @@ BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position)
{
if(mWindow)
{
- MacMoveWindow(mWindow, position.mX, position.mY, false);
+ float pos[2] = {position.mX, position.mY};
+ setWindowPos(mWindow, pos);
}
return TRUE;
@@ -1260,45 +849,35 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size)
{
if(mWindow)
{
- SizeWindow(mWindow, size.mX, size.mY, true);
+ LLCoordWindow to;
+ convertCoords(size, &to);
+ setWindowSize(mWindow, to.mX, to.mY);
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size)
{
- Rect client_rect;
if (mWindow)
{
- OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect);
- if (err == noErr)
- {
- client_rect.right = client_rect.left + size.mX;
- client_rect.bottom = client_rect.top + size.mY;
- err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect);
- }
- if (err == noErr)
- {
- return TRUE;
- }
- else
- {
- llinfos << "Error setting size" << err << llendl;
- return FALSE;
- }
+ const int titlePadding = 22;
+ setWindowSize(mWindow, size.mX, size.mY + titlePadding);
+ return TRUE;
}
+
return FALSE;
}
void LLWindowMacOSX::swapBuffers()
{
- aglSwapBuffers(mContext);
+ CGLFlushDrawable(mContext);
}
F32 LLWindowMacOSX::getGamma()
{
- F32 result = 1.8; // Default to something sane
+ F32 result = 2.2; // Default to something sane
CGGammaValue redMin;
CGGammaValue redMax;
@@ -1454,39 +1033,15 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
return result;
}
-static void fixOrigin(void)
-{
- GrafPtr port;
- Rect portrect;
-
- ::GetPort(&port);
- ::GetPortBounds(port, &portrect);
- if((portrect.left != 0) || (portrect.top != 0))
- {
- // Mozilla sometimes changes our port origin.
- ::SetOrigin(0,0);
- }
-}
-
BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
{
- Point cursor_point;
+ float cursor_point[2];
LLCoordScreen screen_pos;
- GrafPtr save;
if(mWindow == NULL)
return FALSE;
-
- ::GetPort(&save);
- ::SetPort(GetWindowPort(mWindow));
- fixOrigin();
-
- // gets the mouse location in local coordinates
- ::GetMouse(&cursor_point);
-
-// lldebugs << "getCursorPosition(): cursor is at " << cursor_point.h << ", " << cursor_point.v << " port origin: " << portrect.left << ", " << portrect.top << llendl;
-
- ::SetPort(save);
+
+ getCursorPos(mWindow, cursor_point);
if(mCursorDecoupled)
{
@@ -1499,12 +1054,12 @@ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
// CGGetLastMouseDelta may behave strangely when the cursor's first captured.
// Stash in the event handler instead.
- cursor_point.h += mCursorLastEventDeltaX;
- cursor_point.v += mCursorLastEventDeltaY;
+ cursor_point[0] += mCursorLastEventDeltaX;
+ cursor_point[1] += mCursorLastEventDeltaY;
}
- position->mX = cursor_point.h;
- position->mY = cursor_point.v;
+ position->mX = cursor_point[0];
+ position->mY = cursor_point[1];
return TRUE;
}
@@ -1521,7 +1076,6 @@ void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse)
// llinfos << "adjustCursorDecouple: decoupling cursor" << llendl;
CGAssociateMouseAndMouseCursorPosition(false);
mCursorDecoupled = true;
- FlushSpecificEventsFromQueue(GetCurrentEventQueue(), mMoveEventCampartorUPP, NULL);
mCursorIgnoreNextDelta = TRUE;
}
}
@@ -1568,179 +1122,46 @@ F32 LLWindowMacOSX::getPixelAspectRatio()
// MBW -- XXX -- There's got to be a better way than this. Find it, please...
+// Since we're no longer supporting the "typical" fullscreen mode with CGL or NSOpenGL anymore, these are unnecessary. -Geenz
void LLWindowMacOSX::beforeDialog()
{
- if(mFullscreen)
- {
-
-#if CAPTURE_ALL_DISPLAYS
- // Uncapture all displays (may want to do this for final build)
- CGReleaseAllDisplays ();
-#else
- // Uncapture only the main display (useful for debugging)
- CGDisplayRelease (mDisplay);
-#endif
- // kDocumentWindowClass
- // kMovableModalWindowClass
- // kAllWindowClasses
-
- // GLint order = 0;
- // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order);
- aglSetDrawable(mContext, NULL);
- // GetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), &oldWindowLevel);
- // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), CGShieldingWindowLevel());
-
- mHandsOffEvents = TRUE;
-
- }
}
void LLWindowMacOSX::afterDialog()
{
- if(mFullscreen)
- {
- mHandsOffEvents = FALSE;
-
- // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), oldWindowLevel);
- aglSetFullScreen(mContext, 0, 0, 0, 0);
- // GLint order = 1;
- // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order);
-
-#if CAPTURE_ALL_DISPLAYS
- // Capture all displays (may want to do this for final build)
- CGCaptureAllDisplays ();
-#else
- // Capture only the main display (useful for debugging)
- CGDisplayCapture (mDisplay);
-#endif
- }
}
void LLWindowMacOSX::flashIcon(F32 seconds)
{
- // Don't do this if we're already started, since this would try to install the NMRec twice.
- if(!mBounceTimer.getStarted())
- {
- OSErr err;
-
- mBounceTime = seconds;
- memset(&mBounceRec, 0, sizeof(mBounceRec));
- mBounceRec.qType = nmType;
- mBounceRec.nmMark = 1;
- err = NMInstall(&mBounceRec);
- if(err == noErr)
- {
- mBounceTimer.start();
- }
- else
- {
- // This is very not-fatal (only problem is the icon will not bounce), but we'd like to find out about it somehow...
- llinfos << "NMInstall failed with error code " << err << llendl;
- }
- }
+ // For consistency with OS X conventions, the number of seconds given is ignored and
+ // left up to the OS (which will actually bounce it for one second).
+ requestUserAttention();
}
BOOL LLWindowMacOSX::isClipboardTextAvailable()
{
- OSStatus err;
- ScrapRef scrap;
- ScrapFlavorFlags flags;
- BOOL result = false;
-
- err = GetCurrentScrap(&scrap);
-
- if(err == noErr)
- {
- err = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &flags);
- }
-
- if(err == noErr)
- result = true;
-
- return result;
+ return pasteBoardAvailable();
}
BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
-{
- OSStatus err;
- ScrapRef scrap;
- Size len;
- BOOL result = false;
-
- err = GetCurrentScrap(&scrap);
-
- if(err == noErr)
+{
+ llutf16string str(copyFromPBoard());
+ dst = utf16str_to_wstring(str);
+ if (dst != L"")
{
- err = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &len);
- }
-
- if((err == noErr) && (len > 0))
- {
- int u16len = len / sizeof(U16);
- U16 *temp = new U16[u16len + 1];
- if (temp)
- {
- memset(temp, 0, (u16len + 1) * sizeof(temp[0]));
- err = GetScrapFlavorData(scrap, kScrapFlavorTypeUnicode, &len, temp);
- if (err == noErr)
- {
- // convert \r\n to \n and \r to \n in the incoming text.
- U16 *s, *d;
- for(s = d = temp; s[0] != '\0'; s++, d++)
- {
- if(s[0] == '\r')
- {
- if(s[1] == '\n')
- {
- // CRLF, a.k.a. DOS newline. Collapse to a single '\n'.
- s++;
- }
-
- d[0] = '\n';
- }
- else
- {
- d[0] = s[0];
- }
- }
-
- d[0] = '\0';
-
- dst = utf16str_to_wstring(temp);
-
- result = true;
- }
- delete[] temp;
- }
+ return true;
+ } else {
+ return false;
}
-
- return result;
}
BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s)
{
- OSStatus err;
- ScrapRef scrap;
- //Size len;
- //char *temp;
BOOL result = false;
-
- if (!s.empty())
- {
- err = GetCurrentScrap(&scrap);
- if (err == noErr)
- err = ClearScrap(&scrap);
-
- if (err == noErr)
- {
- llutf16string utf16str = wstring_to_utf16str(s);
- size_t u16len = utf16str.length() * sizeof(U16);
- err = PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone, u16len, utf16str.data());
- if (err == noErr)
- result = true;
- }
- }
+ llutf16string utf16str = wstring_to_utf16str(s);
+
+ result = copyToPBoard(utf16str.data(), utf16str.length());
return result;
}
@@ -1806,122 +1227,52 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to)
{
- S32 client_height;
- Rect client_rect;
-
- if(mFullscreen)
- {
- // In the fullscreen case, the "window" is the entire screen.
- client_rect.left = 0;
- client_rect.top = 0;
- client_rect.right = mFullscreenWidth;
- client_rect.bottom = mFullscreenHeight;
- }
- else if (!mWindow ||
- (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) ||
- NULL == to)
- {
- return FALSE;
- }
-
to->mX = from.mX;
- client_height = client_rect.bottom - client_rect.top;
- to->mY = client_height - from.mY - 1;
-
+ to->mY = from.mY;
return TRUE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to)
{
- S32 client_height;
- Rect client_rect;
-
- if(mFullscreen)
- {
- // In the fullscreen case, the "window" is the entire screen.
- client_rect.left = 0;
- client_rect.top = 0;
- client_rect.right = mFullscreenWidth;
- client_rect.bottom = mFullscreenHeight;
- }
- else if (!mWindow ||
- (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) ||
- NULL == to)
- {
- return FALSE;
- }
-
to->mX = from.mX;
- client_height = client_rect.bottom - client_rect.top;
- to->mY = client_height - from.mY - 1;
-
+ to->mY = from.mY;
return TRUE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
{
- if(mFullscreen)
- {
- // In the fullscreen case, window and screen coordinates are the same.
- to->mX = from.mX;
- to->mY = from.mY;
- return TRUE;
- }
- else if(mWindow)
+ if(mWindow)
{
- GrafPtr save;
- Point mouse_point;
-
- mouse_point.h = from.mX;
- mouse_point.v = from.mY;
-
- ::GetPort(&save);
- ::SetPort(GetWindowPort(mWindow));
- fixOrigin();
-
- ::GlobalToLocal(&mouse_point);
+ float mouse_point[2];
- to->mX = mouse_point.h;
- to->mY = mouse_point.v;
+ mouse_point[0] = from.mX;
+ mouse_point[1] = from.mY;
+
+ convertScreenToWindow(mWindow, mouse_point);
- ::SetPort(save);
+ to->mX = mouse_point[0];
+ to->mY = mouse_point[1];
return TRUE;
}
-
return FALSE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to)
{
- if(mFullscreen)
- {
- // In the fullscreen case, window and screen coordinates are the same.
- to->mX = from.mX;
- to->mY = from.mY;
- return TRUE;
- }
- else if(mWindow)
+ if(mWindow)
{
- GrafPtr save;
- Point mouse_point;
-
- mouse_point.h = from.mX;
- mouse_point.v = from.mY;
- ::GetPort(&save);
- ::SetPort(GetWindowPort(mWindow));
- fixOrigin();
-
- LocalToGlobal(&mouse_point);
+ float mouse_point[2];
- to->mX = mouse_point.h;
- to->mY = mouse_point.v;
+ mouse_point[0] = from.mX;
+ mouse_point[1] = from.mY;
+ convertWindowToScreen(mWindow, mouse_point);
- ::SetPort(save);
+ to->mX = mouse_point[0];
+ to->mY = mouse_point[1];
return TRUE;
}
-
return FALSE;
}
@@ -1949,862 +1300,8 @@ void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& ca
OSMessageBox(text, caption, type);
}
-pascal Boolean LLWindowMacOSX::staticMoveEventComparator( EventRef event, void* data)
-{
- UInt32 evtClass = GetEventClass (event);
- UInt32 evtKind = GetEventKind (event);
-
- if ((evtClass == kEventClassMouse) && ((evtKind == kEventMouseDragged) || (evtKind == kEventMouseMoved)))
- {
- return true;
- }
-
- else
- {
- return false;
- }
-}
-
-
-pascal OSStatus LLWindowMacOSX::staticEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData)
-{
- LLWindowMacOSX *self = (LLWindowMacOSX*)userData;
-
- return(self->eventHandler(myHandler, event));
-}
-
-OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef event)
-{
- OSStatus result = eventNotHandledErr;
- UInt32 evtClass = GetEventClass (event);
- UInt32 evtKind = GetEventKind (event);
-
- // Always handle command events, even in hands-off mode.
- if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
- {
- HICommand command;
- GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command);
-
- switch(command.commandID)
- {
- case kHICommandQuit:
- if(mCallbacks->handleCloseRequest(this))
- {
- // Get the app to initiate cleanup.
- mCallbacks->handleQuit(this);
- // The app is responsible for calling destroyWindow when done with GL
- }
- result = noErr;
- break;
-
- default:
- // MBW -- XXX -- Should we handle other events here?
- break;
- }
- }
-
- if(mHandsOffEvents)
- {
- return(result);
- }
-
- switch (evtClass)
- {
- case kEventClassTextInput:
- {
- switch (evtKind)
- {
- case kEventTextInputUpdateActiveInputArea:
- {
- EventParamType param_type;
-
- long fix_len;
- UInt32 text_len;
- if (mPreeditor
- && (result = GetEventParameter(event, kEventParamTextInputSendFixLen,
- typeLongInteger, &param_type, sizeof(fix_len), NULL, &fix_len)) == noErr
- && typeLongInteger == param_type
- && (result = GetEventParameter(event, kEventParamTextInputSendText,
- typeUnicodeText, &param_type, 0, &text_len, NULL)) == noErr
- && typeUnicodeText == param_type)
- {
- // Handle an optional (but essential to facilitate TSMDA) ReplaceRange param.
- CFRange range;
- if (GetEventParameter(event, kEventParamTextInputSendReplaceRange,
- typeCFRange, &param_type, sizeof(range), NULL, &range) == noErr
- && typeCFRange == param_type)
- {
- // Although the spec. is unclear, replace range should
- // not present when there is an active preedit. We just
- // ignore the case. markAsPreedit will detect the case and warn it.
- const LLWString & text = mPreeditor->getPreeditString();
- const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location);
- const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length);
- mPreeditor->markAsPreedit(location, length);
- }
- mPreeditor->resetPreedit();
-
- // Receive the text from input method.
- U16 *const text = new U16[text_len / sizeof(U16)];
- GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, NULL, text_len, NULL, text);
- if (fix_len < 0)
- {
- // Do we still need this? Seems obsolete...
- fix_len = text_len;
- }
- const LLWString fix_string
- = utf16str_to_wstring(llutf16string(text, fix_len / sizeof(U16)));
- const LLWString preedit_string
- = utf16str_to_wstring(llutf16string(text + fix_len / sizeof(U16), (text_len - fix_len) / sizeof(U16)));
- delete[] text;
-
- // Handle fixed (comitted) string.
- if (fix_string.length() > 0)
- {
- for (LLWString::const_iterator i = fix_string.begin(); i != fix_string.end(); i++)
- {
- mPreeditor->handleUnicodeCharHere(*i);
- }
- }
-
- // Receive the segment info and caret position.
- LLPreeditor::segment_lengths_t preedit_segment_lengths;
- LLPreeditor::standouts_t preedit_standouts;
- S32 caret_position = preedit_string.length();
- UInt32 text_range_array_size;
- if (GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray,
- &param_type, 0, &text_range_array_size, NULL) == noErr
- && typeTextRangeArray == param_type
- && text_range_array_size > sizeof(TextRangeArray))
- {
- // TextRangeArray is a variable-length struct.
- TextRangeArray * const text_range_array = (TextRangeArray *) new char[text_range_array_size];
- GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray,
- NULL, text_range_array_size, NULL, text_range_array);
-
- // WARNING: We assume ranges are in ascending order,
- // although the condition is undocumented. It seems
- // OK to assume this. I also assumed
- // the ranges are contiguous in previous versions, but I
- // have heard a rumore that older versions os ATOK may
- // return ranges with some _gap_. I don't know whether
- // it is true, but I'm preparing my code for the case.
-
- const S32 ranges = text_range_array->fNumOfRanges;
- preedit_segment_lengths.reserve(ranges);
- preedit_standouts.reserve(ranges);
-
- S32 last_bytes = 0;
- S32 last_utf32 = 0;
- for (S32 i = 0; i < ranges; i++)
- {
- const TextRange &range = text_range_array->fRange[i];
- if (range.fStart > last_bytes)
- {
- const S32 length_utf16 = (range.fStart - last_bytes) / sizeof(U16);
- const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16);
- preedit_segment_lengths.push_back(length_utf32);
- preedit_standouts.push_back(FALSE);
- last_utf32 += length_utf32;
- }
- if (range.fEnd > range.fStart)
- {
- const S32 length_utf16 = (range.fEnd - range.fStart) / sizeof(U16);
- const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16);
- preedit_segment_lengths.push_back(length_utf32);
- preedit_standouts.push_back(
- kTSMHiliteSelectedRawText == range.fHiliteStyle
- || kTSMHiliteSelectedConvertedText == range.fHiliteStyle
- || kTSMHiliteSelectedText == range.fHiliteStyle);
- last_utf32 += length_utf32;
- }
- if (kTSMHiliteCaretPosition == range.fHiliteStyle)
- {
- caret_position = last_utf32;
- }
- last_bytes = range.fEnd;
- }
- if (preedit_string.length() > last_utf32)
- {
- preedit_segment_lengths.push_back(preedit_string.length() - last_utf32);
- preedit_standouts.push_back(FALSE);
- }
-
- delete[] (char *) text_range_array;
- }
-
- // Handle preedit string.
- if (preedit_string.length() == 0)
- {
- preedit_segment_lengths.clear();
- preedit_standouts.clear();
- }
- else if (preedit_segment_lengths.size() == 0)
- {
- preedit_segment_lengths.push_back(preedit_string.length());
- preedit_standouts.push_back(FALSE);
- }
- mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
-
- result = noErr;
- }
- }
- break;
-
- case kEventTextInputUnicodeForKeyEvent:
- {
- UInt32 modifiers = 0;
-
-
- // First, process the raw event.
- {
- EventRef rawEvent = NULL;
-
- // Get the original event and extract the modifier keys, so we can ignore command-key events.
- if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr)
- {
- // Grab the modifiers for later use in this function...
- GetEventParameter (rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
-
- // and call this function recursively to handle the raw key event.
- eventHandler (myHandler, rawEvent);
-
- // save the raw event until we're done processing the unicode input as well.
- mRawKeyEvent = rawEvent;
- }
- }
-
- OSStatus err = noErr;
- EventParamType actualType = typeUnicodeText;
- UInt32 actualSize = 0;
- size_t actualCount = 0;
- U16 *buffer = NULL;
-
- // Get the size of the unicode data
- err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, 0, &actualSize, NULL);
- if(err == noErr)
- {
- // allocate a buffer and get the actual data.
- actualCount = actualSize / sizeof(U16);
- buffer = new U16[actualCount];
- err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, actualSize, &actualSize, buffer);
- }
-
- if(err == noErr)
- {
- if(modifiers & (cmdKey | controlKey))
- {
- // This was a menu key equivalent. Ignore it.
- }
- else
- {
- MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
-
- llassert( actualType == typeUnicodeText );
-
- // The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar.
-
- // Convert to UTF32 and go character-by-character.
- llutf16string utf16(buffer, actualCount);
- LLWString utf32 = utf16str_to_wstring(utf16);
- LLWString::iterator iter;
-
- for(iter = utf32.begin(); iter != utf32.end(); iter++)
- {
- mCallbacks->handleUnicodeChar(*iter, mask);
- }
- }
- }
-
- if(buffer != NULL)
- {
- delete[] buffer;
- }
-
- mRawKeyEvent = NULL;
- result = err;
- }
- break;
-
- case kEventTextInputOffsetToPos:
- {
- EventParamType param_type;
- long offset;
- if (mPreeditor
- && GetEventParameter(event, kEventParamTextInputSendTextOffset, typeLongInteger,
- &param_type, sizeof(offset), NULL, &offset) == noErr
- && typeLongInteger == param_type)
- {
- S32 preedit, preedit_length;
- mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getPreeditString();
-
- LLCoordGL caret_coord;
- LLRect preedit_bounds;
- if (0 <= offset
- && mPreeditor->getPreeditLocation(wstring_wstring_length_from_utf16_length(text, preedit, offset / sizeof(U16)),
- &caret_coord, &preedit_bounds, NULL))
- {
- LLCoordGL caret_base_coord(caret_coord.mX, preedit_bounds.mBottom);
- LLCoordScreen caret_base_coord_screen;
- convertCoords(caret_base_coord, &caret_base_coord_screen);
- Point qd_point;
- qd_point.h = caret_base_coord_screen.mX;
- qd_point.v = caret_base_coord_screen.mY;
- SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint, sizeof(qd_point), &qd_point);
-
- short line_height = (short) preedit_bounds.getHeight();
- SetEventParameter(event, kEventParamTextInputReplyLineHeight, typeShortInteger, sizeof(line_height), &line_height);
-
- result = noErr;
- }
- else
- {
- result = errOffsetInvalid;
- }
- }
- }
- break;
-
- case kEventTextInputGetSelectedText:
- {
- if (mPreeditor)
- {
- S32 selection, selection_length;
- mPreeditor->getSelectionRange(&selection, &selection_length);
- if (selection_length)
- {
- const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length);
- const llutf16string text_utf16 = wstring_to_utf16str(text);
- result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText,
- text_utf16.length() * sizeof(U16), text_utf16.c_str());
- }
- }
- }
- break;
- }
- }
- break;
-
- case kEventClassKeyboard:
- {
- UInt32 keyCode = 0;
- char charCode = 0;
- UInt32 modifiers = 0;
-
- // Some of these may fail for some event types. That's fine.
- GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
- GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
-
- // save the raw event so getNativeKeyData can use it.
- mRawKeyEvent = event;
-
- // printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers);
- // fflush(stdout);
-
- switch (evtKind)
- {
- case kEventRawKeyDown:
- case kEventRawKeyRepeat:
- if (gDebugWindowProc)
- {
- printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
- (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers);
- fflush(stdout);
- }
- gKeyboard->handleKeyDown(keyCode, modifiers);
- result = eventNotHandledErr;
- break;
-
- case kEventRawKeyUp:
- if (gDebugWindowProc)
- {
- printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
- (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers);
- fflush(stdout);
- }
- gKeyboard->handleKeyUp(keyCode, modifiers);
- result = eventNotHandledErr;
- break;
-
- case kEventRawKeyModifiersChanged:
- // The keyboard input system wants key up/down events for modifier keys.
- // Mac OS doesn't supply these directly, but can supply events when the collective modifier state changes.
- // Use these events to generate up/down events for the modifiers.
-
- if((modifiers & shiftKey) && !(mLastModifiers & shiftKey))
- {
- if (gDebugWindowProc) printf("Shift key down event\n");
- gKeyboard->handleKeyDown(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000));
- }
- else if(!(modifiers & shiftKey) && (mLastModifiers & shiftKey))
- {
- if (gDebugWindowProc) printf("Shift key up event\n");
- gKeyboard->handleKeyUp(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000));
- }
-
- if((modifiers & alphaLock) && !(mLastModifiers & alphaLock))
- {
- if (gDebugWindowProc) printf("Caps lock down event\n");
- gKeyboard->handleKeyDown(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000));
- }
- else if(!(modifiers & alphaLock) && (mLastModifiers & alphaLock))
- {
- if (gDebugWindowProc) printf("Caps lock up event\n");
- gKeyboard->handleKeyUp(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000));
- }
-
- if((modifiers & controlKey) && !(mLastModifiers & controlKey))
- {
- if (gDebugWindowProc) printf("Control key down event\n");
- gKeyboard->handleKeyDown(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000));
- }
- else if(!(modifiers & controlKey) && (mLastModifiers & controlKey))
- {
- if (gDebugWindowProc) printf("Control key up event\n");
- gKeyboard->handleKeyUp(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000));
- }
-
- if((modifiers & optionKey) && !(mLastModifiers & optionKey))
- {
- if (gDebugWindowProc) printf("Option key down event\n");
- gKeyboard->handleKeyDown(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000));
- }
- else if(!(modifiers & optionKey) && (mLastModifiers & optionKey))
- {
- if (gDebugWindowProc) printf("Option key up event\n");
- gKeyboard->handleKeyUp(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000));
- }
-
- // When the state of the 'Fn' key (the one that changes some of the mappings on a powerbook/macbook keyboard
- // to an embedded keypad) changes, it may subsequently cause a key up event to be lost, which may lead to
- // a movement key getting "stuck" down. This is bad.
- // This is an OS bug -- even the GetKeys() API doesn't tell you the key has been released.
- // This workaround causes all held-down keys to be reset whenever the state of the Fn key changes. This isn't
- // exactly what we want, but it does avoid the case where you get stuck running forward.
- if((modifiers & kEventKeyModifierFnMask) != (mLastModifiers & kEventKeyModifierFnMask))
- {
- if (gDebugWindowProc) printf("Fn key state change event\n");
- gKeyboard->resetKeys();
- }
-
- if (gDebugWindowProc) fflush(stdout);
-
- mLastModifiers = modifiers;
- result = eventNotHandledErr;
- break;
- }
-
- mRawKeyEvent = NULL;
- }
- break;
-
- case kEventClassMouse:
- {
- result = CallNextEventHandler(myHandler, event);
- if (eventNotHandledErr == result)
- { // only handle events not already handled (prevents wierd resize interaction)
- EventMouseButton button = kEventMouseButtonPrimary;
- HIPoint location = {0.0f, 0.0f};
- UInt32 modifiers = 0;
- UInt32 clickCount = 1;
- long wheelDelta = 0;
- LLCoordScreen inCoords;
- LLCoordGL outCoords;
- MASK mask = 0;
-
- GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
- GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(location), NULL, &location);
- GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
- GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(wheelDelta), NULL, &wheelDelta);
- GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount);
-
- inCoords.mX = llround(location.x);
- inCoords.mY = llround(location.y);
-
- if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
- if(modifiers & controlKey) { mask |= MASK_CONTROL; }
- if(modifiers & optionKey) { mask |= MASK_ALT; }
-
- if(mCursorDecoupled)
- {
- CGMouseDelta x, y;
-
- // If the cursor's decoupled, we need to read the latest movement delta as well.
- CGGetLastMouseDelta( &x, &y );
- mCursorLastEventDeltaX = x;
- mCursorLastEventDeltaY = y;
-
- if(mCursorIgnoreNextDelta)
- {
- mCursorLastEventDeltaX = 0;
- mCursorLastEventDeltaY = 0;
- mCursorIgnoreNextDelta = FALSE;
- }
- }
- else
- {
- mCursorLastEventDeltaX = 0;
- mCursorLastEventDeltaY = 0;
- }
-
- inCoords.mX += mCursorLastEventDeltaX;
- inCoords.mY += mCursorLastEventDeltaY;
-
- convertCoords(inCoords, &outCoords);
-
- // printf("coords in: %d, %d; coords out: %d, %d\n", inCoords.mX, inCoords.mY, outCoords.mX, outCoords.mY);
- // fflush(stdout);
-
-
- switch (evtKind)
- {
- case kEventMouseDown:
- if (mLanguageTextInputAllowed)
- {
- // We need to interrupt before handling mouse events,
- // so that the fixed string from IM are delivered to
- // the currently focused UI component.
- interruptLanguageTextInput();
- }
- switch(button)
- {
- case kEventMouseButtonPrimary:
- if(modifiers & cmdKey)
- {
- // Simulate a right click
- mSimulatedRightClick = true;
- mCallbacks->handleRightMouseDown(this, outCoords, mask);
- }
- else if(clickCount == 2)
- {
- // Windows double-click events replace the second mousedown event in a double-click.
- mCallbacks->handleDoubleClick(this, outCoords, mask);
- }
- else
- {
- mCallbacks->handleMouseDown(this, outCoords, mask);
- }
- break;
- case kEventMouseButtonSecondary:
- mCallbacks->handleRightMouseDown(this, outCoords, mask);
- break;
-
- case kEventMouseButtonTertiary:
- mCallbacks->handleMiddleMouseDown(this, outCoords, mask);
- break;
- }
- result = noErr;
- break;
- case kEventMouseUp:
-
- switch(button)
- {
- case kEventMouseButtonPrimary:
- if(mSimulatedRightClick)
- {
- // End of simulated right click
- mSimulatedRightClick = false;
- mCallbacks->handleRightMouseUp(this, outCoords, mask);
- }
- else
- {
- mCallbacks->handleMouseUp(this, outCoords, mask);
- }
- break;
- case kEventMouseButtonSecondary:
- mCallbacks->handleRightMouseUp(this, outCoords, mask);
- break;
-
- case kEventMouseButtonTertiary:
- mCallbacks->handleMiddleMouseUp(this, outCoords, mask);
- break;
- }
- result = noErr;
- break;
-
- case kEventMouseWheelMoved:
- {
- static S32 z_delta = 0;
-
- z_delta += wheelDelta;
-
- if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta)
- {
- mCallbacks->handleScrollWheel(this, -z_delta / WHEEL_DELTA);
- z_delta = 0;
- }
- }
- result = noErr;
- break;
-
- case kEventMouseDragged:
- case kEventMouseMoved:
- mCallbacks->handleMouseMove(this, outCoords, mask);
- result = noErr;
- break;
-
- }
- }
- }
- break;
-
- case kEventClassWindow:
- switch(evtKind)
- {
- case kEventWindowActivated:
- if (mTSMDocument)
- {
- ActivateTSMDocument(mTSMDocument);
- }
- mCallbacks->handleFocus(this);
- break;
- case kEventWindowDeactivated:
- if (mTSMDocument)
- {
- DeactivateTSMDocument(mTSMDocument);
- }
- mCallbacks->handleFocusLost(this);
- break;
-
- case kEventWindowBoundsChanging:
- {
- // This is where we would constrain move/resize to a particular screen
-
- const S32 MIN_WIDTH = mMinWindowWidth;
- const S32 MIN_HEIGHT = mMinWindowHeight;
-
- Rect currentBounds;
- Rect previousBounds;
-
- GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &currentBounds);
- GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds);
-
- // Put an offset into window un-maximize operation since the kEventWindowGetIdealSize
- // event only allows the specification of size and not position.
- if (mMaximized)
- {
- short leftOffset = mPreviousWindowRect.left - currentBounds.left;
- currentBounds.left += leftOffset;
- currentBounds.right += leftOffset;
-
- short topOffset = mPreviousWindowRect.top - currentBounds.top;
- currentBounds.top += topOffset;
- currentBounds.bottom += topOffset;
- }
- else
- {
- // Store off the size for future un-maximize operations
- mPreviousWindowRect = previousBounds;
- }
-
- if ((currentBounds.right - currentBounds.left) < MIN_WIDTH)
- {
- currentBounds.right = currentBounds.left + MIN_WIDTH;
- }
-
- if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT)
- {
- currentBounds.bottom = currentBounds.top + MIN_HEIGHT;
- }
-
- SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &currentBounds);
- result = noErr;
- }
- break;
-
- case kEventWindowBoundsChanged:
- {
- // Get new window bounds
- Rect newBounds;
- GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds);
-
- // Get previous window bounds
- Rect oldBounds;
- GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds);
-
- // Determine if the new size is larger than the old
- bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left));
- newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top));
-
- // Check to see if this is a zoom event (+ button on window pane)
- unsigned int eventParams;
- GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams);
- bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0);
-
- // Maximized flag is if zoom event and increasing window size
- mMaximized = (isZoomEvent && newBoundsLarger);
-
- aglUpdateContext(mContext);
-
- mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
- }
- break;
-
- case kEventWindowGetIdealSize:
- // Only recommend a new ideal size when un-maximizing
- if (mMaximized == TRUE)
- {
- Point nonMaximizedSize;
-
- nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top;
- nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left;
-
- SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize);
- result = noErr;
- }
- break;
-
- case kEventWindowClose:
- if(mCallbacks->handleCloseRequest(this))
- {
- // Get the app to initiate cleanup.
- mCallbacks->handleQuit(this);
- // The app is responsible for calling destroyWindow when done with GL
- }
- result = noErr;
- break;
-
- case kEventWindowHidden:
- // llinfos << "LLWindowMacOSX: Deactivating on hide" << llendl;
- mMinimized = TRUE;
- mCallbacks->handleActivate(this, false);
- // result = noErr;
- break;
-
- case kEventWindowShown:
- // llinfos << "LLWindowMacOSX: Activating on show" << llendl;
- mMinimized = FALSE;
- mCallbacks->handleActivate(this, true);
- // result = noErr;
- break;
-
- case kEventWindowCollapsed:
- // llinfos << "LLWindowMacOSX: Deactivating on collapse" << llendl;
- mMinimized = TRUE;
- mCallbacks->handleActivate(this, false);
- // result = noErr;
- break;
-
- case kEventWindowExpanded:
- // llinfos << "LLWindowMacOSX: Activating on expand" << llendl;
- mMinimized = FALSE;
- mCallbacks->handleActivate(this, true);
- // result = noErr;
- break;
-
- case kEventWindowGetClickActivation:
- // BringToFront(mWindow);
- // result = noErr;
- break;
- }
- break;
-
- case kEventClassTSMDocumentAccess:
- if (mPreeditor)
- {
- switch(evtKind)
- {
-
- case kEventTSMDocumentAccessGetLength:
- {
- // Return the number of UTF-16 units in the text, excluding those for preedit.
-
- S32 preedit, preedit_length;
- mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getPreeditString();
- const CFIndex length = wstring_utf16_length(text, 0, preedit)
- + wstring_utf16_length(text, preedit + preedit_length, text.length());
- result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length);
- }
- break;
-
- case kEventTSMDocumentAccessGetSelectedRange:
- {
- // Return the selected range, excluding preedit.
- // In our preeditor, preedit and selection are exclusive, so,
- // when it has a preedit, there is no selection and the
- // insertion point is on the preedit that corrupses into the
- // beginning of the preedit when the preedit was removed.
-
- S32 preedit, preedit_length;
- mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getPreeditString();
-
- CFRange range;
- if (preedit_length)
- {
- range.location = wstring_utf16_length(text, 0, preedit);
- range.length = 0;
- }
- else
- {
- S32 selection, selection_length;
- mPreeditor->getSelectionRange(&selection, &selection_length);
- range.location = wstring_utf16_length(text, 0, selection);
- range.length = wstring_utf16_length(text, selection, selection_length);
- }
-
- result = SetEventParameter(event, kEventParamTSMDocAccessReplyCharacterRange, typeCFRange, sizeof(range), &range);
- }
- break;
-
- case kEventTSMDocumentAccessGetCharacters:
- {
- UniChar *target_pointer;
- CFRange range;
- EventParamType param_type;
- if ((result = GetEventParameter(event, kEventParamTSMDocAccessSendCharacterRange,
- typeCFRange, &param_type, sizeof(range), NULL, &range)) == noErr
- && typeCFRange == param_type
- && (result = GetEventParameter(event, kEventParamTSMDocAccessSendCharactersPtr,
- typePtr, &param_type, sizeof(target_pointer), NULL, &target_pointer)) == noErr
- && typePtr == param_type)
- {
- S32 preedit, preedit_length;
- mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getPreeditString();
-
- // The GetCharacters event of TSMDA has a fundamental flaw;
- // An input method need to decide the starting offset and length
- // *before* it actually see the contents, so it is impossible
- // to guarantee the character-aligned access. The event reply
- // has no way to indicate a condition something like "Request
- // was not fulfilled due to unaligned access. Please retry."
- // Any error sent back to the input method stops use of TSMDA
- // entirely during the session...
- // We need to simulate very strictly the behaviour as if the
- // underlying *text engine* holds the contents in UTF-16.
- // I guess this is the reason why Apple repeats saying "all
- // text handling application should use UTF-16." They are
- // trying to _fix_ the flaw by changing the appliations...
- // ... or, domination of UTF-16 in the industry may be a part
- // of the company vision, and Apple is trying to force third
- // party developers to obey their vision. Remember that use
- // of 16 bits per _a_character_ was one of the very fundamental
- // Unicode design policy on its early days (during late 80s)
- // and the original Unicode design was by two Apple employees...
-
- const llutf16string text_utf16
- = wstring_to_utf16str(text, preedit)
- + wstring_to_utf16str(text.substr(preedit + preedit_length));
-
- llassert_always(sizeof(U16) == sizeof(UniChar));
- llassert(0 <= range.location && 0 <= range.length && range.location + range.length <= text_utf16.length());
- memcpy(target_pointer, text_utf16.c_str() + range.location, range.length * sizeof(UniChar));
-
- // Note that result has already been set above.
- }
- }
- break;
-
- }
- }
- break;
- }
- return result;
-}
-
+ // 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)
@@ -2876,7 +1373,7 @@ static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY)
void LLWindowMacOSX::updateCursor()
{
- OSStatus result = noErr;
+ S32 result = 0;
if (mDragOverrideCursor != -1)
{
@@ -2909,11 +1406,11 @@ void LLWindowMacOSX::updateCursor()
{
default:
case UI_CURSOR_ARROW:
- InitCursor();
+ setArrowCursor();
if(mCursorHidden)
{
// Since InitCursor resets the hide level, correct for it here.
- ::HideCursor();
+ hideNSCursor();
}
break;
@@ -2921,12 +1418,12 @@ void LLWindowMacOSX::updateCursor()
// Find out what they look like and replicate them.
// These are essentially correct
- case UI_CURSOR_WAIT: SetThemeCursor(kThemeWatchCursor); break;
- case UI_CURSOR_IBEAM: SetThemeCursor(kThemeIBeamCursor); break;
- case UI_CURSOR_CROSS: SetThemeCursor(kThemeCrossCursor); break;
- case UI_CURSOR_HAND: SetThemeCursor(kThemePointingHandCursor); break;
+ case UI_CURSOR_WAIT: /* Apple purposely doesn't allow us to set the beachball cursor manually. Let NSApp figure out when to do this. */ break;
+ case UI_CURSOR_IBEAM: setIBeamCursor(); break;
+ case UI_CURSOR_CROSS: setCrossCursor(); break;
+ case UI_CURSOR_HAND: setPointingHandCursor(); break;
// case UI_CURSOR_NO: SetThemeCursor(kThemeNotAllowedCursor); break;
- case UI_CURSOR_ARROWCOPY: SetThemeCursor(kThemeCopyArrowCursor); break;
+ case UI_CURSOR_ARROWCOPY: setCopyCursor(); break;
// Double-check these
case UI_CURSOR_NO:
@@ -2969,7 +1466,7 @@ void LLWindowMacOSX::updateCursor()
if(result != noErr)
{
- InitCursor();
+ setArrowCursor();
}
mCurrentCursor = mNextCursor;
@@ -3039,7 +1536,7 @@ void LLWindowMacOSX::hideCursor()
// llinfos << "hideCursor: hiding" << llendl;
mCursorHidden = TRUE;
mHideCursorPermanent = TRUE;
- ::HideCursor();
+ hideNSCursor();
}
else
{
@@ -3056,7 +1553,7 @@ void LLWindowMacOSX::showCursor()
// llinfos << "showCursor: showing" << llendl;
mCursorHidden = FALSE;
mHideCursorPermanent = FALSE;
- ::ShowCursor();
+ showNSCursor();
}
else
{
@@ -3100,24 +1597,6 @@ LLSplashScreenMacOSX::~LLSplashScreenMacOSX()
void LLSplashScreenMacOSX::showImpl()
{
// This code _could_ be used to display a spash screen...
-#if 0
- IBNibRef nib = NULL;
- OSStatus err;
-
- err = CreateNibReference(CFSTR("SecondLife"), &nib);
-
- if(err == noErr)
- {
- CreateWindowFromNib(nib, CFSTR("Splash Screen"), &mWindow);
-
- DisposeNibReference(nib);
- }
-
- if(mWindow != NULL)
- {
- ShowWindow(mWindow);
- }
-#endif
}
void LLSplashScreenMacOSX::updateImpl(const std::string& mesg)
@@ -3127,25 +1606,6 @@ void LLSplashScreenMacOSX::updateImpl(const std::string& mesg)
CFStringRef string = NULL;
string = CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8);
-
- if(string != NULL)
- {
- ControlRef progressText = NULL;
- ControlID id;
- OSStatus err;
-
- id.signature = 'what';
- id.id = 0;
-
- err = GetControlByID(mWindow, &id, &progressText);
- if(err == noErr)
- {
- err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&string);
- Draw1Control(progressText);
- }
-
- CFRelease(string);
- }
}
}
@@ -3154,111 +1614,21 @@ void LLSplashScreenMacOSX::hideImpl()
{
if(mWindow != NULL)
{
- DisposeWindow(mWindow);
mWindow = NULL;
}
}
-
-
S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type)
{
- S32 result = OSBTN_CANCEL;
- SInt16 retval_mac = 1;
- AlertStdCFStringAlertParamRec params;
- CFStringRef errorString = NULL;
- CFStringRef explanationString = NULL;
- DialogRef alert = NULL;
- AlertType alertType = kAlertCautionAlert;
- OSStatus err;
-
- explanationString = CFStringCreateWithCString(NULL, text.c_str(), kCFStringEncodingUTF8);
- errorString = CFStringCreateWithCString(NULL, caption.c_str(), kCFStringEncodingUTF8);
-
- params.version = kStdCFStringAlertVersionOne;
- params.movable = false;
- params.helpButton = false;
- params.defaultText = (CFStringRef)kAlertDefaultOKText;
- params.cancelText = 0;
- params.otherText = 0;
- params.defaultButton = 1;
- params.cancelButton = 0;
- params.position = kWindowDefaultPosition;
- params.flags = 0;
-
- switch(type)
- {
- case OSMB_OK:
- default:
- break;
- case OSMB_OKCANCEL:
- params.cancelText = (CFStringRef)kAlertDefaultCancelText;
- params.cancelButton = 2;
- break;
- case OSMB_YESNO:
- alertType = kAlertNoteAlert;
- params.defaultText = CFSTR("Yes");
- params.cancelText = CFSTR("No");
- params.cancelButton = 2;
- break;
- }
-
- if(gWindowImplementation != NULL)
- gWindowImplementation->beforeDialog();
-
- err = CreateStandardAlert(
- alertType,
- errorString,
- explanationString,
- &params,
- &alert);
-
- if(err == noErr)
- {
- err = RunStandardAlert(
- alert,
- NULL,
- &retval_mac);
- }
-
- if(gWindowImplementation != NULL)
- gWindowImplementation->afterDialog();
-
- switch(type)
- {
- case OSMB_OK:
- case OSMB_OKCANCEL:
- default:
- if(retval_mac == 1)
- result = OSBTN_OK;
- else
- result = OSBTN_CANCEL;
- break;
- case OSMB_YESNO:
- if(retval_mac == 1)
- result = OSBTN_YES;
- else
- result = OSBTN_NO;
- break;
- }
-
- if(errorString != NULL)
- {
- CFRelease(errorString);
- }
-
- if(explanationString != NULL)
- {
- CFRelease(explanationString);
- }
-
- return result;
+ return showAlert(text, caption, type);
}
// Open a URL with the user's default web browser.
// Must begin with protocol identifier.
void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
{
+ // I'm fairly certain that this is all legitimate under Apple's currently supported APIs.
+
bool found = false;
S32 i;
for (i = 0; i < gURLProtocolWhitelistCount; i++)
@@ -3276,7 +1646,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
return;
}
- OSStatus result = noErr;
+ S32 result = 0;
CFURLRef urlRef = NULL;
llinfos << "Opening URL " << escaped_url << llendl;
@@ -3313,7 +1683,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
LLSD LLWindowMacOSX::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();
-
+#if 0
if(mRawKeyEvent)
{
char char_code = 0;
@@ -3335,7 +1705,7 @@ LLSD LLWindowMacOSX::getNativeKeyData()
// This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc)
// cause llsd serialization to create XML that the llsd deserializer won't parse!
std::string unicode;
- OSStatus err = noErr;
+ S32 err = noErr;
EventParamType actualType = typeUTF8Text;
UInt32 actualSize = 0;
char *buffer = NULL;
@@ -3357,7 +1727,7 @@ LLSD LLWindowMacOSX::getNativeKeyData()
#endif
}
-
+#endif
lldebugs << "native key data is: " << result << llendl;
@@ -3367,34 +1737,9 @@ LLSD LLWindowMacOSX::getNativeKeyData()
BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
+ // Is this even used anywhere? Do we really need an OS color picker?
BOOL retval = FALSE;
- OSErr error = noErr;
- NColorPickerInfo info;
-
- memset(&info, 0, sizeof(info));
- info.theColor.color.rgb.red = (UInt16)(*r * 65535.f);
- info.theColor.color.rgb.green = (UInt16)(*g * 65535.f);
- info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f);
- info.placeWhere = kCenterOnMainScreen;
-
- if(gWindowImplementation != NULL)
- gWindowImplementation->beforeDialog();
-
- error = NPickColor(&info);
-
- if(gWindowImplementation != NULL)
- gWindowImplementation->afterDialog();
-
- if (error == noErr)
- {
- retval = info.newColorChosen;
- if (info.newColorChosen)
- {
- *r = ((float) info.theColor.color.rgb.red) / 65535.0;
- *g = ((float) info.theColor.color.rgb.green) / 65535.0;
- *b = ((float) info.theColor.color.rgb.blue) / 65535.0;
- }
- }
+ //S32 error = 0;
return (retval);
}
@@ -3405,44 +1750,8 @@ void *LLWindowMacOSX::getPlatformWindow()
return (void*)mWindow;
}
-void *LLWindowMacOSX::getMediaWindow()
-{
- /*
- Mozilla needs to be initialized with a WindowRef to function properly.
- (There's no good reason for this, since it shouldn't be interacting with our window in any way, but that's another issue.)
- If we're in windowed mode, we _could_ hand it our actual window pointer, but a subsequent switch to fullscreen will destroy that window,
- which trips up Mozilla.
- Instead of using our actual window, we create an invisible window which will persist for the lifetime of the application and pass that to Mozilla.
- This satisfies its deep-seated need to latch onto a WindowRef and solves the issue with switching between fullscreen and windowed modes.
-
- Note that we will never destroy this window (by design!), but since only one will ever be created per run of the application, that's okay.
- */
-
- if(sMediaWindow == NULL)
- {
- Rect window_rect = {100, 100, 200, 200};
-
- sMediaWindow = NewCWindow(
- NULL,
- &window_rect,
- (ConstStr255Param) "\p",
- false, // Create the window invisible.
- zoomDocProc, // Window with a grow box and a zoom box
- kLastWindowOfClass, // create it behind other windows
- false, // no close box
- 0);
- }
-
- return (void*)sMediaWindow;
-}
-
-void LLWindowMacOSX::stopDockTileBounce()
-{
- NMRemove(&mBounceRec);
- mBounceTimer.stop();
-}
-
// get a double value from a dictionary
+/*
static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
{
double double_value;
@@ -3452,7 +1761,7 @@ static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value)) // or if cant convert it
return -1; // fail
return double_value; // otherwise return the long value
-}
+}*/
// get a long value from a dictionary
static long getDictLong (CFDictionaryRef refDict, CFStringRef key)
@@ -3468,8 +1777,8 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key)
void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
{
- ScriptLanguageRecord script_language;
-
+ allowDirectMarkedTextInput(b, mGLView);
+
if (preeditor != mPreeditor && !b)
{
// This condition may occur by a call to
@@ -3480,9 +1789,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
// is not disturbed.
return;
}
-
- UseInputWindow(mTSMDocument, !b);
-
+
// Take care of old and new preeditors.
if (preeditor != mPreeditor || !b)
{
@@ -3495,44 +1802,17 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
}
mPreeditor = (b ? preeditor : NULL);
}
-
+
if (b == mLanguageTextInputAllowed)
{
return;
}
mLanguageTextInputAllowed = b;
-
- if (b)
- {
- if (mTSMScriptCode != smRoman)
- {
- script_language.fScript = mTSMScriptCode;
- script_language.fLanguage = mTSMLangCode;
- SetTextServiceLanguage(&script_language);
- }
- }
- else
- {
- GetTextServiceLanguage(&script_language);
- mTSMScriptCode = script_language.fScript;
- mTSMLangCode = script_language.fLanguage;
- if (mTSMScriptCode != smRoman)
- {
- script_language.fScript = smRoman;
- script_language.fLanguage = langEnglish;
- SetTextServiceLanguage(&script_language);
- }
- }
}
void LLWindowMacOSX::interruptLanguageTextInput()
{
- if (mTSMDocument)
- {
- FixTSMDocument(mTSMDocument);
- }
- // Don't we need to call resetPreedit here?
- // Well, if Apple's TSM document is correct, we don't.
+ commitCurrentPreedit(mGLView);
}
//static
@@ -3543,21 +1823,21 @@ std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
}
// static
-MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers)
+MASK LLWindowMacOSX::modifiersToMask(S16 modifiers)
{
MASK mask = 0;
- if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
- if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
- if(modifiers & optionKey) { mask |= MASK_ALT; }
+ if(modifiers & MAC_SHIFT_KEY) { mask |= MASK_SHIFT; }
+ if(modifiers & (MAC_CMD_KEY | MAC_CTRL_KEY)) { mask |= MASK_CONTROL; }
+ if(modifiers & MAC_ALT_KEY) { mask |= MASK_ALT; }
return mask;
}
#if LL_OS_DRAGDROP_ENABLED
-
-OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
+/*
+S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
void * handlerRefCon, DragRef drag)
{
- OSErr result = noErr;
+ S16 result = 0;
LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
lldebugs << "drag tracking handler, message = " << message << llendl;
@@ -3582,7 +1862,6 @@ OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef
return result;
}
-
OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
DragRef drag)
{
@@ -3590,126 +1869,69 @@ OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefC
return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
}
-
-OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action)
+*/
+void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action)
{
- OSErr result = dragNotAcceptedErr; // overall function result
- OSErr err = noErr; // for local error handling
-
- // Get the mouse position and modifiers of this drag.
- SInt16 modifiers, mouseDownModifiers, mouseUpModifiers;
- ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers);
- MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
+ MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers());
- Point mouse_point;
- // This will return the mouse point in global screen coords
- ::GetDragMouse(drag, &mouse_point, NULL);
- LLCoordScreen screen_coords(mouse_point.h, mouse_point.v);
+ float mouse_point[2];
+ // This will return the mouse point in window coords
+ getCursorPos(mWindow, mouse_point);
+ LLCoordWindow window_coords(mouse_point[0], mouse_point[1]);
LLCoordGL gl_pos;
- convertCoords(screen_coords, &gl_pos);
-
- // Look at the pasteboard and try to extract an URL from it
- PasteboardRef pasteboard;
- if(GetDragPasteboard(drag, &pasteboard) == noErr)
+ convertCoords(window_coords, &gl_pos);
+
+ if(!url.empty())
{
- ItemCount num_items = 0;
- // Treat an error here as an item count of 0
- (void)PasteboardGetItemCount(pasteboard, &num_items);
-
- // Only deal with single-item drags.
- if(num_items == 1)
- {
- PasteboardItemID item_id = NULL;
- CFArrayRef flavors = NULL;
- CFDataRef data = NULL;
-
- err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based.
-
- // Try to extract an URL from the pasteboard
- if(err == noErr)
- {
- err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors);
- }
-
- if(err == noErr)
- {
- if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL))
- {
- // This is an URL.
- err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data);
- }
- else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText))
+ LLWindowCallbacks::DragNDropResult res =
+ mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
+
+ switch (res) {
+ case LLWindowCallbacks::DND_NONE: // No drop allowed
+ if (action == LLWindowCallbacks::DNDA_TRACK)
{
- // This is a string that might be an URL.
- err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data);
+ mDragOverrideCursor = 0;
}
-
- }
-
- if(flavors != NULL)
- {
- CFRelease(flavors);
- }
-
- if(data != NULL)
- {
- std::string url;
- url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data));
- CFRelease(data);
-
- if(!url.empty())
- {
- LLWindowCallbacks::DragNDropResult res =
- mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
-
- switch (res) {
- case LLWindowCallbacks::DND_NONE: // No drop allowed
- if (action == LLWindowCallbacks::DNDA_TRACK)
- {
- mDragOverrideCursor = kThemeNotAllowedCursor;
- }
- else {
- mDragOverrideCursor = -1;
- }
- break;
- case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
- mDragOverrideCursor = kThemePointingHandCursor;
- result = noErr;
- break;
- case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
- mDragOverrideCursor = kThemeCopyArrowCursor;
- result = noErr;
- break;
- case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation:
- mDragOverrideCursor = kThemeAliasArrowCursor;
- result = noErr;
- break;
- default:
- mDragOverrideCursor = -1;
- break;
- }
- // This overrides the cursor being set by setCursor.
- // This is a bit of a hack workaround because lots of areas
- // within the viewer just blindly set the cursor.
- if (mDragOverrideCursor == -1)
- {
- // Restore the cursor
- ECursorType temp_cursor = mCurrentCursor;
- // get around the "setting the same cursor" code in setCursor()
- mCurrentCursor = UI_CURSOR_COUNT;
- setCursor(temp_cursor);
- }
- else {
- // Override the cursor
- SetThemeCursor(mDragOverrideCursor);
- }
-
+ else {
+ mDragOverrideCursor = -1;
}
- }
+ break;
+ case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
+ mDragOverrideCursor = UI_CURSOR_NO;
+ break;
+ case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
+ mDragOverrideCursor = UI_CURSOR_ARROWCOPY;
+ break;
+ default:
+ mDragOverrideCursor = -1;
+ break;
+ }
+ // This overrides the cursor being set by setCursor.
+ // This is a bit of a hack workaround because lots of areas
+ // within the viewer just blindly set the cursor.
+ if (mDragOverrideCursor == -1)
+ {
+ // Restore the cursor
+ ECursorType temp_cursor = mCurrentCursor;
+ // get around the "setting the same cursor" code in setCursor()
+ mCurrentCursor = UI_CURSOR_COUNT;
+ setCursor(temp_cursor);
+ }
+ else {
+ // Override the cursor
+ switch (mDragOverrideCursor) {
+ case 0:
+ setArrowCursor();
+ break;
+ case UI_CURSOR_NO:
+ setNotAllowedCursor();
+ case UI_CURSOR_ARROWCOPY:
+ setCopyCursor();
+ default:
+ break;
+ };
}
}
-
- return result;
}
#endif // LL_OS_DRAGDROP_ENABLED
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index af83b50097..6a6b39e674 100755
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -29,11 +29,12 @@
#include "llwindow.h"
#include "llwindowcallbacks.h"
+#include "llwindowmacosx-objc.h"
#include "lltimer.h"
-#include <Carbon/Carbon.h>
-#include <AGL/agl.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <OpenGL/OpenGL.h>
// AssertMacros.h does bad things.
#include "fix_macros.h"
@@ -106,7 +107,6 @@ public:
/*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
/*virtual*/ void *getPlatformWindow();
- /*virtual*/ void *getMediaWindow();
/*virtual*/ void bringToFront() {};
/*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b);
@@ -117,7 +117,17 @@ public:
// Provide native key event data
/*virtual*/ LLSD getNativeKeyData();
-
+
+ void* getWindow() { return mWindow; }
+ LLWindowCallbacks* getCallbacks() { return mCallbacks; }
+ LLPreeditor* getPreeditor() { return mPreeditor; }
+
+ void updateMouseDeltas(float* deltas);
+ void getMouseDeltas(float* delta);
+
+ void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action);
+
+ bool allowsLanguageInput() { return mLanguageTextInputAllowed; }
protected:
LLWindowMacOSX(LLWindowCallbacks* callbacks,
@@ -153,40 +163,33 @@ protected:
BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync);
void destroyContext();
void setupFailure(const std::string& text, const std::string& caption, U32 type);
- static pascal OSStatus staticEventHandler (EventHandlerCallRef myHandler, EventRef event, void* userData);
- static pascal Boolean staticMoveEventComparator( EventRef event, void* data);
- OSStatus eventHandler (EventHandlerCallRef myHandler, EventRef event);
void adjustCursorDecouple(bool warpingMouse = false);
- void stopDockTileBounce();
- static MASK modifiersToMask(SInt16 modifiers);
+ static MASK modifiersToMask(S16 modifiers);
#if LL_OS_DRAGDROP_ENABLED
- static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
- void * handlerRefCon, DragRef theDrag);
- static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
- OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action);
+
+ //static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
+ //static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
+
+
#endif // LL_OS_DRAGDROP_ENABLED
//
// Platform specific variables
//
- WindowRef mWindow;
- AGLContext mContext;
- AGLPixelFormat mPixelFormat;
+
+ // Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise.
+ NSWindowRef mWindow;
+ GLViewRef mGLView;
+ CGLContextObj mContext;
+ CGLPixelFormatObj mPixelFormat;
CGDirectDisplayID mDisplay;
- CFDictionaryRef mOldDisplayMode;
- EventLoopTimerRef mTimer;
- EventHandlerUPP mEventHandlerUPP;
- EventHandlerRef mGlobalHandlerRef;
- EventHandlerRef mWindowHandlerRef;
- EventComparatorUPP mMoveEventCampartorUPP;
- Rect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
- Rect mPreviousWindowRect; // Save previous window for un-maximize event
- Str255 mWindowTitle;
+ LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
+ std::string mWindowTitle;
double mOriginalAspectRatio;
BOOL mSimulatedRightClick;
- UInt32 mLastModifiers;
+ U32 mLastModifiers;
BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing.
// Used to allow event processing when putting up dialogs in fullscreen mode.
BOOL mCursorDecoupled;
@@ -201,25 +204,16 @@ protected:
U32 mFSAASamples;
BOOL mForceRebuild;
- S32 mDragOverrideCursor;
-
- F32 mBounceTime;
- NMRec mBounceRec;
- LLTimer mBounceTimer;
+ S32 mDragOverrideCursor;
// Input method management through Text Service Manager.
- TSMDocumentID mTSMDocument;
BOOL mLanguageTextInputAllowed;
- ScriptCode mTSMScriptCode;
- LangCode mTSMLangCode;
LLPreeditor* mPreeditor;
static BOOL sUseMultGL;
friend class LLWindowManager;
- static WindowRef sMediaWindow;
- EventRef mRawKeyEvent;
-
+
};
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 43c0090993..30f5526500 100755
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -159,9 +159,8 @@ LLWinImm LLWinImm::sTheInstance;
LLWinImm::LLWinImm() : mHImmDll(NULL)
{
// Check system metrics
- if ( !GetSystemMetrics( SM_DBCSENABLED ) )
+ if ( !GetSystemMetrics( SM_IMMENABLED ) )
return;
-
mHImmDll = LoadLibraryA("Imm32");
if (mHImmDll != NULL)
@@ -3500,19 +3499,11 @@ void LLWindowWin32::updateLanguageTextInputArea()
void LLWindowWin32::interruptLanguageTextInput()
{
- if (mPreeditor)
+ if (mPreeditor && LLWinImm::isAvailable())
{
- if (LLWinImm::isAvailable())
- {
- HIMC himc = LLWinImm::getContext(mWindowHandle);
- LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
- LLWinImm::releaseContext(mWindowHandle, himc);
- }
-
- // Win32 document says there will be no composition string
- // after NI_COMPOSITIONSTR returns. The following call to
- // resetPreedit should be a NOP unless IME goes mad...
- mPreeditor->resetPreedit();
+ HIMC himc = LLWinImm::getContext(mWindowHandle);
+ LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ LLWinImm::releaseContext(mWindowHandle, himc);
}
}
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 666c03e9ff..97fad7feb0 100755
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -132,14 +132,14 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
LLSD initial, const std::string& comment,
- bool persist, bool hidefromsettingseditor)
+ ePersist persist, bool hidefromsettingseditor)
: mName(name),
mComment(comment),
mType(type),
mPersist(persist),
mHideFromSettingsEditor(hidefromsettingseditor)
{
- if (mPersist && mComment.empty())
+ if ((persist != PERSIST_NO) && mComment.empty())
{
llerrs << "Must supply a comment for control " << mName << llendl;
}
@@ -260,7 +260,7 @@ void LLControlVariable::setDefaultValue(const LLSD& value)
}
}
-void LLControlVariable::setPersist(bool state)
+void LLControlVariable::setPersist(ePersist state)
{
mPersist = state;
}
@@ -292,10 +292,29 @@ void LLControlVariable::resetToDefault(bool fire_signal)
}
}
-bool LLControlVariable::isSaveValueDefault()
-{
- return (mValues.size() == 1)
- || ((mValues.size() > 1) && llsd_compare(mValues[1], mValues[0]));
+bool LLControlVariable::shouldSave(bool nondefault_only)
+{
+ // This method is used to decide whether we should save a given
+ // variable. Two of the three values of mPersist are easy.
+ if (mPersist == PERSIST_NO)
+ return false;
+
+ if (mPersist == PERSIST_ALWAYS)
+ return true;
+
+ // PERSIST_NONDFT
+ // If caller doesn't need us to filter, just save.
+ if (! nondefault_only)
+ return true;
+
+ // PERSIST_NONDFT: caller only wants us to save this variable if its value
+ // differs from default.
+ if (isDefault()) // never been altered
+ return false;
+
+ // We've set at least one other value: compare it to default. Save only if
+ // they differ.
+ return ! llsd_compare(getSaveValue(), getDefault());
}
LLSD LLControlVariable::getSaveValue() const
@@ -355,12 +374,12 @@ std::string LLControlGroup::typeEnumToString(eControlType typeenum)
return mTypeString[typeenum];
}
-BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor)
+LLControlVariable* LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor)
{
LLControlVariable* existing_control = getControl(name);
if (existing_control)
{
- if (persist && existing_control->isType(type))
+ if ((persist != LLControlVariable::PERSIST_NO) && existing_control->isType(type))
{
if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val))
{
@@ -372,68 +391,68 @@ BOOL LLControlGroup::declareControl(const std::string& name, eControlType type,
}
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 TRUE;
+ return existing_control;
}
// if not, create the control and add it to the name table
LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor);
mNameTable[name] = control;
- return TRUE;
+ return control;
}
-BOOL LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
}
-BOOL LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_S32, initial_val, comment, persist);
}
-BOOL LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_F32, initial_val, comment, persist);
}
-BOOL LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
}
-BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_STRING, initial_val, comment, persist);
}
-BOOL LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
}
-BOOL LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
}
-BOOL LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
}
-BOOL LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist )
+LLControlVariable* LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
{
return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
}
-BOOL LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist )
+LLControlVariable* LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
{
return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
}
-BOOL LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist )
+LLControlVariable* LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
{
return declareControl(name, TYPE_LLSD, initial_val, comment, persist);
}
@@ -611,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;
}
@@ -631,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;
}
@@ -649,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;
@@ -664,11 +683,11 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
switch(declare_as)
{
case TYPE_COL4:
- declareColor4(name, LLColor4::white, LLStringUtil::null, NO_PERSIST);
+ declareColor4(name, LLColor4::white, LLStringUtil::null, LLControlVariable::PERSIST_NO);
break;
case TYPE_STRING:
default:
- declareString(name, LLStringUtil::null, LLStringUtil::null, NO_PERSIST);
+ declareString(name, LLStringUtil::null, LLStringUtil::null, LLControlVariable::PERSIST_NO);
break;
}
}
@@ -803,23 +822,14 @@ 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;
}
-
- if( control && control->isPersisted() )
+ else if( control->shouldSave(nondefault_only) )
{
- if (!(nondefault_only && (control->isSaveValueDefault())))
- {
- settings[iter->first]["Type"] = typeEnumToString(control->type());
- settings[iter->first]["Comment"] = control->getComment();
- settings[iter->first]["Value"] = control->getSaveValue();
- ++num_saved;
- }
- else
- {
- // Debug spam
- // llinfos << "Skipping " << control->getName() << llendl;
- }
+ settings[iter->first]["Type"] = typeEnumToString(control->type());
+ settings[iter->first]["Comment"] = control->getComment();
+ settings[iter->first]["Value"] = control->getSaveValue();
+ ++num_saved;
}
}
llofstream file;
@@ -828,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;
@@ -846,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);
}
@@ -862,13 +872,14 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
{
- bool persist = true;
+ LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT;
std::string const & name = itr->first;
LLSD const & control_map = itr->second;
if(control_map.has("Persist"))
{
- persist = control_map["Persist"].asInteger();
+ persist = control_map["Persist"].asInteger()?
+ LLControlVariable::PERSIST_NONDFT : LLControlVariable::PERSIST_NO;
}
// Sometimes we want to use the settings system to provide cheap persistence, but we
@@ -887,6 +898,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
LLControlVariable* existing_control = getControl(name);
if(existing_control)
{
+ // set_default_values is true when we're loading the initial,
+ // immutable files from app_settings, e.g. settings.xml.
if(set_default_values)
{
// Override all previously set properties of this control.
@@ -908,6 +921,9 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
}
else if(existing_control->isPersisted())
{
+ // save_values is specifically false for (e.g.)
+ // SessionSettingsFile and UserSessionSettingsFile -- in other
+ // words, for a file that's supposed to be transient.
existing_control->setValue(control_map["Value"], save_values);
}
// *NOTE: If not persisted and not setting defaults,
@@ -915,6 +931,39 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
}
else
{
+ // We've never seen this control before. Either we're loading up
+ // the initial set of default settings files (set_default_values)
+ // -- or we're loading user settings last saved by a viewer that
+ // supports a superset of the variables we know.
+ // CHOP-962: if we're loading an unrecognized user setting, make
+ // sure we save it later. If you try an experimental viewer, tweak
+ // a new setting, briefly revert to an old viewer, then return to
+ // the new one, we don't want the old viewer to discard the
+ // setting you changed.
+ if (! set_default_values)
+ {
+ // Using PERSIST_ALWAYS insists that saveToFile() (which calls
+ // LLControlVariable::shouldSave()) must save this control
+ // variable regardless of its value. We can safely set this
+ // LLControlVariable persistent because the 'persistent' flag
+ // is not itself persisted!
+ persist = LLControlVariable::PERSIST_ALWAYS;
+ // We want to mention unrecognized user settings variables
+ // (e.g. from a newer version of the viewer) in the log. But
+ // we also arrive here for Boolean variables generated by
+ // the notifications subsystem when the user checks "Don't
+ // show me this again." These aren't declared in settings.xml;
+ // they're actually named for the notification they suppress.
+ // We don't want to mention those. Apologies, this is a bit of
+ // a hack: we happen to know that user settings go into an
+ // LLControlGroup whose name is "Global".
+ if (getKey() == "Global")
+ {
+ LL_INFOS("LLControlGroup") << "preserving unrecognized " << getKey()
+ << " settings variable " << name << LL_ENDL;
+ }
+ }
+
declareControl(name,
typeStringToEnum(control_map["Type"].asString()),
control_map["Value"],
@@ -923,10 +972,11 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
hidefromsettingseditor
);
}
-
+
++validitems;
}
+ LL_DEBUGS("Settings") << "Loaded " << validitems << " settings from " << filename << LL_ENDL;
return validitems;
}
@@ -963,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);
@@ -1224,19 +1274,19 @@ LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const st
LLColor4 color(sd);
if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
{
- llwarns << "Color " << control_name << " red value out of range: " << color << llendl;
+ LL_WARNS("Settings") << "Color " << control_name << " red value out of range: " << color << LL_ENDL;
}
else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
{
- llwarns << "Color " << control_name << " green value out of range: " << color << llendl;
+ LL_WARNS("Settings") << "Color " << control_name << " green value out of range: " << color << LL_ENDL;
}
else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
{
- llwarns << "Color " << control_name << " blue value out of range: " << color << llendl;
+ LL_WARNS("Settings") << "Color " << control_name << " blue value out of range: " << color << LL_ENDL;
}
else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
{
- llwarns << "Color " << control_name << " alpha value out of range: " << color << llendl;
+ LL_WARNS("Settings") << "Color " << control_name << " alpha value out of range: " << color << LL_ENDL;
}
return LLColor4(sd);
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index ee7d1d50b7..e1f9be80dd 100755
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -72,8 +72,6 @@ class LLVector3d;
class LLColor4;
class LLColor3;
-const BOOL NO_PERSIST = FALSE;
-
typedef enum e_control_type
{
TYPE_U32 = 0,
@@ -100,21 +98,28 @@ public:
typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t;
+ enum ePersist
+ {
+ PERSIST_NO, // don't save this var
+ PERSIST_NONDFT, // save this var if differs from default
+ PERSIST_ALWAYS // save this var even if has default value
+ };
+
private:
std::string mName;
std::string mComment;
eControlType mType;
- bool mPersist;
+ ePersist mPersist;
bool mHideFromSettingsEditor;
std::vector<LLSD> mValues;
-
+
commit_signal_t mCommitSignal;
validate_signal_t mValidateSignal;
public:
LLControlVariable(const std::string& name, eControlType type,
LLSD initial, const std::string& comment,
- bool persist = true, bool hidefromsettingseditor = false);
+ ePersist persist = PERSIST_NONDFT, bool hidefromsettingseditor = false);
virtual ~LLControlVariable();
@@ -131,8 +136,8 @@ public:
validate_signal_t* getValidateSignal() { return &mValidateSignal; }
bool isDefault() { return (mValues.size() == 1); }
- bool isSaveValueDefault();
- bool isPersisted() { return mPersist; }
+ bool shouldSave(bool nondefault_only);
+ bool isPersisted() { return mPersist != PERSIST_NO; }
bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
LLSD get() const { return getValue(); }
LLSD getValue() const { return mValues.back(); }
@@ -142,7 +147,7 @@ public:
void set(const LLSD& val) { setValue(val); }
void setValue(const LLSD& value, bool saved_value = TRUE);
void setDefaultValue(const LLSD& value);
- void setPersist(bool state);
+ void setPersist(ePersist);
void setHiddenFromSettingsEditor(bool hide);
void setComment(const std::string& comment);
@@ -207,19 +212,19 @@ public:
virtual void apply(const std::string& name, LLControlVariable* control) = 0;
};
void applyToAll(ApplyFunctor* func);
-
- BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE);
- BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, BOOL persist = TRUE);
- BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE);
+
+ LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor = FALSE);
+ LLControlVariable* declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareS32(const std::string& name, S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareF32(const std::string& name, F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
std::string getString(const std::string& name);
std::string getText(const std::string& name);
@@ -368,7 +373,7 @@ private:
init_value = convert_to_llsd(default_value);
if(type < TYPE_COUNT)
{
- group.declareControl(name, type, init_value, comment, FALSE);
+ group.declareControl(name, type, init_value, comment, LLControlVariable::PERSIST_NO);
return true;
}
return false;
diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp
index ede81956ec..c273773c9b 100755
--- a/indra/llxml/tests/llcontrol_test.cpp
+++ b/indra/llxml/tests/llcontrol_test.cpp
@@ -128,7 +128,11 @@ namespace tut
template<> template<>
void control_group_t::test<3>()
{
- int results = mCG->loadFromFile(mTestConfigFile.c_str());
+ // Pass default_values = true. This tells loadFromFile() we're loading
+ // a default settings file that declares variables, rather than a user
+ // settings file. When loadFromFile() encounters an unrecognized user
+ // settings variable, it forcibly preserves it (CHOP-962).
+ int results = mCG->loadFromFile(mTestConfigFile.c_str(), true);
LLControlVariable* control = mCG->getControl("TestSetting");
LLSD new_value = 13;
control->setValue(new_value, FALSE);
diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l
index 1bb38bbf65..1c9f50202d 100755
--- a/indra/lscript/lscript_compile/indra.l
+++ b/indra/lscript/lscript_compile/indra.l
@@ -336,6 +336,8 @@ int yyerror(const char *fmt, ...);
"ATTACH_HUD_BOTTOM_LEFT" { count(); yylval.ival = 36; return(INTEGER_CONSTANT); }
"ATTACH_HUD_BOTTOM" { count(); yylval.ival = 37; return(INTEGER_CONSTANT); }
"ATTACH_HUD_BOTTOM_RIGHT" { count(); yylval.ival = 38; return(INTEGER_CONSTANT); }
+"ATTACH_NECK" { count(); yylval.ival = 39; return(INTEGER_CONSTANT); }
+"ATTACH_AVATAR_CENTER" { count(); yylval.ival = 40; return(INTEGER_CONSTANT); }
"LAND_LEVEL" { count(); yylval.ival = E_LANDBRUSH_LEVEL; return(INTEGER_CONSTANT); }
"LAND_RAISE" { count(); yylval.ival = E_LANDBRUSH_RAISE; return(INTEGER_CONSTANT); }
diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp
new file mode 100644
index 0000000000..f533d47b18
--- /dev/null
+++ b/indra/mac_updater/mac_updater.cpp
@@ -0,0 +1,1266 @@
+/**
+ * @file mac_updater.cpp
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2006&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 <boost/format.hpp>
+
+#include <libgen.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <curl/curl.h>
+#include <pthread.h>
+
+#include "llerror.h"
+#include "lltimer.h"
+#include "lldir.h"
+#include "llfile.h"
+
+#include "llstring.h"
+
+#include <Carbon/Carbon.h>
+
+#include "llerrorcontrol.h"
+
+#if LL_DARWIN
+// FSPathMakeRef, FSObjectCopy, deprecations...
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+enum
+{
+ kEventClassCustom = 'Cust',
+ kEventCustomProgress = 'Prog',
+ kEventParamCustomCurValue = 'Cur ',
+ kEventParamCustomMaxValue = 'Max ',
+ kEventParamCustomText = 'Text',
+ kEventCustomDone = 'Done',
+};
+
+WindowRef gWindow = NULL;
+EventHandlerRef gEventHandler = NULL;
+OSStatus gFailure = noErr;
+Boolean gCancelled = false;
+
+const char *gUpdateURL;
+const char *gProductName;
+const char *gBundleID;
+const char *gDmgFile;
+const char *gMarkerPath;
+
+void *updatethreadproc(void*);
+
+pthread_t updatethread;
+
+OSStatus setProgress(int cur, int max)
+{
+ OSStatus err;
+ ControlRef progressBar = NULL;
+ ControlID id;
+
+ id.signature = 'prog';
+ id.id = 0;
+
+ err = GetControlByID(gWindow, &id, &progressBar);
+ if(err == noErr)
+ {
+ Boolean indeterminate;
+
+ if(max == 0)
+ {
+ indeterminate = true;
+ err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate);
+ }
+ else
+ {
+ double percentage = (double)cur / (double)max;
+ SetControlMinimum(progressBar, 0);
+ SetControlMaximum(progressBar, 100);
+ SetControlValue(progressBar, (SInt16)(percentage * 100));
+
+ indeterminate = false;
+ err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate);
+
+ Draw1Control(progressBar);
+ }
+ }
+
+ return(err);
+}
+
+OSStatus setProgressText(CFStringRef text)
+{
+ OSStatus err;
+ ControlRef progressText = NULL;
+ ControlID id;
+
+ id.signature = 'what';
+ id.id = 0;
+
+ err = GetControlByID(gWindow, &id, &progressText);
+ if(err == noErr)
+ {
+ err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&text);
+ Draw1Control(progressText);
+ }
+
+ return(err);
+}
+
+OSStatus sendProgress(long cur, long max, CFStringRef text = NULL)
+{
+ OSStatus result;
+ EventRef evt;
+
+ result = CreateEvent(
+ NULL,
+ kEventClassCustom,
+ kEventCustomProgress,
+ 0,
+ kEventAttributeNone,
+ &evt);
+
+ // This event needs to be targeted at the window so it goes to the window's handler.
+ if(result == noErr)
+ {
+ EventTargetRef target = GetWindowEventTarget(gWindow);
+ result = SetEventParameter (
+ evt,
+ kEventParamPostTarget,
+ typeEventTargetRef,
+ sizeof(target),
+ &target);
+ }
+
+ if(result == noErr)
+ {
+ result = SetEventParameter (
+ evt,
+ kEventParamCustomCurValue,
+ typeLongInteger,
+ sizeof(cur),
+ &cur);
+ }
+
+ if(result == noErr)
+ {
+ result = SetEventParameter (
+ evt,
+ kEventParamCustomMaxValue,
+ typeLongInteger,
+ sizeof(max),
+ &max);
+ }
+
+ if(result == noErr)
+ {
+ if(text != NULL)
+ {
+ result = SetEventParameter (
+ evt,
+ kEventParamCustomText,
+ typeCFStringRef,
+ sizeof(text),
+ &text);
+ }
+ }
+
+ if(result == noErr)
+ {
+ // Send the event
+ PostEventToQueue(
+ GetMainEventQueue(),
+ evt,
+ kEventPriorityStandard);
+
+ }
+
+ return(result);
+}
+
+OSStatus sendDone(void)
+{
+ OSStatus result;
+ EventRef evt;
+
+ result = CreateEvent(
+ NULL,
+ kEventClassCustom,
+ kEventCustomDone,
+ 0,
+ kEventAttributeNone,
+ &evt);
+
+ // This event needs to be targeted at the window so it goes to the window's handler.
+ if(result == noErr)
+ {
+ EventTargetRef target = GetWindowEventTarget(gWindow);
+ result = SetEventParameter (
+ evt,
+ kEventParamPostTarget,
+ typeEventTargetRef,
+ sizeof(target),
+ &target);
+ }
+
+ if(result == noErr)
+ {
+ // Send the event
+ PostEventToQueue(
+ GetMainEventQueue(),
+ evt,
+ kEventPriorityStandard);
+
+ }
+
+ return(result);
+}
+
+OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
+{
+ OSStatus result = eventNotHandledErr;
+ OSStatus err;
+ UInt32 evtClass = GetEventClass(event);
+ UInt32 evtKind = GetEventKind(event);
+
+ if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
+ {
+ HICommand cmd;
+ err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
+
+ if(err == noErr)
+ {
+ switch(cmd.commandID)
+ {
+ case kHICommandCancel:
+ gCancelled = true;
+// QuitAppModalLoopForWindow(gWindow);
+ result = noErr;
+ break;
+ }
+ }
+ }
+ else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomProgress))
+ {
+ // Request to update the progress dialog
+ long cur = 0;
+ long max = 0;
+ CFStringRef text = NULL;
+ (void) GetEventParameter(event, kEventParamCustomCurValue, typeLongInteger, NULL, sizeof(cur), NULL, &cur);
+ (void) GetEventParameter(event, kEventParamCustomMaxValue, typeLongInteger, NULL, sizeof(max), NULL, &max);
+ (void) GetEventParameter(event, kEventParamCustomText, typeCFStringRef, NULL, sizeof(text), NULL, &text);
+
+ err = setProgress(cur, max);
+ if(err == noErr)
+ {
+ if(text != NULL)
+ {
+ setProgressText(text);
+ }
+ }
+
+ result = noErr;
+ }
+ else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomDone))
+ {
+ // We're done. Exit the modal loop.
+ QuitAppModalLoopForWindow(gWindow);
+ result = noErr;
+ }
+
+ return(result);
+}
+
+#if 0
+size_t curl_download_callback(void *data, size_t size, size_t nmemb,
+ void *user_data)
+{
+ S32 bytes = size * nmemb;
+ char *cdata = (char *) data;
+ for (int i =0; i < bytes; i += 1)
+ {
+ gServerResponse.append(cdata[i]);
+ }
+ return bytes;
+}
+#endif
+
+int curl_progress_callback_func(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow)
+{
+ int max = (int)(dltotal / 1024.0);
+ int cur = (int)(dlnow / 1024.0);
+ sendProgress(cur, max);
+
+ if(gCancelled)
+ return(1);
+
+ return(0);
+}
+
+int parse_args(int argc, char **argv)
+{
+ int j;
+
+ for (j = 1; j < argc; j++)
+ {
+ if ((!strcmp(argv[j], "-url")) && (++j < argc))
+ {
+ gUpdateURL = argv[j];
+ }
+ else if ((!strcmp(argv[j], "-name")) && (++j < argc))
+ {
+ gProductName = argv[j];
+ }
+ else if ((!strcmp(argv[j], "-bundleid")) && (++j < argc))
+ {
+ gBundleID = argv[j];
+ }
+ else if ((!strcmp(argv[j], "-dmg")) && (++j < argc))
+ {
+ gDmgFile = argv[j];
+ }
+ else if ((!strcmp(argv[j], "-marker")) && (++j < argc))
+ {
+ gMarkerPath = argv[j];;
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ // We assume that all the logs we're looking for reside on the current drive
+ gDirUtilp->initAppDirs("SecondLife");
+
+ LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+
+ // Rename current log file to ".old"
+ std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log.old");
+ std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log");
+ LLFile::rename(log_file.c_str(), old_log_file.c_str());
+
+ // Set the log file to updater.log
+ LLError::logToFile(log_file);
+
+ /////////////////////////////////////////
+ //
+ // Process command line arguments
+ //
+ gUpdateURL = NULL;
+ gProductName = NULL;
+ gBundleID = NULL;
+ gDmgFile = NULL;
+ gMarkerPath = NULL;
+ parse_args(argc, argv);
+ if ((gUpdateURL == NULL) && (gDmgFile == NULL))
+ {
+ llinfos << "Usage: mac_updater -url <url> | -dmg <dmg file> [-name <product_name>] [-program <program_name>]" << llendl;
+ exit(1);
+ }
+ else
+ {
+ llinfos << "Update url is: " << gUpdateURL << llendl;
+ if (gProductName)
+ {
+ llinfos << "Product name is: " << gProductName << llendl;
+ }
+ else
+ {
+ gProductName = "Second Life";
+ }
+ if (gBundleID)
+ {
+ llinfos << "Bundle ID is: " << gBundleID << llendl;
+ }
+ else
+ {
+ gBundleID = "com.secondlife.indra.viewer";
+ }
+ }
+
+ llinfos << "Starting " << gProductName << " Updater" << llendl;
+
+ // Real UI...
+ OSStatus err;
+ IBNibRef nib = NULL;
+
+ err = CreateNibReference(CFSTR("AutoUpdater"), &nib);
+
+ char windowTitle[MAX_PATH]; /* Flawfinder: ignore */
+ snprintf(windowTitle, sizeof(windowTitle), "%s Updater", gProductName);
+ CFStringRef windowTitleRef = NULL;
+ windowTitleRef = CFStringCreateWithCString(NULL, windowTitle, kCFStringEncodingUTF8);
+
+ if(err == noErr)
+ {
+ err = CreateWindowFromNib(nib, CFSTR("Updater"), &gWindow);
+ }
+
+ if (err == noErr)
+ {
+ err = SetWindowTitleWithCFString(gWindow, windowTitleRef);
+ }
+ CFRelease(windowTitleRef);
+
+ if(err == noErr)
+ {
+ // Set up an event handler for the window.
+ EventTypeSpec handlerEvents[] =
+ {
+ { kEventClassCommand, kEventCommandProcess },
+ { kEventClassCustom, kEventCustomProgress },
+ { kEventClassCustom, kEventCustomDone }
+ };
+ InstallStandardEventHandler(GetWindowEventTarget(gWindow));
+ InstallWindowEventHandler(
+ gWindow,
+ NewEventHandlerUPP(dialogHandler),
+ GetEventTypeCount (handlerEvents),
+ handlerEvents,
+ 0,
+ &gEventHandler);
+ }
+
+ if(err == noErr)
+ {
+ ShowWindow(gWindow);
+ SelectWindow(gWindow);
+ }
+
+ if(err == noErr)
+ {
+ pthread_create(&updatethread,
+ NULL,
+ &updatethreadproc,
+ NULL);
+
+ }
+
+ if(err == noErr)
+ {
+ RunAppModalLoopForWindow(gWindow);
+ }
+
+ void *threadresult;
+
+ pthread_join(updatethread, &threadresult);
+
+ if(!gCancelled && (gFailure != noErr))
+ {
+ // Something went wrong. Since we always just tell the user to download a new version, we don't really care what.
+ AlertStdCFStringAlertParamRec params;
+ SInt16 retval_mac = 1;
+ DialogRef alert = NULL;
+ OSStatus err;
+
+ params.version = kStdCFStringAlertVersionOne;
+ params.movable = false;
+ params.helpButton = false;
+ params.defaultText = (CFStringRef)kAlertDefaultOKText;
+ params.cancelText = 0;
+ params.otherText = 0;
+ params.defaultButton = 1;
+ params.cancelButton = 0;
+ params.position = kWindowDefaultPosition;
+ params.flags = 0;
+
+ err = CreateStandardAlert(
+ kAlertStopAlert,
+ CFSTR("Error"),
+ CFSTR("An error occurred while updating Second Life. Please download the latest version from www.secondlife.com."),
+ &params,
+ &alert);
+
+ if(err == noErr)
+ {
+ err = RunStandardAlert(
+ alert,
+ NULL,
+ &retval_mac);
+ }
+
+ if(gMarkerPath != 0)
+ {
+ // Create a install fail marker that can be used by the viewer to
+ // detect install problems.
+ std::ofstream stream(gMarkerPath);
+ if(stream) stream << -1;
+ }
+ exit(-1);
+ } else {
+ exit(0);
+ }
+
+ if(gWindow != NULL)
+ {
+ DisposeWindow(gWindow);
+ }
+
+ if(nib != NULL)
+ {
+ DisposeNibReference(nib);
+ }
+
+ return 0;
+}
+
+bool isDirWritable(FSRef &dir)
+{
+ bool result = false;
+
+ // Test for a writable directory by creating a directory, then deleting it again.
+ // This is kinda lame, but will pretty much always give the right answer.
+
+ OSStatus err = noErr;
+ char temp[PATH_MAX] = ""; /* Flawfinder: ignore */
+
+ err = FSRefMakePath(&dir, (UInt8*)temp, sizeof(temp));
+
+ if(err == noErr)
+ {
+ strncat(temp, "/.test_XXXXXX", (sizeof(temp) - strlen(temp)) - 1);
+
+ if(mkdtemp(temp) != NULL)
+ {
+ // We were able to make the directory. This means the directory is writable.
+ result = true;
+
+ // Clean up.
+ rmdir(temp);
+ }
+ }
+
+#if 0
+ // This seemed like a good idea, but won't tell us if we're on a volume mounted read-only.
+ UInt8 perm;
+ err = FSGetUserPrivilegesPermissions(&targetParentRef, &perm, NULL);
+ if(err == noErr)
+ {
+ if(perm & kioACUserNoMakeChangesMask)
+ {
+ // Parent directory isn't writable.
+ llinfos << "Target parent directory not writable." << llendl;
+ err = -1;
+ replacingTarget = false;
+ }
+ }
+#endif
+
+ return result;
+}
+
+static std::string HFSUniStr255_to_utf8str(const HFSUniStr255* src)
+{
+ llutf16string string16((U16*)&(src->unicode), src->length);
+ std::string result = utf16str_to_utf8str(string16);
+ return result;
+}
+
+int restoreObject(const char* aside, const char* target, const char* path, const char* object)
+{
+ char source[PATH_MAX] = ""; /* Flawfinder: ignore */
+ char dest[PATH_MAX] = ""; /* Flawfinder: ignore */
+ snprintf(source, sizeof(source), "%s/%s/%s", aside, path, object);
+ snprintf(dest, sizeof(dest), "%s/%s", target, path);
+ FSRef sourceRef;
+ FSRef destRef;
+ OSStatus err;
+ err = FSPathMakeRef((UInt8 *)source, &sourceRef, NULL);
+ if(err != noErr) return false;
+ err = FSPathMakeRef((UInt8 *)dest, &destRef, NULL);
+ if(err != noErr) return false;
+
+ llinfos << "Copying " << source << " to " << dest << llendl;
+
+ err = FSCopyObjectSync(
+ &sourceRef,
+ &destRef,
+ NULL,
+ NULL,
+ kFSFileOperationOverwrite);
+
+ if(err != noErr) return false;
+ return true;
+}
+
+// Replace any mention of "Second Life" with the product name.
+void filterFile(const char* filename)
+{
+ char temp[PATH_MAX] = ""; /* Flawfinder: ignore */
+ // First copy the target's version, so we can run it through sed.
+ snprintf(temp, sizeof(temp), "cp '%s' '%s.tmp'", filename, filename);
+ system(temp); /* Flawfinder: ignore */
+
+ // Now run it through sed.
+ snprintf(temp, sizeof(temp),
+ "sed 's/Second Life/%s/g' '%s.tmp' > '%s'", gProductName, filename, filename);
+ system(temp); /* Flawfinder: ignore */
+}
+
+static bool isFSRefViewerBundle(FSRef *targetRef)
+{
+ bool result = false;
+ CFURLRef targetURL = NULL;
+ CFBundleRef targetBundle = NULL;
+ CFStringRef targetBundleID = NULL;
+ CFStringRef sourceBundleID = NULL;
+
+ targetURL = CFURLCreateFromFSRef(NULL, targetRef);
+
+ if(targetURL == NULL)
+ {
+ llinfos << "Error creating target URL." << llendl;
+ }
+ else
+ {
+ targetBundle = CFBundleCreate(NULL, targetURL);
+ }
+
+ if(targetBundle == NULL)
+ {
+ llinfos << "Failed to create target bundle." << llendl;
+ }
+ else
+ {
+ targetBundleID = CFBundleGetIdentifier(targetBundle);
+ }
+
+ if(targetBundleID == NULL)
+ {
+ llinfos << "Couldn't retrieve target bundle ID." << llendl;
+ }
+ else
+ {
+ sourceBundleID = CFStringCreateWithCString(NULL, gBundleID, kCFStringEncodingUTF8);
+ if(CFStringCompare(sourceBundleID, targetBundleID, 0) == kCFCompareEqualTo)
+ {
+ // This is the bundle we're looking for.
+ result = true;
+ }
+ else
+ {
+ llinfos << "Target bundle ID mismatch." << llendl;
+ }
+ }
+
+ // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released.
+ if(targetURL != NULL)
+ CFRelease(targetURL);
+ if(targetBundle != NULL)
+ CFRelease(targetBundle);
+
+ return result;
+}
+
+// Search through the directory specified by 'parent' for an item that appears to be a Second Life viewer.
+static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app)
+{
+ FSIterator iterator;
+ bool found = false;
+
+ OSErr err = FSOpenIterator( parent, kFSIterateFlat, &iterator );
+ if(!err)
+ {
+ do
+ {
+ ItemCount actualObjects = 0;
+ Boolean containerChanged = false;
+ FSCatalogInfo info;
+ FSRef ref;
+ HFSUniStr255 unicodeName;
+ err = FSGetCatalogInfoBulk(
+ iterator,
+ 1,
+ &actualObjects,
+ &containerChanged,
+ kFSCatInfoNodeFlags,
+ &info,
+ &ref,
+ NULL,
+ &unicodeName );
+
+ if(actualObjects == 0)
+ break;
+
+ if(!err)
+ {
+ // Call succeeded and not done with the iteration.
+ std::string name = HFSUniStr255_to_utf8str(&unicodeName);
+
+ llinfos << "Considering \"" << name << "\"" << llendl;
+
+ if(info.nodeFlags & kFSNodeIsDirectoryMask)
+ {
+ // This is a directory. See if it's a .app
+ if(name.find(".app") != std::string::npos)
+ {
+ // Looks promising. Check to see if it has the right bundle identifier.
+ if(isFSRefViewerBundle(&ref))
+ {
+ llinfos << name << " is the one" << llendl;
+ // This is the one. Return it.
+ *app = ref;
+ found = true;
+ break;
+ } else {
+ llinfos << name << " is not the bundle we are looking for; move along" << llendl;
+ }
+
+ }
+ }
+ }
+ }
+ while(!err);
+
+ llinfos << "closing the iterator" << llendl;
+
+ FSCloseIterator(iterator);
+
+ llinfos << "closed" << llendl;
+ }
+
+ if(!err && !found)
+ err = fnfErr;
+
+ return err;
+}
+
+void *updatethreadproc(void*)
+{
+ char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */
+ FSRef tempDirRef;
+ char temp[PATH_MAX] = ""; /* Flawfinder: ignore */
+ // *NOTE: This buffer length is used in a scanf() below.
+ char deviceNode[1024] = ""; /* Flawfinder: ignore */
+ LLFILE *downloadFile = NULL;
+ OSStatus err;
+ ProcessSerialNumber psn;
+ char target[PATH_MAX] = ""; /* Flawfinder: ignore */
+ FSRef targetRef;
+ FSRef targetParentRef;
+ FSVolumeRefNum targetVol;
+ FSRef trashFolderRef;
+ Boolean replacingTarget = false;
+
+ memset(&tempDirRef, 0, sizeof(tempDirRef));
+ memset(&targetRef, 0, sizeof(targetRef));
+ memset(&targetParentRef, 0, sizeof(targetParentRef));
+
+ try
+ {
+ // Attempt to get a reference to the Second Life application bundle containing this updater.
+ // Any failures during this process will cause us to default to updating /Applications/Second Life.app
+ {
+ FSRef myBundle;
+
+ err = GetCurrentProcess(&psn);
+ if(err == noErr)
+ {
+ err = GetProcessBundleLocation(&psn, &myBundle);
+ }
+
+ if(err == noErr)
+ {
+ // Sanity check: Make sure the name of the item referenced by targetRef is "Second Life.app".
+ FSRefMakePath(&myBundle, (UInt8*)target, sizeof(target));
+
+ llinfos << "Updater bundle location: " << target << llendl;
+ }
+
+ // Our bundle should be in Second Life.app/Contents/Resources/AutoUpdater.app
+ // so we need to go up 3 levels to get the path to the main application bundle.
+ if(err == noErr)
+ {
+ err = FSGetCatalogInfo(&myBundle, kFSCatInfoNone, NULL, NULL, NULL, &targetRef);
+ }
+ if(err == noErr)
+ {
+ err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef);
+ }
+ if(err == noErr)
+ {
+ err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef);
+ }
+
+ // And once more to get the parent of the target
+ if(err == noErr)
+ {
+ err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetParentRef);
+ }
+
+ if(err == noErr)
+ {
+ FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target));
+ llinfos << "Path to target: " << target << llendl;
+ }
+
+ // Sanity check: make sure the target is a bundle with the right identifier
+ if(err == noErr)
+ {
+ // Assume the worst...
+ err = -1;
+
+ if(isFSRefViewerBundle(&targetRef))
+ {
+ // This is the bundle we're looking for.
+ err = noErr;
+ replacingTarget = true;
+ }
+ }
+
+ // Make sure the target's parent directory is writable.
+ if(err == noErr)
+ {
+ if(!isDirWritable(targetParentRef))
+ {
+ // Parent directory isn't writable.
+ llinfos << "Target parent directory not writable." << llendl;
+ err = -1;
+ replacingTarget = false;
+ }
+ }
+
+ if(err != noErr)
+ {
+ Boolean isDirectory;
+ llinfos << "Target search failed, defaulting to /Applications/" << gProductName << ".app." << llendl;
+
+ // Set up the parent directory
+ err = FSPathMakeRef((UInt8*)"/Applications", &targetParentRef, &isDirectory);
+ if((err != noErr) || (!isDirectory))
+ {
+ // We're so hosed.
+ llinfos << "Applications directory not found, giving up." << llendl;
+ throw 0;
+ }
+
+ snprintf(target, sizeof(target), "/Applications/%s.app", gProductName);
+
+ memset(&targetRef, 0, sizeof(targetRef));
+ err = FSPathMakeRef((UInt8*)target, &targetRef, NULL);
+ if(err == fnfErr)
+ {
+ // This is fine, just means we're not replacing anything.
+ err = noErr;
+ replacingTarget = false;
+ }
+ else
+ {
+ replacingTarget = true;
+ }
+
+ // Make sure the target's parent directory is writable.
+ if(err == noErr)
+ {
+ if(!isDirWritable(targetParentRef))
+ {
+ // Parent directory isn't writable.
+ llinfos << "Target parent directory not writable." << llendl;
+ err = -1;
+ replacingTarget = false;
+ }
+ }
+
+ }
+
+ // If we haven't fixed all problems by this point, just bail.
+ if(err != noErr)
+ {
+ llinfos << "Unable to pick a target, giving up." << llendl;
+ throw 0;
+ }
+ }
+
+ // Find the volID of the volume the target resides on
+ {
+ FSCatalogInfo info;
+ err = FSGetCatalogInfo(
+ &targetParentRef,
+ kFSCatInfoVolume,
+ &info,
+ NULL,
+ NULL,
+ NULL);
+
+ if(err != noErr)
+ throw 0;
+
+ targetVol = info.volume;
+ }
+
+ // Find the temporary items and trash folders on that volume.
+ err = FSFindFolder(
+ targetVol,
+ kTrashFolderType,
+ true,
+ &trashFolderRef);
+
+ if(err != noErr)
+ throw 0;
+
+#if 0 // *HACK for DEV-11935 see below for details.
+
+ FSRef tempFolderRef;
+
+ err = FSFindFolder(
+ targetVol,
+ kTemporaryFolderType,
+ true,
+ &tempFolderRef);
+
+ if(err != noErr)
+ throw 0;
+
+ err = FSRefMakePath(&tempFolderRef, (UInt8*)temp, sizeof(temp));
+
+ if(err != noErr)
+ throw 0;
+
+#else
+
+ // *HACK for DEV-11935 the above kTemporaryFolderType query was giving
+ // back results with path names that seem to be too long to be used as
+ // mount points. I suspect this incompatibility was introduced in the
+ // Leopard 10.5.2 update, but I have not verified this.
+ char const HARDCODED_TMP[] = "/tmp";
+ strncpy(temp, HARDCODED_TMP, sizeof(HARDCODED_TMP));
+
+#endif // 0 *HACK for DEV-11935
+
+ // Skip downloading the file if the dmg was passed on the command line.
+ std::string dmgName;
+ if(gDmgFile != NULL) {
+ dmgName = basename((char *)gDmgFile);
+ char * dmgDir = dirname((char *)gDmgFile);
+ strncpy(tempDir, dmgDir, sizeof(tempDir));
+ err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL);
+ if(err != noErr) throw 0;
+ chdir(tempDir);
+ goto begin_install;
+ } else {
+ // Continue on to download file.
+ dmgName = "SecondLife.dmg";
+ }
+
+
+ strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1);
+ if(mkdtemp(temp) == NULL)
+ {
+ throw 0;
+ }
+
+ strncpy(tempDir, temp, sizeof(tempDir));
+ temp[sizeof(tempDir) - 1] = '\0';
+
+ llinfos << "tempDir is " << tempDir << llendl;
+
+ err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL);
+
+ if(err != noErr)
+ throw 0;
+
+ chdir(tempDir);
+
+ snprintf(temp, sizeof(temp), "SecondLife.dmg");
+
+ downloadFile = LLFile::fopen(temp, "wb"); /* Flawfinder: ignore */
+ if(downloadFile == NULL)
+ {
+ throw 0;
+ }
+
+ {
+ CURL *curl = curl_easy_init();
+
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback);
+ curl_easy_setopt(curl, CURLOPT_FILE, downloadFile);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func);
+ curl_easy_setopt(curl, CURLOPT_URL, gUpdateURL);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+
+ sendProgress(0, 1, CFSTR("Downloading..."));
+
+ CURLcode result = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+
+ if(gCancelled)
+ {
+ llinfos << "User cancel, bailing out."<< llendl;
+ throw 0;
+ }
+
+ if(result != CURLE_OK)
+ {
+ llinfos << "Error " << result << " while downloading disk image."<< llendl;
+ throw 0;
+ }
+
+ fclose(downloadFile);
+ downloadFile = NULL;
+ }
+
+ begin_install:
+ sendProgress(0, 0, CFSTR("Mounting image..."));
+ LLFile::mkdir("mnt", 0700);
+
+ // NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder,
+ // but if our cleanup fails, this makes it much harder for the user to unmount the image.
+ std::string mountOutput;
+ boost::format cmdFormat("hdiutil attach %s -mountpoint mnt");
+ cmdFormat % dmgName;
+ FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */
+
+ if(mounter == NULL)
+ {
+ llinfos << "Failed to mount disk image, exiting."<< llendl;
+ throw 0;
+ }
+
+ // We need to scan the output from hdiutil to find the device node it uses to attach the disk image.
+ // If we don't have this information, we can't detach it later.
+ while(mounter != NULL)
+ {
+ size_t len = fread(temp, 1, sizeof(temp)-1, mounter);
+ temp[len] = 0;
+ mountOutput.append(temp);
+ if(len < sizeof(temp)-1)
+ {
+ // End of file or error.
+ int result = pclose(mounter);
+ if(result != 0)
+ {
+ // NOTE: We used to abort here, but pclose() started returning
+ // -1, possibly when the size of the DMG passed a certain point
+ llinfos << "Unexpected result closing pipe: " << result << llendl;
+ }
+ mounter = NULL;
+ }
+ }
+
+ if(!mountOutput.empty())
+ {
+ const char *s = mountOutput.c_str();
+ const char *prefix = "/dev/";
+ char *sub = strstr(s, prefix);
+
+ if(sub != NULL)
+ {
+ sub += strlen(prefix); /* Flawfinder: ignore */
+ sscanf(sub, "%1023s", deviceNode); /* Flawfinder: ignore */
+ }
+ }
+
+ if(deviceNode[0] != 0)
+ {
+ llinfos << "Disk image attached on /dev/" << deviceNode << llendl;
+ }
+ else
+ {
+ llinfos << "Disk image device node not found!" << llendl;
+ throw 0;
+ }
+
+ // Get an FSRef to the new application on the disk image
+ FSRef sourceRef;
+ FSRef mountRef;
+ snprintf(temp, sizeof(temp), "%s/mnt", tempDir);
+
+ llinfos << "Disk image mount point is: " << temp << llendl;
+
+ err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL);
+ if(err != noErr)
+ {
+ llinfos << "Couldn't make FSRef to disk image mount point." << llendl;
+ throw 0;
+ }
+
+ sendProgress(0, 0, CFSTR("Searching for the app bundle..."));
+ err = findAppBundleOnDiskImage(&mountRef, &sourceRef);
+ if(err != noErr)
+ {
+ llinfos << "Couldn't find application bundle on mounted disk image." << llendl;
+ throw 0;
+ }
+ else
+ {
+ llinfos << "found the bundle." << llendl;
+ }
+
+ sendProgress(0, 0, CFSTR("Preparing to copy files..."));
+
+ FSRef asideRef;
+ char aside[MAX_PATH]; /* Flawfinder: ignore */
+
+ // this will hold the name of the destination target
+ CFStringRef appNameRef;
+
+ if(replacingTarget)
+ {
+ // Get the name of the target we're replacing
+ HFSUniStr255 appNameUniStr;
+ err = FSGetCatalogInfo(&targetRef, 0, NULL, &appNameUniStr, NULL, NULL);
+ if(err != noErr)
+ throw 0;
+ appNameRef = FSCreateStringFromHFSUniStr(NULL, &appNameUniStr);
+
+ // Move aside old version (into work directory)
+ err = FSMoveObject(&targetRef, &tempDirRef, &asideRef);
+ if(err != noErr)
+ {
+ llwarns << "failed to move aside old version (error code " <<
+ err << ")" << llendl;
+ throw 0;
+ }
+
+ // Grab the path for later use.
+ err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside));
+ }
+ else
+ {
+ // Construct the name of the target based on the product name
+ char appName[MAX_PATH]; /* Flawfinder: ignore */
+ snprintf(appName, sizeof(appName), "%s.app", gProductName);
+ appNameRef = CFStringCreateWithCString(NULL, appName, kCFStringEncodingUTF8);
+ }
+
+ sendProgress(0, 0, CFSTR("Copying files..."));
+
+ llinfos << "Starting copy..." << llendl;
+
+ // Copy the new version from the disk image to the target location.
+ err = FSCopyObjectSync(
+ &sourceRef,
+ &targetParentRef,
+ appNameRef,
+ &targetRef,
+ kFSFileOperationDefaultOptions);
+
+ // Grab the path for later use.
+ err = FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target));
+ if(err != noErr)
+ throw 0;
+
+ llinfos << "Copy complete. Target = " << target << llendl;
+
+ if(err != noErr)
+ {
+ // Something went wrong during the copy. Attempt to put the old version back and bail.
+ (void)FSDeleteObject(&targetRef);
+ if(replacingTarget)
+ {
+ (void)FSMoveObject(&asideRef, &targetParentRef, NULL);
+ }
+ throw 0;
+ }
+ else
+ {
+ // The update has succeeded. Clear the cache directory.
+
+ sendProgress(0, 0, CFSTR("Clearing cache..."));
+
+ llinfos << "Clearing cache..." << llendl;
+
+ gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*");
+
+ llinfos << "Clear complete." << llendl;
+
+ }
+ }
+ catch(...)
+ {
+ if(!gCancelled)
+ if(gFailure == noErr)
+ gFailure = -1;
+ }
+
+ // Failures from here on out are all non-fatal and not reported.
+ sendProgress(0, 3, CFSTR("Cleaning up..."));
+
+ // Close disk image file if necessary
+ if(downloadFile != NULL)
+ {
+ llinfos << "Closing download file." << llendl;
+
+ fclose(downloadFile);
+ downloadFile = NULL;
+ }
+
+ sendProgress(1, 3);
+ // Unmount image
+ if(deviceNode[0] != 0)
+ {
+ llinfos << "Detaching disk image." << llendl;
+
+ snprintf(temp, sizeof(temp), "hdiutil detach '%s'", deviceNode);
+ system(temp); /* Flawfinder: ignore */
+ }
+
+ sendProgress(2, 3);
+
+ // Move work directory to the trash
+ if(tempDir[0] != 0)
+ {
+ llinfos << "Moving work directory to the trash." << llendl;
+
+ FSRef trashRef;
+ OSStatus err = FSMoveObjectToTrashSync(&tempDirRef, &trashRef, 0);
+ if(err != noErr) {
+ llwarns << "failed to move files to trash, (error code " <<
+ err << ")" << llendl;
+ }
+ }
+
+ if(!gCancelled && !gFailure && (target[0] != 0))
+ {
+ llinfos << "Touching application bundle." << llendl;
+
+ snprintf(temp, sizeof(temp), "touch '%s'", target);
+ system(temp); /* Flawfinder: ignore */
+
+ llinfos << "Launching updated application." << llendl;
+
+ snprintf(temp, sizeof(temp), "open '%s'", target);
+ system(temp); /* Flawfinder: ignore */
+ }
+
+ sendDone();
+
+ return(NULL);
+}
+
+#if LL_DARWIN
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+#endif
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index 24328202cb..2dd97a9ba7 100755
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -232,12 +232,8 @@ private:
mMovieHandle = NULL;
};
- if ( mGWorldHandle )
- {
- DisposeGWorld( mGWorldHandle );
- mGWorldHandle = NULL;
- };
-
+ mGWorldHandle = NULL;
+
setStatus(STATUS_NONE);
return true;
@@ -273,6 +269,7 @@ private:
//std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
}
}
+
// sanitize destination size
Rect dest_rect = rectFromSize(mWidth, mHeight);
@@ -281,12 +278,10 @@ private:
int depth_bits = mDepth * 8;
long rowbytes = mDepth * mTextureWidth;
- GWorldPtr old_gworld_handle = mGWorldHandle;
-
if(mPixels != NULL)
{
// We have pixels. Set up a GWorld pointing at the texture.
- OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
+ OSErr result = QTNewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
if ( noErr != result )
{
// TODO: unrecoverable?? throw exception? return something?
@@ -297,7 +292,7 @@ private:
{
// We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
Rect tempRect = rectFromSize(1, 1);
- OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
+ OSErr result = QTNewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
if ( noErr != result )
{
// TODO: unrecoverable?? throw exception? return something?
@@ -305,14 +300,8 @@ private:
}
}
- SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) );
-
- // If the GWorld was already set up, delete it.
- if(old_gworld_handle != NULL)
- {
- DisposeGWorld( old_gworld_handle );
- }
-
+ SetMovieGWorld( mMovieHandle, mGWorldHandle, NULL );
+
// Set up the movie display matrix
{
// scale movie to fit rect and invert vertically to match opengl image format
@@ -579,28 +568,7 @@ private:
}
};
-
- int getDataWidth() const
- {
- if ( mGWorldHandle )
- {
- int depth = mDepth;
-
- if (depth < 1)
- depth = 1;
-
- // ALWAYS use the row bytes from the PixMap if we have a GWorld because
- // sometimes it's not the same as mMediaDepth * mMediaWidth !
- PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle );
- return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth;
- }
- else
- {
- // TODO : return LLMediaImplCommon::getaDataWidth();
- return 0;
- }
- };
-
+
void seek( F64 time )
{
if ( mMovieController )
diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/webkit/mac_volume_catcher.cpp
index 8a06bb8487..cc94556413 100755
--- a/indra/media_plugins/webkit/mac_volume_catcher.cpp
+++ b/indra/media_plugins/webkit/mac_volume_catcher.cpp
@@ -35,10 +35,13 @@
#include "volume_catcher.h"
-#include <Carbon/Carbon.h>
#include <QuickTime/QuickTime.h>
#include <AudioUnit/AudioUnit.h>
+#if LL_DARWIN
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
struct VolumeCatcherStorage;
class VolumeCatcherImpl
@@ -266,3 +269,6 @@ void VolumeCatcher::pump()
// No periodic tasks are necessary for this implementation.
}
+#if LL_DARWIN
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+#endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 89add3e21f..3a09bc530c 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -229,6 +229,7 @@ set(viewer_SOURCE_FILES
llfloaterfonttest.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
+ llfloatergotoline.cpp
llfloatergroupinvite.cpp
llfloatergroups.cpp
llfloaterhandler.cpp
@@ -812,6 +813,7 @@ set(viewer_HEADER_FILES
llfloaterfonttest.h
llfloatergesture.h
llfloatergodtools.h
+ llfloatergotoline.h
llfloatergroupinvite.h
llfloatergroups.h
llfloaterhandler.h
@@ -1270,6 +1272,11 @@ set_source_files_properties(
if (DARWIN)
LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp)
+ LIST(APPEND viewer_SOURCE_FILES llfilepicker_mac.mm)
+ LIST(APPEND viewer_HEADER_FILES llfilepicker_mac.h)
+
+ # This should be compiled with the viewer.
+ LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm)
find_library(AGL_LIBRARY AGL)
find_library(APPKIT_LIBRARY AppKit)
@@ -1290,7 +1297,7 @@ if (DARWIN)
macview.r
gpu_table.txt
Info-SecondLife.plist
- SecondLife.nib/
+ SecondLife.xib/
# CMake doesn't seem to support Xcode language variants well just yet
English.lproj/InfoPlist.strings
English.lproj/language.txt
@@ -1970,20 +1977,25 @@ if (LINUX)
endif (LINUX)
if (DARWIN)
+ # These all get set with PROPERTIES
set(product "Second Life")
-
+ set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer")
+ set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns")
+ set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer")
+ set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
+ set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife")
+ set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}")
+ set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}")
+ set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007")
+ set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib")
+ set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication")
+
set_target_properties(
${VIEWER_BINARY_NAME}
PROPERTIES
OUTPUT_NAME "${product}"
- MACOSX_BUNDLE_INFO_STRING "Second Life Viewer"
- MACOSX_BUNDLE_ICON_FILE "secondlife.icns"
- MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer"
- MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}"
- MACOSX_BUNDLE_BUNDLE_NAME "Second Life"
- MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}"
- MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}"
- MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007"
+ MACOSX_BUNDLE_INFO_PLIST
+ "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist"
)
configure_file(
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index a19844f11c..9b8136a827 100755
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -5,19 +5,33 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
- <string>Second Life</string>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleGetInfoString</key>
+ <string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
- <string>secondlife.icns</string>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
- <string>com.secondlife.indra.viewer</string>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
+ <key>CFBundleLongVersionString</key>
+ <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
- <string>Second Life</string>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>LSRequiresCarbon</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
@@ -59,9 +73,9 @@
<true/>
</dict>
</array>
- <key>CFBundleVersion</key>
- <string>${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}</string>
- <key>CSResourcesFileMapped</key>
- <true/>
+ <key>NSPrincipalClass</key>
+ <string>${MACOSX_BUNDLE_NSPRINCIPAL_CLASS}</string>
+ <key>NSMainNibFile</key>
+ <string>${MACOSX_BUNDLE_NSMAIN_NIB_FILE}</string>
</dict>
</plist>
diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib
new file mode 100644
index 0000000000..8b99b5a770
--- /dev/null
+++ b/indra/newview/SecondLife.nib
Binary files differ
diff --git a/indra/newview/SecondLife.nib/classes.nib b/indra/newview/SecondLife.nib/classes.nib
deleted file mode 100755
index ea58db1189..0000000000
--- a/indra/newview/SecondLife.nib/classes.nib
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-IBClasses = ();
-IBVersion = 1;
-}
diff --git a/indra/newview/SecondLife.nib/info.nib b/indra/newview/SecondLife.nib/info.nib
deleted file mode 100755
index 1b531de104..0000000000
--- a/indra/newview/SecondLife.nib/info.nib
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>IBDocumentLocation</key>
- <string>85 13 356 240 0 0 1280 1002 </string>
- <key>IBEditorPositions</key>
- <dict>
- <key>29</key>
- <string>27 314 247 44 0 0 1280 1002 </string>
- </dict>
- <key>IBFramework Version</key>
- <string>362.0</string>
- <key>IBOpenObjects</key>
- <array>
- <integer>191</integer>
- </array>
- <key>IBSystem Version</key>
- <string>7D24</string>
- <key>targetFramework</key>
- <string>IBCarbonFramework</string>
-</dict>
-</plist>
diff --git a/indra/newview/SecondLife.nib/objects.xib b/indra/newview/SecondLife.nib/objects.xib
deleted file mode 100755
index b7ff30f2b2..0000000000
--- a/indra/newview/SecondLife.nib/objects.xib
+++ /dev/null
@@ -1,259 +0,0 @@
-<?xml version="1.0" standalone="yes"?>
-<object class="NSIBObjectData">
- <string name="targetFramework">IBCarbonFramework</string>
- <object name="rootObject" class="NSCustomObject" id="1">
- <string name="customClass">NSApplication</string>
- </object>
- <array count="31" name="allObjects">
- <object class="IBCarbonMenu" id="29">
- <string name="title">SecondLife</string>
- <array count="4" name="items">
- <object class="IBCarbonMenuItem" id="182">
- <string name="title">Second Life</string>
- <object name="submenu" class="IBCarbonMenu" id="181">
- <string name="title">Second Life</string>
- <array count="1" name="items">
- <object class="IBCarbonMenuItem" id="183">
- <boolean name="disabled">TRUE</boolean>
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">About Second Life</string>
- <int name="keyEquivalentModifier">0</int>
- <ostype name="command">abou</ostype>
- </object>
- </array>
- <string name="name">_NSAppleMenu</string>
- </object>
- </object>
- <object class="IBCarbonMenuItem" id="127">
- <string name="title">File</string>
- <object name="submenu" class="IBCarbonMenu" id="131">
- <string name="title">File</string>
- </object>
- </object>
- <object class="IBCarbonMenuItem" id="152">
- <string name="title">Edit</string>
- <object name="submenu" class="IBCarbonMenu" id="147">
- <string name="title">Edit</string>
- <array count="10" name="items">
- <object class="IBCarbonMenuItem" id="141">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Undo</string>
- <string name="keyEquivalent">z</string>
- <ostype name="command">undo</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="146">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Redo</string>
- <string name="keyEquivalent">Z</string>
- <ostype name="command">redo</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="142">
- <boolean name="separator">TRUE</boolean>
- </object>
- <object class="IBCarbonMenuItem" id="143">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Cut</string>
- <string name="keyEquivalent">x</string>
- <ostype name="command">cut </ostype>
- </object>
- <object class="IBCarbonMenuItem" id="149">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Copy</string>
- <string name="keyEquivalent">c</string>
- <ostype name="command">copy</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="144">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Paste</string>
- <string name="keyEquivalent">v</string>
- <ostype name="command">past</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="151">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Delete</string>
- <ostype name="command">clea</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="148">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Select All</string>
- <string name="keyEquivalent">a</string>
- <ostype name="command">sall</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="188">
- <boolean name="separator">TRUE</boolean>
- </object>
- <object class="IBCarbonMenuItem" id="187">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Special Characters…</string>
- <ostype name="command">chrp</ostype>
- </object>
- </array>
- </object>
- </object>
- <object class="IBCarbonMenuItem" id="153">
- <string name="title">Window</string>
- <object name="submenu" class="IBCarbonMenu" id="154">
- <string name="title">Window</string>
- <array count="6" name="items">
- <object class="IBCarbonMenuItem" id="155">
- <boolean name="dynamic">TRUE</boolean>
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Minimize Window</string>
- <string name="keyEquivalent">m</string>
- <ostype name="command">mini</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="184">
- <boolean name="dynamic">TRUE</boolean>
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Minimize All Windows</string>
- <string name="keyEquivalent">m</string>
- <int name="keyEquivalentModifier">1572864</int>
- <ostype name="command">mina</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="186">
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Zoom</string>
- <ostype name="command">zoom</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="156">
- <boolean name="separator">TRUE</boolean>
- </object>
- <object class="IBCarbonMenuItem" id="157">
- <boolean name="dynamic">TRUE</boolean>
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Bring All to Front</string>
- <ostype name="command">bfrt</ostype>
- </object>
- <object class="IBCarbonMenuItem" id="185">
- <boolean name="dynamic">TRUE</boolean>
- <boolean name="updateSingleItem">TRUE</boolean>
- <string name="title">Arrange in Front</string>
- <int name="keyEquivalentModifier">1572864</int>
- <ostype name="command">frnt</ostype>
- </object>
- </array>
- <string name="name">_NSWindowsMenu</string>
- </object>
- </object>
- </array>
- <string name="name">_NSMainMenu</string>
- </object>
- <reference idRef="127"/>
- <reference idRef="131"/>
- <reference idRef="141"/>
- <reference idRef="142"/>
- <reference idRef="143"/>
- <reference idRef="144"/>
- <reference idRef="146"/>
- <reference idRef="147"/>
- <reference idRef="148"/>
- <reference idRef="149"/>
- <reference idRef="151"/>
- <reference idRef="152"/>
- <reference idRef="153"/>
- <reference idRef="154"/>
- <reference idRef="155"/>
- <reference idRef="156"/>
- <reference idRef="157"/>
- <reference idRef="181"/>
- <reference idRef="182"/>
- <reference idRef="183"/>
- <reference idRef="184"/>
- <reference idRef="185"/>
- <reference idRef="186"/>
- <reference idRef="187"/>
- <reference idRef="188"/>
- <object class="IBCarbonRootControl" id="190">
- <string name="bounds">0 0 482 694 </string>
- <string name="viewFrame">0 0 694 482 </string>
- <array count="2" name="subviews">
- <object class="IBCarbonButton" id="192">
- <string name="bounds">442 604 462 674 </string>
- <string name="viewFrame">604 442 70 20 </string>
- <string name="title">OK</string>
- <ostype name="command">ok </ostype>
- <object name="layoutInfo" class="IBCarbonHILayoutInfo">
- <int name="bindingBottomKind">2</int>
- <int name="bindingRightKind">2</int>
- </object>
- <int name="buttonType">1</int>
- </object>
- <object class="IBCarbonScrollView" id="201">
- <string name="bounds">20 20 422 674 </string>
- <string name="viewFrame">20 20 654 402 </string>
- <array count="1" name="subviews">
- <object class="IBCarbonTextView" id="200">
- <string name="bounds">20 20 422 659 </string>
- <string name="viewFrame">0 0 639 402 </string>
- <ostype name="controlSignature">text</ostype>
- <int name="fontStyle">5</int>
- <boolean name="readOnly">TRUE</boolean>
- </object>
- </array>
- <boolean name="scrollHorizontally">FALSE</boolean>
- </object>
- </array>
- </object>
- <object class="IBCarbonWindow" id="191">
- <string name="windowRect">84 72 566 766 </string>
- <string name="title">Release Notes</string>
- <reference name="rootControl" idRef="190"/>
- <boolean name="receiveUpdates">FALSE</boolean>
- <boolean name="hasCloseBox">FALSE</boolean>
- <boolean name="hasCollapseBox">FALSE</boolean>
- <boolean name="hasHorizontalZoom">FALSE</boolean>
- <boolean name="isResizable">FALSE</boolean>
- <boolean name="hasVerticalZoom">FALSE</boolean>
- <boolean name="liveResize">TRUE</boolean>
- <boolean name="compositing">TRUE</boolean>
- <int name="carbonWindowClass">4</int>
- <int name="windowPosition">1</int>
- <boolean name="isConstrained">FALSE</boolean>
- </object>
- <reference idRef="192"/>
- <reference idRef="200"/>
- <reference idRef="201"/>
- </array>
- <array count="31" name="allParents">
- <reference idRef="1"/>
- <reference idRef="29"/>
- <reference idRef="127"/>
- <reference idRef="147"/>
- <reference idRef="147"/>
- <reference idRef="147"/>
- <reference idRef="147"/>
- <reference idRef="147"/>
- <reference idRef="152"/>
- <reference idRef="147"/>
- <reference idRef="147"/>
- <reference idRef="147"/>
- <reference idRef="29"/>
- <reference idRef="29"/>
- <reference idRef="153"/>
- <reference idRef="154"/>
- <reference idRef="154"/>
- <reference idRef="154"/>
- <reference idRef="182"/>
- <reference idRef="29"/>
- <reference idRef="181"/>
- <reference idRef="154"/>
- <reference idRef="154"/>
- <reference idRef="154"/>
- <reference idRef="147"/>
- <reference idRef="147"/>
- <reference idRef="191"/>
- <reference idRef="1"/>
- <reference idRef="190"/>
- <reference idRef="201"/>
- <reference idRef="190"/>
- </array>
- <dictionary count="3" name="nameTable">
- <string>Files Owner</string>
- <reference idRef="1"/>
- <string>MenuBar</string>
- <reference idRef="29"/>
- <string>Release Notes</string>
- <reference idRef="191"/>
- </dictionary>
- <unsigned_int name="nextObjectID">202</unsigned_int>
-</object>
diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib
new file mode 100644
index 0000000000..370df6bf5f
--- /dev/null
+++ b/indra/newview/SecondLife.xib
@@ -0,0 +1,1136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
+ <data>
+ <int key="IBDocument.SystemTarget">1060</int>
+ <string key="IBDocument.SystemVersion">12E55</string>
+ <string key="IBDocument.InterfaceBuilderVersion">4457.6</string>
+ <string key="IBDocument.AppKitVersion">1187.39</string>
+ <string key="IBDocument.HIToolboxVersion">626.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="NS.object.0">4457.6</string>
+ </object>
+ <array key="IBDocument.IntegratedClassDependencies">
+ <string>NSCustomObject</string>
+ <string>NSMenu</string>
+ <string>NSMenuItem</string>
+ <string>NSScrollView</string>
+ <string>NSScroller</string>
+ <string>NSTextView</string>
+ <string>NSView</string>
+ <string>NSWindowTemplate</string>
+ </array>
+ <array key="IBDocument.PluginDependencies">
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </array>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+ <integer value="1" key="NS.object.0"/>
+ </object>
+ <array class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
+ <object class="NSCustomObject" id="1021">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSCustomObject" id="1014">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1050">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSMenu" id="649796088">
+ <string key="NSTitle">Main Menu</string>
+ <array class="NSMutableArray" key="NSMenuItems">
+ <object class="NSMenuItem" id="694149608">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Second Life</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <object class="NSCustomResource" key="NSOnImage" id="353210768">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuCheckmark</string>
+ </object>
+ <object class="NSCustomResource" key="NSMixedImage" id="549394948">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuMixedState</string>
+ </object>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="110575045">
+ <string key="NSTitle">Second Life</string>
+ <array class="NSMutableArray" key="NSMenuItems">
+ <object class="NSMenuItem" id="238522557">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">About Second Life</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="304266470">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="609285721">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Preferences…</string>
+ <string key="NSKeyEquiv">,</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="481834944">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="1046388886">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Services</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="752062318">
+ <string key="NSTitle">Services</string>
+ <array class="NSMutableArray" key="NSMenuItems"/>
+ <string key="NSName">_NSServicesMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="646227648">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="755159360">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Hide NewApplication</string>
+ <string key="NSKeyEquiv">h</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="342932134">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Hide Others</string>
+ <string key="NSKeyEquiv">h</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="908899353">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Show All</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="1056857174">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="632727374">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Quit Second Life</string>
+ <string key="NSKeyEquiv">q</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ </array>
+ <string key="NSName">_NSAppleMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="725688984">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Edit</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="701759256">
+ <string key="NSTitle">Edit</string>
+ <array class="NSMutableArray" key="NSMenuItems">
+ <object class="NSMenuItem" id="521487141">
+ <reference key="NSMenu" ref="701759256"/>
+ <string key="NSTitle">Undo</string>
+ <string key="NSKeyEquiv">z</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="668936019">
+ <reference key="NSMenu" ref="701759256"/>
+ <string key="NSTitle">Redo</string>
+ <string key="NSKeyEquiv">Z</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="383018193">
+ <reference key="NSMenu" ref="701759256"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="984623395">
+ <reference key="NSMenu" ref="701759256"/>
+ <string key="NSTitle">Cut</string>
+ <string key="NSKeyEquiv">x</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="656529582">
+ <reference key="NSMenu" ref="701759256"/>
+ <string key="NSTitle">Copy</string>
+ <string key="NSKeyEquiv">c</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="1032676691">
+ <reference key="NSMenu" ref="701759256"/>
+ <string key="NSTitle">Paste</string>
+ <string key="NSKeyEquiv">v</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="538907583">
+ <reference key="NSMenu" ref="701759256"/>
+ <string key="NSTitle">Select All</string>
+ <string key="NSKeyEquiv">a</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ </array>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="713487014">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Window</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="835318025">
+ <string key="NSTitle">Window</string>
+ <array class="NSMutableArray" key="NSMenuItems">
+ <object class="NSMenuItem" id="1011231497">
+ <reference key="NSMenu" ref="835318025"/>
+ <string key="NSTitle">Minimize</string>
+ <string key="NSKeyEquiv">m</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="575023229">
+ <reference key="NSMenu" ref="835318025"/>
+ <string key="NSTitle">Zoom</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="86356408">
+ <reference key="NSMenu" ref="835318025"/>
+ <string key="NSTitle">Enter Full Screen</string>
+ <string key="NSKeyEquiv">f</string>
+ <int key="NSKeyEquivModMask">1310720</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="299356726">
+ <reference key="NSMenu" ref="835318025"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ <object class="NSMenuItem" id="625202149">
+ <reference key="NSMenu" ref="835318025"/>
+ <string key="NSTitle">Bring All to Front</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ </array>
+ <string key="NSName">_NSWindowsMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="391199113">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Help</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="353210768"/>
+ <reference key="NSMixedImage" ref="549394948"/>
+ </object>
+ </array>
+ <string key="NSName">_NSMainMenu</string>
+ </object>
+ <object class="NSCustomObject" id="756173070">
+ <string key="NSClassName">LLAppDelegate</string>
+ </object>
+ <object class="NSWindowTemplate" id="110292814">
+ <int key="NSWindowStyleMask">15</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{196, 240}, {1024, 600}}</string>
+ <int key="NSWTFlags">74974208</int>
+ <string key="NSWindowTitle">Second Life</string>
+ <string key="NSWindowClass">LLNSWindow</string>
+ <nil key="NSViewClass"/>
+ <nil key="NSUserInterfaceItemIdentifier"/>
+ <object class="NSView" key="NSWindowView" id="305280978">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <array class="NSMutableArray" key="NSSubviews"/>
+ <string key="NSFrameSize">{1024, 600}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <string key="NSReuseIdentifierKey">_NS:20</string>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string>
+ <string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+ <string key="NSFrameAutosaveName">Second Life</string>
+ <int key="NSWindowCollectionBehavior">128</int>
+ <bool key="NSWindowIsRestorable">YES</bool>
+ </object>
+ <object class="NSWindowTemplate" id="979091056">
+ <int key="NSWindowStyleMask">31</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{272, 176}, {938, 42}}</string>
+ <int key="NSWTFlags">-1535638528</int>
+ <string key="NSWindowTitle">Input Window</string>
+ <string key="NSWindowClass">LLUserInputWindow</string>
+ <nil key="NSViewClass"/>
+ <nil key="NSUserInterfaceItemIdentifier"/>
+ <object class="NSView" key="NSWindowView" id="1044753903">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <array class="NSMutableArray" key="NSSubviews">
+ <object class="NSScrollView" id="238626476">
+ <reference key="NSNextResponder" ref="1044753903"/>
+ <int key="NSvFlags">256</int>
+ <array class="NSMutableArray" key="NSSubviews">
+ <object class="NSClipView" id="871543330">
+ <reference key="NSNextResponder" ref="238626476"/>
+ <int key="NSvFlags">2322</int>
+ <array class="NSMutableArray" key="NSSubviews">
+ <object class="NSTextView" id="395788163">
+ <reference key="NSNextResponder" ref="871543330"/>
+ <int key="NSvFlags">2322</int>
+ <set class="NSMutableSet" key="NSDragTypes">
+ <string>Apple HTML pasteboard type</string>
+ <string>Apple PDF pasteboard type</string>
+ <string>Apple PICT pasteboard type</string>
+ <string>Apple PNG pasteboard type</string>
+ <string>Apple URL pasteboard type</string>
+ <string>CorePasteboardFlavorType 0x6D6F6F76</string>
+ <string>NSColor pasteboard type</string>
+ <string>NSFilenamesPboardType</string>
+ <string>NSStringPboardType</string>
+ <string>NeXT Encapsulated PostScript v1.2 pasteboard type</string>
+ <string>NeXT RTFD pasteboard type</string>
+ <string>NeXT Rich Text Format v1.0 pasteboard type</string>
+ <string>NeXT TIFF v4.0 pasteboard type</string>
+ <string>NeXT font pasteboard type</string>
+ <string>NeXT ruler pasteboard type</string>
+ <string>WebURLsWithTitlesPboardType</string>
+ <string>public.url</string>
+ </set>
+ <string key="NSFrameSize">{938, 42}</string>
+ <reference key="NSSuperview" ref="871543330"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="339833963"/>
+ <string key="NSReuseIdentifierKey">_NS:13</string>
+ <object class="NSTextContainer" key="NSTextContainer" id="648552009">
+ <object class="NSLayoutManager" key="NSLayoutManager">
+ <object class="NSTextStorage" key="NSTextStorage">
+ <object class="NSMutableString" key="NSString">
+ <characters key="NS.bytes"/>
+ </object>
+ <nil key="NSDelegate"/>
+ </object>
+ <array class="NSMutableArray" key="NSTextContainers">
+ <reference ref="648552009"/>
+ </array>
+ <int key="NSLMFlags">166</int>
+ <nil key="NSDelegate"/>
+ </object>
+ <reference key="NSTextView" ref="395788163"/>
+ <double key="NSWidth">938</double>
+ <int key="NSTCFlags">1</int>
+ </object>
+ <object class="NSTextViewSharedData" key="NSSharedData">
+ <int key="NSFlags">67121127</int>
+ <int key="NSTextCheckingTypes">0</int>
+ <nil key="NSMarkedAttributes"/>
+ <object class="NSColor" key="NSBackgroundColor" id="535647664">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <dictionary key="NSSelectedAttributes">
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">selectedTextBackgroundColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">selectedTextColor</string>
+ <object class="NSColor" key="NSColor" id="835883401">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </dictionary>
+ <reference key="NSInsertionColor" ref="835883401"/>
+ <dictionary key="NSLinkAttributes">
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MCAwIDEAA</bytes>
+ </object>
+ <object class="NSCursor" key="NSCursor">
+ <string key="NSHotSpot">{8, -8}</string>
+ <int key="NSCursorType">13</int>
+ </object>
+ <integer value="1" key="NSUnderline"/>
+ </dictionary>
+ <nil key="NSDefaultParagraphStyle"/>
+ <nil key="NSTextFinder"/>
+ <int key="NSPreferredTextFinderStyle">1</int>
+ </object>
+ <int key="NSTVFlags">6</int>
+ <string key="NSMaxSize">{939, 10000000}</string>
+ <nil key="NSDelegate"/>
+ </object>
+ </array>
+ <string key="NSFrame">{{1, 1}, {938, 42}}</string>
+ <reference key="NSSuperview" ref="238626476"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="395788163"/>
+ <string key="NSReuseIdentifierKey">_NS:11</string>
+ <reference key="NSDocView" ref="395788163"/>
+ <reference key="NSBGColor" ref="535647664"/>
+ <object class="NSCursor" key="NSCursor">
+ <string key="NSHotSpot">{4, 5}</string>
+ <object class="NSImage" key="NSImage">
+ <int key="NSImageFlags">79691776</int>
+ <array key="NSReps">
+ <array>
+ <integer value="5"/>
+ <object class="NSURL">
+ <nil key="NS.base"/>
+ <string key="NS.relative">file://localhost/Applications/Xcode.app/Contents/SharedFrameworks/DVTKit.framework/Resources/DVTIbeamCursor.tiff</string>
+ </object>
+ </array>
+ </array>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ </object>
+ </object>
+ <int key="NScvFlags">4</int>
+ </object>
+ <object class="NSScroller" id="339833963">
+ <reference key="NSNextResponder" ref="238626476"/>
+ <int key="NSvFlags">256</int>
+ <string key="NSFrame">{{923, 1}, {16, 42}}</string>
+ <reference key="NSSuperview" ref="238626476"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <string key="NSReuseIdentifierKey">_NS:83</string>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ <reference key="NSTarget" ref="238626476"/>
+ <string key="NSAction">_doScroller:</string>
+ <double key="NSPercent">0.96666666666666667</double>
+ </object>
+ <object class="NSScroller" id="1067057765">
+ <reference key="NSNextResponder" ref="238626476"/>
+ <int key="NSvFlags">-2147483392</int>
+ <string key="NSFrame">{{-100, -100}, {87, 18}}</string>
+ <reference key="NSSuperview" ref="238626476"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="871543330"/>
+ <string key="NSReuseIdentifierKey">_NS:33</string>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ <int key="NSsFlags">1</int>
+ <reference key="NSTarget" ref="238626476"/>
+ <string key="NSAction">_doScroller:</string>
+ <double key="NSCurValue">1</double>
+ <double key="NSPercent">0.94565218687057495</double>
+ </object>
+ </array>
+ <string key="NSFrame">{{-1, -1}, {940, 44}}</string>
+ <reference key="NSSuperview" ref="1044753903"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="1067057765"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <int key="NSsFlags">133138</int>
+ <reference key="NSVScroller" ref="339833963"/>
+ <reference key="NSHScroller" ref="1067057765"/>
+ <reference key="NSContentView" ref="871543330"/>
+ <double key="NSMinMagnification">0.25</double>
+ <double key="NSMaxMagnification">4</double>
+ <double key="NSMagnification">1</double>
+ </object>
+ </array>
+ <string key="NSFrameSize">{938, 42}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="238626476"/>
+ <string key="NSReuseIdentifierKey">_NS:21</string>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string>
+ <string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+ <bool key="NSWindowIsRestorable">YES</bool>
+ </object>
+ </array>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <array class="NSMutableArray" key="connectionRecords">
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">terminate:</string>
+ <reference key="source" ref="1050"/>
+ <reference key="destination" ref="632727374"/>
+ </object>
+ <int key="connectionID">823</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontStandardAboutPanel:</string>
+ <reference key="source" ref="1021"/>
+ <reference key="destination" ref="238522557"/>
+ </object>
+ <int key="connectionID">142</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1021"/>
+ <reference key="destination" ref="756173070"/>
+ </object>
+ <int key="connectionID">845</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performMiniaturize:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1011231497"/>
+ </object>
+ <int key="connectionID">37</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">arrangeInFront:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="625202149"/>
+ </object>
+ <int key="connectionID">39</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performZoom:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="575023229"/>
+ </object>
+ <int key="connectionID">240</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">hide:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="755159360"/>
+ </object>
+ <int key="connectionID">369</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">hideOtherApplications:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="342932134"/>
+ </object>
+ <int key="connectionID">370</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">unhideAllApplications:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="908899353"/>
+ </object>
+ <int key="connectionID">372</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">cut:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="984623395"/>
+ </object>
+ <int key="connectionID">768</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">paste:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1032676691"/>
+ </object>
+ <int key="connectionID">769</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">undo:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="521487141"/>
+ </object>
+ <int key="connectionID">776</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">copy:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="656529582"/>
+ </object>
+ <int key="connectionID">782</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">selectAll:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="538907583"/>
+ </object>
+ <int key="connectionID">785</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleFullScreen:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="86356408"/>
+ </object>
+ <int key="connectionID">842</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="756173070"/>
+ <reference key="destination" ref="110292814"/>
+ </object>
+ <int key="connectionID">850</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">inputWindow</string>
+ <reference key="source" ref="756173070"/>
+ <reference key="destination" ref="979091056"/>
+ </object>
+ <int key="connectionID">953</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">inputView</string>
+ <reference key="source" ref="756173070"/>
+ <reference key="destination" ref="395788163"/>
+ </object>
+ <int key="connectionID">954</int>
+ </object>
+ </array>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <array key="orderedObjects">
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <array key="object" id="0"/>
+ <reference key="children" ref="1048"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1021"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1014"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1050"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">29</int>
+ <reference key="object" ref="649796088"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="713487014"/>
+ <reference ref="694149608"/>
+ <reference ref="391199113"/>
+ <reference ref="725688984"/>
+ </array>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Main Menu</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">19</int>
+ <reference key="object" ref="713487014"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="835318025"/>
+ </array>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">56</int>
+ <reference key="object" ref="694149608"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="110575045"/>
+ </array>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">103</int>
+ <reference key="object" ref="391199113"/>
+ <array class="NSMutableArray" key="children"/>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">57</int>
+ <reference key="object" ref="110575045"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="238522557"/>
+ <reference ref="755159360"/>
+ <reference ref="908899353"/>
+ <reference ref="632727374"/>
+ <reference ref="646227648"/>
+ <reference ref="609285721"/>
+ <reference ref="481834944"/>
+ <reference ref="304266470"/>
+ <reference ref="1046388886"/>
+ <reference ref="1056857174"/>
+ <reference ref="342932134"/>
+ </array>
+ <reference key="parent" ref="694149608"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">58</int>
+ <reference key="object" ref="238522557"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">134</int>
+ <reference key="object" ref="755159360"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">150</int>
+ <reference key="object" ref="908899353"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">136</int>
+ <reference key="object" ref="632727374"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">144</int>
+ <reference key="object" ref="646227648"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">129</int>
+ <reference key="object" ref="609285721"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">143</int>
+ <reference key="object" ref="481834944"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">236</int>
+ <reference key="object" ref="304266470"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">131</int>
+ <reference key="object" ref="1046388886"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="752062318"/>
+ </array>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">149</int>
+ <reference key="object" ref="1056857174"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">145</int>
+ <reference key="object" ref="342932134"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">130</int>
+ <reference key="object" ref="752062318"/>
+ <reference key="parent" ref="1046388886"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">24</int>
+ <reference key="object" ref="835318025"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="299356726"/>
+ <reference ref="625202149"/>
+ <reference ref="575023229"/>
+ <reference ref="1011231497"/>
+ <reference ref="86356408"/>
+ </array>
+ <reference key="parent" ref="713487014"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">92</int>
+ <reference key="object" ref="299356726"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5</int>
+ <reference key="object" ref="625202149"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">239</int>
+ <reference key="object" ref="575023229"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">23</int>
+ <reference key="object" ref="1011231497"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">711</int>
+ <reference key="object" ref="725688984"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="701759256"/>
+ </array>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">712</int>
+ <reference key="object" ref="701759256"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="521487141"/>
+ <reference ref="668936019"/>
+ <reference ref="383018193"/>
+ <reference ref="984623395"/>
+ <reference ref="656529582"/>
+ <reference ref="1032676691"/>
+ <reference ref="538907583"/>
+ </array>
+ <reference key="parent" ref="725688984"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">716</int>
+ <reference key="object" ref="984623395"/>
+ <reference key="parent" ref="701759256"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">717</int>
+ <reference key="object" ref="656529582"/>
+ <reference key="parent" ref="701759256"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">718</int>
+ <reference key="object" ref="1032676691"/>
+ <reference key="parent" ref="701759256"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">721</int>
+ <reference key="object" ref="538907583"/>
+ <reference key="parent" ref="701759256"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">824</int>
+ <reference key="object" ref="756173070"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">841</int>
+ <reference key="object" ref="86356408"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">828</int>
+ <reference key="object" ref="110292814"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="305280978"/>
+ </array>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">829</int>
+ <reference key="object" ref="305280978"/>
+ <array class="NSMutableArray" key="children"/>
+ <reference key="parent" ref="110292814"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">713</int>
+ <reference key="object" ref="521487141"/>
+ <reference key="parent" ref="701759256"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">714</int>
+ <reference key="object" ref="668936019"/>
+ <reference key="parent" ref="701759256"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">715</int>
+ <reference key="object" ref="383018193"/>
+ <reference key="parent" ref="701759256"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">941</int>
+ <reference key="object" ref="979091056"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="1044753903"/>
+ </array>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">942</int>
+ <reference key="object" ref="1044753903"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="238626476"/>
+ </array>
+ <reference key="parent" ref="979091056"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">943</int>
+ <reference key="object" ref="238626476"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="395788163"/>
+ <reference ref="1067057765"/>
+ <reference ref="339833963"/>
+ </array>
+ <reference key="parent" ref="1044753903"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">944</int>
+ <reference key="object" ref="395788163"/>
+ <reference key="parent" ref="238626476"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">945</int>
+ <reference key="object" ref="1067057765"/>
+ <reference key="parent" ref="238626476"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">946</int>
+ <reference key="object" ref="339833963"/>
+ <reference key="parent" ref="238626476"/>
+ </object>
+ </array>
+ </object>
+ <dictionary class="NSMutableDictionary" key="flattenedProperties">
+ <string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="103.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="129.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="130.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="131.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="134.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="136.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="143.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="144.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="145.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="149.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="150.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="19.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="236.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="239.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="24.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="29.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="56.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="57.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="58.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="711.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="712.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="713.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="714.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="715.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="716.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="717.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="718.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="721.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="824.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="YES" key="828.IBNSWindowAutoPositionCentersHorizontal"/>
+ <boolean value="YES" key="828.IBNSWindowAutoPositionCentersVertical"/>
+ <string key="828.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="YES" key="828.NSWindowTemplate.visibleAtLaunch"/>
+ <string key="829.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="841.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="92.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="941.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="NO" key="941.NSWindowTemplate.visibleAtLaunch"/>
+ <string key="942.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="943.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="944.CustomClassName">LLNonInlineTextView</string>
+ <string key="944.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="945.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="946.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </dictionary>
+ <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+ <nil key="activeLocalization"/>
+ <dictionary class="NSMutableDictionary" key="localizations"/>
+ <nil key="sourceID"/>
+ <int key="maxID">954</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <array class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <object class="IBPartialClassDescription">
+ <string key="className">LLAppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <dictionary class="NSMutableDictionary" key="outlets">
+ <string key="inputView">LLNonInlineTextView</string>
+ <string key="inputWindow">NSWindow</string>
+ <string key="window">LLNSWindow</string>
+ </dictionary>
+ <dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <object class="IBToOneOutletInfo" key="inputView">
+ <string key="name">inputView</string>
+ <string key="candidateClassName">LLNonInlineTextView</string>
+ </object>
+ <object class="IBToOneOutletInfo" key="inputWindow">
+ <string key="name">inputWindow</string>
+ <string key="candidateClassName">NSWindow</string>
+ </object>
+ <object class="IBToOneOutletInfo" key="window">
+ <string key="name">window</string>
+ <string key="candidateClassName">LLNSWindow</string>
+ </object>
+ </dictionary>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/LLAppDelegate.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">LLNSWindow</string>
+ <string key="superclassName">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/LLNSWindow.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">LLNonInlineTextView</string>
+ <string key="superclassName">NSTextView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/LLNonInlineTextView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">LLUserInputWindow</string>
+ <string key="superclassName">NSPanel</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/LLUserInputWindow.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSTextView</string>
+ <dictionary class="NSMutableDictionary" key="actions">
+ <string key="orderFrontSharingServicePicker:">id</string>
+ <string key="toggleQuickLookPreviewPanel:">id</string>
+ </dictionary>
+ <dictionary class="NSMutableDictionary" key="actionInfosByName">
+ <object class="IBActionInfo" key="orderFrontSharingServicePicker:">
+ <string key="name">orderFrontSharingServicePicker:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo" key="toggleQuickLookPreviewPanel:">
+ <string key="name">toggleQuickLookPreviewPanel:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </dictionary>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/NSTextView.h</string>
+ </object>
+ </object>
+ </array>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+ <real value="1060" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+ <integer value="4600" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+ <string key="NSMenuCheckmark">{11, 11}</string>
+ <string key="NSMenuMixedState">{10, 3}</string>
+ </dictionary>
+ </data>
+</archive>
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 4a788a01da..4f2c1d15f6 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.6.3
+3.6.6
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 7ab7787d77..a9f6079630 100755
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -22,7 +22,8 @@
<map>
<key>count</key>
<integer>1</integer>
- <!-- Special case. Not mapped to a setting. -->
+ <key>map-to</key>
+ <string>CmdLineChannel</string>
</map>
<key>console</key>
@@ -96,6 +97,8 @@
0 - low, 1 - medium, 2 - high, 3 - ultra</string>
<key>count</key>
<integer>1</integer>
+ <key>map-to</key>
+ <string>RenderQualityPerformance</string>
</map>
<key>grid</key>
@@ -108,6 +111,16 @@
<string>CmdLineGridChoice</string>
</map>
+ <key>update-service</key>
+ <map>
+ <key>desc</key>
+ <string>Override the url base for the update query.</string>
+ <key>count</key>
+ <integer>1</integer>
+ <key>map-to</key>
+ <string>CmdLineUpdateService</string>
+ </map>
+
<key>help</key>
<map>
<key>desc</key>
@@ -370,7 +383,8 @@
<boolean>true</boolean>
<key>last_option</key>
<boolean>true</boolean>
- <!-- Special case. Not mapped to a setting. -->
+ <key>map-to</key>
+ <string>CmdLineLoginLocation</string>
</map>
<key>url</key>
@@ -381,7 +395,8 @@
<integer>1</integer>
<key>last_option</key>
<boolean>true</boolean>
- <!-- Special case. Not mapped to a setting. -->
+ <key>map-to</key>
+ <string>CmdLineLoginLocation</string>
</map>
<key>usersessionsettings</key>
diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini
index f0d8b77afd..a87310955f 100755
--- a/indra/newview/app_settings/keywords.ini
+++ b/indra/newview/app_settings/keywords.ini
@@ -274,7 +274,8 @@ ATTACH_LLLEG Passed to llAttachToAvatar to attach task to left lower leg
ATTACH_BELLY Passed to llAttachToAvatar to attach task to belly
ATTACH_LEFT_PEC Passed to llAttachToAvatar to attach task to left pectoral
ATTACH_RIGHT_PEC Passed to llAttachToAvatar to attach task to right pectoral
-
+ATTACH_NECK Passed to llAttachToAvatar to attach task to neck
+ATTACH_AVATAR_CENTER Passed to llAttachToAvatar to attach task to avatar center
LAND_LEVEL Passed to llModifyLand to level terrain
LAND_RAISE Passed to llModifyLand to raise terrain
LAND_LOWER Passed to llModifyLand to lower terrain
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 344079b640..0b5c4d962f 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -126,6 +126,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>AnalyzePerformance</key>
+ <map>
+ <key>Comment</key>
+ <string>Request performance analysis for a particular viewer run</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>AnimateTextures</key>
<map>
<key>Comment</key>
@@ -1738,6 +1749,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>CmdLineChannel</key>
+ <map>
+ <key>Comment</key>
+ <string>Command line specified channel name</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
<key>CmdLineDisableVoice</key>
<map>
<key>Comment</key>
@@ -1760,6 +1782,17 @@
<key>Value</key>
<string />
</map>
+ <key>CmdLineUpdateService</key>
+ <map>
+ <key>Comment</key>
+ <string>Override the url base for the update query.</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
<key>CmdLineHelperURI</key>
<map>
<key>Comment</key>
@@ -1784,6 +1817,17 @@
<string />
</array>
</map>
+ <key>CmdLineLoginLocation</key>
+ <map>
+ <key>Comment</key>
+ <string>Startup destination requested on command line</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string/>
+ </map>
<key>ConnectAsGod</key>
<map>
<key>Comment</key>
@@ -1916,6 +1960,17 @@
<key>Value</key>
<integer>262144</integer>
</map>
+ <key>CrashOnStartup</key>
+ <map>
+ <key>Comment</key>
+ <string>User-requested crash on viewer startup</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>CreateToolCopyCenters</key>
<map>
<key>Comment</key>
@@ -2158,6 +2213,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DebugSession</key>
+ <map>
+ <key>Comment</key>
+ <string>Request debugging for a particular viewer session</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DebugShowColor</key>
<map>
<key>Comment</key>
@@ -2972,6 +3038,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DisableCrashLogger</key>
+ <map>
+ <key>Comment</key>
+ <string>Do not send crash report to Linden server</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DisableMouseWarp</key>
<map>
<key>Comment</key>
@@ -3489,16 +3566,27 @@
<key>Value</key>
<real>10.0</real>
</map>
- <key>FilterItemsPerFrame</key>
+ <key>FilterItemsMaxTimePerFrameVisible</key>
<map>
- <key>Comment</key>
- <string>Maximum number of inventory items to match against search filter every frame (lower to increase framerate while searching, higher to improve search speed)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>500</integer>
+ <key>Comment</key>
+ <string>Max time devoted to items filtering per frame for visible inventory listings (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>10</integer>
+ </map>
+ <key>FilterItemsMaxTimePerFrameUnvisible</key>
+ <map>
+ <key>Comment</key>
+ <string>Max time devoted to items filtering per frame for non visible inventory listings (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
</map>
<key>FindLandArea</key>
<map>
@@ -4842,6 +4930,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>
@@ -5217,6 +5315,28 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>LogMetrics</key>
+ <map>
+ <key>Comment</key>
+ <string>Log viewer metrics</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string/>
+ </map>
+ <key>LogPerformance</key>
+ <map>
+ <key>Comment</key>
+ <string>Log performance analysis for a particular viewer run</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>LogTextureNetworkTraffic</key>
<map>
<key>Comment</key>
@@ -6394,6 +6514,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>NoQuickTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable QuickTime for a particular viewer run</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>NoVerifySSLCert</key>
<map>
<key>Comment</key>
@@ -6430,7 +6561,10 @@
<key>NotificationConferenceIMOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Conference IM Notifications.</string>
+ <string>
+ Specifies how the UI responds to Conference IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6441,7 +6575,10 @@
<key>NotificationFriendIMOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Friend IM Notifications.</string>
+ <string>
+ Specifies how the UI responds to Friend IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6452,7 +6589,10 @@
<key>NotificationGroupChatOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Group Chat Notifications.</string>
+ <string>
+ Specifies how the UI responds to Group Chat Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6463,7 +6603,10 @@
<key>NotificationNearbyChatOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Nearby Chat Notifications.</string>
+ <string>
+ Specifies how the UI responds to Nearby Chat Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6474,7 +6617,24 @@
<key>NotificationNonFriendIMOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Non Friend IM Notifications.</string>
+ <string>
+ Specifies how the UI responds to Non Friend IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>toast</string>
+ </map>
+ <key>NotificationObjectIMOptions</key>
+ <map>
+ <key>Comment</key>
+ <string>
+ Specifies how the UI responds to Object IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6987,6 +7147,17 @@
<key>Value</key>
<real>90.0</real>
</map>
+ <key>PlayChatAnim</key>
+ <map>
+ <key>Comment</key>
+ <string>Your avatar plays the chat animation whenever you say, shout or whisper something in nearby chat</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>PlayTypingAnim</key>
<map>
<key>Comment</key>
@@ -7020,6 +7191,72 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>PlaySoundFriendIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when friend's IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundNonFriendIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when non-friend's IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundConferenceIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when conference IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundGroupChatIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when group chat IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundNearbyChatIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when nearby chat IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundObjectIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when IM fom an object received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>PlaySoundNewConversation</key>
<map>
<key>Comment</key>
@@ -8446,6 +8683,18 @@
<integer>0</integer>
</map>
+ <key>RenderDepthOfFieldInEditMode</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether to use depth of field effect when in edit mode</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+
<key>CameraDoFResScale</key>
<map>
<key>Comment</key>
@@ -9642,6 +9891,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>ReplaySession</key>
+ <map>
+ <key>Comment</key>
+ <string>Request replay of previously-recorded pilot file</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RotateRight</key>
<map>
<key>Comment</key>
@@ -10105,6 +10365,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>
@@ -12858,12 +13129,13 @@
<key>UserLoginInfo</key>
<map>
<key>Comment</key>
- <string>Users loging data.</string>
+ <string>User login data.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>LLSD</string>
<key>Value</key>
+ <string/>
</map>
<key>VFSOldSize</key>
<map>
diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml
index bfc09286e3..4a9e522a96 100755
--- a/indra/newview/app_settings/settings_files.xml
+++ b/indra/newview/app_settings/settings_files.xml
@@ -4,6 +4,9 @@
<file name="Global"
file_name="settings.xml"
required="true"/>
+ <file name="Global"
+ file_name="settings_install.xml"
+ required="false"/>
<file name="PerAccount"
file_name="settings_per_account.xml"
required="true"/>
diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml
index 01a70f2671..e660c1a33b 100755
--- a/indra/newview/app_settings/settings_minimal.xml
+++ b/indra/newview/app_settings/settings_minimal.xml
@@ -1 +1,4 @@
-<llsd/> \ No newline at end of file
+<?xml version="1.0"?>
+<llsd>
+ <undef/>
+</llsd>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 590f41283b..636caf5ef3 100755
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -109,18 +109,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
- <key>DisplayDestinationsOnInitialRun</key>
- <map>
- <key>Comment</key>
- <string>Display the destinations guide when a user first launches Second Life.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
+ </map>
<key>LastInventoryInboxActivity</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
index 43ed41a205..efd0d03965 100755
--- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
@@ -45,3 +45,4 @@ mat4 getObjectSkinnedTransform()
return mat;
}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl
index 2cef8f2a5d..a2b4b3b8c8 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl
@@ -24,6 +24,7 @@
*/
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index 97bf49a605..0443b592e2 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -32,6 +32,7 @@ out vec4 frag_color;
//class 1 -- no shadows
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 08583ad0f2..58875ff4ea 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -24,6 +24,7 @@
*/
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 1975b18652..28432dac9a 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -22,8 +22,9 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
@@ -31,6 +32,8 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
+//class 1 -- no shadows
+
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect depthMap;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 780df9ed1a..37179c7e14 100755
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -24,6 +24,7 @@
*/
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index fc0e6b2388..9bdee15541 100755
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -24,6 +24,7 @@
*/
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt
index c64e11929d..122577b132 100755
--- a/indra/newview/gpu_table.txt
+++ b/indra/newview/gpu_table.txt
@@ -38,7 +38,7 @@ ATI 3D-Analyze .*ATI.*3D-Analyze.* 0 0 0 0
ATI All-in-Wonder 7500 .*ATI.*All-in-Wonder 75.* 0 1 0 0
ATI All-in-Wonder 8500 .*ATI.*All-in-Wonder 85.* 0 1 0 0
ATI All-in-Wonder 9200 .*ATI.*All-in-Wonder 92.* 0 1 0 0
-ATI All-in-Wonder 9xxx .*ATI.*All-in-Wonder 9.* 1 1 0 0
+ATI All-in-Wonder 9xxx .*ATI.*All-in-Wonder 9.* 1 1 0 2.1
ATI All-in-Wonder HD .*ATI.*All-in-Wonder HD.* 1 1 1 3.3
ATI All-in-Wonder X600 .*ATI.*All-in-Wonder X6.* 1 1 0 0
ATI All-in-Wonder X800 .*ATI.*All-in-Wonder X8.* 1 1 1 2.1
@@ -46,162 +46,132 @@ ATI All-in-Wonder X1800 .*ATI.*All-in-Wonder X18.* 3 1 0 0
ATI All-in-Wonder X1900 .*ATI.*All-in-Wonder X19.* 3 1 0 0
ATI All-in-Wonder PCI-E .*ATI.*All-in-Wonder.*PCI-E.* 1 1 0 0
ATI All-in-Wonder Radeon .*ATI.*All-in-Wonder Radeon.* 0 1 0 0
-ATI ASUS ARES .*ATI.*ASUS.*ARES.* 3 1 0 0
-ATI ASUS A9xxx .*ATI.*ASUS.*A9.* 1 1 0 0
-ATI ASUS AH24xx .*ATI.*ASUS.*AH24.* 1 1 1 3.3
-ATI ASUS AH26xx .*ATI.*ASUS.*AH26.* 1 1 1 3.3
-ATI ASUS AH34xx .*ATI.*ASUS.*AH34.* 1 1 1 3.3
-ATI ASUS AH36xx .*ATI.*ASUS.*AH36.* 1 1 1 3.3
-ATI ASUS AH46xx .*ATI.*ASUS.*AH46.* 2 1 1 3.3
-ATI ASUS AX3xx .*ATI.*ASUS.*AX3.* 1 1 0 0
-ATI ASUS AX5xx .*ATI.*ASUS.*AX5.* 1 1 0 0
-ATI ASUS AX8xx .*ATI.*ASUS.*AX8.* 2 1 0 0
-ATI ASUS EAH24xx .*ATI.*ASUS.*EAH24.* 2 1 0 0
-ATI ASUS EAH26xx .*ATI.*ASUS.*EAH26.* 3 1 0 0
-ATI ASUS EAH29xx .*ATI.*ASUS.*EAH29.* 3 1 0 0
-ATI ASUS EAH34xx .*ATI.*ASUS.*EAH34.* 1 1 0 0
-ATI ASUS EAH36xx .*ATI.*ASUS.*EAH36.* 2 1 0 0
-ATI ASUS EAH38xx .*ATI.*ASUS.*EAH38.* 2 1 1 3.3
-ATI ASUS EAH43xx .*ATI.*ASUS.*EAH43.* 2 1 1 3.3
-ATI ASUS EAH45xx .*ATI.*ASUS.*EAH45.* 2 1 0 0
-ATI ASUS EAH48xx .*ATI.*ASUS.*EAH48.* 3 1 1 3.3
-ATI ASUS EAH57xx .*ATI.*ASUS.*EAH57.* 3 1 1 4.1
-ATI ASUS EAH58xx .*ATI.*ASUS.*EAH58.* 5 1 1 4.1
-ATI ASUS EAH62xx .*ATI.*ASUS.*EAH62.* 2 1 0 0
-ATI ASUS EAH63xx .*ATI.*ASUS.*EAH63.* 2 1 0 0
-ATI ASUS EAH64xx .*ATI.*ASUS.*EAH64.* 2 1 0 0
-ATI ASUS EAH65xx .*ATI.*ASUS.*EAH65.* 2 1 0 4.1
-ATI ASUS EAH66xx .*ATI.*ASUS.*EAH66.* 3 1 0 4.1
-ATI ASUS EAH67xx .*ATI.*ASUS.*EAH67.* 3 1 0 0
-ATI ASUS EAH68xx .*ATI.*ASUS.*EAH68.* 5 1 0 4
-ATI ASUS EAH69xx .*ATI.*ASUS.*EAH69.* 5 1 0 4.1
-ATI ASUS Radeon X1xxx .*ATI.*ASUS.*X1.* 2 1 1 2.1
-ATI Radeon X7xx .*ATI.*ASUS.*X7.* 1 1 0 0
-ATI Radeon X19xx .*ATI.*(Radeon|Diamond) X19.* ?.* 2 1 1 2.1
-ATI Radeon X18xx .*ATI.*(Radeon|Diamond) X18.* ?.* 3 1 1 2.1
+ATI Radeon X1300 .*ATI.*(ASUS|Radeon).*X13.* 2 1 1 2.1
+ATI Radeon X1500 .*ATI.*(ASUS|Radeon).*X15.* 2 1 1 2.1
+ATI Radeon X1600 .*ATI.*(ASUS|Radeon).*X16.* 2 1 1 2.1
+ATI Radeon X1700 .*ATI.*(ASUS|Radeon).*X17.* 2 1 1 2.1
+ATI Radeon X1800 .*ATI.*(Radeon|Diamond) X18.* ?.* 3 1 1 2.1
+ATI Radeon X1900 .*ATI.*(Radeon|Diamond|ASUS) X19.* ?.* 2 1 1 2.1
ATI Radeon X17xx .*ATI.*(Radeon|Diamond) X17.* ?.* 1 1 1 2.1
-ATI Radeon X16xx .*ATI.*(Radeon|Diamond) X16.* ?.* 1 1 1 2.1
-ATI Radeon X15xx .*ATI.*(Radeon|Diamond) X15.* ?.* 1 1 1 2.1
-ATI Radeon X13xx .*ATI.*(Radeon|Diamond) X13.* ?.* 1 1 1 2.1
-ATI Radeon X1xxx .*ATI.*(Radeon|Diamond) X1.. ?.* 0 1 1 2.1
-ATI Radeon X2xxx .*ATI.*(Radeon|Diamond) X2.. ?.* 1 1 1 2.1
+ATI Radeon X16xx .*ATI.*(Radeon|Diamond) X17.* ?.* 1 1 1 2.1
+ATI Radeon X28xx .*ATI.*(Radeon|Diamond) X28.. ?.* 1 1 1 2.1
ATI Display Adapter .*ATI.*display adapter.* 1 1 1 4.1
ATI FireGL 5200 .*ATI.*FireGL V52.* 1 1 1 2.1
ATI FireGL 5xxx .*ATI.*FireGL V5.* 2 1 1 3.3
ATI FireGL .*ATI.*Fire.*GL.* 4 1 1 4.2
-ATI FirePro M3900 .*ATI.*FirePro.*M39.* 2 1 0 0
+ATI FirePro M3900 .*ATI.*FirePro.*M39.* 2 1 0 4.1
ATI FirePro M5800 .*ATI.*FirePro.*M58.* 3 1 0 0
ATI FirePro M7740 .*ATI.*FirePro.*M77.* 3 1 0 0
ATI FirePro M7820 .*ATI.*FirePro.*M78.* 5 1 1 4.2
-ATI FireMV .*ATI.*FireMV.* 0 1 1 1.3
+ATI FireMV .*ATI.*FireMV.* 0 1 1 3.2
ATI Generic .*ATI.*Generic.* 0 0 0 0
ATI Hercules 9800 .*ATI.*Hercules.* 9800.* 1 1 0 0
-ATI IGP 340M .*ATI.*IGP.*340M.* 0 0 0 0
+ATI IGP 340M .*ATI.*IGP.* 34[0-9]M.* 0 0 0 1.3
ATI M52 .*ATI.*M52.* 1 1 0 0
ATI M54 .*ATI.*M54.* 1 1 0 0
ATI M56 .*ATI.*M56.* 1 1 0 0
ATI M71 .*ATI.*M71.* 1 1 0 0
ATI M72 .*ATI.*M72.* 1 1 0 0
ATI M76 .*ATI.*M76.* 3 1 0 0
-ATI Radeon HD 64xx .*ATI.*AMD Radeon.* HD [67]4..[MG] 2 1 1 4.2
-ATI Radeon HD 65xx .*ATI.*AMD Radeon.* HD [67]5..[MG] 2 1 1 4.2
-ATI Radeon HD 66xx .*ATI.*AMD Radeon.* HD [67]6..[MG] 3 1 1 4.2
-ATI Radeon HD 7100 .*ATI.*AMD Radeon.* HD 71.* 2 1 0 0
-ATI Radeon HD 7200 .*ATI.*AMD Radeon.* HD 72.* 2 1 0 0
-ATI Radeon HD 7300 .*ATI.*AMD Radeon.* HD 73.* 2 1 0 4.2
-ATI Radeon HD 7400 .*ATI.*AMD Radeon.* HD 74.* 2 1 0 4.2
-ATI Radeon HD 7500 .*ATI.*AMD Radeon.* HD 75.* 3 1 1 4.2
-ATI Radeon HD 7600 .*ATI.*AMD Radeon.* HD 76.* 3 1 0 4.2
-ATI Radeon HD 7700 .*ATI.*AMD Radeon.* HD 77.* 4 1 1 4.2
-ATI Radeon HD 7800 .*ATI.*AMD Radeon.* HD 78.* 5 1 1 4.2
-ATI Radeon HD 7900 .*ATI.*AMD Radeon.* HD 79.* 5 1 1 4.2
-ATI ASUS HD7100 .*ATI.*ASUS.* HD71.* 2 1 0 0
-ATI ASUS HD7200 .*ATI.*ASUS.* HD72.* 2 1 0 0
-ATI ASUS HD7300 .*ATI.*ASUS.* HD73.* 2 1 0 0
-ATI ASUS HD7400 .*ATI.*ASUS.* HD74.* 2 1 0 0
-ATI ASUS HD7500 .*ATI.*ASUS.* HD75.* 3 1 1 4.2
-ATI ASUS HD7600 .*ATI.*ASUS.* HD76.* 3 1 0 0
-ATI ASUS HD7700 .*ATI.*ASUS.* HD77.* 4 1 1 4.2
-ATI ASUS HD7800 .*ATI.*ASUS.* HD78.* 5 1 1 4.2
-ATI ASUS HD7900 .*ATI.*ASUS.* HD79.* 5 1 1 4.2
+ATI Radeon HD 6300M .*ATI.*AMD Radeon.* (HD|HD )63..M 2 1 1 4.2
+ATI Radeon HD 6400M .*ATI.*AMD Radeon.* (HD|HD )64..M 2 1 1 4.2
+ATI Radeon HD 6500M .*ATI.*AMD Radeon.* (HD|HD )65..M 2 1 1 4.2
+ATI Radeon HD 6600M .*ATI.*AMD Radeon.* (HD 6|6)6..M 3 1 1 4.2
+ATI Radeon HD 6700M .*ATI.*AMD Radeon.* (HD|HD )67..M 3 1 1 4.2
+ATI Radeon HD 6800M .*ATI.*AMD Radeon.* (HD|HD )68..M 3 1 1 4.2
+ATI Radeon HD 6300G .*ATI.*AMD Radeon.* (HD|HD )63..G 2 1 1 4.2
+ATI Radeon HD 6400G .*ATI.*AMD Radeon.* (HD|HD )64..G 2 1 1 4.2
+ATI Radeon HD 6500G .*ATI.*AMD Radeon.* (HD|HD )65..G 2 1 1 4.2
+ATI Radeon HD 6600G .*ATI.*AMD Radeon.* (HD|HD )66..G 3 1 1 4.2
+ATI Radeon HD 7100 .*ATI.*(Radeon|ASUS).* (HD|HD )71.* 2 1 0 0
+ATI Radeon HD 7200 .*ATI.*(Radeon|ASUS).* (HD|HD )72.* 2 1 0 4.2
+ATI Radeon HD 7300 .*ATI.*(Radeon|ASUS).* (HD|HD )73.* 2 1 0 4.2
+ATI Radeon HD 7400 .*ATI.*(Radeon|ASUS).* (HD|HD )74.* 2 1 0 4.2
+ATI Radeon HD 7500 .*ATI.*(Radeon|ASUS).* (HD|HD )75.* 3 1 1 4.2
+ATI Radeon HD 7600 .*ATI.*(Radeon|ASUS).* (HD|HD )76.* 3 1 0 4.2
+ATI Radeon HD 7700 .*ATI.*(Radeon|ASUS).* (HD|HD )77.* 4 1 1 4.2
+ATI Radeon HD 7800 .*ATI.*(Radeon|ASUS).* (HD|HD )78.* 5 1 1 4.2
+ATI Radeon HD 7900 .*ATI.*(Radeon|ASUS).* (HD|HD )79.* 5 1 1 4.2
+ATI Radeon HD 7000 Series .*ATI.*(Radeon|ASUS).* (HD|HD )7000 Series.* 3 1 1 4.2
ATI Mobility Radeon 4100 .*ATI.*Mobility.* 41.. 1 1 1 3.3
+ATI Mobility Radeon 5000 .*ATI.*Mobility.* 50.. 1 1 1 4.2
ATI Mobility Radeon 7xxx .*ATI.*Mobility.*Radeon 7.* 0 1 1 1.3
ATI Mobility Radeon 8xxx .*ATI.*Mobility.*Radeon 8.* 0 1 0 0
ATI Mobility Radeon 9800 .*ATI.*Mobility.* 98.* 1 1 0 0
ATI Mobility Radeon 9700 .*ATI.*Mobility.* 97.* 0 1 1 2.1
ATI Mobility Radeon 9600 .*ATI.*Mobility.* 96.* 1 1 1 2.1
-ATI Mobility Radeon HD 530v .*ATI.*Mobility.*HD *530v.* 1 1 1 3.3
-ATI Mobility Radeon HD 540v .*ATI.*Mobility.*HD *540v.* 1 1 1 3.3
-ATI Mobility Radeon HD 545v .*ATI.*Mobility.*HD *545v.* 2 1 1 4
-ATI Mobility Radeon HD 550v .*ATI.*Mobility.*HD *550v.* 3 1 1 4
-ATI Mobility Radeon HD 560v .*ATI.*Mobility.*HD *560v.* 3 1 1 3.2
-ATI Mobility Radeon HD 565v .*ATI.*Mobility.*HD *565v.* 3 1 1 3.3
-ATI Mobility Radeon HD 2300 .*ATI.*Mobility.*HD *23.* 0 1 1 2.1
-ATI Mobility Radeon HD 2400 .*ATI.*Mobility.*HD *24.* 1 1 1 3.3
-ATI Mobility Radeon HD 2600 .*ATI.*Mobility.*HD *26.* 1 1 1 3.3
-ATI Mobility Radeon HD 2700 .*ATI.*Mobility.*HD *27.* 3 1 0 0
-ATI Mobility Radeon HD 3100 .*ATI.*Mobility.*HD *31.* 0 1 0 0
-ATI Mobility Radeon HD 3200 .*ATI.*Mobility.*HD *32.* 0 1 0 0
-ATI Mobility Radeon HD 3400 .*ATI.*Mobility.*HD *34.* 1 1 1 3.3
-ATI Mobility Radeon HD 3600 .*ATI.*Mobility.*HD *36.* 1 1 1 4
-ATI Mobility Radeon HD 3800 .*ATI.*Mobility.*HD *38.* 3 1 1 3.3
-ATI Mobility Radeon HD 4200 .*ATI.*Mobility.*HD *42.* 1 1 1 4
-ATI Mobility Radeon HD 4300 .*ATI.*Mobility.*HD *43.* 1 1 1 4
-ATI Mobility Radeon HD 4500 .*ATI.*Mobility.*HD *45.* 1 1 1 4
-ATI Mobility Radeon HD 4600 .*ATI.*Mobility.*HD *46.* 2 1 1 3.3
-ATI Mobility Radeon HD 4800 .*ATI.*Mobility.*HD *48.* 3 1 1 3.3
-ATI Mobility Radeon HD 5100 .*ATI.*Mobility.*HD *51.* 3 1 1 3.2
-ATI Mobility Radeon HD 5300 .*ATI.*Mobility.*HD *53.* 3 1 0 0
-ATI Mobility Radeon HD 5400 .*ATI.*Mobility.*HD *54.* 2 1 1 4.2
-ATI Mobility Radeon HD 5500 .*ATI.*Mobility.*HD *55.* 3 1 0 0
-ATI Mobility Radeon HD 5600 .*ATI.*Mobility.*HD *56.* 3 1 1 4.2
-ATI Mobility Radeon HD 5700 .*ATI.*Mobility.*HD *57.* 3 1 1 4.1
-ATI Mobility Radeon HD 6200 .*ATI.*Mobility.*HD *62.* 3 1 0 0
-ATI Mobility Radeon HD 6300 .*ATI.*Mobility.*HD *63.* 3 1 1 4.2
-ATI Mobility Radeon HD 6400M .*ATI.*Mobility.*HD *64.* 3 1 0 0
-ATI Mobility Radeon HD 6500M .*ATI.*Mobility.*HD *65.* 5 1 1 4.2
-ATI Mobility Radeon HD 6600M .*ATI.*Mobility.*HD *66.* 5 1 0 0
-ATI Mobility Radeon HD 6700M .*ATI.*Mobility.*HD *67.* 5 1 0 0
-ATI Mobility Radeon HD 6800M .*ATI.*Mobility.*HD *68.* 5 1 0 0
-ATI Mobility Radeon HD 6900M .*ATI.*Mobility.*HD *69.* 5 1 0 0
-ATI Radeon HD 2300 .*ATI.*Radeon HD *23.. 0 1 1 3.3
-ATI Radeon HD 2400 .*ATI.*Radeon HD *24.. 1 1 1 4
-ATI Radeon HD 2600 .*ATI.*Radeon HD *26.. 2 1 1 3.3
-ATI Radeon HD 2900 .*ATI.*Radeon HD *29.. 3 1 1 3.3
-ATI Radeon HD 3000 .*ATI.*Radeon HD *30.. 0 1 0 0
-ATI Radeon HD 3100 .*ATI.*Radeon HD *31.. 1 1 0 0
-ATI Radeon HD 3200 .*ATI.*Radeon HD *32.. 1 1 1 4
-ATI Radeon HD 3300 .*ATI.*Radeon HD *33.. 1 1 1 3.3
-ATI Radeon HD 3400 .*ATI.*Radeon HD *34.. 1 1 1 4
-ATI Radeon HD 3500 .*ATI.*Radeon HD *35.. 2 1 0 0
-ATI Radeon HD 3600 .*ATI.*Radeon HD *36.. 3 1 1 3.3
-ATI Radeon HD 3700 .*ATI.*Radeon HD *37.. 3 1 0 0
+ATI Mobility Radeon HD 530v .*ATI.*Mobility.*HD 530v.* 1 1 1 3.3
+ATI Mobility Radeon HD 540v .*ATI.*Mobility.*HD 540v.* 1 1 1 3.3
+ATI Mobility Radeon HD 545v .*ATI.*Mobility.*HD 545v.* 2 1 1 4
+ATI Mobility Radeon HD 550v .*ATI.*Mobility.*HD 550v.* 3 1 1 4
+ATI Mobility Radeon HD 560v .*ATI.*Mobility.*HD 560v.* 3 1 1 3.2
+ATI Mobility Radeon HD 565v .*ATI.*Mobility.*HD 565v.* 3 1 1 3.3
+ATI Mobility Radeon HD 2300 .*ATI.*Mobility.*HD 23.* 0 1 1 2.1
+ATI Mobility Radeon HD 2400 .*ATI.*Mobility.*HD 24.* 1 1 1 3.3
+ATI Mobility Radeon HD 2600 .*ATI.*Mobility.*HD 26.* 1 1 1 3.3
+ATI Mobility Radeon HD 2700 .*ATI.*Mobility.*HD 27.* 3 1 0 0
+ATI Mobility Radeon HD 3100 .*ATI.*Mobility.*HD 31.* 0 1 0 0
+ATI Mobility Radeon HD 3200 .*ATI.*Mobility.*HD 32.* 0 1 0 0
+ATI Mobility Radeon HD 3400 .*ATI.*Mobility.*HD 34.* 1 1 1 4
+ATI Mobility Radeon HD 3600 .*ATI.*Mobility.*HD 36.* 1 1 1 4
+ATI Mobility Radeon HD 3800 .*ATI.*Mobility.*HD 38.* 3 1 1 3.3
+ATI Mobility Radeon HD 4200 .*ATI.*Mobility.*HD 42.* 1 1 1 4
+ATI Mobility Radeon HD 4300 .*ATI.*Mobility.*(HD |HD)43.* 1 1 1 4
+ATI Mobility Radeon HD 4500 .*ATI.*Mobility.*HD 45.* 1 1 1 4
+ATI Mobility Radeon HD 4600 .*ATI.*Mobility.*HD 46.* 2 1 1 3.3
+ATI Mobility Radeon HD 4800 .*ATI.*Mobility.*HD 48.* 3 1 1 3.3
+ATI Mobility Radeon HD 5000 Series .*ATI.*Mobility.*HD 50.* 3 1 1 3.2
+ATI Mobility Radeon HD 5100 .*ATI.*Mobility.*HD 51.* 3 1 1 3.2
+ATI Mobility Radeon HD 5300 .*ATI.*Mobility.*HD 53.* 3 1 0 0
+ATI Mobility Radeon HD 5400 .*ATI.*Mobility.*HD 54.* 2 1 1 4.2
+ATI Mobility Radeon HD 5500 .*ATI.*Mobility.*HD 55.* 3 1 0 4.2
+ATI Mobility Radeon HD 5600 .*ATI.*Mobility.*HD 56.* 3 1 1 4.2
+ATI Mobility Radeon HD 5700 .*ATI.*Mobility.*HD 57.* 3 1 1 4.1
+ATI Mobility Radeon HD 6200 .*ATI.*Mobility.*HD 62.* 3 1 0 0
+ATI Mobility Radeon HD 6300 .*ATI.*Mobility.*HD 63.* 3 1 1 4.2
+ATI Mobility Radeon HD 6400M .*ATI.*Mobility.*HD 64.* 3 1 0 0
+ATI Mobility Radeon HD 6500M .*ATI.*Mobility.*HD 65.* 5 1 1 4.2
+ATI Mobility Radeon HD 6600M .*ATI.*Mobility.*HD 66.* 5 1 0 0
+ATI Mobility Radeon HD 6700M .*ATI.*Mobility.*HD 67.* 5 1 0 0
+ATI Mobility Radeon HD 6800M .*ATI.*Mobility.*HD 68.* 5 1 0 0
+ATI Mobility Radeon HD 6900M .*ATI.*Mobility.*HD 69.* 5 1 0 0
+ATI Mobility Radeon Graphics .*ATI Mobility Radeon Graphics.* 1 1 0 4
+ATI Radeon HD 2300 .*ATI.*Radeon.* (HD|HD )23.. 0 1 1 3.3
+ATI Radeon HD 2400 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)24.. 1 1 1 4
+ATI Radeon HD 2600 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)26.. 2 1 1 4
+ATI Radeon HD 2900 .*ATI.*Radeon.* (HD|HD )29.. 3 1 1 3.3
+ATI Radeon HD 3000 .*ATI.*Radeon.* (HD|HD )30.. 0 1 0 0
+ATI Radeon HD 3100 .*ATI.*Radeon.* (HD|HD )31.. 1 1 0 0
+ATI Radeon HD 3200 .*ATI.*Radeon.* (HD|HD )32.. 1 1 1 4
+ATI Radeon HD 3300 .*ATI.*Radeon.* (HD|HD )33.. 1 1 1 3.3
+ATI Radeon HD 3400 .*ATI.*(Radeon|ASUS).* (HD|HD |AH|EAH)34.. 1 1 1 4
+ATI Radeon HD 3500 .*ATI.*Radeon.* (HD|HD )35.. 2 1 0 0
+ATI Radeon HD 3600 .*ATI.*(Radeon|ASUS).* (HD|HD |AH|EAH)36.. 3 1 1 4
+ATI Radeon HD 3700 .*ATI.*Radeon.* (HD|HD )37.. 3 1 0 3.3
ATI HD3700 .*ATI.* HD37.. 3 1 0 3.3
-ATI Radeon HD 3800 .*ATI.*Radeon HD *38.. 3 1 1 4
-ATI Radeon HD 4100 .*ATI.*Radeon HD *41.. 1 1 0 0
-ATI Radeon HD 4200 .*ATI.*Radeon HD *42.. 1 1 1 4
-ATI Radeon HD 4300 .*ATI.*Radeon HD *43.. 2 1 1 4
-ATI Radeon HD 4400 .*ATI.*Radeon HD *44.. 2 1 0 0
-ATI Radeon HD 4500 .*ATI.*Radeon HD *45.. 2 1 1 3.3
-ATI Radeon HD 4600 .*ATI.*Radeon HD *46.. 3 1 1 4
-ATI Radeon HD 4700 .*ATI.*Radeon HD *47.. 3 1 1 3.3
-ATI Radeon HD 4800 .*ATI.*Radeon HD *48.. 3 1 1 4
-ATI ASUS EAH5400 .*ATI.*ASUS EAH54.. 3 1 1 4.2
-ATI Radeon HD 5400 .*ATI.*Radeon HD *54.. 3 1 1 4.2
-ATI Radeon HD 5500 .*ATI.*Radeon HD *55.. 3 1 1 4.2
-ATI ASUS EAH5500 .*ATI.*ASUS EAH55.. 3 1 1 4.2
-ATI Radeon HD 5600 .*ATI.*Radeon HD *56.. 3 1 1 4.2
-ATI Radeon HD 5700 .*ATI.*Radeon HD *57.. 3 1 1 4.2
-ATI Radeon HD 5800 .*ATI.*Radeon HD *58.. 4 1 1 4.2
-ATI Radeon HD 5900 .*ATI.*Radeon HD *59.. 4 1 1 4.2
-ATI Radeon HD 6200 .*ATI.*Radeon HD *62.. 0 1 1 4.2
-ATI Radeon HD 6300 .*ATI.*Radeon HD *63.. 1 1 1 4.2
-ATI Radeon HD 6400 .*ATI.*Radeon HD *64.. 3 1 1 4.2
-ATI Radeon HD 6500 .*ATI.*Radeon HD *65.. 3 1 1 4.2
-ATI Radeon HD 6600 .*ATI.*Radeon HD *66.. 3 1 1 4.2
-ATI Radeon HD 6700 .*ATI.*Radeon HD *67.. 3 1 1 4.2
-ATI Radeon HD 6800 .*ATI.*Radeon HD *68.. 4 1 1 4.2
-ATI Radeon HD 6900 .*ATI.*Radeon HD *69.. 5 1 1 4.2
+ATI Radeon HD 3800 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)38.. 3 1 1 4
+ATI Radeon HD 4100 .*ATI.*Radeon.* (HD|HD )41.. 1 1 0 0
+ATI Radeon HD 4200 .*ATI.*Radeon.* (HD|HD )42.. 1 1 1 4
+ATI Radeon HD 4300 .*ATI.*(Radeon|ASUS).* (HD4|HD 4|EAH4|4)3.. 2 1 1 4
+ATI Radeon HD 4400 .*ATI.*Radeon.* (HD|HD )44.. 2 1 0 0
+ATI Radeon HD 4500 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)45.. 2 1 1 3.3
+ATI Radeon HD 4600 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)46.. 3 1 1 4
+ATI Radeon HD 4700 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)47.. 3 1 1 3.3
+ATI Radeon HD 4800 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)48.. 3 1 1 4
+ATI Radeon HD 5400 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)54.. 3 1 1 4.2
+ATI Radeon HD 5500 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)55.. 3 1 1 4.2
+ATI Radeon HD 5600 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)56.. 3 1 1 4.2
+ATI Radeon HD 5700 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)57.. 3 1 1 4.2
+ATI Radeon HD 5800 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)58.. 4 1 1 4.2
+ATI Radeon HD 5900 .*ATI.*Radeon.* (HD|HD )59.. 4 1 1 4.2
+ATI Radeon HD 6200 .*ATI.*Radeon.* (HD|HD )62.. 0 1 1 4.2
+ATI Radeon HD 6300 .*ATI.*Radeon.* (HD|HD )63.. 1 1 1 4.2
+ATI Radeon HD 6400 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)64.. 3 1 1 4.2
+ATI Radeon HD 6500 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)65.. 3 1 1 4.2
+ATI Radeon HD 6600 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)66.. 3 1 1 4.2
+ATI Radeon HD 6700 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)67.. 3 1 1 4.2
+ATI Radeon HD 6800 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)68.. 4 1 1 4.2
+ATI Radeon HD 6900 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)69.. 5 1 1 4.2
ATI Radeon OpenGL .*ATI.*Radeon OpenGL.* 0 0 0 0
ATI Radeon 2100 .*ATI.*Radeon 21.. 0 1 1 2.1
ATI Radeon 3000 .*ATI.*Radeon 30.. 1 1 1 4
@@ -219,17 +189,21 @@ ATI Radeon 9800 .*ATI.*Radeon 98.. 1 1 1 2.1
ATI Radeon RV250 .*ATI.*RV250.* 0 1 0 0
ATI Radeon RV600 .*ATI.*RV6.* 1 1 0 0
ATI Radeon RX700 .*ATI.*RX70.* 1 1 0 0
-ATI Radeon RX800 .*ATI.*Radeon *RX80.* 2 1 0 0
+ATI Radeon RX800 .*ATI.*Radeon RX80.* 2 1 0 0
ATI RS880M .*ATI.*RS880M 1 1 0 0
ATI Radeon RX9550 .*ATI.*RX9550.* 1 1 0 0
ATI Radeon VE .*ATI.*Radeon.*VE.* 0 0 0 0
-ATI Radeon X300 .*ATI.*Radeon *X3.* 1 1 1 2.1
+ATI Radeon X300 .*ATI.*Radeon X3.* 1 1 1 2.1
ATI Radeon X400 .*ATI.*Radeon ?X4.* 0 1 0 0
ATI Radeon X500 .*ATI.*Radeon ?X5.* 1 1 1 2.1
-ATI Radeon X600 .*ATI.*Radeon ?X6.* 1 1 1 2.1
+ATI Radeon X600 .*ATI.*(Radeon |ASUS Extreme A)X6.* 1 1 1 2.1
ATI Radeon X700 .*ATI.*Radeon ?X7.* 2 1 1 2.1
ATI Radeon X800 .*ATI.*Radeon ?X8.* 1 1 1 2.1
ATI Radeon X900 .*ATI.*Radeon ?X9.* 2 1 0 0
+ATI Radeon X1000 .*ATI.*Radeon ?X10.* 2 1 0 2.1
+ATI Radeon X1200 .*ATI.*Radeon ?X12.* 2 1 0 2.1
+ATI Radeon X1400 .*ATI.*Radeon ?X14.* 2 1 0 2.1
+ATI Radeon X2300 .*ATI.*Radeon ?X23.* 2 1 0 2.1
ATI Radeon Xpress .*ATI.*Radeon Xpress.* 0 1 1 2.1
ATI Rage 128 .*ATI.*Rage 128.* 0 1 0 0
ATI R300 (9700) .*R300.* 0 1 1 2.1
@@ -248,41 +222,43 @@ ATI RV530 .*RV530.* 1 1 0 0
ATI RX480 (Xpress 200P) .*RX480.* 0 1 0 0
ATI RX700 .*RX700.* 1 1 0 0
AMD ANTILLES (HD 6990) .*(AMD|ATI).*Antilles.* 3 1 0 0
+ATI ROBSON .*(AMD|ATI).*ROBSON.* 3 1 0 4
AMD BARTS (HD 6800) .*(AMD|ATI).*Barts.* 3 1 1 2.1
+AMD WRESTLER .*(AMD|ATI).*WRESTLER.* 3 1 1 4
+AMD SUMO .*(AMD|ATI).*SUMO.* 3 1 1 4.1
AMD CAICOS (HD 6400) .*(AMD|ATI).*Caicos.* 3 1 0 0
AMD CAYMAN (HD 6900) .*(AMD|ATI).*(Cayman|CAYMAM).* 3 1 0 0
-AMD CEDAR (HD 5450) .*(AMD|ATI).*Cedar.* 2 1 0 0
+AMD CEDAR (HD 5450) .*(AMD|ATI).*Cedar.* 2 1 0 2.1
AMD CYPRESS (HD 5800) .*(AMD|ATI).*Cypress.* 3 1 0 0
AMD HEMLOCK (HD 5970) .*(AMD|ATI).*Hemlock.* 3 1 0 0
AMD JUNIPER (HD 5700) .*(AMD|ATI).*Juniper.* 3 1 0 0
AMD PARK .*(AMD|ATI).*Park.* 3 1 0 0
-AMD REDWOOD (HD 5500/5600) .*(AMD|ATI).*Redwood.* 3 1 0 0
-AMD TURKS (HD 6500/6600) .*(AMD|ATI).*Turks.* 3 1 0 0
+AMD REDWOOD (HD 5500/5600) .*(AMD|ATI).*Redwood.* 3 1 0 1.4
+AMD TURKS (HD 6500/6600) .*(AMD|ATI).*Turks.* 3 1 0 2.1
AMD RS780 (HD 3200) .*RS780.* 0 1 1 2.1
AMD RS880 (HD 4200) .*RS880.* 0 1 1 3.2
AMD RV610 (HD 2400) .*RV610.* 1 1 0 0
AMD RV620 (HD 3400) .*RV620.* 1 1 0 0
AMD RV630 (HD 2600) .*RV630.* 2 1 0 0
-AMD RV635 (HD 3600) .*RV635.* 3 1 0 0
+AMD RV635 (HD 3600) .*RV635.* 3 1 0 1.4
AMD RV670 (HD 3800) .*RV670.* 3 1 0 0
AMD R680 (HD 3870 X2) .*R680.* 3 1 0 0
AMD R700 (HD 4800 X2) .*R700.* 3 1 0 0
AMD RV710 (HD 4300) .*RV710.* 0 1 1 1.4
-AMD RV730 (HD 4600) .*RV730.* 3 1 0 0
+AMD RV730 (HD 4600) .*RV730.* 3 1 0 1.4
AMD RV740 (HD 4700) .*RV740.* 3 1 0 0
AMD RV770 (HD 4800) .*RV770.* 3 1 0 0
AMD RV790 (HD 4800) .*RV790.* 3 1 0 0
ATI 760G/Radeon 3000 .*ATI.*AMD 760G.* 1 1 1 3.3
ATI 780L/Radeon 3000 .*ATI.*AMD 780L.* 1 1 0 0
ATI Radeon DDR .*ATI.*Radeon ?DDR.* 0 1 0 0
-ATI FirePro 2000 .*ATI.*FirePro 2.* 2 1 1 4.1
+ATI FirePro 2000 .*ATI.*FirePro 2.* 2 1 1 4.2
ATI FirePro 3000 .*ATI.*FirePro V3.* 2 1 0 0
-ATI FirePro 4000 .*ATI.*FirePro V4.* 2 1 0 0
+ATI FirePro 4000 .*ATI.*FirePro V4.* 2 1 0 4.1
ATI FirePro 5000 .*ATI.*FirePro V5.* 3 1 0 0
ATI FirePro 7000 .*ATI.*FirePro V7.* 3 1 0 0
ATI FirePro M .*ATI.*FirePro M.* 3 1 1 4.2
ATI R300 (9700) .*R300.* 0 1 1 2.1
-ATI Radeon .*ATI.*(Diamond|Radeon).* 0 1 0 4.2
Intel X3100 .*Intel.*X3100.* 1 1 1 2.1
Intel GMA 3600 .*Intel.* 3600.* 0 1 1 3
Intel 830M .*Intel.*830M 0 0 0 0
@@ -308,8 +284,6 @@ Intel Graphics Media HD .*Intel.*Graphics Media.*HD.* 1 1 1 2.1
Intel HD Graphics 2000 .*Intel.*HD Graphics 2.* 2 1 0 4
Intel HD Graphics 3000 .*Intel.*HD Graphics 3.* 3 1 1 3.1
Intel HD Graphics 4000 .*Intel.*HD Graphics 4.* 3 1 1 4
-Intel HD2000 .*Intel.*HD2000.* 2 1 0 0
-Intel HD3000 .*Intel.*HD3000.* 3 1 0 0
Intel HD Graphics .*Intel.*HD Graphics.* 2 1 1 4
Intel Mobile 4 Series .*Intel.*Mobile.* 4 Series.* 0 1 1 2.1
Intel 4 Series Internal .*Intel.* 4 Series Internal.* 1 1 1 2.1
@@ -322,113 +296,109 @@ Intel Q45/Q43 .*Intel.*Q4.* 1 1 1 2.1
Intel B45/B43 .*Intel.*B4.* 1 1 1 2.1
Intel 3D-Analyze .*Intel.*3D-Analyze.* 2 1 0 0
Matrox .*Matrox.* 0 0 0 0
-Mesa .*Mesa.* 1 0 1 2.1
+Mesa .*Mesa.* 1 0 1 3
Gallium .*Gallium.* 1 1 1 2.1
-NVIDIA G100M .*NVIDIA .*100M.* 4 1 1 3.3
-NVIDIA G102M .*NVIDIA .*102M.* 1 1 1 3.3
-NVIDIA G103M .*NVIDIA .*103M.* 2 1 1 3.3
-NVIDIA G105M .*NVIDIA .*105M.* 2 1 1 3.3
-NVIDIA G 110M .*NVIDIA .*110M.* 1 1 1 3.3
-NVIDIA G 120M .*NVIDIA .*120M.* 1 1 1 3.3
-NVIDIA G 205M .*NVIDIA .*205M.* 1 1 0 0
-NVIDIA G 410M .*NVIDIA .*410M.* 3 1 1 4.2
-NVIDIA GT 120M .*NVIDIA .*GT *12*M.* 3 1 1 3.3
-NVIDIA GT 130M .*NVIDIA .*GT *13*M.* 3 1 1 3.3
-NVIDIA GT 140M .*NVIDIA .*GT *14*M.* 3 1 1 3.3
-NVIDIA GT 150M .*NVIDIA .*GTS *15*M.* 2 1 0 0
-NVIDIA GTS 160M .*NVIDIA .*GTS *16*M.* 2 1 0 0
-NVIDIA G210M .*NVIDIA .*G21*M.* 3 1 0 0
-NVIDIA GT 220M .*NVIDIA .*GT *22*M.* 3 1 1 3.3
-NVIDIA GT 230M .*NVIDIA .*GT *23*M.* 3 1 1 3.3
-NVIDIA GT 240M .*NVIDIA .*GT *24*M.* 3 1 1 3.3
-NVIDIA GTS 250M .*NVIDIA .*GTS *25*M.* 3 1 0 0
-NVIDIA GTS 260M .*NVIDIA .*GTS *26*M.* 3 1 0 0
-NVIDIA GTX 260M .*NVIDIA .*GTX *26*M.* 3 1 0 0
-NVIDIA GTX 270M .*NVIDIA .*GTX *27*M.* 3 1 0 0
-NVIDIA GTX 280M .*NVIDIA .*GTX *28*M.* 3 1 0 0
-NVIDIA 300M .*NVIDIA .*30*M.* 3 1 1 4.2
-NVIDIA G 310M .*NVIDIA .*31*M.* 2 1 0 0
-NVIDIA GT 320M .*NVIDIA .*GT *32*M.* 3 1 0 0
-NVIDIA GT 325M .*NVIDIA .*GT *32*M.* 3 1 1 3.3
-NVIDIA GT 330M .*NVIDIA .*GT *33*M.* 3 1 1 3.3
-NVIDIA GT 340M .*NVIDIA .*GT *34*M.* 4 1 1 3.3
-NVIDIA GTS 350M .*NVIDIA .*GTS *35*M.* 4 1 1 3.3
-NVIDIA GTS 360M .*NVIDIA .*GTS *360M.* 5 1 1 3.3
-NVIDIA 405M .*NVIDIA .* 40*M.* 2 1 0 4.2
-NVIDIA 410M .*NVIDIA .* 41*M.* 3 1 0 0
-NVIDIA GT 415M .*NVIDIA .*GT *41*M.* 3 1 1 4.2
-NVIDIA GT 420M .*NVIDIA .*GT *42*M.* 3 1 1 4.2
-NVIDIA GT 430M .*NVIDIA .*GT *43*M.* 3 1 1 4.2
-NVIDIA GT 440M .*NVIDIA .*GT *44*M.* 3 1 1 4.2
-NVIDIA GT 450M .*NVIDIA .*GT *45*M.* 3 1 0 0
-NVIDIA GTX 460M .*NVIDIA .*GTX *46*M.* 4 1 1 4.2
-NVIDIA GTX 470M .*NVIDIA .*GTX *47*M.* 3 1 0 0
-NVIDIA GTX 480M .*NVIDIA .*GTX *48*M.* 3 1 1 4.2
-NVIDIA GT 520M .*NVIDIA .*GT *52*M.* 3 1 1 4.2
-NVIDIA GT 530M .*NVIDIA .*GT *53*M.* 3 1 1 4.2
-NVIDIA GT 540M .*NVIDIA .*GT *54*M.* 3 1 1 4.2
-NVIDIA GT 550M .*NVIDIA .*GT *55*M.* 3 1 1 4.2
-NVIDIA GTX 560M .*NVIDIA .*GTX *56*M.* 3 1 0 0
-NVIDIA GTX 570M .*NVIDIA .*GTX *57*M.* 5 1 0 0
-NVIDIA GTX 580M .*NVIDIA .*GTX *58*M.* 5 1 1 4.2
-NVIDIA 610M .*NVIDIA.* 61*M.* 3 1 1 4.2
-NVIDIA GT 620M .*NVIDIA .*GT *62*M.* 3 1 0 0
-NVIDIA GT 630M .*NVIDIA .*GT *63*M.* 3 1 0 0
-NVIDIA GT 640M .*NVIDIA .*GT *64*M.* 3 1 0 0
-NVIDIA GT 650M .*NVIDIA .*GT *65*M.* 3 1 0 0
-NVIDIA GTX 660M .*NVIDIA .*GTX *66*M.* 5 1 0 0
-NVIDIA GTX 670M .*NVIDIA .*GTX *67*M.* 5 1 1 4.2
-NVIDIA GTX 680M .*NVIDIA .*GTX *68*M.* 5 1 0 0
-NVIDIA GTX 690M .*NVIDIA .*GTX *69*M.* 5 1 0 0
+NVIDIA G100M .*NVIDIA .* 10[0-9]M.* 4 1 1 3.3
+NVIDIA G 110M .*NVIDIA .* 11[0-9]M.* 1 1 1 3.3
+NVIDIA G 120M .*NVIDIA .* 12[0-9]M.* 1 1 1 3.3
+NVIDIA G 200M .*NVIDIA .* 20[0-9]M.* 1 1 0 0
+NVIDIA G 410M .*NVIDIA .* 41[0-9]M.* 3 1 1 4.2
+NVIDIA GT 130M .*NVIDIA .*GT 13[0-9]M.* 3 1 1 3.3
+NVIDIA GT 140M .*NVIDIA .*GT 14[0-9]M.* 3 1 1 3.3
+NVIDIA GT 150M .*NVIDIA .*GTS 15[0-9]M.* 2 1 0 0
+NVIDIA GTS 160M .*NVIDIA .*GTS 16[0-9]M.* 2 1 0 0
+NVIDIA G210M .*NVIDIA .*G21[0-9]M.* 3 1 0 3.3
+NVIDIA GT 220M .*NVIDIA .*GT 22[0-9]M.* 3 1 1 3.3
+NVIDIA GT 230M .*NVIDIA .*GT 23[0-9]M.* 3 1 1 3.3
+NVIDIA GT 240M .*NVIDIA .*GT 24[0-9]M.* 3 1 1 3.3
+NVIDIA GTS 250M .*NVIDIA .*GTS 25[0-9]M.* 3 1 0 3.3
+NVIDIA GTS 260M .*NVIDIA .*GTS 26[0-9]M.* 3 1 0 0
+NVIDIA GTX 260M .*NVIDIA .*GTX 26[0-9]M.* 3 1 0 3.3
+NVIDIA GTX 270M .*NVIDIA .*GTX 27[0-9]M.* 3 1 0 0
+NVIDIA GTX 280M .*NVIDIA .*GTX 28[0-9]M.* 3 1 0 3.3
+NVIDIA 300M .*NVIDIA .*GT 30[0-9]M.* 3 1 1 4.2
+NVIDIA G 310M .*NVIDIA .* 31[0-9]M.* 2 1 0 3.3
+NVIDIA GT 320M .*NVIDIA .* 32[0-9]M.* 3 1 0 3.3
+NVIDIA GT 330M .*NVIDIA .*GT 33[0-9]M.* 3 1 1 3.3
+NVIDIA GT 340M .*NVIDIA .*GT 34[0-9]M.* 4 1 1 3.3
+NVIDIA GTS 350M .*NVIDIA .*GTS 35[0-9]M.* 4 1 1 3.3
+NVIDIA GTS 360M .*NVIDIA .*GTS 36[0-9]M.* 5 1 1 3.3
+NVIDIA 400M .*NVIDIA .* 40[0-9]M.* 2 1 0 0
+NVIDIA 410M .*NVIDIA .* 41[0-9]M.* 3 1 0 0
+NVIDIA GT 420M .*NVIDIA .*GT 42[0-9]M.* 3 1 1 4.2
+NVIDIA GT 430M .*NVIDIA .*GT 43[0-9]M.* 3 1 1 4.2
+NVIDIA GT 440M .*NVIDIA .*GT 44[0-9]M.* 3 1 1 4.2
+NVIDIA GT 450M .*NVIDIA .*GT 45[0-9]M.* 3 1 0 0
+NVIDIA GTX 460M .*NVIDIA .*GTX 46[0-9]M.* 4 1 1 4.3
+NVIDIA GTX 470M .*NVIDIA .*GTX 47[0-9]M.* 3 1 0 4.2
+NVIDIA GTX 480M .*NVIDIA .*GTX 48[0-9]M.* 3 1 1 4.2
+NVIDIA GT 520M .*NVIDIA .*GT 52[0-9]M.* 3 1 1 4.2
+NVIDIA GT 530M .*NVIDIA .*GT 53[0-9]M.* 3 1 1 4.2
+NVIDIA GT 540M .*NVIDIA .*GT 54[0-9]M.* 3 1 1 4.2
+NVIDIA GT 550M .*GeForce GT 55[0-9]M.* 3 1 1 4.2
+NVIDIA GTX 560M .*NVIDIA .*GTX 56[0-9]M.* 3 1 0 4.2
+NVIDIA GTX 570M .*NVIDIA .*GTX 57[0-9]M.* 5 1 0 4.2
+NVIDIA GTX 580M .*NVIDIA .*GTX 58[0-9]M.* 5 1 1 4.2
+NVIDIA 610M .*NVIDIA.* 61[0-9]M.* 3 1 1 4.2
+NVIDIA GT 620M .*NVIDIA .*GT 62[0-9]M.* 3 1 0 4.2
+NVIDIA GT 630M .*NVIDIA .*GT 63[0-9]M.* 3 1 0 4.2
+NVIDIA GT 640M .*NVIDIA .*GT 64[0-9]M.* 3 1 0 4.2
+NVIDIA GT 650M .*NVIDIA .*GT 65[0-9]M.* 3 1 0 4.2
+NVIDIA GTX 660M .*NVIDIA .*GTX 66[0-9]M.* 5 1 0 4.3
+NVIDIA GTX 670M .*NVIDIA .*GTX 67[0-9]M.* 5 1 1 4.2
+NVIDIA GTX 680M .*NVIDIA .*GTX 68[0-9]M.* 5 1 0 4.2
+NVIDIA GTX 690M .*NVIDIA .*GTX 69[0-9]M.* 5 1 0 0
NVIDIA G100 .*NVIDIA .*G10.* 3 1 1 4.2
-NVIDIA GT 120 .*NVIDIA .*GT *12.* 2 1 0 3
-NVIDIA GT 130 .*NVIDIA .*GT *13.* 2 1 0 3.3
-NVIDIA GTS 150 .*NVIDIA .*GTS *15.* 2 1 0 0
+NVIDIA GT 120 .*NVIDIA .*GT 12.* 2 1 0 3.3
+NVIDIA GT 130 .*NVIDIA .*GT 13.* 2 1 0 3.3
+NVIDIA GT 140 .*NVIDIA .*GT 14.* 2 1 0 3.3
+NVIDIA GTS 150 .*NVIDIA .*GTS 15.* 2 1 0 0
NVIDIA 200 .*NVIDIA .*GeForce 20.* 2 1 1 3.3
NVIDIA G200 .*NVIDIA .*GeForce G20.* 2 1 1 3.3
NVIDIA G210 .*NVIDIA .*GeForce G210.* 3 1 1 3.3
NVIDIA 210 .*NVIDIA .*GeForce 210.* 3 1 1 3.3
-NVIDIA GT 220 .*NVIDIA .*GT *22.* 2 1 1 3.3
-NVIDIA GT 230 .*NVIDIA .*GT *23.* 2 1 1 3.3
-NVIDIA GT 240 .*NVIDIA .*GT *24.* 4 1 1 3.3
-NVIDIA GTS 240 .*NVIDIA .*GTS *24.* 4 1 1 3.3
-NVIDIA GTS 250 .*NVIDIA .*GTS *25.* 4 1 1 3.3
-NVIDIA GTX 260 .*NVIDIA .*GTX *26.* 4 1 1 3.3
-NVIDIA GTX 270 .*NVIDIA .*GTX *27.* 4 1 0 3.3
-NVIDIA GTX 280 .*NVIDIA .*GTX *28.* 4 1 1 3.3
-NVIDIA GTX 290 .*NVIDIA .*GTX *29.* 5 1 0 3.3
+NVIDIA GT 220 .*NVIDIA .*GT 22.* 2 1 1 3.3
+NVIDIA GT 230 .*NVIDIA .*GT 23.* 2 1 1 3.3
+NVIDIA GT 240 .*NVIDIA .*GT 24.* 4 1 1 3.3
+NVIDIA GTS 240 .*NVIDIA .*GTS 24.* 4 1 1 3.3
+NVIDIA GTS 250 .*NVIDIA .*GTS 25.* 4 1 1 3.3
+NVIDIA GTX 260 .*NVIDIA .*GTX 26.* 4 1 1 3.3
+NVIDIA GTX 270 .*NVIDIA .*GTX 27.* 4 1 0 3.3
+NVIDIA GTX 280 .*NVIDIA .*GTX 28.* 4 1 1 3.3
+NVIDIA GTX 290 .*NVIDIA .*GTX 29.* 5 1 0 3.3
NVIDIA 310 .*NVIDIA .*GeForce 310.* 3 1 1 3.3
NVIDIA 315 .*NVIDIA .*GeForce 315.* 3 1 1 3.3
-NVIDIA GT 320 .*NVIDIA .*GT *32.* 3 1 0 3.3
-NVIDIA GT 330 .*NVIDIA .*GT *33.* 3 1 0 3.3
-NVIDIA GT 340 .*NVIDIA .*GT *34.* 3 1 0 0
+NVIDIA GT 320 .*NVIDIA .*GT 32.* 3 1 0 3.3
+NVIDIA GT 330 .*NVIDIA .*GT 33.* 3 1 0 3.3
+NVIDIA GT 340 .*NVIDIA .*GT 34.* 3 1 0 3.3
NVIDIA 405 .*NVIDIA .* 405.* 3 1 0 3.3
-NVIDIA GT 420 .*NVIDIA .*GT *42.* 3 1 1 4.2
-NVIDIA GT 430 .*NVIDIA .*GT *43.* 3 1 1 4.2
-NVIDIA GT 440 .*NVIDIA .*GT *44.* 4 1 0 4.2
-NVIDIA GTS 450 .*NVIDIA .*GTS *45.* 4 1 1 4.2
-NVIDIA GTX 460 .*NVIDIA .*GTX *46.* 5 1 1 4.3
-NVIDIA GTX 470 .*NVIDIA .*GTX *47.* 5 1 1 4.2
-NVIDIA GTX 480 .*NVIDIA .*GTX *48.* 5 1 1 4.2
-NVIDIA 510 .*NVIDIA .* 510.* 3 1 0 0
-NVIDIA GT 520 .*NVIDIA .*GT *52.* 3 1 1 4.2
-NVIDIA GT 530 .*NVIDIA .*GT *53.* 3 1 1 4.2
-NVIDIA GT 540 .*NVIDIA .*GT *54.* 3 1 1 4.2
-NVIDIA GTX 550 .*NVIDIA .*GTX *55.* 5 1 1 4.3
-NVIDIA GTX 560 .*NVIDIA .*GTX *56.* 5 1 1 4.2
-NVIDIA GTX 570 .*NVIDIA .*GTX *57.* 5 1 1 4.2
-NVIDIA GTX 580 .*NVIDIA .*GTX *58.* 5 1 1 4.3
-NVIDIA GTX 590 .*NVIDIA .*GTX *59.* 5 1 1 4.2
-NVIDIA GT 610 .*NVIDIA .*GT *61.* 3 1 1 4.2
-NVIDIA GT 620 .*NVIDIA .*GT *62.* 3 1 0 4.2
-NVIDIA GT 630 .*NVIDIA .*GT *63.* 3 1 0 4.2
-NVIDIA GT 640 .*NVIDIA .*GT *64.* 3 1 0 4.3
-NVIDIA GT 650 .*NVIDIA .*GT *65.* 3 1 1 4.2
-NVIDIA GTX 650 .*NVIDIA .*GTX *65.* 3 1 1 4.2
-NVIDIA GTX 660 .*NVIDIA .*GTX *66.* 5 1 0 4.3
-NVIDIA GTX 670 .*NVIDIA .*GTX *67.* 5 1 1 4.2
-NVIDIA GTX 680 .*NVIDIA .*GTX *68.* 5 1 1 4.2
-NVIDIA GTX 690 .*NVIDIA .*GTX *69.* 5 1 1 4.2
+NVIDIA GT 420 .*NVIDIA .*GT 42.* 3 1 1 4.2
+NVIDIA GT 430 .*NVIDIA .*GT 43.* 3 1 1 4.3
+NVIDIA GT 440 .*NVIDIA .*GT 44.* 4 1 0 4.3
+NVIDIA GTS 450 .*NVIDIA .*GTS 45.* 4 1 1 4.2
+NVIDIA GTX 460 .*NVIDIA .*GTX 46.* 5 1 1 4.3
+NVIDIA GTX 470 .*NVIDIA .*GTX 47.* 5 1 1 4.2
+NVIDIA GTX 480 .*NVIDIA .*GTX 48.* 5 1 1 4.2
+NVIDIA 510 .*NVIDIA .* 510.* 3 1 0 4.2
+NVIDIA GT 520 .*NVIDIA .*GT 52.* 3 1 1 4.2
+NVIDIA GT 530 .*NVIDIA .*GT 53.* 3 1 1 4.2
+NVIDIA GT 540 .*NVIDIA .*GT 54.* 3 1 1 4.2
+NVIDIA GTX 550 .*NVIDIA .*GTX 55.* 5 1 1 4.3
+NVIDIA GTX 560 .*NVIDIA .*GTX 56.* 5 1 1 4.3
+NVIDIA GTX 570 .*NVIDIA .*GTX 57.* 5 1 1 4.2
+NVIDIA GTX 580 .*NVIDIA .*GTX 58.* 5 1 1 4.3
+NVIDIA GTX 590 .*NVIDIA .*GTX 59.* 5 1 1 4.2
+NVIDIA 605 .*NVIDIA .* 605.* 3 1 1 4.2
+NVIDIA GT 610 .*NVIDIA .*GT 61.* 3 1 1 4.2
+NVIDIA GT 620 .*NVIDIA .*GT 62.* 3 1 0 4.2
+NVIDIA GT 630 .*NVIDIA .*GT 63.* 3 1 0 4.2
+NVIDIA GT 640 .*NVIDIA .*GT 64.* 3 1 0 4.2
+NVIDIA GT 650 .*NVIDIA .*GT 65.* 3 1 1 4.2
+NVIDIA GTX 650 .*NVIDIA .*GTX 65.* 3 1 1 4.2
+NVIDIA GTX 660 .*NVIDIA .*GTX 66.* 5 1 0 4.3
+NVIDIA GTX 670 .*NVIDIA .*GTX 67.* 5 1 1 4.2
+NVIDIA GTX 680 .*NVIDIA .*GTX 68.* 5 1 1 4.2
+NVIDIA GTX 690 .*NVIDIA .*GTX 69.* 5 1 1 4.2
NVIDIA C51 .*NVIDIA .*C51.* 0 1 1 2
NVIDIA G72 .*NVIDIA .*G72.* 1 1 0 0
NVIDIA G73 .*NVIDIA .*G73.* 1 1 0 0
@@ -437,13 +407,7 @@ NVIDIA G86 .*NVIDIA .*G86.* 3 1 0 0
NVIDIA G92 .*NVIDIA .*G92.* 3 1 0 0
NVIDIA GeForce .*GeForce 256.* 0 0 0 0
NVIDIA GeForce 2 .*GeForce ?2 ?.* 0 1 1 1.5
-NVIDIA GeForce 3 .*GeForce ?3 ?.* 2 1 1 2.1
-NVIDIA GeForce 3 Ti .*GeForce ?3 Ti.* 0 1 0 0
NVIDIA GeForce 4 .*NVIDIA .*GeForce ?4.* 0 1 1 1.5
-NVIDIA GeForce 4 Go .*NVIDIA .*GeForce ?4.*Go.* 0 1 0 0
-NVIDIA GeForce 4 MX .*NVIDIA .*GeForce ?4 MX.* 0 1 0 0
-NVIDIA GeForce 4 PCX .*NVIDIA .*GeForce ?4 PCX.* 0 1 0 0
-NVIDIA GeForce 4 Ti .*NVIDIA .*GeForce ?4 Ti.* 0 1 0 0
NVIDIA GeForce 6100 .*NVIDIA .*GeForce 61.* 3 1 1 4.2
NVIDIA GeForce 6200 .*NVIDIA .*GeForce 62.* 0 1 1 2.1
NVIDIA GeForce 6500 .*NVIDIA .*GeForce 65.* 1 1 1 2.1
@@ -458,33 +422,33 @@ NVIDIA GeForce 7500 .*NVIDIA .*GeForce 75.* 2 1 1 2.1
NVIDIA GeForce 7600 .*NVIDIA .*GeForce 76.* 2 1 1 2.1
NVIDIA GeForce 7800 .*NVIDIA .*GeForce 78.* 2 1 1 2.1
NVIDIA GeForce 7900 .*NVIDIA .*GeForce 79.* 3 1 1 2.1
-NVIDIA GeForce 8100 .*NVIDIA .*GeForce 81.* 1 1 0 0
-NVIDIA GeForce 8200M .*NVIDIA .*GeForce 8200M.* 1 1 0 3.3
-NVIDIA GeForce 8200 .*NVIDIA .*GeForce 82.* 1 1 0 2.1
+NVIDIA GeForce 8100 .*NVIDIA .*GeForce 81.* 1 1 0 3.3
+NVIDIA GeForce 8200M .*NVIDIA .*GeForce 820[0-9]M.* 1 1 0 3.3
+NVIDIA GeForce 8200 .*NVIDIA .*GeForce 82.* 1 1 0 3.3
NVIDIA GeForce 8300 .*NVIDIA .*GeForce 83.* 3 1 1 3.3
-NVIDIA GeForce 8400M .*NVIDIA .*GeForce 8400M.* 1 1 1 3.3
+NVIDIA GeForce 8400M .*NVIDIA .*GeForce 840[0-9]M.* 1 1 1 3.3
NVIDIA GeForce 8400 .*NVIDIA .*GeForce 84.* 2 1 1 3.3
NVIDIA GeForce 8500 .*NVIDIA .*GeForce 85.* 2 1 1 3.3
-NVIDIA GeForce 8600M .*NVIDIA .*GeForce 8600M.* 2 1 1 3.3
+NVIDIA GeForce 8600M .*NVIDIA .*GeForce 860[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 8600 .*NVIDIA .*GeForce 86.* 3 1 1 3.3
-NVIDIA GeForce 8700M .*NVIDIA .*GeForce 8700M.* 2 1 1 3.3
+NVIDIA GeForce 8700M .*NVIDIA .*GeForce 870[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 8700 .*NVIDIA .*GeForce 87.* 3 1 0 0
-NVIDIA GeForce 8800M .*NVIDIA .*GeForce 8800M.* 2 1 1 3.3
+NVIDIA GeForce 8800M .*NVIDIA .*GeForce 880[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 8800 .*NVIDIA .*GeForce 88.* 3 1 1 3.3
-NVIDIA GeForce 9100M .*NVIDIA .*GeForce 9100M.* 0 1 0 0
+NVIDIA GeForce 9100M .*NVIDIA .*GeForce 910[0-9]M.* 0 1 0 3.3
NVIDIA GeForce 9100 .*NVIDIA .*GeForce 91.* 0 1 0 3.3
-NVIDIA GeForce 9200M .*NVIDIA .*GeForce 9200M.* 1 1 0 3.1
+NVIDIA GeForce 9200M .*NVIDIA .*GeForce 920[0-9]M.* 1 1 0 3.3
NVIDIA GeForce 9200 .*NVIDIA .*GeForce 92.* 1 1 0 3.3
-NVIDIA GeForce 9300M .*NVIDIA .*GeForce 9300M.* 1 1 1 3.3
+NVIDIA GeForce 9300M .*NVIDIA .*GeForce 930[0-9]M.* 1 1 1 3.3
NVIDIA GeForce 9300 .*NVIDIA .*GeForce 93.* 1 1 1 3.3
-NVIDIA GeForce 9400M .*NVIDIA .*GeForce 9400M.* 2 1 1 3.3
+NVIDIA GeForce 9400M .*NVIDIA .*GeForce 940[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 9400 .*NVIDIA .*GeForce 94.* 3 1 1 3.3
-NVIDIA GeForce 9500M .*NVIDIA .*GeForce 9500M.* 1 1 1 3.3
+NVIDIA GeForce 9500M .*NVIDIA .*GeForce 950[0-9]M.* 1 1 1 3.3
NVIDIA GeForce 9500 .*NVIDIA .*GeForce 95.* 3 1 1 3.3
-NVIDIA GeForce 9600M .*NVIDIA .*GeForce 9600M.* 2 1 1 3.3
+NVIDIA GeForce 9600M .*NVIDIA .*GeForce 960[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 9600 .*NVIDIA .*GeForce 96.* 3 1 1 3.3
-NVIDIA GeForce 9700M .*NVIDIA .*GeForce 9700M.* 0 1 1 3.3
-NVIDIA GeForce 9800M .*NVIDIA .*GeForce 9800M.* 2 1 1 3.3
+NVIDIA GeForce 9700M .*NVIDIA .*GeForce 970[0-9]M.* 0 1 1 3.3
+NVIDIA GeForce 9800M .*NVIDIA .*GeForce 980[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 9800 .*NVIDIA .*GeForce 98.* 3 1 1 3.3
NVIDIA GeForce FX 5100 .*NVIDIA .*GeForce FX 51.* 0 1 0 0
NVIDIA GeForce FX 5200 .*NVIDIA .*GeForce FX 52.* 0 1 0 2.1
@@ -495,7 +459,7 @@ NVIDIA GeForce FX 5700 .*NVIDIA .*GeForce FX 57.* 0 1 1 2.1
NVIDIA GeForce FX 5800 .*NVIDIA .*GeForce FX 58.* 1 1 0 0
NVIDIA GeForce FX 5900 .*NVIDIA .*GeForce FX 59.* 1 1 1 2.1
NVIDIA GeForce FX Go5100 .*NVIDIA .*GeForce FX Go51.* 0 1 0 0
-NVIDIA GeForce FX Go5200 .*NVIDIA .*GeForce FX Go52.* 0 1 0 0
+NVIDIA GeForce FX Go5200 .*NVIDIA .*GeForce FX Go52.* 0 1 0 1.5
NVIDIA GeForce FX Go5300 .*NVIDIA .*GeForce FX Go53.* 0 1 0 0
NVIDIA GeForce FX Go5500 .*NVIDIA .*GeForce FX Go55.* 0 1 0 0
NVIDIA GeForce FX Go5600 .*NVIDIA .*GeForce FX Go56.* 0 1 1 2.1
@@ -504,13 +468,13 @@ NVIDIA GeForce FX Go5800 .*NVIDIA .*GeForce FX Go58.* 1 1 0 0
NVIDIA GeForce FX Go5900 .*NVIDIA .*GeForce FX Go59.* 1 1 0 0
NVIDIA GeForce FX Go5xxx .*NVIDIA .*GeForce FX Go.* 0 1 0 0
NVIDIA GeForce Go 6100 .*NVIDIA .*GeForce Go 61.* 0 1 1 2.1
-NVIDIA GeForce Go 6200 .*NVIDIA .*GeForce Go 62.* 0 1 0 0
-NVIDIA GeForce Go 6400 .*NVIDIA .*GeForce Go 64.* 1 1 1 2
+NVIDIA GeForce Go 6200 .*NVIDIA .*GeForce Go 62.* 0 1 0 1.5
+NVIDIA GeForce Go 6400 .*NVIDIA .*GeForce Go 64.* 1 1 1 2.1
NVIDIA GeForce Go 6500 .*NVIDIA .*GeForce Go 65.* 1 1 0 0
NVIDIA GeForce Go 6600 .*NVIDIA .*GeForce Go 66.* 0 1 1 2.1
NVIDIA GeForce Go 6700 .*NVIDIA .*GeForce Go 67.* 1 1 0 0
NVIDIA GeForce Go 6800 .*NVIDIA .*GeForce Go 68.* 0 1 1 2.1
-NVIDIA GeForce Go 7200 .*NVIDIA .*GeForce Go 72.* 1 1 0 0
+NVIDIA GeForce Go 7200 .*NVIDIA .*GeForce Go 72.* 1 1 0 2.1
NVIDIA GeForce Go 7300 LE .*NVIDIA .*GeForce Go 73.*LE.* 1 1 0 0
NVIDIA GeForce Go 7300 .*NVIDIA .*GeForce Go 73.* 1 1 1 2.1
NVIDIA GeForce Go 7400 .*NVIDIA .*GeForce Go 74.* 1 1 1 2.1
@@ -528,9 +492,9 @@ NVIDIA NB8P .*NVIDIA .*NB8P.* 2 1 0 0
NVIDIA NB9E .*NVIDIA .*NB9E.* 3 1 0 0
NVIDIA NB9M .*NVIDIA .*NB9M.* 1 1 0 0
NVIDIA NB9P .*NVIDIA .*NB9P.* 2 1 0 0
-NVIDIA N10 .*NVIDIA .*N10.* 1 1 0 0
-NVIDIA GeForce PCX .*GeForce PCX.* 0 1 0 0
-NVIDIA Generic .*NVIDIA .*Unknown.* 0 0 0 3
+NVIDIA N10 .*NVIDIA .*N10.* 1 1 0 2.1
+NVIDIA GeForce PCX .*GeForce PCX.* 0 1 0 1.5
+NVIDIA Generic .*NVIDIA .*Unknown.* 0 0 0 2.1
NVIDIA NV17 .*NVIDIA .*NV17.* 0 1 0 0
NVIDIA NV34 .*NVIDIA .*NV34.* 0 1 0 0
NVIDIA NV35 .*NVIDIA .*NV35.* 0 1 0 0
@@ -540,7 +504,7 @@ NVIDIA NV43 .*NVIDIA .*NV43.* 1 1 0 0
NVIDIA NV44 .*NVIDIA .*NV44.* 1 1 0 0
NVIDIA nForce .*NVIDIA .*nForce.* 0 0 0 3.3
NVIDIA MCP51 .*NVIDIA .*MCP51.* 1 1 0 0
-NVIDIA MCP61 .*NVIDIA .*MCP61.* 1 1 0 0
+NVIDIA MCP61 .*NVIDIA .*MCP61.* 1 1 0 2.1
NVIDIA MCP67 .*NVIDIA .*MCP67.* 1 1 0 0
NVIDIA MCP68 .*NVIDIA .*MCP68.* 1 1 0 0
NVIDIA MCP73 .*NVIDIA .*MCP73.* 1 1 0 0
@@ -548,44 +512,44 @@ NVIDIA MCP77 .*NVIDIA .*MCP77.* 1 1 0 0
NVIDIA MCP78 .*NVIDIA .*MCP78.* 1 1 0 0
NVIDIA MCP79 .*NVIDIA .*MCP79.* 1 1 0 0
NVIDIA MCP7A .*NVIDIA .*MCP7A.* 1 1 0 0
-NVIDIA Quadro2 .*Quadro2.* 0 1 0 0
-NVIDIA Quadro 1000M .*Quadro.*1000M.* 2 1 0 4.2
-NVIDIA Quadro 2000 M/D .*Quadro.*2000.* 3 1 0 4.2
-NVIDIA Quadro 3000M .*Quadro.*3000M.* 3 1 0 0
-NVIDIA Quadro 4000M .*Quadro.*4000M.* 3 1 0 0
-NVIDIA Quadro 4000 .*Quadro *4000.* 3 1 0 4.2
-NVIDIA Quadro 50x0 M .*Quadro.*50.0.* 3 1 0 0
+NVIDIA Quadro2 .*Quadro2.* 0 1 0 1.5
+NVIDIA Quadro 1000M .*Quadro.* (K1|1)00[0-9]M.* 2 1 0 4.2
+NVIDIA Quadro 2000 M/D .*Quadro.* (K2|2)000.* 3 1 0 4.2
+NVIDIA Quadro 3000M .*Quadro.* (K3|3)00[0-9]M.* 3 1 0 4.2
+NVIDIA Quadro 4000M .*Quadro.* (K4|4)00[0-9]M.* 3 1 0 4.2
+NVIDIA Quadro 4000 .*Quadro 4000.* 3 1 0 4.2
+NVIDIA Quadro 50x0 M .*Quadro.* 50.0.* 3 1 0 4.2
NVIDIA Quadro 6000 .*Quadro.* 6000.* 3 1 0 0
NVIDIA Quadro 400 .*Quadro.* 400.* 2 1 0 3.3
-NVIDIA Quadro 600 .*Quadro.*600.* 2 1 0 3.3
-NVIDIA Quadro4 .*Quadro4.* 0 1 0 0
+NVIDIA Quadro 600 .*Quadro.* 600.* 2 1 0 4.2
+NVIDIA Quadro4 .*Quadro4.* 0 1 0 1.5
NVIDIA Quadro DCC .*Quadro DCC.* 0 1 0 0
NVIDIA Quadro CX .*Quadro.*CX.* 3 1 0 0
-NVIDIA Quadro FX 770M .*Quadro.*FX *770M.* 2 1 0 0
-NVIDIA Quadro FX 1500M .*Quadro.*FX *1500M.* 1 1 0 2.1
-NVIDIA Quadro FX 1600M .*Quadro.*FX *1600M.* 2 1 0 0
-NVIDIA Quadro FX 2500M .*Quadro.*FX *2500M.* 2 1 0 0
-NVIDIA Quadro FX 2700M .*Quadro.*FX *2700M.* 3 1 0 0
-NVIDIA Quadro FX 2800M .*Quadro.*FX *2800M.* 3 1 0 3.3
-NVIDIA Quadro FX 3500 .*Quadro.*FX *3500.* 2 1 0 2.1
-NVIDIA Quadro FX 3600 .*Quadro.*FX *3600.* 3 1 0 0
-NVIDIA Quadro FX 3700 .*Quadro.*FX *3700.* 3 1 0 3.3
-NVIDIA Quadro FX 3800 .*Quadro.*FX *3800.* 3 1 0 3.2
-NVIDIA Quadro FX 4500 .*Quadro.*FX *45.* 3 1 0 0
-NVIDIA Quadro FX 880M .*Quadro.*FX *880M.* 3 1 0 3.3
-NVIDIA Quadro FX 4800 .*NVIDIA .*Quadro *FX *4800.* 3 1 0 0
+NVIDIA Quadro FX 770M .*Quadro.*FX 77[0-9]M.* 2 1 0 3.3
+NVIDIA Quadro FX 1500M .*Quadro.*FX 150[0-9]M.* 1 1 0 2.1
+NVIDIA Quadro FX 1600M .*Quadro.*FX 160[0-9]M.* 2 1 0 3.3
+NVIDIA Quadro FX 2500M .*Quadro.*FX 250[0-9]M.* 2 1 0 2.1
+NVIDIA Quadro FX 2700M .*Quadro.*FX 270[0-9]M.* 3 1 0 3.3
+NVIDIA Quadro FX 2800M .*Quadro.*FX 280[0-9]M.* 3 1 0 3.3
+NVIDIA Quadro FX 3500 .*Quadro.*FX 3500.* 2 1 0 2.1
+NVIDIA Quadro FX 3600 .*Quadro.*FX 3600.* 3 1 0 3.3
+NVIDIA Quadro FX 3700 .*Quadro.*FX 3700.* 3 1 0 3.3
+NVIDIA Quadro FX 3800 .*Quadro.*FX 3800.* 3 1 0 3.3
+NVIDIA Quadro FX 4500 .*Quadro.*FX 45.* 3 1 0 2.1
+NVIDIA Quadro FX 880M .*Quadro.*FX 88[0-9]M.* 3 1 0 3.3
+NVIDIA Quadro FX 4800 .*NVIDIA .*Quadro FX 4800.* 3 1 0 3.1
NVIDIA Quadro FX .*Quadro FX.* 1 1 0 3.3
-NVIDIA Quadro NVS 1xxM .*Quadro NVS *1.[05]M.* 0 1 1 3.3
-NVIDIA Quadro NVS 300M .*NVIDIA .*NVS *300M.* 2 1 0 0
-NVIDIA Quadro NVS 320M .*NVIDIA .*NVS *320M.* 2 1 0 0
-NVIDIA Quadro NVS 2100M .*NVIDIA .*NVS *2100M.* 2 1 0 0
-NVIDIA Quadro NVS 3100M .*NVIDIA .*NVS *3100M.* 2 1 0 0
-NVIDIA Quadro NVS 4200M .*NVIDIA .*NVS *4200M.* 2 1 0 4.1
-NVIDIA Quadro NVS 5100M .*NVIDIA .*NVS *5100M.* 2 1 0 0
-NVIDIA Quadro NVS .*NVIDIA .*NVS 0 1 0 3.2
+NVIDIA Quadro NVS 1xxM .*Quadro NVS 1.[05]M.* 0 1 1 3.3
+NVIDIA Quadro NVS 300M .*NVIDIA .*NVS 30[0-9]M.* 2 1 0 0
+NVIDIA Quadro NVS 320M .*NVIDIA .*NVS 32[0-9]M.* 2 1 0 0
+NVIDIA Quadro NVS 2100M .*NVIDIA .*NVS 210[0-9]M.* 2 1 0 3.3
+NVIDIA Quadro NVS 3100M .*NVIDIA .*NVS 310[0-9]M.* 2 1 0 3.3
+NVIDIA Quadro NVS 4200M .*NVIDIA .*NVS 420[0-9]M.* 2 1 0 4.2
+NVIDIA Quadro NVS 5100M .*NVIDIA .*NVS 510[0-9]M.* 2 1 0 0
+NVIDIA Quadro NVS .*NVIDIA .*NVS 0 1 0 4.2
NVIDIA Corporation N12P .*NVIDIA .*N12P.* 1 1 1 4.1
-NVIDIA Corporation N11M .*NVIDIA .*N11M.* 2 1 0 0
-NVIDIA RIVA TNT .*RIVA TNT.* 0 0 0 0
+NVIDIA Corporation N11M .*NVIDIA .*N11M.* 2 1 0 3.1
+NVIDIA RIVA TNT .*RIVA TNT.* 0 0 0 1.5
S3 .*S3 Graphics.* 0 0 1 1.4
SiS SiS.* 0 0 1 1.5
Trident Trident.* 0 0 0 0
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index d8440eebf1..c23401d5a6 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -121,37 +121,21 @@ export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}"
-# Have to deal specially with gridargs.dat; typical contents look like:
-# --channel "Second Life Test" --settings settings_test.xml
-# Simply embedding $(<etc/gridargs.dat) into a command line treats each of
-# Second, Life and Developer as separate args -- no good. We need bash to
-# process quotes using eval.
-# First, check if we have been instructed to skip reading in gridargs.dat:
-skip_gridargs=false
-argnum=0
+# Copy "$@" to ARGS array specifically to delete the --skip-gridargs switch.
+# The gridargs.dat file is no more, but we still want to avoid breaking
+# scripts that invoke this one with --skip-gridargs.
+ARGS=()
for ARG in "$@"; do
- if [ "--skip-gridargs" == "$ARG" ]; then
- skip_gridargs=true
- else
- ARGS[$argnum]="$ARG"
- argnum=$(($argnum+1))
+ if [ "--skip-gridargs" != "$ARG" ]; then
+ ARGS[${#ARGS[*]}]="$ARG"
fi
done
-# Second, read it without scanning, then scan that string. Break quoted words
-# into a bash array. Note that if gridargs.dat is empty, or contains only
-# whitespace, the resulting gridargs array will be empty -- zero entries --
-# therefore "${gridargs[@]}" entirely vanishes from the command line below,
-# just as we want.
-if ! $skip_gridargs ; then
- eval gridargs=("$(<etc/gridargs.dat)")
-fi
-
# Run the program.
# Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the
-# command line. But DO quote "$@": preserve separate args as individually
-# quoted. Similar remarks about the contents of gridargs.
-$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${gridargs[@]}" "${ARGS[@]}"
+# command line. But DO quote "${ARGS[@]}": preserve separate args as
+# individually quoted.
+$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${ARGS[@]}"
LL_RUN_ERR=$?
# Handle any resulting errors
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 3e94c5edf7..f4ce3c9118 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -46,6 +46,7 @@
#include "llenvmanager.h"
#include "llfirstuse.h"
#include "llfloatercamera.h"
+#include "llfloaterimcontainer.h"
#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llgroupactions.h"
@@ -91,6 +92,7 @@
#include "llworld.h"
#include "llworldmap.h"
#include "stringize.h"
+#include "boost/foreach.hpp"
using namespace LLAvatarAppearanceDefines;
@@ -433,7 +435,7 @@ void LLAgent::init()
{
mMoveTimer.start();
- gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", LLControlVariable::PERSIST_NO);
gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2));
// *Note: this is where LLViewerCamera::getInstance() used to be constructed.
@@ -2037,7 +2039,16 @@ void LLAgent::endAnimationUpdateUI()
{
skip_list.insert(LLFloaterReg::findInstance("mini_map"));
}
-
+
+ LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
+ LLFloaterIMContainer::floater_list_t conversations;
+ im_box->getDetachedConversationFloaters(conversations);
+ BOOST_FOREACH(LLFloater* conversation, conversations)
+ {
+ llinfos << "skip_list.insert(session_floater): " << conversation->getTitle() << llendl;
+ skip_list.insert(conversation);
+ }
+
gFloaterView->popVisibleAll(skip_list);
#endif
mViewsPushed = FALSE;
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
new file mode 100644
index 0000000000..30476b3d22
--- /dev/null
+++ b/indra/newview/llappdelegate-objc.mm
@@ -0,0 +1,144 @@
+/**
+ * @file llappdelegate-objc.mm
+ * @brief Class implementation for the Mac version's application delegate.
+ *
+ * $LicenseInfo:firstyear=2000&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$
+ */
+
+#import "llappdelegate-objc.h"
+#include "llwindowmacosx-objc.h"
+#include <Carbon/Carbon.h> // Used for Text Input Services ("Safe" API - it's supported)
+
+@implementation LLAppDelegate
+
+@synthesize window;
+@synthesize inputWindow;
+@synthesize inputView;
+@synthesize currentInputLanguage;
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+- (void) applicationDidFinishLaunching:(NSNotification *)notification
+{
+ frameTimer = nil;
+
+ [self languageUpdated];
+
+ if (initViewer())
+ {
+ frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
+ } else {
+ handleQuit();
+ }
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];
+}
+
+- (void) applicationDidBecomeActive:(NSNotification *)notification
+{
+ callWindowFocus();
+}
+
+- (void) applicationDidResignActive:(NSNotification *)notification
+{
+ callWindowUnfocus();
+}
+
+- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender
+{
+ if (!runMainLoop())
+ {
+ handleQuit();
+ return NSTerminateCancel;
+ } else {
+ [frameTimer release];
+ cleanupViewer();
+ return NSTerminateNow;
+ }
+}
+
+- (void) mainLoop
+{
+ bool appExiting = runMainLoop();
+ if (appExiting)
+ {
+ [frameTimer release];
+ [[NSApplication sharedApplication] terminate:self];
+ }
+}
+
+- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent
+{
+ if (![self romanScript])
+ {
+ if (show)
+ {
+ NSLog(@"Showing input window.");
+ [inputWindow makeKeyAndOrderFront:inputWindow];
+ if (textEvent != nil)
+ {
+ [[inputView inputContext] discardMarkedText];
+ [[inputView inputContext] handleEvent:textEvent];
+ }
+ } else {
+ NSLog(@"Hiding input window.");
+ [inputWindow orderOut:inputWindow];
+ [window makeKeyAndOrderFront:window];
+ }
+ }
+}
+
+// This will get called multiple times by NSNotificationCenter.
+// It will be called every time that the window focus changes, and every time that the input language gets changed.
+// The primary use case for this selector is to update our current input language when the user, for whatever reason, changes the input language.
+// This is the more elegant way of handling input language changes instead of checking every time we want to use the input window.
+
+- (void) languageUpdated
+{
+ TISInputSourceRef currentInput = TISCopyCurrentKeyboardInputSource();
+ CFArrayRef languages = (CFArrayRef)TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages);
+
+#if 0 // In the event of ever needing to add new language sources, change this to 1 and watch the terminal for "languages:"
+ NSLog(@"languages: %@", TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages));
+#endif
+
+ // Typically the language we want is going to be the very first result in the array.
+ currentInputLanguage = (NSString*)CFArrayGetValueAtIndex(languages, 0);
+}
+
+- (bool) romanScript
+{
+ // How to add support for new languages with the input window:
+ // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.)
+ NSArray *nonRomanScript = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil];
+ if ([nonRomanScript containsObject:currentInputLanguage])
+ {
+ return false;
+ }
+
+ return true;
+}
+
+@end
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f92274dbbd..becc75203a 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -222,6 +222,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
@@ -668,7 +672,6 @@ LLAppViewer::LLAppViewer() :
mSecondInstance(false),
mSavedFinalSnapshot(false),
mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
- mForceGraphicsDetail(false),
mQuitRequested(false),
mLogoutRequestSent(false),
mYieldTime(-1),
@@ -696,6 +699,7 @@ LLAppViewer::LLAppViewer() :
LLAppViewer::~LLAppViewer()
{
delete mSettingsLocationList;
+ LLViewerEventRecorder::instance().~LLViewerEventRecorder();
LLLoginInstance::instance().setUpdaterService(0);
@@ -724,6 +728,11 @@ bool LLAppViewer::init()
// we run the "program crashed last time" error handler below.
//
LLFastTimer::reset();
+
+
+#ifdef LL_DARWIN
+ mMainLoopInitialized = false;
+#endif
// initialize LLWearableType translation bridge.
// Memory will be cleaned up in ::cleanupClass()
@@ -1254,40 +1263,57 @@ LLFastTimer::DeclareTimer FTM_FRAME("Frame", true);
bool LLAppViewer::mainLoop()
{
- mMainloopTimeout = new LLWatchdogTimeout();
+#ifdef LL_DARWIN
+ if (!mMainLoopInitialized)
+#endif
+ {
+ mMainloopTimeout = new LLWatchdogTimeout();
+
+ //-------------------------------------------
+ // Run main loop until time to quit
+ //-------------------------------------------
+
+ // Create IO Pump to use for HTTP Requests.
+ gServicePump = new LLPumpIO(gAPRPoolp);
+ LLHTTPClient::setPump(*gServicePump);
+ LLCurl::setCAFile(gDirUtilp->getCAFile());
+
+ // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
+
+ LLVoiceChannel::initClass();
+ LLVoiceClient::getInstance()->init(gServicePump);
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
+
+ joystick = LLViewerJoystick::getInstance();
+ joystick->setNeedsReset(true);
+
+#ifdef LL_DARWIN
+ // Ensure that this section of code never gets called again on OS X.
+ mMainLoopInitialized = true;
+#endif
+ }
+ // As we do not (yet) send data on the mainloop LLEventPump that varies
+ // with each frame, no need to instantiate a new LLSD event object each
+ // time. Obviously, if that changes, just instantiate the LLSD at the
+ // point of posting.
+
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+
+ LLSD newFrame;
- //-------------------------------------------
- // Run main loop until time to quit
- //-------------------------------------------
-
- // Create IO Pump to use for HTTP Requests.
- gServicePump = new LLPumpIO(gAPRPoolp);
- LLHTTPClient::setPump(*gServicePump);
- LLCurl::setCAFile(gDirUtilp->getCAFile());
-
- // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
-
- LLVoiceChannel::initClass();
- LLVoiceClient::getInstance()->init(gServicePump);
- LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
- LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
- joystick->setNeedsReset(true);
-
- LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
- // As we do not (yet) send data on the mainloop LLEventPump that varies
- // with each frame, no need to instantiate a new LLSD event object each
- // time. Obviously, if that changes, just instantiate the LLSD at the
- // point of posting.
- LLSD newFrame;
-
+
//LLPrivateMemoryPoolTester::getInstance()->run(false) ;
//LLPrivateMemoryPoolTester::getInstance()->run(true) ;
//LLPrivateMemoryPoolTester::destroy() ;
// Handle messages
+#ifdef LL_DARWIN
+ if (!LLApp::isExiting())
+#else
while (!LLApp::isExiting())
+#endif
{
LLFastTimer _(FTM_FRAME);
LLFastTimer::nextFrame();
@@ -1563,34 +1589,37 @@ bool LLAppViewer::mainLoop()
}
}
- // Save snapshot for next time, if we made it through initialization
- if (STATE_STARTED == LLStartUp::getStartupState())
+ if (LLApp::isExiting())
{
- try
- {
- saveFinalSnapshot();
- }
- catch(std::bad_alloc)
+ // Save snapshot for next time, if we made it through initialization
+ if (STATE_STARTED == LLStartUp::getStartupState())
{
- llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
-
- //stop memory leaking simulation
- LLFloaterMemLeak* mem_leak_instance =
- LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
- if(mem_leak_instance)
+ try
{
- mem_leak_instance->stop() ;
- }
+ saveFinalSnapshot();
+ }
+ catch(std::bad_alloc)
+ {
+ llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
+
+ //stop memory leaking simulation
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
+ {
+ mem_leak_instance->stop() ;
+ }
+ }
}
+
+ delete gServicePump;
+
+ destroyMainloopTimeout();
+
+ llinfos << "Exiting main_loop" << llendflush;
}
-
- delete gServicePump;
- destroyMainloopTimeout();
-
- llinfos << "Exiting main_loop" << llendflush;
-
- return true;
+ return LLApp::isExiting();
}
void LLAppViewer::flushVFSIO()
@@ -2223,13 +2252,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;
}
@@ -2258,7 +2287,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
@@ -2272,7 +2301,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;
}
}
}
@@ -2307,17 +2336,24 @@ void LLAppViewer::loadColorSettings()
LLUIColorTable::instance().loadFromSettings();
}
+namespace
+{
+ void handleCommandLineError(LLControlGroupCLP& clp)
+ {
+ llwarns << "Error parsing command line options. Command Line options ignored." << llendl;
+
+ llinfos << "Command line usage:\n" << clp << llendl;
+
+ OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()),
+ LLStringUtil::null,
+ OSMB_OK);
+ }
+} // anonymous namespace
+
bool LLAppViewer::initConfiguration()
{
//Load settings files list
std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
- //LLControlGroup settings_control("SettingsFiles");
- //llinfos << "Loading settings file list " << settings_file_list << llendl;
- //if (0 == settings_control.loadFromFile(settings_file_list))
- //{
- // llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
- //}
-
LLXMLNodePtr root;
BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);
if (!success)
@@ -2361,8 +2397,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
@@ -2376,9 +2410,7 @@ bool LLAppViewer::initConfiguration()
{
c->setValue(true, false);
}
-#endif
-#ifndef LL_RELEASE_FOR_DOWNLOAD
gSavedSettings.setBOOL("QAMode", TRUE );
gSavedSettings.setS32("WatchdogEnabled", 0);
#endif
@@ -2414,13 +2446,7 @@ bool LLAppViewer::initConfiguration()
if(!initParseCommandLine(clp))
{
- llwarns << "Error parsing command line options. Command Line options ignored." << llendl;
-
- llinfos << "Command line usage:\n" << clp << llendl;
-
- std::ostringstream msg;
- msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage();
- OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
+ handleCommandLineError(clp);
return false;
}
@@ -2434,8 +2460,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
@@ -2451,8 +2477,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");
@@ -2460,19 +2486,23 @@ 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");
// - apply command line settings
- clp.notify();
+ if (! clp.notify())
+ {
+ handleCommandLineError(clp);
+ return false;
+ }
// Register the core crash option as soon as we can
// if we want gdb post-mortem on cores we need to be up and running
// ASAP or we might miss init issue etc.
- if(clp.hasOption("disablecrashlogger"))
+ if(gSavedSettings.getBOOL("DisableCrashLogger"))
{
llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl;
LLAppViewer::instance()->disableCrashlogger();
@@ -2545,91 +2575,56 @@ bool LLAppViewer::initConfiguration()
}
}
- if(clp.hasOption("channel"))
- {
- LLVersionInfo::resetChannel(clp.getOption("channel")[0]);
- }
+ if (clp.hasOption("logevents")) {
+ LLViewerEventRecorder::instance().setEventLoggingOn();
+ }
- // If we have specified crash on startup, set the global so we'll trigger the crash at the right time
- if(clp.hasOption("crashonstartup"))
+ std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
+ if(! CmdLineChannel.empty())
{
- gCrashOnStartup = TRUE;
+ LLVersionInfo::resetChannel(CmdLineChannel);
}
- if (clp.hasOption("logperformance"))
+ // If we have specified crash on startup, set the global so we'll trigger the crash at the right time
+ gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup");
+
+ if (gSavedSettings.getBOOL("LogPerformance"))
{
LLFastTimer::sLog = TRUE;
LLFastTimer::sLogName = std::string("performance");
}
-
- if (clp.hasOption("logmetrics"))
- {
- LLFastTimer::sMetricLog = TRUE ;
- // '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test
- // In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...)
- std::string test_name = clp.getOption("logmetrics")[0];
+
+ std::string test_name(gSavedSettings.getString("LogMetrics"));
+ if (! test_name.empty())
+ {
+ 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;
- if (test_name == "")
- {
- llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl;
- LLFastTimer::sLogName = DEFAULT_METRIC_NAME;
- }
- else
- {
- LLFastTimer::sLogName = test_name;
- }
+ LLFastTimer::sLogName = test_name;
}
if (clp.hasOption("graphicslevel"))
{
- const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel");
- if(value.size() != 1)
- {
- llwarns << "Usage: -graphicslevel <0-3>" << llendl;
- }
- else
- {
- std::string detail = value.front();
- mForceGraphicsDetail = TRUE;
-
- switch (detail.c_str()[0])
- {
- case '0':
- gSavedSettings.setU32("RenderQualityPerformance", 0);
- break;
- case '1':
- gSavedSettings.setU32("RenderQualityPerformance", 1);
- break;
- case '2':
- gSavedSettings.setU32("RenderQualityPerformance", 2);
- break;
- case '3':
- gSavedSettings.setU32("RenderQualityPerformance", 3);
- break;
- default:
- mForceGraphicsDetail = FALSE;
- llwarns << "Usage: -graphicslevel <0-3>" << llendl;
- break;
- }
- }
- }
-
- if (clp.hasOption("analyzeperformance"))
- {
- LLFastTimerView::sAnalyzePerformance = TRUE;
+ // User explicitly requested --graphicslevel on the command line. We
+ // expect this switch has already set RenderQualityPerformance. Check
+ // 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;
+ }
}
- if (clp.hasOption("replaysession"))
- {
- gAgentPilot.setReplaySession(TRUE);
- }
+ LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance");
+ gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession"));
- if (clp.hasOption("nonotifications"))
- {
- gSavedSettings.getControl("IgnoreAllNotifications")->setValue(true, false);
- }
-
- if (clp.hasOption("debugsession"))
+ if (gSavedSettings.getBOOL("DebugSession"))
{
gDebugSession = TRUE;
gDebugGL = TRUE;
@@ -2654,20 +2649,16 @@ 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
- if(clp.hasOption("url"))
- {
- LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
- if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION)
- {
- LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid());
-
- }
- }
- else if(clp.hasOption("slurl"))
- {
- LLSLURL start_slurl(clp.getOption("slurl")[0]);
+ std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation"));
+ if(! CmdLineLoginLocation.empty())
+ {
+ LLSLURL start_slurl(CmdLineLoginLocation);
LLStartUp::setStartSLURL(start_slurl);
- }
+ if(start_slurl.getType() == LLSLURL::LOCATION)
+ {
+ LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
+ }
+ }
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
@@ -2708,8 +2699,6 @@ bool LLAppViewer::initConfiguration()
//}
#if LL_DARWIN
- // Initialize apple menubar and various callbacks
- init_apple_menu(LLTrans::getString("APP_NAME").c_str());
#if __ppc__
// If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further.
@@ -2810,9 +2799,8 @@ 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"))
- && !clp.hasOption("url")
- && !clp.hasOption("slurl"))
+ else if ((clp.hasOption("login") || clp.hasOption("autologin"))
+ && gSavedSettings.getString("CmdLineLoginLocation").empty())
{
// If automatic login from command line with --login switch
// init StartSLURL location.
@@ -3048,13 +3036,19 @@ namespace {
void LLAppViewer::initUpdater()
{
// Initialize the updater service.
- // Generate URL to the udpater service
// Get Channel
// Get Version
- std::string url = gSavedSettings.getString("UpdaterServiceURL");
+
+ /*****************************************************************
+ * Previously, the url was derived from the settings
+ * UpdaterServiceURL
+ * UpdaterServicePath
+ * it is now obtained from the grid manager. The settings above
+ * are no longer used.
+ *****************************************************************/
std::string channel = LLVersionInfo::getChannel();
std::string version = LLVersionInfo::getVersion();
- std::string service_path = gSavedSettings.getString("UpdaterServicePath");
+
U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");
bool willing_to_test;
LL_DEBUGS("UpdaterService") << "channel " << channel << LL_ENDL;
@@ -3079,9 +3073,7 @@ void LLAppViewer::initUpdater()
}
mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
- mUpdater->initialize(url,
- service_path,
- channel,
+ mUpdater->initialize(channel,
version,
gPlatform,
getOSInfo().getOSVersionString(),
@@ -3186,11 +3178,12 @@ bool LLAppViewer::initWindow()
// Initialize GL stuff
//
- if (mForceGraphicsDetail)
+ if (mForceGraphicsLevel)
{
- LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false);
+ 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 );
@@ -4599,11 +4592,6 @@ void LLAppViewer::idle()
llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl;
gObjectList.mNumDeadObjectUpdates = 0;
}
- if (gObjectList.mNumUnknownKills)
- {
- llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl;
- gObjectList.mNumUnknownKills = 0;
- }
if (gObjectList.mNumUnknownUpdates)
{
llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index cd91ae8b2b..3ae8a78845 100755
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -32,6 +32,7 @@
#include "llsys.h" // for LLOSInfo
#include "lltimer.h"
#include "llappcorehttp.h"
+#include <boost/optional.hpp>
class LLCommandLineParser;
class LLFrameTimer;
@@ -41,6 +42,7 @@ class LLImageDecodeThread;
class LLTextureFetch;
class LLWatchdogTimeout;
class LLUpdaterService;
+class LLViewerJoystick;
extern LLFastTimer::DeclareTimer FTM_FRAME;
@@ -254,11 +256,13 @@ private:
std::string mSerialNumber;
bool mPurgeCache;
bool mPurgeOnExit;
+ bool mMainLoopInitialized;
+ LLViewerJoystick* joystick;
bool mSavedFinalSnapshot;
bool mSavePerAccountSettings; // only save per account settings if login succeeded
- bool mForceGraphicsDetail;
+ boost::optional<U32> mForceGraphicsLevel;
bool mQuitRequested; // User wants to quit, may have modified documents open.
bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim.
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 4d340cafa9..316c90d9d2 100755
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -30,7 +30,10 @@
#error "Use only with Mac OS X"
#endif
+#define LL_CARBON_CRASH_HANDLER 1
+
#include "llappviewermacosx.h"
+#include "llwindowmacosx-objc.h"
#include "llcommandlineparser.h"
#include "llviewernetwork.h"
@@ -38,7 +41,10 @@
#include "llmd5.h"
#include "llfloaterworldmap.h"
#include "llurldispatcher.h"
+#include <ApplicationServices/ApplicationServices.h>
+#ifdef LL_CARBON_CRASH_HANDLER
#include <Carbon/Carbon.h>
+#endif
#include "lldir.h"
#include <signal.h>
#include <CoreAudio/CoreAudio.h> // for systemwide mute
@@ -50,9 +56,9 @@ namespace
// They are not used immediately by the app.
int gArgC;
char** gArgV;
-
bool sCrashReporterIsRunning = false;
-
+ LLAppViewerMacOSX* gViewerAppPtr;
+#ifdef LL_CARBON_CRASH_HANDLER
OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
{
OSErr result = noErr;
@@ -61,9 +67,10 @@ namespace
return(result);
}
+#endif
}
-int main( int argc, char **argv )
+bool initViewer()
{
#if LL_SOLARIS && defined(__sparc)
asm ("ta\t6"); // NOTE: Make sure memory alignment is enforced on SPARC
@@ -73,43 +80,60 @@ int main( int argc, char **argv )
if (chdir(gDirUtilp->getAppRODataDir().c_str()) == -1)
{
llwarns << "Could not change directory to "
- << gDirUtilp->getAppRODataDir() << ": " << strerror(errno)
- << llendl;
+ << gDirUtilp->getAppRODataDir() << ": " << strerror(errno)
+ << llendl;
}
-
- LLAppViewerMacOSX* viewer_app_ptr = new LLAppViewerMacOSX();
-
- viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
-
- // Store off the command line args for use later.
- gArgC = argc;
- gArgV = argv;
- bool ok = viewer_app_ptr->init();
+ gViewerAppPtr = new LLAppViewerMacOSX();
+
+ gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
+
+
+
+ bool ok = gViewerAppPtr->init();
if(!ok)
{
llwarns << "Application init failed." << llendl;
- return -1;
}
+
+ return ok;
+}
- // Run the application main loop
- if(!LLApp::isQuitting())
+void handleQuit()
+{
+ LLAppViewer::instance()->userQuit();
+}
+
+bool runMainLoop()
+{
+ bool ret = LLApp::isQuitting();
+ if (!ret && gViewerAppPtr != NULL)
{
- viewer_app_ptr->mainLoop();
+ ret = gViewerAppPtr->mainLoop();
+ } else {
+ ret = true;
}
+
+ return ret;
+}
- if (!LLApp::isError())
+void cleanupViewer()
+{
+ if(!LLApp::isError())
{
- //
- // We don't want to do cleanup here if the error handler got called -
- // the assumption is that the error handler is responsible for doing
- // app cleanup if there was a problem.
- //
- viewer_app_ptr->cleanup();
+ gViewerAppPtr->cleanup();
}
- delete viewer_app_ptr;
- viewer_app_ptr = NULL;
- return 0;
+
+ delete gViewerAppPtr;
+ gViewerAppPtr = NULL;
+}
+
+int main( int argc, char **argv )
+{
+ // Store off the command line args for use later.
+ gArgC = argc;
+ gArgV = argv;
+ return createNSApp(argc, (const char**)argv);
}
LLAppViewerMacOSX::LLAppViewerMacOSX()
@@ -148,28 +172,13 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp)
// The next two lines add the support for parsing the mac -psn_XXX arg.
clp.addOptionDesc("psn", NULL, 1, "MacOSX process serial number");
clp.setCustomParser(parse_psn);
-
- // First read in the args from arguments txt.
- const char* filename = "arguments.txt";
- llifstream ifs(filename, llifstream::binary);
- if (!ifs.is_open())
- {
- llwarns << "Unable to open file" << filename << llendl;
- return false;
- }
-
- if(clp.parseCommandLineFile(ifs) == false)
- {
- return false;
- }
- // Then parse the user's command line, so that any --url arg can appear last
- // Succesive calls to clp.parse... will NOT override earlier options.
+ // parse the user's command line
if(clp.parseCommandLine(gArgC, gArgV) == false)
{
return false;
}
-
+
// Get the user's preferred language string based on the Mac OS localization mechanism.
// To add a new localization:
// go to the "Resources" section of the project
@@ -254,23 +263,24 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
return reset_count == 0;
}
-static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
- EventRef inEvent,
+#ifdef LL_CARBON_CRASH_HANDLER
+static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
+ EventRef inEvent,
void* inUserData)
{
ProcessSerialNumber psn;
- GetEventParameter(inEvent,
- kEventParamProcessID,
- typeProcessSerialNumber,
- NULL,
- sizeof(psn),
- NULL,
+ GetEventParameter(inEvent,
+ kEventParamProcessID,
+ typeProcessSerialNumber,
+ NULL,
+ sizeof(psn),
+ NULL,
&psn);
- if( GetEventKind(inEvent) == kEventAppTerminated )
+ if( GetEventKind(inEvent) == kEventAppTerminated )
{
- Boolean matching_psn = FALSE;
+ Boolean matching_psn = FALSE;
OSErr os_result = SameProcess(&psn, (ProcessSerialNumber*)inUserData, &matching_psn);
if(os_result >= 0 && matching_psn)
{
@@ -280,48 +290,58 @@ static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
}
return noErr;
}
+#endif
void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
{
- // This used to use fork&exec, but is switched to LSOpenApplication to
+#ifdef LL_CARBON_CRASH_HANDLER
+ // This used to use fork&exec, but is switched to LSOpenApplication to
// Make sure the crash reporter launches in front of the SL window.
std::string command_str;
//command_str = "open Second Life.app/Contents/Resources/mac-crash-logger.app";
command_str = "mac-crash-logger.app/Contents/MacOS/mac-crash-logger";
+ CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)command_str.c_str(), strlen(command_str.c_str()), FALSE);
+
+ // FSRef apparently isn't deprecated.
+ // There's other funcitonality that depends on it existing as well that isn't deprecated.
+ // There doesn't seem to be much to directly verify what the status of FSRef is, outside of some documentation pointing at FSRef being valid, and other documentation pointing to everything in Files.h being deprecated.
+ // We'll assume it isn't for now, since all non-deprecated functions that use it seem to assume similar.
+
FSRef appRef;
- Boolean isDir = 0;
- OSStatus os_result = FSPathMakeRef((UInt8*)command_str.c_str(),
- &appRef,
- &isDir);
- if(os_result >= 0)
+ Boolean pathstatus = CFURLGetFSRef(urlRef, &appRef);
+
+ OSStatus os_result = noErr;
+
+ if(pathstatus == true)
{
LSApplicationParameters appParams;
memset(&appParams, 0, sizeof(appParams));
appParams.version = 0;
appParams.flags = kLSLaunchNoParams | kLSLaunchStartClassic;
+
appParams.application = &appRef;
if(reportFreeze)
{
- // Make sure freeze reporting launches the crash logger synchronously, lest
+ // Make sure freeze reporting launches the crash logger synchronously, lest
// Log files get changed by SL while the logger is running.
-
+
// *NOTE:Mani A better way - make a copy of the data that the crash reporter will send
// and let SL go about its business. This way makes the mac work like windows and linux
- // and is the smallest patch for the issue.
+ // and is the smallest patch for the issue.
sCrashReporterIsRunning = false;
ProcessSerialNumber o_psn;
-
+
static EventHandlerRef sCarbonEventsRef = NULL;
- static const EventTypeSpec kEvents[] =
+ static const EventTypeSpec kEvents[] =
{
{ kEventClassApplication, kEventAppTerminated }
};
// Install the handler to detect crash logger termination
- InstallEventHandler(GetApplicationEventTarget(),
+ InstallEventHandler(GetApplicationEventTarget(),
(EventHandlerUPP) CarbonEventHandler,
GetEventTypeCount(kEvents),
kEvents,
@@ -329,31 +349,31 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
&sCarbonEventsRef
);
- // Remove, temporarily the quit handler - which has *crash* behavior before
+ // Remove, temporarily the quit handler - which has *crash* behavior before
// the mainloop gets running!
- AERemoveEventHandler(kCoreEventClass,
- kAEQuitApplication,
+ AERemoveEventHandler(kCoreEventClass,
+ kAEQuitApplication,
NewAEEventHandlerUPP(AEQuitHandler),
false);
-
+
// Launch the crash reporter.
os_result = LSOpenApplication(&appParams, &o_psn);
if(os_result >= 0)
- {
+ {
sCrashReporterIsRunning = true;
}
-
+
while(sCrashReporterIsRunning)
{
RunApplicationEventLoop();
}
-
+
// Re-install the apps quit handler.
- AEInstallEventHandler(kCoreEventClass,
- kAEQuitApplication,
+ AEInstallEventHandler(kCoreEventClass,
+ kAEQuitApplication,
NewAEEventHandlerUPP(AEQuitHandler),
- 0,
+ 0,
false);
// Remove the crash reporter quit handler.
@@ -363,12 +383,12 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
{
appParams.flags |= kLSLaunchAsync;
clear_signals();
-
+
ProcessSerialNumber o_psn;
os_result = LSOpenApplication(&appParams, &o_psn);
}
-
}
+#endif
}
std::string LLAppViewerMacOSX::generateSerialNumber()
@@ -501,73 +521,3 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
return(result);
}
-
-OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
-{
- OSStatus result = eventNotHandledErr;
- OSStatus err;
- UInt32 evtClass = GetEventClass(event);
- UInt32 evtKind = GetEventKind(event);
- WindowRef window = (WindowRef)userdata;
-
- if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
- {
- HICommand cmd;
- err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
-
- if(err == noErr)
- {
- switch(cmd.commandID)
- {
- case kHICommandOK:
- QuitAppModalLoopForWindow(window);
- result = noErr;
- break;
-
- case kHICommandCancel:
- QuitAppModalLoopForWindow(window);
- result = userCanceledErr;
- break;
- }
- }
- }
-
- return(result);
-}
-
-void init_apple_menu(const char* product)
-{
- // Load up a proper menu bar.
- {
- OSStatus err;
- IBNibRef nib = NULL;
- // NOTE: DO NOT translate or brand this string. It's an internal name in the .nib file, and MUST match exactly.
- err = CreateNibReference(CFSTR("SecondLife"), &nib);
-
- if(err == noErr)
- {
- // NOTE: DO NOT translate or brand this string. It's an internal name in the .nib file, and MUST match exactly.
- SetMenuBarFromNib(nib, CFSTR("MenuBar"));
- }
-
- if(nib != NULL)
- {
- DisposeNibReference(nib);
- }
- }
-
- // Install a handler for 'gurl' AppleEvents. This is how secondlife:// URLs get passed to the viewer.
-
- if(AEInstallEventHandler('GURL', 'GURL', NewAEEventHandlerUPP(AEGURLHandler),0, false) != noErr)
- {
- // Couldn't install AppleEvent handler. This error shouldn't be fatal.
- llinfos << "Couldn't install 'GURL' AppleEvent handler. Continuing..." << llendl;
- }
-
- // Install a handler for 'quit' AppleEvents. This makes quitting the application from the dock work.
- if(AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(AEQuitHandler),0, false) != noErr)
- {
- // Couldn't install AppleEvent handler. This error shouldn't be fatal.
- llinfos << "Couldn't install Quit AppleEvent handler. Continuing..." << llendl;
- }
-}
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 3cf3c739d9..80a80f4298 100755
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -172,21 +172,20 @@ void ll_nvapi_init(NvDRSSessionHandle hSession)
nvapi_error(status);
return;
}
+
+ // (5) Now we apply (or save) our changes to the system
+ status = NvAPI_DRS_SaveSettings(hSession);
+ if (status != NVAPI_OK)
+ {
+ nvapi_error(status);
+ return;
+ }
}
else if (status != NVAPI_OK)
{
nvapi_error(status);
return;
}
-
-
-
- // (5) Now we apply (or save) our changes to the system
- status = NvAPI_DRS_SaveSettings(hSession);
- if (status != NVAPI_OK)
- {
- nvapi_error(status);
- }
}
//#define DEBUGGING_SEH_FILTER 1
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index b513a52ff7..70cc48f12b 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -73,6 +73,8 @@
#include "llcallingcard.h"
#include "llslurl.h" // IDEVO
#include "llsidepanelinventory.h"
+#include "llavatarname.h"
+#include "llagentui.h"
// static
void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
@@ -391,6 +393,72 @@ void LLAvatarActions::pay(const LLUUID& id)
}
}
+void LLAvatarActions::teleport_request_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option;
+ if (response.isInteger())
+ {
+ option = response.asInteger();
+ }
+ else
+ {
+ option = LLNotificationsUtil::getSelectedOption(notification, response);
+ }
+
+ if (0 == option)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_MessageBlock);
+ msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
+ msg->addUUIDFast(_PREHASH_ToAgentID, notification["substitutions"]["uuid"] );
+ msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
+ msg->addU8Fast(_PREHASH_Dialog, IM_TELEPORT_REQUEST);
+ msg->addUUIDFast(_PREHASH_ID, LLUUID::null);
+ msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
+
+ std::string name;
+ LLAgentUI::buildFullname(name);
+
+ msg->addStringFast(_PREHASH_FromAgentName, name);
+ msg->addStringFast(_PREHASH_Message, response["message"]);
+ msg->addU32Fast(_PREHASH_ParentEstateID, 0);
+ msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
+ msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
+
+ gMessageSystem->addBinaryDataFast(
+ _PREHASH_BinaryBucket,
+ EMPTY_BINARY_BUCKET,
+ EMPTY_BINARY_BUCKET_SIZE);
+
+ gAgent.sendReliableMessage();
+ }
+}
+
+// static
+void LLAvatarActions::teleportRequest(const LLUUID& id)
+{
+ LLSD notification;
+ notification["uuid"] = id;
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(id, &av_name))
+ {
+ // unlikely ... they just picked this name from somewhere...
+ LLAvatarNameCache::get(id, boost::bind(&LLAvatarActions::teleportRequest, id));
+ return; // reinvoke this when the name resolves
+ }
+ notification["NAME"] = av_name.getCompleteName();
+
+ LLSD payload;
+
+ LLNotificationsUtil::add("TeleportRequestPrompt", notification, payload, teleport_request_callback);
+}
+
// static
void LLAvatarActions::kick(const LLUUID& id)
{
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 6e1198cd09..403414558e 100755
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -111,6 +111,12 @@ public:
static void pay(const LLUUID& id);
/**
+ * Request teleport from other avatar
+ */
+ static void teleportRequest(const LLUUID& id);
+ static void teleport_request_callback(const LLSD& notification, const LLSD& response);
+
+ /**
* Share items with the avatar.
*/
static void share(const LLUUID& id);
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index 43757d0174..8b2d9e639f 100755
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -139,8 +139,6 @@ void LLChannelManager::onLoginCompleted()
}
LLPersistentNotificationStorage::getInstance()->loadNotifications();
-
- LLDoNotDisturbNotificationStorage::getInstance()->initialize();
LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications();
}
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 7d0331757b..b3bc0ba966 100755
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -381,7 +381,7 @@ void LLChatBar::sendChat( EChatType type )
if (!utf8_revised_text.empty())
{
// Chat with animation
- sendChatFromViewer(utf8_revised_text, type, TRUE);
+ sendChatFromViewer(utf8_revised_text, type, gSavedSettings.getBOOL("PlayChatAnim"));
}
}
}
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 0f138873ac..af3c6eff11 100755
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -628,6 +628,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
editor_params.enabled = false; // read only
editor_params.show_context_menu = "true";
mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);
+ mEditor->setIsFriendCallback(LLAvatarActions::isFriend);
}
LLSD LLChatHistory::getValue() const
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index a1a9463d43..fd4f17b694 100755
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -323,12 +323,11 @@ BOOL LLFloaterIMNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask)
return TRUE;
else
{
- (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory();
+ LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->showHistory();
return FALSE;
}
}
-
- (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory();
+ LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->showHistory();
return LLPanel::handleMouseUp(x,y,mask);
}
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 88884042d4..131aea9da3 100755
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -220,18 +220,25 @@ void LLNotificationChiclet::setCounter(S32 counter)
bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification )
{
- if (notification->getName() == "ScriptDialog")
+ bool displayNotification;
+ if ( (notification->getName() == "ScriptDialog") // special case for scripts
+ // if there is no toast window for the notification, filter it
+ || (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID()))
+ )
{
- return false;
+ displayNotification = false;
}
-
- if( !(notification->canLogToIM() && notification->hasFormElements())
- && (!notification->getPayload().has("give_inventory_notification")
- || notification->getPayload()["give_inventory_notification"]))
+ else if( !(notification->canLogToIM() && notification->hasFormElements())
+ && (!notification->getPayload().has("give_inventory_notification")
+ || notification->getPayload()["give_inventory_notification"]))
{
- return true;
+ displayNotification = true;
}
- return false;
+ else
+ {
+ displayNotification = false;
+ }
+ return displayNotification;
}
//////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index 17d403bbe1..a6384ded12 100755
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -38,16 +38,23 @@
#endif
#include <boost/program_options.hpp>
+#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
-#include<boost/tokenizer.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/assign/list_of.hpp>
#if _MSC_VER
# pragma warning(pop)
#endif
#include "llsdserialize.h"
+#include "llerror.h"
+#include "stringize.h"
+#include <string>
+#include <set>
#include <iostream>
#include <sstream>
+#include <typeinfo>
#include "llcontrol.h"
@@ -63,10 +70,22 @@ namespace po = boost::program_options;
// This could be good or bad, and probably won't matter for most use cases.
namespace
{
+ // List of command-line switches that can't map-to settings variables.
+ // Going forward, we want every new command-line switch to map-to some
+ // settings variable. This list is used to validate that.
+ const std::set<std::string> unmapped_options = boost::assign::list_of
+ ("help")
+ ("set")
+ ("setdefault")
+ ("settings")
+ ("sessionsettings")
+ ("usersessionsettings")
+ ;
+
po::options_description gOptionsDesc;
po::positional_options_description gPositionalOptions;
po::variables_map gVariableMap;
-
+
const LLCommandLineParser::token_vector_t gEmptyValue;
void read_file_into_string(std::string& str, const std::basic_istream < char >& file)
@@ -384,9 +403,19 @@ bool LLCommandLineParser::parseCommandLineFile(const std::basic_istream < char >
return parseCommandLineString(args);
}
-void LLCommandLineParser::notify()
+bool LLCommandLineParser::notify()
{
- po::notify(gVariableMap);
+ try
+ {
+ po::notify(gVariableMap);
+ return true;
+ }
+ catch (const LLCLPError& e)
+ {
+ llwarns << "Caught Error: " << e.what() << llendl;
+ mErrorMsg = e.what();
+ return false;
+ }
}
void LLCommandLineParser::printOptions() const
@@ -428,43 +457,129 @@ const LLCommandLineParser::token_vector_t& LLCommandLineParser::getOption(const
//----------------------------------------------------------------------------
// LLControlGroupCLP defintions
//----------------------------------------------------------------------------
+namespace {
+LLCommandLineParser::token_vector_t::value_type
+onevalue(const std::string& option,
+ const LLCommandLineParser::token_vector_t& value)
+{
+ if (value.empty())
+ {
+ // What does it mean when the user specifies a command-line switch
+ // that requires a value, but omits the value? Complain.
+ throw LLCLPError(STRINGIZE("No value specified for --" << option << "!"));
+ }
+ else if (value.size() > 1)
+ {
+ llwarns << "Ignoring extra tokens specified for --"
+ << option << "." << llendl;
+ }
+ return value[0];
+}
+
+void badvalue(const std::string& option,
+ const std::string& varname,
+ const std::string& type,
+ const std::string& value)
+{
+ // If the user passes an unusable value for a command-line switch, it
+ // seems like a really bad idea to just ignore it, even with a log
+ // warning.
+ throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option
+ << "' for variable '" << varname << "' of type " << type
+ << ": '" << value << "'"));
+}
+
+template <typename T>
+T convertTo(const std::string& option,
+ const std::string& varname,
+ const LLCommandLineParser::token_vector_t::value_type& value)
+{
+ try
+ {
+ return boost::lexical_cast<T>(value);
+ }
+ catch (const boost::bad_lexical_cast&)
+ {
+ badvalue(option, varname, typeid(T).name(), value);
+ // bogus return; compiler unaware that badvalue() won't return
+ return T();
+ }
+}
+
void setControlValueCB(const LLCommandLineParser::token_vector_t& value,
- const std::string& opt_name,
- LLControlGroup* ctrlGroup)
+ const std::string& option,
+ LLControlVariable* ctrl)
{
- // *FIX: Do sematic conversion here.
+ // *FIX: Do semantic conversion here.
// LLSD (ImplString) Is no good for doing string to type conversion for...
// booleans
// compound types
// ?...
- LLControlVariable* ctrl = ctrlGroup->getControl(opt_name);
if(NULL != ctrl)
{
switch(ctrl->type())
{
case TYPE_BOOLEAN:
- if(value.size() > 1)
+ if (value.empty())
{
- llwarns << "Ignoring extra tokens." << llendl;
+ // Boolean-valued command-line switches are unusual. If you
+ // simply specify the switch without an explicit value, we can
+ // infer you mean 'true'.
+ ctrl->setValue(LLSD(true), false);
}
-
- if(value.size() > 0)
+ else
{
+ // Only call onevalue() AFTER handling value.empty() case!
+ std::string token(onevalue(option, value));
+
// There's a token. check the string for true/false/1/0 etc.
BOOL result = false;
- BOOL gotSet = LLStringUtil::convertToBOOL(value[0], result);
- if(gotSet)
+ BOOL gotSet = LLStringUtil::convertToBOOL(token, result);
+ if (gotSet)
{
ctrl->setValue(LLSD(result), false);
}
+ else
+ {
+ badvalue(option, ctrl->getName(), "bool", token);
+ }
+ }
+ break;
+
+ case TYPE_U32:
+ {
+ std::string token(onevalue(option, value));
+ // To my surprise, for an unsigned target, lexical_cast() doesn't
+ // complain about an input string such as "-17". In that case, you
+ // get a very large positive result. So for U32, make sure there's
+ // no minus sign!
+ if (token.find('-') == std::string::npos)
+ {
+ ctrl->setValue(LLSD::Integer(convertTo<U32>(option, ctrl->getName(), token)),
+ false);
}
else
{
- ctrl->setValue(LLSD(true), false);
+ badvalue(option, ctrl->getName(), "unsigned", token);
}
break;
+ }
+
+ case TYPE_S32:
+ ctrl->setValue(convertTo<S32>(option, ctrl->getName(),
+ onevalue(option, value)), false);
+ break;
+
+ case TYPE_F32:
+ ctrl->setValue(convertTo<F32>(option, ctrl->getName(),
+ onevalue(option, value)), false);
+ break;
+ // It appears that no one has yet tried to define a command-line
+ // switch mapped to a settings variable of TYPE_VEC3, TYPE_VEC3D,
+ // TYPE_RECT, TYPE_COL4, TYPE_COL3. Such types would certainly seem to
+ // call for a bit of special handling here...
default:
{
// For the default types, let llsd do the conversion.
@@ -481,16 +596,9 @@ void setControlValueCB(const LLCommandLineParser::token_vector_t& value,
ctrl->setValue(llsdArray, false);
}
- else if(value.size() > 0)
+ else
{
- if(value.size() > 1)
- {
- llwarns << "Ignoring extra tokens mapped to the setting: " << opt_name << "." << llendl;
- }
-
- LLSD llsdValue;
- llsdValue.assign(LLSD::String(value[0]));
- ctrl->setValue(llsdValue, false);
+ ctrl->setValue(onevalue(option, value), false);
}
}
break;
@@ -498,12 +606,14 @@ void setControlValueCB(const LLCommandLineParser::token_vector_t& value,
}
else
{
- llwarns << "Command Line option mapping '"
- << opt_name
- << "' not found! Ignoring."
- << llendl;
+ // This isn't anything a user can affect -- it's a misconfiguration on
+ // the part of the coder. Rub the coder's nose in the problem right
+ // away so even preliminary testing will surface it.
+ llerrs << "Command Line option --" << option
+ << " maps to unknown setting!" << llendl;
}
}
+} // anonymous namespace
void LLControlGroupCLP::configure(const std::string& config_filename, LLControlGroup* controlGroup)
{
@@ -561,11 +671,37 @@ void LLControlGroupCLP::configure(const std::string& config_filename, LLControlG
}
boost::function1<void, const token_vector_t&> callback;
- if(option_params.has("map-to") && (NULL != controlGroup))
+ if (! option_params.has("map-to"))
+ {
+ // If this option isn't mapped to a settings variable, is it
+ // one of the ones for which that's unreasonable, or did
+ // someone carelessly add a new option? (Make all these
+ // configuration errors fatal so a maintainer will catch them
+ // right away.)
+ std::set<std::string>::const_iterator found = unmapped_options.find(long_name);
+ if (found == unmapped_options.end())
+ {
+ llerrs << "New command-line option " << long_name
+ << " should map-to a variable in settings.xml" << llendl;
+ }
+ }
+ else // option specifies map-to
{
std::string controlName = option_params["map-to"].asString();
- callback = boost::bind(setControlValueCB, _1,
- controlName, controlGroup);
+ if (! controlGroup)
+ {
+ llerrs << "Must pass gSavedSettings to LLControlGroupCLP::configure() for "
+ << long_name << " (map-to " << controlName << ")" << llendl;
+ }
+
+ LLControlVariable* ctrl = controlGroup->getControl(controlName);
+ if (! ctrl)
+ {
+ llerrs << "Option " << long_name << " specifies map-to " << controlName
+ << " which does not exist" << llendl;
+ }
+
+ callback = boost::bind(setControlValueCB, _1, long_name, ctrl);
}
this->addOptionDesc(
diff --git a/indra/newview/llcommandlineparser.h b/indra/newview/llcommandlineparser.h
index 44f2a26843..71388b8217 100755
--- a/indra/newview/llcommandlineparser.h
+++ b/indra/newview/llcommandlineparser.h
@@ -86,7 +86,7 @@ public:
*
* Use this to handle the results of parsing.
*/
- void notify();
+ bool notify();
/** @brief Print a description of the configured options.
*
diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp
index 5ab108b39f..44212298cf 100755
--- a/indra/newview/llconversationloglist.cpp
+++ b/indra/newview/llconversationloglist.cpp
@@ -313,6 +313,10 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
{
LLAvatarActions::offerTeleport(selected_conversation_participant_id);
}
+ else if ("request_teleport" == command_name)
+ {
+ LLAvatarActions::teleportRequest(selected_conversation_participant_id);
+ }
else if("add_friend" == command_name)
{
if (!LLAvatarActions::isFriend(selected_conversation_participant_id))
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index c74ce24872..affa24f78c 100755
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -132,6 +132,7 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
items.push_back(std::string("view_profile"));
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
+ items.push_back(std::string("request_teleport"));
items.push_back(std::string("voice_call"));
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
@@ -363,7 +364,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)
lldebugs << "LLConversationItemParticipant::buildContextMenu()" << llendl;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
-
+ if((flags & ITEM_IN_MULTI_SELECTION) && (this->getType() != CONV_SESSION_NEARBY))
+ {
+ items.push_back(std::string("close_selected_conversations"));
+ }
if(this->getType() == CONV_SESSION_1_ON_1)
{
items.push_back(std::string("close_conversation"));
@@ -386,6 +390,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)
addVoiceOptions(items);
items.push_back(std::string("chat_history"));
}
+ else if(this->getType() == CONV_SESSION_NEARBY)
+ {
+ items.push_back(std::string("chat_history"));
+ }
hide_context_entries(menu, items, disabled_items);
}
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 8766585049..d8cdcdfc97 100755
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -252,11 +252,10 @@ public:
const std::string& getName() const { return mEmpty; }
const std::string& getFilterText() { return mEmpty; }
void setModified(EFilterModified behavior = FILTER_RESTART) { }
-
- void setFilterCount(S32 count) { }
- S32 getFilterCount() const { return 0; }
- void decrementFilterCount() { }
-
+
+ void resetTime(S32 timeout) { }
+ bool isTimedOut() { return false; }
+
bool isDefault() const { return true; }
bool isNotDefault() const { return false; }
void markDefault() { }
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index b6c53e5e30..9faa12b2ee 100755
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -118,9 +118,19 @@ void LLConversationViewSession::setFlashState(bool flash_state)
mFlashTimer->stopFlashing();
}
+void LLConversationViewSession::setHighlightState(bool hihglight_state)
+{
+ mFlashStateOn = hihglight_state;
+ mFlashStarted = true;
+ mFlashTimer->stopFlashing();
+}
+
void LLConversationViewSession::startFlashing()
{
- if (isInVisibleChain() && mFlashStateOn && !mFlashStarted)
+ LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
+
+ // Need to start flashing only when "Conversations" is opened or brought on top
+ if (isInVisibleChain() && !im_box->isMinimized() && mFlashStateOn && !mFlashStarted)
{
mFlashStarted = true;
mFlashTimer->startFlashing();
@@ -263,6 +273,29 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask )
return result;
}
+BOOL LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask )
+{
+ BOOL result = LLFolderViewFolder::handleMouseUp(x, y, mask);
+
+ LLFloater* volume_floater = LLFloaterReg::findInstance("floater_voice_volume");
+ LLFloater* chat_volume_floater = LLFloaterReg::findInstance("chat_voice");
+ if (result
+ && getRoot()
+ && !(volume_floater && volume_floater->isShown() && volume_floater->hasFocus())
+ && !(chat_volume_floater && chat_volume_floater->isShown() && chat_volume_floater->hasFocus()))
+ {
+ LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem());
+ LLUUID session_id = item? item->getUUID() : LLUUID();
+ LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
+ if(!session_floater->hasFocus())
+ {
+ session_floater->setFocus(true);
+ }
+ }
+
+ return result;
+}
+
BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask )
{
BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask);
@@ -340,16 +373,20 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)
{
// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized
// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here
- LLFolderViewModelItem* item = mViewModelItem;
- LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID();
- LLFloater* session_floater = LLFloaterIMSessionTab::getConversation(session_uuid);
-
- if (session_floater && !session_floater->getHost() && !session_floater->isMinimized())
+ LLFloater* session_floater = getSessionFloater();
+ if (session_floater && session_floater->isDetachedAndNotMinimized())
{
session_floater->setVisible(visible);
}
}
+LLFloater* LLConversationViewSession::getSessionFloater()
+{
+ LLFolderViewModelItem* item = mViewModelItem;
+ LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID();
+ return LLFloaterIMSessionTab::getConversation(session_uuid);
+}
+
LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id)
{
// This is *not* a general tree parsing algorithm. We search only in the mItems list
diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h
index 3eb2e63792..5a74974302 100755
--- a/indra/newview/llconversationview.h
+++ b/indra/newview/llconversationview.h
@@ -69,6 +69,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ /*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask );
/*virtual*/ S32 arrange(S32* width, S32* height);
@@ -86,6 +87,9 @@ public:
virtual void refresh();
/*virtual*/ void setFlashState(bool flash_state);
+ void setHighlightState(bool hihglight_state);
+
+ LLFloater* getSessionFloater();
private:
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index d7d9f82910..4c4424edc4 100755
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -37,7 +37,7 @@
#include "llwindow.h" // beforeDialog()
#include "llviewercontrol.h"
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX || LL_SOLARIS || LL_DARWIN
# include "llfilepicker.h"
#endif
@@ -147,152 +147,36 @@ std::string LLDirPicker::getDirName()
#elif LL_DARWIN
LLDirPicker::LLDirPicker() :
- mFileName(NULL),
- mLocked(false)
+mFileName(NULL),
+mLocked(false)
{
+ mFilePicker = new LLFilePicker();
reset();
-
- memset(&mNavOptions, 0, sizeof(mNavOptions));
- OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
- if (error == noErr)
- {
- mNavOptions.modality = kWindowModalityAppModal;
- }
}
LLDirPicker::~LLDirPicker()
{
- // nothing
+ delete mFilePicker;
}
-//static
-pascal void LLDirPicker::doNavCallbackEvent(NavEventCallbackMessage callBackSelector,
- NavCBRecPtr callBackParms, void* callBackUD)
+void LLDirPicker::reset()
{
- switch(callBackSelector)
- {
- case kNavCBStart:
- {
- if (!sInstance.mFileName) break;
-
- OSStatus error = noErr;
- AEDesc theLocation = {typeNull, NULL};
- FSSpec outFSSpec;
-
- //Convert string to a FSSpec
- FSRef myFSRef;
-
- const char* filename=sInstance.mFileName->c_str();
-
- error = FSPathMakeRef ((UInt8*)filename, &myFSRef, NULL);
-
- if (error != noErr) break;
-
- error = FSGetCatalogInfo (&myFSRef, kFSCatInfoNone, NULL, NULL, &outFSSpec, NULL);
-
- if (error != noErr) break;
-
- error = AECreateDesc(typeFSS, &outFSSpec, sizeof(FSSpec), &theLocation);
-
- if (error != noErr) break;
-
- error = NavCustomControl(callBackParms->context,
- kNavCtlSetLocation, (void*)&theLocation);
-
- }
- }
+ if (mFilePicker)
+ mFilePicker->reset();
}
-OSStatus LLDirPicker::doNavChooseDialog()
-{
- OSStatus error = noErr;
- NavDialogRef navRef = NULL;
- NavReplyRecord navReply;
-
- memset(&navReply, 0, sizeof(navReply));
-
- // NOTE: we are passing the address of a local variable here.
- // This is fine, because the object this call creates will exist for less than the lifetime of this function.
- // (It is destroyed by NavDialogDispose() below.)
-
- error = NavCreateChooseFolderDialog(&mNavOptions, &doNavCallbackEvent, NULL, NULL, &navRef);
-
- gViewerWindow->getWindow()->beforeDialog();
-
- if (error == noErr)
- error = NavDialogRun(navRef);
-
- gViewerWindow->getWindow()->afterDialog();
-
- if (error == noErr)
- error = NavDialogGetReply(navRef, &navReply);
-
- if (navRef)
- NavDialogDispose(navRef);
-
- if (error == noErr && navReply.validRecord)
- {
- FSRef fsRef;
- AEKeyword theAEKeyword;
- DescType typeCode;
- Size actualSize = 0;
- char path[LL_MAX_PATH]; /*Flawfinder: ignore*/
-
- memset(&fsRef, 0, sizeof(fsRef));
- error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
-
- if (error == noErr)
- error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
-
- if (error == noErr)
- mDir = path;
- }
-
- return error;
-}
+//static
BOOL LLDirPicker::getDir(std::string* filename)
{
- if( mLocked ) return FALSE;
- BOOL success = FALSE;
- OSStatus error = noErr;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- mFileName = filename;
-
-// mNavOptions.saveFileName
-
- // Modal, so pause agent
- send_agent_pause();
- {
- error = doNavChooseDialog();
- }
- send_agent_resume();
- if (error == noErr)
- {
- if (mDir.length() > 0)
- success = true;
- }
-
- // Account for the fact that the app has been stalled.
- LLFrameTimer::updateFrameTime();
- return success;
+ LLFilePicker::ELoadFilter filter=LLFilePicker::FFLOAD_DIRECTORY;
+
+ return mFilePicker->getOpenFile(filter, true);
}
std::string LLDirPicker::getDirName()
{
- return mDir;
-}
-
-void LLDirPicker::reset()
-{
- mLocked = false;
- mDir.clear();
+ return mFilePicker->getFirstFile();
}
#elif LL_LINUX || LL_SOLARIS
diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h
index 682f9d6476..9cc62431ef 100755
--- a/indra/newview/lldirpicker.h
+++ b/indra/newview/lldirpicker.h
@@ -34,11 +34,10 @@
#include "stdtypes.h"
#if LL_DARWIN
-#include <Carbon/Carbon.h>
// AssertMacros.h does bad things.
-#include "fix_macros.h"
#undef verify
+#undef check
#undef require
#include <vector>
@@ -77,15 +76,7 @@ private:
void buildDirname( void );
bool check_local_file_access_enabled();
-#if LL_DARWIN
- NavDialogCreationOptions mNavOptions;
- static pascal void doNavCallbackEvent(NavEventCallbackMessage callBackSelector,
- NavCBRecPtr callBackParms, void* callBackUD);
- OSStatus doNavChooseDialog();
-
-#endif
-
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX || LL_SOLARIS || LL_DARWIN
// On Linux we just implement LLDirPicker on top of LLFilePicker
LLFilePicker *mFilePicker;
#endif
diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp
index 82affcf068..495cd01349 100755
--- a/indra/newview/lldonotdisturbnotificationstorage.cpp
+++ b/indra/newview/lldonotdisturbnotificationstorage.cpp
@@ -70,7 +70,7 @@ BOOL LLDoNotDisturbNotificationStorageTimer::tick()
LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()
: LLSingleton<LLDoNotDisturbNotificationStorage>()
- , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml"))
+ , LLNotificationStorage("")
, mDirty(false)
{
nameToPayloadParameterMap[toastName] = "SESSION_ID";
@@ -83,6 +83,7 @@ LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage()
void LLDoNotDisturbNotificationStorage::initialize()
{
+ setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml"));
getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1));
}
@@ -115,7 +116,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications()
{
LLNotificationPtr notificationPtr = historyIter->second;
- if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired())
+ if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() &&
+ !notificationPtr->isExpired() && !notificationPtr->isPersistent())
{
data.append(notificationPtr->asLLSD(true));
}
@@ -210,12 +212,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
}
- if(imToastExists)
- {
- LLFloaterReg::showInstance("im_container");
- }
-
- if(group_ad_hoc_toast_exists)
+ bool isConversationLoggingAllowed = gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0;
+ if(group_ad_hoc_toast_exists && isConversationLoggingAllowed)
{
LLFloaterReg::showInstance("conversation");
}
@@ -266,11 +264,6 @@ void LLDoNotDisturbNotificationStorage::updateNotifications()
}
}
- if(imToastExists)
- {
- LLFloaterReg::showInstance("im_container");
- }
-
if(imToastExists || offerExists)
{
make_ui_sound("UISndNewIncomingIMSession");
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 075299386e..a0024a231c 100755
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -135,6 +135,16 @@ void LLDrawPoolAvatar::prerender()
{
sBufferUsage = GL_STREAM_DRAW_ARB;
}
+
+ if (!mDrawFace.empty())
+ {
+ const LLFace *facep = mDrawFace[0];
+ if (facep && facep->getDrawable())
+ {
+ LLVOAvatar* avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
+ updateRiggedVertexBuffers(avatarp);
+ }
+ }
}
LLMatrix4& LLDrawPoolAvatar::getModelView()
@@ -1434,6 +1444,65 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
}
+void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
+{
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+
+ //rigged faces do not batch textures
+ face->setTextureIndex(255);
+
+ if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
+ { //make a new buffer
+ if (sShaderLevel > 0)
+ {
+ buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
+ }
+ else
+ {
+ buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
+ }
+ buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true);
+ }
+ else
+ { //resize existing buffer
+ buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices);
+ }
+
+ face->setSize(vol_face.mNumVertices, vol_face.mNumIndices);
+ face->setVertexBuffer(buffer);
+
+ U16 offset = 0;
+
+ LLMatrix4 mat_vert = skin->mBindShapeMatrix;
+ glh::matrix4f m((F32*) mat_vert.mMatrix);
+ m = m.inverse().transpose();
+
+ F32 mat3[] =
+ { m.m[0], m.m[1], m.m[2],
+ m.m[4], m.m[5], m.m[6],
+ m.m[8], m.m[9], m.m[10] };
+
+ LLMatrix3 mat_normal(mat3);
+
+ //let getGeometryVolume know if alpha should override shiny
+ U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture());
+
+ if (type == LLDrawPool::POOL_ALPHA)
+ {
+ face->setPoolType(LLDrawPool::POOL_ALPHA);
+ }
+ else
+ {
+ face->setPoolType(LLDrawPool::POOL_AVATAR);
+ }
+
+ //llinfos << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << llendl;
+ face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true);
+
+ buffer->flush();
+}
+
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
{
LLVector4a* weight = vol_face.mWeights;
@@ -1453,60 +1522,27 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
buffer->getNumIndices() != vol_face.mNumIndices ||
(drawable && drawable->isState(LLDrawable::REBUILD_ALL)))
{
- face->setGeomIndex(0);
- face->setIndicesIndex(0);
-
- //rigged faces do not batch textures
- face->setTextureIndex(255);
-
- if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
- { //make a new buffer
- if (sShaderLevel > 0)
+ if (drawable && drawable->isState(LLDrawable::REBUILD_ALL))
+ { //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
{
- buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
- }
- else
- {
- buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
+ LLFace* facep = drawable->getFace(i);
+ U32 face_data_mask = facep->getRiggedVertexBufferDataMask();
+ if (face_data_mask)
+ {
+ LLPointer<LLVertexBuffer> cur_buffer = facep->getVertexBuffer();
+ const LLVolumeFace& cur_vol_face = volume->getVolumeFace(i);
+ getRiggedGeometry(facep, cur_buffer, face_data_mask, skin, volume, cur_vol_face);
+ }
}
- buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true);
- }
- else
- { //resize existing buffer
- buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices);
- }
-
- face->setSize(vol_face.mNumVertices, vol_face.mNumIndices);
- face->setVertexBuffer(buffer);
-
- U16 offset = 0;
-
- LLMatrix4 mat_vert = skin->mBindShapeMatrix;
- glh::matrix4f m((F32*) mat_vert.mMatrix);
- m = m.inverse().transpose();
-
- F32 mat3[] =
- { m.m[0], m.m[1], m.m[2],
- m.m[4], m.m[5], m.m[6],
- m.m[8], m.m[9], m.m[10] };
-
- LLMatrix3 mat_normal(mat3);
-
- //let getGeometryVolume know if alpha should override shiny
- U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture());
+ drawable->clearState(LLDrawable::REBUILD_ALL);
- if (type == LLDrawPool::POOL_ALPHA)
- {
- face->setPoolType(LLDrawPool::POOL_ALPHA);
+ buffer = face->getVertexBuffer();
}
else
- {
- face->setPoolType(LLDrawPool::POOL_AVATAR);
+ { //just rebuild this face
+ getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face);
}
-
- face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true);
-
- buffer->flush();
}
if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
@@ -1591,11 +1627,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
}
}
}
-
- if (drawable && (face->getTEOffset() == drawable->getNumFaces()-1))
- {
- drawable->clearState(LLDrawable::REBUILD_ALL);
- }
}
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
@@ -1771,7 +1802,6 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar)
{
- updateRiggedVertexBuffers(avatar);
renderRigged(avatar, RIGGED_DEFERRED_SIMPLE);
}
@@ -1840,7 +1870,6 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar)
{
- updateRiggedVertexBuffers(avatar);
renderRigged(avatar, RIGGED_SIMPLE);
}
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 7d0368a945..4fbda1f862 100755
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -133,6 +133,7 @@ public:
void endDeferredRiggedSimple();
void endDeferredRiggedBump();
+ void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face);
void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
LLFace* facep,
const LLMeshSkinInfo* skin,
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index f021f4ed0f..9b2b778677 100755
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -768,7 +768,7 @@ bool less_than_max_mag(const LLVector4a& vec)
}
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
- const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)
+ const LLMatrix4& mat_vert_in, BOOL global_volume)
{
//get bounding box
if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED))
@@ -777,10 +777,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
LLMatrix4a mat_vert;
mat_vert.loadu(mat_vert_in);
- LLMatrix4a mat_normal;
- mat_normal.loadu(mat_normal_in);
-
- //VECTORIZE THIS
LLVector4a min,max;
if (f >= volume.getNumVolumeFaces())
@@ -797,100 +793,68 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
llassert(less_than_max_mag(max));
//min, max are in volume space, convert to drawable render space
- LLVector4a center;
- LLVector4a t;
- t.setAdd(min, max);
- t.mul(0.5f);
- mat_vert.affineTransform(t, center);
- LLVector4a size;
- size.setSub(max, min);
- size.mul(0.5f);
- llassert(less_than_max_mag(min));
- llassert(less_than_max_mag(max));
+ //get 8 corners of bounding box
+ LLVector4Logical mask[6];
- if (!global_volume)
+ for (U32 i = 0; i < 6; ++i)
{
- //VECTORIZE THIS
- LLVector4a scale;
- scale.load3(mDrawablep->getVObj()->getScale().mV);
- size.mul(scale);
+ mask[i].clear();
}
- // Catch potential badness from normalization before it happens
- //
- llassert(mat_normal.mMatrix[0].isFinite3() && (mat_normal.mMatrix[0].dot3(mat_normal.mMatrix[0]).getF32() > F_APPROXIMATELY_ZERO));
- llassert(mat_normal.mMatrix[1].isFinite3() && (mat_normal.mMatrix[1].dot3(mat_normal.mMatrix[1]).getF32() > F_APPROXIMATELY_ZERO));
- llassert(mat_normal.mMatrix[2].isFinite3() && (mat_normal.mMatrix[2].dot3(mat_normal.mMatrix[2]).getF32() > F_APPROXIMATELY_ZERO));
-
- mat_normal.mMatrix[0].normalize3fast();
- mat_normal.mMatrix[1].normalize3fast();
- mat_normal.mMatrix[2].normalize3fast();
+ mask[0].setElement<2>(); //001
+ mask[1].setElement<1>(); //010
+ mask[2].setElement<1>(); //011
+ mask[2].setElement<2>();
+ mask[3].setElement<0>(); //100
+ mask[4].setElement<0>(); //101
+ mask[4].setElement<2>();
+ mask[5].setElement<0>(); //110
+ mask[5].setElement<1>();
- LLVector4a v[4];
+ LLVector4a v[8];
- //get 4 corners of bounding box
- mat_normal.rotate(size,v[0]);
+ v[6] = min;
+ v[7] = max;
- //VECTORIZE THIS
- LLVector4a scale;
-
- scale.set(-1.f, -1.f, 1.f);
- scale.mul(size);
- mat_normal.rotate(scale, v[1]);
-
- scale.set(1.f, -1.f, -1.f);
- scale.mul(size);
- mat_normal.rotate(scale, v[2]);
-
- scale.set(-1.f, 1.f, -1.f);
- scale.mul(size);
- mat_normal.rotate(scale, v[3]);
+ for (U32 i = 0; i < 6; ++i)
+ {
+ v[i].setSelectWithMask(mask[i], min, max);
+ }
+
+ LLVector4a tv[8];
+ //transform bounding box into drawable space
+ for (U32 i = 0; i < 8; ++i)
+ {
+ mat_vert.affineTransform(v[i], tv[i]);
+ }
+
+ //find bounding box
LLVector4a& newMin = mExtents[0];
LLVector4a& newMax = mExtents[1];
-
- newMin = newMax = center;
-
- llassert(less_than_max_mag(center));
-
- for (U32 i = 0; i < 4; i++)
- {
- LLVector4a delta;
- delta.setAbs(v[i]);
- LLVector4a min;
- min.setSub(center, delta);
- LLVector4a max;
- max.setAdd(center, delta);
- newMin.setMin(newMin,min);
- newMax.setMax(newMax,max);
+ newMin = newMax = tv[0];
- llassert(less_than_max_mag(newMin));
- llassert(less_than_max_mag(newMax));
+ for (U32 i = 1; i < 8; ++i)
+ {
+ newMin.setMin(newMin, tv[i]);
+ newMax.setMax(newMax, tv[i]);
}
if (!mDrawablep->isActive())
- {
+ { // Shift position for region
LLVector4a offset;
offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
newMin.add(offset);
newMax.add(offset);
-
- llassert(less_than_max_mag(newMin));
- llassert(less_than_max_mag(newMax));
}
- t.setAdd(newMin, newMax);
+ LLVector4a t;
+ t.setAdd(newMin,newMax);
t.mul(0.5f);
- llassert(less_than_max_mag(t));
-
- //VECTORIZE THIS
mCenterLocal.set(t.getF32ptr());
-
- llassert(less_than_max_mag(newMin));
- llassert(less_than_max_mag(newMax));
t.setSub(newMax,newMin);
mBoundingSphereRadius = t.getLength3().getF32()*0.5f;
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 0687544d53..763634a3ab 100755
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -195,7 +195,7 @@ public:
void setSize(S32 numVertices, S32 num_indices = 0, bool align = false);
BOOL genVolumeBBoxes(const LLVolume &volume, S32 f,
- const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume = FALSE);
+ const LLMatrix4& mat, BOOL global_volume = FALSE);
void init(LLDrawable* drawablep, LLViewerObject* objp);
void destroy();
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 6d90667194..b35ef3a961 100755
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -400,6 +400,8 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));
addChild(mMoreTextBox);
+ mDropDownItemsCount = 0;
+
LLTextBox::Params label_param(p.label);
mBarLabel = LLUICtrlFactory::create<LLTextBox> (label_param);
addChild(mBarLabel);
@@ -820,11 +822,13 @@ void LLFavoritesBarCtrl::updateButtons()
}
// Update overflow menu
LLToggleableMenu* overflow_menu = static_cast <LLToggleableMenu*> (mOverflowMenuHandle.get());
- if (overflow_menu && overflow_menu->getVisible())
+ if (overflow_menu && overflow_menu->getVisible() && (overflow_menu->getItemCount() != mDropDownItemsCount))
{
overflow_menu->setVisible(FALSE);
if (mUpdateDropDownItems)
+ {
showDropDownMenu();
+ }
}
}
else
@@ -940,6 +944,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
menu->updateParent(LLMenuGL::sMenuContainer);
menu->setButtonRect(mMoreTextBox->getRect(), this);
positionAndShowMenu(menu);
+ mDropDownItemsCount = menu->getItemCount();
}
}
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index f06e9b9b64..211d3c4ce3 100755
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -101,6 +101,7 @@ protected:
LLUUID mFavoriteFolderId;
const LLFontGL *mFont;
S32 mFirstDropDownItem;
+ S32 mDropDownItemsCount;
bool mUpdateDropDownItems;
bool mRestoreOverflowMenu;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index ddb9d3bc43..9d292ce7bb 100755
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -30,6 +30,7 @@
#include <fstream>
#include <boost/regex.hpp>
+#include <boost/assign/list_of.hpp>
#include "llfeaturemanager.h"
#include "lldir.h"
@@ -52,6 +53,8 @@
#include "llboost.h"
#include "llweb.h"
#include "llviewershadermgr.h"
+#include "llstring.h"
+#include "stringize.h"
#if LL_WINDOWS
#include "lldxhardware.h"
@@ -187,6 +190,55 @@ void LLFeatureList::dump()
LL_DEBUGS("RenderInit") << LL_ENDL;
}
+static const std::vector<std::string> sGraphicsLevelNames = boost::assign::list_of
+ ("Low")
+ ("LowMid")
+ ("Mid")
+ ("MidHigh")
+ ("High")
+ ("HighUltra")
+ ("Ultra")
+;
+
+U32 LLFeatureManager::getMaxGraphicsLevel() const
+{
+ return sGraphicsLevelNames.size() - 1;
+}
+
+bool LLFeatureManager::isValidGraphicsLevel(U32 level) const
+{
+ return (level <= getMaxGraphicsLevel());
+}
+
+std::string LLFeatureManager::getNameForGraphicsLevel(U32 level) const
+{
+ if (isValidGraphicsLevel(level))
+ {
+ return sGraphicsLevelNames[level];
+ }
+ return STRINGIZE("Invalid graphics level " << level << ", valid are 0 .. "
+ << getMaxGraphicsLevel());
+}
+
+S32 LLFeatureManager::getGraphicsLevelForName(const std::string& name) const
+{
+ const std::string FixedFunction("FixedFunction");
+ std::string rname(name);
+ if (LLStringUtil::endsWith(rname, FixedFunction))
+ {
+ // chop off any "FixedFunction" suffix
+ rname = rname.substr(0, rname.length() - FixedFunction.length());
+ }
+ for (S32 i(0), iend(getMaxGraphicsLevel()); i <= iend; ++i)
+ {
+ if (sGraphicsLevelNames[i] == rname)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
LLFeatureList *LLFeatureManager::findMask(const std::string& name)
{
if (mMaskList.count(name))
@@ -620,7 +672,7 @@ void LLFeatureManager::applyRecommendedSettings()
{
// apply saved settings
// cap the level at 2 (high)
- S32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5));
+ U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5));
llinfos << "Applying Recommended Features" << llendl;
@@ -696,62 +748,33 @@ void LLFeatureManager::applyFeatures(bool skipFeatures)
}
}
-void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures)
+void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures)
{
LLViewerShaderMgr::sSkipReload = true;
applyBaseMasks();
-
- switch (level)
+
+ // if we're passed an invalid level, default to "Low"
+ std::string features(isValidGraphicsLevel(level)? getNameForGraphicsLevel(level) : "Low");
+ if (features == "Low")
{
- case 0:
#if LL_DARWIN
- // This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac
- // systems which support them instead of falling back to fixed-function unnecessarily
- // MAINT-2157
- //
- if (gGLManager.mGLVersion < 2.1f)
- {
- maskFeatures("LowFixedFunction");
- }
- else
- { //same as low, but with "Basic Shaders" enabled
- maskFeatures("Low");
- }
+ // This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac
+ // systems which support them instead of falling back to fixed-function unnecessarily
+ // MAINT-2157
+ if (gGLManager.mGLVersion < 2.1f)
#else
- if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel)
- { //only use fixed function by default if GL version < 3.0 or this is an intel graphics chip
- maskFeatures("LowFixedFunction");
- }
- else
- { //same as low, but with "Basic Shaders" enabled
- maskFeatures("Low");
- }
+ // only use fixed function by default if GL version < 3.0 or this is an intel graphics chip
+ if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel)
#endif
- break;
- case 1:
- maskFeatures("LowMid");
- break;
- case 2:
- maskFeatures("Mid");
- break;
- case 3:
- maskFeatures("MidHigh");
- break;
- case 4:
- maskFeatures("High");
- break;
- case 5:
- maskFeatures("HighUltra");
- break;
- case 6:
- maskFeatures("Ultra");
- break;
- default:
- maskFeatures("Low");
- break;
+ {
+ // same as Low, but with "Basic Shaders" disabled
+ features = "LowFixedFunction";
+ }
}
+ maskFeatures(features);
+
applyFeatures(skipFeatures);
LLViewerShaderMgr::sSkipReload = false;
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index ad72c16743..3b8d251236 100755
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -134,8 +134,18 @@ public:
// skipFeatures forces skipping of mostly hardware settings
// that we don't want to change when we change graphics
// settings
- void setGraphicsLevel(S32 level, bool skipFeatures);
-
+ void setGraphicsLevel(U32 level, bool skipFeatures);
+
+ // What 'level' values are valid to pass to setGraphicsLevel()?
+ // 0 is the low end...
+ U32 getMaxGraphicsLevel() const;
+ bool isValidGraphicsLevel(U32 level) const;
+
+ // setGraphicsLevel() levels have names.
+ std::string getNameForGraphicsLevel(U32 level) const;
+ // returns -1 for unrecognized name (hence S32 rather than U32)
+ S32 getGraphicsLevelForName(const std::string& name) const;
+
void applyBaseMasks();
void applyRecommendedSettings();
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index d13f85baa2..b26d520557 100755
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -62,6 +62,11 @@ LLFilePicker LLFilePicker::sInstance;
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
#endif
+#ifdef LL_DARWIN
+#include "llfilepicker_mac.h"
+//#include <boost/algorithm/string/predicate.hpp>
+#endif
+
//
// Implementation
//
@@ -94,14 +99,6 @@ LLFilePicker::LLFilePicker()
mFilesW[0] = '\0';
#endif
-#if LL_DARWIN
- memset(&mNavOptions, 0, sizeof(mNavOptions));
- OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
- if (error == noErr)
- {
- mNavOptions.modality = kWindowModalityAppModal;
- }
-#endif
}
LLFilePicker::~LLFilePicker()
@@ -546,369 +543,197 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
#elif LL_DARWIN
-Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
+std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
{
- Boolean result = true;
- ELoadFilter filter = *((ELoadFilter*) callBackUD);
- OSStatus error = noErr;
-
- if (filterMode == kNavFilteringBrowserList && filter != FFLOAD_ALL && (theItem->descriptorType == typeFSRef || theItem->descriptorType == typeFSS))
- {
- // navInfo is only valid for typeFSRef and typeFSS
- NavFileOrFolderInfo *navInfo = (NavFileOrFolderInfo*) info;
- if (!navInfo->isFolder)
- {
- AEDesc desc;
- error = AECoerceDesc(theItem, typeFSRef, &desc);
- if (error == noErr)
- {
- FSRef fileRef;
- error = AEGetDescData(&desc, &fileRef, sizeof(fileRef));
- if (error == noErr)
- {
- LSItemInfoRecord fileInfo;
- error = LSCopyItemInfoForRef(&fileRef, kLSRequestExtension | kLSRequestTypeCreator, &fileInfo);
- if (error == noErr)
- {
- if (filter == FFLOAD_IMAGE)
- {
- if (fileInfo.filetype != 'JPEG' && fileInfo.filetype != 'JPG ' &&
- fileInfo.filetype != 'BMP ' && fileInfo.filetype != 'TGA ' &&
- fileInfo.filetype != 'BMPf' && fileInfo.filetype != 'TPIC' &&
- fileInfo.filetype != 'PNG ' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("jpeg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
- CFStringCompare(fileInfo.extension, CFSTR("jpg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
- CFStringCompare(fileInfo.extension, CFSTR("bmp"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
- CFStringCompare(fileInfo.extension, CFSTR("tga"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
- CFStringCompare(fileInfo.extension, CFSTR("png"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
- )
- {
- result = false;
- }
- }
- else if (filter == FFLOAD_WAV)
- {
- if (fileInfo.filetype != 'WAVE' && fileInfo.filetype != 'WAV ' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("wave"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
- CFStringCompare(fileInfo.extension, CFSTR("wav"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
- )
- {
- result = false;
- }
- }
- else if (filter == FFLOAD_ANIM)
- {
- if (fileInfo.filetype != 'BVH ' &&
- fileInfo.filetype != 'ANIM' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
- fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("anim"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
- )
- {
- result = false;
- }
- }
- else if (filter == FFLOAD_COLLADA)
- {
- if (fileInfo.filetype != 'DAE ' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dae"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
- )
- {
- result = false;
- }
- }
+ std::vector<std::string> *allowedv = new std::vector< std::string >;
+ switch(filter)
+ {
+ case FFLOAD_ALL:
+ allowedv->push_back("wav");
+ allowedv->push_back("bvh");
+ allowedv->push_back("anim");
+ allowedv->push_back("dae");
+ allowedv->push_back("raw");
+ allowedv->push_back("lsl");
+ allowedv->push_back("dic");
+ allowedv->push_back("xcu");
+ case FFLOAD_IMAGE:
+ allowedv->push_back("jpg");
+ allowedv->push_back("jpeg");
+ allowedv->push_back("bmp");
+ allowedv->push_back("tga");
+ allowedv->push_back("bmpf");
+ allowedv->push_back("tpic");
+ allowedv->push_back("png");
+ break;
+ case FFLOAD_WAV:
+ allowedv->push_back("wav");
+ break;
+ case FFLOAD_ANIM:
+ allowedv->push_back("bvh");
+ allowedv->push_back("anim");
+ break;
+ case FFLOAD_COLLADA:
+ allowedv->push_back("dae");
+ break;
#ifdef _CORY_TESTING
- else if (filter == FFLOAD_GEOMETRY)
- {
- if (fileInfo.filetype != 'SLG ' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("slg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
- )
- {
- result = false;
- }
- }
+ case FFLOAD_GEOMETRY:
+ allowedv->push_back("slg");
+ break;
#endif
- else if (filter == FFLOAD_SLOBJECT)
- {
- llwarns << "*** navOpenFilterProc: FFLOAD_SLOBJECT NOT IMPLEMENTED ***" << llendl;
- }
- else if (filter == FFLOAD_RAW)
- {
- if (fileInfo.filetype != '\?\?\?\?' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("raw"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
- )
- {
- result = false;
- }
- }
- else if (filter == FFLOAD_SCRIPT)
- {
- if (fileInfo.filetype != 'LSL ' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("lsl"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) )
- {
- result = false;
- }
- }
- else if (filter == FFLOAD_DICTIONARY)
- {
- if (fileInfo.filetype != 'DIC ' &&
- fileInfo.filetype != 'XCU ' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
- fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xcu"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)))
- {
- result = false;
- }
- }
-
- if (fileInfo.extension)
- {
- CFRelease(fileInfo.extension);
- }
- }
- }
- AEDisposeDesc(&desc);
- }
- }
- }
- return result;
+ case FFLOAD_RAW:
+ allowedv->push_back("raw");
+ break;
+ case FFLOAD_SCRIPT:
+ allowedv->push_back("lsl");
+ break;
+ case FFLOAD_DICTIONARY:
+ allowedv->push_back("dic");
+ allowedv->push_back("xcu");
+ break;
+ case FFLOAD_DIRECTORY:
+ break;
+ default:
+ llwarns << "Unsupported format." << llendl;
+ }
+
+ return allowedv;
}
-OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter)
+bool LLFilePicker::doNavChooseDialog(ELoadFilter filter)
{
- OSStatus error = noErr;
- NavDialogRef navRef = NULL;
- NavReplyRecord navReply;
-
// if local file browsing is turned off, return without opening dialog
if ( check_local_file_access_enabled() == false )
{
- return FALSE;
+ return false;
}
-
- memset(&navReply, 0, sizeof(navReply));
-
- // NOTE: we are passing the address of a local variable here.
- // This is fine, because the object this call creates will exist for less than the lifetime of this function.
- // (It is destroyed by NavDialogDispose() below.)
- error = NavCreateChooseFileDialog(&mNavOptions, NULL, NULL, NULL, navOpenFilterProc, (void*)(&filter), &navRef);
-
+
gViewerWindow->getWindow()->beforeDialog();
-
- if (error == noErr)
- error = NavDialogRun(navRef);
+
+ std::vector<std::string> *allowed_types=navOpenFilterProc(filter);
+
+ std::vector<std::string> *filev = doLoadDialog(allowed_types,
+ mPickOptions);
gViewerWindow->getWindow()->afterDialog();
- if (error == noErr)
- error = NavDialogGetReply(navRef, &navReply);
- if (navRef)
- NavDialogDispose(navRef);
-
- if (error == noErr && navReply.validRecord)
- {
- SInt32 count = 0;
- SInt32 index;
-
- // AE indexes are 1 based...
- error = AECountItems(&navReply.selection, &count);
- for (index = 1; index <= count; index++)
- {
- FSRef fsRef;
- AEKeyword theAEKeyword;
- DescType typeCode;
- Size actualSize = 0;
- char path[MAX_PATH]; /*Flawfinder: ignore*/
-
- memset(&fsRef, 0, sizeof(fsRef));
- error = AEGetNthPtr(&navReply.selection, index, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
-
- if (error == noErr)
- error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
-
- if (error == noErr)
- mFiles.push_back(std::string(path));
- }
- }
+ if (filev && filev->size() > 0)
+ {
+ mFiles.insert(mFiles.end(), filev->begin(), filev->end());
+ return true;
+ }
- return error;
+ return false;
}
-OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
+bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
{
- OSStatus error = noErr;
- NavDialogRef navRef = NULL;
- NavReplyRecord navReply;
-
- memset(&navReply, 0, sizeof(navReply));
// Setup the type, creator, and extension
- OSType type, creator;
- CFStringRef extension = NULL;
+ std::string extension, type, creator;
+
switch (filter)
{
case FFSAVE_WAV:
- type = 'WAVE';
- creator = 'TVOD';
- extension = CFSTR(".wav");
+ type = "WAVE";
+ creator = "TVOD";
+ extension = "wav";
break;
case FFSAVE_TGA:
- type = 'TPIC';
- creator = 'prvw';
- extension = CFSTR(".tga");
+ type = "TPIC";
+ creator = "prvw";
+ extension = "tga";
break;
case FFSAVE_BMP:
- type = 'BMPf';
- creator = 'prvw';
- extension = CFSTR(".bmp");
+ type = "BMPf";
+ creator = "prvw";
+ extension = "bmp";
break;
case FFSAVE_JPEG:
- type = 'JPEG';
- creator = 'prvw';
- extension = CFSTR(".jpeg");
+ type = "JPEG";
+ creator = "prvw";
+ extension = "jpeg";
break;
case FFSAVE_PNG:
- type = 'PNG ';
- creator = 'prvw';
- extension = CFSTR(".png");
+ type = "PNG ";
+ creator = "prvw";
+ extension = "png";
break;
case FFSAVE_AVI:
- type = '\?\?\?\?';
- creator = '\?\?\?\?';
- extension = CFSTR(".mov");
+ type = "\?\?\?\?";
+ creator = "\?\?\?\?";
+ extension = "mov";
break;
case FFSAVE_ANIM:
- type = '\?\?\?\?';
- creator = '\?\?\?\?';
- extension = CFSTR(".xaf");
+ type = "\?\?\?\?";
+ creator = "\?\?\?\?";
+ extension = "xaf";
break;
#ifdef _CORY_TESTING
case FFSAVE_GEOMETRY:
- type = '\?\?\?\?';
- creator = '\?\?\?\?';
- extension = CFSTR(".slg");
+ type = "\?\?\?\?";
+ creator = "\?\?\?\?";
+ extension = "slg";
break;
#endif
case FFSAVE_RAW:
- type = '\?\?\?\?';
- creator = '\?\?\?\?';
- extension = CFSTR(".raw");
+ type = "\?\?\?\?";
+ creator = "\?\?\?\?";
+ extension = "raw";
break;
case FFSAVE_J2C:
- type = '\?\?\?\?';
- creator = 'prvw';
- extension = CFSTR(".j2c");
+ type = "\?\?\?\?";
+ creator = "prvw";
+ extension = "j2c";
break;
case FFSAVE_SCRIPT:
- type = 'LSL ';
- creator = '\?\?\?\?';
- extension = CFSTR(".lsl");
+ type = "LSL ";
+ creator = "\?\?\?\?";
+ extension = "lsl";
break;
case FFSAVE_ALL:
default:
- type = '\?\?\?\?';
- creator = '\?\?\?\?';
- extension = CFSTR("");
+ type = "\?\?\?\?";
+ creator = "\?\?\?\?";
+ extension = "";
break;
}
- // Create the dialog
- error = NavCreatePutFileDialog(&mNavOptions, type, creator, NULL, NULL, &navRef);
- if (error == noErr)
- {
- CFStringRef nameString = NULL;
- bool hasExtension = true;
-
- // Create a CFString of the initial file name
- if (!filename.empty())
- nameString = CFStringCreateWithCString(NULL, filename.c_str(), kCFStringEncodingUTF8);
- else
- nameString = CFSTR("Untitled");
-
- // Add the extension if one was not provided
- if (nameString && !CFStringHasSuffix(nameString, extension))
- {
- CFStringRef tempString = nameString;
- hasExtension = false;
- nameString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), tempString, extension);
- CFRelease(tempString);
- }
-
- // Set the name in the dialog
- if (nameString)
- {
- error = NavDialogSetSaveFileName(navRef, nameString);
- CFRelease(nameString);
- }
- else
- {
- error = paramErr;
- }
- }
-
+ std::string namestring = filename;
+ if (namestring.empty()) namestring="Untitled";
+
+// if (! boost::algorithm::ends_with(namestring, extension) )
+// {
+// namestring = namestring + "." + extension;
+//
+// }
+
gViewerWindow->getWindow()->beforeDialog();
// Run the dialog
- if (error == noErr)
- error = NavDialogRun(navRef);
+ std::string* filev = doSaveDialog(&namestring,
+ &type,
+ &creator,
+ &extension,
+ mPickOptions);
gViewerWindow->getWindow()->afterDialog();
- if (error == noErr)
- error = NavDialogGetReply(navRef, &navReply);
-
- if (navRef)
- NavDialogDispose(navRef);
-
- if (error == noErr && navReply.validRecord)
+ if ( filev && !filev->empty() )
{
- SInt32 count = 0;
-
- // AE indexes are 1 based...
- error = AECountItems(&navReply.selection, &count);
- if (count > 0)
- {
- // Get the FSRef to the containing folder
- FSRef fsRef;
- AEKeyword theAEKeyword;
- DescType typeCode;
- Size actualSize = 0;
-
- memset(&fsRef, 0, sizeof(fsRef));
- error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
-
- if (error == noErr)
- {
- char path[PATH_MAX]; /*Flawfinder: ignore*/
- char newFileName[SINGLE_FILENAME_BUFFER_SIZE]; /*Flawfinder: ignore*/
-
- error = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX);
- if (error == noErr)
- {
- if (CFStringGetCString(navReply.saveFileName, newFileName, sizeof(newFileName), kCFStringEncodingUTF8))
- {
- mFiles.push_back(std::string(path) + "/" + std::string(newFileName));
- }
- else
- {
- error = paramErr;
- }
- }
- else
- {
- error = paramErr;
- }
- }
- }
- }
+ mFiles.push_back(*filev);
+ return true;
+ }
- return error;
+ return false;
}
BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
@@ -924,16 +749,21 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
return FALSE;
}
- OSStatus error = noErr;
-
reset();
- mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
+ mPickOptions &= ~F_MULTIPLE;
+ mPickOptions |= F_FILE;
+
+ if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
+ {
+
+ mPickOptions |= ( F_NAV_SUPPORT | F_DIRECTORY );
+ mPickOptions &= ~F_FILE;
+ }
if(filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
{
- // mNavOptions.optionFlags |= kNavAllowOpenPackages;
- mNavOptions.optionFlags |= kNavSupportPackages;
+ mPickOptions &= F_NAV_SUPPORT;
}
if (blocking)
@@ -942,14 +772,13 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
send_agent_pause();
}
+
+ success = doNavChooseDialog(filter);
+
+ if (success)
{
- error = doNavChooseDialog(filter);
- }
-
- if (error == noErr)
- {
- if (getFileCount())
- success = true;
+ if (!getFileCount())
+ success = false;
}
if (blocking)
@@ -975,21 +804,22 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
return FALSE;
}
- OSStatus error = noErr;
-
reset();
-
- mNavOptions.optionFlags |= kNavAllowMultipleFiles;
+
+ mPickOptions |= F_FILE;
+
+ mPickOptions |= F_MULTIPLE;
// Modal, so pause agent
send_agent_pause();
+
+ success = doNavChooseDialog(filter);
+
+ send_agent_resume();
+
+ if (success)
{
- error = doNavChooseDialog(filter);
- }
- send_agent_resume();
- if (error == noErr)
- {
- if (getFileCount())
- success = true;
+ if (!getFileCount())
+ success = false;
if (getFileCount() > 1)
mLocked = true;
}
@@ -1001,37 +831,37 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
{
+
if( mLocked )
- return FALSE;
- BOOL success = FALSE;
- OSStatus error = noErr;
+ return false;
+ BOOL success = false;
// if local file browsing is turned off, return without opening dialog
if ( check_local_file_access_enabled() == false )
{
- return FALSE;
+ return false;
}
reset();
- mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
+ mPickOptions &= ~F_MULTIPLE;
// Modal, so pause agent
send_agent_pause();
+
+ success = doNavSaveDialog(filter, filename);
+
+ if (success)
{
- error = doNavSaveDialog(filter, filename);
- }
- send_agent_resume();
- if (error == noErr)
- {
- if (getFileCount())
- success = true;
+ if (!getFileCount())
+ success = false;
}
// Account for the fact that the app has been stalled.
LLFrameTimer::updateFrameTime();
return success;
}
+//END LL_DARWIN
#elif LL_LINUX || LL_SOLARIS
@@ -1537,4 +1367,4 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
return FALSE;
}
-#endif
+#endif // LL_LINUX || LL_SOLARIS
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 4f602f63f1..0d279f73f3 100755
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -39,8 +39,8 @@
#include <Carbon/Carbon.h>
// AssertMacros.h does bad things.
-#include "fix_macros.h"
#undef verify
+#undef check
#undef require
#include <vector>
@@ -85,7 +85,8 @@ public:
FFLOAD_MODEL = 9,
FFLOAD_COLLADA = 10,
FFLOAD_SCRIPT = 11,
- FFLOAD_DICTIONARY = 12
+ FFLOAD_DICTIONARY = 12,
+ FFLOAD_DIRECTORY = 13 //To call from lldirpicker.
};
enum ESaveFilter
@@ -158,15 +159,14 @@ private:
#endif
#if LL_DARWIN
- NavDialogCreationOptions mNavOptions;
+ S32 mPickOptions;
std::vector<std::string> mFileVector;
UInt32 mFileIndex;
- OSStatus doNavChooseDialog(ELoadFilter filter);
- OSStatus doNavSaveDialog(ESaveFilter filter, const std::string& filename);
- void getFilePath(SInt32 index);
- void getFileName(SInt32 index);
- static Boolean navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode);
+ bool doNavChooseDialog(ELoadFilter filter);
+ bool doNavSaveDialog(ESaveFilter filter, const std::string& filename);
+ //static Boolean navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode);
+ std::vector<std::string>* navOpenFilterProc(ELoadFilter filter);
#endif
#if LL_GTK
diff --git a/indra/newview/llfilepicker_mac.h b/indra/newview/llfilepicker_mac.h
new file mode 100644
index 0000000000..e0b7e2e8ce
--- /dev/null
+++ b/indra/newview/llfilepicker_mac.h
@@ -0,0 +1,58 @@
+/**
+ * @file llfilepicker_mac.h
+ * @brief OS-specific file picker
+ *
+ * $LicenseInfo:firstyear=2001&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$
+ */
+
+// OS specific file selection dialog. This is implemented as a
+// singleton class, so call the instance() method to get the working
+// instance. When you call getMultipleOpenFile(), it locks the picker
+// until you iterate to the end of the list of selected files with
+// getNextFile() or call reset().
+
+#ifndef LL_LLFILEPICKER_MAC_H
+#define LL_LLFILEPICKER_MAC_H
+
+#if LL_DARWIN
+
+#include <string>
+#include <vector>
+
+//void modelessPicker();
+std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,
+ unsigned int flags);
+std::string* doSaveDialog(const std::string* file,
+ const std::string* type,
+ const std::string* creator,
+ const std::string* extension,
+ unsigned int flags);
+enum {
+ F_FILE = 0x00000001,
+ F_DIRECTORY = 0x00000002,
+ F_MULTIPLE = 0x00000004,
+ F_NAV_SUPPORT=0x00000008
+};
+
+#endif
+
+#endif
diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm
new file mode 100644
index 0000000000..2a84226e0a
--- /dev/null
+++ b/indra/newview/llfilepicker_mac.mm
@@ -0,0 +1,132 @@
+/**
+ * @file llfilepicker_mac.cpp
+ * @brief OS-specific file picker
+ *
+ * $LicenseInfo:firstyear=2001&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$
+ */
+
+#ifdef LL_DARWIN
+#import <Cocoa/Cocoa.h>
+#include <iostream>
+#include "llfilepicker_mac.h"
+
+std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,
+ unsigned int flags)
+{
+ int i, result;
+
+ //Aura TODO: We could init a small window and release it at the end of this routine
+ //for a modeless interface.
+
+ NSOpenPanel *panel = [NSOpenPanel openPanel];
+ //NSString *fileName = nil;
+ NSMutableArray *fileTypes = nil;
+
+
+ if ( allowed_types && !allowed_types->empty())
+ {
+ fileTypes = [[NSMutableArray alloc] init];
+
+ for (i=0;i<allowed_types->size();++i)
+ {
+ [fileTypes addObject:
+ [NSString stringWithCString:(*allowed_types)[i].c_str()
+ encoding:[NSString defaultCStringEncoding]]];
+ }
+ }
+
+ //[panel setMessage:@"Import one or more files or directories."];
+ [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ];
+ [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ];
+ [panel setCanCreateDirectories: true];
+ [panel setResolvesAliases: true];
+ [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )];
+ [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
+
+ std::vector<std::string>* outfiles = NULL;
+
+ if (fileTypes)
+ {
+ [panel setAllowedFileTypes:fileTypes];
+ result = [panel runModal];
+ }
+ else
+ {
+ // I suggest it's better to open the last path and let this default to home dir as necessary
+ // for consistency with other OS X apps
+ //
+ //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ];
+ result = [panel runModal];
+ }
+
+ if (result == NSOKButton)
+ {
+ NSArray *filesToOpen = [panel URLs];
+ int i, count = [filesToOpen count];
+
+ if (count > 0)
+ {
+ outfiles = new std::vector<std::string>;
+ }
+
+ for (i=0; i<count; i++) {
+ NSString *aFile = [[filesToOpen objectAtIndex:i] path];
+ std::string *afilestr = new std::string([aFile UTF8String]);
+ outfiles->push_back(*afilestr);
+ }
+ }
+ return outfiles;
+}
+
+
+std::string* doSaveDialog(const std::string* file,
+ const std::string* type,
+ const std::string* creator,
+ const std::string* extension,
+ unsigned int flags)
+{
+ NSSavePanel *panel = [NSSavePanel savePanel];
+
+ NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]];
+ NSArray *fileType = [[NSArray alloc] initWithObjects:extensionns,nil];
+
+ //[panel setMessage:@"Save Image File"];
+ [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
+ [panel setCanSelectHiddenExtension:true];
+ [panel setAllowedFileTypes:fileType];
+ NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]];
+
+ std::string *outfile = NULL;
+ NSURL* url = [NSURL fileURLWithPath:fileName];
+ [panel setDirectoryURL: url];
+ if([panel runModal] ==
+ NSFileHandlingPanelOKButton)
+ {
+ NSURL* url = [panel URL];
+ NSString* p = [url path];
+ outfile = new std::string( [p UTF8String] );
+ // write the file
+ }
+ return outfile;
+}
+
+#endif
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 83fb887d81..fea8e34729 100755
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -33,8 +33,10 @@
// Viewer includes
#include "llagent.h"
+#include "llagentui.h"
#include "llappviewer.h"
#include "llsecondlifeurls.h"
+#include "llslurl.h"
#include "llvoiceclient.h"
#include "lluictrlfactory.h"
#include "llviewertexteditor.h"
@@ -250,12 +252,16 @@ LLSD LLFloaterAbout::getInfo()
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
- const LLVector3d &pos = gAgent.getPositionGlobal();
+ LLVector3d pos = gAgent.getPositionGlobal();
info["POSITION"] = ll_sd_from_vector3d(pos);
+ info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos));
info["REGION"] = gAgent.getRegion()->getName();
info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
info["SERVER_VERSION"] = gLastVersionChannel;
+ LLSLURL slurl;
+ LLAgentUI::buildSLURL(slurl);
+ info["SLURL"] = slurl.getSLURLString();
}
// CPU
@@ -307,12 +313,12 @@ LLSD LLFloaterAbout::getInfo()
static std::string get_viewer_release_notes_url()
{
// return a URL to the release notes for this viewer, such as:
- // http://wiki.secondlife.com/wiki/Release_Notes/Second Life Beta Viewer/2.1.0
+ // http://wiki.secondlife.com/wiki/Release_Notes/Second Life Beta Viewer/2.1.0.123456
std::string url = LLTrans::getString("RELEASE_NOTES_BASE_URL");
if (! LLStringUtil::endsWith(url, "/"))
url += "/";
url += LLVersionInfo::getChannel() + "/";
- url += LLVersionInfo::getShortVersion();
+ url += LLVersionInfo::getVersion();
return LLWeb::escapeURL(url);
}
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 113aa9a8f2..c0afb72cff 100755
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -513,6 +513,7 @@ void LLFloaterAvatarPicker::find()
url += "/";
}
url += "?page_size=100&names=";
+ std::replace(text.begin(), text.end(), '.', ' ');
url += LLURI::escape(text);
llinfos << "avatar picker " << url << llendl;
LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID, getKey().asString()));
@@ -748,7 +749,12 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&
{
getChildView("ok_btn")->setEnabled(true);
search_results->setEnabled(true);
- search_results->selectFirstItem();
+ search_results->sortByColumnIndex(1, TRUE);
+ std::string text = getChild<LLUICtrl>("Edit")->getValue().asString();
+ if (!search_results->selectItemByLabel(text, TRUE, 1))
+ {
+ search_results->selectFirstItem();
+ }
onList();
search_results->setFocus(TRUE);
}
diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp
index 39b6e465f3..76f62a7880 100755
--- a/indra/newview/llfloaterbulkpermission.cpp
+++ b/indra/newview/llfloaterbulkpermission.cpp
@@ -57,6 +57,7 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)
mDone(FALSE)
{
mID.generate();
+ mCommitCallbackRegistrar.add("BulkPermission.Ok", boost::bind(&LLFloaterBulkPermission::onOkBtn, this));
mCommitCallbackRegistrar.add("BulkPermission.Apply", boost::bind(&LLFloaterBulkPermission::onApplyBtn, this));
mCommitCallbackRegistrar.add("BulkPermission.Close", boost::bind(&LLFloaterBulkPermission::onCloseBtn, this));
mCommitCallbackRegistrar.add("BulkPermission.CheckAll", boost::bind(&LLFloaterBulkPermission::onCheckAll, this));
@@ -66,6 +67,21 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)
BOOL LLFloaterBulkPermission::postBuild()
{
+ mBulkChangeIncludeAnimations = gSavedSettings.getBOOL("BulkChangeIncludeAnimations");
+ mBulkChangeIncludeBodyParts = gSavedSettings.getBOOL("BulkChangeIncludeBodyParts");
+ mBulkChangeIncludeClothing = gSavedSettings.getBOOL("BulkChangeIncludeClothing");
+ mBulkChangeIncludeGestures = gSavedSettings.getBOOL("BulkChangeIncludeGestures");
+ mBulkChangeIncludeNotecards = gSavedSettings.getBOOL("BulkChangeIncludeNotecards");
+ mBulkChangeIncludeObjects = gSavedSettings.getBOOL("BulkChangeIncludeObjects");
+ mBulkChangeIncludeScripts = gSavedSettings.getBOOL("BulkChangeIncludeScripts");
+ mBulkChangeIncludeSounds = gSavedSettings.getBOOL("BulkChangeIncludeSounds");
+ mBulkChangeIncludeTextures = gSavedSettings.getBOOL("BulkChangeIncludeTextures");
+ mBulkChangeShareWithGroup = gSavedSettings.getBOOL("BulkChangeShareWithGroup");
+ mBulkChangeEveryoneCopy = gSavedSettings.getBOOL("BulkChangeEveryoneCopy");
+ mBulkChangeNextOwnerModify = gSavedSettings.getBOOL("BulkChangeNextOwnerModify");
+ mBulkChangeNextOwnerCopy = gSavedSettings.getBOOL("BulkChangeNextOwnerCopy");
+ mBulkChangeNextOwnerTransfer = gSavedSettings.getBOOL("BulkChangeNextOwnerTransfer");
+
return TRUE;
}
@@ -144,6 +160,12 @@ void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,
}
}
+void LLFloaterBulkPermission::onOkBtn()
+{
+ doApply();
+ closeFloater();
+}
+
void LLFloaterBulkPermission::onApplyBtn()
{
doApply();
@@ -151,6 +173,20 @@ void LLFloaterBulkPermission::onApplyBtn()
void LLFloaterBulkPermission::onCloseBtn()
{
+ gSavedSettings.setBOOL("BulkChangeIncludeAnimations", mBulkChangeIncludeAnimations);
+ gSavedSettings.setBOOL("BulkChangeIncludeBodyParts", mBulkChangeIncludeBodyParts);
+ gSavedSettings.setBOOL("BulkChangeIncludeClothing", mBulkChangeIncludeClothing);
+ gSavedSettings.setBOOL("BulkChangeIncludeGestures", mBulkChangeIncludeGestures);
+ gSavedSettings.setBOOL("BulkChangeIncludeNotecards", mBulkChangeIncludeNotecards);
+ gSavedSettings.setBOOL("BulkChangeIncludeObjects", mBulkChangeIncludeObjects);
+ gSavedSettings.setBOOL("BulkChangeIncludeScripts", mBulkChangeIncludeScripts);
+ gSavedSettings.setBOOL("BulkChangeIncludeSounds", mBulkChangeIncludeSounds);
+ gSavedSettings.setBOOL("BulkChangeIncludeTextures", mBulkChangeIncludeTextures);
+ gSavedSettings.setBOOL("BulkChangeShareWithGroup", mBulkChangeShareWithGroup);
+ gSavedSettings.setBOOL("BulkChangeEveryoneCopy", mBulkChangeEveryoneCopy);
+ gSavedSettings.setBOOL("BulkChangeNextOwnerModify", mBulkChangeNextOwnerModify);
+ gSavedSettings.setBOOL("BulkChangeNextOwnerCopy", mBulkChangeNextOwnerCopy);
+ gSavedSettings.setBOOL("BulkChangeNextOwnerTransfer", mBulkChangeNextOwnerTransfer);
closeFloater();
}
diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h
index 7dd05df7ee..25e76eca65 100755
--- a/indra/newview/llfloaterbulkpermission.h
+++ b/indra/newview/llfloaterbulkpermission.h
@@ -72,6 +72,7 @@ private:
bool is_new);
void onCloseBtn();
+ void onOkBtn();
void onApplyBtn();
void onCommitCopy();
void onCheckAll() { doCheckUncheckAll(TRUE); }
@@ -94,6 +95,21 @@ private:
LLUUID mCurrentObjectID;
BOOL mDone;
+ bool mBulkChangeIncludeAnimations;
+ bool mBulkChangeIncludeBodyParts;
+ bool mBulkChangeIncludeClothing;
+ bool mBulkChangeIncludeGestures;
+ bool mBulkChangeIncludeNotecards;
+ bool mBulkChangeIncludeObjects;
+ bool mBulkChangeIncludeScripts;
+ bool mBulkChangeIncludeSounds;
+ bool mBulkChangeIncludeTextures;
+ bool mBulkChangeShareWithGroup;
+ bool mBulkChangeEveryoneCopy;
+ bool mBulkChangeNextOwnerModify;
+ bool mBulkChangeNextOwnerCopy;
+ bool mBulkChangeNextOwnerTransfer;
+
LLUUID mID;
const char* mStartString;
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index a3d715530d..b570de14aa 100755
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -50,6 +50,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i
BOOL LLFloaterConversationPreview::postBuild()
{
mChatHistory = getChild<LLChatHistory>("chat_history");
+ LLLoadHistoryThread::setLoadEndSignal(boost::bind(&LLFloaterConversationPreview::SetPages, this, _1, _2));
const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID);
std::string name;
@@ -70,7 +71,7 @@ BOOL LLFloaterConversationPreview::postBuild()
name = LLTrans::getString("NearbyChatTitle");
file = "chat";
}
-
+ mChatHistoryFileName = file;
LLStringUtil::format_map_t args;
args["[NAME]"] = name;
std::string title = getString("Title", args);
@@ -80,23 +81,46 @@ BOOL LLFloaterConversationPreview::postBuild()
load_params["load_all_history"] = true;
load_params["cut_off_todays_date"] = false;
- LLLogChat::loadChatHistory(file, mMessages, load_params);
- mCurrentPage = mMessages.size() / mPageSize;
+ LLSD loading;
+ loading[LL_IM_TEXT] = LLTrans::getString("loading_chat_logs");
+ mMessages.push_back(loading);
mPageSpinner = getChild<LLSpinCtrl>("history_page_spin");
mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this));
mPageSpinner->setMinValue(1);
- mPageSpinner->setMaxValue(mCurrentPage + 1);
- mPageSpinner->set(mCurrentPage + 1);
-
- std::string total_page_num = llformat("/ %d", mCurrentPage + 1);
- getChild<LLTextBox>("page_num_label")->setValue(total_page_num);
-
+ mPageSpinner->set(1);
+ mPageSpinner->setEnabled(false);
+ mChatHistoryLoaded = false;
+ LLLogChat::startChatHistoryThread(file, load_params);
return LLFloater::postBuild();
}
+void LLFloaterConversationPreview::SetPages(std::list<LLSD>& messages, const std::string& file_name)
+{
+ if(file_name == mChatHistoryFileName)
+ {
+ mMessages = messages;
+
+
+ mCurrentPage = mMessages.size() / mPageSize;
+ mPageSpinner->setEnabled(true);
+ mPageSpinner->setMaxValue(mCurrentPage+1);
+ mPageSpinner->set(mCurrentPage+1);
+
+ std::string total_page_num = llformat("/ %d", mCurrentPage+1);
+ getChild<LLTextBox>("page_num_label")->setValue(total_page_num);
+ mChatHistoryLoaded = true;
+
+ }
+
+}
void LLFloaterConversationPreview::draw()
{
+ if(mChatHistoryLoaded)
+ {
+ showHistory();
+ mChatHistoryLoaded = false;
+ }
LLFloater::draw();
}
@@ -128,6 +152,11 @@ void LLFloaterConversationPreview::showHistory()
for (int msg_num = 0; (iter != mMessages.end() && msg_num < mPageSize); ++iter, ++msg_num)
{
+ if (iter->size() == 0)
+ {
+ continue;
+ }
+
LLSD msg = *iter;
LLUUID from_id = LLUUID::null;
diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h
index b17ae84b63..389f3dfd09 100755
--- a/indra/newview/llfloaterconversationpreview.h
+++ b/indra/newview/llfloaterconversationpreview.h
@@ -42,6 +42,7 @@ public:
virtual ~LLFloaterConversationPreview(){};
virtual BOOL postBuild();
+ void SetPages(std::list<LLSD>& messages,const std::string& file_name);
virtual void draw();
virtual void onOpen(const LLSD& key);
@@ -59,6 +60,8 @@ private:
std::list<LLSD> mMessages;
std::string mAccountName;
std::string mCompleteName;
+ std::string mChatHistoryFileName;
+ bool mChatHistoryLoaded;
};
#endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */
diff --git a/indra/newview/llfloatergotoline.cpp b/indra/newview/llfloatergotoline.cpp
new file mode 100644
index 0000000000..d66e418926
--- /dev/null
+++ b/indra/newview/llfloatergotoline.cpp
@@ -0,0 +1,160 @@
+/**
+ * @file llfloatergotoline.h
+ * @author MartinRJ
+ * @brief LLFloaterGotoLine class implementation
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, 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 "llfloatergotoline.h"
+#include "llpreviewscript.h"
+#include "llfloaterreg.h"
+#include "lllineeditor.h"
+#include "llviewertexteditor.h"
+#include "llviewerwindow.h"
+
+LLFloaterGotoLine* LLFloaterGotoLine::sInstance = NULL;
+
+LLFloaterGotoLine::LLFloaterGotoLine(LLScriptEdCore* editor_core)
+: LLFloater(LLSD()),
+ mGotoBox(NULL),
+ mEditorCore(editor_core)
+{
+ buildFromFile("floater_goto_line.xml");
+
+ sInstance = this;
+
+ // find floater in which script panel is embedded
+ LLView* viewp = (LLView*)editor_core;
+ while(viewp)
+ {
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
+ if (floaterp)
+ {
+ floaterp->addDependentFloater(this);
+ break;
+ }
+ viewp = viewp->getParent();
+ }
+}
+
+BOOL LLFloaterGotoLine::postBuild()
+{
+ mGotoBox = getChild<LLLineEditor>("goto_line");
+ mGotoBox->setCommitCallback(boost::bind(&LLFloaterGotoLine::onGotoBoxCommit, this));
+ mGotoBox->setCommitOnFocusLost(FALSE);
+ getChild<LLLineEditor>("goto_line")->setPrevalidate(LLTextValidate::validateNonNegativeS32);
+ childSetAction("goto_btn", onBtnGoto,this);
+ setDefaultBtn("goto_btn");
+
+ return TRUE;
+}
+
+//static
+void LLFloaterGotoLine::show(LLScriptEdCore* editor_core)
+{
+ if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core)
+ {
+ sInstance->closeFloater();
+ delete sInstance;
+ }
+
+ if (!sInstance)
+ {
+ // sInstance will be assigned in the constructor.
+ new LLFloaterGotoLine(editor_core);
+ }
+
+ sInstance->openFloater();
+}
+
+LLFloaterGotoLine::~LLFloaterGotoLine()
+{
+ sInstance = NULL;
+}
+
+// static
+void LLFloaterGotoLine::onBtnGoto(void *userdata)
+{
+ LLFloaterGotoLine* self = (LLFloaterGotoLine*)userdata;
+ self->handleBtnGoto();
+}
+
+void LLFloaterGotoLine::handleBtnGoto()
+{
+ S32 row = 0;
+ S32 column = 0;
+ row = getChild<LLUICtrl>("goto_line")->getValue().asInteger();
+ if (row >= 0)
+ {
+ if (mEditorCore && mEditorCore->mEditor)
+ {
+ mEditorCore->mEditor->deselect();
+ mEditorCore->mEditor->setCursor(row, column);
+ mEditorCore->mEditor->setFocus(TRUE);
+ }
+ }
+}
+
+bool LLFloaterGotoLine::hasAccelerators() const
+{
+ if (mEditorCore)
+ {
+ return mEditorCore->hasAccelerators();
+ }
+ return FALSE;
+}
+
+BOOL LLFloaterGotoLine::handleKeyHere(KEY key, MASK mask)
+{
+ if (mEditorCore)
+ {
+ return mEditorCore->handleKeyHere(key, mask);
+ }
+
+ return FALSE;
+}
+
+void LLFloaterGotoLine::onGotoBoxCommit()
+{
+ S32 row = 0;
+ S32 column = 0;
+ row = getChild<LLUICtrl>("goto_line")->getValue().asInteger();
+ if (row >= 0)
+ {
+ if (mEditorCore && mEditorCore->mEditor)
+ {
+ mEditorCore->mEditor->setCursor(row, column);
+
+ S32 rownew = 0;
+ S32 columnnew = 0;
+ mEditorCore->mEditor->getCurrentLineAndColumn( &rownew, &columnnew, FALSE ); // don't include wordwrap
+ if (rownew == row && columnnew == column)
+ {
+ mEditorCore->mEditor->deselect();
+ mEditorCore->mEditor->setFocus(TRUE);
+ sInstance->closeFloater();
+ } //else do nothing (if the cursor-position didn't change)
+ }
+ }
+}
diff --git a/indra/newview/llfloatergotoline.h b/indra/newview/llfloatergotoline.h
new file mode 100644
index 0000000000..058d601752
--- /dev/null
+++ b/indra/newview/llfloatergotoline.h
@@ -0,0 +1,66 @@
+/**
+ * @file llfloatergotoline.h
+ * @author MartinRJ
+ * @brief LLFloaterGotoLine class definition
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, 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_LLFLOATERGOTOLINE_H
+#define LL_LLFLOATERGOTOLINE_H
+
+#include "llfloater.h"
+#include "lllineeditor.h"
+#include "llpreviewscript.h"
+
+class LLScriptEdCore;
+
+class LLFloaterGotoLine : public LLFloater
+{
+public:
+ LLFloaterGotoLine(LLScriptEdCore* editor_core);
+ ~LLFloaterGotoLine();
+
+ /*virtual*/ BOOL postBuild();
+ static void show(LLScriptEdCore* editor_core);
+
+ static void onBtnGoto(void* userdata);
+ void handleBtnGoto();
+
+ LLScriptEdCore* getEditorCore() { return mEditorCore; }
+ static LLFloaterGotoLine* getInstance() { return sInstance; }
+
+ virtual bool hasAccelerators() const;
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+private:
+
+ LLScriptEdCore* mEditorCore;
+
+ static LLFloaterGotoLine* sInstance;
+
+protected:
+ LLLineEditor* mGotoBox;
+ void onGotoBoxCommit();
+};
+
+#endif // LL_LLFLOATERGOTOLINE_H
diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp
index 116bd241c4..792a2a5d25 100755
--- a/indra/newview/llfloaterhardwaresettings.cpp
+++ b/indra/newview/llfloaterhardwaresettings.cpp
@@ -89,8 +89,10 @@ void LLFloaterHardwareSettings::refresh()
void LLFloaterHardwareSettings::refreshEnabledState()
{
+ F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
+
S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
- S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting();
+ S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem);
getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem);
@@ -149,12 +151,17 @@ BOOL LLFloaterHardwareSettings::postBuild()
{
childSetAction("OK", onBtnOK, this);
+// Don't do this on Mac as their braindead GL versioning
+// sets this when 8x and 16x are indeed available
+//
+#if !LL_DARWIN
if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f)
{ //remove FSAA settings above "4x"
LLComboBox* combo = getChild<LLComboBox>("fsaa");
combo->remove("8x");
combo->remove("16x");
}
+#endif
refresh();
center();
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index b40789db9c..d6b4909318 100755
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -47,6 +47,7 @@
#include "llfloaterpreference.h"
#include "llimview.h"
#include "llnotificationsutil.h"
+#include "lltoolbarview.h"
#include "lltransientfloatermgr.h"
#include "llviewercontrol.h"
#include "llconversationview.h"
@@ -54,6 +55,7 @@
#include "llworld.h"
#include "llsdserialize.h"
#include "llviewerobjectlist.h"
+#include "boost/foreach.hpp"
//
// LLFloaterIMContainer
@@ -63,7 +65,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mExpandCollapseBtn(NULL),
mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"),
- mInitialized(false)
+ mInitialized(false),
+ mIsFirstLaunch(true)
{
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@@ -113,6 +116,10 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str
void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
{
+ if(!isInVisibleChain())
+ {
+ setVisibleAndFrontmost(false);
+ }
selectConversationPair(session_id, true);
collapseMessagesPane(false);
}
@@ -204,6 +211,7 @@ BOOL LLFloaterIMContainer::postBuild()
// a scroller for folder view
LLRect scroller_view_rect = mConversationsListPanel->getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ scroller_view_rect.mBottom += getChild<LLLayoutStack>("conversations_pane_buttons_stack")->getRect().getHeight();
LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>());
scroller_params.rect(scroller_view_rect);
@@ -221,7 +229,8 @@ BOOL LLFloaterIMContainer::postBuild()
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this));
mStubCollapseBtn = getChild<LLButton>("stub_collapse_btn");
mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this));
- getChild<LLButton>("speak_btn")->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));
+ mSpeakBtn = getChild<LLButton>("speak_btn");
+ mSpeakBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));
childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this));
@@ -258,7 +267,6 @@ BOOL LLFloaterIMContainer::postBuild()
void LLFloaterIMContainer::onOpen(const LLSD& key)
{
LLMultiFloater::onOpen(key);
- openNearbyChat();
reSelectConversation();
assignResizeLimits();
}
@@ -593,6 +601,7 @@ void LLFloaterIMContainer::setMinimized(BOOL b)
//Switching from minimized to un-minimized
if(was_minimized && !b)
{
+ gToolBarView->flashCommand(LLCommandId("chat"), false);
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession);
if(session_floater && !session_floater->isTornOff())
@@ -621,7 +630,6 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLFloaterReg::toggleInstanceOrBringToFront(name);
selectConversationPair(LLUUID(NULL), false, false);
}
- openNearbyChat();
flashConversationItemWidget(mSelectedSession,false);
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession);
@@ -651,7 +659,11 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second);
if (widget)
{
- widget->setVisibleIfDetached(visible);
+ LLFloater* session_floater = widget->getSessionFloater();
+ if (session_floater != nearby_chat)
+ {
+ widget->setVisibleIfDetached(visible);
+ }
}
}
@@ -659,10 +671,37 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLMultiFloater::setVisible(visible);
}
+void LLFloaterIMContainer::getDetachedConversationFloaters(floater_list_t& floaters)
+{
+ typedef conversations_widgets_map::value_type conv_pair;
+ BOOST_FOREACH(conv_pair item, mConversationsWidgets)
+ {
+ LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(item.second);
+ if (widget)
+ {
+ LLFloater* session_floater = widget->getSessionFloater();
+ if (session_floater && session_floater->isDetachedAndNotMinimized())
+ {
+ floaters.push_back(session_floater);
+ }
+ }
+ }
+}
+
void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLMultiFloater::setVisibleAndFrontmost(take_focus, key);
- selectConversationPair(getSelectedSession(), false, take_focus);
+ // Do not select "Nearby Chat" conversation, since it will bring its window to front
+ // Only select other sessions
+ if (!getSelectedSession().isNull())
+ {
+ selectConversationPair(getSelectedSession(), false, take_focus);
+ }
+ if (mInitialized && mIsFirstLaunch)
+ {
+ collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
+ mIsFirstLaunch = false;
+ }
}
void LLFloaterIMContainer::updateResizeLimits()
@@ -779,13 +818,6 @@ void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 d
setCanMinimize(at_least_one_panel_is_expanded);
assignResizeLimits();
-
- // force set correct size for the title after show/hide minimize button
- LLRect cur_rect = getRect();
- LLRect force_rect = cur_rect;
- force_rect.mRight = cur_rect.mRight + 1;
- setRect(force_rect);
- setRect(cur_rect);
}
void LLFloaterIMContainer::assignResizeLimits()
@@ -793,15 +825,12 @@ void LLFloaterIMContainer::assignResizeLimits()
bool is_conv_pane_expanded = !mConversationsPane->isCollapsed();
bool is_msg_pane_expanded = !mMessagesPane->isCollapsed();
- // With two panels visible number of borders is three, because the borders
- // between the panels are merged into one
- S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3);
- S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH;
- S32 conv_pane_target_width = is_conv_pane_expanded?
- (is_msg_pane_expanded?
- mConversationsPane->getRect().getWidth()
- : mConversationsPane->getExpandedMinDim())
- : mConversationsPane->getMinDim();
+ S32 summary_width_of_visible_borders = (is_msg_pane_expanded ? mConversationsStack->getPanelSpacing() : 0) + 1;
+
+ S32 conv_pane_target_width = is_conv_pane_expanded
+ ? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() )
+ : 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;
@@ -961,11 +990,11 @@ void LLFloaterIMContainer::setSortOrder(const LLConversationSort& order)
conversation_floater->setSortOrder(order);
}
}
-
+
gSavedSettings.setU32("ConversationSortOrder", (U32)order);
}
-void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids)
+void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids, bool participant_uuids/* = true*/)
{
const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList();
@@ -978,7 +1007,7 @@ void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids)
conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem());
//When a one-on-one conversation exists, retrieve the participant id from the conversation floater
- if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1)
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1 && participant_uuids)
{
LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversationItem->getUUID());
LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID();
@@ -1046,6 +1075,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);
@@ -1133,6 +1166,11 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
{
LLFloater::onClickClose(conversationFloater);
}
+ else if("close_selected_conversations" == command)
+ {
+ getSelectedUUIDs(selectedIDS,false);
+ closeSelectedConversations(selectedIDS);
+ }
else if("open_voice_conversation" == command)
{
gIMMgr->startCall(conversationItem->getUUID());
@@ -1143,7 +1181,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());
}
@@ -1156,6 +1194,17 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
}
}
}
+ //if there is no LLFloaterIMSession* instance for selected conversation it might be Nearby chat
+ else
+ {
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_NEARBY)
+ {
+ if("chat_history" == command)
+ {
+ LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true);
+ }
+ }
+ }
}
void LLFloaterIMContainer::doToSelected(const LLSD& userdata)
@@ -1185,7 +1234,7 @@ void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata)
if (action == "group_profile")
{
- LLGroupActions::show(mSelectedSession);
+ LLGroupActions::show(mSelectedSession);
}
else if (action == "activate_group")
{
@@ -1211,7 +1260,19 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
//Enable Chat history item for ad-hoc and group conversations
if ("can_chat_history" == item && uuids.size() > 0)
{
- return LLLogChat::isTranscriptExist(uuids.front());
+ //Disable menu item if selected participant is user agent
+ if(uuids.front() != gAgentID)
+ {
+ if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_NEARBY)
+ {
+ return LLLogChat::isNearbyTranscriptExist();
+ }
+ else
+ {
+ bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP);
+ return LLLogChat::isTranscriptExist(uuids.front(),is_group);
+ }
+ }
}
// If nothing is selected(and selected item is not group chat), everything needs to be disabled
@@ -1886,13 +1947,6 @@ void LLFloaterIMContainer::openNearbyChat()
}
}
-void LLFloaterIMContainer::onNearbyChatClosed()
-{
- // If nearby chat is the only remaining conversation and it is closed, close whole conversation floater as well
- if (mConversationsItems.size() == 1)
- closeFloater();
-}
-
void LLFloaterIMContainer::reSelectConversation()
{
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession);
@@ -1904,7 +1958,6 @@ void LLFloaterIMContainer::reSelectConversation()
void LLFloaterIMContainer::updateSpeakBtnState()
{
- LLButton* mSpeakBtn = getChild<LLButton>("speak_btn");
mSpeakBtn->setToggleState(LLVoiceClient::getInstance()->getUserPTTState());
mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak"));
}
@@ -1925,6 +1978,17 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id,
}
}
+void LLFloaterIMContainer::highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted)
+{
+ //Finds the conversation line item to highlight using the session_id
+ LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id));
+
+ if (widget)
+ {
+ widget->setHighlightState(is_highlighted);
+ }
+}
+
bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget)
{
llassert(conversation_item_widget != NULL);
@@ -1940,23 +2004,28 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve
BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )
{
+ BOOL handled = FALSE;
+
if(mask == MASK_ALT)
{
if (KEY_RETURN == key )
{
expandConversation();
+ handled = TRUE;
}
if ((KEY_DOWN == key ) || (KEY_RIGHT == key))
{
selectNextorPreviousConversation(true);
+ handled = TRUE;
}
if ((KEY_UP == key) || (KEY_LEFT == key))
{
selectNextorPreviousConversation(false);
+ handled = TRUE;
}
}
- return TRUE;
+ return handled;
}
bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected)
@@ -2013,7 +2082,22 @@ void LLFloaterIMContainer::expandConversation()
}
}
-void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
+// By default, if torn off session is currently frontmost, LLFloater::isFrontmost() will return FALSE, which can lead to some bugs
+// So LLFloater::isFrontmost() is overriden here to check both selected session and the IM floater itself
+// Exclude "Nearby Chat" session from the check, as "Nearby Chat" window and "Conversations" floater can be brought
+// to front independently
+/*virtual*/
+BOOL LLFloaterIMContainer::isFrontmost()
+{
+ LLFloaterIMSessionTab* selected_session = LLFloaterIMSessionTab::getConversation(mSelectedSession);
+ LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
+ return (selected_session && selected_session->isFrontmost() && (selected_session != nearby_chat))
+ || LLFloater::isFrontmost();
+}
+
+// For conversations, closeFloater() (linked to Ctrl-W) does not actually close the floater but the active conversation.
+// This is intentional so it doesn't confuse the user. onClickCloseBtn() closes the whole floater.
+void LLFloaterIMContainer::onClickCloseBtn()
{
// Always unminimize before trying to close.
// Most of the time the user will never see this state.
@@ -2022,7 +2106,80 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
LLMultiFloater::setMinimized(FALSE);
}
- LLFloater::closeFloater(app_quitting);
+ LLFloater::closeFloater();
+}
+
+void LLFloaterIMContainer::closeHostedFloater()
+{
+ onClickCloseBtn();
+}
+
+void LLFloaterIMContainer::closeAllConversations()
+{
+ LLDynamicArray<LLUUID> ids;
+ for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++)
+ {
+ LLUUID session_id = it_session->first;
+ if (session_id != LLUUID())
+ {
+ ids.push_back(session_id);
+ }
+ }
+
+ for (LLDynamicArray<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(*it);
+ LLFloater::onClickClose(conversationFloater);
+ }
+}
+
+void LLFloaterIMContainer::closeSelectedConversations(const uuid_vec_t& ids)
+{
+ for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ //We don't need to close Nearby chat, so skip it
+ if (*it != LLUUID())
+ {
+ LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(*it);
+ if(conversationFloater)
+ {
+ LLFloater::onClickClose(conversationFloater);
+ }
+ }
+ }
+}
+void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
+{
+ if(app_quitting)
+ {
+ closeAllConversations();
+ onClickCloseBtn();
+ }
+ else
+ {
+ // Check for currently active session
+ LLUUID session_id = getSelectedSession();
+ // If current session is Nearby Chat or there is only one session remaining, close the floater
+ if (mConversationsItems.size() == 1 || session_id == LLUUID() || app_quitting)
+ {
+ onClickCloseBtn();
+ }
+ else
+ {
+ // Otherwise, close current conversation
+ LLFloaterIMSessionTab* active_conversation = LLFloaterIMSessionTab::getConversation(session_id);
+ if (active_conversation)
+ {
+ active_conversation->closeFloater();
+ }
+ }
+ }
+}
+
+void LLFloaterIMContainer::handleReshape(const LLRect& rect, bool by_user)
+{
+ LLMultiFloater::handleReshape(rect, by_user);
+ storeRectControl();
}
// EOF
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index e39d20ec35..36da457cac 100755
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -63,6 +63,8 @@ public:
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void updateResizeLimits();
+ /*virtual*/ void handleReshape(const LLRect& rect, bool by_user);
+
void onCloseFloater(LLUUID& id);
/*virtual*/ void addFloater(LLFloater* floaterp,
@@ -105,8 +107,6 @@ public:
LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); }
LLConversationSort& getSortOrder() { return mConversationViewModel.getSorter(); }
- void onNearbyChatClosed();
-
// Handling of lists of participants is public so to be common with llfloatersessiontab
// *TODO : Find a better place for this.
bool checkContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS);
@@ -116,6 +116,10 @@ public:
void assignResizeLimits();
virtual BOOL handleKeyHere(KEY key, MASK mask );
/*virtual*/ void closeFloater(bool app_quitting = false);
+ void closeAllConversations();
+ void closeSelectedConversations(const uuid_vec_t& ids);
+ /*virtual*/ BOOL isFrontmost();
+
private:
typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t;
@@ -130,6 +134,8 @@ private:
void onStubCollapseButtonClicked();
void processParticipantsStyleUpdate();
void onSpeakButtonClicked();
+ /*virtual*/ void onClickCloseBtn();
+ /*virtual*/ void closeHostedFloater();
void collapseConversationsPane(bool collapse, bool save_is_allowed=true);
@@ -144,7 +150,7 @@ private:
void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order);
void setSortOrder(const LLConversationSort& order);
- void getSelectedUUIDs(uuid_vec_t& selected_uuids);
+ void getSelectedUUIDs(uuid_vec_t& selected_uuids, bool participant_uuids = true);
const LLConversationItem * getCurSelectedViewModelItem();
void getParticipantUUIDs(uuid_vec_t& selected_uuids);
void doToSelected(const LLSD& userdata);
@@ -169,6 +175,7 @@ private:
LLButton* mExpandCollapseBtn;
LLButton* mStubCollapseBtn;
+ LLButton* mSpeakBtn;
LLPanel* mStubPanel;
LLTextBox* mStubTextBox;
LLLayoutPanel* mMessagesPane;
@@ -176,6 +183,7 @@ private:
LLLayoutStack* mConversationsStack;
bool mInitialized;
+ bool mIsFirstLaunch;
LLUUID mSelectedSession;
std::string mGeneralTitle;
@@ -190,9 +198,12 @@ public:
void updateSpeakBtnState();
static bool isConversationLoggingAllowed();
void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes);
+ void highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted);
bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget);
boost::signals2::connection mMicroChangedSignal;
S32 getConversationListItemSize() { return mConversationsWidgets.size(); }
+ typedef std::list<LLFloater*> floater_list_t;
+ void getDetachedConversationFloaters(floater_list_t& floaters);
private:
LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 56b0c15cb9..3d77ea4f0b 100755
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -125,7 +125,7 @@ BOOL LLFloaterIMNearbyChat::postBuild()
setTitle(LLTrans::getString("NearbyChatTitle"));
// obsolete, but may be needed for backward compatibility?
- gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true);
+ gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", LLControlVariable::PERSIST_NONDFT);
if (gSavedPerAccountSettings.getBOOL("LogShowHistory"))
{
@@ -138,19 +138,28 @@ BOOL LLFloaterIMNearbyChat::postBuild()
// virtual
void LLFloaterIMNearbyChat::closeHostedFloater()
{
- // Should check how many conversations are ongoing. Close all if 1 only (the Nearby Chat), select next one otherwise
+ // If detached from conversations window close anyway
+ if (!getHost())
+ {
+ setVisible(FALSE);
+ }
+
+ // Should check how many conversations are ongoing. Select next to "Nearby Chat" in case there are some other besides.
+ // Close conversations window in case "Nearby Chat" is attached and the only conversation
LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
if (floater_container->getConversationListItemSize() == 1)
{
- floater_container->closeFloater();
+ if (getHost())
+ {
+ floater_container->closeFloater();
+ }
}
else
{
if (!getHost())
{
- setVisible(FALSE);
+ floater_container->selectNextConversationByID(LLUUID());
}
- floater_container->selectNextConversationByID(LLUUID());
}
}
@@ -262,7 +271,7 @@ void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD&
{
LLFloaterIMSessionTab::setVisibleAndFrontmost(take_focus, key);
- if(!isTornOff() && matchesKey(key))
+ if(matchesKey(key))
{
LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, take_focus);
}
@@ -296,7 +305,6 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting)
{
// Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater
LLFloaterIMSessionTab::restoreFloater();
- onClickCloseBtn();
}
// virtual
@@ -306,13 +314,7 @@ void LLFloaterIMNearbyChat::onClickCloseBtn()
{
return;
}
- LLFloaterIMSessionTab::onTearOffClicked();
-
- LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance();
- if (im_box)
- {
- im_box->onNearbyChatClosed();
- }
+ closeHostedFloater();
}
void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp)
@@ -350,11 +352,17 @@ bool LLFloaterIMNearbyChat::isChatVisible() const
void LLFloaterIMNearbyChat::showHistory()
{
openFloater();
+ LLFloaterIMContainer::getInstance()->selectConversation(LLUUID(NULL));
+
if(!isMessagePaneExpanded())
{
restoreFloater();
setFocus(true);
}
+ else
+ {
+ LLFloaterIMContainer::getInstance()->setFocus(TRUE);
+ }
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
}
@@ -568,7 +576,10 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )
if (0 == channel)
{
// discard returned "found" boolean
- LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text);
+ if(!LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text))
+ {
+ utf8_revised_text = utf8text;
+ }
}
else
{
@@ -582,7 +593,7 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )
if (!utf8_revised_text.empty())
{
// Chat with animation
- sendChatFromViewer(utf8_revised_text, type, TRUE);
+ sendChatFromViewer(utf8_revised_text, type, gSavedSettings.getBOOL("PlayChatAnim"));
}
}
@@ -636,10 +647,7 @@ void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLS
void LLFloaterIMNearbyChat::onChatBoxCommit()
{
- if (mInputEditor->getText().length() > 0)
- {
- sendChat(CHAT_TYPE_NORMAL);
- }
+ sendChat(CHAT_TYPE_NORMAL);
gAgent.stopTyping();
}
diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp
index 9ce5e12897..cc00b6fd10 100755
--- a/indra/newview/llfloaterimnearbychathandler.cpp
+++ b/indra/newview/llfloaterimnearbychathandler.cpp
@@ -606,6 +606,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
//Don't show nearby toast, if conversation is visible and selected
if ((nearby_chat->hasFocus()) ||
+ (LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized()) ||
((im_box->getSelectedSession().isNull() &&
((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost())
|| (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost())))))
diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp
index 14a22bcd84..5a5f6c72c8 100755
--- a/indra/newview/llfloaterimnearbychatlistener.cpp
+++ b/indra/newview/llfloaterimnearbychatlistener.cpp
@@ -33,7 +33,7 @@
#include "llagent.h"
#include "llchat.h"
-
+#include "llviewercontrol.h"
LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar)
@@ -95,6 +95,6 @@ void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const
}
// Send it as if it was typed in
- mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, (BOOL)(channel == 0));
+ mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, ((BOOL)(channel == 0)) && gSavedSettings.getBOOL("PlayChatAnim"));
}
diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
index 8ec85e1160..5cb9df5625 100755
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -109,18 +109,6 @@ void LLFloaterIMSession::refresh()
void LLFloaterIMSession::onTearOffClicked()
{
LLFloaterIMSessionTab::onTearOffClicked();
-
- if(mIsP2PChat)
- {
- if(isTornOff())
- {
- mSpeakingIndicator->setSpeakerId(mOtherParticipantUUID, mSessionID);
- }
- else
- {
- mSpeakingIndicator->setSpeakerId(LLUUID::null);
- }
- }
}
// virtual
@@ -442,8 +430,11 @@ void LLFloaterIMSession::addSessionParticipants(const uuid_vec_t& uuids)
}
else
{
- // remember whom we have invited, to notify others later, when the invited ones actually join
- mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ if(findInstance(mSessionID))
+ {
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ }
inviteToSession(uuids);
}
@@ -469,13 +460,18 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con
temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end());
// then we can close the current session
- onClose(false);
+ if(findInstance(mSessionID))
+ {
+ onClose(false);
+
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ }
// we start a new session so reset the initialization flag
mSessionInitialized = false;
- // remember whom we have invited, to notify others later, when the invited ones actually join
- mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+
// Start a new ad hoc voice call if we invite new participants to a P2P call,
// or start a text chat otherwise.
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index ce6e639305..0ccfdb9a7b 100755
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -55,7 +55,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
, mSessionID(session_id.asUUID())
, mConversationsRoot(NULL)
, mScroller(NULL)
- , mSpeakingIndicator(NULL)
, mChatHistory(NULL)
, mInputEditor(NULL)
, mInputEditorPad(0)
@@ -212,7 +211,7 @@ void LLFloaterIMSessionTab::assignResizeLimits()
mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);
S32 participants_pane_target_width = is_participants_pane_collapsed?
- 0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH);
+ 0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing());
S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;
@@ -241,7 +240,10 @@ BOOL LLFloaterIMSessionTab::postBuild()
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
mGearBtn = getChild<LLButton>("gear_btn");
-
+ mAddBtn = getChild<LLButton>("add_btn");
+ mVoiceButton = getChild<LLButton>("voice_call_btn");
+ mTranslationCheckBox = getChild<LLUICtrl>("translate_chat_checkbox_lp");
+
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder");
@@ -256,8 +258,6 @@ BOOL LLFloaterIMSessionTab::postBuild()
scroller_params.rect(scroller_view_rect);
mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
mScroller->setFollowsAll();
-
- mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
// Insert that scroller into the panel widgets hierarchy
mParticipantListPanel->addChild(mScroller);
@@ -270,6 +270,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
mInputPanels = getChild<LLLayoutStack>("input_panels");
mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this));
+ mInputEditor->setMouseUpCallback(boost::bind(&LLFloaterIMSessionTab::onInputEditorClicked, this));
mInputEditor->setCommitOnFocusLost( FALSE );
mInputEditor->setPassDelete(TRUE);
mInputEditor->setFont(LLViewerChat::getChatFont());
@@ -372,7 +373,7 @@ void LLFloaterIMSessionTab::draw()
void LLFloaterIMSessionTab::enableDisableCallBtn()
{
- getChildView("voice_call_btn")->setEnabled(
+ mVoiceButton->setEnabled(
mSessionID.notNull()
&& mSession
&& mSession->mSessionInitialized
@@ -399,6 +400,16 @@ void LLFloaterIMSessionTab::onFocusLost()
LLTransientDockableFloater::onFocusLost();
}
+void LLFloaterIMSessionTab::onInputEditorClicked()
+{
+ LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
+ if (im_box)
+ {
+ im_box->flashConversationItemWidget(mSessionID,false);
+ }
+ gToolBarView->flashCommand(LLCommandId("chat"), false);
+}
+
std::string LLFloaterIMSessionTab::appendTime()
{
time_t utc_time;
@@ -758,7 +769,7 @@ void LLFloaterIMSessionTab::reshapeChatLayoutPanel()
void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)
{
- getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE);
+ mTranslationCheckBox->setVisible(mIsNearbyChat && show);
}
// static
@@ -805,15 +816,10 @@ void LLFloaterIMSessionTab::reloadEmptyFloaters()
void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive)
{
- LLButton* voiceButton = getChild<LLButton>("voice_call_btn");
- voiceButton->setImageOverlay(
- callIsActive? getString("call_btn_stop") : getString("call_btn_start"));
-
- voiceButton->setToolTip(
- callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));
+ mVoiceButton->setImageOverlay(callIsActive? getString("call_btn_stop") : getString("call_btn_start"));
+ mVoiceButton->setToolTip(callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));
enableDisableCallBtn();
-
}
void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
@@ -898,6 +904,7 @@ void LLFloaterIMSessionTab::restoreFloater()
mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
setMessagePaneExpanded(true);
saveCollapsedState();
+ mInputEditor->enableSingleLineMode(false);
enableResizeCtrls(true, true, true);
}
}
@@ -953,8 +960,8 @@ void LLFloaterIMSessionTab::updateGearBtn()
if(prevVisibility != mGearBtn->getVisible())
{
LLRect gear_btn_rect = mGearBtn->getRect();
- LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect();
- LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect();
+ LLRect add_btn_rect = mAddBtn->getRect();
+ LLRect call_btn_rect = mVoiceButton->getRect();
S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;
S32 right_shift = gear_btn_rect.getWidth() + gap_width;
if(mGearBtn->getVisible())
@@ -968,24 +975,24 @@ void LLFloaterIMSessionTab::updateGearBtn()
add_btn_rect.translate(-right_shift,0);
call_btn_rect.translate(-right_shift,0);
}
- getChild<LLButton>("add_btn")->setRect(add_btn_rect);
- getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect);
+ mAddBtn->setRect(add_btn_rect);
+ mVoiceButton->setRect(call_btn_rect);
}
}
void LLFloaterIMSessionTab::initBtns()
{
LLRect gear_btn_rect = mGearBtn->getRect();
- LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect();
- LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect();
+ LLRect add_btn_rect = mAddBtn->getRect();
+ LLRect call_btn_rect = mVoiceButton->getRect();
S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;
S32 right_shift = gear_btn_rect.getWidth() + gap_width;
add_btn_rect.translate(-right_shift,0);
call_btn_rect.translate(-right_shift,0);
- getChild<LLButton>("add_btn")->setRect(add_btn_rect);
- getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect);
+ mAddBtn->setRect(add_btn_rect);
+ mVoiceButton->setRect(call_btn_rect);
}
// static
@@ -1083,21 +1090,26 @@ void LLFloaterIMSessionTab::saveCollapsedState()
}
BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
{
+ BOOL handled = FALSE;
+
if(mask == MASK_ALT)
{
LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
if (KEY_RETURN == key && !isTornOff())
{
floater_container->expandConversation();
+ handled = TRUE;
}
if ((KEY_UP == key) || (KEY_LEFT == key))
{
floater_container->selectNextorPreviousConversation(false);
+ handled = TRUE;
}
if ((KEY_DOWN == key ) || (KEY_RIGHT == key))
{
floater_container->selectNextorPreviousConversation(true);
+ handled = TRUE;
}
}
- return TRUE;
+ return handled;
}
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 302d5a8066..e7b05a584b 100755
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -171,8 +171,7 @@ protected:
LLFolderView* mConversationsRoot;
LLScrollContainer* mScroller;
- LLOutputMonitorCtrl* mSpeakingIndicator;
- LLChatHistory* mChatHistory;
+ LLChatHistory* mChatHistory;
LLChatEntry* mInputEditor;
LLLayoutPanel * mChatLayoutPanel;
LLLayoutStack * mInputPanels;
@@ -182,6 +181,9 @@ protected:
LLButton* mTearOffBtn;
LLButton* mCloseBtn;
LLButton* mGearBtn;
+ LLButton* mAddBtn;
+ LLButton* mVoiceButton;
+ LLUICtrl* mTranslationCheckBox;
private:
// Handling selection and contextual menu
@@ -201,6 +203,8 @@ private:
*/
void reshapeChatLayoutPanel();
+ void onInputEditorClicked();
+
bool checkIfTornOff();
bool mIsHostAttached;
bool mHasVisibleBeenInitialized;
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 8290494c22..ba9fbbc84e 100755
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2092,7 +2092,6 @@ void LLPanelLandOptions::refresh()
// virtual
void LLPanelLandOptions::draw()
{
- refreshSearch(); // Is this necessary? JC
LLPanel::draw();
}
@@ -2106,9 +2105,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;
}
@@ -2118,7 +2116,7 @@ void LLPanelLandOptions::refreshSearch()
bool can_change =
LLViewerParcelMgr::isParcelModifiableByAgent(
- parcel, GP_LAND_CHANGE_IDENTITY)
+ parcel, GP_LAND_FIND_PLACES)
&& region
&& !(region->getRegionFlag(REGION_FLAGS_BLOCK_PARCEL_SEARCH));
@@ -2135,10 +2133,9 @@ void LLPanelLandOptions::refreshSearch()
mCheckShowDirectory ->set(show_directory);
// Set by string in case the order in UI doesn't match the order by index.
- // *TODO:Translate
LLParcel::ECategory cat = parcel->getCategory();
- const std::string& category_string = LLParcel::getCategoryUIString(cat);
- mCategoryCombo->setSimple(category_string);
+ const std::string& category_string = LLParcel::getCategoryString(cat);
+ mCategoryCombo->setValue(category_string);
std::string tooltip;
bool enable_show_directory = false;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index bf50297022..f48d99b651 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -452,6 +452,7 @@ BOOL LLFloaterPreference::postBuild()
getChild<LLComboBox>("ConferenceIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ConferenceIMOptions"));
getChild<LLComboBox>("GroupChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"GroupChatOptions"));
getChild<LLComboBox>("NearbyChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NearbyChatOptions"));
+ getChild<LLComboBox>("ObjectIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ObjectIMOptions"));
// if floater is opened before login set default localized do not disturb message
if (LLStartUp::getStartupState() < STATE_STARTED)
@@ -724,6 +725,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
onNotificationsChange("ConferenceIMOptions");
onNotificationsChange("GroupChatOptions");
onNotificationsChange("NearbyChatOptions");
+ onNotificationsChange("ObjectIMOptions");
LLPanelLogin::setAlwaysRefresh(true);
refresh();
@@ -931,7 +933,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName)
bool show_notifications_alert = true;
for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++)
{
- if(it_notification->second != "None")
+ if(it_notification->second != "No action")
{
show_notifications_alert = false;
break;
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 50c013a49d..66bf49331b 100755
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -1734,7 +1734,7 @@ void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)
LLSD args;
args["NUM_ADDED"] = llformat("%d",ids.size());
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- args["LIST_TYPE"] = "Allowed Residents";
+ args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents");
args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
delete change_info;
@@ -1750,7 +1750,7 @@ void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)
LLSD args;
args["NUM_ADDED"] = llformat("%d",ids.size());
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- args["LIST_TYPE"] = "Banned Residents";
+ args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");
args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
delete change_info;
@@ -2815,9 +2815,10 @@ bool LLDispatchSetEstateAccess::operator()(
}
- std::string msg = llformat("Banned residents: (%d, max %d)",
- totalBannedAgents,
- ESTATE_MAX_ACCESS_IDS);
+ LLStringUtil::format_map_t args;
+ args["[BANNEDAGENTS]"] = llformat("%d", totalBannedAgents);
+ args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
+ std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);
panel->getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));
if (banned_agent_name_list)
@@ -2837,9 +2838,10 @@ bool LLDispatchSetEstateAccess::operator()(
if (access_flags & ESTATE_ACCESS_MANAGERS)
{
- std::string msg = llformat("Estate Managers: (%d, max %d)",
- num_estate_managers,
- ESTATE_MAX_MANAGERS);
+ LLStringUtil::format_map_t args;
+ args["[ESTATEMANAGERS]"] = llformat("%d", num_estate_managers);
+ args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS);
+ std::string msg = LLTrans::getString("RegionInfoEstateManagers", args);
panel->getChild<LLUICtrl>("estate_manager_label")->setValue(LLSD(msg));
LLNameListCtrl* estate_manager_name_list =
diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp
index 586965e5a0..c28657dbcd 100755
--- a/indra/newview/llfolderviewmodelinventory.cpp
+++ b/indra/newview/llfolderviewmodelinventory.cpp
@@ -74,6 +74,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
it != end_it;
++it)
{
+ // Recursive call to sort() on child (CHUI-849)
LLFolderViewFolder* child_folderp = *it;
sort(child_folderp);
@@ -129,12 +130,12 @@ void LLFolderViewModelItemInventory::requestSort()
void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size)
{
LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size);
-
- bool passed_filter_before = mPrevPassedAllFilters;
+ bool before = mPrevPassedAllFilters;
mPrevPassedAllFilters = passedFilter(filter_generation);
- if (passed_filter_before != mPrevPassedAllFilters)
+ if (before != mPrevPassedAllFilters)
{
+ // Need to rearrange the folder if the filtered state of the item changed
LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder();
if (parent_folder)
{
@@ -150,11 +151,11 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite
bool continue_filtering = true;
if (item->getLastFilterGeneration() < filter_generation)
{
- // recursive application of the filter for child items
+ // Recursive application of the filter for child items (CHUI-849)
continue_filtering = item->filter( filter );
}
- // track latest generation to pass any child items, for each folder up to root
+ // Update latest generation to pass filter in parent and propagate up to root
if (item->passedFilter())
{
LLFolderViewModelItemInventory* view_model = this;
@@ -174,53 +175,61 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter)
const S32 filter_generation = filter.getCurrentGeneration();
const S32 must_pass_generation = filter.getFirstRequiredGeneration();
- if (getLastFilterGeneration() >= must_pass_generation
+ if (getLastFilterGeneration() >= must_pass_generation
&& getLastFolderFilterGeneration() >= must_pass_generation
&& !passedFilter(must_pass_generation))
{
// failed to pass an earlier filter that was a subset of the current one
- // go ahead and flag this item as done
+ // go ahead and flag this item as not pass
setPassedFilter(false, filter_generation);
setPassedFolderFilter(false, filter_generation);
return true;
}
- const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)
- ? filter.checkFolder(this)
- : true;
+ // *TODO : Revise the logic for fast pass on less restrictive filter case
+ /*
+ const S32 sufficient_pass_generation = filter.getFirstSuccessGeneration();
+ if (getLastFilterGeneration() >= sufficient_pass_generation
+ && getLastFolderFilterGeneration() >= sufficient_pass_generation
+ && passedFilter(sufficient_pass_generation))
+ {
+ // passed an earlier filter that was a superset of the current one
+ // go ahead and flag this item as pass
+ setPassedFilter(true, filter_generation);
+ setPassedFolderFilter(true, filter_generation);
+ return true;
+ }
+ */
+
+ const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) ? filter.checkFolder(this) : true;
setPassedFolderFilter(passed_filter_folder, filter_generation);
- if(!mChildren.empty()
+ bool continue_filtering = true;
+
+ if (!mChildren.empty()
&& (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass
- || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement
+ || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement
{
// now query children
- for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end();
- iter != end_iter && filter.getFilterCount() > 0;
- ++iter)
+ for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); iter != end_iter; ++iter)
{
- if (!filterChildItem((*iter), filter))
+ continue_filtering = filterChildItem((*iter), filter);
+ if (!continue_filtering)
{
break;
}
}
}
- // if we didn't use all filter iterations
- // that means we filtered all of our descendants
- // so filter ourselves now
- if (filter.getFilterCount() > 0)
+ // If we didn't use all the filter time that means we filtered all of our descendants so we can filter ourselves now
+ if (continue_filtering)
{
- filter.decrementFilterCount();
-
+ // This is where filter check on the item done (CHUI-849)
const bool passed_filter = filter.check(this);
setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize());
- return true;
- }
- else
- {
- return false;
+ continue_filtering = !filter.isTimedOut();
}
+ return continue_filtering;
}
LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel()
@@ -307,8 +316,8 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a,
}
}
-LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model )
- : LLFolderViewModelItemCommon(root_view_model),
- mPrevPassedAllFilters(false)
+LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model ) :
+ LLFolderViewModelItemCommon(root_view_model),
+ mPrevPassedAllFilters(false)
{
}
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index 890d03d1c9..9dcfdfa185 100755
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -59,9 +59,8 @@ public:
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;
virtual LLToolDragAndDrop::ESource getDragSource() const = 0;
-
protected:
- bool mPrevPassedAllFilters;
+ bool mPrevPassedAllFilters;
};
class LLInventorySort
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index a0f2918bd7..302d21c2e4 100755
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -116,6 +116,80 @@ public:
};
LLGroupHandler gGroupHandler;
+// This object represents a pending request for specified group member information
+// which is needed to check whether avatar can leave group
+class LLFetchGroupMemberData : public LLGroupMgrObserver
+{
+public:
+ LLFetchGroupMemberData(const LLUUID& group_id) :
+ mGroupId(group_id),
+ mRequestProcessed(false),
+ LLGroupMgrObserver(group_id)
+ {
+ llinfos << "Sending new group member request for group_id: "<< group_id << llendl;
+ LLGroupMgr* mgr = LLGroupMgr::getInstance();
+ // register ourselves as an observer
+ mgr->addObserver(this);
+ // send a request
+ mgr->sendGroupPropertiesRequest(group_id);
+ mgr->sendCapGroupMembersRequest(group_id);
+ }
+
+ ~LLFetchGroupMemberData()
+ {
+ if (!mRequestProcessed)
+ {
+ // Request is pending
+ llwarns << "Destroying pending group member request for group_id: "
+ << mGroupId << llendl;
+ }
+ // Remove ourselves as an observer
+ LLGroupMgr::getInstance()->removeObserver(this);
+ }
+
+ void changed(LLGroupChange gc)
+ {
+ if (gc == GC_MEMBER_DATA && !mRequestProcessed)
+ {
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId);
+ if (!gdatap)
+ {
+ llwarns << "LLGroupMgr::getInstance()->getGroupData() was NULL" << llendl;
+ }
+ else if (!gdatap->isMemberDataComplete())
+ {
+ llwarns << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << llendl;
+ }
+ else
+ {
+ processGroupData();
+ mRequestProcessed = true;
+ }
+ }
+ }
+
+ LLUUID getGroupId() { return mGroupId; }
+ virtual void processGroupData() = 0;
+protected:
+ LLUUID mGroupId;
+private:
+ bool mRequestProcessed;
+};
+
+class LLFetchLeaveGroupData: public LLFetchGroupMemberData
+{
+public:
+ LLFetchLeaveGroupData(const LLUUID& group_id)
+ : LLFetchGroupMemberData(group_id)
+ {}
+ void processGroupData()
+ {
+ LLGroupActions::processLeaveGroupDataResponse(mGroupId);
+ }
+};
+
+LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL;
+
// static
void LLGroupActions::search()
{
@@ -208,23 +282,52 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response)
void LLGroupActions::leave(const LLUUID& group_id)
{
if (group_id.isNull())
+ {
return;
+ }
- S32 count = gAgent.mGroups.count();
- S32 i;
- for (i = 0; i < count; ++i)
+ LLGroupData group_data;
+ if (gAgent.getGroupData(group_id, group_data))
{
- if(gAgent.mGroups.get(i).mID == group_id)
- break;
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+ if (!gdatap || !gdatap->isMemberDataComplete())
+ {
+ if (gFetchLeaveGroupData != NULL)
+ {
+ delete gFetchLeaveGroupData;
+ gFetchLeaveGroupData = NULL;
+ }
+ gFetchLeaveGroupData = new LLFetchLeaveGroupData(group_id);
+ }
+ else
+ {
+ processLeaveGroupDataResponse(group_id);
+ }
}
- if (i < count)
+}
+
+//static
+void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id)
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+ LLUUID agent_id = gAgent.getID();
+ LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.find(agent_id);
+ //get the member data for the group
+ if ( mit != gdatap->mMembers.end() )
{
- LLSD args;
- args["GROUP"] = gAgent.mGroups.get(i).mName;
- LLSD payload;
- payload["group_id"] = group_id;
- LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
+ LLGroupMemberData* member_data = (*mit).second;
+
+ if ( member_data && member_data->isOwner() && gdatap->mMemberCount == 1)
+ {
+ LLNotificationsUtil::add("OwnerCannotLeaveGroup");
+ return;
+ }
}
+ LLSD args;
+ args["GROUP"] = gdatap->mName;
+ LLSD payload;
+ payload["group_id"] = group_id;
+ LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
}
// static
diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h
index 3f9852f194..afc4686dd7 100755
--- a/indra/newview/llgroupactions.h
+++ b/indra/newview/llgroupactions.h
@@ -114,6 +114,14 @@ public:
private:
static bool onJoinGroup(const LLSD& notification, const LLSD& response);
static bool onLeaveGroup(const LLSD& notification, const LLSD& response);
+
+ /**
+ * This function is called by LLFetchLeaveGroupData upon receiving a response to a group
+ * members data request.
+ */
+ static void processLeaveGroupDataResponse(const LLUUID group_id);
+
+ friend class LLFetchLeaveGroupData;
};
#endif // LL_LLGROUPACTIONS_H
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 3b72ad3cd9..9e23755d73 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -103,6 +103,7 @@ BOOL LLSessionTimeoutTimer::tick()
}
+void notify_of_message(const LLSD& msg, bool is_dnd_msg);
void process_dnd_im(const LLSD& notification)
{
@@ -129,15 +130,9 @@ 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)
+ }
- LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
-
- if (im_box)
- {
- im_box->flashConversationItemWidget(sessionID, true);
- }
-
- }
+ notify_of_message(data, true);
}
@@ -158,75 +153,106 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
}
-void on_new_message(const LLSD& msg)
+void notify_of_message(const LLSD& msg, bool is_dnd_msg)
{
- std::string user_preferences;
- LLUUID participant_id = msg["from_id"].asUUID();
- LLUUID session_id = msg["session_id"].asUUID();
- LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
-
- // do not show notification which goes from agent
- if (gAgent.getID() == participant_id)
- {
- return;
- }
+ 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);
- // determine state of conversations floater
- enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
+ // 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;
- 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();
if (!LLFloater::isVisible(im_box) || im_box->isMinimized())
{
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())
- {
- user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
- }
- else if(session->isP2PSessionType())
- {
- if (LLAvatarTracker::instance().isBuddy(participant_id))
- {
- user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
- }
- else
- {
- user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
- }
- }
- else if(session->isAdHocSessionType())
- {
- user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
- }
- else if(session->isGroupSessionType())
- {
- user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
- }
+ // determine user prefs for this session
+ if (session_id.isNull())
+ {
+ if (msg["source_type"].asInteger() == CHAT_SOURCE_OBJECT)
+ {
+ user_preferences = gSavedSettings.getString("NotificationObjectIMOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundObjectIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ else
+ {
+ 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");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ 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");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ 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 (("none" == user_preferences ||
+ if (("noaction" == user_preferences ||
ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status)
&& session_floater->isMessagePaneExpanded())
{
@@ -261,57 +287,103 @@ void on_new_message(const LLSD& msg)
}
}
}
- else
- {
- //If in DND mode, allow notification to be stored so upon DND exit
- //useMostItrusiveIMNotification will be called to notify user a message exists
- if(session_id.notNull()
- && participant_id.notNull()
- && !session_floater->isShown())
- {
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
- }
- }
+ 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)
- || ("flash" == user_preferences && CLOSED == conversations_floater_status))
- {
- if(!LLMuteList::getInstance()->isMuted(participant_id))
- {
- im_box->flashConversationItemWidget(session_id, true);
- }
- }
+ }
- // 3. Flash FUI button
- if (("toast" == user_preferences || "flash" == user_preferences) &&
- (CLOSED == conversations_floater_status
- || NOT_ON_TOP == conversations_floater_status))
- {
- if(!LLMuteList::getInstance()->isMuted(participant_id)
- && !gAgent.isDoNotDisturb())
- {
- gToolBarView->flashCommand(LLCommandId("chat"), true);
- }
- }
+ // 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(gAgent.isDoNotDisturb())
+ {
+ store_dnd_message = true;
+ }
+ else
+ {
+ if (is_dnd_msg && (ON_TOP == conversations_floater_status ||
+ NOT_ON_TOP == conversations_floater_status ||
+ CLOSED == conversations_floater_status))
+ {
+ im_box->highlightConversationItemWidget(session_id, true);
+ }
+ else
+ {
+ im_box->flashConversationItemWidget(session_id, true);
+ }
+ }
+ }
+ }
- // 4. Toast
- if ((("toast" == user_preferences) &&
- (CLOSED == conversations_floater_status
- || NOT_ON_TOP == conversations_floater_status))
- || !session_floater->isMessagePaneExpanded())
+ // 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;
+ }
+ }
+ }
- {
- //Show IM toasts (upper right toasts)
- // Skip toasting for system messages and for nearby chat
- if(session_id.notNull() && participant_id.notNull())
- {
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
- }
+ // 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())
+
+ {
+ //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())
+ {
+ store_dnd_message = true;
+ }
+ else
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
+ }
+ }
+ }
+ if (store_dnd_message)
+ {
+ // If in DND mode, allow notification to be stored so upon DND exit
+ // the user will be notified with some limitations (see 'is_dnd_msg' flag checks)
+ if(session_id.notNull()
+ && participant_id.notNull()
+ && !session_floater->isShown())
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
+ }
+}
+
+void on_new_message(const LLSD& msg)
+{
+ notify_of_message(msg, false);
}
LLIMModel::LLIMModel()
@@ -2597,6 +2669,13 @@ void LLIMMgr::addMessage(
fixed_session_name = session_name;
name_is_setted = true;
}
+ bool skip_message = false;
+ if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
+ {
+ // Evaluate if we need to skip this message when that setting is true (default is false)
+ skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends...
+ skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself
+ }
bool new_session = !hasSession(new_session_id);
if (new_session)
@@ -2608,6 +2687,12 @@ void LLIMMgr::addMessage(
}
LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg);
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id);
+ skip_message &= !session->isGroupSessionType(); // Do not skip group chats...
+ if(skip_message)
+ {
+ gIMMgr->leaveSession(new_session_id);
+ }
// When we get a new IM, and if you are a god, display a bit
// of information about the source. This is to help liaisons
// when answering questions.
@@ -2648,23 +2733,13 @@ void LLIMMgr::addMessage(
}
}
- bool skip_message = false;
- if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
- {
- // Evaluate if we need to skip this message when that setting is true (default is false)
- LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id);
- skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends...
- skip_message &= !session->isGroupSessionType(); // Do not skip group chats...
- skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself
- }
-
if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message)
{
LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
}
// Open conversation floater if offline messages are present
- if (is_offline_msg)
+ if (is_offline_msg && !skip_message)
{
LLFloaterReg::showInstance("im_container");
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->
@@ -2971,10 +3046,9 @@ void LLIMMgr::inviteToSession(
{
bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup"));
bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL));
- bool isRejectDoNotDisturb = (gAgent.isDoNotDisturb() && !hasSession(session_id));
- if (isRejectGroupCall || isRejectNonFriendCall || isRejectDoNotDisturb)
+ if (isRejectGroupCall || isRejectNonFriendCall || gAgent.isDoNotDisturb())
{
- if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall)
+ if (gAgent.isDoNotDisturb() && !isRejectGroupCall && !isRejectNonFriendCall)
{
LLSD args;
addSystemMessage(session_id, "you_auto_rejected_call", args);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index e4fc469bb7..80ef506272 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4739,6 +4739,16 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act
LLAvatarActions::offerTeleport(item->getCreatorUUID());
}
}
+ else if ("request_lure" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ LLAvatarActions::teleportRequest(item->getCreatorUUID());
+ }
+ }
+
else LLItemBridge::performAction(model, action);
}
@@ -4825,6 +4835,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Send Instant Message Separator"));
items.push_back(std::string("Send Instant Message"));
items.push_back(std::string("Offer Teleport..."));
+ items.push_back(std::string("Request Teleport..."));
items.push_back(std::string("Conference Chat"));
if (!good_card)
@@ -4834,6 +4845,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
if (!good_card || !user_online)
{
disabled_items.push_back(std::string("Offer Teleport..."));
+ disabled_items.push_back(std::string("Request Teleport..."));
disabled_items.push_back(std::string("Conference Chat"));
}
}
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 92f2d33073..3c6974cf6d 100755
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -70,11 +70,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)
mFilterSubString(p.substring),
mCurrentGeneration(0),
mFirstRequiredGeneration(0),
- mFirstSuccessGeneration(0),
- mFilterCount(0)
+ mFirstSuccessGeneration(0)
{
- mNextFilterGeneration = mCurrentGeneration + 1;
-
// copy mFilterOps into mDefaultFilterOps
markDefault();
}
@@ -92,9 +89,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
return passed_clipboard;
}
- std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos;
-
- BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos);
+ bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true);
passed = passed && checkAgainstFilterType(listener);
passed = passed && checkAgainstPermissions(listener);
passed = passed && checkAgainstFilterLinks(listener);
@@ -105,17 +100,12 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
bool LLInventoryFilter::check(const LLInventoryItem* item)
{
- std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos;
-
+ const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true);
const bool passed_filtertype = checkAgainstFilterType(item);
const bool passed_permissions = checkAgainstPermissions(item);
- const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID());
- const bool passed = (passed_filtertype
- && passed_permissions
- && passed_clipboard
- && (mFilterSubString.size() == 0 || string_offset != std::string::npos));
+ const bool passed_clipboard = checkAgainstClipboard(item->getUUID());
- return passed;
+ return passed_filtertype && passed_permissions && passed_clipboard && passed_string;
}
bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const
@@ -439,7 +429,7 @@ void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
current_types = types;
if (more_bits_set && fewer_bits_set)
{
- // neither less or more restrive, both simultaneously
+ // neither less or more restrictive, both simultaneously
// so we need to filter from scratch
setModified(FILTER_RESTART);
}
@@ -714,7 +704,7 @@ void LLInventoryFilter::resetDefault()
void LLInventoryFilter::setModified(EFilterModified behavior)
{
mFilterText.clear();
- mCurrentGeneration = mNextFilterGeneration++;
+ mCurrentGeneration++;
if (mFilterModified == FILTER_NONE)
{
@@ -1021,21 +1011,19 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
return mFilterOps.mShowFolderState;
}
-void LLInventoryFilter::setFilterCount(S32 count)
-{
- mFilterCount = count;
-}
-S32 LLInventoryFilter::getFilterCount() const
+bool LLInventoryFilter::isTimedOut()
{
- return mFilterCount;
+ return mFilterTime.hasExpired();
}
-void LLInventoryFilter::decrementFilterCount()
-{
- mFilterCount--;
+void LLInventoryFilter::resetTime(S32 timeout)
+{
+ mFilterTime.reset();
+ F32 time_in_sec = (F32)(timeout)/1000.0;
+ mFilterTime.setTimerExpirySec(time_in_sec);
}
-S32 LLInventoryFilter::getCurrentGeneration() const
+S32 LLInventoryFilter::getCurrentGeneration() const
{
return mCurrentGeneration;
}
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 4912b5ca91..ce516af0b9 100755
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -215,12 +215,11 @@ public:
void setModified(EFilterModified behavior = FILTER_RESTART);
// +-------------------------------------------------------------------+
- // + Count
+ // + Time
// +-------------------------------------------------------------------+
- void setFilterCount(S32 count);
- S32 getFilterCount() const;
- void decrementFilterCount();
-
+ void resetTime(S32 timeout);
+ bool isTimedOut();
+
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
@@ -262,13 +261,15 @@ private:
const std::string mName;
S32 mCurrentGeneration;
+ // The following makes checking for pass/no pass possible even if the item is not checked against the current generation
+ // Any item that *did not pass* the "required generation" will *not pass* the current one
+ // Any item that *passes* the "success generation" will *pass* the current one
S32 mFirstRequiredGeneration;
S32 mFirstSuccessGeneration;
- S32 mNextFilterGeneration;
- S32 mFilterCount;
EFilterModified mFilterModified;
-
+ LLTimer mFilterTime;
+
std::string mFilterText;
std::string mEmptyLookupMessage;
};
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index cf1fd4c0d0..e5b9e11d48 100755
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -192,7 +192,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
p.show_item_link_overlays = mShowItemLinkOverlays;
p.root = NULL;
p.options_menu = "menu_inventory.xml";
-
+
return LLUICtrlFactory::create<LLFolderView>(p);
}
@@ -396,6 +396,7 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
return getFilter().getShowFolderState();
}
+// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849)
void LLInventoryPanel::modelChanged(U32 mask)
{
static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 2d7454b636..90b169ecd3 100755
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -25,7 +25,7 @@
*/
#include "llviewerprecompiledheaders.h"
-
+#include "llfloaterconversationpreview.h"
#include "llagent.h"
#include "llagentui.h"
#include "llavatarnamecache.h"
@@ -206,6 +206,7 @@ private:
};
LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL;
+LLLoadHistoryThread::load_end_signal_t * LLLoadHistoryThread::mLoadEndSignal = NULL;
//static
std::string LLLogChat::makeLogFileName(std::string filename)
@@ -336,75 +337,83 @@ void LLLogChat::saveHistory(const std::string& filename,
void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
{
if (file_name.empty())
- {
- llwarns << "Session name is Empty!" << llendl;
- return ;
- }
-
- bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
+ {
+ LL_WARNS("LLLogChat::loadChatHistory") << "Session name is Empty!" << LL_ENDL;
+ return ;
+ }
- LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
- if (!fptr)
- {
- fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
- if (!fptr)
- {
- return; //No previous conversation with this name.
- }
- }
-
- char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
- char *bptr;
- S32 len;
- bool firstline = TRUE;
+ bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
- if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END))
- { //We need to load the whole historyFile or it's smaller than recall size, so get it all.
- firstline = FALSE;
- if (fseek(fptr, 0, SEEK_SET))
- {
- fclose(fptr);
- return;
- }
- }
+ LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ return; //No previous conversation with this name.
+ }
+ }
- while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr))
- {
- len = strlen(buffer) - 1; /*Flawfinder: ignore*/
- for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0';
-
- if (firstline)
- {
- firstline = FALSE;
- continue;
- }
+ char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
+ char *bptr;
+ S32 len;
+ bool firstline = TRUE;
+
+ if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END))
+ { //We need to load the whole historyFile or it's smaller than recall size, so get it all.
+ firstline = FALSE;
+ if (fseek(fptr, 0, SEEK_SET))
+ {
+ fclose(fptr);
+ return;
+ }
+ }
+ while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr))
+ {
+ len = strlen(buffer) - 1; /*Flawfinder: ignore*/
+ for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0';
+
+ if (firstline)
+ {
+ firstline = FALSE;
+ continue;
+ }
+
+ std::string line(buffer);
+
+ //updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message
+ if (' ' == line[0])
+ {
+ line.erase(0, MULTI_LINE_PREFIX.length());
+ append_to_last_message(messages, '\n' + line);
+ }
+ else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
+ {
+ //to support old format's multilined messages with new lines used to divide paragraphs
+ append_to_last_message(messages, line);
+ }
+ else
+ {
+ LLSD item;
+ if (!LLChatLogParser::parse(line, item, load_params))
+ {
+ item[LL_IM_TEXT] = line;
+ }
+ messages.push_back(item);
+ }
+ }
+ fclose(fptr);
- std::string line(buffer);
- //updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message
- if (' ' == line[0])
- {
- line.erase(0, MULTI_LINE_PREFIX.length());
- append_to_last_message(messages, '\n' + line);
- }
- else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
- {
- //to support old format's multilined messages with new lines used to divide paragraphs
- append_to_last_message(messages, line);
- }
- else
- {
- LLSD item;
- if (!LLChatLogParser::parse(line, item, load_params))
- {
- item[LL_IM_TEXT] = line;
- }
- messages.push_back(item);
- }
- }
- fclose(fptr);
}
+void LLLogChat::startChatHistoryThread(const std::string& file_name, const LLSD& load_params)
+{
+
+ LLLoadHistoryThread* mThread = new LLLoadHistoryThread();
+ mThread->start();
+ mThread->setHistoryParams(file_name, load_params);
+}
// static
std::string LLLogChat::oldLogFileName(std::string filename)
{
@@ -461,6 +470,13 @@ void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string
LLFILE * filep = LLFile::fopen(fullname, "rb");
if (NULL != filep)
{
+ if(makeLogFileName("chat")== fullname)
+ {
+ //Add Nearby chat history to the list of transcriptions
+ list_of_transcriptions.push_back(gDirUtilp->add(dirname, filename));
+ LLFile::close(filep);
+ return;
+ }
char buffer[LOG_RECALL_SIZE];
fseek(filep, 0, SEEK_END); // seek to end of file
@@ -631,7 +647,7 @@ void LLLogChat::deleteTranscripts()
}
// static
-bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)
+bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group)
{
std::vector<std::string> list_of_transcriptions;
LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
@@ -641,20 +657,53 @@ bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)
LLAvatarName avatar_name;
LLAvatarNameCache::get(avatar_id, &avatar_name);
std::string avatar_user_name = avatar_name.getAccountName();
- std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_');
-
- BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ if(!is_group)
{
- if (std::string::npos != transcript_file_name.find(avatar_user_name))
+ std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_');
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
{
- return true;
+ if (std::string::npos != transcript_file_name.find(avatar_user_name))
+ {
+ return true;
+ }
}
}
+ else
+ {
+ std::string file_name;
+ gCacheName->getGroupName(avatar_id, file_name);
+ file_name = makeLogFileName(file_name);
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ {
+ if (transcript_file_name == file_name)
+ {
+ return true;
+ }
+ }
+ }
+
}
return false;
}
+bool LLLogChat::isNearbyTranscriptExist()
+{
+ std::vector<std::string> list_of_transcriptions;
+ LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
+
+ std::string file_name;
+ file_name = makeLogFileName("chat");
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ {
+ if (transcript_file_name == file_name)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
//which are more strict by its nature (only firstname and secondname)
//Example, an object's name can be written like "Object <actual_object's_name>"
@@ -795,3 +844,116 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
im[LL_IM_TEXT] = name_and_text[IDX_TEXT];
return true; //parsed name and message text, maybe have a timestamp too
}
+
+
+
+ LLLoadHistoryThread::LLLoadHistoryThread() : LLThread("load chat history")
+ {
+ mNewLoad = false;
+ }
+
+ void LLLoadHistoryThread::run()
+ {
+ while (!LLApp::isQuitting())
+ {
+ if(mNewLoad)
+ {
+ loadHistory(mFileName,mMessages,mLoadParams);
+ shutdown();
+ }
+ }
+ }
+ void LLLoadHistoryThread::setHistoryParams(const std::string& file_name, const LLSD& load_params)
+ {
+ mFileName = file_name;
+ mLoadParams = load_params;
+ mNewLoad = true;
+ }
+ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
+ {
+
+ if (file_name.empty())
+ {
+ LL_WARNS("LLLogChat::loadHistory") << "Session name is Empty!" << LL_ENDL;
+ return ;
+ }
+
+ bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
+
+ LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ mNewLoad = false;
+ (*mLoadEndSignal)(messages, file_name);
+ return; //No previous conversation with this name.
+ }
+ }
+
+ char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
+ char *bptr;
+ S32 len;
+ bool firstline = TRUE;
+
+ if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END))
+ { //We need to load the whole historyFile or it's smaller than recall size, so get it all.
+ firstline = FALSE;
+ if (fseek(fptr, 0, SEEK_SET))
+ {
+ fclose(fptr);
+ mNewLoad = false;
+ (*mLoadEndSignal)(messages, file_name);
+ return;
+ }
+ }
+ while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr))
+ {
+ len = strlen(buffer) - 1; /*Flawfinder: ignore*/
+ for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0';
+
+ if (firstline)
+ {
+ firstline = FALSE;
+ continue;
+ }
+
+ std::string line(buffer);
+
+ //updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message
+ if (' ' == line[0])
+ {
+ line.erase(0, MULTI_LINE_PREFIX.length());
+ append_to_last_message(messages, '\n' + line);
+ }
+ else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
+ {
+ //to support old format's multilined messages with new lines used to divide paragraphs
+ append_to_last_message(messages, line);
+ }
+ else
+ {
+ LLSD item;
+ if (!LLChatLogParser::parse(line, item, load_params))
+ {
+ item[LL_IM_TEXT] = line;
+ }
+ messages.push_back(item);
+ }
+ }
+ fclose(fptr);
+ mNewLoad = false;
+ (*mLoadEndSignal)(messages, file_name);
+ }
+
+ //static
+ boost::signals2::connection LLLoadHistoryThread::setLoadEndSignal(const load_end_signal_t::slot_type& cb)
+ {
+ if (NULL == mLoadEndSignal)
+ {
+ mLoadEndSignal = new load_end_signal_t();
+ }
+
+ return mLoadEndSignal->connect(cb);
+ }
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index e819f00dd9..acee99afa2 100755
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -28,6 +28,24 @@
#define LL_LLLOGCHAT_H
class LLChat;
+class LLLoadHistoryThread : public LLThread
+{
+private:
+ std::string mFileName;
+ std::list<LLSD> mMessages;
+ LLSD mLoadParams;
+ bool mNewLoad;
+public:
+ LLLoadHistoryThread();
+
+ void setHistoryParams(const std::string& file_name, const LLSD& load_params);
+ virtual void loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params);
+ virtual void run();
+
+ typedef boost::signals2::signal<void (std::list<LLSD>& messages,const std::string& file_name)> load_end_signal_t;
+ static load_end_signal_t * mLoadEndSignal;
+ static boost::signals2::connection setLoadEndSignal(const load_end_signal_t::slot_type& cb);
+};
class LLLogChat
{
@@ -39,6 +57,7 @@ public:
LOG_LLSD,
LOG_END
};
+
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
/**
@@ -54,6 +73,7 @@ public:
static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());
+ static void startChatHistoryThread(const std::string& file_name, const LLSD& load_params);
typedef boost::signals2::signal<void ()> save_history_signal_t;
static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb);
@@ -67,7 +87,8 @@ public:
std::vector<std::string>& listOfFilesToMove);
static void deleteTranscripts();
- static bool isTranscriptExist(const LLUUID& avatar_id);
+ static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false);
+ static bool isNearbyTranscriptExist();
private:
static std::string cleanFileName(std::string filename);
@@ -126,6 +147,7 @@ protected:
virtual ~LLChatLogParser() {};
};
+
// LLSD map lookup constants
extern const std::string LL_IM_TIME; //("time");
extern const std::string LL_IM_TEXT; //("message");
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index d79f1040bb..4cbdfde868 100755
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -1376,74 +1376,28 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
projected_mouse -= snap_plane_center;
- S32 snap_plane = 0;
-
- F32 dot = cam_to_snap_plane * constraint_axis;
- if (llabs(dot) < 0.01f)
- {
- // looking at ring edge on, project onto view plane and check if mouse is past ring
- getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
- projected_mouse -= snap_plane_center;
- dot = projected_mouse * constraint_axis;
- if (projected_mouse * constraint_axis > 0)
- {
- snap_plane = 1;
- }
- projected_mouse -= dot * constraint_axis;
- }
- else if (dot > 0.f)
- {
- // look for mouse position outside and in front of snap circle
- if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
- {
- snap_plane = 1;
- }
- }
- else
- {
- // look for mouse position inside or in back of snap circle
- if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
- {
- snap_plane = 1;
- }
- }
-
- if (snap_plane == 0)
- {
- // try other plane
- snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f));
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
- }
- else
- {
- cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent();
- cam_to_snap_plane.normVec();
- }
-
- hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
- projected_mouse -= snap_plane_center;
-
- dot = cam_to_snap_plane * constraint_axis;
+ if (gSavedSettings.getBOOL("SnapEnabled")) {
+ S32 snap_plane = 0;
+
+ F32 dot = cam_to_snap_plane * constraint_axis;
if (llabs(dot) < 0.01f)
{
// looking at ring edge on, project onto view plane and check if mouse is past ring
getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
projected_mouse -= snap_plane_center;
dot = projected_mouse * constraint_axis;
- if (projected_mouse * constraint_axis < 0)
+ if (projected_mouse * constraint_axis > 0)
{
- snap_plane = 2;
+ snap_plane = 1;
}
projected_mouse -= dot * constraint_axis;
}
- else if (dot < 0.f)
+ else if (dot > 0.f)
{
// look for mouse position outside and in front of snap circle
if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
{
- snap_plane = 2;
+ snap_plane = 1;
}
}
else
@@ -1451,78 +1405,136 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
// look for mouse position inside or in back of snap circle
if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
{
- snap_plane = 2;
+ snap_plane = 1;
}
}
- }
-
- if (snap_plane > 0)
- {
- LLVector3 cam_at_axis;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- cam_at_axis.setVec(1.f, 0.f, 0.f);
- }
- else
- {
- cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent();
- cam_at_axis.normVec();
- }
-
- // first, project mouse onto screen plane at point tangent to rotation radius.
- getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis);
- // project that point onto rotation plane
- projected_mouse -= snap_plane_center;
- projected_mouse -= projected_vec(projected_mouse, constraint_axis);
-
- F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec());
- F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
- if (llabs(mouse_lateral_dist) > 0.01f)
- {
- mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -
- (mouse_lateral_dist * mouse_lateral_dist));
- }
- LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis);
- projected_mouse -= mouse_depth * projected_camera_at;
-
- if (!mInSnapRegime)
+
+ if (snap_plane == 0)
{
- mSmoothRotate = TRUE;
+ // try other plane
+ snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f));
+ if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
+ {
+ cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
+ }
+ else
+ {
+ cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent();
+ cam_to_snap_plane.normVec();
+ }
+
+ hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
+ projected_mouse -= snap_plane_center;
+
+ dot = cam_to_snap_plane * constraint_axis;
+ if (llabs(dot) < 0.01f)
+ {
+ // looking at ring edge on, project onto view plane and check if mouse is past ring
+ getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
+ projected_mouse -= snap_plane_center;
+ dot = projected_mouse * constraint_axis;
+ if (projected_mouse * constraint_axis < 0)
+ {
+ snap_plane = 2;
+ }
+ projected_mouse -= dot * constraint_axis;
+ }
+ else if (dot < 0.f)
+ {
+ // look for mouse position outside and in front of snap circle
+ if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
+ {
+ snap_plane = 2;
+ }
+ }
+ else
+ {
+ // look for mouse position inside or in back of snap circle
+ if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
+ {
+ snap_plane = 2;
+ }
+ }
}
- mInSnapRegime = TRUE;
- // 0 to 360 deg
- F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f);
- F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT);
- //fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f);
-
- LLVector3 object_axis;
- getObjectAxisClosestToMouse(object_axis);
- object_axis = object_axis * first_object_node->mSavedRotation;
-
- // project onto constraint plane
- object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
- object_axis.normVec();
-
- if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
+ if (snap_plane > 0)
{
- F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f));
- angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
+ LLVector3 cam_at_axis;
+ if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
+ {
+ cam_at_axis.setVec(1.f, 0.f, 0.f);
+ }
+ else
+ {
+ cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent();
+ cam_at_axis.normVec();
+ }
+
+ // first, project mouse onto screen plane at point tangent to rotation radius.
+ getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis);
+ // project that point onto rotation plane
+ projected_mouse -= snap_plane_center;
+ projected_mouse -= projected_vec(projected_mouse, constraint_axis);
+
+ F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec());
+ F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
+ if (llabs(mouse_lateral_dist) > 0.01f)
+ {
+ mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -
+ (mouse_lateral_dist * mouse_lateral_dist));
+ }
+ LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis);
+ projected_mouse -= mouse_depth * projected_camera_at;
+
+ if (!mInSnapRegime)
+ {
+ mSmoothRotate = TRUE;
+ }
+ mInSnapRegime = TRUE;
+ // 0 to 360 deg
+ F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f);
+
+ F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT);
+ //fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f);
+
+ LLVector3 object_axis;
+ getObjectAxisClosestToMouse(object_axis);
+ object_axis = object_axis * first_object_node->mSavedRotation;
+
+ // project onto constraint plane
+ object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
+ object_axis.normVec();
+
+ if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
+ {
+ F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f));
+ angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
+ }
+ else
+ {
+ angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
+ }
+ return LLQuaternion( -angle, constraint_axis );
}
else
{
- angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
+ if (mInSnapRegime)
+ {
+ mSmoothRotate = TRUE;
+ }
+ mInSnapRegime = FALSE;
}
- return LLQuaternion( -angle, constraint_axis );
}
- else
- {
+ else {
if (mInSnapRegime)
{
mSmoothRotate = TRUE;
}
mInSnapRegime = FALSE;
-
+ }
+
+ if (!mInSnapRegime)
+ {
LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis;
up_from_axis.normVec();
LLVector3 cur_intersection;
diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
index 2b92b0b3d1..a567d1217a 100755
--- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
+++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
@@ -92,7 +92,7 @@ void LLMenuOptionPathfindingRebakeNavmesh::initialize()
void LLMenuOptionPathfindingRebakeNavmesh::quit()
{
- if (mIsInitialized)
+ if (mIsInitialized) // Quitting from the login screen leaves this uninitialized
{
if (mNavMeshSlot.connected())
{
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 8602271f84..8eaf691d6f 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -413,7 +413,7 @@ public:
void startRequest() { ++mPendingUploads; }
void stopRequest() { --mPendingUploads; }
-
+
bool finished() { return mFinished; }
virtual void run();
void preStart();
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 7f396b7b7e..7ddd04fed0 100755
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -416,9 +416,9 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
}
-void LLNameListCtrl::updateColumns()
+void LLNameListCtrl::updateColumns(bool force_update)
{
- LLScrollListCtrl::updateColumns();
+ LLScrollListCtrl::updateColumns(force_update);
if (!mNameColumn.empty())
{
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index 271802d48a..5aa1e1c458 100755
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -149,7 +149,7 @@ public:
void sortByName(BOOL ascending);
- /*virtual*/ void updateColumns();
+ /*virtual*/ void updateColumns(bool force_update);
/*virtual*/ void mouseOverHighlightNthItem( S32 index );
private:
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index dea90b9042..08b5eaedbb 100755
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -343,8 +343,11 @@ void LLNetMap::draw()
// Draw avatars
for (U32 i = 0; i < avatar_ids.size(); i++)
{
- pos_map = globalPosToView(positions[i]);
LLUUID uuid = avatar_ids[i];
+ // Skip self, we'll draw it later
+ if (uuid == gAgent.getID()) continue;
+
+ pos_map = globalPosToView(positions[i]);
bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL);
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
index 08c98e4f28..56ed1044e9 100755
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -87,7 +87,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)
{
LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());
}
- else
+ else if (notification->canShowToast())
{
LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification);
diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h
index 7aabf7d09e..53fd898ea4 100755
--- a/indra/newview/llnotificationstorage.h
+++ b/indra/newview/llnotificationstorage.h
@@ -44,6 +44,7 @@ public:
protected:
bool writeNotifications(const LLSD& pNotificationData) const;
bool readNotifications(LLSD& pNotificationData) const;
+ void setFileName(std::string pFileName) {mFileName = pFileName;}
LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams) const;
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index a85335f1ba..4ca961c1f9 100755
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -83,13 +83,6 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)
if (notification->canLogToChat())
{
LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM);
-
- // don't show toast if Nearby Chat is opened
- LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
- if (nearby_chat->isChatVisible())
- {
- return false;
- }
}
std::string session_name = notification->getPayload()["SESSION_NAME"];
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index 133b269c11..a9a3c686a6 100755
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -85,6 +85,7 @@ public:
std::string mAlreadyInGroup;
std::string mTooManySelected;
bool mConfirmedOwnerInvite;
+ std::set<LLUUID> mInviteeIDs;
void (*mCloseCallback)(void* data);
@@ -117,31 +118,30 @@ LLPanelGroupInvite::impl::~impl()
}
}
+const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap.
+
void LLPanelGroupInvite::impl::addUsers(const std::vector<std::string>& names,
const uuid_vec_t& agent_ids)
{
std::string name;
LLUUID id;
+ if (names.size() + mInviteeIDs.size() > MAX_GROUP_INVITES)
+ {
+ // Fail! Show a warning and don't add any names.
+ LLSD msg;
+ msg["MESSAGE"] = mTooManySelected;
+ LLNotificationsUtil::add("GenericAlert", msg);
+ return;
+ }
+
for (S32 i = 0; i < (S32)names.size(); i++)
{
name = names[i];
id = agent_ids[i];
// Make sure this agent isn't already in the list.
- bool already_in_list = false;
- std::vector<LLScrollListItem*> items = mInvitees->getAllData();
- for (std::vector<LLScrollListItem*>::iterator iter = items.begin();
- iter != items.end(); ++iter)
- {
- LLScrollListItem* item = *iter;
- if (item->getUUID() == id)
- {
- already_in_list = true;
- break;
- }
- }
- if (already_in_list)
+ if (mInviteeIDs.find(id) != mInviteeIDs.end())
{
continue;
}
@@ -152,6 +152,7 @@ void LLPanelGroupInvite::impl::addUsers(const std::vector<std::string>& names,
row["columns"][0]["value"] = name;
mInvitees->addElement(row);
+ mInviteeIDs.insert(id);
}
}
@@ -193,7 +194,6 @@ void LLPanelGroupInvite::impl::submitInvitations()
role_member_pairs[item->getUUID()] = role_id;
}
- const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap.
if (role_member_pairs.size() > MAX_GROUP_INVITES)
{
// Fail!
@@ -334,6 +334,12 @@ void LLPanelGroupInvite::impl::handleRemove()
mInvitees->getAllSelected();
if (selection.empty()) return;
+ std::vector<LLScrollListItem*>::iterator iter;
+ for(iter = selection.begin(); iter != selection.end(); ++iter)
+ {
+ mInviteeIDs.erase( (*iter)->getUUID() );
+ }
+
// Remove all selected invitees.
mInvitees->deleteSelectedItems();
mRemoveButton->setEnabled(FALSE);
@@ -459,6 +465,7 @@ void LLPanelGroupInvite::clear()
mImplementation->mRoleNames->clear();
mImplementation->mRoleNames->removeall();
mImplementation->mOKButton->setEnabled(FALSE);
+ mImplementation->mInviteeIDs.clear();
}
void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index cfdac11d26..fdcd1f5ebb 100755
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1101,27 +1101,61 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
}
void LLPanelGroupMembersSubTab::handleEjectMembers()
-{
- //send down an eject message
- uuid_vec_t selected_members;
-
+{
std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
if (selection.empty()) return;
-
- std::vector<LLScrollListItem*>::iterator itor;
- for (itor = selection.begin() ;
- itor != selection.end(); ++itor)
+
+ S32 selection_count = selection.size();
+ if (selection_count == 1)
{
- LLUUID member_id = (*itor)->getUUID();
- selected_members.push_back( member_id );
+ LLSD args;
+ LLUUID selected_avatar = mMembersList->getValue().asUUID();
+ std::string fullname = LLSLURL("agent", selected_avatar, "inspect").getSLURLString();
+ args["AVATAR_NAME"] = fullname;
+ LLSD payload;
+ LLNotificationsUtil::add("EjectGroupMemberWarning",
+ args,
+ payload,
+ boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
}
+ else
+ {
+ LLSD args;
+ args["COUNT"] = llformat("%d", selection_count);
+ LLSD payload;
+ LLNotificationsUtil::add("EjectGroupMembersWarning",
+ args,
+ payload,
+ boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
+ }
+}
- mMembersList->deleteSelectedItems();
-
- sendEjectNotifications(mGroupID, selected_members);
-
- LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID,
- selected_members);
+bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option) // Eject button
+ {
+ //send down an eject message
+ uuid_vec_t selected_members;
+
+ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+ if (selection.empty()) return false;
+
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = selection.begin() ;
+ itor != selection.end(); ++itor)
+ {
+ LLUUID member_id = (*itor)->getUUID();
+ selected_members.push_back( member_id );
+ }
+
+ mMembersList->deleteSelectedItems();
+
+ sendEjectNotifications(mGroupID, selected_members);
+
+ LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);
+ }
+ return false;
}
void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members)
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 78bb3c57a1..0cf272f3ee 100755
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -167,6 +167,7 @@ public:
static void onEjectMembers(void*);
void handleEjectMembers();
void sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members);
+ bool handleEjectCallback(const LLSD& notification, const LLSD& response);
static void onRoleCheck(LLUICtrl* check, void* user_data);
void handleRoleCheck(const LLUUID& role_id,
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index bcb90bcb56..911ecaad9d 100755
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -82,10 +82,6 @@ const S32 MAX_PASSWORD = 16;
LLPanelLogin *LLPanelLogin::sInstance = NULL;
BOOL LLPanelLogin::sCapslockDidNotification = FALSE;
-// Helper for converting a user name into the canonical "Firstname Lastname" form.
-// For new accounts without a last name "Resident" is added as a last name.
-static std::string canonicalize_username(const std::string& name);
-
class LLLoginRefreshHandler : public LLCommandHandler
{
public:
@@ -266,7 +262,6 @@ void LLPanelLogin::addFavoritesToStartLocation()
// Load favorites into the combo.
std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
- std::string canonical_user_name = canonicalize_username(user_defined_name);
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
LLSD fav_llsd;
llifstream file;
@@ -279,7 +274,7 @@ void LLPanelLogin::addFavoritesToStartLocation()
// The account name in stored_favorites.xml has Resident last name even if user has
// a single word account name, so it can be compared case-insensitive with the
// user defined "firstname lastname".
- S32 res = LLStringUtil::compareInsensitive(canonical_user_name, iter->first);
+ S32 res = LLStringUtil::compareInsensitive(user_defined_name, iter->first);
if (res != 0)
{
lldebugs << "Skipping favorites for " << iter->first << llendl;
@@ -1012,29 +1007,3 @@ void LLPanelLogin::onLocationSLURL()
LLStartUp::setStartSLURL(location); // calls onUpdateStartSLURL, above
}
-
-
-std::string canonicalize_username(const std::string& name)
-{
- std::string cname = name;
- LLStringUtil::trim(cname);
-
- // determine if the username is a first/last form or not.
- size_t separator_index = cname.find_first_of(" ._");
- std::string first = cname.substr(0, separator_index);
- std::string last;
- if (separator_index != cname.npos)
- {
- last = cname.substr(separator_index+1, cname.npos);
- LLStringUtil::trim(last);
- }
- else
- {
- // ...on Linden grids, single username users as considered to have
- // last name "Resident"
- last = "Resident";
- }
-
- // Username in traditional "firstname lastname" form.
- return first + ' ' + last;
-}
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d6535c88e9..53deded2f2 100755
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -130,6 +130,8 @@ BOOL LLPanelMainInventory::postBuild()
mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this));
+ mCounterCtrl = getChild<LLUICtrl>("ItemcountText");
+
//panel->getFilter().markDefault();
// Set up the default inv. panel/filter settings.
@@ -566,7 +568,7 @@ void LLPanelMainInventory::draw()
void LLPanelMainInventory::updateItemcountText()
{
// *TODO: Calling setlocale() on each frame may be inefficient.
- LLLocale locale(LLStringUtil::getLocale());
+ //LLLocale locale(LLStringUtil::getLocale());
std::string item_count_string;
LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
@@ -589,8 +591,7 @@ void LLPanelMainInventory::updateItemcountText()
text = getString("ItemcountUnknown");
}
- // *TODO: Cache the LLUICtrl* for the ItemcountText control
- getChild<LLUICtrl>("ItemcountText")->setValue(text);
+ mCounterCtrl->setValue(text);
}
void LLPanelMainInventory::onFocusReceived()
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 899931aa89..394b004e20 100755
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -121,6 +121,7 @@ private:
LLFilterEditor* mFilterEditor;
LLTabContainer* mFilterTabs;
+ LLUICtrl* mCounterCtrl;
LLHandle<LLFloater> mFinderHandle;
LLInventoryPanel* mActivePanel;
bool mResortActivePanel;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 4138558bad..d7c634d619 100755
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -76,6 +76,8 @@ 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 */
class LLAvatarItemRecentComparator : public LLAvatarItemComparator
{
@@ -808,6 +810,8 @@ void LLPanelPeople::updateButtons()
LLPanel* groups_panel = mTabContainer->getCurrentPanel();
groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected
+ groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count()));
+ groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d",(gMaxAgentGroups-gAgent.mGroups.count())));
}
else
{
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index 49f7361c4a..0b2bf1d2c8 100755
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -74,6 +74,7 @@ LLContextMenu* PeopleContextMenu::createMenu()
registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id));
registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, id));
registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id));
+ registrar.add("Avatar.TeleportRequest", boost::bind(&PeopleContextMenu::requestTeleport, this));
registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id));
enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
@@ -125,6 +126,7 @@ void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
items.push_back(std::string("view_profile"));
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
+ items.push_back(std::string("request_teleport"));
items.push_back(std::string("voice_call"));
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
@@ -255,6 +257,13 @@ bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)
return false;
}
+void PeopleContextMenu::requestTeleport()
+{
+ // boost::bind cannot recognize overloaded method LLAvatarActions::teleportRequest(),
+ // so we have to use a wrapper.
+ LLAvatarActions::teleportRequest(mUUIDs.front());
+}
+
void PeopleContextMenu::offerTeleport()
{
// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
@@ -284,6 +293,7 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
items.push_back(std::string("view_profile"));
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
+ items.push_back(std::string("request_teleport"));
items.push_back(std::string("voice_call"));
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h
index 0a1dcef303..abf5fa05e4 100755
--- a/indra/newview/llpanelpeoplemenus.h
+++ b/indra/newview/llpanelpeoplemenus.h
@@ -47,6 +47,7 @@ private:
bool enableContextMenuItem(const LLSD& userdata);
bool checkContextMenuItem(const LLSD& userdata);
void offerTeleport();
+ void requestTeleport();
};
/**
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index e2e7006773..5acc98904b 100755
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -36,6 +36,8 @@
#include "lltabcontainer.h"
#include "llviewercontrol.h"
#include "llviewernetwork.h"
+#include "llmutelist.h"
+#include "llpanelblockedlist.h"
static const std::string PANEL_PICKS = "panel_picks";
@@ -137,6 +139,12 @@ public:
return true;
}
+ if (verb == "removefriend")
+ {
+ LLAvatarActions::removeFriendDialog(avatar_id);
+ return true;
+ }
+
if (verb == "mute")
{
if (! LLAvatarActions::isBlocked(avatar_id))
@@ -155,6 +163,18 @@ public:
return true;
}
+ if (verb == "block")
+ {
+ if (params.size() > 2)
+ {
+ const std::string object_name = params[2].asString();
+ LLMute mute(avatar_id, object_name, LLMute::OBJECT);
+ LLMuteList::getInstance()->add(mute);
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
+ }
+ return true;
+ }
+
return false;
}
};
diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp
index 666f10df96..076c3e0235 100755
--- a/indra/newview/llpersistentnotificationstorage.cpp
+++ b/indra/newview/llpersistentnotificationstorage.cpp
@@ -38,7 +38,8 @@
LLPersistentNotificationStorage::LLPersistentNotificationStorage()
: LLSingleton<LLPersistentNotificationStorage>()
- , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml"))
+ , LLNotificationStorage("")
+ , mLoaded(false)
{
}
@@ -89,8 +90,13 @@ void LLPersistentNotificationStorage::loadNotifications()
LL_INFOS("LLPersistentNotificationStorage") << "start loading notifications" << LL_ENDL;
- LLNotifications::instance().getChannel("Persistent")->
- connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
+ if (mLoaded)
+ {
+ LL_INFOS("LLPersistentNotificationStorage") << "notifications already loaded, exiting" << LL_ENDL;
+ return;
+ }
+
+ mLoaded = true;
LLSD input;
if (!readNotifications(input) ||input.isUndefined())
@@ -135,8 +141,20 @@ void LLPersistentNotificationStorage::loadNotifications()
LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL;
}
+void LLPersistentNotificationStorage::initialize()
+{
+ setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml"));
+ LLNotifications::instance().getChannel("Persistent")->
+ connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
+}
+
bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)
{
+ // In case we received channel changed signal but haven't yet loaded notifications, do it
+ if (!mLoaded)
+ {
+ loadNotifications();
+ }
// we ignore "load" messages, but rewrite the persistence file on any other
const std::string sigtype = payload["sigtype"].asString();
if ("load" != sigtype)
diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h
index 98a825d2c1..bf0306380e 100755
--- a/indra/newview/llpersistentnotificationstorage.h
+++ b/indra/newview/llpersistentnotificationstorage.h
@@ -53,10 +53,13 @@ public:
void saveNotifications();
void loadNotifications();
+ void initialize();
+
protected:
private:
bool onPersistentChannelChanged(const LLSD& payload);
+ bool mLoaded;
};
#endif // LL_LLPERSISTENTNOTIFICATIONSTORAGE_H
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 968a912ea2..e533be7f24 100755
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -86,6 +86,7 @@
#include "lltrans.h"
#include "llviewercontrol.h"
#include "llappviewer.h"
+#include "llfloatergotoline.h"
const std::string HELLO_LSL =
"default\n"
@@ -193,12 +194,17 @@ private:
LLScriptEdCore* mEditorCore;
static LLFloaterScriptSearch* sInstance;
+
+protected:
+ LLLineEditor* mSearchBox;
+ void onSearchBoxCommit();
};
LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;
LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core)
: LLFloater(LLSD()),
+ mSearchBox(NULL),
mEditorCore(editor_core)
{
buildFromFile("floater_script_search.xml");
@@ -221,6 +227,9 @@ LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core)
BOOL LLFloaterScriptSearch::postBuild()
{
+ mSearchBox = getChild<LLLineEditor>("search_text");
+ mSearchBox->setCommitCallback(boost::bind(&LLFloaterScriptSearch::onSearchBoxCommit, this));
+ mSearchBox->setCommitOnFocusLost(FALSE);
childSetAction("search_btn", onBtnSearch,this);
childSetAction("replace_btn", onBtnReplace,this);
childSetAction("replace_all_btn", onBtnReplaceAll,this);
@@ -315,6 +324,15 @@ BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask)
return FALSE;
}
+void LLFloaterScriptSearch::onSearchBoxCommit()
+{
+ if (mEditorCore && mEditorCore->mEditor)
+ {
+ LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text");
+ mEditorCore->mEditor->selectNext(getChild<LLUICtrl>("search_text")->getValue().asString(), caseChk->get());
+ }
+}
+
/// ---------------------------------------------------------------------------
/// LLScriptEdCore
/// ---------------------------------------------------------------------------
@@ -503,6 +521,9 @@ void LLScriptEdCore::initMenu()
menuItem = getChild<LLMenuItemCallGL>("Search / Replace...");
menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this));
+ menuItem = getChild<LLMenuItemCallGL>("Go to line...");
+ menuItem->setClickCallback(boost::bind(&LLFloaterGotoLine::show, this));
+
menuItem = getChild<LLMenuItemCallGL>("Help...");
menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnHelp, this));
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index 7563cecd9d..9fb0a4fb63 100755
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -34,6 +34,7 @@
#include "llcombobox.h"
#include "lliconctrl.h"
#include "llframetimer.h"
+#include "llfloatergotoline.h"
class LLLiveLSLFile;
class LLMessageSystem;
@@ -49,6 +50,7 @@ class LLKeywordToken;
class LLVFS;
class LLViewerInventoryItem;
class LLScriptEdContainer;
+class LLFloaterGotoLine;
// Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these.
class LLScriptEdCore : public LLPanel
@@ -58,6 +60,7 @@ class LLScriptEdCore : public LLPanel
friend class LLLiveLSLEditor;
friend class LLFloaterScriptSearch;
friend class LLScriptEdContainer;
+ friend class LLFloaterGotoLine;
protected:
// Supposed to be invoked only by the container.
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 928d26646b..c4d5450e2b 100755
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -207,6 +207,7 @@ LLSD _basic_constraints_ext(X509* cert)
}
}
+ BASIC_CONSTRAINTS_free( bs );
}
return result;
}
@@ -268,6 +269,8 @@ LLSD _ext_key_usage_ext(X509* cert)
ASN1_OBJECT_free(usage);
}
}
+
+ EXTENDED_KEY_USAGE_free( eku );
}
return result;
}
@@ -280,6 +283,8 @@ LLSD _subject_key_identifier_ext(X509 *cert)
if(skeyid)
{
result = cert_string_from_octet_string(skeyid);
+
+ ASN1_OCTET_STRING_free( skeyid );
}
return result;
}
@@ -300,6 +305,9 @@ LLSD _authority_key_identifier_ext(X509* cert)
{
result[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL] = cert_string_from_asn1_integer(akeyid->serial);
}
+
+
+ AUTHORITY_KEYID_free( akeyid );
}
// we ignore the issuer name in the authority key identifier, we check the issue name via
@@ -1049,6 +1057,8 @@ void LLBasicCertificateStore::validate(int validation_policy,
throw LLInvalidCertificate((*current_cert));
}
std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);
+ X509_free( cert_x509 );
+ cert_x509 = NULL;
t_cert_cache::iterator cache_entry = mTrustedCertCache.find(sha1_hash);
if(cache_entry != mTrustedCertCache.end())
{
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 941c578783..9e97790df8 100755
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -3457,7 +3457,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
}
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE)
{
- /*LLVolumeParams volume_params;
+ LLVolumeParams volume_params;
volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
volume_params.setBeginAndEndS( 0.f, 1.f );
volume_params.setBeginAndEndT( 0.f, 1.f );
@@ -3467,7 +3467,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
gGL.diffuseColor4fv(color.mV);
pushVerts(sphere);
- LLPrimitive::sVolumeManager->unrefVolume(sphere);*/
+ LLPrimitive::sVolumeManager->unrefVolume(sphere);
}
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER)
{
@@ -3545,51 +3545,67 @@ void renderPhysicsShapes(LLSpatialGroup* group)
for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
LLDrawable* drawable = *i;
- LLVOVolume* volume = drawable->getVOVolume();
- if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE )
+
+ if (drawable->isSpatialBridge())
{
- if (!group->mSpatialPartition->isBridge())
+ LLSpatialBridge* bridge = drawable->asPartition()->asBridge();
+
+ if (bridge)
{
gGL.pushMatrix();
- LLVector3 trans = drawable->getRegion()->getOriginAgent();
- gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);
- renderPhysicsShape(drawable, volume);
+ gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ bridge->renderPhysicsShapes();
gGL.popMatrix();
}
- else
- {
- renderPhysicsShape(drawable, volume);
- }
}
else
{
- LLViewerObject* object = drawable->getVObj();
- if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
+ LLVOVolume* volume = drawable->getVOVolume();
+ if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE )
{
- gGL.pushMatrix();
- gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix);
- //push face vertices for terrain
- for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ if (!group->mSpatialPartition->isBridge())
{
- LLFace* face = drawable->getFace(i);
- if (face)
+ gGL.pushMatrix();
+ LLVector3 trans = drawable->getRegion()->getOriginAgent();
+ gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);
+ renderPhysicsShape(drawable, volume);
+ gGL.popMatrix();
+ }
+ else
+ {
+ renderPhysicsShape(drawable, volume);
+ }
+ }
+ else
+ {
+ LLViewerObject* object = drawable->getVObj();
+ if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
+ {
+ gGL.pushMatrix();
+ gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix);
+ //push face vertices for terrain
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
{
- LLVertexBuffer* buff = face->getVertexBuffer();
- if (buff)
+ LLFace* face = drawable->getFace(i);
+ if (face)
{
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ LLVertexBuffer* buff = face->getVertexBuffer();
+ if (buff)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
- gGL.diffuseColor3f(0.2f, 0.5f, 0.3f);
- buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
+ buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ gGL.diffuseColor3f(0.2f, 0.5f, 0.3f);
+ buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
- gGL.diffuseColor3f(0.2f, 1.f, 0.3f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
+ gGL.diffuseColor3f(0.2f, 1.f, 0.3f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
+ }
}
}
+ gGL.popMatrix();
}
- gGL.popMatrix();
}
}
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index cff3a7e02a..67a76460a7 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -51,6 +51,7 @@
#include "lllandmark.h"
#include "llcachename.h"
#include "lldir.h"
+#include "lldonotdisturbnotificationstorage.h"
#include "llerrorcontrol.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
@@ -68,6 +69,7 @@
#include "llfloaterimnearbychat.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
+#include "llpersistentnotificationstorage.h"
#include "llteleporthistory.h"
#include "llregionhandle.h"
#include "llsd.h"
@@ -900,6 +902,10 @@ bool idle_startup()
gDirUtilp->setLindenUserDir(userid);
LLFile::mkdir(gDirUtilp->getLindenUserDir());
+ // As soon as directories are ready initialize notification storages
+ LLPersistentNotificationStorage::getInstance()->initialize();
+ LLDoNotDisturbNotificationStorage::getInstance()->initialize();
+
// Set PerAccountSettingsFile to the default value.
gSavedSettings.setString("PerAccountSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index e92bd766ca..626d69aca4 100755
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -118,6 +118,11 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)
}
}
+ LLPanel * LLSysWellWindow::findItemByID(const LLUUID& id)
+{
+ return mMessageList->getItemByValue(id);
+}
+
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
void LLSysWellWindow::initChannel()
@@ -423,9 +428,18 @@ void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)
void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)
{
LLUUID id = item->getID();
- removeItemByID(id);
+
if(mChannel)
+ {
+ // removeItemByID() is invoked from killToastByNotificationID() and item will removed;
mChannel->killToastByNotificationID(id);
+ }
+ else
+ {
+ // removeItemByID() should be called one time for each item to remove it from notification well
+ removeItemByID(id);
+ }
+
}
void LLNotificationWellWindow::onAdd( LLNotificationPtr notify )
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index cc5c057d8b..71b41476f5 100755
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -55,6 +55,7 @@ public:
// Operating with items
void removeItemByID(const LLUUID& id);
+ LLPanel * findItemByID(const LLUUID& id);
// Operating with outfit
virtual void setVisible(BOOL visible);
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 36a7aeb590..5bc2e971eb 100755
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1922,10 +1922,10 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 dis
h >>= i;
if(w * h *c > 0) //valid
{
- LLPointer<LLImageRaw> newraw = new LLImageRaw(raw->getData(), raw->getWidth(), raw->getHeight(), raw->getComponents());
- newraw->scale(w, h) ;
- raw = newraw;
-
+ //make a duplicate to keep the original raw image untouched.
+ raw = raw->duplicate();
+ raw->scale(w, h) ;
+
discardlevel += i ;
}
}
@@ -1935,9 +1935,12 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 dis
memcpy(mFastCachePadBuffer + sizeof(S32), &h, sizeof(S32));
memcpy(mFastCachePadBuffer + sizeof(S32) * 2, &c, sizeof(S32));
memcpy(mFastCachePadBuffer + sizeof(S32) * 3, &discardlevel, sizeof(S32));
- if(w * h * c > 0) //valid
+
+ S32 copy_size = w * h * c;
+ if(copy_size > 0) //valid
{
- memcpy(mFastCachePadBuffer + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD, raw->getData(), w * h * c);
+ copy_size = llmin(copy_size, TEXTURE_FAST_CACHE_ENTRY_SIZE - TEXTURE_FAST_CACHE_ENTRY_OVERHEAD);
+ memcpy(mFastCachePadBuffer + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD, raw->getData(), copy_size);
}
S32 offset = id * TEXTURE_FAST_CACHE_ENTRY_SIZE;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 6173e76a35..6173e76a35 100755..100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index 75e6e3d13a..09ab31df36 100755
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -28,6 +28,7 @@
#include "lltoastimpanel.h"
#include "llagent.h"
+#include "llavatarnamecache.h"
#include "llfloaterreg.h"
#include "llgroupactions.h"
#include "llgroupiconctrl.h"
@@ -61,6 +62,15 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
style_params.font.name(font_name);
style_params.font.size(font_size);
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(p.session_id);
+ mIsGroupMsg = (im_session && im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION);
+ if(mIsGroupMsg)
+ {
+ mAvatarName->setValue(im_session->mName);
+ LLAvatarName avatar_name;
+ LLAvatarNameCache::get(p.avatar_id, &avatar_name);
+ p.message = "[From " + avatar_name.getDisplayName() + "]\n" + p.message;
+ }
//Handle IRC styled /me messages.
std::string prefix = p.message.substr(0, 4);
@@ -81,12 +91,17 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mMessage->setText(p.message, style_params);
}
- mAvatarName->setValue(p.from);
+ if(!mIsGroupMsg)
+ {
+ mAvatarName->setValue(p.from);
+ }
mTime->setValue(p.time);
mSessionID = p.session_id;
mAvatarID = p.avatar_id;
mNotification = p.notification;
+
+
initIcon();
S32 maxLinesCount;
@@ -147,7 +162,14 @@ void LLToastIMPanel::spawnNameToolTip()
LLToolTip::Params params;
params.background_visible(false);
- params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
+ if(!mIsGroupMsg)
+ {
+ params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
+ }
+ else
+ {
+ params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_group", LLSD().with("group_id", mSessionID), FALSE));
+ }
params.delay_time(0.0f); // spawn instantly on hover
params.image(LLUI::getUIImage("Info_Small"));
params.message("");
diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h
index 3eb11fb3bc..767617dabc 100755
--- a/indra/newview/lltoastimpanel.h
+++ b/indra/newview/lltoastimpanel.h
@@ -73,6 +73,8 @@ private:
LLTextBox* mAvatarName;
LLTextBox* mTime;
LLTextBox* mMessage;
+
+ bool mIsGroupMsg;
};
#endif // LLTOASTIMPANEL_H_
diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp
index b2318f9158..78a555d67d 100755
--- a/indra/newview/lltoolbarview.cpp
+++ b/indra/newview/lltoolbarview.cpp
@@ -51,8 +51,6 @@ LLToolBarView* gToolBarView = NULL;
static LLDefaultChildRegistry::Register<LLToolBarView> r("toolbar_view");
-void handleLoginToolbarSetup();
-
bool isToolDragged()
{
return (LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_VIEWER);
@@ -111,8 +109,6 @@ BOOL LLToolBarView::postBuild()
mToolbars[i]->setButtonAddCallback(boost::bind(LLToolBarView::onToolBarButtonAdded,_1));
mToolbars[i]->setButtonRemoveCallback(boost::bind(LLToolBarView::onToolBarButtonRemoved,_1));
}
-
- LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&handleLoginToolbarSetup));
return TRUE;
}
@@ -180,13 +176,13 @@ S32 LLToolBarView::stopCommandInProgress(const LLCommandId& commandId)
return command_location;
}
-S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash)
+S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */)
{
S32 command_location = hasCommand(commandId);
if (command_location != TOOLBAR_NONE)
{
- mToolbars[command_location]->flashCommand(commandId, flash);
+ mToolbars[command_location]->flashCommand(commandId, flash, force_flashing);
}
return command_location;
@@ -696,18 +692,3 @@ bool LLToolBarView::isModified() const
}
-//
-// HACK to bring up destinations guide at startup
-//
-
-void handleLoginToolbarSetup()
-{
- // Open the destinations guide by default on first login, per Rhett
- if (gSavedPerAccountSettings.getBOOL("DisplayDestinationsOnInitialRun") || gAgent.isFirstLogin())
- {
- LLFloaterReg::showInstance("destinations");
-
- gSavedPerAccountSettings.setBOOL("DisplayDestinationsOnInitialRun", FALSE);
- }
-}
-
diff --git a/indra/newview/lltoolbarview.h b/indra/newview/lltoolbarview.h
index 7125dd9990..dcc3862074 100755
--- a/indra/newview/lltoolbarview.h
+++ b/indra/newview/lltoolbarview.h
@@ -90,7 +90,7 @@ public:
S32 removeCommand(const LLCommandId& commandId, int& rank); // Sets the rank the removed command was at, RANK_NONE if not found
S32 enableCommand(const LLCommandId& commandId, bool enabled);
S32 stopCommandInProgress(const LLCommandId& commandId);
- S32 flashCommand(const LLCommandId& commandId, bool flash);
+ S32 flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing = false);
// Loads the toolbars from the existing user or default settings
bool loadToolbars(bool force_default = false); // return false if load fails
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index fc9a316759..1c362c18e0 100755
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -121,7 +121,7 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
// don't pick transparent so users can't "pay" transparent objects
- mPick = gViewerWindow->pickImmediate(x, y, FALSE);
+ mPick = gViewerWindow->pickImmediate(x, y, FALSE, TRUE);
mPick.mKeyMask = mask;
// claim not handled so UI focus stays same
@@ -1687,6 +1687,13 @@ BOOL LLToolPie::handleRightClickPick()
showVisualContextMenuEffect();
}
}
+ else if (mPick.mParticleOwnerID.notNull())
+ {
+ if (gMenuMuteParticle && mPick.mParticleOwnerID != gAgent.getID())
+ {
+ gMenuMuteParticle->show(x,y);
+ }
+ }
LLTool::handleRightMouseDown(x, y, mask);
// We handled the event.
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index afbb59e723..744ec4de2b 100755
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -83,7 +83,9 @@
BOOL gHackGodmode = FALSE;
#endif
-
+// Should you contemplate changing the name "Global", please first grep for
+// that string literal. There are at least a couple other places in the C++
+// code that assume the LLControlGroup named "Global" is gSavedSettings.
LLControlGroup gSavedSettings("Global"); // saved at end of session
LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session
LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index 4ecdc31e21..0d243804a7 100755
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -676,12 +676,16 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL
if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end())
{
mKeyHandledByUI[translated_key] = FALSE;
+ LL_INFOS("Keyboard Handling") << "Key wasn't handled by UI!" << LL_ENDL;
}
else
{
// it is sufficient to set this value once per call to handlekey
// without clearing it, as it is only used in the subsequent call to scanKey
- mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);
+ mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);
+ // mKeyHandledByUI is not what you think ... this indicates whether the UI has handled this keypress yet (any keypress)
+ // NOT whether some UI shortcut wishes to handle the keypress
+
}
return mKeyHandledByUI[translated_key];
}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 5e2f05f468..323eac19a4 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -40,6 +40,7 @@
#include "llinventorypanel.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
+#include "llviewereventrecorder.h"
// newview includes
#include "llagent.h"
@@ -169,6 +170,7 @@ LLContextMenu *gMenuObject = NULL;
LLContextMenu *gMenuAttachmentSelf = NULL;
LLContextMenu *gMenuAttachmentOther = NULL;
LLContextMenu *gMenuLand = NULL;
+LLContextMenu *gMenuMuteParticle = NULL;
const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents");
@@ -425,6 +427,9 @@ void init_menus()
gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>(
"menu_land.xml", gMenuHolder, registry);
+ gMenuMuteParticle = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_mute_particle.xml", gMenuHolder, registry);
+
///
/// set up the colors
///
@@ -1950,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 //
@@ -2450,6 +2492,9 @@ void cleanup_menus()
delete gMenuLand;
gMenuLand = NULL;
+ delete gMenuMuteParticle;
+ gMenuMuteParticle = NULL;
+
delete gMenuBarView;
gMenuBarView = NULL;
@@ -2803,6 +2848,13 @@ bool enable_object_edit()
return enable;
}
+bool enable_mute_particle()
+{
+ const LLPickInfo& pick = LLToolPie::getInstance()->getPick();
+
+ return pick.mParticleOwnerID != LLUUID::null && pick.mParticleOwnerID != gAgent.getID();
+}
+
// mutually exclusive - show either edit option or build in menu
bool enable_object_build()
{
@@ -6220,6 +6272,33 @@ class LLLandEdit : public view_listener_t
}
};
+class LLMuteParticle : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLUUID id = LLToolPie::getInstance()->getPick().mParticleOwnerID;
+
+ if (id.notNull())
+ {
+ std::string name;
+ gCacheName->getFullName(id, name);
+
+ LLMute mute(id, name, LLMute::AGENT);
+ if (LLMuteList::getInstance()->isMuted(mute.mID))
+ {
+ LLMuteList::getInstance()->remove(mute);
+ }
+ else
+ {
+ LLMuteList::getInstance()->add(mute);
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
+ }
+ }
+
+ return true;
+ }
+};
+
class LLWorldEnableBuyLand : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -8320,6 +8399,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));
@@ -8578,6 +8659,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");
@@ -8713,6 +8795,9 @@ void initialize_menus()
view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");
view_listener_t::addMenu(new LLLandEdit(), "Land.Edit");
+ // Particle muting
+ view_listener_t::addMenu(new LLMuteParticle(), "Particle.Mute");
+
view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass");
commit.add("Land.Buy", boost::bind(&handle_buy_land));
@@ -8735,6 +8820,7 @@ void initialize_menus()
enable.add("EnablePayObject", boost::bind(&enable_pay_object));
enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));
enable.add("EnableEdit", boost::bind(&enable_object_edit));
+ enable.add("EnableMuteParticle", boost::bind(&enable_mute_particle));
enable.add("VisibleBuild", boost::bind(&enable_object_build));
commit.add("Pathfinding.Linksets.Select", boost::bind(&LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects));
enable.add("EnableSelectInPathfindingLinksets", boost::bind(&enable_object_select_in_pathfinding_linksets));
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 143420e227..7f09fc2d8f 100755
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -177,6 +177,7 @@ extern LLContextMenu *gMenuObject;
extern LLContextMenu *gMenuAttachmentSelf;
extern LLContextMenu *gMenuAttachmentOther;
extern LLContextMenu *gMenuLand;
+extern LLContextMenu *gMenuMuteParticle;
// Needed to build menus when attachment site list available
extern LLMenuGL* gAttachSubMenu;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ace16396db..1f0ffac737 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -259,11 +259,15 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
break;
}
- LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm()));
- modified_form->setElementEnabled("Accept", false);
- modified_form->setElementEnabled("Decline", false);
- notification_ptr->updateForm(modified_form);
- notification_ptr->repost();
+ // TODO: this set of calls has undesirable behavior under Windows OS (CHUI-985):
+ // here appears three additional toasts instead one modified
+ // need investigation and fix
+
+ // LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm()));
+ // modified_form->setElementEnabled("Accept", false);
+ // modified_form->setElementEnabled("Decline", false);
+ // notification_ptr->updateForm(modified_form);
+ // notification_ptr->repost();
}
return false;
@@ -2216,7 +2220,7 @@ static std::string clean_name_from_im(const std::string& name, EInstantMessage t
case IM_LURE_ACCEPTED:
case IM_LURE_DECLINED:
case IM_GODLIKE_LURE_USER:
- case IM_YET_TO_BE_USED:
+ case IM_TELEPORT_REQUEST:
case IM_GROUP_ELECTION_DEPRECATED:
//IM_GOTO_URL
//IM_FROM_TASK_AS_ALERT
@@ -2649,7 +2653,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
send_do_not_disturb_message(msg, from_id);
}
- else
+
+ if (!is_muted)
{
LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;
// Read the binary bucket for more information.
@@ -2981,6 +2986,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
break;
case IM_LURE_USER:
+ case IM_TELEPORT_REQUEST:
{
if (is_muted)
{
@@ -3003,7 +3009,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);
@@ -3075,12 +3082,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;
@@ -3673,6 +3690,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
LLSD msg_notify = LLSD(LLSD::emptyMap());
msg_notify["session_id"] = LLUUID();
msg_notify["from_id"] = chat.mFromID;
+ msg_notify["source_type"] = chat.mSourceType;
on_new_message(msg_notify);
}
}
@@ -4570,7 +4588,6 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
if (id == LLUUID::null)
{
LL_DEBUGS("Messaging") << "Unknown kill for local " << local_id << LL_ENDL;
- gObjectList.mNumUnknownKills++;
continue;
}
else
@@ -4594,18 +4611,12 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
// Do the kill
gObjectList.killObject(objectp);
}
- else
- {
- LL_WARNS("Messaging") << "Object in UUID lookup, but not on object list in kill!" << LL_ENDL;
- gObjectList.mNumUnknownKills++;
- }
}
// We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab,
// which is using the object, release the mouse capture correctly when the object dies.
// See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical().
LLSelectMgr::getInstance()->removeObjectFromSelections(id);
-
}
}
@@ -5937,6 +5948,15 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
return true;
}
}
+ // HACK -- handle callbacks for specific alerts.
+ if( notificationID == "HomePositionSet" )
+ {
+ // save the home location image to disk
+ std::string snap_filename = gDirUtilp->getLindenUserDir();
+ snap_filename += gDirUtilp->getDirDelimiter();
+ snap_filename += SCREEN_HOME_FILENAME;
+ gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE);
+ }
LLNotificationsUtil::add(notificationID, llsdBlock);
return true;
@@ -6012,14 +6032,6 @@ void process_alert_core(const std::string& message, BOOL modal)
{
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT);
}
- else if( message == "Home position set." )
- {
- // save the home location image to disk
- std::string snap_filename = gDirUtilp->getLindenUserDir();
- snap_filename += gDirUtilp->getDirDelimiter();
- snap_filename += SCREEN_HOME_FILENAME;
- gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE);
- }
const std::string ALERT_PREFIX("ALERT: ");
const std::string NOTIFY_PREFIX("NOTIFY: ");
@@ -6851,6 +6863,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;
@@ -6864,50 +6921,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;
@@ -6947,6 +6966,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,
@@ -7326,8 +7397,12 @@ void process_script_teleport_request(LLMessageSystem* msg, void**)
LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
if(instance)
{
- instance->trackURL(
- sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]);
+ llinfos << "Object named " << object_name
+ << " is offering TP to region "
+ << sim_name << " position " << pos
+ << llendl;
+
+ instance->trackURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]);
LLFloaterReg::showInstance("world_map", "center");
}
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 97f4c3e5fe..e7821d4b9e 100755
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -43,6 +43,8 @@ const std::string GRID_LABEL_VALUE = "label";
const std::string GRID_ID_VALUE = "grid_login_id";
/// the url for the login cgi script
const std::string GRID_LOGIN_URI_VALUE = "login_uri";
+/// url base for update queries
+const std::string GRID_UPDATE_SERVICE_URL = "update_query_url_base";
///
const std::string GRID_HELPER_URI_VALUE = "helper_uri";
/// the splash page url
@@ -63,6 +65,8 @@ const std::string DEFAULT_LOGIN_PAGE = "http://viewer-login.agni.lindenlab.com/"
const std::string MAIN_GRID_LOGIN_URI = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
+const std::string SL_UPDATE_QUERY_URL = "https://update.secondlife.com/update";
+
const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/";
const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app";
@@ -120,12 +124,14 @@ void LLGridManager::initialize(const std::string& grid_file)
MAIN_GRID_LOGIN_URI,
"https://secondlife.com/helpers/",
DEFAULT_LOGIN_PAGE,
+ SL_UPDATE_QUERY_URL,
"Agni");
addSystemGrid("Second Life Beta Test Grid (Aditi)",
"util.aditi.lindenlab.com",
"https://login.aditi.lindenlab.com/cgi-bin/login.cgi",
"http://aditi-secondlife.webdev.lindenlab.com/helpers/",
DEFAULT_LOGIN_PAGE,
+ SL_UPDATE_QUERY_URL,
"Aditi");
LLSD other_grids;
@@ -332,6 +338,7 @@ void LLGridManager::addSystemGrid(const std::string& label,
const std::string& login_uri,
const std::string& helper,
const std::string& login_page,
+ const std::string& update_url_base,
const std::string& login_id)
{
LLSD grid = LLSD::emptyMap();
@@ -341,6 +348,7 @@ void LLGridManager::addSystemGrid(const std::string& label,
grid[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray();
grid[GRID_LOGIN_URI_VALUE].append(login_uri);
grid[GRID_LOGIN_PAGE_VALUE] = login_page;
+ grid[GRID_UPDATE_SERVICE_URL] = update_url_base;
grid[GRID_IS_SYSTEM_GRID_VALUE] = true;
grid[GRID_LOGIN_IDENTIFIER_TYPES] = LLSD::emptyArray();
grid[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_AGENT);
@@ -537,6 +545,30 @@ std::string LLGridManager::getGridLoginID()
return mGridList[mGrid][GRID_ID_VALUE];
}
+std::string LLGridManager::getUpdateServiceURL()
+{
+ std::string update_url_base = gSavedSettings.getString("CmdLineUpdateService");;
+ if ( !update_url_base.empty() )
+ {
+ LL_INFOS2("UpdaterService","GridManager")
+ << "Update URL base overridden from command line: " << update_url_base
+ << LL_ENDL;
+ }
+ else if ( mGridList[mGrid].has(GRID_UPDATE_SERVICE_URL) )
+ {
+ update_url_base = mGridList[mGrid][GRID_UPDATE_SERVICE_URL].asString();
+ }
+ else
+ {
+ LL_WARNS2("UpdaterService","GridManager")
+ << "The grid property '" << GRID_UPDATE_SERVICE_URL
+ << "' is not defined for the grid '" << mGrid << "'"
+ << LL_ENDL;
+ }
+
+ return update_url_base;
+}
+
void LLGridManager::updateIsInProductionGrid()
{
mIsInProductionGrid = false;
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 3f56103b2e..8526c0ba7f 100755
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -140,6 +140,14 @@ class LLGridManager : public LLSingleton<LLGridManager>
*/
//@}
+ /* ================================================================
+ * @name Update Related Properties
+ * @{
+ */
+ /// Get the update service URL base (host and path) for the selected grid
+ std::string getUpdateServiceURL();
+
+ //@}
/* ================================================================
* @name URL Construction Properties
@@ -207,6 +215,7 @@ class LLGridManager : public LLSingleton<LLGridManager>
const std::string& login,
const std::string& helper,
const std::string& login_page,
+ const std::string& update_url_base,
const std::string& login_id = "");
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index caacf26cb3..b4e287c446 100755
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -106,7 +106,6 @@ LLViewerObjectList::LLViewerObjectList()
mNumNewObjects = 0;
mWasPaused = FALSE;
mNumDeadObjectUpdates = 0;
- mNumUnknownKills = 0;
mNumUnknownUpdates = 0;
}
@@ -955,15 +954,17 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
objectp = *idle_iter;
llassert(objectp->isActive());
objectp->idleUpdate(agent, world, frame_time);
-
- }
+ }
//update flexible objects
LLVolumeImplFlexible::updateClass();
//update animated textures
- LLViewerTextureAnim::updateClass();
- }
+ if (gAnimateTextures)
+ {
+ LLViewerTextureAnim::updateClass();
+ }
+ }
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 449a4633ff..6518c25d09 100755
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -188,7 +188,6 @@ public:
S32 mNumUnknownUpdates;
S32 mNumDeadObjectUpdates;
- S32 mNumUnknownKills;
S32 mNumDeadObjects;
protected:
std::vector<U64> mOrphanParents; // LocalID/ip,port of orphaned objects
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index 6bd9f66b9c..61cdfd7818 100755
--- a/indra/newview/llviewerpartsim.cpp
+++ b/indra/newview/llviewerpartsim.cpp
@@ -488,9 +488,13 @@ void LLViewerPartSim::destroyClass()
//static
BOOL LLViewerPartSim::shouldAddPart()
{
- if (sParticleCount > PART_THROTTLE_THRESHOLD*sMaxParticleCount)
+ if (sParticleCount >= MAX_PART_COUNT)
{
+ return FALSE;
+ }
+ if (sParticleCount > PART_THROTTLE_THRESHOLD*sMaxParticleCount)
+ {
F32 frac = (F32)sParticleCount/(F32)sMaxParticleCount;
frac -= PART_THROTTLE_THRESHOLD;
frac *= PART_THROTTLE_RESCALE;
@@ -500,7 +504,10 @@ BOOL LLViewerPartSim::shouldAddPart()
return FALSE;
}
}
- if (sParticleCount >= MAX_PART_COUNT)
+
+ // Check frame rate, and don't add more if the viewer is really slow
+ const F32 MIN_FRAME_RATE_FOR_NEW_PARTICLES = 4.f;
+ if (gFPSClamped < MIN_FRAME_RATE_FOR_NEW_PARTICLES)
{
return FALSE;
}
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 6cc9f4ace1..84f66c359f 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1199,10 +1199,10 @@ void LLViewerFetchedTexture::dump()
// ONLY called from LLViewerFetchedTextureList
void LLViewerFetchedTexture::destroyTexture()
{
- //if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory.
- //{
- // return ;
- //}
+ if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes * 0.95f)//not ready to release unused memory.
+ {
+ return ;
+ }
if (mNeedsCreateTexture)//return if in the process of generating a new texture.
{
return ;
@@ -1290,7 +1290,12 @@ void LLViewerFetchedTexture::addToCreateTexture()
destroyRawImage();
return ;
}
- mRawImage->scale(w >> i, h >> i) ;
+
+ {
+ //make a duplicate in case somebody else is using this raw image
+ mRawImage = mRawImage->duplicate();
+ mRawImage->scale(w >> i, h >> i) ;
+ }
}
}
}
@@ -1521,7 +1526,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
else if (pixel_priority < 0.001f && !have_all_data)
{
// Not on screen but we might want some data
- if (mBoostLevel > BOOST_HIGH)
+ if (mBoostLevel > BOOST_SELECTED)
{
// Always want high boosted images
priority = 1.f;
@@ -2669,7 +2674,11 @@ void LLViewerFetchedTexture::setCachedRawImage()
--i ;
}
- mRawImage->scale(w >> i, h >> i) ;
+ {
+ //make a duplicate in case somebody else is using this raw image
+ mRawImage = mRawImage->duplicate();
+ mRawImage->scale(w >> i, h >> i) ;
+ }
}
mCachedRawImage = mRawImage ;
mRawDiscardLevel += i ;
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index c96f89017f..10101a4b9b 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -101,6 +101,7 @@ public:
INVALID_TEXTURE_TYPE
};
+
typedef std::vector<LLFace*> ll_face_list_t;
typedef std::vector<LLVOVolume*> ll_volume_list_t;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index d9f3548a29..2de31cae98 100755
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1237,7 +1237,7 @@ S32 LLViewerTextureList::getMinVideoRamSetting()
//static
// Returns max setting for TextureMemory (in MB)
-S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
+S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier)
{
S32 max_texmem;
if (gGLManager.mVRAM != 0)
@@ -1281,7 +1281,10 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
max_texmem = llmin(max_texmem, (S32)(system_ram/2));
else
max_texmem = llmin(max_texmem, (S32)(system_ram));
-
+
+ // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
+ max_texmem = llmin(max_texmem, (S32) (mem_multiplier * (F32) max_texmem));
+
max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES);
return max_texmem;
@@ -1294,7 +1297,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
// Initialize the image pipeline VRAM settings
S32 cur_mem = gSavedSettings.getS32("TextureMemory");
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
- S32 default_mem = getMaxVideoRamSetting(true); // recommended default
+ S32 default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default
if (mem == 0)
{
mem = cur_mem > 0 ? cur_mem : default_mem;
@@ -1304,10 +1307,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
mem = default_mem;
}
- // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
- mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem));
-
- mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting());
+ mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier));
if (mem != cur_mem)
{
gSavedSettings.setS32("TextureMemory", mem);
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 136042620d..26dc6dcbe2 100755
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -114,7 +114,7 @@ public:
void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
static S32 getMinVideoRamSetting();
- static S32 getMaxVideoRamSetting(bool get_recommended = false);
+ static S32 getMaxVideoRamSetting(bool get_recommended, float mem_multiplier);
private:
void updateImagesDecodePriorities();
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 65a906d3c0..963eb3eb88 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -197,6 +197,8 @@
#include "llagentui.h"
#include "llwearablelist.h"
+#include "llviewereventrecorder.h"
+
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llnotificationmanager.h"
@@ -229,7 +231,9 @@ LLFrameTimer gAwayTriggerTimer;
BOOL gShowOverlayTitle = FALSE;
LLViewerObject* gDebugRaycastObject = NULL;
+LLVOPartGroup* gDebugRaycastParticle = NULL;
LLVector4a gDebugRaycastIntersection;
+LLVector4a gDebugRaycastParticleIntersection;
LLVector2 gDebugRaycastTexCoord;
LLVector4a gDebugRaycastNormal;
LLVector4a gDebugRaycastTangent;
@@ -914,27 +918,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) )
@@ -942,27 +937,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;
@@ -1333,7 +1345,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
}
@@ -1811,7 +1824,6 @@ void LLViewerWindow::initBase()
gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
-
// Console
llassert( !gConsole );
@@ -2477,6 +2489,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;
}
@@ -2491,12 +2505,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;
}
}
@@ -2506,6 +2522,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
@@ -2520,11 +2537,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;
}
@@ -2564,18 +2583,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;
}
@@ -2583,6 +2611,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;
}
@@ -2631,7 +2661,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)
{
@@ -2654,14 +2684,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;
@@ -2670,8 +2693,6 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
void LLViewerWindow::handleScrollWheel(S32 clicks)
{
- LLView::sMouseHandlerMessage.clear();
-
LLUI::resetMouseIdleTimer();
LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
@@ -2844,6 +2865,8 @@ void LLViewerWindow::updateUI()
&gDebugRaycastTangent,
&gDebugRaycastStart,
&gDebugRaycastEnd);
+
+ gDebugRaycastParticle = gPipeline.lineSegmentIntersectParticle(gDebugRaycastStart, gDebugRaycastEnd, &gDebugRaycastParticleIntersection, NULL);
}
updateMouseDelta();
@@ -3664,7 +3687,7 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback
pick_transparent = TRUE;
}
- LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
+ LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, FALSE, TRUE, callback);
schedulePick(pick_info);
}
@@ -3720,7 +3743,7 @@ void LLViewerWindow::returnEmptyPicks()
}
// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent)
+LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_particle)
{
BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
@@ -3729,10 +3752,10 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans
// "Show Debug Alpha" means no object actually transparent
pick_transparent = TRUE;
}
-
+
// shortcut queueing in mPicks and just update mLastPick in place
MASK key_mask = gKeyboard->currentMask(TRUE);
- mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, TRUE, NULL);
+ mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_particle, TRUE, NULL);
mLastPick.fetchResults();
return mLastPick;
@@ -4291,7 +4314,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
F32 scale_factor = 1.0f ;
if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height))
{
- if ((image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui)
+ if ((image_width <= gGLManager.mGLMaxTextureSize && image_height <= gGLManager.mGLMaxTextureSize) &&
+ (image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui)
{
if (scratch_space.allocate(image_width, image_height, GL_RGBA, true, true))
{
@@ -4306,6 +4330,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
snapshot_height = image_height;
reset_deferred = true;
mWorldViewRectRaw.set(0, image_height, image_width, 0);
+ LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+ LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
scratch_space.bindTarget();
}
else
@@ -4515,6 +4541,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
if (reset_deferred)
{
mWorldViewRectRaw = window_rect;
+ LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+ LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
scratch_space.flush();
scratch_space.release();
gPipeline.allocateScreenBuffer(original_width, original_height);
@@ -5128,13 +5156,15 @@ LLPickInfo::LLPickInfo()
mTangent(),
mBinormal(),
mHUDIcon(NULL),
- mPickTransparent(FALSE)
+ mPickTransparent(FALSE),
+ mPickParticle(FALSE)
{
}
LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
MASK keyboard_mask,
BOOL pick_transparent,
+ BOOL pick_particle,
BOOL pick_uv_coords,
void (*pick_callback)(const LLPickInfo& pick_info))
: mMousePt(mouse_pos),
@@ -5150,7 +5180,8 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
mTangent(),
mBinormal(),
mHUDIcon(NULL),
- mPickTransparent(pick_transparent)
+ mPickTransparent(pick_transparent),
+ mPickParticle(pick_particle)
{
}
@@ -5168,6 +5199,10 @@ void LLPickInfo::fetchResults()
LLVector4a origin;
origin.load3(LLViewerCamera::getInstance()->getOrigin().mV);
F32 icon_dist = 0.f;
+ LLVector4a start;
+ LLVector4a end;
+ LLVector4a particle_end;
+
if (hit_icon)
{
LLVector4a delta;
@@ -5177,14 +5212,24 @@ void LLPickInfo::fetchResults()
LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
NULL, -1, mPickTransparent, &face_hit,
- &intersection, &uv, &normal, &tangent);
+ &intersection, &uv, &normal, &tangent, &start, &end);
mPickPt = mMousePt;
U32 te_offset = face_hit > -1 ? face_hit : 0;
- //unproject relative clicked coordinate from window coordinate using GL
-
+ if (mPickParticle)
+ { //get the end point of line segement to use for particle raycast
+ if (hit_object)
+ {
+ particle_end = intersection;
+ }
+ else
+ {
+ particle_end = end;
+ }
+ }
+
LLViewerObject* objectp = hit_object;
@@ -5199,6 +5244,7 @@ void LLPickInfo::fetchResults()
mHUDIcon = hit_icon;
mPickType = PICK_ICON;
mPosGlobal = mHUDIcon->getPositionGlobal();
+
}
else if (objectp)
{
@@ -5248,6 +5294,18 @@ void LLPickInfo::fetchResults()
}
}
+ if (mPickParticle)
+ { //search for closest particle to click origin out to intersection point
+ S32 part_face = -1;
+
+ LLVOPartGroup* group = gPipeline.lineSegmentIntersectParticle(start, particle_end, NULL, &part_face);
+ if (group)
+ {
+ mParticleOwnerID = group->getPartOwner(part_face);
+ mParticleSourceID = group->getPartSource(part_face);
+ }
+ }
+
if (mPickCallback)
{
mPickCallback(*this);
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 89f6e3bc26..c16b80b214 100755
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -65,6 +65,7 @@ class LLWindow;
class LLRootView;
class LLWindowListener;
class LLViewerWindowListener;
+class LLVOPartGroup;
class LLPopupView;
#define PICK_HALF_WIDTH 5
@@ -87,7 +88,8 @@ public:
LLPickInfo();
LLPickInfo(const LLCoordGL& mouse_pos,
MASK keyboard_mask,
- BOOL pick_transparent,
+ BOOL pick_transparent,
+ BOOL pick_particle,
BOOL pick_surface_info,
void (*pick_callback)(const LLPickInfo& pick_info));
@@ -108,6 +110,8 @@ public:
LLVector3d mPosGlobal;
LLVector3 mObjectOffset;
LLUUID mObjectID;
+ LLUUID mParticleOwnerID;
+ LLUUID mParticleSourceID;
S32 mObjectFace;
LLHUDIcon* mHUDIcon;
LLVector3 mIntersection;
@@ -118,6 +122,7 @@ public:
LLVector4 mTangent;
LLVector3 mBinormal;
BOOL mPickTransparent;
+ BOOL mPickParticle;
void getSurfaceInfo();
private:
@@ -356,7 +361,7 @@ public:
void returnEmptyPicks();
void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), BOOL pick_transparent = FALSE);
- LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent);
+ LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_particle = FALSE);
LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
LLVector4a* intersection);
@@ -501,6 +506,8 @@ extern LLFrameTimer gAwayTriggerTimer; // how long the avatar has been away
extern LLViewerObject* gDebugRaycastObject;
extern LLVector4a gDebugRaycastIntersection;
+extern LLVOPartGroup* gDebugRaycastParticle;
+extern LLVector4a gDebugRaycastParticleIntersection;
extern LLVector2 gDebugRaycastTexCoord;
extern LLVector4a gDebugRaycastNormal;
extern LLVector4a gDebugRaycastTangent;
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 43a5ddba42..8ed86b4fd5 100755
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -193,8 +193,14 @@ void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
const LLVector3& pos_agent = getPositionAgent();
newMin.load3( (pos_agent - mScale).mV);
newMax.load3( (pos_agent + mScale).mV);
+
+ llassert(newMin.isFinite3());
+ llassert(newMax.isFinite3());
+
LLVector4a pos;
pos.load3(pos_agent.mV);
+
+ llassert(pos.isFinite3());
mDrawable->setPositionGroup(pos);
}
@@ -234,6 +240,37 @@ LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline)
const F32 MAX_PARTICLE_AREA_SCALE = 0.02f; // some tuned constant, limits on how much particle area to draw
+ LLUUID LLVOPartGroup::getPartOwner(S32 idx)
+ {
+ LLUUID ret = LLUUID::null;
+
+ if (idx < (S32) mViewerPartGroupp->mParticles.size())
+ {
+ ret = mViewerPartGroupp->mParticles[idx]->mPartSourcep->getOwnerUUID();
+ }
+
+ return ret;
+ }
+
+ LLUUID LLVOPartGroup::getPartSource(S32 idx)
+ {
+ LLUUID ret = LLUUID::null;
+
+ if (idx < (S32) mViewerPartGroupp->mParticles.size())
+ {
+ LLViewerPart* part = mViewerPartGroupp->mParticles[idx];
+ if (part && part->mPartSourcep.notNull() &&
+ part->mPartSourcep->mSourceObjectp.notNull())
+ {
+ LLViewerObject* source = part->mPartSourcep->mSourceObjectp;
+ ret = source->getID();
+ }
+ }
+
+ return ret;
+ }
+
+
F32 LLVOPartGroup::getPartSize(S32 idx)
{
if (idx < (S32) mViewerPartGroupp->mParticles.size())
@@ -316,6 +353,10 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
inv_camera_dist_squared = 1.f / camera_dist_squared;
else
inv_camera_dist_squared = 1.f;
+
+ llassert(llfinite(inv_camera_dist_squared));
+ llassert(!llisnan(inv_camera_dist_squared));
+
F32 area = part->mScale.mV[0] * part->mScale.mV[1] * inv_camera_dist_squared;
tot_area = llmax(tot_area, area);
@@ -387,20 +428,63 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
return TRUE;
}
-void LLVOPartGroup::getGeometry(S32 idx,
- LLStrider<LLVector4a>& verticesp,
- LLStrider<LLVector3>& normalsp,
- LLStrider<LLVector2>& texcoordsp,
- LLStrider<LLColor4U>& colorsp,
- LLStrider<U16>& indicesp)
+
+BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ S32 face,
+ BOOL pick_transparent,
+ S32* face_hit,
+ LLVector4a* intersection,
+ LLVector2* tex_coord,
+ LLVector4a* normal,
+ LLVector4a* bi_normal)
{
- if (idx >= (S32) mViewerPartGroupp->mParticles.size())
+ LLVector4a dir;
+ dir.setSub(end, start);
+
+ F32 closest_t = 2.f;
+ BOOL ret = FALSE;
+
+ for (U32 idx = 0; idx < mViewerPartGroupp->mParticles.size(); ++idx)
{
- return;
+ const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx]));
+
+ LLVector4a v[4];
+ LLStrider<LLVector4a> verticesp;
+ verticesp = v;
+
+ getGeometry(part, verticesp);
+
+ F32 a,b,t;
+ if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a,b,t) ||
+ LLTriangleRayIntersect(v[1], v[3], v[2], start, dir, a,b,t))
+ {
+ if (t >= 0.f &&
+ t <= 1.f &&
+ t < closest_t)
+ {
+ ret = TRUE;
+ closest_t = t;
+ if (face_hit)
+ {
+ *face_hit = idx;
+ }
+
+ if (intersection)
+ {
+ LLVector4a intersect = dir;
+ intersect.mul(closest_t);
+ intersection->setAdd(intersect, start);
+ }
+ }
+ }
}
- const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx]));
+ return ret;
+}
+void LLVOPartGroup::getGeometry(const LLViewerPart& part,
+ LLStrider<LLVector4a>& verticesp)
+{
LLVector4a part_pos_agent;
part_pos_agent.load3(part.mPosAgent.mV);
LLVector4a camera_agent;
@@ -452,8 +536,6 @@ void LLVOPartGroup::getGeometry(S32 idx,
up.mul(0.5f*part.mScale.mV[1]);
- LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis();
-
//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should)
// this works because there is actually a 4th float stored after the vertex position which is used as a texture index
// also, somebody please VECTORIZE THIS
@@ -472,6 +554,25 @@ void LLVOPartGroup::getGeometry(S32 idx,
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setAdd(ppamu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
+}
+
+
+
+void LLVOPartGroup::getGeometry(S32 idx,
+ LLStrider<LLVector4a>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U16>& indicesp)
+{
+ if (idx >= (S32) mViewerPartGroupp->mParticles.size())
+ {
+ return;
+ }
+
+ const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx]));
+
+ getGeometry(part, verticesp);
*colorsp++ = part.mColor;
*colorsp++ = part.mColor;
@@ -480,6 +581,7 @@ void LLVOPartGroup::getGeometry(S32 idx,
if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK))
{ //not fullbright, needs normal
+ LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis();
*normalsp++ = normal;
*normalsp++ = normal;
*normalsp++ = normal;
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index 42c1252d01..2befb01823 100755
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -69,11 +69,23 @@ public:
virtual void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax);
virtual U32 getPartitionType() const;
+ /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ S32 face,
+ BOOL pick_transparent,
+ S32* face_hit,
+ LLVector4a* intersection,
+ LLVector2* tex_coord,
+ LLVector4a* normal,
+ LLVector4a* tangent);
+
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent);
/*virtual*/ void updateTextures();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
+ void getGeometry(const LLViewerPart& part,
+ LLStrider<LLVector4a>& verticesp);
+
void getGeometry(S32 idx,
LLStrider<LLVector4a>& verticesp,
LLStrider<LLVector3>& normalsp,
@@ -83,6 +95,9 @@ public:
void updateFaceSize(S32 idx) { }
F32 getPartSize(S32 idx);
+ LLUUID getPartOwner(S32 idx);
+ LLUUID getPartSource(S32 idx);
+
void setViewerPartGroup(LLViewerPartGroup *part_groupp) { mViewerPartGroupp = part_groupp; }
LLViewerPartGroup* getViewerPartGroup() { return mViewerPartGroupp; }
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 3be1f52352..e6385dceea 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1113,7 +1113,13 @@ void LLVOVolume::sculpt()
S32 max_discard = mSculptTexture->getMaxDiscardLevel();
if (discard_level > max_discard)
- discard_level = max_discard; // clamp to the best we can do
+ {
+ discard_level = max_discard; // clamp to the best we can do
+ }
+ if(discard_level > MAX_DISCARD_LEVEL)
+ {
+ return; //we think data is not ready yet.
+ }
S32 current_discard = getVolume()->getSculptLevel() ;
if(current_discard < -2)
@@ -1452,7 +1458,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
continue;
}
res &= face->genVolumeBBoxes(*volume, i,
- mRelativeXform, mRelativeXformInvTrans,
+ mRelativeXform,
(mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
if (rebuild)
@@ -4833,7 +4839,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (is_rigged)
{
- drawablep->setState(LLDrawable::RIGGED);
+ if (!drawablep->isState(LLDrawable::RIGGED))
+ {
+ drawablep->setState(LLDrawable::RIGGED);
+
+ //first time this is drawable is being marked as rigged,
+ // do another LoD update to use avatar bounding box
+ vobj->updateLOD();
+ }
}
else
{
diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp
index 28f959eb71..a8e06511d7 100755
--- a/indra/newview/llwindowlistener.cpp
+++ b/indra/newview/llwindowlistener.cpp
@@ -265,7 +265,9 @@ void LLWindowListener::getPaths(LLSD const & request)
void LLWindowListener::keyDown(LLSD const & evt)
{
Response response(LLSD(), evt);
-
+ KEY key = getKEY(evt);
+ MASK mask = getMask(evt);
+
if (evt.has("path"))
{
std::string path(evt["path"]);
@@ -280,8 +282,6 @@ void LLWindowListener::keyDown(LLSD const & evt)
response.setResponse(target_view->getInfo());
gFocusMgr.setKeyboardFocus(target_view);
- KEY key = getKEY(evt);
- MASK mask = getMask(evt);
gViewerKeyboard.handleKey(key, mask, false);
if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
}
@@ -294,7 +294,8 @@ void LLWindowListener::keyDown(LLSD const & evt)
}
else
{
- mKbGetter()->handleTranslatedKeyDown(getKEY(evt), getMask(evt));
+ gViewerKeyboard.handleKey(key, mask, false);
+ if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
}
}
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index 5fa380e0e3..bfae142812 100755
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -522,6 +522,17 @@ bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID&
tooltip_fmt.setArg("[AREA]", llformat("%d", extra));
tooltip_fmt.setArg("[PRICE]", llformat("%d", extra2));
+
+ // Check for division by zero
+ if (extra != 0)
+ {
+ tooltip_fmt.setArg("[SQMPRICE]", llformat("%.1f", (F32)extra2 / (F32)extra));
+ }
+ else
+ {
+ tooltip_fmt.setArg("[SQMPRICE]", LLTrans::getString("Unknown"));
+ }
+
new_item.setTooltip(tooltip_fmt.getString());
if (type == MAP_ITEM_LAND_FOR_SALE)
diff --git a/indra/newview/macutil_Prefix.h b/indra/newview/macutil_Prefix.h
index b54a764a62..b8df961cac 100755
--- a/indra/newview/macutil_Prefix.h
+++ b/indra/newview/macutil_Prefix.h
@@ -32,7 +32,6 @@
*
*/
-#include <Carbon/Carbon.h>
#include "fix_macros.h"
#undef verify
diff --git a/indra/newview/noise.h b/indra/newview/noise.h
index 0923bffcf2..b3efad73c5 100755
--- a/indra/newview/noise.h
+++ b/indra/newview/noise.h
@@ -310,6 +310,8 @@ static void normalize3(F32 v[3])
static void init(void)
{
+ // we want repeatable noise (e.g. for stable terrain texturing), so seed with known value
+ srand(42);
int i, j, k;
for (i = 0 ; i < B ; i++) {
@@ -340,6 +342,9 @@ static void init(void)
for (j = 0 ; j < 3 ; j++)
g3[B + i][j] = g3[i][j];
}
+
+ // reintroduce entropy
+ srand(time(NULL)); // Flawfinder: ignore
}
#undef B
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index c25d22bbdf..f49395da34 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -163,6 +163,7 @@ S32 LLPipeline::RenderGlowIterations;
F32 LLPipeline::RenderGlowWidth;
F32 LLPipeline::RenderGlowStrength;
BOOL LLPipeline::RenderDepthOfField;
+BOOL LLPipeline::RenderDepthOfFieldInEditMode;
F32 LLPipeline::CameraFocusTransitionTime;
F32 LLPipeline::CameraFNumber;
F32 LLPipeline::CameraFocalLength;
@@ -615,6 +616,7 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("RenderGlowWidth");
connectRefreshCachedSettingsSafe("RenderGlowStrength");
connectRefreshCachedSettingsSafe("RenderDepthOfField");
+ connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode");
connectRefreshCachedSettingsSafe("CameraFocusTransitionTime");
connectRefreshCachedSettingsSafe("CameraFNumber");
connectRefreshCachedSettingsSafe("CameraFocalLength");
@@ -1125,6 +1127,7 @@ void LLPipeline::refreshCachedSettings()
RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth");
RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength");
RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
+ RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode");
CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime");
CameraFNumber = gSavedSettings.getF32("CameraFNumber");
CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");
@@ -4864,18 +4867,6 @@ void LLPipeline::renderPhysicsDisplay()
}
}
- for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
- {
- LLSpatialBridge* bridge = *i;
- if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
- {
- gGL.pushMatrix();
- gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
- bridge->renderPhysicsShapes();
- gGL.popMatrix();
- }
- }
-
gGL.flush();
if (LLGLSLShader::sNoFixedFunction)
@@ -5323,6 +5314,42 @@ void LLPipeline::renderDebug()
gUIProgram.bind();
}
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only)
+ { //draw crosshairs on particle intersection
+ if (gDebugRaycastParticle)
+ {
+ if (LLGLSLShader::sNoFixedFunction)
+ { //this debug display requires shaders
+ gDebugProgram.bind();
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr());
+ LLVector3 size(0.1f, 0.1f, 0.1f);
+
+ LLVector3 p[6];
+
+ p[0] = center + size.scaledVec(LLVector3(1,0,0));
+ p[1] = center + size.scaledVec(LLVector3(-1,0,0));
+ p[2] = center + size.scaledVec(LLVector3(0,1,0));
+ p[3] = center + size.scaledVec(LLVector3(0,-1,0));
+ p[4] = center + size.scaledVec(LLVector3(0,0,1));
+ p[5] = center + size.scaledVec(LLVector3(0,0,-1));
+
+ gGL.begin(LLRender::LINES);
+ gGL.diffuseColor3f(1.f, 1.f, 0.f);
+ for (U32 i = 0; i < 6; i++)
+ {
+ gGL.vertex3fv(p[i].mV);
+ }
+ gGL.end();
+ gGL.flush();
+
+ gDebugProgram.unbind();
+ }
+ }
+ }
+
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
LLVertexBuffer::unbind();
@@ -5356,7 +5383,7 @@ void LLPipeline::renderDebug()
if (i > 3)
{ //render shadow frusta as volumes
if (mShadowFrustPoints[i-4].empty())
- {
+ {
continue;
}
@@ -7003,6 +7030,48 @@ void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel)
sRenderHighlightTextureChannel = channel;
}
+LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection,
+ S32* face_hit)
+{
+ LLVector4a local_end = end;
+
+ LLVector4a position;
+
+ LLDrawable* drawable = NULL;
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE);
+ if (part && hasRenderType(part->mDrawableType))
+ {
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, face_hit, &position, NULL, NULL, NULL);
+ if (hit)
+ {
+ drawable = hit;
+ local_end = position;
+ }
+ }
+ }
+
+ LLVOPartGroup* ret = NULL;
+ if (drawable)
+ {
+ //make sure we're returning an LLVOPartGroup
+ llassert(drawable->getVObj()->getPCode() == LLViewerObject::LL_VO_PART_GROUP);
+ ret = (LLVOPartGroup*) drawable->getVObj().get();
+ }
+
+ if (intersection)
+ {
+ *intersection = position;
+ }
+
+ return ret;
+}
+
LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
S32* face_hit,
@@ -7562,7 +7631,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
{
bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
- !LLToolMgr::getInstance()->inBuildMode() &&
+ (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
RenderDepthOfField;
@@ -9582,7 +9651,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector
pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2]));
//add corners of camera frustum
- for (U32 i = 0; i < 8; i++)
+ for (U32 i = 0; i < LLCamera::AGENT_FRUSTRUM_NUM; i++)
{
pp.push_back(camera.mAgentFrustum[i]);
}
@@ -9609,7 +9678,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector
for (U32 i = 0; i < 12; i++)
{ //for each line segment in bounding box
- for (U32 j = 0; j < 6; j++)
+ for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; j++)
{ //for each plane in camera frustum
const LLPlane& cp = camera.getAgentPlane(j);
const LLVector3& v1 = pp[bs[i*2+0]];
@@ -9695,19 +9764,19 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector
}
}
- for (U32 j = 0; j < 6; ++j)
+ for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; ++j)
{
const LLPlane& cp = camera.getAgentPlane(j);
F32 dist = cp.dist(pp[i]);
if (dist > 0.05f) //point is above some plane, not contained
- {
+ {
found = false;
break;
- }
- }
+ }
+ }
- if (found)
- {
+ if (found)
+ {
fp.push_back(pp[i]);
}
}
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 70dcf80407..f0bebbe20d 100755
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -58,6 +58,7 @@ class LLRenderFunc;
class LLCubeMap;
class LLCullResult;
class LLVOAvatar;
+class LLVOPartGroup;
class LLGLSLShader;
class LLCurlRequest;
class LLDrawPoolAlpha;
@@ -202,6 +203,12 @@ public:
LLVector4a* normal = NULL, // return the surface normal at the intersection point
LLVector4a* tangent = NULL // return the surface tangent at the intersection point
);
+
+ //get the closest particle to start between start and end, returns the LLVOPartGroup and particle index
+ LLVOPartGroup* lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection,
+ S32* face_hit);
+
+
LLViewerObject* lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
S32* face_hit, // return the face hit
@@ -910,6 +917,7 @@ public:
static F32 RenderGlowWidth;
static F32 RenderGlowStrength;
static BOOL RenderDepthOfField;
+ static BOOL RenderDepthOfFieldInEditMode;
static F32 CameraFocusTransitionTime;
static F32 CameraFNumber;
static F32 CameraFocalLength;
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index a9176595c7..f53995732f 100755
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -884,4 +884,19 @@
<color
name="blue"
value="0 0 1 1"/>
+
+ <!--Resize bar colors -->
+
+ <color
+ name="ResizebarBorderLight"
+ value="0.231 0.231 0.231 1"/>
+
+ <color
+ name="ResizebarBorderDark"
+ value="0.133 0.133 0.133 1"/>
+
+ <color
+ name="ResizebarBody"
+ value="0.208 0.208 0.208 1"/>
+
</colors>
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index b0e4b71d21..54f60f4441 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -774,4 +774,7 @@ with the same filename but different name
<texture name="Popup_Caution" file_name="icons/pop_up_caution.png"/>
<texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
<texture name="NavBar Separator" file_name="navbar/separator.png"/>
+
+ <texture name="Horizontal Drag Handle" file_name="widgets/horizontal_drag_handle.png"/>
+ <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png"/>
</textures>
diff --git a/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png
new file mode 100644
index 0000000000..642eac4065
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png
new file mode 100644
index 0000000000..b06b70cf36
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml
index fc8bc33096..9206690c8f 100755
--- a/indra/newview/skins/default/xui/da/floater_about.xml
+++ b/indra/newview/skins/default/xui/da/floater_about.xml
@@ -8,7 +8,7 @@
Bygget med [COMPILER] version [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Du er ved [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] i regionen [REGION] lokaliseret ved &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml
index 4387a61963..5245467183 100755
--- a/indra/newview/skins/default/xui/de/floater_about.xml
+++ b/indra/newview/skins/default/xui/de/floater_about.xml
@@ -8,7 +8,7 @@
Kompiliert mit [COMPILER] version [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Sie befinden sich in [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] auf &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Sie befinden sich in [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 63eb87f27a..703015af20 100755
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -22,7 +22,9 @@ Built with [COMPILER] version [COMPILER_VERSION]
</floater.string>
<floater.string
name="AboutPosition">
-You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
+(global coordinates [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 793a6e6fa1..a660e812cc 100755
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1365,7 +1365,7 @@ Only large parcels can be listed in search.
<combo_box.item
label="Any Category"
name="item0"
- value="any" />
+ value="none" />
<combo_box.item
label="Linden Location"
name="item1"
diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
index 4e0cfb0cd4..e7ab3cacdc 100755
--- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
@@ -6,7 +6,7 @@
layout="topleft"
name="floaterbulkperms"
help_topic="floaterbulkperms"
- title="EDIT CONTENT PERMISSIONS"
+ title="ADJUST CONTENT PERMISSIONS"
width="410">
<floater.string
name="nothing_to_modify_text">
@@ -192,7 +192,7 @@
name="newperms"
top="90"
width="250">
- New Content Permissions
+ Adjust Content Permissions To
</text>
<text
type="string"
@@ -292,11 +292,22 @@
height="23"
label="OK"
layout="topleft"
- left="205"
- name="apply"
+ left="110"
+ name="ok"
top_pad="10"
width="90">
<button.commit_callback
+ function="BulkPermission.Ok"/>
+ </button>
+ <button
+ follows="left|top"
+ height="23"
+ label="Apply"
+ layout="topleft"
+ left_pad="5"
+ name="apply"
+ width="90">
+ <button.commit_callback
function="BulkPermission.Apply"/>
</button>
<button
diff --git a/indra/newview/skins/default/xui/en/floater_goto_line.xml b/indra/newview/skins/default/xui/en/floater_goto_line.xml
new file mode 100644
index 0000000000..b236888219
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_goto_line.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ default_tab_group="1"
+ height="90"
+ layout="topleft"
+ name="script goto"
+ help_topic="script_goto"
+ title="GO TO LINE"
+ width="200">
+ <button
+ height="24"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ left="55"
+ name="goto_btn"
+ top="53"
+ width="90" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="txt"
+ top="21"
+ width="65">
+ Go to line
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="75"
+ max_length_bytes="9"
+ name="goto_line"
+ tab_group="1"
+ top="21"
+ width="85" />
+</floater> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index 65f623a47e..1215efb7f9 100755
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -4,6 +4,7 @@
can_minimize="true"
can_resize="true"
height="210"
+ min_height="210"
layout="topleft"
name="floater_im_box"
help_topic="floater_im_box"
@@ -24,24 +25,28 @@
value="Conv_toolbar_expand"/>
<layout_stack
animate="true"
- bottom="-1"
+ bottom="-5"
+ drag_handle_gap="6"
+ drag_handle_first_indent="27"
+ drag_handle_second_indent="10"
follows="all"
layout="topleft"
left="0"
name="conversations_stack"
orientation="horizontal"
right="-1"
+ show_drag_handle="true"
top="0">
<layout_panel
auto_resize="false"
user_resize="true"
name="conversations_layout_panel"
min_dim="38"
- expanded_min_dim="156">
+ expanded_min_dim="136">
<layout_stack
animate="false"
follows="left|top|right"
- height="35"
+ height="27"
layout="topleft"
left="0"
name="conversations_pane_buttons_stack"
@@ -50,7 +55,6 @@
top="0">
<layout_panel
auto_resize="true"
- height="35"
name="conversations_pane_buttons_expanded">
<menu_button
follows="top|left"
@@ -64,7 +68,7 @@
left="5"
name="sort_btn"
tool_tip="View/sort options"
- top="5"
+ top="1"
width="31" />
<button
follows="top|left"
@@ -74,7 +78,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="add_btn"
tool_tip="Start a new conversation"
@@ -87,7 +91,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="speak_btn"
tool_tip="Speak with people using your microphone"
@@ -95,9 +99,8 @@
</layout_panel>
<layout_panel
auto_resize="false"
- height="35"
name="conversations_pane_buttons_collapsed"
- width="41">
+ width="31">
<button
follows="right|top"
height="25"
@@ -106,8 +109,8 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
- left="1"
+ top="1"
+ left="0"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this list"
width="31" />
@@ -119,7 +122,7 @@
layout="topleft"
name="conversations_list_panel"
opaque="true"
- top="35"
+ top_pad="0"
left="5"
right="-1"/>
</layout_panel>
@@ -127,7 +130,7 @@
auto_resize="true"
user_resize="true"
name="messages_layout_panel"
- expanded_min_dim="222">
+ expanded_min_dim="212">
<panel_container
bottom="-1"
follows="all"
@@ -136,44 +139,44 @@
name="im_box_tab_container"
right="-1"
top="0">
- <panel
- bottom="-1"
- follows="all"
- layout="topleft"
- name="stub_panel"
- opaque="true"
- top_pad="0"
- left="0"
- right="-1">
- <button
- follows="right|top"
- height="25"
- image_hover_unselected="Toolbar_Middle_Over"
- image_overlay="Conv_toolbar_collapse"
- image_selected="Toolbar_Middle_Selected"
- image_unselected="Toolbar_Middle_Off"
+ <panel
+ bottom="-1"
+ follows="all"
layout="topleft"
- top="5"
- right="-10"
- name="stub_collapse_btn"
- tool_tip="Collapse this pane"
- width="31" />
- <text
- type="string"
- clip_partial="false"
- follows="left|top|right"
- layout="topleft"
- left="15"
- right="-15"
- name="stub_textbox"
- top="25"
- height="40"
- valign="center"
- parse_urls="true"
- wrap="true">
- This conversation is in a separate window. [secondlife:/// Bring it back.]
- </text>
- </panel>
+ name="stub_panel"
+ opaque="true"
+ top_pad="0"
+ left="0"
+ right="-1">
+ <button
+ follows="right|top"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Conv_toolbar_collapse"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="1"
+ right="-10"
+ name="stub_collapse_btn"
+ tool_tip="Collapse this pane"
+ width="31" />
+ <text
+ type="string"
+ clip_partial="false"
+ follows="left|top|right"
+ layout="topleft"
+ left="15"
+ right="-15"
+ name="stub_textbox"
+ top="25"
+ height="40"
+ valign="center"
+ parse_urls="true"
+ wrap="true">
+ This conversation is in a separate window. [secondlife:/// Bring it back.]
+ </text>
+ </panel>
</panel_container>
</layout_panel>
</layout_stack>
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 2152a9f6e9..43d0f2fb18 100755
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -70,26 +70,23 @@
top="0"
left="0"
right="-1"
- bottom="-3">
+ bottom="-1">
<layout_stack
animate="false"
+ bottom="-1"
default_tab_group="2"
follows="all"
- right="-5"
- bottom="-1"
- top="0"
- left="5"
- border_size="0"
+ left="3"
layout="topleft"
- orientation="vertical"
name="main_stack"
- tab_group="1">
+ right="-3"
+ orientation="vertical"
+ tab_group="1"
+ top="0">
<layout_panel
auto_resize="false"
name="toolbar_panel"
- height="35"
- right="-1"
- left="1">
+ height="25">
<menu_button
menu_filename="menu_im_session_showmodes.xml"
follows="top|left"
@@ -102,7 +99,7 @@
left="5"
name="view_options_btn"
tool_tip="View/sort options"
- top="5"
+ top="1"
width="31" />
<menu_button
menu_filename="menu_im_conversation.xml"
@@ -113,7 +110,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="gear_btn"
visible="false"
@@ -128,7 +125,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="add_btn"
tool_tip="Add someone to this conversation"
@@ -141,23 +138,11 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="voice_call_btn"
tool_tip="Open voice connection"
- width="31"/>
- <output_monitor
- auto_update="true"
- follows="top|left"
- draw_border="false"
- height="16"
- layout="topleft"
- top="10"
- left_pad="10"
- mouse_opaque="true"
- name="speaking_indicator"
- visible="false"
- width="20" />
+ width="31"/>
<button
follows="right|top"
height="25"
@@ -166,8 +151,8 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
- right="-67"
+ top="1"
+ right="-70"
name="close_btn"
tool_tip="End this conversation"
width="31" />
@@ -179,7 +164,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this pane"
@@ -194,18 +179,21 @@
layout="topleft"
left_pad="2"
name="tear_off_btn"
- top="5"
+ top="1"
width="31" />
</layout_panel>
<layout_panel
name="body_panel"
- top="1"
- bottom="-1">
+ height="235">
<layout_stack
default_tab_group="2"
+ drag_handle_gap="6"
+ drag_handle_first_indent="0"
+ drag_handle_second_indent="1"
follows="all"
orientation="horizontal"
name="im_panels"
+ show_drag_handle="true"
tab_group="1"
top="0"
right="-1"
@@ -217,14 +205,12 @@
min_dim="0"
width="150"
user_resize="true"
- auto_resize="false"
- bottom="-1" />
+ auto_resize="false" />
<layout_panel
default_tab_group="3"
tab_group="2"
name="right_part_holder"
- min_width="221"
- bottom="-1">
+ min_width="172">
<layout_stack
animate="true"
default_tab_group="2"
@@ -233,7 +219,7 @@
name="translate_and_chat_stack"
tab_group="1"
top="0"
- left="0"
+ left="1"
right="-1"
bottom="-1">
<layout_panel
@@ -259,7 +245,7 @@
parse_highlights="true"
parse_urls="true"
right="-1"
- left="5"
+ left="0"
top="0"
bottom="-1" />
</layout_panel>
@@ -268,10 +254,7 @@
</layout_stack>
</layout_panel>
<layout_panel
- top_delta="0"
- top="0"
- height="26"
- bottom="-1"
+ height="35"
auto_resize="false"
name="chat_layout_panel">
<layout_stack
@@ -281,15 +264,11 @@
orientation="horizontal"
name="input_panels"
top="0"
- bottom="-2"
+ bottom="-1"
left="0"
right="-1">
<layout_panel
- name="input_editor_layout_panel"
- auto_resize="true"
- user_resize="false"
- top="0"
- bottom="-1">
+ name="input_editor_layout_panel">
<chat_editor
layout="topleft"
expand_lines_count="5"
@@ -302,32 +281,27 @@
max_length="1023"
spellcheck="true"
tab_group="3"
- top="1"
- bottom="-2"
- left="4"
- right="-4"
+ bottom="-8"
+ left="5"
+ right="-5"
wrap="true" />
</layout_panel>
<layout_panel
auto_resize="false"
- user_resize="false"
name="input_button_layout_panel"
- width="30"
- top="0"
- bottom="-1">
+ width="32">
<button
- layout="topleft"
left="1"
- right="-1"
- top="1"
- height="22"
+ top="4"
+ height="25"
follows="left|right|top"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Conv_expand_one_line"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="minz_btn"
- tool_tip="Shows/hides message panel" />
+ tool_tip="Shows/hides message panel"
+ width="28" />
</layout_panel>
</layout_stack>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
index 46ba4bd29d..0a8beec7de 100755
--- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
@@ -112,4 +112,15 @@
<menu_item_call.on_enable
function="Object.EnableInspect" />
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Block Particle Owner"
+ name="Mute Particle">
+ <menu_item_call.on_click
+ function="Particle.Mute" />
+ <menu_item_call.on_enable
+ function="EnableMuteParticle" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index 28e032ce5f..bcbc8d5b86 100755
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -143,4 +143,15 @@ name="Edit Outfit">
<menu_item_call.on_enable
function="Attachment.EnableDrop" />
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Block Particle Owner"
+ name="Mute Particle">
+ <menu_item_call.on_click
+ function="Particle.Mute" />
+ <menu_item_call.on_enable
+ function="EnableMuteParticle" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
index e7c2b80da2..8be2683680 100755
--- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
@@ -103,4 +103,15 @@
<menu_item_call.on_enable
function="EnablePayAvatar" />
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Block Particle Owner"
+ name="Mute Particle">
+ <menu_item_call.on_click
+ function="Particle.Mute" />
+ <menu_item_call.on_enable
+ function="EnableMuteParticle" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index c1ff026a74..ca0c9bd5e4 100755
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -269,4 +269,16 @@
<menu_item_call.on_visible
function="Advanced.EnableAppearanceToXML"/>
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Block Particle Owner"
+ name="Mute Particle">
+ <menu_item_call.on_click
+ function="Particle.Mute" />
+
+ <menu_item_call.on_enable
+ function="EnableMuteParticle" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
index 5a13ef0a59..31b1d091ee 100755
--- a/indra/newview/skins/default/xui/en/menu_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation.xml
@@ -11,7 +11,7 @@
layout="topleft"
name="close_conversation">
<on_click function="Avatar.DoToSelected" parameter="close_conversation"/>
- </menu_item_call>
+ </menu_item_call>
<menu_item_call
label="Open voice conversation"
layout="topleft"
@@ -25,6 +25,12 @@
<on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/>
</menu_item_call>
<menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/>
+ <menu_item_call
+ label="Close Selected"
+ layout="topleft"
+ name="close_selected_conversations">
+ <on_click function="Avatar.DoToSelected" parameter="close_selected_conversations"/>
+ </menu_item_call>
<menu_item_call
label="View Profile"
layout="topleft"
@@ -47,6 +53,13 @@
<on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/>
</menu_item_call>
<menu_item_call
+ label="Request teleport"
+ layout="topleft"
+ name="request_teleport">
+ <on_click function="Avatar.DoToSelected" parameter="request_teleport"/>
+ <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/>
+ </menu_item_call>
+ <menu_item_call
label="Voice call"
layout="topleft"
name="voice_call">
diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml
index 8796b87955..a1a3afbf68 100755
--- a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml
@@ -56,6 +56,16 @@
function="Calllog.Enable"
parameter="can_offer_teleport"/>
</menu_item_call>
+ <menu_item_call
+ label="Request Teleport"
+ name="request_teleport">
+ <on_click
+ function="Calllog.Action"
+ parameter="request_teleport"/>
+ <on_enable
+ function="Calllog.Enable"
+ parameter="can_offer_teleport"/>
+ </menu_item_call>
<menu_item_separator />
<menu_item_call
label="Add Friend"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 13dc0b941a..512205ba43 100755
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -591,6 +591,14 @@
parameter="lure" />
</menu_item_call>
<menu_item_call
+ label="Request Teleport..."
+ layout="topleft"
+ name="Request Teleport...">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="request_lure" />
+ </menu_item_call>
+ <menu_item_call
label="Start Conference Chat"
layout="topleft"
name="Conference Chat">
diff --git a/indra/newview/skins/default/xui/en/menu_land.xml b/indra/newview/skins/default/xui/en/menu_land.xml
index cc6d8ad9c1..2ad5cbbe95 100755
--- a/indra/newview/skins/default/xui/en/menu_land.xml
+++ b/indra/newview/skins/default/xui/en/menu_land.xml
@@ -61,4 +61,15 @@
<menu_item_call.on_enable
function="EnableEdit" />
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Block Particle Owner"
+ name="Mute Particle">
+ <menu_item_call.on_click
+ function="Particle.Mute" />
+ <menu_item_call.on_enable
+ function="EnableMuteParticle" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_mute_particle.xml b/indra/newview/skins/default/xui/en/menu_mute_particle.xml
new file mode 100644
index 0000000000..a4261bf39e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_mute_particle.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- *NOTE: See also menu_attachment_other.xml -->
+<context_menu
+ layout="topleft"
+ name="Mute Particle Pie">
+ <menu_item_call
+ enabled="false"
+ label="Block Particle Owner"
+ name="Mute Particle">
+ <menu_item_call.on_click
+ function="Particle.Mute" />
+ <menu_item_call.on_enable
+ function="EnableMuteParticle" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index f6004621a6..52ab7da515 100755
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -196,4 +196,15 @@
<menu_item_call.on_enable
function="Object.EnableDelete" />
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Block Particle Owner"
+ name="Mute Particle">
+ <menu_item_call.on_click
+ function="Particle.Mute" />
+ <menu_item_call.on_enable
+ function="EnableMuteParticle" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml
index dde9432867..8790fde7c5 100755
--- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml
@@ -44,6 +44,8 @@
<menu_item_check.on_check
function="Floater.Visible"
parameter="conversation" />
+ <menu_item_check.on_enable
+ function="Conversation.IsConversationLoggingAllowed" />
<menu_item_check.on_click
function="Floater.Toggle"
parameter="conversation" />
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
index 3abb5f7bc8..f12226ebeb 100755
--- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
@@ -29,6 +29,15 @@
parameter="can_offer_teleport"/>
</menu_item_call>
<menu_item_call
+ label="Request Teleport"
+ name="request_teleport">
+ <menu_item_call.on_click
+ function="Avatar.TeleportRequest"/>
+ <menu_item_call.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_offer_teleport"/>
+ </menu_item_call>
+ <menu_item_call
label="Voice call"
layout="topleft"
name="voice_call">
@@ -134,5 +143,4 @@
function="Avatar.EnableItem"
parameter="can_block" />
</menu_item_check>
- <menu_item_separator />
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml
index 7cd56f257a..e8b6116026 100755
--- a/indra/newview/skins/default/xui/en/menu_url_agent.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml
@@ -21,8 +21,15 @@
layout="topleft"
name="add_friend">
<menu_item_call.on_click
- function="Url.AddFriend" />
+ function="Url.AddFriend" />
</menu_item_call>
+ <menu_item_call
+ label="Remove Friend..."
+ layout="topleft"
+ name="remove_friend">
+ <menu_item_call.on_click
+ function="Url.RemoveFriend" />
+ </menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
index 87ab58e622..b9d003b841 100755
--- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
@@ -9,6 +9,13 @@
<menu_item_call.on_click
function="Url.Execute" />
</menu_item_call>
+ <menu_item_call
+ label="Block..."
+ layout="topleft"
+ name="block_object">
+ <menu_item_call.on_click
+ function="Url.Block" />
+ </menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index b01c3067ff..dabfc4eebd 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -874,6 +874,15 @@
function="Tools.EnableSelectNextPart" />
</menu_item_call>
</menu>
+ <menu_item_call
+ label="Linksets..."
+ name="pathfinding_linkset_menu_item">
+ <menu_item_call.on_click
+ function="Floater.ToggleOrBringToFront"
+ parameter="pathfinding_linksets" />
+ <menu_item_call.on_enable
+ function="Tools.EnablePathfinding" />
+ </menu_item_call>
<menu_item_separator/>
<menu_item_call
@@ -896,7 +905,7 @@
<menu_item_call.on_enable
function="Tools.SomethingSelectedNoHUD" />
</menu_item_call>
-
+
<menu_item_separator/>
<menu
@@ -2919,6 +2928,34 @@
label="Recorder"
name="Recorder"
tear_off="true">
+ <menu_item_call visible="false"
+ label="Start event recording"
+ name="Start event recording">
+ <menu_item_call.on_visible
+ function="displayViewerEventRecorderMenuItems" />
+ <menu_item_call.on_click
+ function="Advanced.EventRecorder"
+ parameter="start recording" />
+ </menu_item_call>
+ <menu_item_call visible="false"
+ label="Stop event recording"
+ name="Stop event recording">
+ <menu_item_call.on_visible
+ function="displayViewerEventRecorderMenuItems" />
+ <menu_item_call.on_click
+ function="Advanced.EventRecorder"
+ parameter="stop recording" />
+ </menu_item_call>
+ <menu_item_call visible="false"
+ label="Playback event recording"
+ name="Playback event recording">
+ <menu_item_call.on_visible
+ function="displayViewerEventRecorderMenuItems" />
+ <menu_item_call.on_click
+ function="Advanced.EventRecorder"
+ parameter="start playback" />
+ </menu_item_call>
+
<menu_item_call
label="Start Playback"
name="Start Playback">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 9e582cf0de..fce21b403b 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -506,6 +506,33 @@ Add this Ability to &apos;[ROLE_NAME]&apos;?
notext="No"
yestext="Yes"/>
</notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="EjectGroupMemberWarning"
+ type="alertmodal">
+ You are about to eject [AVATAR_NAME] from the group.
+ <tag>group</tag>
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm ejecting a participant from group"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Eject"/>
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="EjectGroupMembersWarning"
+ type="alertmodal">
+ You are about to eject [COUNT] members from the group.
+ <tag>group</tag>
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm ejecting multiple members from group"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Eject"/>
+ </notification>
<notification
icon="alertmodal.tga"
@@ -2682,7 +2709,7 @@ Please enter a higher price.
icon="alertmodal.tga"
name="ConfirmItemDeleteHasLinks"
type="alertmodal">
-At least one of the items you has link items that point to it. If you delete this item, its links will permanently stop working. It is strongly advised to delete the links first.
+At least one of the items has links that point to it. If you delete this item, its links will permanently stop working. It is strongly advised to delete the links first.
Are you sure you want to delete these items?
<tag>confirm</tag>
@@ -2724,7 +2751,7 @@ Are you sure you want to delete these items?
icon="alertmodal.tga"
name="ConfirmObjectDeleteNoOwn"
type="alertmodal">
-You do not own least one of the items you have selected.
+You do not own at least one of the items you have selected.
Are you sure you want to delete these items?
<tag>confirm</tag>
@@ -2754,7 +2781,7 @@ Are you sure you want to delete these items?
name="ConfirmObjectDeleteLockNoOwn"
type="alertmodal">
At least one object is locked.
-You do not own least one object.
+You do not own at least one object.
Are you sure you want to delete these items?
<tag>confirm</tag>
@@ -2769,7 +2796,7 @@ Are you sure you want to delete these items?
name="ConfirmObjectDeleteNoCopyNoOwn"
type="alertmodal">
At least one object is not copyable.
-You do not own least one object.
+You do not own at least one object.
Are you sure you want to delete these items?
<tag>confirm</tag>
@@ -2785,13 +2812,13 @@ Are you sure you want to delete these items?
type="alertmodal">
At least one object is locked.
At least one object is not copyable.
-You do not own least one object.
+You do not own at least one object.
Are you sure you want to delete these items?
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
- notext="cancel"
+ notext="Cancel"
yestext="OK"/>
</notification>
@@ -3709,6 +3736,17 @@ Leave Group?
</notification>
<notification
+ icon="alertmodal.tga"
+ name="OwnerCannotLeaveGroup"
+ type="alertmodal">
+ Unable to leave group. You cannot leave the group because you are the last owner of the group. Please assign another member to the owner role first.
+ <tag>group</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alert.tga"
name="ConfirmKick"
type="alert">
@@ -4033,6 +4071,27 @@ Join me in [REGION]
<notification
icon="alertmodal.tga"
+ name="TeleportRequestPrompt"
+ type="alertmodal">
+Request a teleport to [NAME] with the following message
+ <tag>confirm</tag>
+ <form name="form">
+ <input name="message" type="text">
+
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+ <notification
+ icon="alertmodal.tga"
name="TooManyTeleportOffers"
type="alertmodal">
You attempted to make [OFFERS] teleport offers
@@ -5943,9 +6002,7 @@ Your calling card was declined.
icon="notifytip.tga"
name="TeleportToPerson"
type="notifytip">
- To contact Residents like &apos;[NAME]&apos;, click on the &quot;People&quot; button , select a Resident from the window that opens, then click &apos;IM&apos; at the
- bottom of the window.
- (You can also double-click on their name in the list, or right-click and choose &apos;IM&apos;).
+ To open a private conversation with someone, right-click on their avatar and choose &apos;IM&apos; from the menu.
</notification>
<notification
@@ -6573,7 +6630,7 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
icon="notify.tga"
name="JoinGroup"
persist="true"
- type="notify">
+ type="offer">
<tag>group</tag>
[MESSAGE]
<form name="form">
@@ -6601,7 +6658,7 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
sound="UISndNewIncomingIMSession">
[NAME_SLURL] has offered to teleport you to their location:
-“[MESSAGE]”
+"[MESSAGE]”
&lt;icon&gt;[MATURITY_ICON]&lt;/icon&gt; - [MATURITY_STR]
<tag>confirm</tag>
<form name="form">
@@ -6666,6 +6723,27 @@ However, this region contains content accessible to adults only.
Teleport offer sent to [TO_NAME]
</notification>
+ <notification
+ icon="notify.tga"
+ name="TeleportRequest"
+ log_to_im="true"
+ type="offer">
+[NAME_SLURL] is requesting to be teleported to your location.
+[MESSAGE]
+
+Offer a teleport?
+ <tag>confirm</tag>
+ <form name="form">
+ <button
+ index="0"
+ name="Yes"
+ text="Yes"/>
+ <button
+ index="1"
+ name="No"
+ text="No"/>
+ </form>
+ </notification>
<notification
icon="notify.tga"
@@ -6714,7 +6792,6 @@ However, this region contains content accessible to adults only.
icon="notify.tga"
name="FriendshipOffered"
log_to_im="true"
- show_toast="false"
type="notify">
<tag>friendship</tag>
You have offered friendship to [TO_NAME]
@@ -6764,7 +6841,6 @@ However, this region contains content accessible to adults only.
icon="notify.tga"
name="FriendshipAcceptedByMe"
log_to_im="true"
- show_toast="false"
type="notify">
<tag>friendship</tag>
Friendship offer accepted.
@@ -6774,7 +6850,6 @@ Friendship offer accepted.
icon="notify.tga"
name="FriendshipDeclinedByMe"
log_to_im="true"
- show_toast="false"
type="notify">
<tag>friendship</tag>
Friendship offer declined.
@@ -6804,7 +6879,6 @@ This will add a bookmark in your inventory so you can quickly IM this Resident.
name="RegionRestartMinutes"
priority="high"
sound="UISndAlert"
- persist="true"
type="notify">
This region will restart in [MINUTES] minutes.
If you stay in this region you will be logged out.
@@ -6815,7 +6889,6 @@ If you stay in this region you will be logged out.
name="RegionRestartSeconds"
priority="high"
sound="UISndAlert"
- persist="true"
type="notify">
This region will restart in [SECONDS] seconds.
If you stay in this region you will be logged out.
diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml
index 6d5fb51e85..c8ce5cdebf 100755
--- a/indra/newview/skins/default/xui/en/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml
@@ -202,14 +202,14 @@ Maximum 200 per group daily
Drag and drop item here to attach it:
</text>
<icon
- height="72"
+ height="48"
image_name="DropTarget"
layout="topleft"
left_pad="10"
mouse_opaque="true"
name="drop_icon"
top_delta="-10"
- width="72" />
+ width="110" />
<button
follows="left|top"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 7ce2627be9..ed274d0233 100755
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -480,10 +480,22 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
function="People.Group.Minus" />
</dnd_button>
</panel>
+ <text
+ type="string"
+ length="1"
+ follows="all"
+ height="14"
+ layout="topleft"
+ right="-10"
+ top_pad="4"
+ left="3"
+ name="groupcount">
+ You belong to [COUNT] groups, and can join [REMAINING] more.
+ </text>
<group_list
allow_select="true"
follows="all"
- height="406"
+ height="388"
layout="topleft"
left="3"
name="group_list"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 2cc9d9c1b0..50fd57494f 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -138,7 +138,7 @@
initial_value="1"
layout="topleft"
left_pad="0"
- max_val="1.4"
+ max_val="1.5"
min_val="0.75"
name="ui_scale_slider"
top_pad="-14"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index bd096ebb88..8e867259c5 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -14,6 +14,7 @@
border="false"
height="60"
layout="topleft"
+ name="general_chat_settings"
top="10"
left="13"
width="517">
@@ -97,20 +98,13 @@
border="false"
height="165"
layout="topleft"
+ name="im_notification_settings"
left="13"
width="517">
<text
layout="topleft"
height="12"
- name="notifications"
- left="0"
- width="120">
- Notifications
- </text>
- <text
- layout="topleft"
- height="12"
name="friend_ims"
width="145"
left="0"
@@ -138,17 +132,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundFriendIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_friend_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
height="12"
name="non_friend_ims"
width="145"
left="0"
- top_pad="9">
+ top_pad="11">
Non-friend IMs:
</text>
<combo_box
@@ -172,17 +176,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundNonFriendIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_non_friend_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"
height="13"
name="conference_ims"
width="145"
- top_pad="9">
+ top_pad="11">
Conference IMs:
</text>
<combo_box
@@ -206,17 +220,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundConferenceIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_conference_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"
height="13"
name="group_chat"
width="145"
- top_pad="9">
+ top_pad="11">
Group chat:
</text>
<combo_box
@@ -240,17 +264,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundGroupChatIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_group_chat_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"
height="12"
name="nearby_chat"
width="145"
- top_pad="9">
+ top_pad="11">
Nearby chat:
</text>
<combo_box
@@ -274,10 +308,64 @@
name="FlashToolBarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundNearbyChatIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_nearby_chat_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
+ <text
+ layout="topleft"
+ left="0"
+ height="12"
+ name="object_ims"
+ width="145"
+ top_pad="11">
+ Object IMs:
+ </text>
+ <combo_box
+ control_name="NotificationObjectIMOptions"
+ height="23"
+ layout="topleft"
+ left_pad="5"
+ top_delta="-6"
+ name="ObjectIMOptions"
+ width="223">
+ <item
+ label="Open Conversations window"
+ name="OpenConversationsWindow"
+ value="openconversations"/>
+ <item
+ label="Pop up the message"
+ name="PopUpMessage"
+ value="toast"/>
+ <item
+ label="Flash toolbar button"
+ name="FlashToolBarButton"
+ value="flash"/>
+ <item
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
+ </combo_box>
+ <check_box
+ control_name="PlaySoundObjectIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_object_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"
@@ -296,6 +384,7 @@
border="false"
height="50"
layout="topleft"
+ name="play_sound_settings"
left="13"
top_pad="10"
width="517">
@@ -358,6 +447,7 @@
<panel
height="50"
layout="topleft"
+ name="log_settings"
left="13"
top_pad="10"
width="505">
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index d7db7caf66..3c4d288037 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -47,7 +47,7 @@
Better
</text>
<icon
- color="0.12 0.12 0.12 1"
+ color="DkGray"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -56,16 +56,15 @@
top_delta="-2"
width="2" />
<icon
- color="0.12 0.12 0.12 1"
+ color="DkGray"
height="14"
image_name="Rounded_Square"
layout="topleft"
left_pad="41"
- name="LowMidraphicsDivet"
- top_delta="-2"
+ name="LowMidGraphicsDivet"
width="2" />
<icon
- color="0.12 0.12 0.12 1"
+ color="DkGray"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -74,7 +73,7 @@
top_delta="0"
width="2" />
<icon
- color="0.12 0.12 0.12 1"
+ color="DkGray"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -83,7 +82,7 @@
top_delta="0"
width="2" />
<icon
- color="0.12 0.12 0.12 1"
+ color="DkGray"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -92,7 +91,7 @@
top_delta="0"
width="2" />
<icon
- color="0.12 0.12 0.12 1"
+ color="DkGray"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -101,7 +100,7 @@
top_delta="0"
width="2" />
<icon
- color="0.12 0.12 0.12 1"
+ color="DkGray"
height="14"
image_name="Rounded_Square"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml
index 765b07ed8b..bcdef96138 100755
--- a/indra/newview/skins/default/xui/en/panel_script_ed.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml
@@ -125,6 +125,10 @@
label="Search / Replace..."
layout="topleft"
name="Search / Replace..." />
+ <menu_item_call
+ label="Go to line..."
+ layout="topleft"
+ name="Go to line..." />
</menu>
<menu
top="0"
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index dd2a0c6627..064ece6e4b 100755
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -113,7 +113,7 @@
image_pressed="Pause_Press"
image_pressed_selected="Play_Press"
is_toggle="true"
- left_pad="15"
+ left_pad="5"
top="1"
name="media_toggle_btn"
tool_tip="Start/Stop All Media (Music, Video, Web pages)"
diff --git a/indra/newview/skins/default/xui/en/role_actions.xml b/indra/newview/skins/default/xui/en/role_actions.xml
index 89aef57cca..0eeccbeac5 100755
--- a/indra/newview/skins/default/xui/en/role_actions.xml
+++ b/indra/newview/skins/default/xui/en/role_actions.xml
@@ -70,8 +70,8 @@
longdescription="Toggle &apos;Show Place in Search&apos; and setting a parcel&apos;s category in About Land &gt; Options tab."
name="land find places" value="17" />
<action
- description="Change parcel name, description, and &apos;Show Place in Search&apos; settings"
- longdescription="Change parcel name, description, and &apos;Show Place in Search&apos; settings. This is done in About Land &gt; Options tab."
+ description="Change parcel name, description, and &apos;Moderate Content&apos; settings"
+ longdescription="Change parcel name, description, and &apos;Moderate Content&apos; settings. This is done in About Land &gt; Options tab."
name="land change identity" value="18" />
<action description="Set landing point and set teleport routing"
longdescription="On a group-owned parcel, Members in a Role with this Ability can set a landing point to specify where incoming teleports arrive, and also set teleport routing for further control. This is done in About Land &gt; Options tab."
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index f7b33b0a4a..a6b1961849 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -209,7 +209,8 @@ Please try logging in again in a minute.</string>
<string name="SLappAgentIM">IM</string>
<string name="SLappAgentPay">Pay</string>
<string name="SLappAgentOfferTeleport">Offer Teleport to </string>
- <string name="SLappAgentRequestFriend">Friend Request </string>
+ <string name="SLappAgentRequestFriend">Friend Request</string>
+ <string name="SLappAgentRemoveFriend">Friend Removal</string>
<!-- ButtonToolTips, llfloater.cpp -->
<string name="BUTTON_CLOSE_DARWIN">Close (&#8984;W)</string>
@@ -378,7 +379,7 @@ Please try logging in again in a minute.</string>
<!-- world map -->
<string name="texture_loading">Loading...</string>
<string name="worldmap_offline">Offline</string>
- <string name="worldmap_item_tooltip_format">[AREA] m² L$[PRICE]</string>
+ <string name="worldmap_item_tooltip_format">[AREA] m² L$[PRICE] ([SQMPRICE] L$/m²)</string>
<string name="worldmap_results_none_found">None found.</string>
<!-- animations uploading status codes -->
@@ -2460,7 +2461,11 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale
all estates that you manage for [OWNER]
</string>
<string name="RegionInfoAllowedResidents">Allowed Residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string>
- <string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string>
+ <string name="RegionInfoAllowedGroups">Allowed Groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string>
+ <string name="RegionInfoEstateManagers">Estate Managers: ([ESTATEMANAGERS], max [MAXMANAGERS])</string>
+ <string name="RegionInfoBannedResidents">Banned Residents: ([BANNEDAGENTS], max [MAXBANNED])</string>
+ <string name="RegionInfoListTypeAllowedAgents">Allowed Residents</string>
+ <string name="RegionInfoListTypeBannedAgents">Banned Residents</string>
<!-- script limits floater -->
<string name="ScriptLimitsParcelScriptMemory">Parcel Script Memory</string>
@@ -2515,6 +2520,8 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale
<string name="ATTACH_HUD_BOTTOM_LEFT">HUD Bottom Left</string>
<string name="ATTACH_HUD_BOTTOM">HUD Bottom</string>
<string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string>
+ <string name="ATTACH_NECK">Neck</string>
+ <string name="ATTACH_AVATAR_CENTER">Avatar Center</string>
<!-- script editor -->
<string name="CursorPos">Line [LINE], Column [COLUMN]</string>
@@ -3927,5 +3934,8 @@ Try enclosing path to the editor with double quotes.
<string name="logging_calls_enabled_log_empty">
There are no logged conversations. After you contact someone, or someone contacts you, a log entry will be shown here.
</string>
+ <string name="loading_chat_logs">
+ Loading...
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml
index 3696c7e12c..7ca1e3721f 100755
--- a/indra/newview/skins/default/xui/es/floater_about.xml
+++ b/indra/newview/skins/default/xui/es/floater_about.xml
@@ -8,7 +8,7 @@
Compilado con [COMPILER], versión [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Estás en la posición [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1], de [REGION], alojada en &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml
index a659cb4245..d45bdccf3e 100755
--- a/indra/newview/skins/default/xui/fr/floater_about.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about.xml
@@ -8,7 +8,7 @@
Compilé avec [COMPILER] version [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Vous êtes à [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] dans [REGION], se trouvant à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml
index c672511fc5..b0fb585fa2 100755
--- a/indra/newview/skins/default/xui/it/floater_about.xml
+++ b/indra/newview/skins/default/xui/it/floater_about.xml
@@ -8,7 +8,7 @@
Generato con [COMPILER] versione [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Tu sei [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] che si trova a &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Tu sei [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml
index 6d5df75645..eae52c98ec 100755
--- a/indra/newview/skins/default/xui/ja/floater_about.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about.xml
@@ -8,7 +8,7 @@
コンパイラー [COMPILER] [COMPILER_VERSION] バージョン
</floater.string>
<floater.string name="AboutPosition">
- あなたの現在地は、[POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] の [REGION] です。位置は &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; です。([HOSTIP])
+ あなたの現在地は、[POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] の [REGION] です。位置は &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; です。([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/pl/floater_about.xml b/indra/newview/skins/default/xui/pl/floater_about.xml
index 409429ffaa..61a72ff27d 100755
--- a/indra/newview/skins/default/xui/pl/floater_about.xml
+++ b/indra/newview/skins/default/xui/pl/floater_about.xml
@@ -8,7 +8,7 @@
Buduj z [COMPILER] wersją [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Położenie [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] w [REGION] zlokalizowanym w &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Położenie [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] w [REGION] zlokalizowanym w &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml
index 299f88b22a..d089266342 100755
--- a/indra/newview/skins/default/xui/pt/floater_about.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about.xml
@@ -7,7 +7,7 @@
Construído com [COMPILER] versão [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Você está em [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] em [REGION] localizado em [HOSTNAME]&lt;/nolink&gt;([HOSTIP])
+ Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em [HOSTNAME]&lt;/nolink&gt;([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml
index bb6266ac9a..2b2b3cf453 100755
--- a/indra/newview/skins/default/xui/ru/floater_about.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about.xml
@@ -8,7 +8,7 @@
Использован компилятор [COMPILER], версия [COMPILER_VERSION]
</floater.string>
<floater.string name="AboutPosition">
- Вы в точке [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] в регионе «[REGION]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml
index 9cc9c7a220..4dcf6200c6 100755
--- a/indra/newview/skins/default/xui/tr/floater_about.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about.xml
@@ -8,7 +8,7 @@
[COMPILER] [COMPILER_VERSION] sürümü ile oluşturuldu
</floater.string>
<floater.string name="AboutPosition">
- &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] konumundasınız
+ &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml
index 643881e416..1193243c7e 100755
--- a/indra/newview/skins/default/xui/zh/floater_about.xml
+++ b/indra/newview/skins/default/xui/zh/floater_about.xml
@@ -8,7 +8,7 @@
以 [COMPILER_VERSION] 版本 [COMPILER] 建置
</floater.string>
<floater.string name="AboutPosition">
- 你的方位是 [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1],地區名:[REGION],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ 你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp
index 3ba25f3c10..a40b5c9a3d 100755
--- a/indra/newview/tests/llagentaccess_test.cpp
+++ b/indra/newview/tests/llagentaccess_test.cpp
@@ -49,10 +49,10 @@ LLControlGroup::~LLControlGroup()
}
// Implementation of just the LLControlGroup methods we requre
-BOOL LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
test_preferred_maturity = initial_val;
- return true;
+ return NULL;
}
void LLControlGroup::setU32(const std::string& name, U32 val)
@@ -80,7 +80,7 @@ namespace tut
void agentaccess_object_t::test<1>()
{
LLControlGroup cgr("test");
- cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
LLAgentAccess aa(cgr);
cgr.setU32("PreferredMaturity", SIM_ACCESS_PG);
@@ -109,7 +109,7 @@ namespace tut
void agentaccess_object_t::test<2>()
{
LLControlGroup cgr("test");
- cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
LLAgentAccess aa(cgr);
// make sure default is PG
@@ -157,7 +157,7 @@ namespace tut
void agentaccess_object_t::test<3>()
{
LLControlGroup cgr("test");
- cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
LLAgentAccess aa(cgr);
#ifndef HACKED_GODLIKE_VIEWER
@@ -195,7 +195,7 @@ namespace tut
void agentaccess_object_t::test<4>()
{
LLControlGroup cgr("test");
- cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
LLAgentAccess aa(cgr);
#ifndef HACKED_GODLIKE_VIEWER
@@ -272,7 +272,7 @@ namespace tut
void agentaccess_object_t::test<5>()
{
LLControlGroup cgr("test");
- cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
LLAgentAccess aa(cgr);
cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT);
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index f038112fd0..adeb848e03 100755
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -135,6 +135,7 @@ void LLGridManager::addSystemGrid(const std::string& label,
const std::string& login,
const std::string& helper,
const std::string& login_page,
+ const std::string& update_url_base,
const std::string& login_id)
{
}
@@ -175,8 +176,8 @@ F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; }
U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }
void LLControlGroup::setString(const std::string& name, const std::string& val) {}
std::string LLControlGroup::getString(const std::string& name) { return "test_string"; }
-BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; }
-BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; }
+LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; }
#include "lluicolortable.h"
void LLUIColorTable::saveUserSettings(void)const {}
@@ -208,9 +209,7 @@ std::string const & LLUpdaterService::pumpName(void)
return wakka;
}
bool LLUpdaterService::updateReadyToInstall(void) { return false; }
-void LLUpdaterService::initialize(const std::string& url,
- const std::string& path,
- const std::string& channel,
+void LLUpdaterService::initialize(const std::string& channel,
const std::string& version,
const std::string& platform,
const std::string& platform_version,
@@ -344,13 +343,13 @@ namespace tut
gTOSReplyPump = 0; // clear the callback.
- gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE);
- gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE);
- gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
- gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
- gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
- gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
- gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
+ gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", LLControlVariable::PERSIST_NO);
+ gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", LLControlVariable::PERSIST_NO);
+ gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", LLControlVariable::PERSIST_NO);
+ gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", LLControlVariable::PERSIST_NO);
+ gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", LLControlVariable::PERSIST_NO);
+ gSavedSettings.declareString("NextLoginLocation", "", "", LLControlVariable::PERSIST_NO);
+ gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", LLControlVariable::PERSIST_NO);
LLSD authenticator = LLSD::emptyMap();
LLSD identifier = LLSD::emptyMap();
diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp
index 703603e2db..d7e87ed52e 100755
--- a/indra/newview/tests/llsecapi_test.cpp
+++ b/indra/newview/tests/llsecapi_test.cpp
@@ -39,10 +39,10 @@
LLControlGroup::LLControlGroup(const std::string& name)
: LLInstanceTracker<LLControlGroup, std::string>(name) {}
LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
const std::string& initial_val,
const std::string& comment,
- BOOL persist) {return TRUE;}
+ LLControlVariable::ePersist persist) {return NULL;}
void LLControlGroup::setString(const std::string& name, const std::string& val){}
std::string LLControlGroup::getString(const std::string& name)
{
diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp
index 0235400976..2a8dc15346 100755
--- a/indra/newview/tests/llsechandler_basic_test.cpp
+++ b/indra/newview/tests/llsechandler_basic_test.cpp
@@ -71,10 +71,10 @@ std::string gLastName;
LLControlGroup::LLControlGroup(const std::string& name)
: LLInstanceTracker<LLControlGroup, std::string>(name) {}
LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
const std::string& initial_val,
const std::string& comment,
- BOOL persist) {return TRUE;}
+ LLControlVariable::ePersist persist) {return NULL;}
void LLControlGroup::setString(const std::string& name, const std::string& val){}
std::string LLControlGroup::getString(const std::string& name)
{
diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp
index 09343ef227..86229ad636 100755
--- a/indra/newview/tests/llslurl_test.cpp
+++ b/indra/newview/tests/llslurl_test.cpp
@@ -37,10 +37,10 @@
LLControlGroup::LLControlGroup(const std::string& name)
: LLInstanceTracker<LLControlGroup, std::string>(name) {}
LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
const std::string& initial_val,
const std::string& comment,
- BOOL persist) {return TRUE;}
+ LLControlVariable::ePersist persist) {return NULL;}
void LLControlGroup::setString(const std::string& name, const std::string& val){}
std::string gCmdLineLoginURI;
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
index 710881d811..f6456a2839 100755
--- a/indra/newview/tests/llviewerhelputil_test.cpp
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -49,10 +49,10 @@ static std::string gOS;
LLControlGroup::LLControlGroup(const std::string& name)
: LLInstanceTracker<LLControlGroup, std::string>(name) {}
LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
const std::string& initial_val,
const std::string& comment,
- BOOL persist) {return TRUE;}
+ LLControlVariable::ePersist persist) {return NULL;}
void LLControlGroup::setString(const std::string& name, const std::string& val){}
std::string LLControlGroup::getString(const std::string& name)
{
diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp
index a1e97ea17e..7ad7947ca4 100755
--- a/indra/newview/tests/llviewernetwork_test.cpp
+++ b/indra/newview/tests/llviewernetwork_test.cpp
@@ -37,10 +37,10 @@
LLControlGroup::LLControlGroup(const std::string& name)
: LLInstanceTracker<LLControlGroup, std::string>(name) {}
LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
const std::string& initial_val,
const std::string& comment,
- BOOL persist) {return TRUE;}
+ LLControlVariable::ePersist persist) {return NULL;}
void LLControlGroup::setString(const std::string& name, const std::string& val){}
std::string gCmdLineLoginURI;
@@ -127,6 +127,7 @@ const char *gSampleGridFile =
" <array>"
" <string>myloginuri</string>"
" </array>"
+ " <key>update_query_url_base</key><string>https://update.secondlife.com/update</string>"
" <key>keyname</key><string>util.foobar.lindenlab.com</string>"
" </map>"
" </map>"
@@ -185,6 +186,9 @@ namespace tut
ensure_equals("id for agni",
std::string("Agni"),
LLGridManager::getInstance()->getGridId("util.agni.lindenlab.com"));
+ ensure_equals("update url base for Agni", // relies on agni being the default
+ std::string("https://update.secondlife.com/update"),
+ LLGridManager::getInstance()->getUpdateServiceURL());
ensure_equals("label for agni",
LLGridManager::getInstance()->getGridLabel("util.agni.lindenlab.com"),
std::string("Second Life Main Grid (Agni)"));
@@ -256,6 +260,9 @@ namespace tut
ensure_equals("id for agni",
LLGridManager::getInstance()->getGridId("util.agni.lindenlab.com"),
std::string("Agni"));
+ ensure_equals("update url base for Agni", // relies on agni being the default
+ std::string("https://update.secondlife.com/update"),
+ LLGridManager::getInstance()->getUpdateServiceURL());
ensure_equals("label for agni",
LLGridManager::getInstance()->getGridLabel("util.agni.lindenlab.com"),
std::string("Second Life Main Grid (Agni)"));
@@ -384,6 +391,9 @@ namespace tut
ensure_equals("getLoginPage",
LLGridManager::getInstance()->getLoginPage(),
std::string("http://viewer-login.agni.lindenlab.com/"));
+ ensure_equals("update url base for Agni", // relies on agni being the default
+ std::string("https://update.secondlife.com/update"),
+ LLGridManager::getInstance()->getUpdateServiceURL());
ensure("Is Agni a production grid", LLGridManager::getInstance()->isInProductionGrid());
std::vector<std::string> uris;
LLGridManager::getInstance()->getLoginURIs(uris);
diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp
index 711c2a3d51..20f913b670 100755
--- a/indra/newview/tests/llxmlrpclistener_test.cpp
+++ b/indra/newview/tests/llxmlrpclistener_test.cpp
@@ -62,8 +62,8 @@ namespace tut
// These variables are required by machinery used by
// LLXMLRPCTransaction. The values reflect reality for this test
// executable; hopefully these values are correct.
- gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist
- gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist
+ gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", LLControlVariable::PERSIST_NO); // don't persist
+ gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", LLControlVariable::PERSIST_NO); // don't persist
}
// LLEventPump listener signature
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 5e08e54b7c..19863dd845 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -34,9 +34,15 @@ import tarfile
import time
import random
viewer_dir = os.path.dirname(__file__)
-# add llmanifest library to our path so we don't have to muck with PYTHONPATH
-sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util'))
-from llmanifest import LLManifest, main, proper_windows_path, path_ancestors
+# Add indra/lib/python to our path so we don't have to muck with PYTHONPATH.
+# Put it FIRST because some of our build hosts have an ancient install of
+# indra.util.llmanifest under their system Python!
+sys.path.insert(0, os.path.join(viewer_dir, os.pardir, "lib", "python"))
+from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors
+try:
+ from llbase import llsd
+except ImportError:
+ from indra.base import llsd
class ViewerManifest(LLManifest):
def is_packaging_viewer(self):
@@ -65,13 +71,13 @@ class ViewerManifest(LLManifest):
# include the entire shaders directory recursively
self.path("shaders")
# include the extracted list of contributors
- contributor_names = self.extract_names("../../doc/contributions.txt")
- self.put_in_file(contributor_names, "contributors.txt")
- self.file_list.append(["../../doc/contributions.txt",self.dst_path_of("contributors.txt")])
+ contributions_path = "../../doc/contributions.txt"
+ contributor_names = self.extract_names(contributions_path)
+ self.put_in_file(contributor_names, "contributors.txt", src=contributions_path)
# include the extracted list of translators
- translator_names = self.extract_names("../../doc/translations.txt")
- self.put_in_file(translator_names, "translators.txt")
- self.file_list.append(["../../doc/translations.txt",self.dst_path_of("translators.txt")])
+ translations_path = "../../doc/translations.txt"
+ translator_names = self.extract_names(translations_path)
+ self.put_in_file(translator_names, "translators.txt", src=translations_path)
# include the list of Lindens (if any)
# see https://wiki.lindenlab.com/wiki/Generated_Linden_Credits
linden_names_path = os.getenv("LINDEN_CREDITS")
@@ -85,10 +91,9 @@ class ViewerManifest(LLManifest):
else:
# all names should be one line, but the join below also converts to a string
linden_names = ', '.join(linden_file.readlines())
- self.put_in_file(linden_names, "lindens.txt")
+ self.put_in_file(linden_names, "lindens.txt", src=linden_names_path)
linden_file.close()
print "Linden names extracted from '%s'" % linden_names_path
- self.file_list.append([linden_names_path,self.dst_path_of("lindens.txt")])
# ... and the entire windlight directory
self.path("windlight")
@@ -99,6 +104,27 @@ class ViewerManifest(LLManifest):
self.path("dictionaries")
self.end_prefix(pkgdir)
+ # CHOP-955: If we have "sourceid" in the build process
+ # environment, generate it into settings_install.xml.
+ try:
+ sourceid = os.environ["sourceid"]
+ except KeyError:
+ # no sourceid, no settings_install.xml file
+ pass
+ else:
+ if sourceid:
+ # Single-entry subset of the LLSD content of settings.xml
+ content = dict(sourceid=dict(Comment='Identify referring agency to Linden web servers',
+ Persist=1,
+ Type='String',
+ Value=sourceid))
+ # put_in_file(src=) need not be an actual pathname; it
+ # only needs to be non-empty
+ settings_install = self.put_in_file(llsd.format_pretty_xml(content),
+ "settings_install.xml",
+ src="environment")
+ print "Put sourceid '%s' in %s" % (sourceid, settings_install)
+
self.end_prefix("app_settings")
if self.prefix(src="character"):
@@ -196,24 +222,26 @@ class ViewerManifest(LLManifest):
""" Convenience function that returns the command-line flags
for the grid"""
- # Set command line flags relating to the target grid
- grid_flags = ''
- if not self.default_grid():
- grid_flags = "--grid %(grid)s "\
- "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\
- {'grid':self.grid()}
-
- # Deal with settings
- setting_flags = ''
- if not self.default_channel() or not self.default_grid():
- if self.default_grid():
- setting_flags = '--settings settings_%s.xml'\
- % self.channel_lowerword()
- else:
- setting_flags = '--settings settings_%s_%s.xml'\
- % (self.grid(), self.channel_lowerword())
-
- return " ".join((grid_flags, setting_flags)).strip()
+ # The original role of this method seems to have been to build a
+ # grid-specific viewer: one that would, on launch, preselect a
+ # particular grid. (Apparently that dates back to when the protocol
+ # between viewer and simulator required them to be updated in
+ # lockstep, so that "the beta grid" required "a beta viewer.") But
+ # those viewer command-line switches no longer work without tweaking
+ # user_settings/grids.xml. In fact, going forward, it's unclear what
+ # use case that would address.
+
+ # This method also set a channel-specific (or grid-and-channel-
+ # specific) user_settings/settings_something.xml file. It has become
+ # clear that saving user settings in a channel-specific file causes
+ # more problems (confusion) than it solves, so we've discontinued that.
+
+ # In fact we now avoid forcing viewer command-line switches at all,
+ # instead introducing a settings_install.xml file. Command-line
+ # switches don't aggregate well; for instance the generated --channel
+ # switch actually prevented the user specifying --channel on the
+ # command line. Settings files have well-defined override semantics.
+ return None
def extract_names(self,src):
try:
@@ -530,8 +558,7 @@ class WindowsManifest(ViewerManifest):
'final_exe' : self.final_exe(),
'grid':self.args['grid'],
'grid_caps':self.args['grid'].upper(),
- # escape quotes becase NSIS doesn't handle them well
- 'flags':self.flags_list().replace('"', '$\\"'),
+ 'flags':'',
'channel':self.channel(),
'channel_oneword':self.channel_oneword(),
'channel_unique':self.channel_unique(),
@@ -759,9 +786,6 @@ class DarwinManifest(ViewerManifest):
self.end_prefix("llplugin")
- # command line arguments for connecting to the proper grid
- self.put_in_file(self.flags_list(), 'arguments.txt')
-
self.end_prefix("Resources")
self.end_prefix("Contents")
@@ -807,10 +831,6 @@ class DarwinManifest(ViewerManifest):
'bundle': self.get_dst_prefix()
})
- channel_standin = 'Second Life Viewer' # hah, our default channel is not usable on its own
- if not self.default_channel():
- channel_standin = self.channel()
-
imagename="SecondLife_" + '_'.join(self.args['version'])
# MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning.
@@ -928,9 +948,6 @@ class LinuxManifest(ViewerManifest):
self.path("install.sh")
self.end_prefix("linux_tools")
- # Create an appropriate gridargs.dat for this package, denoting required grid.
- self.put_in_file(self.flags_list(), 'etc/gridargs.dat')
-
if self.prefix(src="", dst="bin"):
self.path("secondlife-bin","do-not-directly-run-secondlife-bin")
self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
index 1e768f52d9..dc8ff2f644 100755
--- a/indra/viewer_components/updater/llupdatechecker.cpp
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -62,8 +62,7 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
}
-void LLUpdateChecker::checkVersion(std::string const & hostUrl,
- std::string const & servicePath,
+void LLUpdateChecker::checkVersion(std::string const & urlBase,
std::string const & channel,
std::string const & version,
std::string const & platform,
@@ -71,7 +70,7 @@ void LLUpdateChecker::checkVersion(std::string const & hostUrl,
unsigned char uniqueid[MD5HEX_STR_SIZE],
bool willing_to_test)
{
- mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test);
+ mImplementation->checkVersion(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);
}
@@ -80,7 +79,6 @@ void LLUpdateChecker::checkVersion(std::string const & hostUrl,
//-----------------------------------------------------------------------------
-const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0";
const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1";
@@ -99,8 +97,7 @@ LLUpdateChecker::Implementation::~Implementation()
}
-void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,
- std::string const & servicePath,
+void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase,
std::string const & channel,
std::string const & version,
std::string const & platform,
@@ -112,8 +109,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,
{
mInProgress = true;
- mHostUrl = hostUrl;
- mServicePath = servicePath;
+ mUrlBase = urlBase;
mChannel = channel;
mVersion = version;
mPlatform = platform;
@@ -123,7 +119,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,
mProtocol = sProtocolVersion;
- std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test);
+ std::string checkUrl = buildUrl(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);
LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;
mHttpClient.get(checkUrl, this);
@@ -153,40 +149,11 @@ void LLUpdateChecker::Implementation::completed(U32 status,
server_error += content["error_text"].asString();
}
- if (status == 404)
- {
- if (mProtocol == sProtocolVersion)
- {
- mProtocol = sLegacyProtocolVersion;
- std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest);
-
- LL_WARNS("UpdaterService")
- << "update response using " << sProtocolVersion
- << " was HTTP 404 (" << server_error
- << "); retry with legacy protocol " << mProtocol
- << "\n at " << retryUrl
- << LL_ENDL;
-
- mHttpClient.get(retryUrl, this);
- }
- else
- {
- LL_WARNS("UpdaterService")
- << "update response using " << sLegacyProtocolVersion
- << " was 404 (" << server_error
- << "); request failed"
- << LL_ENDL;
- mClient.error(reason);
- }
- }
- else
- {
- LL_WARNS("UpdaterService") << "response error " << status
- << " " << reason
- << " (" << server_error << ")"
- << LL_ENDL;
- mClient.error(reason);
- }
+ LL_WARNS("UpdaterService") << "response error " << status
+ << " " << reason
+ << " (" << server_error << ")"
+ << LL_ENDL;
+ mClient.error(reason);
}
else
{
@@ -203,26 +170,21 @@ void LLUpdateChecker::Implementation::error(U32 status, const std::string & reas
}
-std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl,
- std::string const & servicePath,
+std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBase,
std::string const & channel,
std::string const & version,
std::string const & platform,
std::string const & platform_version,
unsigned char uniqueid[MD5HEX_STR_SIZE],
bool willing_to_test)
-{
+{
LLSD path;
- path.append(servicePath);
path.append(mProtocol);
path.append(channel);
path.append(version);
path.append(platform);
- if (mProtocol != sLegacyProtocolVersion)
- {
- path.append(platform_version);
- path.append(willing_to_test ? "testok" : "testno");
- path.append((char*)uniqueid);
- }
- return LLURI::buildHTTP(hostUrl, path).asString();
+ path.append(platform_version);
+ path.append(willing_to_test ? "testok" : "testno");
+ path.append((char*)uniqueid);
+ return LLURI::buildHTTP(urlBase, path).asString();
}
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
index 8e85587490..4244007340 100755
--- a/indra/viewer_components/updater/llupdatechecker.h
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -43,8 +43,7 @@ public:
public:
Implementation(Client & client);
~Implementation();
- void checkVersion(std::string const & hostUrl,
- std::string const & servicePath,
+ void checkVersion(std::string const & urlBase,
std::string const & channel,
std::string const & version,
std::string const & platform,
@@ -68,16 +67,14 @@ public:
LLHTTPClient mHttpClient;
bool mInProgress;
std::string mVersion;
- std::string mHostUrl;
- std::string mServicePath;
+ std::string mUrlBase;
std::string mChannel;
std::string mPlatform;
std::string mPlatformVersion;
unsigned char mUniqueId[MD5HEX_STR_SIZE];
bool mWillingToTest;
- std::string buildUrl(std::string const & hostUrl,
- std::string const & servicePath,
+ std::string buildUrl(std::string const & urlBase,
std::string const & channel,
std::string const & version,
std::string const & platform,
@@ -95,8 +92,7 @@ public:
LLUpdateChecker(Client & client);
// Check status of current app on the given host for the channel and version provided.
- void checkVersion(std::string const & hostUrl,
- std::string const & servicePath,
+ void checkVersion(std::string const & urlBase,
std::string const & channel,
std::string const & version,
std::string const & platform,
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 1bd9fa4fc0..16950e1d62 100755
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -38,6 +38,7 @@
#include "lldir.h"
#include "llsdserialize.h"
#include "llfile.h"
+#include "llviewernetwork.h"
#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
@@ -93,8 +94,6 @@ class LLUpdaterServiceImpl :
static const std::string sListenerName;
std::string mProtocolVersion;
- std::string mUrl;
- std::string mPath;
std::string mChannel;
std::string mVersion;
std::string mPlatform;
@@ -120,9 +119,7 @@ public:
LLUpdaterServiceImpl();
virtual ~LLUpdaterServiceImpl();
- void initialize(const std::string& url,
- const std::string& path,
- const std::string& channel,
+ void initialize(const std::string& channel,
const std::string& version,
const std::string& platform,
const std::string& platform_version,
@@ -183,9 +180,7 @@ LLUpdaterServiceImpl::~LLUpdaterServiceImpl()
LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
}
-void LLUpdaterServiceImpl::initialize(const std::string& url,
- const std::string& path,
- const std::string& channel,
+void LLUpdaterServiceImpl::initialize(const std::string& channel,
const std::string& version,
const std::string& platform,
const std::string& platform_version,
@@ -198,8 +193,6 @@ void LLUpdaterServiceImpl::initialize(const std::string& url,
"while updater is running.");
}
- mUrl = url;
- mPath = path;
mChannel = channel;
mVersion = version;
mPlatform = platform;
@@ -207,8 +200,6 @@ void LLUpdaterServiceImpl::initialize(const std::string& url,
memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);
mWillingToTest = willing_to_test;
LL_DEBUGS("UpdaterService")
- << "\n url: " << mUrl
- << "\n path: " << mPath
<< "\n channel: " << mChannel
<< "\n version: " << mVersion
<< "\n uniqueid: " << mUniqueId
@@ -228,7 +219,7 @@ void LLUpdaterServiceImpl::setBandwidthLimit(U64 bytesPerSecond)
void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
{
- if(mUrl.empty() || mChannel.empty() || mVersion.empty())
+ if(mChannel.empty() || mVersion.empty())
{
throw LLUpdaterService::UsageError("Set params before call to "
"LLUpdaterService::startCheck().");
@@ -415,7 +406,7 @@ void LLUpdaterServiceImpl::response(LLSD const & content)
setState(LLUpdaterService::UP_TO_DATE);
}
- else
+ else if ( content.isMap() && content.has("url") )
{
// there is an update available...
stopTimer();
@@ -439,6 +430,12 @@ void LLUpdaterServiceImpl::response(LLSD const & content)
<< LL_ENDL;
mUpdateDownloader.download(url, content["hash"].asString(), mNewChannel, mNewVersion, more_info, required);
}
+ else
+ {
+ LL_WARNS("UpdaterService") << "Invalid update query response ignored; retry in "
+ << mCheckPeriod << " seconds" << LL_ENDL;
+ restartTimer(mCheckPeriod);
+ }
}
void LLUpdaterServiceImpl::downloadComplete(LLSD const & data)
@@ -565,8 +562,26 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
}
else
{
- mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest);
- setState(LLUpdaterService::CHECKING_FOR_UPDATE);
+ std::string query_url = LLGridManager::getInstance()->getUpdateServiceURL();
+ if ( !query_url.empty() )
+ {
+ mUpdateChecker.checkVersion(query_url, mChannel, mVersion,
+ mPlatform, mPlatformVersion, mUniqueId,
+ mWillingToTest);
+ setState(LLUpdaterService::CHECKING_FOR_UPDATE);
+ }
+ else
+ {
+ LL_WARNS("UpdaterService")
+ << "No updater service defined for grid '" << LLGridManager::getInstance()->getGrid()
+ << "' will check again in " << mCheckPeriod << " seconds"
+ << LL_ENDL;
+ // Because the grid can be changed after the viewer is started (when the first check takes place)
+ // but before the user logs in, the next check may be on a different grid, so set the retry timer
+ // even though this check did not happen. The default time is once an hour, and if we're not
+ // doing the check anyway the performance impact is completely insignificant.
+ restartTimer(mCheckPeriod);
+ }
}
}
else
@@ -610,9 +625,7 @@ LLUpdaterService::~LLUpdaterService()
{
}
-void LLUpdaterService::initialize(const std::string& url,
- const std::string& path,
- const std::string& channel,
+void LLUpdaterService::initialize(const std::string& channel,
const std::string& version,
const std::string& platform,
const std::string& platform_version,
@@ -620,7 +633,7 @@ void LLUpdaterService::initialize(const std::string& url,
const bool& willing_to_test
)
{
- mImpl->initialize(url, path, channel, version, platform, platform_version, uniqueid, willing_to_test);
+ mImpl->initialize(channel, version, platform, platform_version, uniqueid, willing_to_test);
}
void LLUpdaterService::setCheckPeriod(unsigned int seconds)
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
index 982f99b861..0ddf24935b 100755
--- a/indra/viewer_components/updater/llupdaterservice.h
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -71,9 +71,7 @@ public:
LLUpdaterService();
~LLUpdaterService();
- void initialize(const std::string& url,
- const std::string& path,
- const std::string& channel,
+ void initialize(const std::string& channel,
const std::string& version,
const std::string& platform,
const std::string& platform_version,
diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install
index a9df9042fd..03089f192e 100755
--- a/indra/viewer_components/updater/scripts/linux/update_install
+++ b/indra/viewer_components/updater/scripts/linux/update_install
@@ -69,8 +69,11 @@ then # zenity on PATH and is executable
# clear any previous message
clear_message
# put up a new zenity box and capture its pid
- "$zenpath" --info --title "Second Life Viewer Updater" \
- --width=320 --height=120 --text="$*" &
+## "$zenpath" --info --title "Second Life Viewer Updater" \
+## --width=320 --height=120 --text="$*" &
+ # MAINT-2333: use bouncing progress bar
+ "$zenpath" --progress --pulsate --no-cancel --title "Second Life Viewer Updater" \
+ --width=320 --height=120 --text "$*" </dev/null &
statuspid=$!
}
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
index 4812272ebc..759e41ef4c 100755
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -44,8 +44,7 @@
*****************************************************************************/
LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
{}
-void LLUpdateChecker::checkVersion(std::string const & hostUrl,
- std::string const & servicePath,
+void LLUpdateChecker::checkVersion(std::string const & urlBase,
std::string const & channel,
std::string const & version,
std::string const & platform,
@@ -91,6 +90,21 @@ bool LLDir::setCacheDir(const std::string &path){ return true; }
void LLDir::dumpCurrentDirectories() {}
void LLDir::updatePerAccountChatLogsDir() {}
+#include "llviewernetwork.h"
+LLGridManager::LLGridManager() :
+ mGrid("test.grid.lindenlab.com"),
+ mIsInProductionGrid(false)
+{
+}
+std::string LLGridManager::getUpdateServiceURL()
+{
+ return "https://update.secondlife.com/update";
+}
+LLGridManager::~LLGridManager()
+{
+}
+
+
std::string LLDir::getExpandedFilename(ELLPath location,
const std::string &filename) const
{
@@ -179,10 +193,10 @@ namespace tut
try
{
unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111";
- updater.initialize(test_url, "update" ,test_channel, test_version, "win", "1.2.3", id1, true);
+ updater.initialize(test_channel, test_version, "win", "1.2.3", id1, true);
updater.startChecking();
unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222";
- updater.initialize("other_url", "update", test_channel, test_version, "win", "4.5.6", id2, true);
+ updater.initialize(test_channel, test_version, "win", "4.5.6", id2, true);
}
catch(LLUpdaterService::UsageError)
{
@@ -197,7 +211,7 @@ namespace tut
DEBUG;
LLUpdaterService updater;
unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333";
- updater.initialize(test_url, "update", test_channel, test_version, "win", "7.8.9", id, true);
+ updater.initialize(test_channel, test_version, "win", "7.8.9", id, true);
updater.startChecking();
ensure(updater.isChecking());
updater.stopChecking();