IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntSize& transformOffset, const IntPoint& popupInitialCoordinate) { // Reset the max width and height to their default values, they will be // recomputed below if necessary. m_listBox->setMaxHeight(PopupListBox::defaultMaxHeight); m_listBox->setMaxWidth(std::numeric_limits<int>::max()); // Lay everything out to figure out our preferred size, then tell the view's // WidgetClient about it. It should assign us a client. m_listBox->layout(); fitToListBox(); bool isRTL = this->isRTL(); // Compute the starting x-axis for a normal RTL or right-aligned LTR // dropdown. For those, the right edge of dropdown box should be aligned // with the right edge of <select>/<input> element box, and the dropdown box // should be expanded to the left if more space is needed. // m_originalFrameRect.width() is the width of the target <select>/<input> // element. int rtlOffset = m_controlPosition.p2().x() - m_controlPosition.p1().x() - (m_listBox->width() + borderSize * 2); int rightOffset = isRTL ? rtlOffset : 0; // Compute the y-axis offset between the bottom left and bottom right // points. If the <select>/<input> is transformed, they are not the same. int verticalOffset = - m_controlPosition.p4().y() + m_controlPosition.p3().y(); int verticalForRTLOffset = isRTL ? verticalOffset : 0; // Assume m_listBox size is already calculated. IntSize targetSize(m_listBox->width() + borderSize * 2, m_listBox->height() + borderSize * 2); IntRect widgetRectInScreen; // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(m_frameView.get()); // Use popupInitialCoordinate.x() + rightOffset because RTL position // needs to be considered. float pageScaleFactor = m_frameView->frame().page()->pageScaleFactor(); int popupX = round((popupInitialCoordinate.x() + rightOffset) * pageScaleFactor); int popupY = round((popupInitialCoordinate.y() + verticalForRTLOffset) * pageScaleFactor); widgetRectInScreen = chromeClient().rootViewToScreen(IntRect(popupX, popupY, targetSize.width(), targetSize.height())); // If we have multiple screens and the browser rect is in one screen, we // have to clip the window width to the screen width. // When clipping, we also need to set a maximum width for the list box. FloatRect windowRect = chromeClient().windowRect(); bool needToResizeView = false; widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen, targetControlHeight, windowRect, screen, isRTL, rtlOffset, verticalOffset, transformOffset, m_listBox.get(), needToResizeView); if (needToResizeView) fitToListBox(); return widgetRectInScreen; }
int PopupContainer::layoutAndGetRTLOffset() { m_listBox->layout(); fitToListBox(); // Compute the starting x-axis for a normal RTL or right-aligned LTR dropdown. For those, // the right edge of dropdown box should be aligned with the right edge of <select>/<input> element box, // and the dropdown box should be expanded to the left if more space is needed. // m_originalFrameRect.width() is the width of the target <select>/<input> element. return m_originalFrameRect.width() - (m_listBox->width() + kBorderSize * 2); }
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate) { // Reset the max width and height to their default values, they will be recomputed below // if necessary. m_listBox->setMaxHeight(kMaxHeight); m_listBox->setMaxWidth(std::numeric_limits<int>::max()); // Lay everything out to figure out our preferred size, then tell the view's // WidgetClient about it. It should assign us a client. int rtlOffset = layoutAndGetRTLOffset(); bool isRTL = this->isRTL(); int rightOffset = isRTL ? rtlOffset : 0; // Assume m_listBox size is already calculated. IntSize targetSize(m_listBox->width() + kBorderSize * 2, m_listBox->height() + kBorderSize * 2); IntRect widgetRectInScreen; ChromeClientChromium* chromeClient = chromeClientChromium(); if (chromeClient) { // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(m_frameView.get()); // Use popupInitialCoordinate.x() + rightOffset because RTL position // needs to be considered. widgetRectInScreen = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height())); // If we have multiple screens and the browser rect is in one screen, we have // to clip the window width to the screen width. // When clipping, we also need to set a maximum width for the list box. FloatRect windowRect = chromeClient->windowRect(); bool needToResizeView = false; widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen, targetControlHeight, windowRect, screen, isRTL, rtlOffset, m_listBox.get(), needToResizeView); if (needToResizeView) fitToListBox(); } return widgetRectInScreen; }