Пример #1
0
void DragAndDropHandler::dragLeave(GdkDragContext* context)
{
    DroppingContext* droppingContext = m_droppingContexts.get(context);
    if (!droppingContext)
        return;

    // During a drop GTK+ will fire a drag-leave signal right before firing
    // the drag-drop signal. We want the actions for drag-leave to happen after
    // those for drag-drop, so schedule them to happen asynchronously here.
#if 0 //ZRL replace this.
    GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] handleDragLeaveLater", [this, droppingContext]() {
        auto it = m_droppingContexts.find(droppingContext->gdkContext);
        if (it == m_droppingContexts.end())
            return;

        // If the view doesn't know about the drag yet (there are still pending data requests),
        // don't update it with information about the drag.
        if (droppingContext->pendingDataRequests)
            return;

        if (!droppingContext->dropHappened) {
            // Don't call dragExited if we have just received a drag-drop signal. This
            // happens in the case of a successful drop onto the view.
            const IntPoint& position = droppingContext->lastMotionPosition;
            DragData dragData(droppingContext->dataObject.get(), position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), DragOperationNone);
            m_page.dragExited(dragData);
            m_page.resetCurrentDragInformation();
        }

        m_droppingContexts.remove(it);
    });
#else
    GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] handleDragLeaveLater", std::function<void()>([this, droppingContext]() {
        auto it = m_droppingContexts.find(droppingContext->gdkContext);
        if (it == m_droppingContexts.end())
            return;

        // If the view doesn't know about the drag yet (there are still pending data requests),
        // don't update it with information about the drag.
        if (droppingContext->pendingDataRequests)
            return;

        if (!droppingContext->dropHappened) {
            // Don't call dragExited if we have just received a drag-drop signal. This
            // happens in the case of a successful drop onto the view.
            const IntPoint& position = droppingContext->lastMotionPosition;
            DragData dragData(droppingContext->dataObject.get(), position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), DragOperationNone);
            m_page.dragExited(dragData);
            m_page.resetCurrentDragInformation();
        }

        m_droppingContexts.remove(it);
    }));
