예제 #1
0
float PagePopupClient::zoomFactor() {
  if (const ComputedStyle* style = ownerElement().computedStyle())
    return style->effectiveZoom();
  if (LocalFrame* frame = ownerElement().document().frame())
    return frame->pageZoomFactor();
  return 1;
}
void PopupMenuImpl::writeDocument(SharedBuffer* data)
{
    IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elementRectRelativeToViewport());

    PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
    data->append(Platform::current()->loadResource("pickerCommon.css"));
    data->append(Platform::current()->loadResource("listPicker.css"));
    PagePopupClient::addString("</style></head><body><div id=main>Loading...</div><script>\n"
        "window.dialogArguments = {\n", data);
    addProperty("selectedIndex", m_client->selectedIndex(), data);
    const ComputedStyle* ownerStyle = ownerElement().computedStyle();
    ItemIterationContext context(*ownerStyle, data);
    context.serializeBaseStyle();
    PagePopupClient::addString("children: [\n", data);
    for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) {
        if (isHTMLOptionElement(child))
            addOption(context, toHTMLOptionElement(child));
        if (isHTMLOptGroupElement(child))
            addOptGroup(context, toHTMLOptGroupElement(child));
        if (isHTMLHRElement(child))
            addSeparator(context, toHTMLHRElement(child));
    }
    PagePopupClient::addString("],\n", data);

    addProperty("anchorRectInScreen", anchorRectInScreen, data);
    bool isRTL = !ownerStyle->isLeftToRightDirection();
    addProperty("isRTL", isRTL, data);
    addProperty("paddingStart", isRTL ? m_client->clientPaddingRight().toDouble() : m_client->clientPaddingLeft().toDouble(), data);
    PagePopupClient::addString("};\n", data);
    data->append(Platform::current()->loadResource("pickerCommon.js"));
    data->append(Platform::current()->loadResource("listPicker.js"));
    PagePopupClient::addString("</script></body>\n", data);
}
void PopupMenuImpl::update()
{
    if (!m_popup || !m_client)
        return;
    ownerElement().document().updateLayoutTreeIfNeeded();
    if (!m_client)
        return;
    m_needsUpdate = false;
    RefPtr<SharedBuffer> data = SharedBuffer::create();
    PagePopupClient::addString("window.updateData = {\n", data.get());
    PagePopupClient::addString("type: \"update\",\n", data.get());
    ItemIterationContext context(*ownerElement().computedStyle(), data.get());
    context.serializeBaseStyle();
    PagePopupClient::addString("children: [", data.get());
    for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) {
        if (isHTMLOptionElement(child))
            addOption(context, toHTMLOptionElement(child));
        if (isHTMLOptGroupElement(child))
            addOptGroup(context, toHTMLOptGroupElement(child));
        if (isHTMLHRElement(child))
            addSeparator(context, toHTMLHRElement(child));
    }
    PagePopupClient::addString("],\n", data.get());
    PagePopupClient::addString("}\n", data.get());
    m_popup->postMessage(String::fromUTF8(data->data(), data->size()));
}
예제 #4
0
void PopupMenuImpl::update()
{
    if (!m_popup || !m_client)
        return;
    ownerElement().document().updateLayoutTreeIfNeeded();
    if (!m_client)
        return;
    m_needsUpdate = false;
    RefPtr<SharedBuffer> data = SharedBuffer::create();
    PagePopupClient::addString("window.updateData = {\n", data.get());
    PagePopupClient::addString("type: \"update\",\n", data.get());
    PagePopupClient::addString("children: [", data.get());
    bool enableExtraStyling = !hasTooManyItemsForStyling();
    for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) {
        if (isHTMLOptionElement(child))
            addOption(toHTMLOptionElement(child), enableExtraStyling, data.get());
        if (isHTMLOptGroupElement(child))
            addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data.get());
        if (isHTMLHRElement(child))
            addSeparator(toHTMLHRElement(child), enableExtraStyling, data.get());
    }
    PagePopupClient::addString("],\n", data.get());
    PagePopupClient::addString("}\n", data.get());
    m_popup->postMessage(String::fromUTF8(data->data(), data->size()));
}
예제 #5
0
// We don't make child style information if the popup will have a lot of items
// because of a performance problem.
// TODO(tkent): This is a workaround.  We should do a performance optimization.
bool PopupMenuImpl::hasTooManyItemsForStyling()
{
    // 300 is enough for world-wide countries.
    const unsigned styledChildrenLimit = 300;

    if (!isHTMLSelectElement(ownerElement()))
        return false;
    return toHTMLSelectElement(ownerElement()).listItems().size() > styledChildrenLimit;
}
예제 #6
0
void PopupMenuImpl::update()
{
    if (!m_popup || !m_ownerElement)
        return;
    ownerElement().document().updateLayoutTreeIfNeeded();
    // disconnectClient() might have been called.
    if (!m_ownerElement)
        return;
    m_needsUpdate = false;
    RefPtr<SharedBuffer> data = SharedBuffer::create();
    PagePopupClient::addString("window.updateData = {\n", data.get());
    PagePopupClient::addString("type: \"update\",\n", data.get());
    ItemIterationContext context(*m_ownerElement->computedStyle(), data.get());
    context.serializeBaseStyle();
    PagePopupClient::addString("children: [", data.get());
    const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = m_ownerElement->listItems();
    for (; context.m_listIndex < items.size(); ++context.m_listIndex) {
        Element& child = *items[context.m_listIndex];
        if (!isHTMLOptGroupElement(child.parentNode()))
            context.finishGroupIfNecessary();
        if (isHTMLOptionElement(child))
            addOption(context, toHTMLOptionElement(child));
        else if (isHTMLOptGroupElement(child))
            addOptGroup(context, toHTMLOptGroupElement(child));
        else if (isHTMLHRElement(child))
            addSeparator(context, toHTMLHRElement(child));
    }
    context.finishGroupIfNecessary();
    PagePopupClient::addString("],\n", data.get());
    PagePopupClient::addString("}\n", data.get());
    m_popup->postMessage(String::fromUTF8(data->data(), data->size()));
}
예제 #7
0
void PopupMenuImpl::updateFromElement()
{
    if (m_needsUpdate)
        return;
    m_needsUpdate = true;
    ownerElement().document().postTask(BLINK_FROM_HERE, createSameThreadTask(&PopupMenuImpl::update, PassRefPtrWillBeRawPtr<PopupMenuImpl>(this)));
}
예제 #8
0
void PopupMenuImpl::setValueAndClosePopup(int numValue,
                                          const String& stringValue) {
  DCHECK(m_popup);
  DCHECK(m_ownerElement);
  if (!stringValue.isEmpty()) {
    bool success;
    int listIndex = stringValue.toInt(&success);
    DCHECK(success);

    EventQueueScope scope;
    m_ownerElement->selectOptionByPopup(listIndex);
    if (m_popup)
      m_chromeClient->closePagePopup(m_popup);
    // 'change' event is dispatched here.  For compatbility with
    // Angular 1.2, we need to dispatch a change event before
    // mouseup/click events.
  } else {
    if (m_popup)
      m_chromeClient->closePagePopup(m_popup);
  }
  // We dispatch events on the owner element to match the legacy behavior.
  // Other browsers dispatch click events before and after showing the popup.
  if (m_ownerElement) {
    PlatformMouseEvent event;
    Element* owner = &ownerElement();
    owner->dispatchMouseEvent(event, EventTypeNames::mouseup);
    owner->dispatchMouseEvent(event, EventTypeNames::click);
  }
}
예제 #9
0
void PopupMenuImpl::update() {
  if (!m_popup || !m_ownerElement)
    return;
  ownerElement().document().updateStyleAndLayoutTree();
  // disconnectClient() might have been called.
  if (!m_ownerElement)
    return;
  m_needsUpdate = false;

  if (!ownerElement()
           .document()
           .frame()
           ->view()
           ->visibleContentRect()
           .intersects(ownerElement().pixelSnappedBoundingBox())) {
    hide();
    return;
  }

  RefPtr<SharedBuffer> data = SharedBuffer::create();
  PagePopupClient::addString("window.updateData = {\n", data.get());
  PagePopupClient::addString("type: \"update\",\n", data.get());
  ItemIterationContext context(*m_ownerElement->computedStyle(), data.get());
  context.serializeBaseStyle();
  PagePopupClient::addString("children: [", data.get());
  const HeapVector<Member<HTMLElement>>& items = m_ownerElement->listItems();
  for (; context.m_listIndex < items.size(); ++context.m_listIndex) {
    Element& child = *items[context.m_listIndex];
    if (!isHTMLOptGroupElement(child.parentNode()))
      context.finishGroupIfNecessary();
    if (isHTMLOptionElement(child))
      addOption(context, toHTMLOptionElement(child));
    else if (isHTMLOptGroupElement(child))
      addOptGroup(context, toHTMLOptGroupElement(child));
    else if (isHTMLHRElement(child))
      addSeparator(context, toHTMLHRElement(child));
  }
  context.finishGroupIfNecessary();
  PagePopupClient::addString("],\n", data.get());
  IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(
      m_ownerElement->visibleBoundsInVisualViewport(),
      ownerElement().document().view());
  addProperty("anchorRectInScreen", anchorRectInScreen, data.get());
  PagePopupClient::addString("}\n", data.get());
  m_popup->postMessage(String::fromUTF8(data->data(), data->size()));
}
예제 #10
0
void PopupMenuImpl::updateFromElement(UpdateReason) {
  if (m_needsUpdate)
    return;
  m_needsUpdate = true;
  ownerElement().document().postTask(
      BLINK_FROM_HERE,
      createSameThreadTask(&PopupMenuImpl::update, wrapPersistent(this)));
}
예제 #11
0
void PopupMenuImpl::writeDocument(SharedBuffer* data)
{
    IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elementRectRelativeToViewport());

    PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
    data->append(Platform::current()->loadResource("pickerCommon.css"));
    data->append(Platform::current()->loadResource("listPicker.css"));
    PagePopupClient::addString("</style></head><body><div id=main>Loading...</div><script>\n"
        "window.dialogArguments = {\n", data);
    addProperty("selectedIndex", m_client->selectedIndex(), data);
    PagePopupClient::addString("children: [\n", data);
    bool enableExtraStyling = !hasTooManyItemsForStyling();
    for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) {
        if (isHTMLOptionElement(child))
            addOption(toHTMLOptionElement(child), enableExtraStyling, data);
        if (isHTMLOptGroupElement(child))
            addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data);
        if (isHTMLHRElement(child))
            addSeparator(toHTMLHRElement(child), enableExtraStyling, data);
    }
    PagePopupClient::addString("],\n", data);
    addProperty("anchorRectInScreen", anchorRectInScreen, data);
    const ComputedStyle* ownerStyle = ownerElement().computedStyle();
    Color backgroundColor = ownerStyle->visitedDependentColor(CSSPropertyBackgroundColor);
