SL-20438 Emoji picker will dock with edge of screen if the Conversations floater is dragged there
parent
93e4d069d1
commit
1e7643eea5
|
|
@ -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();
|
||||
const LLRect& constraint = snap_in_toolbars ? getSnapRect() : gFloaterView->getRect();
|
||||
S32 min_overlap_pixels = allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX;
|
||||
|
||||
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;
|
||||
|
||||
// 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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ void LLFloaterEmojiPicker::show(pick_callback_t pick_callback, close_callback_t
|
|||
}
|
||||
|
||||
LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key)
|
||||
: LLFloater(key)
|
||||
: super(key)
|
||||
{
|
||||
loadState();
|
||||
}
|
||||
|
|
@ -894,14 +894,14 @@ BOOL LLFloaterEmojiPicker::handleKeyHere(KEY key, MASK mask)
|
|||
}
|
||||
}
|
||||
|
||||
return LLFloater::handleKeyHere(key, mask);
|
||||
return super::handleKeyHere(key, mask);
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLFloaterEmojiPicker::closeFloater(bool app_quitting)
|
||||
{
|
||||
saveState();
|
||||
LLFloater::closeFloater(app_quitting);
|
||||
super::closeFloater(app_quitting);
|
||||
if (mFloaterCloseCallback)
|
||||
{
|
||||
mFloaterCloseCallback();
|
||||
|
|
|
|||
Loading…
Reference in New Issue