Ejemplo n.º 1
0
void PopupContainer::showInRect(const IntRect& r, FrameView* v, int index)
{
    // The rect is the size of the select box. It's usually larger than we need.
    // subtract border size so that usually the container will be displayed
    // exactly the same width as the select box.
    listBox()->setBaseWidth(max(r.width() - kBorderSize * 2, 0));

    listBox()->updateFromElement();

    // We set the selected item in updateFromElement(), and disregard the
    // index passed into this function (same as Webkit's PopupMenuWin.cpp)
    // FIXME: make sure this is correct, and add an assertion.
    // ASSERT(popupWindow(popup)->listBox()->selectedIndex() == index);

    // Convert point to main window coords.
    IntPoint location = v->contentsToWindow(r.location());

    // Move it below the select widget.
    location.move(0, r.height());

    m_originalFrameRect = IntRect(location, r.size());

    // Position at (0, 0) since the frameRect().location() is relative to the parent WebWidget.
    setFrameRect(IntRect(IntPoint(), r.size()));
    showPopup(v);
}
Ejemplo n.º 2
0
IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const
{
    ASSERT(m_effectBuffer);
    IntPoint location = m_absolutePaintRect.location();
    location.move(-effectRect.x(), -effectRect.y());
    return IntRect(location, m_effectBuffer->size());
}
Ejemplo n.º 3
0
IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
{
    IntPoint newPoint = parentPoint;
    // Scrollbars won't be transformed within us
    newPoint.move(-scrollbar->location());
    return newPoint;
}
Ejemplo n.º 4
0
ScrollbarPart PlatformScrollbar::hitTest(const PlatformMouseEvent& evt)
{
    if (!isEnabled())
        return NoPart;

    IntPoint mousePosition = convertFromContainingWindow(evt.pos());
    mousePosition.move(x(), y());

    if (hasButtons()) {
        if (backButtonRect().contains(mousePosition))
            return BackButtonPart;

        if (forwardButtonRect().contains(mousePosition))
            return ForwardButtonPart;
    }

    if (!hasThumb())
        return NoPart;

    IntRect track = trackRect();
    if (track.contains(mousePosition)) {
        IntRect beforeThumbRect, thumbRect, afterThumbRect;
        splitTrack(track, beforeThumbRect, thumbRect, afterThumbRect);
        if (beforeThumbRect.contains(mousePosition))
            return BackTrackPart;
        if (thumbRect.contains(mousePosition))
            return ThumbPart;
        return ForwardTrackPart;
    }
    return NoPart;
}
void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index)
{
    ASSERT(client());

    if (!m_popup) {
        m_popup = GtkPopupMenu::create();
        g_signal_connect(m_popup->platformMenu(), "unmap", G_CALLBACK(PopupMenuGtk::menuUnmapped), this);
    } else
        m_popup->clear();

    const int size = client()->listSize();
    for (int i = 0; i < size; ++i) {
        if (client()->itemIsSeparator(i))
            m_popup->appendSeparator();
        else {
            GRefPtr<GtkAction> action = adoptGRef(createGtkActionForMenuItem(i));
            m_popup->appendItem(action.get());
        }
    }

    IntPoint menuPosition = convertWidgetPointToScreenPoint(GTK_WIDGET(view->hostWindow()->platformPageClient()), view->contentsToWindow(rect.location()));
    menuPosition.move(0, rect.height());

    m_popup->popUp(rect.size(), menuPosition, size, index, gtk_get_current_event());

    // GTK can refuse to actually open the menu when mouse grabs fails.
    // Ensure WebCore does not go into some pesky state.
    if (!gtk_widget_get_visible(m_popup->platformMenu()))
        client()->popupDidHide();
}
Ejemplo n.º 6
0
// FIXME: test these on windows
IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
{
    // Scrollbars won't be transformed within us
    IntPoint newPoint = localPoint;
    newPoint.move(scrollbar->location());
    return newPoint;
}
Ejemplo n.º 7
0
void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index)
{
    ASSERT(client());

    if (!m_popup) {
        m_popup = GtkPopupMenu::create();
        g_signal_connect(m_popup->platformMenu(), "unmap", G_CALLBACK(PopupMenuGtk::menuUnmapped), this);
    } else
        m_popup->clear();

    const int size = client()->listSize();
    for (int i = 0; i < size; ++i) {
        if (client()->itemIsSeparator(i))
            m_popup->appendSeparator();
        else {
            GRefPtr<GtkAction> action = adoptGRef(createGtkActionForMenuItem(i));
            m_popup->appendItem(action.get());
        }
    }

    IntPoint menuPosition = convertWidgetPointToScreenPoint(GTK_WIDGET(view->hostWindow()->platformPageClient()), view->contentsToWindow(rect.location()));
    menuPosition.move(0, rect.height());

    m_popup->popUp(rect.size(), menuPosition, size, index, gtk_get_current_event());
}
// Tests moving extent over to the other side of the vase and immediately
// passing the word boundary and going into word granularity.
TEST_F(GranularityStrategyTest, DirectionSwitchSideWordGranularityThenShrink)
{
    dummyPageHolder().frame().settings()->setDefaultFontSize(12);
    String str = "ab cd efghijkl mnopqr iiin, abc";
    RawPtr<Text> text = document().createTextNode(str);
    document().body()->appendChild(text);
    dummyPageHolder().frame().settings()->setSelectionStrategy(SelectionStrategy::Direction);

    parseText(text.get());

    // "abcd efgh ijkl mno^pqr|> iiin, abc" (^ means base, | means extent, < means start, and > means end).
    selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 21)));
    EXPECT_EQ_SELECTED_TEXT("pqr");
    // Move to the middle of word #4 selecting it - this will set the offset to
    // be half the width of "iiin".
    selection().moveRangeSelectionExtent(m_wordMiddles[4]);
    EXPECT_EQ_SELECTED_TEXT("pqr iiin");
    // Move to the middle of word #2 - extent will switch over to the other
    // side of the base, and we should enter word granularity since we pass
    // the word boundary. The offset should become negative since the width
    // of "efghjkkl" is greater than that of "iiin".
    int offset = m_letterPos[26].x() - m_wordMiddles[4].x();
    IntPoint p = IntPoint(m_wordMiddles[2].x() - offset - 1, m_wordMiddles[2].y());
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("efghijkl mno");
    p.move(m_letterPos[7].x() - m_letterPos[6].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("fghijkl mno");
}
Ejemplo n.º 9
0
ScrollbarPart PlatformScrollbar::hitTest(const PlatformMouseEvent& evt)
{
    ScrollbarPart result = NoPart;
    if (!isEnabled() || !parent())
        return result;

    IntPoint mousePosition = convertFromContainingWindow(evt.pos());
    mousePosition.move(x(), y());
    if (backButtonRect().contains(mousePosition))
        result = BackButtonPart;
    else if (forwardButtonRect().contains(mousePosition))
        result = ForwardButtonPart;
    else {
        IntRect track = trackRect();
        if (track.contains(mousePosition)) {
            IntRect beforeThumbRect, thumbRect, afterThumbRect;
            splitTrack(track, beforeThumbRect, thumbRect, afterThumbRect);
            if (beforeThumbRect.contains(mousePosition))
                result = BackTrackPart;
            else if (thumbRect.contains(mousePosition))
                result = ThumbPart;
            else
                result = ForwardTrackPart;
        }
    }
    return result;
}
Ejemplo n.º 10
0
bool RenderThemeGtk::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
    GraphicsContext* context = paintInfo.context;

    context->fillRect(FloatRect(r), m_panelColor, ColorSpaceDeviceRGB);
    context->fillRect(FloatRect(IntRect(r.x(), r.y() + (r.height() - m_mediaSliderHeight) / 2,
                                        r.width(), m_mediaSliderHeight)), m_sliderColor, ColorSpaceDeviceRGB);

    RenderStyle* style = o->style();
    HTMLMediaElement* mediaElement = toParentMediaElement(o);

    if (!mediaElement)
        return false;

    // Draw the buffered ranges. This code is highly inspired from
    // Chrome for the gradient code.
    float mediaDuration = mediaElement->duration();
    RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
    IntRect trackRect = r;
    int totalWidth = trackRect.width();

    trackRect.inflate(-style->borderLeftWidth());
    context->save();
    context->setStrokeStyle(NoStroke);

    for (unsigned index = 0; index < timeRanges->length(); ++index) {
        ExceptionCode ignoredException;
        float start = timeRanges->start(index, ignoredException);
        float end = timeRanges->end(index, ignoredException);
        int width = ((end - start) * totalWidth) / mediaDuration;
        IntRect rangeRect;
        if (!index) {
            rangeRect = trackRect;
            rangeRect.setWidth(width);
        } else {
            rangeRect.setLocation(IntPoint(trackRect.x() + start / mediaDuration* totalWidth, trackRect.y()));
            rangeRect.setSize(IntSize(width, trackRect.height()));
        }

        // Don't bother drawing empty range.
        if (rangeRect.isEmpty())
            continue;

        IntPoint sliderTopLeft = rangeRect.location();
        IntPoint sliderTopRight = sliderTopLeft;
        sliderTopRight.move(0, rangeRect.height());

        RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight);
        Color startColor = m_panelColor;
        gradient->addColorStop(0.0, startColor);
        gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha()));

        context->setFillGradient(gradient);
        context->fillRect(rangeRect);
    }

    context->restore();
    return false;
}
Ejemplo n.º 11
0
void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const
{
    // Search up the parent chain and create a vector of all scrollable parent objects
    // and ending with this object itself.
    Vector<const AXObject*> objects;
    AXObject* parentObject;
    for (parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) {
        if (parentObject->getScrollableAreaIfScrollable())
            objects.prepend(parentObject);
    }
    objects.append(this);

    // Start with the outermost scrollable (the main window) and try to scroll the
    // next innermost object to the given point.
    int offsetX = 0, offsetY = 0;
    IntPoint point = globalPoint;
    size_t levels = objects.size() - 1;
    for (size_t i = 0; i < levels; i++) {
        const AXObject* outer = objects[i];
        const AXObject* inner = objects[i + 1];

        ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable();

        LayoutRect innerRect = inner->isAXScrollView() ? inner->parentObject()->elementRect() : inner->elementRect();
        LayoutRect objectRect = innerRect;
        IntPoint scrollPosition = scrollableArea->scrollPosition();

        // Convert the object rect into local coordinates.
        objectRect.move(offsetX, offsetY);
        if (!outer->isAXScrollView())
            objectRect.move(scrollPosition.x(), scrollPosition.y());

        int desiredX = computeBestScrollOffset(
            0,
            objectRect.x(), objectRect.maxX(),
            objectRect.x(), objectRect.maxX(),
            point.x(), point.x());
        int desiredY = computeBestScrollOffset(
            0,
            objectRect.y(), objectRect.maxY(),
            objectRect.y(), objectRect.maxY(),
            point.y(), point.y());
        outer->scrollTo(IntPoint(desiredX, desiredY));

        if (outer->isAXScrollView() && !inner->isAXScrollView()) {
            // If outer object we just scrolled is a scroll view (main window or iframe) but the
            // inner object is not, keep track of the coordinate transformation to apply to
            // future nested calculations.
            scrollPosition = scrollableArea->scrollPosition();
            offsetX -= (scrollPosition.x() + point.x());
            offsetY -= (scrollPosition.y() + point.y());
            point.move(scrollPosition.x() - innerRect.x(), scrollPosition.y() - innerRect.y());
        } else if (inner->isAXScrollView()) {
            // Otherwise, if the inner object is a scroll view, reset the coordinate transformation.
            offsetX = 0;
            offsetY = 0;
        }
    }
}
IntPoint visiblePositionToContentsPoint(const VisiblePosition& pos)
{
    IntPoint result = absoluteCaretBoundsOf(pos).minXMaxYCorner();
    // Need to move the point at least by 1 - caret's minXMaxYCorner is not
    // evaluated to the same line as the text by hit testing.
    result.move(0, -1);
    return result;
}
bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction)
{
    // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point
    // was on the control but not on the inner element (see Radar 4617841).

    // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block,
    // and act as if we've hit the close block if we're to the right of the inner text block.

    if (!RenderTextControl::nodeAtPoint(request, result, xPos, yPos, tx, ty, hitTestAction))
        return false;

    // If we hit a node inside the inner text element, say that we hit that element,
    // and if we hit our node (e.g. we're over the border or padding), also say that we hit the
    // inner text element so that it gains focus.
    if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node())
        hitInnerTextElement(result, xPos, yPos, tx, ty);

    // If we're not a search field, or we already found the results or cancel buttons, we're done.
    if (!m_innerBlock || result.innerNode() == m_resultsButton || result.innerNode() == m_cancelButton)
        return true;

    Node* innerNode = 0;
    RenderBox* innerBlockRenderer = m_innerBlock->renderBox();
    RenderBox* innerTextRenderer = innerTextElement()->renderBox();

    IntPoint localPoint = result.localPoint();
    localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y());

    int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x();
    if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft)
        innerNode = m_resultsButton.get();

    if (!innerNode) {
        int textRight = textLeft + innerTextRenderer->width();
        if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight)
            innerNode = m_cancelButton.get();
    }

    if (innerNode) {
        result.setInnerNode(innerNode);
        localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y());
    }

    result.setLocalPoint(localPoint);
    return true;
}
Ejemplo n.º 14
0
static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
    HTMLMediaElement* mediaElement = toParentMediaElement(object);
    if (!mediaElement)
        return false;

    RenderStyle* style = object->style();
    GraphicsContext* context = paintInfo.context;

    // Draw the border of the time bar.
    // FIXME: this should be a rounded rect but need to fix GraphicsContextSkia first.
    // https://bugs.webkit.org/show_bug.cgi?id=30143
    context->save();
    context->setShouldAntialias(true);
    context->setStrokeStyle(SolidStroke);
    context->setStrokeColor(style->visitedDependentColor(CSSPropertyBorderLeftColor), ColorSpaceDeviceRGB);
    context->setStrokeThickness(style->borderLeftWidth());
    context->setFillColor(style->visitedDependentColor(CSSPropertyBackgroundColor), ColorSpaceDeviceRGB);
    context->drawRect(rect);
    context->restore();

    // Draw the buffered ranges.
    // FIXME: Draw multiple ranges if there are multiple buffered ranges.
    IntRect bufferedRect = rect;
    bufferedRect.inflate(-style->borderLeftWidth());

    double bufferedWidth = 0.0;
    if (mediaElement->percentLoaded() > 0.0) {
        // Account for the width of the slider thumb.
        Image* mediaSliderThumb = getMediaSliderThumb();
        double thumbWidth = mediaSliderThumb->width() / 2.0 + 1.0;
        double rectWidth = bufferedRect.width() - thumbWidth;
        if (rectWidth < 0.0)
            rectWidth = 0.0;
        bufferedWidth = rectWidth * mediaElement->percentLoaded() + thumbWidth;
    }
    bufferedRect.setWidth(bufferedWidth);

    // Don't bother drawing an empty area.
    if (!bufferedRect.isEmpty()) {
        IntPoint sliderTopLeft = bufferedRect.location();
        IntPoint sliderTopRight = sliderTopLeft;
        sliderTopRight.move(0, bufferedRect.height());

        RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight);
        Color startColor = object->style()->visitedDependentColor(CSSPropertyColor);
        gradient->addColorStop(0.0, startColor);
        gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha()));

        context->save();
        context->setStrokeStyle(NoStroke);
        context->setFillGradient(gradient);
        context->fillRect(bufferedRect);
        context->restore();
    }

    return true;
}
Ejemplo n.º 15
0
bool ScrollbarTheme::shouldSnapBackToDragOrigin(
    const ScrollbarThemeClient& scrollbar,
    const PlatformMouseEvent& evt) {
  IntPoint mousePosition = scrollbar.convertFromRootFrame(evt.position());
  mousePosition.move(scrollbar.x(), scrollbar.y());
  return Platform::current()->scrollbarBehavior()->shouldSnapBackToDragOrigin(
      mousePosition, trackRect(scrollbar),
      scrollbar.orientation() == HorizontalScrollbar);
}
Ejemplo n.º 16
0
IntPoint ChromeClientBlackBerry::screenToRootView(const IntPoint& screenPos) const
{
    IntPoint windowPoint;
    if (Window* window = m_webPagePrivate->m_client->window())
        windowPoint = window->windowLocation();

    windowPoint.move(-screenPos.x(), -screenPos.y());
    return windowPoint;
}
bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction)
{
    // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point
    // was on the control but not on the inner element (see Radar 4617841).

    // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block,
    // and act as if we've hit the close block if we're to the right of the inner text block.

    if (!RenderTextControl::nodeAtPoint(request, result, xPos, yPos, tx, ty, hitTestAction))
        return false;

    if (result.innerNode() != element() && result.innerNode() != m_innerBlock.get())
        return false;

    hitInnerTextBlock(result, xPos, yPos, tx, ty);

    if (!m_innerBlock)
        return true;

    Node* innerNode = 0;
    RenderBox* innerBlockRenderer = m_innerBlock->renderBox();
    RenderBox* innerTextRenderer = innerTextElement()->renderBox();

    IntPoint localPoint = result.localPoint();
    localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y());

    int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x();
    if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft)
        innerNode = m_resultsButton.get();

    if (!innerNode) {
        int textRight = textLeft + innerTextRenderer->width();
        if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight)
            innerNode = m_cancelButton.get();
    }

    if (innerNode) {
        result.setInnerNode(innerNode);
        localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y());
    }

    result.setLocalPoint(localPoint);
    return true;
}
// Tests moving selection extent over to the other side of the base
// on text "abcd efgh ijkl mno^pqr|> iiinmni, abc"
// (^ means base, | means extent, < means start, and > means end).
// Text needs to be laid out on a single line with no rotation.
void GranularityStrategyTest::testDirectionSwitchSide()
{
    // Move to the middle of word #4, selecting it - this will set the offset to
    // be half the width of "iiinmni.
    selection().moveRangeSelectionExtent(m_wordMiddles[4]);
    EXPECT_EQ_SELECTED_TEXT("pqr iiinmni");
    // Move back leaving only one letter selected.
    IntPoint p = m_wordMiddles[4];
    p.move(m_letterPos[19].x() - m_letterPos[29].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("p");
    // Confirm selection doesn't change if extent is positioned at base.
    p.move(m_letterPos[18].x() - m_letterPos[19].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("p");
    // Move over to the other side of the base. Confirm the offset is preserved.
    // (i.e. the selection start stays on the right of the extent)
    // Confirm we stay in character granularity until the beginning of the word
    // is passed.
    p.move(m_letterPos[17].x() - m_letterPos[18].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("o");
    p.move(m_letterPos[16].x() - m_letterPos[17].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("no");
    p.move(m_letterPos[14].x() - m_letterPos[16].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT(" mno");
    // Move to just one pixel on the right before the middle of the word #2.
    // We should switch to word granularity, so the selection shouldn't change.
    p.move(m_wordMiddles[2].x() - m_letterPos[14].x() + 1, 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT(" mno");
    // Move over the middle of the word. The word should get selected.
    // This should reduce the offset, but it should still stay greated than 0,
    // since the width of "iiinmni" is greater than the width of "ijkl".
    p.move(-2, 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("ijkl mno");
    // Move to just one pixel on the right of the middle of word #1.
    // The selection should now include the space between the words.
    p.move(m_wordMiddles[1].x() - m_letterPos[10].x() + 1, 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT(" ijkl mno");
    // Move over the middle of the word. The word should get selected.
    p.move(-2, 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("efgh ijkl mno");
}
Ejemplo n.º 19
0
void WebPopupMenuProxyGtk::showPopupMenu(const IntRect& rect, TextDirection, double /* pageScaleFactor */, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex)
{
    populatePopupMenu(items);
    gtk_menu_set_active(GTK_MENU(m_popup), selectedIndex);

    resetTypeAheadFindState();


    IntPoint menuPosition = convertWidgetPointToScreenPoint(m_webView, rect.location());
    menuPosition.move(0, rect.height());

    // This approach follows the one in gtkcombobox.c.
    GtkRequisition requisition;
    gtk_widget_set_size_request(m_popup, -1, -1);
    gtk_widget_get_preferred_size(m_popup, &requisition, nullptr);
    gtk_widget_set_size_request(m_popup, std::max(rect.width(), requisition.width), -1);

    if (int itemCount = items.size()) {
        GUniquePtr<GList> children(gtk_container_get_children(GTK_CONTAINER(m_popup)));
        int i;
        GList* child;
        for (i = 0, child = children.get(); i < itemCount; i++, child = g_list_next(child)) {
            if (i > selectedIndex)
                break;

            GtkWidget* item = GTK_WIDGET(child->data);
            GtkRequisition itemRequisition;
            gtk_widget_get_preferred_size(item, &itemRequisition, nullptr);
            menuPosition.setY(menuPosition.y() - itemRequisition.height);
        }
    } else {
        // Center vertically the empty popup in the combo box area.
        menuPosition.setY(menuPosition.y() - rect.height() / 2);
    }

    const GdkEvent* event = m_client->currentlyProcessedMouseDownEvent() ? m_client->currentlyProcessedMouseDownEvent()->nativeEvent() : nullptr;
    gtk_menu_popup_for_device(GTK_MENU(m_popup), event ? gdk_event_get_device(event) : nullptr, nullptr, nullptr,
        [](GtkMenu*, gint* x, gint* y, gboolean* pushIn, gpointer userData) {
            // We can pass a pointer to the menuPosition local variable because the nested main loop ensures this is called in the function context.
            IntPoint* menuPosition = static_cast<IntPoint*>(userData);
            *x = menuPosition->x();
            *y = menuPosition->y();
            *pushIn = menuPosition->y() < 0;
        }, &menuPosition, nullptr, event && event->type == GDK_BUTTON_PRESS ? event->button.button : 1,
        event ? gdk_event_get_time(event) : GDK_CURRENT_TIME);

    // Now that the menu has a position, schedule a resize to make sure it's resized to fit vertically in the work area.
    gtk_widget_queue_resize(m_popup);

    // PopupMenu can fail to open when there is no mouse grab.
    // Ensure WebCore does not go into some pesky state.
    if (!gtk_widget_get_visible(m_popup)) {
       m_client->failedToShowPopupMenu();
       return;
    }
}
IntPoint RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
{
    RenderView* view = box().view();
    if (!view)
        return scrollbarPoint;

    IntPoint point = scrollbarPoint;
    point.move(scrollbarOffset(scrollbar));
    return view->frameView()->convertFromRenderer(box(), point);
}
// DirectionGranularityStrategy strategy on rotated text should revert to the
// same behavior as CharacterGranularityStrategy
TEST_F(GranularityStrategyTest, DirectionRotate)
{
    RefPtrWillBeRawPtr<Text> text = setupRotate("Foo Bar Baz,");
    // "Foo B^a|>r Baz," (^ means base, | means extent, , < means start, and > means end).
    selection().setSelection(VisibleSelection(Position(text, 5), Position(text, 6)));
    EXPECT_EQ_SELECTED_TEXT("a");
    IntPoint p = m_letterPos[9];
    // Need to move by one pixel, otherwise this point is not evaluated
    // to the same line as the text by hit testing.
    p.move(1, 0);
    // "Foo B^ar B|>az,"
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("ar B");
    p = m_letterPos[1];
    p.move(1, 0);
    // "F<|oo B^ar Baz,"
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("oo B");
}
Region ScrollingCoordinator::computeNonFastScrollableRegion(const Frame* frame, const IntPoint& frameLocation) const
{
#if ENABLE(IOS_TOUCH_EVENTS)
    // On iOS, we use nonFastScrollableRegion to represent the region covered by elements with touch event handlers.
    ASSERT(frame->isMainFrame());
    UNUSED_PARAM(frameLocation);

    Document* document = frame->document();
    if (!document)
        return Region();

    Vector<IntRect> touchRects;
    document->getTouchRects(touchRects);
    
    Region touchRegion;
    for (const auto& rect : touchRects)
        touchRegion.unite(rect);

    return touchRegion;
#else
    Region nonFastScrollableRegion;
    FrameView* frameView = frame->view();
    if (!frameView)
        return nonFastScrollableRegion;

    IntPoint offset = frameLocation;
    offset.moveBy(frameView->frameRect().location());
    offset.move(0, frameView->topContentInset());

    if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrollableAreas()) {
        for (FrameView::ScrollableAreaSet::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
            ScrollableArea* scrollableArea = *it;
            // Composited scrollable areas can be scrolled off the main thread.
            if (scrollableArea->usesCompositedScrolling())
                continue;
            IntRect box = scrollableArea->scrollableAreaBoundingBox();
            box.moveBy(offset);
            nonFastScrollableRegion.unite(box);
        }
    }

    for (const auto& child : frameView->children()) {
        if (!child->isPluginViewBase())
            continue;
        PluginViewBase* pluginViewBase = toPluginViewBase(child.get());
        if (pluginViewBase->wantsWheelEvents())
            nonFastScrollableRegion.unite(pluginViewBase->frameRect());
    }

    for (Frame* subframe = frame->tree().firstChild(); subframe; subframe = subframe->tree().nextSibling())
        nonFastScrollableRegion.unite(computeNonFastScrollableRegion(subframe, offset));

    return nonFastScrollableRegion;
#endif
}
IntPoint RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
{
    RenderView* view = box().view();
    if (!view)
        return parentPoint;

    IntPoint point = view->frameView()->convertToRenderer(box(), parentPoint);

    point.move(-scrollbarOffset(scrollbar));
    return point;
}
static void paintSliderRangeHighlight(const IntRect& rect, const RenderStyle* style, GraphicsContext* context, int startPosition, int endPosition, Color startColor, Color endColor)
{
    // Calculate border radius; need to avoid being smaller than half the slider height
    // because of https://bugs.webkit.org/show_bug.cgi?id=30143.
    int borderRadius = rect.height() / 2;
    IntSize radii(borderRadius, borderRadius);

    // Calculate highlight rectangle and edge dimensions.
    int startOffset = startPosition;
    int endOffset = rect.width() - endPosition;
    int rangeWidth = endPosition - startPosition;

    if (rangeWidth <= 0)
        return;

    // Make sure the range width is bigger than border radius at the edges to retain rounded corners.
    if (startOffset < borderRadius && rangeWidth < borderRadius)
        rangeWidth = borderRadius;
    if (endOffset < borderRadius && rangeWidth < borderRadius)
        rangeWidth = borderRadius;

    // Set rectangle to highlight range.
    IntRect highlightRect = rect;
    highlightRect.move(startOffset, 0);
    highlightRect.setWidth(rangeWidth);

    // Don't bother drawing an empty area.
    if (highlightRect.isEmpty())
        return;

    // Calculate white-grey gradient.
    IntPoint sliderTopLeft = highlightRect.location();
    IntPoint sliderBottomLeft = sliderTopLeft;
    sliderBottomLeft.move(0, highlightRect.height());
    RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderBottomLeft);
    gradient->addColorStop(0.0, startColor);
    gradient->addColorStop(1.0, endColor);

    // Fill highlight rectangle with gradient, potentially rounded if on left or right edge.
    context->save();
    context->setFillGradient(gradient);

    if (startOffset < borderRadius && endOffset < borderRadius)
        context->fillRoundedRect(highlightRect, radii, radii, radii, radii, startColor);
    else if (startOffset < borderRadius)
        context->fillRoundedRect(highlightRect, radii, IntSize(0, 0), radii, IntSize(0, 0), startColor);
    else if (endOffset < borderRadius)
        context->fillRoundedRect(highlightRect, IntSize(0, 0), radii, IntSize(0, 0), radii, startColor);
    else
        context->fillRect(highlightRect);

    context->restore();
}
void WebPopupMenuProxyWin::paint(const IntRect& damageRect, HDC hdc)
{
    if (!m_popup)
        return;

    if (!m_DC) {
        m_DC = ::CreateCompatibleDC(::GetDC(m_popup));
        if (!m_DC)
            return;
    }

    if (m_bmp) {
        bool keepBitmap = false;
        BITMAP bitmap;
        if (::GetObject(m_bmp, sizeof(bitmap), &bitmap))
            keepBitmap = bitmap.bmWidth == clientRect().width() && bitmap.bmHeight == clientRect().height();
        if (!keepBitmap) {
            ::DeleteObject(m_bmp);
            m_bmp = 0;
        }
    }

    if (!m_bmp) {
        BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size());
        void* pixels = 0;
        m_bmp = ::CreateDIBSection(m_DC, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
        if (!m_bmp)
            return;
        ::SelectObject(m_DC, m_bmp);
    }

    GraphicsContext context(m_DC);

    IntRect translatedDamageRect = damageRect;
    translatedDamageRect.move(IntSize(0, m_scrollOffset * m_itemHeight));
    m_data.m_notSelectedBackingStore->paint(context, damageRect.location(), translatedDamageRect);

    IntRect selectedIndexRectInBackingStore(0, focusedIndex() * m_itemHeight, m_data.m_selectedBackingStore->size().width(), m_itemHeight);
    IntPoint selectedIndexDstPoint = selectedIndexRectInBackingStore.location();
    selectedIndexDstPoint.move(0, -m_scrollOffset * m_itemHeight);

    m_data.m_selectedBackingStore->paint(context, selectedIndexDstPoint, selectedIndexRectInBackingStore);

    if (m_scrollbar)
        m_scrollbar->paint(&context, damageRect);

    HDC localDC = hdc ? hdc : ::GetDC(m_popup);

    ::BitBlt(localDC, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC, damageRect.x(), damageRect.y(), SRCCOPY);

    if (!hdc)
        ::ReleaseDC(m_popup, localDC);
}
Ejemplo n.º 26
0
void WebCoreDrawDoubledTextAtPoint(GraphicsContext& context, const String& text, const IntPoint& point, const Font& font, const Color& topColor, const Color& bottomColor, int underlinedIndex)
{
    context.save();

    IntPoint textPos = point;

    doDrawTextAtPoint(context, text, textPos, font, bottomColor, underlinedIndex);
    textPos.move(0, -1);
    doDrawTextAtPoint(context, text, textPos, font, topColor, underlinedIndex);

    context.restore();
}
Ejemplo n.º 27
0
IntPoint RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
{
    RenderView* view = this->view();
    if (!view)
        return parentPoint;

    IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);

    int scrollbarLeft = width() - borderRight() - scrollbar->width();
    int scrollbarTop = borderTop();
    point.move(-scrollbarLeft, -scrollbarTop);
    return point;
}
// Tests shrinking selection on text "abcdef ghij kl mno^pqr|> iiinmni, abc"
// (^ means base, | means extent, < means start, and > means end).
// Text needs to be laid out on a single line with no rotation.
void GranularityStrategyTest::testDirectionShrink()
{
    // Move to the middle of word #4 to it and then move back, confirming
    // that the selection end is moving with the extent. The offset between the
    // extent and the selection end will be equal to half the width of "iiinmni".
    selection().moveRangeSelectionExtent(m_wordMiddles[4]);
    EXPECT_EQ_SELECTED_TEXT("pqr iiinmni");
    IntPoint p = m_wordMiddles[4];
    p.move(m_letterPos[28].x() - m_letterPos[29].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("pqr iiinmn");
    p.move(m_letterPos[27].x() - m_letterPos[28].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("pqr iiinm");
    p.move(m_letterPos[26].x() - m_letterPos[27].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("pqr iiin");
    // Move right by the width of char 30 ('m'). Selection shouldn't change,
    // but offset should be reduced.
    p.move(m_letterPos[27].x() - m_letterPos[26].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("pqr iiin");
    // Move back a couple of character widths and confirm the selection still
    // updates accordingly.
    p.move(m_letterPos[25].x() - m_letterPos[26].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("pqr iii");
    p.move(m_letterPos[24].x() - m_letterPos[25].x(), 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("pqr ii");
    // "Catch up" with the handle - move the extent to where the handle is.
    // "abcdef ghij kl mno^pqr ii|>inmni, abc"
    selection().moveRangeSelectionExtent(m_letterPos[24]);
    EXPECT_EQ_SELECTED_TEXT("pqr ii");
    // Move ahead and confirm the selection expands accordingly
    // "abcdef ghij kl mno^pqr iii|>nmni, abc"
    selection().moveRangeSelectionExtent(m_letterPos[25]);
    EXPECT_EQ_SELECTED_TEXT("pqr iii");

    // Confirm we stay in character granularity if the user moves within a word.
    // "abcdef ghij kl mno^pqr |>iiinmni, abc"
    selection().moveRangeSelectionExtent(m_letterPos[22]);
    EXPECT_EQ_SELECTED_TEXT("pqr ");
    // It's possible to get a move when position doesn't change.
    // It shouldn't affect anything.
    p = m_letterPos[22];
    p.move(1, 0);
    selection().moveRangeSelectionExtent(p);
    EXPECT_EQ_SELECTED_TEXT("pqr ");
    // "abcdef ghij kl mno^pqr i|>iinmni, abc"
    selection().moveRangeSelectionExtent(m_letterPos[23]);
    EXPECT_EQ_SELECTED_TEXT("pqr i");
}
Ejemplo n.º 29
0
IntPoint RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
{
    RenderView* view = this->view();
    if (!view)
        return scrollbarPoint;

    IntPoint point = scrollbarPoint;

    int scrollbarLeft = width() - borderRight() - scrollbar->width();
    int scrollbarTop = borderTop();
    point.move(scrollbarLeft, scrollbarTop);

    return view->frameView()->convertFromRenderer(this, point);
}
Ejemplo n.º 30
0
bool ScrollbarThemeWin::shouldSnapBackToDragOrigin(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
{
    // Find the rect within which we shouldn't snap, by expanding the track rect
    // in both dimensions.
    IntRect rect = trackRect(scrollbar);
    const bool horz = scrollbar->orientation() == HorizontalScrollbar;
    const int thickness = scrollbarThickness(scrollbar->controlSize());
    rect.inflateX((horz ? kOffEndMultiplier : kOffSideMultiplier) * thickness);
    rect.inflateY((horz ? kOffSideMultiplier : kOffEndMultiplier) * thickness);

    // Convert the event to local coordinates.
    IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.pos());
    mousePosition.move(scrollbar->x(), scrollbar->y());

    // We should snap iff the event is outside our calculated rect.
    return !rect.contains(mousePosition);
}