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())); }
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())); }
// 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; }
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())); }
void PopupMenuImpl::updateFromElement() { if (m_needsUpdate) return; m_needsUpdate = true; ownerElement().document().postTask(BLINK_FROM_HERE, createSameThreadTask(&PopupMenuImpl::update, PassRefPtrWillBeRawPtr<PopupMenuImpl>(this))); }
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); } }
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())); }
void PopupMenuImpl::updateFromElement(UpdateReason) { if (m_needsUpdate) return; m_needsUpdate = true; ownerElement().document().postTask( BLINK_FROM_HERE, createSameThreadTask(&PopupMenuImpl::update, wrapPersistent(this))); }
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); }
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; }
void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) { Document& ownerDocument = ownerElement().document(); document.styleEngine().setFontSelector(PopupMenuCSSFontSelector::create(&document, ownerDocument.styleEngine().fontSelector())); }