Changeset 89916 in webkit
- Timestamp:
- Jun 28, 2011 2:52:10 AM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r89915 r89916 1 2011-06-27 Alexander Pavlov <apavlov@chromium.org> 2 3 Reviewed by Kent Tamura. 4 5 [Chromium] SELECT or autofill popup is trimmed by screen edge on Windows 6 https://bugs.webkit.org/show_bug.cgi?id=63438 7 8 If the popup is calculated to be trimmed by a screen edge, an attempt is made 9 to alter its vertical edge alignment (set to the right edge for LTR or to the left edge for RTL) 10 to see if the trimmed portion becomes smaller than that with the original layout. 11 The change involves remembering the original frameRect for the popup and restoring it in refresh(). 12 This is due to the fact that the frameRect originally set in showInRect() is overwritten 13 by layoutAndGetRTLOffset(), which breaks the originally requested popup container layout metrics. 14 The max width is reset on every layoutAndCalculateWidgetRect(), as it can be constrained by the screen edge, 15 and thus should be re-checked every time the popup is displayed, in case the browser window has been moved. 16 17 Tests: manual-tests/popup-width-restriction-within-screen.html partly covers the fix (should not regress). 18 Other than that, there is no way to unit-test the platform-specific native code. 19 20 * platform/chromium/PopupMenuChromium.cpp: 21 (WebCore::PopupListBox::setMaxWidth): Added. Avoid duplicate popup content layouts (in contrast with setMaxWidthAndLayout()). 22 (WebCore::PopupListBox::PopupListBox): 23 (WebCore::PopupContainer::layoutAndCalculateWidgetRect): Attempt a left-right popup alignment inversion 24 to minimize the trimmed content. Also restore a default max popup width. 25 (WebCore::PopupContainer::layoutAndGetRTLOffset): Always return the popup listbox offset for the RTL (right alignment) case. 26 The method rename is due to the return value semantics change. 27 (WebCore::PopupContainer::showInRect): Store the originally requested frameRect for the popup. 28 (WebCore::PopupContainer::refresh): Restore the original popup frameRect to avoid layout artifacts on refresh. 29 (WebCore::PopupContainer::isRTL): This check should be made by the layoutAndGetRTLOffset() clients. 30 * platform/chromium/PopupMenuChromium.h: 31 1 32 2011-06-28 Kentaro Hara <haraken@google.com> 2 33 -
trunk/Source/WebCore/platform/chromium/PopupMenuChromium.cpp
r88895 r89916 59 59 #include <wtf/unicode/CharacterNames.h> 60 60 61 using namespace std; 61 62 using namespace WTF; 62 63 using namespace Unicode; … … 146 147 147 148 void setMaxHeight(int maxHeight) { m_maxHeight = maxHeight; } 149 150 void setMaxWidth(int maxWidth) { m_maxWindowWidth = maxWidth; } 148 151 149 152 void setMaxWidthAndLayout(int); … … 168 171 , m_repeatingChar(0) 169 172 , m_lastCharTime(0) 170 , m_maxWindowWidth( std::numeric_limits<int>::max())173 , m_maxWindowWidth(numeric_limits<int>::max()) 171 174 { 172 175 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); … … 341 344 IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate) 342 345 { 343 // Reset the max height to its default value, itwill be recomputed below346 // Reset the max width and height to their default values, they will be recomputed below 344 347 // if necessary. 345 348 m_listBox->setMaxHeight(kMaxHeight); 349 m_listBox->setMaxWidth(numeric_limits<int>::max()); 346 350 347 351 // Lay everything out to figure out our preferred size, then tell the view's 348 352 // WidgetClient about it. It should assign us a client. 349 int rightOffset = layoutAndGetRightOffset(); 353 int rtlOffset = layoutAndGetRTLOffset(); 354 bool isRTL = this->isRTL(); 355 int rightOffset = isRTL ? rtlOffset : 0; 350 356 351 357 // Assume m_listBox size is already calculated. … … 367 373 // When clipping, we also need to set a maximum width for the list box. 368 374 FloatRect windowRect = chromeClient->windowRect(); 369 if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX()) { 370 if (m_listBox->m_popupClient->menuStyle().textDirection() == RTL && widgetRect.x() < screen.x()) { 375 if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() && (widgetRect.x() < screen.x() || widgetRect.maxX() > screen.maxX())) { 376 // First, inverse the popup alignment if it does not fit the screen - this might fix things (or make them better). 377 IntRect inverseWidgetRect = chromeClient->windowToScreen(IntRect(popupInitialCoordinate.x() + (isRTL ? 0 : rtlOffset), popupInitialCoordinate.y(), targetSize.width(), targetSize.height())); 378 IntRect enclosingScreen = enclosingIntRect(screen); 379 unsigned originalCutoff = max(enclosingScreen.x() - widgetRect.x(), 0) + max(widgetRect.maxX() - enclosingScreen.maxX(), 0); 380 unsigned inverseCutoff = max(enclosingScreen.x() - inverseWidgetRect.x(), 0) + max(inverseWidgetRect.maxX() - enclosingScreen.maxX(), 0); 381 382 // Accept the inverse popup alignment if the trimmed content gets shorter than that in the original alignment case. 383 if (inverseCutoff < originalCutoff) 384 widgetRect = inverseWidgetRect; 385 386 if (widgetRect.x() < screen.x()) { 387 unsigned widgetRight = widgetRect.maxX(); 371 388 widgetRect.setWidth(widgetRect.maxX() - screen.x()); 372 widgetRect.setX( screen.x());389 widgetRect.setX(widgetRight - widgetRect.width()); 373 390 listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorderSize * 2, 0)); 374 391 } else if (widgetRect.maxX() > screen.maxX()) { … … 392 409 else 393 410 m_listBox->setMaxHeight(spaceBelow); 394 layoutAndGetR ightOffset();411 layoutAndGetRTLOffset(); 395 412 // Our height has changed, so recompute only Y axis of widgetRect. 396 413 // We don't have to recompute X axis, so we only replace Y axis … … 445 462 } 446 463 447 int PopupContainer::layoutAndGetR ightOffset()464 int PopupContainer::layoutAndGetRTLOffset() 448 465 { 449 466 m_listBox->layout(); … … 457 474 int listBoxWidth = m_listBox->width() + kBorderSize * 2; 458 475 resize(listBoxWidth, m_listBox->height() + kBorderSize * 2); 459 460 // Adjust the starting x-axis for RTL dropdown. For RTL dropdown, the right edge461 // of dropdown box should be aligned with the right edge of <select> element box,462 // and the dropdown box should be expanded to left if more space needed.463 PopupMenuClient* popupClient = m_listBox->m_popupClient;464 int rightOffset = 0;465 if (popupClient) {466 bool rightAligned = m_listBox->m_popupClient->menuStyle().textDirection() == RTL;467 if (rightAligned)468 rightOffset = popupWidth - listBoxWidth;469 }470 476 invalidate(); 471 477 472 return rightOffset; 478 // Compute the starting x-axis for a normal RTL or right-aligned LTR dropdown. For those, 479 // the right edge of dropdown box should be aligned with the right edge of <select> element box, 480 // and the dropdown box should be expanded to the left if more space is needed. 481 return popupWidth - listBoxWidth; 473 482 } 474 483 … … 576 585 location.move(0, r.height()); 577 586 578 setFrameRect(IntRect(location, r.size())); 587 m_originalFrameRect = IntRect(location, r.size()); 588 setFrameRect(m_originalFrameRect); 579 589 showPopup(v); 580 590 } … … 585 595 // Move it below the select widget. 586 596 location.move(0, targetControlRect.height()); 597 598 listBox()->setBaseWidth(max(m_originalFrameRect.width() - kBorderSize * 2, 0)); 599 setFrameRect(m_originalFrameRect); 587 600 588 601 listBox()->updateFromElement(); … … 590 603 IntSize originalSize = size(); 591 604 IntRect widgetRect = layoutAndCalculateWidgetRect(targetControlRect.height(), location); 592 if (originalSize != widgetRect.size()) 593 setFrameRect(widgetRect); 605 if (originalSize != widgetRect.size()) { 606 ChromeClientChromium* chromeClient = chromeClientChromium(); 607 if (chromeClient) { 608 IntPoint widgetLocation = chromeClient->screenToWindow(widgetRect.location()); 609 widgetRect.setLocation(widgetLocation); 610 setFrameRect(widgetRect); 611 } 612 } 594 613 595 614 invalidate(); 615 } 616 617 inline bool PopupContainer::isRTL() const 618 { 619 return m_listBox->m_popupClient->menuStyle().textDirection() == RTL; 596 620 } 597 621 -
trunk/Source/WebCore/platform/chromium/PopupMenuChromium.h
r88021 r89916 142 142 void notifyPopupHidden(); 143 143 144 // Compute size of widget and children. Return right offset for RTL.145 int layoutAndGetR ightOffset();144 // Compute size of widget and children. Return right offset for the popup right alignment. 145 int layoutAndGetRTLOffset(); 146 146 147 147 PopupListBox* listBox() const { return m_listBox.get(); } 148 149 bool isRTL() const; 148 150 149 151 // Gets the index of the item that the user is currently moused-over or … … 191 193 PopupContainerSettings m_settings; 192 194 PopupType m_popupType; 195 IntRect m_originalFrameRect; 193 196 // Whether the popup is currently open. 194 197 bool m_popupOpen;
Note: See TracChangeset
for help on using the changeset viewer.