#endif
}
Пример #2
0
IntPoint PageClientImpl::screenToWindow(const IntPoint& point)
{
    IntPoint widgetPositionOnScreen = convertWidgetPointToScreenPoint(m_viewWidget, IntPoint());
    IntPoint result(point);
    result.move(-widgetPositionOnScreen.x(), -widgetPositionOnScreen.y());
    return result;
}
void WebContextMenuProxyGtk::showContextMenu()
{
    Vector<RefPtr<WebContextMenuItem>> proposedAPIItems;
    for (auto& item : m_context.menuItems()) {
        if (item.action() != ContextMenuItemTagShareMenu)
            proposedAPIItems.append(WebContextMenuItem::create(item));
    }

    Vector<RefPtr<WebContextMenuItem>> clientItems;
    bool useProposedItems = true;

    if (m_page->contextMenuClient().getContextMenuFromProposedMenu(*m_page, proposedAPIItems, clientItems, m_context.webHitTestResultData(), m_page->process().transformHandlesToObjects(m_userData.object()).get()))
        useProposedItems = false;

    const Vector<RefPtr<WebContextMenuItem>>& items = useProposedItems ? proposedAPIItems : clientItems;

    if (!items.isEmpty())
        populate(items);

    if (!m_menu.itemCount())
        return;

    m_popupPosition = convertWidgetPointToScreenPoint(m_webView, m_context.menuLocation());

    // Display menu initiated by right click (mouse button pressed = 3).
    NativeWebMouseEvent* mouseEvent = m_page->currentlyProcessedMouseDownEvent();
    const GdkEvent* event = mouseEvent ? mouseEvent->nativeEvent() : 0;
    gtk_menu_attach_to_widget(m_menu.platformDescription(), GTK_WIDGET(m_webView), 0);
    gtk_menu_popup(m_menu.platformDescription(), 0, 0, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this,
                   event ? event->button.button : 3, event ? event->button.time : GDK_CURRENT_TIME);
}
IntPoint ChromeClient::screenToRootView(const IntPoint& point) const
{
    IntPoint widgetPositionOnScreen = convertWidgetPointToScreenPoint(GTK_WIDGET(m_webView), IntPoint());
    IntPoint result(point);
    result.move(-widgetPositionOnScreen.x(), -widgetPositionOnScreen.y());
    return result;
}
Пример #5
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());

    GOwnPtr<GdkEvent> currentEvent(gtk_get_current_event());
    m_popup->popUp(rect.size(), menuPosition, size, index, currentEvent.get());

    // 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();
}
Пример #6
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());
}
Пример #7
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;
    }
}
Пример #8
0
void DragAndDropHandler::dragMotion(GdkDragContext* context, const IntPoint& position, unsigned time)
{
    DataObjectGtk* dataObject = requestDragData(context, position, time);
    if (!dataObject)
        return;

    DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
    m_page.dragUpdated(dragData);
    DragOperation operation = m_page.currentDragOperation();
    gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
}
Пример #9
0
void DragAndDropHandler::dragEntered(GdkDragContext* context, GtkSelectionData* selectionData, unsigned info, unsigned time)
{
    IntPoint position;
    DataObjectGtk* dataObject = dataObjectForDropData(context, selectionData, info, position);
    if (!dataObject)
        return;

    DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
    m_page.resetCurrentDragInformation();
    m_page.dragEntered(dragData);
    DragOperation operation = m_page.currentDragOperation();
    gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
}
Пример #10
0
bool DragAndDropHandler::drop(GdkDragContext* context, const IntPoint& position, unsigned time)
{
    DroppingContext* droppingContext = m_droppingContexts.get(context);
    if (!droppingContext)
        return false;

    droppingContext->dropHappened = true;

    DragData dragData(droppingContext->selectionData.ptr(), position, convertWidgetPointToScreenPoint(m_page.viewWidget(), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
    SandboxExtension::Handle handle;
    SandboxExtension::HandleArray sandboxExtensionForUpload;
    m_page.performDragOperation(dragData, String(), handle, sandboxExtensionForUpload);
    gtk_drag_finish(context, TRUE, FALSE, time);
    return true;
}
void WebContextMenuProxyGtk::showContextMenu(const WebCore::IntPoint& position, const Vector<WebContextMenuItemData>& items)
{
    if (!items.isEmpty())
        populate(items);

    if (!m_menu.itemCount())
        return;

    m_popupPosition = convertWidgetPointToScreenPoint(m_webView, position);

    // Display menu initiated by right click (mouse button pressed = 3).
    NativeWebMouseEvent* mouseEvent = m_page->currentlyProcessedMouseDownEvent();
    const GdkEvent* event = mouseEvent ? mouseEvent->nativeEvent() : 0;
    gtk_menu_attach_to_widget(m_menu.platformDescription(), GTK_WIDGET(m_webView), 0);
    gtk_menu_popup(m_menu.platformDescription(), 0, 0, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this,
                   event ? event->button.button : 3, event ? event->button.time : GDK_CURRENT_TIME);
}
Пример #12
0
void GtkDragAndDropHelper::handleDragLeaveLater(DroppingContext* context)
{
    auto iterator = m_droppingContexts.find(context->gdkContext);
    if (iterator == m_droppingContexts.end())
        return;

    // If the view doesn't know about the drag yet (there are still pending data)
    // requests, don't update it with information about the drag.
    if (context->pendingDataRequests)
        return;

    const IntPoint& position = context->lastMotionPosition;
    DragData dragData(context->dataObject.get(), position,
                      convertWidgetPointToScreenPoint(m_widget, position),
                      DragOperationNone);
    context->exitedCallback(m_widget, dragData, context->dropHappened);

    m_droppingContexts.remove(iterator);
}
Пример #13
0
IntRect PageClientImpl::windowToScreen(const IntRect& rect)
{
    return IntRect(convertWidgetPointToScreenPoint(m_viewWidget, rect.location()), rect.size());
}
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);
    }

    gulong unmapHandler = g_signal_connect(m_popup, "unmap", G_CALLBACK(menuUnmapped), this);

    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 = TRUE;
        }, &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;
    }

    // WebPageProxy expects the menu to run in a nested run loop, since it invalidates the
    // menu right after calling WebPopupMenuProxy::showPopupMenu().
    m_runLoop = adoptGRef(g_main_loop_new(nullptr, FALSE));

// This is to suppress warnings about gdk_threads_leave and gdk_threads_enter.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    gdk_threads_leave();
    g_main_loop_run(m_runLoop.get());
    gdk_threads_enter();
#pragma GCC diagnostic pop

    m_runLoop.clear();

    g_signal_handler_disconnect(m_popup, unmapHandler);

    if (!m_client)
        return;

    m_client->valueChangedForPopupMenu(this, m_activeItem);
}
IntRect ChromeClient::rootViewToScreen(const IntRect& rect) const
{
    return IntRect(convertWidgetPointToScreenPoint(GTK_WIDGET(m_webView), rect.location()), rect.size());
}