| 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 29 matching lines...) Expand all Loading... |
| 40 #include "platform/PlatformGestureEvent.h" | 40 #include "platform/PlatformGestureEvent.h" |
| 41 #include "platform/PlatformKeyboardEvent.h" | 41 #include "platform/PlatformKeyboardEvent.h" |
| 42 #include "platform/PlatformMouseEvent.h" | 42 #include "platform/PlatformMouseEvent.h" |
| 43 #include "platform/PlatformScreen.h" | 43 #include "platform/PlatformScreen.h" |
| 44 #include "platform/PlatformTouchEvent.h" | 44 #include "platform/PlatformTouchEvent.h" |
| 45 #include "platform/PlatformWheelEvent.h" | 45 #include "platform/PlatformWheelEvent.h" |
| 46 #include "platform/PopupMenuClient.h" | 46 #include "platform/PopupMenuClient.h" |
| 47 #include "platform/UserGestureIndicator.h" | 47 #include "platform/UserGestureIndicator.h" |
| 48 #include "platform/geometry/IntRect.h" | 48 #include "platform/geometry/IntRect.h" |
| 49 #include "platform/graphics/GraphicsContext.h" | 49 #include "platform/graphics/GraphicsContext.h" |
| 50 #include "platform/scroll/FramelessScrollViewClient.h" | |
| 51 #include "public/web/WebPopupMenuInfo.h" | 50 #include "public/web/WebPopupMenuInfo.h" |
| 52 #include "public/web/WebPopupType.h" | 51 #include "public/web/WebPopupType.h" |
| 53 #include "public/web/WebViewClient.h" | 52 #include "public/web/WebViewClient.h" |
| 53 #include "web/PopupContainerClient.h" |
| 54 #include "web/WebPopupMenuImpl.h" | 54 #include "web/WebPopupMenuImpl.h" |
| 55 #include "web/WebViewImpl.h" | 55 #include "web/WebViewImpl.h" |
| 56 #include <limits> | 56 #include <limits> |
| 57 | 57 |
| 58 namespace blink { | 58 namespace blink { |
| 59 | 59 |
| 60 static const int borderSize = 1; | 60 static const int borderSize = 1; |
| 61 | 61 |
| 62 static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent&
e, FramelessScrollView* parent, FramelessScrollView* child) | 62 static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent&
e, PopupContainer* parent, PopupListBox* child) |
| 63 { | 63 { |
| 64 IntPoint pos = parent->convertSelfToChild(child, e.position()); | 64 IntPoint pos = parent->convertSelfToChild(child, e.position()); |
| 65 | 65 |
| 66 // FIXME: This is a horrible hack since PlatformMouseEvent has no setters fo
r x/y. | 66 // FIXME: This is a horrible hack since PlatformMouseEvent has no setters fo
r x/y. |
| 67 PlatformMouseEvent relativeEvent = e; | 67 PlatformMouseEvent relativeEvent = e; |
| 68 IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.position()); | 68 IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.position()); |
| 69 relativePos.setX(pos.x()); | 69 relativePos.setX(pos.x()); |
| 70 relativePos.setY(pos.y()); | 70 relativePos.setY(pos.y()); |
| 71 return relativeEvent; | 71 return relativeEvent; |
| 72 } | 72 } |
| 73 | 73 |
| 74 static PlatformWheelEvent constructRelativeWheelEvent(const PlatformWheelEvent&
e, FramelessScrollView* parent, FramelessScrollView* child) | 74 static PlatformWheelEvent constructRelativeWheelEvent(const PlatformWheelEvent&
e, PopupContainer* parent, PopupListBox* child) |
| 75 { | 75 { |
| 76 IntPoint pos = parent->convertSelfToChild(child, e.position()); | 76 IntPoint pos = parent->convertSelfToChild(child, e.position()); |
| 77 | 77 |
| 78 // FIXME: This is a horrible hack since PlatformWheelEvent has no setters fo
r x/y. | 78 // FIXME: This is a horrible hack since PlatformWheelEvent has no setters fo
r x/y. |
| 79 PlatformWheelEvent relativeEvent = e; | 79 PlatformWheelEvent relativeEvent = e; |
| 80 IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.position()); | 80 IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.position()); |
| 81 relativePos.setX(pos.x()); | 81 relativePos.setX(pos.x()); |
| 82 relativePos.setY(pos.y()); | 82 relativePos.setY(pos.y()); |
| 83 return relativeEvent; | 83 return relativeEvent; |
| 84 } | 84 } |
| 85 | 85 |
| 86 // static | 86 // static |
| 87 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client, bool
deviceSupportsTouch) | 87 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client, bool
deviceSupportsTouch) |
| 88 { | 88 { |
| 89 return adoptRef(new PopupContainer(client, deviceSupportsTouch)); | 89 return adoptRef(new PopupContainer(client, deviceSupportsTouch)); |
| 90 } | 90 } |
| 91 | 91 |
| 92 PopupContainer::PopupContainer(PopupMenuClient* client, bool deviceSupportsTouch
) | 92 PopupContainer::PopupContainer(PopupMenuClient* client, bool deviceSupportsTouch
) |
| 93 : m_listBox(PopupListBox::create(client, deviceSupportsTouch)) | 93 : m_listBox(PopupListBox::create(client, deviceSupportsTouch, this)) |
| 94 , m_popupOpen(false) | 94 , m_popupOpen(false) |
| 95 , m_client(0) |
| 95 { | 96 { |
| 96 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); | |
| 97 } | 97 } |
| 98 | 98 |
| 99 PopupContainer::~PopupContainer() | 99 PopupContainer::~PopupContainer() |
| 100 { | 100 { |
| 101 if (m_listBox && m_listBox->parent()) | 101 if (m_listBox->parent()) |
| 102 removeChild(m_listBox.get()); | 102 m_listBox->setParent(0); |
| 103 } | 103 } |
| 104 | 104 |
| 105 IntRect PopupContainer::layoutAndCalculateWidgetRectInternal(IntRect widgetRectI
nScreen, int targetControlHeight, const FloatRect& windowRect, const FloatRect&
screen, bool isRTL, const int rtlOffset, const int verticalOffset, const IntSize
& transformOffset, PopupContent* listBox, bool& needToResizeView) | 105 IntRect PopupContainer::layoutAndCalculateWidgetRectInternal(IntRect widgetRectI
nScreen, int targetControlHeight, const FloatRect& windowRect, const FloatRect&
screen, bool isRTL, const int rtlOffset, const int verticalOffset, const IntSize
& transformOffset, PopupContent* listBox, bool& needToResizeView) |
| 106 { | 106 { |
| 107 ASSERT(listBox); | 107 ASSERT(listBox); |
| 108 if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() && (w
idgetRectInScreen.x() < screen.x() || widgetRectInScreen.maxX() > screen.maxX())
) { | 108 if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() && (w
idgetRectInScreen.x() < screen.x() || widgetRectInScreen.maxX() > screen.maxX())
) { |
| 109 // First, inverse the popup alignment if it does not fit the screen - | 109 // First, inverse the popup alignment if it does not fit the screen - |
| 110 // this might fix things (or make them better). | 110 // this might fix things (or make them better). |
| 111 IntRect inverseWidgetRectInScreen = widgetRectInScreen; | 111 IntRect inverseWidgetRectInScreen = widgetRectInScreen; |
| 112 inverseWidgetRectInScreen.setX(inverseWidgetRectInScreen.x() + (isRTL ?
-rtlOffset : rtlOffset)); | 112 inverseWidgetRectInScreen.setX(inverseWidgetRectInScreen.x() + (isRTL ?
-rtlOffset : rtlOffset)); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen
, targetControlHeight, windowRect, screen, isRTL, rtlOffset, verticalOffset, tra
nsformOffset, m_listBox.get(), needToResizeView); | 205 widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen
, targetControlHeight, windowRect, screen, isRTL, rtlOffset, verticalOffset, tra
nsformOffset, m_listBox.get(), needToResizeView); |
| 206 if (needToResizeView) | 206 if (needToResizeView) |
| 207 fitToListBox(); | 207 fitToListBox(); |
| 208 | 208 |
| 209 return widgetRectInScreen; | 209 return widgetRectInScreen; |
| 210 } | 210 } |
| 211 | 211 |
| 212 void PopupContainer::showPopup(FrameView* view) | 212 void PopupContainer::showPopup(FrameView* view) |
| 213 { | 213 { |
| 214 m_frameView = view; | 214 m_frameView = view; |
| 215 listBox()->m_focusedElement = m_frameView->frame().document()->focusedElemen
t(); | 215 m_listBox->m_focusedElement = m_frameView->frame().document()->focusedElemen
t(); |
| 216 | 216 |
| 217 IntSize transformOffset(m_controlPosition.p4().x() - m_controlPosition.p1().
x(), m_controlPosition.p4().y() - m_controlPosition.p1().y() - m_controlSize.hei
ght()); | 217 IntSize transformOffset(m_controlPosition.p4().x() - m_controlPosition.p1().
x(), m_controlPosition.p4().y() - m_controlPosition.p1().y() - m_controlSize.hei
ght()); |
| 218 popupOpened(layoutAndCalculateWidgetRect(m_controlSize.height(), transformOf
fset, roundedIntPoint(m_controlPosition.p4()))); | 218 popupOpened(layoutAndCalculateWidgetRect(m_controlSize.height(), transformOf
fset, roundedIntPoint(m_controlPosition.p4()))); |
| 219 m_popupOpen = true; | 219 m_popupOpen = true; |
| 220 | 220 |
| 221 if (!m_listBox->parent()) | 221 if (!m_listBox->parent()) |
| 222 addChild(m_listBox.get()); | 222 m_listBox->setParent(this); |
| 223 | 223 |
| 224 // Enable scrollbars after the listbox is inserted into the hierarchy, | 224 // Enable scrollbars after the listbox is inserted into the hierarchy, |
| 225 // so it has a proper WidgetClient. | 225 // so it has a proper WidgetClient. |
| 226 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); | 226 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); |
| 227 | 227 |
| 228 m_listBox->scrollToRevealSelection(); | 228 m_listBox->scrollToRevealSelection(); |
| 229 | 229 |
| 230 invalidate(); | 230 invalidate(); |
| 231 } | 231 } |
| 232 | 232 |
| 233 void PopupContainer::hidePopup() | 233 void PopupContainer::hidePopup() |
| 234 { | 234 { |
| 235 listBox()->abandon(); | 235 m_listBox->abandon(); |
| 236 } | 236 } |
| 237 | 237 |
| 238 void PopupContainer::notifyPopupHidden() | 238 void PopupContainer::notifyPopupHidden() |
| 239 { | 239 { |
| 240 if (!m_popupOpen) | 240 if (!m_popupOpen) |
| 241 return; | 241 return; |
| 242 m_popupOpen = false; | 242 m_popupOpen = false; |
| 243 WebViewImpl::fromPage(m_frameView->frame().page())->popupClosed(this); | 243 WebViewImpl::fromPage(m_frameView->frame().page())->popupClosed(this); |
| 244 } | 244 } |
| 245 | 245 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 ChromeClient& PopupContainer::chromeClient() | 371 ChromeClient& PopupContainer::chromeClient() |
| 372 { | 372 { |
| 373 return m_frameView->frame().page()->chrome().client(); | 373 return m_frameView->frame().page()->chrome().client(); |
| 374 } | 374 } |
| 375 | 375 |
| 376 void PopupContainer::showInRect(const FloatQuad& controlPosition, const IntSize&
controlSize, FrameView* v, int index) | 376 void PopupContainer::showInRect(const FloatQuad& controlPosition, const IntSize&
controlSize, FrameView* v, int index) |
| 377 { | 377 { |
| 378 // The controlSize is the size of the select box. It's usually larger than | 378 // The controlSize is the size of the select box. It's usually larger than |
| 379 // we need. Subtract border size so that usually the container will be | 379 // we need. Subtract border size so that usually the container will be |
| 380 // displayed exactly the same width as the select box. | 380 // displayed exactly the same width as the select box. |
| 381 listBox()->setBaseWidth(max(controlSize.width() - borderSize * 2, 0)); | 381 m_listBox->setBaseWidth(max(controlSize.width() - borderSize * 2, 0)); |
| 382 | 382 |
| 383 listBox()->updateFromElement(); | 383 m_listBox->updateFromElement(); |
| 384 | 384 |
| 385 // We set the selected item in updateFromElement(), and disregard the | 385 // We set the selected item in updateFromElement(), and disregard the |
| 386 // index passed into this function (same as Webkit's PopupMenuWin.cpp) | 386 // index passed into this function (same as Webkit's PopupMenuWin.cpp) |
| 387 // FIXME: make sure this is correct, and add an assertion. | 387 // FIXME: make sure this is correct, and add an assertion. |
| 388 // ASSERT(popupWindow(popup)->listBox()->selectedIndex() == index); | 388 // ASSERT(popupWindow(popup)->listBox()->selectedIndex() == index); |
| 389 | 389 |
| 390 // Save and convert the controlPosition to main window coords. Each point is
converted separately | 390 // Save and convert the controlPosition to main window coords. Each point is
converted separately |
| 391 // to window coordinates because the control could be in a transformed webvi
ew and then each point | 391 // to window coordinates because the control could be in a transformed webvi
ew and then each point |
| 392 // would be transformed by a different delta. | 392 // would be transformed by a different delta. |
| 393 m_controlPosition.setP1(v->contentsToWindow(IntPoint(controlPosition.p1().x(
), controlPosition.p1().y()))); | 393 m_controlPosition.setP1(v->contentsToWindow(IntPoint(controlPosition.p1().x(
), controlPosition.p1().y()))); |
| 394 m_controlPosition.setP2(v->contentsToWindow(IntPoint(controlPosition.p2().x(
), controlPosition.p2().y()))); | 394 m_controlPosition.setP2(v->contentsToWindow(IntPoint(controlPosition.p2().x(
), controlPosition.p2().y()))); |
| 395 m_controlPosition.setP3(v->contentsToWindow(IntPoint(controlPosition.p3().x(
), controlPosition.p3().y()))); | 395 m_controlPosition.setP3(v->contentsToWindow(IntPoint(controlPosition.p3().x(
), controlPosition.p3().y()))); |
| 396 m_controlPosition.setP4(v->contentsToWindow(IntPoint(controlPosition.p4().x(
), controlPosition.p4().y()))); | 396 m_controlPosition.setP4(v->contentsToWindow(IntPoint(controlPosition.p4().x(
), controlPosition.p4().y()))); |
| 397 | 397 |
| 398 m_controlSize = controlSize; | 398 m_controlSize = controlSize; |
| 399 | 399 |
| 400 // Position at (0, 0) since the frameRect().location() is relative to the | 400 // Position at (0, 0) since the frameRect().location() is relative to the |
| 401 // parent WebWidget. | 401 // parent WebWidget. |
| 402 setFrameRect(IntRect(IntPoint(), controlSize)); | 402 setFrameRect(IntRect(IntPoint(), controlSize)); |
| 403 showPopup(v); | 403 showPopup(v); |
| 404 } | 404 } |
| 405 | 405 |
| 406 IntRect PopupContainer::refresh(const IntRect& targetControlRect) | 406 IntRect PopupContainer::refresh(const IntRect& targetControlRect) |
| 407 { | 407 { |
| 408 listBox()->setBaseWidth(max(m_controlSize.width() - borderSize * 2, 0)); | 408 m_listBox->setBaseWidth(max(m_controlSize.width() - borderSize * 2, 0)); |
| 409 listBox()->updateFromElement(); | 409 m_listBox->updateFromElement(); |
| 410 | 410 |
| 411 IntPoint locationInWindow = m_frameView->contentsToWindow(targetControlRect.
location()); | 411 IntPoint locationInWindow = m_frameView->contentsToWindow(targetControlRect.
location()); |
| 412 | 412 |
| 413 // Move it below the select widget. | 413 // Move it below the select widget. |
| 414 locationInWindow.move(0, targetControlRect.height()); | 414 locationInWindow.move(0, targetControlRect.height()); |
| 415 | 415 |
| 416 IntRect widgetRectInScreen = layoutAndCalculateWidgetRect(targetControlRect.
height(), IntSize(), locationInWindow); | 416 IntRect widgetRectInScreen = layoutAndCalculateWidgetRect(targetControlRect.
height(), IntSize(), locationInWindow); |
| 417 | 417 |
| 418 // Reset the size (which can be set to the PopupListBox size in | 418 // Reset the size (which can be set to the PopupListBox size in |
| 419 // layoutAndGetRTLOffset(), exceeding the available widget rectangle.) | 419 // layoutAndGetRTLOffset(), exceeding the available widget rectangle.) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 const WTF::Vector<PopupItem*>& PopupContainer:: popupData() const | 453 const WTF::Vector<PopupItem*>& PopupContainer:: popupData() const |
| 454 { | 454 { |
| 455 return m_listBox->items(); | 455 return m_listBox->items(); |
| 456 } | 456 } |
| 457 | 457 |
| 458 String PopupContainer::getSelectedItemToolTip() | 458 String PopupContainer::getSelectedItemToolTip() |
| 459 { | 459 { |
| 460 // We cannot use m_popupClient->selectedIndex() to choose tooltip message, | 460 // We cannot use m_popupClient->selectedIndex() to choose tooltip message, |
| 461 // because the selectedIndex() might return final selected index, not | 461 // because the selectedIndex() might return final selected index, not |
| 462 // hovering selection. | 462 // hovering selection. |
| 463 return listBox()->m_popupClient->itemToolTip(listBox()->m_selectedIndex); | 463 return m_listBox->m_popupClient->itemToolTip(m_listBox->m_selectedIndex); |
| 464 } | 464 } |
| 465 | 465 |
| 466 void PopupContainer::popupOpened(const IntRect& bounds) | 466 void PopupContainer::popupOpened(const IntRect& bounds) |
| 467 { | 467 { |
| 468 WebViewImpl* webView = WebViewImpl::fromPage(m_frameView->frame().page()); | 468 WebViewImpl* webView = WebViewImpl::fromPage(m_frameView->frame().page()); |
| 469 if (!webView->client()) | 469 if (!webView->client()) |
| 470 return; | 470 return; |
| 471 | 471 |
| 472 WebWidget* webwidget = webView->client()->createPopupMenu(WebPopupTypeSelect
); | 472 WebWidget* webwidget = webView->client()->createPopupMenu(WebPopupTypeSelect
); |
| 473 if (!webwidget) | 473 if (!webwidget) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 } | 507 } |
| 508 } | 508 } |
| 509 | 509 |
| 510 info->itemHeight = menuItemHeight(); | 510 info->itemHeight = menuItemHeight(); |
| 511 info->itemFontSize = menuItemFontSize(); | 511 info->itemFontSize = menuItemFontSize(); |
| 512 info->selectedIndex = selectedIndex(); | 512 info->selectedIndex = selectedIndex(); |
| 513 info->items.swap(outputItems); | 513 info->items.swap(outputItems); |
| 514 info->rightAligned = menuStyle().textDirection() == RTL; | 514 info->rightAligned = menuStyle().textDirection() == RTL; |
| 515 } | 515 } |
| 516 | 516 |
| 517 void PopupContainer::invalidateRect(const IntRect& rect) |
| 518 { |
| 519 if (HostWindow* h = hostWindow()) |
| 520 h->invalidateContentsAndRootView(rect); |
| 521 } |
| 522 |
| 523 HostWindow* PopupContainer::hostWindow() const |
| 524 { |
| 525 return const_cast<PopupContainerClient*>(m_client); |
| 526 } |
| 527 |
| 517 } // namespace blink | 528 } // namespace blink |
| OLD | NEW |