From 2a5c25cb3a47a319559aae6de1206e91b3c1647e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 17 Oct 2009 11:56:26 -0400 Subject: New LLFloater methods capture LLFloaterReg visibility tests. The logic was redundantly expressed in LLFloaterReg -- and would be useful elsewhere -- so was introduced as LLFloater::isShown(). Thanks to Richard and James for suggesting the terminology. --- indra/llui/llfloater.cpp | 10 ++++++++++ indra/llui/llfloater.h | 8 +++++++- indra/llui/llfloaterreg.cpp | 11 ++--------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 66defbbf0a..d7a24192bb 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2605,3 +2605,13 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o moveResizeHandlesToFront(); } +bool LLFloater::isShown() const +{ + return ! isMinimized() && isInVisibleChain(); +} + +/* static */ +bool LLFloater::isShown(const LLFloater* floater) +{ + return floater && floater->isShown(); +} diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 466d060068..ef609860d1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -185,7 +185,13 @@ public: void addDependentFloater(LLHandle dependent_handle, BOOL reposition = TRUE); LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); } void removeDependentFloater(LLFloater* dependent); - BOOL isMinimized() { return mMinimized; } + BOOL isMinimized() const { return mMinimized; } + /// isShown() differs from getVisible() in that isShown() also considers + /// isMinimized(). isShown() is true only if visible and not minimized. + bool isShown() const; + /// The static isShown() can accept a NULL pointer (which of course + /// returns false). When non-NULL, it calls the non-static isShown(). + static bool isShown(const LLFloater* floater); BOOL isFrontmost(); BOOL isDependent() { return !mDependeeHandle.isDead(); } void setCanMinimize(BOOL can_minimize); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 8617ba940e..589a34b2c8 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -247,7 +247,7 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) { LLFloater* instance = findInstance(name, key); - if (instance && !instance->isMinimized() && instance->isInVisibleChain()) + if (LLFloater::isShown(instance)) { // When toggling *visibility*, close the host instead of the floater when hosted if (instance->getHost()) @@ -267,14 +267,7 @@ bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key) { LLFloater* instance = findInstance(name, key); - if (instance && !instance->isMinimized() && instance->isInVisibleChain()) - { - return true; - } - else - { - return false; - } + return LLFloater::isShown(instance); } //static -- cgit v1.2.3 From ed84101a6e31760b7a44de857669ce255ee67d9b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 17 Oct 2009 12:00:12 -0400 Subject: Introduce LLView::isAvailable() to test enabled & visible. Better term? The point of the method is to verify that a user could actually interact with the LLView in question. --- indra/llui/llview.cpp | 12 ++++++++++++ indra/llui/llview.h | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 1df8838738..2be8b8c17d 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -438,6 +438,18 @@ void LLView::setEnabled(BOOL enabled) mEnabled = enabled; } +//virtual +bool LLView::isAvailable() const +{ + return isInEnabledChain() && isInVisibleChain(); +} + +//static +bool LLView::isAvailable(const LLView* view) +{ + return view && view->isAvailable(); +} + //virtual BOOL LLView::setLabelArg( const std::string& key, const LLStringExplicit& text ) { diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 7ddff2bd9e..f630932317 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -304,6 +304,11 @@ public: BOOL getVisible() const { return mVisible; } virtual void setEnabled(BOOL enabled); BOOL getEnabled() const { return mEnabled; } + /// 'available' in this context means 'visible and enabled': in other + /// words, can a user actually interact with this? + virtual bool isAvailable() const; + /// The static isAvailable() tests an LLView* that could be NULL. + static bool isAvailable(const LLView* view); U8 getSoundFlags() const { return mSoundFlags; } virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); -- cgit v1.2.3 From 2849175a302f26be03b5da404ef93363d42ed313 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 17 Oct 2009 12:03:23 -0400 Subject: Introduce LLFloaterRegListener "clickButton" event operation. Based on discussion with James and Richard, this operation should allow an automation script to locate a visible LLFloater and simulate clicking any one of its LLButton children by name. As yet untested. --- indra/llui/llfloaterreglistener.cpp | 48 +++++++++++++++++++++++++++++++++++++ indra/llui/llfloaterreglistener.h | 1 + 2 files changed, 49 insertions(+) diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp index cb8fa6dfda..57d148b5af 100644 --- a/indra/llui/llfloaterreglistener.cpp +++ b/indra/llui/llfloaterreglistener.cpp @@ -18,6 +18,8 @@ // external library headers // other Linden headers #include "llfloaterreg.h" +#include "llfloater.h" +#include "llbutton.h" LLFloaterRegListener::LLFloaterRegListener(const std::string& pumpName): LLDispatchListener(pumpName, "op") @@ -28,6 +30,10 @@ LLFloaterRegListener::LLFloaterRegListener(const std::string& pumpName): add("showInstance", &LLFloaterRegListener::showInstance, requiredName); add("hideInstance", &LLFloaterRegListener::hideInstance, requiredName); add("toggleInstance", &LLFloaterRegListener::toggleInstance, requiredName); + LLSD requiredNameButton; + requiredNameButton["name"] = LLSD(); + requiredNameButton["button"] = LLSD(); + add("clickButton", &LLFloaterRegListener::clickButton, requiredNameButton); } void LLFloaterRegListener::getBuildMap(const LLSD& event) const @@ -64,3 +70,45 @@ void LLFloaterRegListener::toggleInstance(const LLSD& event) const { LLFloaterReg::toggleInstance(event["name"], event["key"]); } + +void LLFloaterRegListener::clickButton(const LLSD& event) const +{ + // If the caller requests a reply, build the reply. + LLReqID reqID(event); + LLSD reply(reqID.makeResponse()); + + LLFloater* floater = LLFloaterReg::findInstance(event["name"], event["key"]); + if (! LLFloater::isShown(floater)) + { + reply["type"] = "LLFloater"; + reply["name"] = event["name"]; + reply["key"] = event["key"]; + reply["error"] = floater? "!isShown()" : "NULL"; + } + else + { + // Here 'floater' points to an LLFloater instance with the specified + // name and key which isShown(). + LLButton* button = floater->findChild(event["button"]); + if (! LLButton::isAvailable(button)) + { + reply["type"] = "LLButton"; + reply["name"] = event["button"]; + reply["error"] = button? "!isAvailable()" : "NULL"; + } + else + { + // Here 'button' points to an isAvailable() LLButton child of + // 'floater' with the specified button name. Pretend to click it. + button->onCommit(); + // Leave reply["error"] isUndefined(): no error, i.e. success. + } + } + + // Send a reply only if caller asked for a reply. + LLSD replyPump(event["reply"]); + if (replyPump.isString()) // isUndefined() if absent + { + LLEventPumps::instance().obtain(replyPump).post(reply); + } +} diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h index 58d2c07936..304ecd1090 100644 --- a/indra/llui/llfloaterreglistener.h +++ b/indra/llui/llfloaterreglistener.h @@ -30,6 +30,7 @@ private: void showInstance(const LLSD& event) const; void hideInstance(const LLSD& event) const; void toggleInstance(const LLSD& event) const; + void clickButton(const LLSD& event) const; }; #endif /* ! defined(LL_LLFLOATERREGLISTENER_H) */ -- cgit v1.2.3 From 27cadfbe951abb2cf350d5a1c91876ac958d50cf Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 17 Oct 2009 12:21:22 -0400 Subject: DEV-40930: Introduce LLAppViewerListener "forceQuit" operation. The bug was driven by the following sequence in llstartup.cpp: if(reason_response == "update" || reason_response == "optional") { // used to resend status event still containing "update", // erroneously instantiating a second forced-update // LLAlertDialog LLLoginInstance::getInstance()->disconnect(); // quit with an LLAlertDialog still on sModalStack used // to result in LL_ERRS LLAppViewer::instance()->forceQuit(); } I hope to be able to introduce a test script to verify the fix. That script would need to be able to call LLAppViewer::forceQuit() rather than requestQuit(), which is already available via LLAppViewerListener. At the same time, changed LLAppViewerListener to bind a functor to retrieve an LLAppViewer instance (namely LLAppViewer::instance) rather than an LLAppViewer*. Apparently the static instantiation of LLAppViewerListener was calling LLAppViewer::instance() too early, before things were ready, so the declaration was changed to pass NULL -- then in each method, call LLAppViewer::instance() if the bound pointer is NULL. Binding the LLAppViewer* is a Feathers tactic intended to avoid the need to reference the singleton. Binding a functor still leaves it up to the instantiating code to reference LLAppViewer::instance, while deferring the actual call to that method. --- indra/newview/llappviewer.cpp | 2 +- indra/newview/llappviewerlistener.cpp | 17 ++++++++++------- indra/newview/llappviewerlistener.h | 7 +++++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a631314d5b..80749295ff 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -204,7 +204,7 @@ #pragma warning (disable:4702) #endif -static LLAppViewerListener sAppViewerListener("LLAppViewer", NULL); +static LLAppViewerListener sAppViewerListener("LLAppViewer", LLAppViewer::instance); ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor // diff --git a/indra/newview/llappviewerlistener.cpp b/indra/newview/llappviewerlistener.cpp index a3af251a3c..3259309eee 100644 --- a/indra/newview/llappviewerlistener.cpp +++ b/indra/newview/llappviewerlistener.cpp @@ -19,19 +19,22 @@ // other Linden headers #include "llappviewer.h" -LLAppViewerListener::LLAppViewerListener(const std::string& pumpname, LLAppViewer* llappviewer): +LLAppViewerListener::LLAppViewerListener(const std::string& pumpname, + const LLAppViewerGetter& getter): LLDispatchListener(pumpname, "op"), - mAppViewer(llappviewer) + mAppViewerGetter(getter) { // add() every method we want to be able to invoke via this event API. add("requestQuit", &LLAppViewerListener::requestQuit); + add("forceQuit", &LLAppViewerListener::forceQuit); } void LLAppViewerListener::requestQuit(const LLSD& event) { - if(mAppViewer == NULL) - { - mAppViewer = LLAppViewer::instance(); - } - mAppViewer->requestQuit(); + mAppViewerGetter()->requestQuit(); +} + +void LLAppViewerListener::forceQuit(const LLSD& event) +{ + mAppViewerGetter()->forceQuit(); } diff --git a/indra/newview/llappviewerlistener.h b/indra/newview/llappviewerlistener.h index d702f605ef..73227cb95a 100644 --- a/indra/newview/llappviewerlistener.h +++ b/indra/newview/llappviewerlistener.h @@ -13,6 +13,7 @@ #define LL_LLAPPVIEWERLISTENER_H #include "lleventdispatcher.h" +#include class LLAppViewer; class LLSD; @@ -21,14 +22,16 @@ class LLSD; class LLAppViewerListener: public LLDispatchListener { public: + typedef boost::function LLAppViewerGetter; /// Specify the pump name on which to listen, and bind the LLAppViewer /// instance to use (e.g. LLAppViewer::instance()). - LLAppViewerListener(const std::string& pumpname, LLAppViewer* llappviewer); + LLAppViewerListener(const std::string& pumpname, const LLAppViewerGetter& getter); private: void requestQuit(const LLSD& event); + void forceQuit(const LLSD& event); - LLAppViewer* mAppViewer; + LLAppViewerGetter mAppViewerGetter; }; #endif /* ! defined(LL_LLAPPVIEWERLISTENER_H) */ -- cgit v1.2.3 From b52b97b6e1fa1ac709ba951c32ff422ed55fbdf1 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 20 Oct 2009 08:51:23 -0400 Subject: It seems that ADD_INTEGRATION_TEST tests now require GoogleMock to build --- indra/cmake/LLAddBuildTest.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 499bf19afd..d8f64199cf 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -1,5 +1,6 @@ # -*- cmake -*- include(LLTestCommand) +include(GoogleMock) MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) # Given a project name and a list of sourcefiles (with optional properties on each), @@ -190,6 +191,7 @@ FUNCTION(LL_ADD_INTEGRATION_TEST SET(libraries ${library_dependencies} + ${GOOGLEMOCK_LIBRARIES} ${PTHREAD_LIBRARY} ) -- cgit v1.2.3 From 6f44e1de9bc22b9f944686472e7e46239c14c225 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 20 Oct 2009 08:53:18 -0400 Subject: Don't include linden_common.h in lldate.h, or any other .h files. Migrate to the .cpp files where it's needed. --- indra/llcommon/lldate.h | 2 -- indra/llcommon/tests/llstring_test.cpp | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 5c28a076cd..5b1ec9295f 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -35,8 +35,6 @@ #ifndef LL_LLDATE_H #define LL_LLDATE_H -#include "linden_common.h" - #include #include diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 6a2ebc61f5..beba55416a 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -32,6 +32,7 @@ * $/LicenseInfo$ */ +#include "linden_common.h" #include "../test/lltut.h" #include "../llstring.h" -- cgit v1.2.3 From 7aff3d0842475de4b0bb3bc33d5b4cc86a056623 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 20 Oct 2009 11:32:45 -0400 Subject: Disabling dubious getHostName() test as explained in comments --- indra/llmessage/tests/llhost_test.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/indra/llmessage/tests/llhost_test.cpp b/indra/llmessage/tests/llhost_test.cpp index 5dc9ce42ee..ebe61fcad3 100644 --- a/indra/llmessage/tests/llhost_test.cpp +++ b/indra/llmessage/tests/llhost_test.cpp @@ -166,7 +166,21 @@ namespace tut // the main domain name and not do the exact compare std::string hostname = host.getHostName(); - ensure("getHostName failed", hostname.find(hostStr) != std::string::npos); +/*==========================================================================*| + // nat 2009-10-20: not sure this ensure() is such a good idea, at + // least with "google.com". The logic below is failing for me with: + // set 'google.com'; reported 'yx-in-f100.1e100.net' + // Disabling test until we can replace it with something more robust. + try + { + ensure("getHostName failed", hostname.find(hostStr) != std::string::npos); + } + catch (const std::exception&) + { + std::cerr << "set '" << hostStr << "'; reported '" << hostname << "'" << std::endl; + throw; + } +|*==========================================================================*/ } // setHostByName for dotted IP -- cgit v1.2.3