#if OS(LINUX)
    // On other platforms, the <option> background color is the same as the
    // <select> background color. On Linux, that makes the <option>
    // background color very dark, so by default, try to use a lighter
    // background color for <option>s.
    if (LayoutTheme::theme().systemColor(CSSValueButtonface) == backgroundColor)
        backgroundColor = LayoutTheme::theme().systemColor(CSSValueMenu);
#endif
    addProperty("backgroundColor", backgroundColor.serialized(), data);
    bool isRTL = !ownerStyle->isLeftToRightDirection();
    addProperty("isRTL", isRTL, data);
    addProperty("paddingStart", isRTL ? m_client->clientPaddingRight().toDouble() : m_client->clientPaddingLeft().toDouble(), data);
    PagePopupClient::addString("};\n", data);
    data->append(Platform::current()->loadResource("pickerCommon.js"));
    data->append(Platform::current()->loadResource("listPicker.js"));
    PagePopupClient::addString("</script></body>\n", data);
}
예제 #12
0
void PopupMenuImpl::setValueAndClosePopup(int numValue, const String& stringValue)
{
    ASSERT(m_popup);
    ASSERT(m_ownerElement);
    EventQueueScope scope;
    RefPtrWillBeRawPtr<PopupMenuImpl> protector(this);
    bool success;
    int listIndex = stringValue.toInt(&success);
    ASSERT(success);
    m_ownerElement->valueChanged(listIndex);
    if (m_popup)
        m_chromeClient->closePagePopup(m_popup);
    // We dispatch events on the owner element to match the legacy behavior.
    // Other browsers dispatch click events before and after showing the popup.
    if (m_ownerElement) {
        PlatformMouseEvent event;
        RefPtrWillBeRawPtr<Element> owner = &ownerElement();
        owner->dispatchMouseEvent(event, EventTypeNames::mouseup);
        owner->dispatchMouseEvent(event, EventTypeNames::click);
    }
}
void ExternalPopupMenu::didAcceptIndices(const WebVector<int>& indices)
{
    if (!m_ownerElement) {
        m_webExternalPopupMenu = 0;
        return;
    }

    // Calling methods on the HTMLSelectElement might lead to this object being
    // derefed. This ensures it does not get deleted while we are running this
    // method.
    RefPtrWillBeRawPtr<ExternalPopupMenu> protect(this);
    RefPtrWillBeRawPtr<HTMLSelectElement> ownerElement(m_ownerElement.get());
    ownerElement->popupDidHide();

    if (indices.size() == 0) {
        ownerElement->valueChanged(static_cast<unsigned>(-1));
    } else {
        for (size_t i = 0; i < indices.size(); ++i)
            ownerElement->listBoxSelectItem(toPopupMenuItemIndex(indices[i], *ownerElement), (i > 0), false, (i == indices.size() - 1));
    }

    m_webExternalPopupMenu = 0;
}
예제 #14
0
void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document)
{
    Document& ownerDocument = ownerElement().document();
    document.styleEngine().setFontSelector(PopupMenuCSSFontSelector::create(&document, ownerDocument.styleEngine().fontSelector()));
}