Changeset 213278 in webkit


Ignore:
Timestamp:
Mar 2, 2017 6:20:47 AM (7 years ago)
Author:
tpopela@redhat.com
Message:

[WK2] Keyboard menu key should show context menu
https://bugs.webkit.org/show_bug.cgi?id=72099

Source/WebCore:

Reviewed by Carlos Garcia Campos.

Show the context menu when the GtkWidget::popup-menu signal is
emitted. This signal is triggered by pressing a key (usually
the Menu key or the Shift + F10 shortcut) or it could be emitted on
WebKitWebView.

Test: fast/events/context-activated-by-key-event.html

Also could be tested by:

ManualTests/keyboard-menukey-event.html
ManualTests/win/contextmenu-key.html
ManualTests/win/contextmenu-key2.html

  • page/EventHandler.cpp:

(WebCore::EventHandler::sendContextMenuEventForKey):
Correctly send the mouse event that used for showing the context menu.
Previously the event was immediately dispatched as it is, but this was
only the right way if some element was focused on the page. If there
was no focused element or non-empty text range then the event lacked
the right node, where it was supposed to be shown. The correct node
is determined and added to the event in the sendContextMenuEvent() so
we have to use this function to send the event.

Also use absoluteBoundingBoxRect() instead of
pixelSnappedAbsoluteClippedOverflowRect() when determining
a coordinate where to show the context menu for the currently focus
element. The latter is not returning a right box (it is bigger) which
could lead to the situation that no menu will be displayed at all,
because the HitTest won't contain the right element as the
determined coordinates could be outside of the element.

  • page/EventHandler.h:

Source/WebKit2:

Reviewed by Carlos Garcia Campos.

Show the context menu when the GtkWidget::popup-menu signal is
emitted. This signal is triggered by pressing a key (usually
the Menu key or the Shift + F10 shortcut) or it could be emitted on
WebKitWebView.

  • UIProcess/API/gtk/WebKitWebView.cpp:

(webkit_web_view_class_init):
(webkit_web_view_class_init): Update the documentation for the
context-menu signal

  • UIProcess/API/gtk/WebKitWebViewBase.cpp:

(webkitWebViewBasePopupMenu): Connect to the popup-menu signal and
save the event that was used to trigger the signal. If there is no
such event create a new GdkEvent with GDK_NOTHING type.
(webkitWebViewBasePopupMenu):
(webkit_web_view_base_class_init):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::handleContextMenuKeyEvent):

  • UIProcess/WebPageProxy.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::contextMenuForKeyEvent):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:

Tools:

Show the context menu when the GtkWidget::popup-menu signal is
emitted. This signal is triggered by pressing a key (usually
the Menu key or the Shift + F10 shortcut) or it could be emitted on
WebKitWebView.

Reviewed by Carlos Garcia Campos.

  • TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp:

(testContextMenuDefaultMenu):

  • TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp:

(WebViewTest::emitPopupMenuSignal):

  • TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h:

LayoutTests:

Reviewed by Carlos Garcia Campos.

Skip the fast/events/context-activated-by-key-event.html on Mac as it
does not have a key to activate the context menu and on iOS as well.

  • platform/ios-simulator-wk2/TestExpectations:
  • platform/mac-wk2/TestExpectations:
  • platform/mac/TestExpectations:
