summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorAlexander Gavriliuk <alexandrgproductengine@lindenlab.com>2023-11-09 17:51:32 +0100
committerGuru <alexandrgproductengine@lindenlab.com>2023-11-09 18:40:08 +0100
commit1e7643eea5883db5b773db99b37440eb06b63e3e (patch)
treec383a99741998b57cb035f7a532c5a2804f290d0 /indra/llui
parent93e4d069d1a9d003664f23f842cf100f635607ed (diff)
SL-20438 Emoji picker will dock with edge of screen if the Conversations floater is dragged there
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llfloater.cpp96
-rw-r--r--indra/llui/llfloater.h7
-rw-r--r--indra/llui/llview.cpp41
-rw-r--r--indra/llui/llview.h1
4 files changed, 100 insertions, 45 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 98895d56dd..23d3a66631 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -829,6 +829,24 @@ void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent)
LLPanel::reshape(width, height, called_from_parent);
}
+// virtual
+void LLFloater::translate(S32 x, S32 y)
+{
+ LLView::translate(x, y);
+
+ if (!mTranslateWithDependents || mDependents.empty())
+ return;
+
+ for (const LLHandle<LLFloater>& handle : mDependents)
+ {
+ LLFloater* floater = handle.get();
+ if (floater && floater->getSnapTarget() == getHandle())
+ {
+ floater->LLView::translate(x, y);
+ }
+ }
+}
+
void LLFloater::releaseFocus()
{
LLUI::getInstance()->removePopup(this);
@@ -1117,9 +1135,9 @@ BOOL LLFloater::canSnapTo(const LLView* other_view)
if (other_view != getParent())
{
- const LLFloater* other_floaterp = dynamic_cast<const LLFloater*>(other_view);
- if (other_floaterp
- && other_floaterp->getSnapTarget() == getHandle()
+ const LLFloater* other_floaterp = dynamic_cast<const LLFloater*>(other_view);
+ if (other_floaterp
+ && other_floaterp->getSnapTarget() == getHandle()
&& mDependents.find(other_floaterp->getHandle()) != mDependents.end())
{
// this is a dependent that is already snapped to us, so don't snap back to it
@@ -1552,6 +1570,44 @@ void LLFloater::removeDependentFloater(LLFloater* floaterp)
floaterp->mDependeeHandle = LLHandle<LLFloater>();
}
+void LLFloater::fitWithDependentsOnScreen(const LLRect& left, const LLRect& bottom, const LLRect& right, const LLRect& constraint, S32 min_overlap_pixels)
+{
+ LLRect total_rect = getRect();
+
+ for (const LLHandle<LLFloater>& handle : mDependents)
+ {
+ LLFloater* floater = handle.get();
+ if (floater && floater->getSnapTarget() == getHandle())
+ {
+ total_rect.unionWith(floater->getRect());
+ }
+ }
+
+ S32 delta_left = left.notEmpty() ? left.mRight - total_rect.mRight : 0;
+ S32 delta_bottom = bottom.notEmpty() ? bottom.mTop - total_rect.mTop : 0;
+ S32 delta_right = right.notEmpty() ? right.mLeft - total_rect.mLeft : 0;
+
+ // move floater with dependings fully onscreen
+ mTranslateWithDependents = true;
+ if (translateRectIntoRect(total_rect, constraint, min_overlap_pixels))
+ {
+ clearSnapTarget();
+ }
+ else if (delta_left > 0 && total_rect.mTop < left.mTop && total_rect.mBottom > left.mBottom)
+ {
+ translate(delta_left, 0);
+ }
+ else if (delta_bottom > 0 && total_rect.mLeft > bottom.mLeft && total_rect.mRight < bottom.mRight)
+ {
+ translate(0, delta_bottom);
+ }
+ else if (delta_right < 0 && total_rect.mTop < right.mTop && total_rect.mBottom > right.mBottom)
+ {
+ translate(delta_right, 0);
+ }
+ mTranslateWithDependents = false;
+}
+
BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index)
{
if( mButtonsEnabled[index] )
@@ -2862,10 +2918,17 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
// floater is hosted elsewhere, so ignore
return;
}
+
+ if (floater->getDependee() &&
+ floater->getDependee() == floater->getSnapTarget().get())
+ {
+ // floater depends on other and snaps to it, so ignore
+ return;
+ }
+
LLRect::tCoordType screen_width = getSnapRect().getWidth();
LLRect::tCoordType screen_height = getSnapRect().getHeight();
-
// only automatically resize non-minimized, resizable floaters
if( floater->isResizable() && !floater->isMinimized() )
{
@@ -2907,29 +2970,10 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
}
}
- const LLRect& floater_rect = floater->getRect();
-
- S32 delta_left = mToolbarLeftRect.notEmpty() ? mToolbarLeftRect.mRight - floater_rect.mRight : 0;
- S32 delta_bottom = mToolbarBottomRect.notEmpty() ? mToolbarBottomRect.mTop - floater_rect.mTop : 0;
- S32 delta_right = mToolbarRightRect.notEmpty() ? mToolbarRightRect.mLeft - floater_rect.mLeft : 0;
+ const LLRect& constraint = snap_in_toolbars ? getSnapRect() : gFloaterView->getRect();
+ S32 min_overlap_pixels = allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX;
- // move window fully onscreen
- if (floater->translateIntoRect( snap_in_toolbars ? getSnapRect() : gFloaterView->getRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))
- {
- floater->clearSnapTarget();
- }
- else if (delta_left > 0 && floater_rect.mTop < mToolbarLeftRect.mTop && floater_rect.mBottom > mToolbarLeftRect.mBottom)
- {
- floater->translate(delta_left, 0);
- }
- else if (delta_bottom > 0 && floater_rect.mLeft > mToolbarBottomRect.mLeft && floater_rect.mRight < mToolbarBottomRect.mRight)
- {
- floater->translate(0, delta_bottom);
- }
- else if (delta_right < 0 && floater_rect.mTop < mToolbarRightRect.mTop && floater_rect.mBottom > mToolbarRightRect.mBottom)
- {
- floater->translate(delta_right, 0);
- }
+ floater->fitWithDependentsOnScreen(mToolbarLeftRect, mToolbarBottomRect, mToolbarRightRect, constraint, min_overlap_pixels);
}
void LLFloaterView::draw()
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 3699629ef8..08fc5f425f 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -113,8 +113,6 @@ struct LLCoordFloater : LLCoord<LL_COORD_FLOATER>
bool operator!=(const LLCoordFloater& other) const { return !(*this == other); }
void setFloater(LLFloater& floater);
-
-
};
class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
@@ -237,6 +235,7 @@ public:
virtual void closeHostedFloater();
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ /*virtual*/ void translate(S32 x, S32 y);
// Release keyboard and mouse focus
void releaseFocus();
@@ -258,7 +257,8 @@ public:
void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE, BOOL resize = FALSE);
void addDependentFloater(LLHandle<LLFloater> dependent_handle, BOOL reposition = TRUE, BOOL resize = FALSE);
LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); }
- void removeDependentFloater(LLFloater* dependent);
+ void removeDependentFloater(LLFloater* dependent);
+ void fitWithDependentsOnScreen(const LLRect& left, const LLRect& bottom, const LLRect& right, const LLRect& constraint, S32 min_overlap_pixels);
BOOL isMinimized() const { return mMinimized; }
/// isShown() differs from getVisible() in that isShown() also considers
/// isMinimized(). isShown() is true only if visible and not minimized.
@@ -506,6 +506,7 @@ private:
typedef std::set<LLHandle<LLFloater> > handle_set_t;
typedef std::set<LLHandle<LLFloater> >::iterator handle_set_iter_t;
handle_set_t mDependents;
+ bool mTranslateWithDependents { false };
bool mButtonsEnabled[BUTTON_COUNT];
F32 mButtonScale;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index d8d605871f..0046105870 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1753,23 +1753,26 @@ LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, S3
const S32 KEEP_ONSCREEN_PIXELS_WIDTH = llmin(min_overlap_pixels, input.getWidth());
const S32 KEEP_ONSCREEN_PIXELS_HEIGHT = llmin(min_overlap_pixels, input.getHeight());
- if( input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH < constraint.mLeft )
+ if (KEEP_ONSCREEN_PIXELS_WIDTH <= constraint.getWidth() &&
+ KEEP_ONSCREEN_PIXELS_HEIGHT <= constraint.getHeight())
{
- delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH);
- }
- else if( input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH > constraint.mRight )
- {
- delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH);
- }
+ if (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH < constraint.mLeft)
+ {
+ delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH);
+ }
+ else if (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH > constraint.mRight)
+ {
+ delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH);
+ }
- if( input.mTop > constraint.mTop )
- {
- delta.mY = constraint.mTop - input.mTop;
- }
- else
- if( input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT < constraint.mBottom )
- {
- delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT);
+ if (input.mTop > constraint.mTop)
+ {
+ delta.mY = constraint.mTop - input.mTop;
+ }
+ else if (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT < constraint.mBottom)
+ {
+ delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT);
+ }
}
return delta;
@@ -1780,13 +1783,19 @@ LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, S3
// (Why top and left? That's where the drag bars are for floaters.)
BOOL LLView::translateIntoRect(const LLRect& constraint, S32 min_overlap_pixels)
{
- LLCoordGL translation = getNeededTranslation(getRect(), constraint, min_overlap_pixels);
+ return translateRectIntoRect(getRect(), constraint, min_overlap_pixels);
+}
+
+BOOL LLView::translateRectIntoRect(const LLRect& rect, const LLRect& constraint, S32 min_overlap_pixels)
+{
+ LLCoordGL translation = getNeededTranslation(rect, constraint, min_overlap_pixels);
if (translation.mX != 0 || translation.mY != 0)
{
translate(translation.mX, translation.mY);
return TRUE;
}
+
return FALSE;
}
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 3d52d3048f..b498451dce 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -369,6 +369,7 @@ public:
virtual void translate( S32 x, S32 y );
void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); }
BOOL translateIntoRect( const LLRect& constraint, S32 min_overlap_pixels = S32_MAX);
+ BOOL translateRectIntoRect( const LLRect& rect, const LLRect& constraint, S32 min_overlap_pixels = S32_MAX);
BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels = S32_MAX);
void centerWithin(const LLRect& bounds);