OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011, Google Inc. All rights reserved. | 2 * Copyright (c) 2011, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 // Lay everything out to figure out our preferred size, then tell the view's | 127 // Lay everything out to figure out our preferred size, then tell the view's |
128 // WidgetClient about it. It should assign us a client. | 128 // WidgetClient about it. It should assign us a client. |
129 int rtlOffset = layoutAndGetRTLOffset(); | 129 int rtlOffset = layoutAndGetRTLOffset(); |
130 bool isRTL = this->isRTL(); | 130 bool isRTL = this->isRTL(); |
131 int rightOffset = isRTL ? rtlOffset : 0; | 131 int rightOffset = isRTL ? rtlOffset : 0; |
132 | 132 |
133 // Assume m_listBox size is already calculated. | 133 // Assume m_listBox size is already calculated. |
134 IntSize targetSize(m_listBox->width() + kBorderSize * 2, | 134 IntSize targetSize(m_listBox->width() + kBorderSize * 2, |
135 m_listBox->height() + kBorderSize * 2); | 135 m_listBox->height() + kBorderSize * 2); |
136 | 136 |
137 IntRect widgetRect; | 137 IntRect widgetRectInScreen; |
138 ChromeClientChromium* chromeClient = chromeClientChromium(); | 138 ChromeClientChromium* chromeClient = chromeClientChromium(); |
139 if (chromeClient) { | 139 if (chromeClient) { |
140 // If the popup would extend past the bottom of the screen, open upwards | 140 // If the popup would extend past the bottom of the screen, open upwards |
141 // instead. | 141 // instead. |
142 FloatRect screen = screenAvailableRect(m_frameView.get()); | 142 FloatRect screen = screenAvailableRect(m_frameView.get()); |
143 // Use popupInitialCoordinate.x() + rightOffset because RTL position | 143 // Use popupInitialCoordinate.x() + rightOffset because RTL position |
144 // needs to be considered. | 144 // needs to be considered. |
145 widgetRect = chromeClient->rootViewToScreen(IntRect(popupInitialCoordina
te.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize
.height())); | 145 widgetRectInScreen = chromeClient->rootViewToScreen(IntRect(popupInitial
Coordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), ta
rgetSize.height())); |
146 | 146 |
147 // If we have multiple screens and the browser rect is in one screen, we
have | 147 // If we have multiple screens and the browser rect is in one screen, we
have |
148 // to clip the window width to the screen width. | 148 // to clip the window width to the screen width. |
149 // When clipping, we also need to set a maximum width for the list box. | 149 // When clipping, we also need to set a maximum width for the list box. |
150 FloatRect windowRect = chromeClient->windowRect(); | 150 FloatRect windowRect = chromeClient->windowRect(); |
151 if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() &
& (widgetRect.x() < screen.x() || widgetRect.maxX() > screen.maxX())) { | 151 if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() &
& (widgetRectInScreen.x() < screen.x() || widgetRectInScreen.maxX() > screen.max
X())) { |
152 // First, inverse the popup alignment if it does not fit the screen
- this might fix things (or make them better). | 152 // First, inverse the popup alignment if it does not fit the screen
- this might fix things (or make them better). |
153 IntRect inverseWidgetRect = chromeClient->rootViewToScreen(IntRect(p
opupInitialCoordinate.x() + (isRTL ? 0 : rtlOffset), popupInitialCoordinate.y(),
targetSize.width(), targetSize.height())); | 153 IntRect inverseWidgetRectInScreen = chromeClient->rootViewToScreen(I
ntRect(popupInitialCoordinate.x() + (isRTL ? 0 : rtlOffset), popupInitialCoordin
ate.y(), targetSize.width(), targetSize.height())); |
154 IntRect enclosingScreen = enclosingIntRect(screen); | 154 IntRect enclosingScreen = enclosingIntRect(screen); |
155 unsigned originalCutoff = max(enclosingScreen.x() - widgetRect.x(),
0) + max(widgetRect.maxX() - enclosingScreen.maxX(), 0); | 155 unsigned originalCutoff = max(enclosingScreen.x() - widgetRectInScre
en.x(), 0) + max(widgetRectInScreen.maxX() - enclosingScreen.maxX(), 0); |
156 unsigned inverseCutoff = max(enclosingScreen.x() - inverseWidgetRect
.x(), 0) + max(inverseWidgetRect.maxX() - enclosingScreen.maxX(), 0); | 156 unsigned inverseCutoff = max(enclosingScreen.x() - inverseWidgetRect
InScreen.x(), 0) + max(inverseWidgetRectInScreen.maxX() - enclosingScreen.maxX()
, 0); |
157 | 157 |
158 // Accept the inverse popup alignment if the trimmed content gets sh
orter than that in the original alignment case. | 158 // Accept the inverse popup alignment if the trimmed content gets sh
orter than that in the original alignment case. |
159 if (inverseCutoff < originalCutoff) | 159 if (inverseCutoff < originalCutoff) |
160 widgetRect = inverseWidgetRect; | 160 widgetRectInScreen = inverseWidgetRectInScreen; |
161 | 161 |
162 if (widgetRect.x() < screen.x()) { | 162 if (widgetRectInScreen.x() < screen.x()) { |
163 unsigned widgetRight = widgetRect.maxX(); | 163 unsigned widgetRight = widgetRectInScreen.maxX(); |
164 widgetRect.setWidth(widgetRect.maxX() - screen.x()); | 164 widgetRectInScreen.setWidth(widgetRectInScreen.maxX() - screen.x
()); |
165 widgetRect.setX(widgetRight - widgetRect.width()); | 165 widgetRectInScreen.setX(widgetRight - widgetRectInScreen.width()
); |
166 listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorder
Size * 2, 0)); | 166 listBox()->setMaxWidthAndLayout(max(widgetRectInScreen.width() -
kBorderSize * 2, 0)); |
167 } else if (widgetRect.maxX() > screen.maxX()) { | 167 } else if (widgetRectInScreen.maxX() > screen.maxX()) { |
168 widgetRect.setWidth(screen.maxX() - widgetRect.x()); | 168 widgetRectInScreen.setWidth(screen.maxX() - widgetRectInScreen.x
()); |
169 listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorder
Size * 2, 0)); | 169 listBox()->setMaxWidthAndLayout(max(widgetRectInScreen.width() -
kBorderSize * 2, 0)); |
170 } | 170 } |
171 } | 171 } |
172 | 172 |
173 // Calculate Y axis size. | 173 // Calculate Y axis size. |
174 if (widgetRect.maxY() > static_cast<int>(screen.maxY())) { | 174 if (widgetRectInScreen.maxY() > static_cast<int>(screen.maxY())) { |
175 if (widgetRect.y() - widgetRect.height() - targetControlHeight > 0)
{ | 175 if (widgetRectInScreen.y() - widgetRectInScreen.height() - targetCon
trolHeight > 0) { |
176 // There is enough room to open upwards. | 176 // There is enough room to open upwards. |
177 widgetRect.move(0, -(widgetRect.height() + targetControlHeight))
; | 177 widgetRectInScreen.move(0, -(widgetRectInScreen.height() + targe
tControlHeight)); |
178 } else { | 178 } else { |
179 // Figure whether upwards or downwards has more room and set the | 179 // Figure whether upwards or downwards has more room and set the |
180 // maximum number of items. | 180 // maximum number of items. |
181 int spaceAbove = widgetRect.y() - targetControlHeight; | 181 int spaceAbove = widgetRectInScreen.y() - targetControlHeight; |
182 int spaceBelow = screen.maxY() - widgetRect.y(); | 182 int spaceBelow = screen.maxY() - widgetRectInScreen.y(); |
183 if (spaceAbove > spaceBelow) | 183 if (spaceAbove > spaceBelow) |
184 m_listBox->setMaxHeight(spaceAbove); | 184 m_listBox->setMaxHeight(spaceAbove); |
185 else | 185 else |
186 m_listBox->setMaxHeight(spaceBelow); | 186 m_listBox->setMaxHeight(spaceBelow); |
187 layoutAndGetRTLOffset(); | 187 layoutAndGetRTLOffset(); |
188 // Our height has changed, so recompute only Y axis of widgetRec
t. | 188 // Our height has changed, so recompute only Y axis of widgetRec
t. |
189 // We don't have to recompute X axis, so we only replace Y axis | 189 // We don't have to recompute X axis, so we only replace Y axis |
190 // in widgetRect. | 190 // in widgetRect. |
191 IntRect frameInScreen = chromeClient->rootViewToScreen(frameRect
()); | 191 IntRect frameInScreen = chromeClient->rootViewToScreen(frameRect
()); |
192 widgetRect.setY(frameInScreen.y()); | 192 widgetRectInScreen.setY(frameInScreen.y()); |
193 widgetRect.setHeight(frameInScreen.height()); | 193 widgetRectInScreen.setHeight(frameInScreen.height()); |
194 // And move upwards if necessary. | 194 // And move upwards if necessary. |
195 if (spaceAbove > spaceBelow) | 195 if (spaceAbove > spaceBelow) |
196 widgetRect.move(0, -(widgetRect.height() + targetControlHeig
ht)); | 196 widgetRectInScreen.move(0, -(widgetRectInScreen.height() + t
argetControlHeight)); |
197 } | 197 } |
198 } | 198 } |
199 } | 199 } |
200 return widgetRect; | 200 |
| 201 return widgetRectInScreen; |
201 } | 202 } |
202 | 203 |
203 void PopupContainer::showPopup(FrameView* view) | 204 void PopupContainer::showPopup(FrameView* view) |
204 { | 205 { |
205 m_frameView = view; | 206 m_frameView = view; |
206 listBox()->m_focusedNode = m_frameView->frame()->document()->focusedNode(); | 207 listBox()->m_focusedNode = m_frameView->frame()->document()->focusedNode(); |
207 | 208 |
208 ChromeClientChromium* chromeClient = chromeClientChromium(); | 209 ChromeClientChromium* chromeClient = chromeClientChromium(); |
209 if (chromeClient) { | 210 if (chromeClient) { |
210 IntRect popupRect = frameRect(); | 211 IntRect popupRect = m_originalFrameRect; |
211 chromeClient->popupOpened(this, layoutAndCalculateWidgetRect(popupRect.h
eight(), popupRect.location()), false); | 212 chromeClient->popupOpened(this, layoutAndCalculateWidgetRect(popupRect.h
eight(), popupRect.location()), false); |
212 m_popupOpen = true; | 213 m_popupOpen = true; |
213 } | 214 } |
214 | 215 |
215 if (!m_listBox->parent()) | 216 if (!m_listBox->parent()) |
216 addChild(m_listBox.get()); | 217 addChild(m_listBox.get()); |
217 | 218 |
218 // Enable scrollbars after the listbox is inserted into the hierarchy, | 219 // Enable scrollbars after the listbox is inserted into the hierarchy, |
219 // so it has a proper WidgetClient. | 220 // so it has a proper WidgetClient. |
220 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); | 221 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 // FIXME: make sure this is correct, and add an assertion. | 394 // FIXME: make sure this is correct, and add an assertion. |
394 // ASSERT(popupWindow(popup)->listBox()->selectedIndex() == index); | 395 // ASSERT(popupWindow(popup)->listBox()->selectedIndex() == index); |
395 | 396 |
396 // Convert point to main window coords. | 397 // Convert point to main window coords. |
397 IntPoint location = v->contentsToWindow(r.location()); | 398 IntPoint location = v->contentsToWindow(r.location()); |
398 | 399 |
399 // Move it below the select widget. | 400 // Move it below the select widget. |
400 location.move(0, r.height()); | 401 location.move(0, r.height()); |
401 | 402 |
402 m_originalFrameRect = IntRect(location, r.size()); | 403 m_originalFrameRect = IntRect(location, r.size()); |
403 setFrameRect(m_originalFrameRect); | 404 |
| 405 // Position at (0, 0) since the frameRect().location() is relative to the pa
rent WebWidget. |
| 406 setFrameRect(IntRect(IntPoint(), r.size())); |
404 showPopup(v); | 407 showPopup(v); |
405 } | 408 } |
406 | 409 |
407 void PopupContainer::refresh(const IntRect& targetControlRect) | 410 void PopupContainer::refresh(const IntRect& targetControlRect) |
408 { | 411 { |
409 IntPoint location = m_frameView->contentsToWindow(targetControlRect.location
()); | 412 listBox()->setBaseWidth(max(m_originalFrameRect.width() - kBorderSize * 2, 0
)); |
| 413 listBox()->updateFromElement(); |
| 414 |
| 415 IntPoint locationInWindow = m_frameView->contentsToWindow(targetControlRect.
location()); |
| 416 |
410 // Move it below the select widget. | 417 // Move it below the select widget. |
411 location.move(0, targetControlRect.height()); | 418 locationInWindow.move(0, targetControlRect.height()); |
412 | 419 |
413 listBox()->setBaseWidth(max(m_originalFrameRect.width() - kBorderSize * 2, 0
)); | 420 IntRect widgetRectInScreen = layoutAndCalculateWidgetRect(targetControlRect.
height(), locationInWindow); |
414 | 421 |
415 listBox()->updateFromElement(); | 422 // Reset the size (which can be set to the PopupListBox size in layoutAndGet
RTLOffset(), exceeding the available widget rectangle.) |
416 // Store the original size to check if we need to request the location. | 423 if (size() != widgetRectInScreen.size()) |
417 IntSize originalSize = size(); | 424 resize(widgetRectInScreen.size()); |
418 IntRect widgetRect = layoutAndCalculateWidgetRect(targetControlRect.height()
, location); | 425 |
419 if (originalSize != widgetRect.size()) { | 426 ChromeClientChromium* chromeClient = chromeClientChromium(); |
420 ChromeClientChromium* chromeClient = chromeClientChromium(); | 427 if (chromeClient) { |
421 if (chromeClient) { | 428 // Update the WebWidget location (which is relative to the screen origin
). |
422 IntPoint widgetLocation = chromeClient->screenToRootView(widgetRect.
location()); | 429 if (widgetRectInScreen != chromeClient->windowRect()) |
423 widgetRect.setLocation(widgetLocation); | 430 chromeClient->setWindowRect(widgetRectInScreen); |
424 setFrameRect(widgetRect); | |
425 } | |
426 } | 431 } |
427 | 432 |
428 invalidate(); | 433 invalidate(); |
429 } | 434 } |
430 | 435 |
431 inline bool PopupContainer::isRTL() const | 436 inline bool PopupContainer::isRTL() const |
432 { | 437 { |
433 return m_listBox->m_popupClient->menuStyle().textDirection() == RTL; | 438 return m_listBox->m_popupClient->menuStyle().textDirection() == RTL; |
434 } | 439 } |
435 | 440 |
(...skipping 23 matching lines...) Expand all Loading... |
459 } | 464 } |
460 | 465 |
461 String PopupContainer::getSelectedItemToolTip() | 466 String PopupContainer::getSelectedItemToolTip() |
462 { | 467 { |
463 // We cannot use m_popupClient->selectedIndex() to choose tooltip message, | 468 // We cannot use m_popupClient->selectedIndex() to choose tooltip message, |
464 // because the selectedIndex() might return final selected index, not hoveri
ng selection. | 469 // because the selectedIndex() might return final selected index, not hoveri
ng selection. |
465 return listBox()->m_popupClient->itemToolTip(listBox()->m_selectedIndex); | 470 return listBox()->m_popupClient->itemToolTip(listBox()->m_selectedIndex); |
466 } | 471 } |
467 | 472 |
468 } // namespace WebCore | 473 } // namespace WebCore |
OLD | NEW |