Location:
trunk
Files:
2 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r213277 r213278  
     12017-03-02  Tomas Popela  <tpopela@redhat.com>
     2
     3        [WK2] Keyboard menu key should show context menu
     4        https://bugs.webkit.org/show_bug.cgi?id=72099
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Skip the fast/events/context-activated-by-key-event.html on Mac as it
     9        does not have a key to activate the context menu and on iOS as well.
     10
     11        * platform/ios-simulator-wk2/TestExpectations:
     12        * platform/mac-wk2/TestExpectations:
     13        * platform/mac/TestExpectations:
     14
    1152017-03-02  Javier Fernandez  <jfernandez@igalia.com>
    216
  • trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations

    r213253 r213278  
    19171917
    19181918imported/w3c/web-platform-tests/webrtc [ Skip ]
     1919
     1920# Skipped because there is no key to show the context menu
     1921fast/events/context-activated-by-key-event.html [ Skip ]
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r213156 r213278  
    639639webkit.org/b/168391 [ ElCapitan Debug ] storage/indexeddb/modern/idbcursor-continue-primary-key-1.html [ Pass Timeout ]
    640640
     641
    641642webkit.org/b/168380 [ ElCapitan Debug ] imported/w3c/web-platform-tests/IndexedDB/idb-binary-key-roundtrip.htm [ Pass Failure ]
     643
     644# Skipped because Mac doesn't have a key to show the context menu
     645fast/events/context-activated-by-key-event.html [ Skip ]
  • trunk/LayoutTests/platform/mac/TestExpectations

    r213254 r213278  
    15511551
    15521552webkit.org/b/168927 fast/dom/timer-throttling-hidden-page.html [ Pass Failure ]
     1553
     1554# Skipped because Mac doesn't have a key to show the context menu
     1555fast/events/context-activated-by-key-event.html [ Skip ]
  • trunk/Source/WebCore/ChangeLog

    r213276 r213278  
     12017-03-02  Tomas Popela  <tpopela@redhat.com>
     2
     3        [WK2] Keyboard menu key should show context menu
     4        https://bugs.webkit.org/show_bug.cgi?id=72099
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Show the context menu when the GtkWidget::popup-menu signal is
     9        emitted. This signal is triggered by pressing a key (usually
     10        the Menu key or the Shift + F10 shortcut) or it could be emitted on
     11        WebKitWebView.
     12
     13        Test: fast/events/context-activated-by-key-event.html
     14
     15        Also could be tested by:
     16
     17        ManualTests/keyboard-menukey-event.html
     18        ManualTests/win/contextmenu-key.html
     19        ManualTests/win/contextmenu-key2.html
     20
     21        * page/EventHandler.cpp:
     22        (WebCore::EventHandler::sendContextMenuEventForKey):
     23        Correctly send the mouse event that used for showing the context menu.
     24        Previously the event was immediately dispatched as it is, but this was
     25        only the right way if some element was focused on the page. If there
     26        was no focused element or non-empty text range then the event lacked
     27        the right node, where it was supposed to be shown. The correct node
     28        is determined and added to the event in the sendContextMenuEvent() so
     29        we have to use this function to send the event.
     30
     31        Also use absoluteBoundingBoxRect() instead of
     32        pixelSnappedAbsoluteClippedOverflowRect() when determining
     33        a coordinate where to show the context menu for the currently focus
     34        element. The latter is not returning a right box (it is bigger) which
     35        could lead to the situation that no menu will be displayed at all,
     36        because the HitTest won't contain the right element as the
     37        determined coordinates could be outside of the element.
     38        * page/EventHandler.h:
     39
    1402017-03-02  Carlos Garcia Campos  <cgarcia@igalia.com>
    241
  • trunk/Source/WebCore/page/EventHandler.cpp

    r212484 r213278  
    29002900        if (!box)
    29012901            return false;
    2902         IntRect clippedRect = box->pixelSnappedAbsoluteClippedOverflowRect();
    2903         location = IntPoint(clippedRect.x(), clippedRect.maxY() - 1);
     2902
     2903        IntRect boundingBoxRect = box->absoluteBoundingBoxRect(true);
     2904        location = IntPoint(boundingBoxRect.x(), boundingBoxRect.maxY() - 1);
    29042905    } else {
    29052906        location = IntPoint(
     
    29332934    PlatformMouseEvent platformMouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WTF::currentTime(), ForceAtClick, NoTap);
    29342935
    2935     return !dispatchMouseEvent(eventNames().contextmenuEvent, targetNode, true, 0, platformMouseEvent, false);
     2936    return sendContextMenuEvent(platformMouseEvent);
    29362937}
    29372938#endif // ENABLE(CONTEXT_MENUS)
  • trunk/Source/WebCore/page/EventHandler.h

    r212476 r213278  
    235235#if ENABLE(CONTEXT_MENUS)
    236236    WEBCORE_EXPORT bool sendContextMenuEvent(const PlatformMouseEvent&);
    237     bool sendContextMenuEventForKey();
     237    WEBCORE_EXPORT bool sendContextMenuEventForKey();
    238238#endif
    239239
  • trunk/Source/WebKit2/ChangeLog

    r213272 r213278  
     12017-03-02  Tomas Popela  <tpopela@redhat.com>
     2
     3        [WK2] Keyboard menu key should show context menu
     4        https://bugs.webkit.org/show_bug.cgi?id=72099
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Show the context menu when the GtkWidget::popup-menu signal is
     9        emitted. This signal is triggered by pressing a key (usually
     10        the Menu key or the Shift + F10 shortcut) or it could be emitted on
     11        WebKitWebView.
     12
     13        * UIProcess/API/gtk/WebKitWebView.cpp:
     14        (webkit_web_view_class_init):
     15        (webkit_web_view_class_init): Update the documentation for the
     16        context-menu signal
     17        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
     18        (webkitWebViewBasePopupMenu): Connect to the popup-menu signal and
     19        save the event that was used to trigger the signal. If there is no
     20        such event create a new GdkEvent with GDK_NOTHING type.
     21        (webkitWebViewBasePopupMenu):
     22        (webkit_web_view_base_class_init):
     23        * UIProcess/WebPageProxy.cpp:
     24        (WebKit::WebPageProxy::handleContextMenuKeyEvent):
     25        * UIProcess/WebPageProxy.h:
     26        * WebProcess/WebPage/WebPage.cpp:
     27        (WebKit::WebPage::contextMenuForKeyEvent):
     28        * WebProcess/WebPage/WebPage.h:
     29        * WebProcess/WebPage/WebPage.messages.in:
     30
    1312017-03-01  Wenson Hsieh  <wenson_hsieh@apple.com>
    232
  • trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp

    r212345 r213278  
    16171617     * </itemizedlist>
    16181618     *
     1619     * The @event is expected to be one of the following types:
     1620     * <itemizedlist>
     1621     * <listitem><para>
     1622     * a #GdkEventButton of type %GDK_BUTTON_PRESS when the context menu
     1623     * was triggered with mouse.
     1624     * <listitem><para>
     1625     * a #GdkEventKey of type %GDK_KEY_PRESS if the keyboard was used to show
     1626     * the menu.
     1627     * </para></listitem>
     1628     * <listitem><para>
     1629     * a generic #GdkEvent of type %GDK_NOTHING when the #GtkWidget:popup-menu
     1630     * signal was used to show the context menu.
     1631     * </para></listitem>
     1632     * </itemizedlist>
     1633     *
    16191634     * If the signal handler returns %FALSE the context menu represented by @context_menu
    16201635     * will be shown, if it return %TRUE the context menu will not be shown.
  • trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp

    r211669 r213278  
    808808}
    809809
     810static gboolean webkitWebViewBasePopupMenu(GtkWidget* widget)
     811{
     812    WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
     813    WebKitWebViewBasePrivate* priv = webViewBase->priv;
     814
     815    GdkEvent* currentEvent = gtk_get_current_event();
     816    if (!currentEvent)
     817        currentEvent = gdk_event_new(GDK_NOTHING);
     818    priv->contextMenuEvent.reset(currentEvent);
     819    priv->pageProxy->handleContextMenuKeyEvent();
     820
     821    return TRUE;
     822}
     823
    810824static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event)
    811825{
     
    11221136    widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
    11231137    widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
     1138    widgetClass->popup_menu = webkitWebViewBasePopupMenu;
    11241139    widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
    11251140    widgetClass->enter_notify_event = webkitWebViewBaseCrossingNotifyEvent;
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r213168 r213278  
    46554655    m_process->send(Messages::WebPage::DidSelectItemFromActiveContextMenu(item), m_pageID);
    46564656}
     4657
     4658void WebPageProxy::handleContextMenuKeyEvent()
     4659{
     4660    m_process->send(Messages::WebPage::ContextMenuForKeyEvent(), m_pageID);
     4661}
    46574662#endif // ENABLE(CONTEXT_MENUS)
    46584663
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r213036 r213278  
    898898    // Called by the WebContextMenuProxy.
    899899    void contextMenuItemSelected(const WebContextMenuItemData&);
     900    void handleContextMenuKeyEvent();
    900901#endif
    901902
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp

    r212776 r213278  
    22022202    return handled;
    22032203}
     2204
     2205void WebPage::contextMenuForKeyEvent()
     2206{
     2207    corePage()->contextMenuController().clearContextMenu();
     2208
     2209    Frame& frame = m_page->focusController().focusedOrMainFrame();
     2210    bool handled = frame.eventHandler().sendContextMenuEventForKey();
     2211    if (handled)
     2212        contextMenu()->show();
     2213}
    22042214#endif
    22052215
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h

    r212745 r213278  
    10611061#if ENABLE(CONTEXT_MENUS)
    10621062    void contextMenuHidden() { m_isShowingContextMenu = false; }
     1063    void contextMenuForKeyEvent();
    10631064#endif
    10641065
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

    r212745 r213278  
    122122#if ENABLE(CONTEXT_MENUS)
    123123    ContextMenuHidden()
     124    ContextMenuForKeyEvent()
    124125#endif
    125126
  • trunk/Tools/ChangeLog

    r213272 r213278  
     12017-03-02  Tomas Popela  <tpopela@redhat.com>
     2
     3        [WK2] Keyboard menu key should show context menu
     4        https://bugs.webkit.org/show_bug.cgi?id=72099
     5
     6        Show the context menu when the GtkWidget::popup-menu signal is
     7        emitted. This signal is triggered by pressing a key (usually
     8        the Menu key or the Shift + F10 shortcut) or it could be emitted on
     9        WebKitWebView.
     10
     11        Reviewed by Carlos Garcia Campos.
     12
     13        * TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp:
     14        (testContextMenuDefaultMenu):
     15        * TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp:
     16        (WebViewTest::emitPopupMenuSignal):
     17        * TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h:
     18
    1192017-03-01  Wenson Hsieh  <wenson_hsieh@apple.com>
    220
  • trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp

    r212630 r213278  
    3434    {
    3535        g_assert(event);
    36         g_assert_cmpint(event->type, ==, GDK_BUTTON_PRESS);
    37         g_assert_cmpint(event->button.button, ==, 3);
    38         g_assert_cmpint(event->button.x, ==, m_menuPositionX);
    39         g_assert_cmpint(event->button.y, ==, m_menuPositionY);
     36        g_assert_cmpint(event->type, ==, m_expectedEventType);
     37
     38        switch (m_expectedEventType) {
     39        case GDK_BUTTON_PRESS:
     40            g_assert_cmpint(event->button.button, ==, 3);
     41            g_assert_cmpint(event->button.x, ==, m_menuPositionX);
     42            g_assert_cmpint(event->button.y, ==, m_menuPositionY);
     43            break;
     44        case GDK_KEY_PRESS:
     45            g_assert_cmpint(event->key.keyval, ==, GDK_KEY_Menu);
     46            break;
     47        case GDK_NOTHING:
     48            // GDK_NOTHING means that the context menu was triggered by the
     49            // popup-menu signal. We don't have anything to check here.
     50            break;
     51        default:
     52            g_assert_not_reached();
     53        }
    4054    }
    4155
     
    5973        : m_menuPositionX(0)
    6074        , m_menuPositionY(0)
     75        , m_expectedEventType(GDK_BUTTON_PRESS)
    6176    {
    6277        g_signal_connect(m_webView, "context-menu", G_CALLBACK(contextMenuCallback), this);
     
    200215    void showContextMenuAndWaitUntilFinished()
    201216    {
     217        m_expectedEventType = GDK_BUTTON_PRESS;
    202218        showContextMenuAtPositionAndWaitUntilFinished(0, 0);
    203219    }
     
    215231    }
    216232
     233    static gboolean emitPopupMenuSignalIdleCallback(ContextMenuTest* test)
     234    {
     235        test->emitPopupMenuSignal();
     236        return FALSE;
     237    }
     238
     239    void showContextMenuTriggeredByPopupEventAndWaitUntilFinished()
     240    {
     241        m_expectedEventType = GDK_NOTHING;
     242        g_idle_add(reinterpret_cast<GSourceFunc>(emitPopupMenuSignalIdleCallback), this);
     243        g_main_loop_run(m_mainLoop);
     244    }
     245
     246    static gboolean simulateMenuKeyIdleCallback(ContextMenuTest* test)
     247    {
     248        test->keyStroke(GDK_KEY_Menu);
     249        return FALSE;
     250    }
     251
     252    void showContextMenuTriggeredByContextMenuKeyAndWaitUntilFinished()
     253    {
     254        m_expectedEventType = GDK_KEY_PRESS;
     255        g_idle_add(reinterpret_cast<GSourceFunc>(simulateMenuKeyIdleCallback), this);
     256        g_main_loop_run(m_mainLoop);
     257    }
     258
    217259    double m_menuPositionX;
    218260    double m_menuPositionY;
     261    GdkEventType m_expectedEventType;
    219262};
    220263
     
    366409};
    367410
    368 static void testContextMenuDefaultMenu(ContextMenuDefaultTest* test, gconstpointer)
    369 {
    370     test->showInWindowAndWaitUntilMapped();
    371 
     411static void prepareContextMenuTestView(ContextMenuDefaultTest* test)
     412{
    372413    GUniquePtr<char> baseDir(g_strdup_printf("file://%s/", Test::getResourcesDir().data()));
    373414    const char* linksHTML =
     
    389430    test->loadHtml(linksHTML, baseDir.get());
    390431    test->waitUntilLoadFinished();
     432}
     433
     434static void testContextMenuDefaultMenu(ContextMenuDefaultTest* test, gconstpointer)
     435{
     436    test->showInWindowAndWaitUntilMapped();
     437
     438    prepareContextMenuTestView(test);
    391439
    392440    // Context menu for selection.
     
    426474    test->m_expectedMenuType = ContextMenuDefaultTest::Editable;
    427475    test->showContextMenuAtPositionAndWaitUntilFinished(5, 35);
     476}
     477
     478static void testPopupEventSignal(ContextMenuDefaultTest* test, gconstpointer)
     479{
     480    test->showInWindowAndWaitUntilMapped();
     481
     482    prepareContextMenuTestView(test);
     483
     484    test->m_expectedMenuType = ContextMenuDefaultTest::Selection;
     485    test->showContextMenuTriggeredByPopupEventAndWaitUntilFinished();
     486}
     487
     488static void testContextMenuKey(ContextMenuDefaultTest* test, gconstpointer)
     489{
     490    test->showInWindowAndWaitUntilMapped();
     491
     492    prepareContextMenuTestView(test);
     493
     494    test->m_expectedMenuType = ContextMenuDefaultTest::Selection;
     495    test->showContextMenuTriggeredByContextMenuKeyAndWaitUntilFinished();
    428496}
    429497
     
    918986{
    919987    ContextMenuDefaultTest::add("WebKitWebView", "default-menu", testContextMenuDefaultMenu);
     988    ContextMenuDefaultTest::add("WebKitWebView", "context-menu-key", testContextMenuKey);
     989    ContextMenuDefaultTest::add("WebKitWebView", "popup-event-signal", testPopupEventSignal);
    920990    ContextMenuCustomTest::add("WebKitWebView", "populate-menu", testContextMenuPopulateMenu);
    921991    ContextMenuCustomFullTest::add("WebKitWebView", "custom-menu", testContextMenuCustomMenu);
  • trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp

    r210574 r213278  
    334334}
    335335
     336void WebViewTest::emitPopupMenuSignal()
     337{
     338    GtkWidget* viewWidget = GTK_WIDGET(m_webView);
     339    g_assert(gtk_widget_get_realized(viewWidget));
     340
     341    gboolean handled;
     342    g_signal_emit_by_name(viewWidget, "popup-menu", &handled);
     343}
     344
    336345void WebViewTest::keyStroke(unsigned keyVal, unsigned keyModifiers)
    337346{
  • trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h

    r210574 r213278  
    6464    void keyStroke(unsigned keyVal, unsigned keyModifiers = 0);
    6565
     66    void emitPopupMenuSignal();
     67
    6668    WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**);
    6769    WebKitJavascriptResult* runJavaScriptFromGResourceAndWaitUntilFinished(const char* resource, GError**);
Note: See TracChangeset for help on using the changeset viewer.