Title: [260889] trunk
Revision
260889
Author
[email protected]
Date
2020-04-29 03:06:54 -0700 (Wed, 29 Apr 2020)

Log Message

[GTK] Misplaced right click menu on web page due to deprecated gtk_menu_popup()
https://bugs.webkit.org/show_bug.cgi?id=170553

Source/WebCore:

Reviewed by Carlos Garcia Campos.

* platform/gtk/GtkVersioning.h: Add replacements for GtkPopover functions which are no longet available in GTK4.
(gtk_popover_menu_new): Added.
(gtk_popover_bind_model): Added.
(gtk_popover_set_relative_to): Added.

Source/WebKit:

Reviewed by Carlos Garcia Campos.

Replace GtkMenuShell with a GtkPopoverMenu for context menus. The former is not available
at all in GTK4, and the later allows for simplifying the positioning code: it is enough
to provide a point in WebKitWebView widget where to place the popup, and GTK takes care
of everything. This removes the custom positioning code (as it is not needed anymore),
which did GdkScreen-relative calculations that GTK4 does not support.

No new tests needed.

* Shared/glib/WebContextMenuItemGlib.h:
* UIProcess/API/glib/WebKitWebView.cpp:
(contextMenuDismissed): Change parameter from GtkMenuShell to GtkMenuShell to GtkWidget.
(webkitWebViewPopulateContextMenu): Connect to the GtkPopover::closed signal instead of
GtkMenuShell::deactivate.
* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(activeContextMenuClosed): Renamed from activeContextMenuUnmapped(), changed parameter
from GtkMenuShell to GtkWidget, and compare with WebContextMenuProxyGtk::gtkWidget().
(activeContextMenuUnmapped): Renamed to activeContextMenuClosed().
(webkitWebViewBaseSetActiveContextMenuProxy): Connect to the GtkPopover::closed signal
instead of GtkMenuShell::deactivate.
(webkitWebViewBaseGetActiveContextMenuProxy):
* UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
* UIProcess/API/gtk/WebKitWebViewGtk.cpp:
* UIProcess/gtk/WebContextMenuProxyGtk.cpp: Arrange to use GtkPopoverMenu instead of
GtkMenuShell.
* UIProcess/gtk/WebContextMenuProxyGtk.cpp:
(WebKit::WebContextMenuProxyGtk::populate):
(WebKit::WebContextMenuProxyGtk::showContextMenuWithItems): Simplify using
m_context.menuLocation() to obtain the location where to make the context menu popup
next to, which allows removing the ::menuPositionFunction() callback as well.
(WebKit::WebContextMenuProxyGtk::WebContextMenuProxyGtk):
(WebKit::WebContextMenuProxyGtk::~WebContextMenuProxyGtk):
* UIProcess/gtk/WebContextMenuProxyGtk.h: Remove declarations for ::menuPositionFunction()
and ::m_popupPosition, which are now unneeded.
(WebKit::WebContextMenuProxyGtk::gtkWidget const): Renamed from ::gtkMenu(), and made it
return a GtkWidget.

Tools:

Minor adaptations needed in the API tests to account for the differences between
GtkMenuShell and GtkPopoverMenu.

Reviewed by Carlos Garcia Campos.

* TestWebKitAPI/Tests/WebKitGtk/TestContextMenu.cpp:
(lookupWidgetsWalkChild): Added.
(lookupWidgets): Added.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (260888 => 260889)


--- trunk/Source/WebCore/ChangeLog	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebCore/ChangeLog	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,3 +1,15 @@
+2020-04-29  Adrian Perez de Castro  <[email protected]>
+
+        [GTK] Misplaced right click menu on web page due to deprecated gtk_menu_popup()
+        https://bugs.webkit.org/show_bug.cgi?id=170553
+
+        Reviewed by Carlos Garcia Campos.
+
+        * platform/gtk/GtkVersioning.h: Add replacements for GtkPopover functions which are no longet available in GTK4.
+        (gtk_popover_menu_new): Added.
+        (gtk_popover_bind_model): Added.
+        (gtk_popover_set_relative_to): Added.
+
 2020-04-29  Philippe Normand  <[email protected]>
 
         [GStreamer] Switch to audiointerleave

Modified: trunk/Source/WebCore/platform/gtk/GtkVersioning.h (260888 => 260889)


--- trunk/Source/WebCore/platform/gtk/GtkVersioning.h	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebCore/platform/gtk/GtkVersioning.h	2020-04-29 10:06:54 UTC (rev 260889)
@@ -151,4 +151,20 @@
         *keycode = gdk_key_event_get_keycode(const_cast<GdkEvent*>(event));
     return TRUE;
 }
+
+static inline GtkWidget* gtk_popover_menu_new()
+{
+    return gtk_popover_menu_new_from_model(nullptr);
+}
+
+static inline void gtk_popover_bind_model(GtkPopover* popover, GMenuModel* model, const char*)
+{
+    ASSERT(GTK_IS_POPOVER_MENU(popover));
+    gtk_popover_menu_set_menu_model(GTK_POPOVER_MENU(popover), model);
+}
+
+static inline void gtk_popover_set_relative_to(GtkPopover* popover, GtkWidget* parent)
+{
+    gtk_widget_set_parent(GTK_WIDGET(popover), parent);
+}
 #endif // USE(GTK4)

Modified: trunk/Source/WebKit/ChangeLog (260888 => 260889)


--- trunk/Source/WebKit/ChangeLog	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/ChangeLog	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,3 +1,46 @@
+2020-04-29  Adrian Perez de Castro  <[email protected]>
+
+        [GTK] Misplaced right click menu on web page due to deprecated gtk_menu_popup()
+        https://bugs.webkit.org/show_bug.cgi?id=170553
+
+        Reviewed by Carlos Garcia Campos.
+
+        Replace GtkMenuShell with a GtkPopoverMenu for context menus. The former is not available
+        at all in GTK4, and the later allows for simplifying the positioning code: it is enough
+        to provide a point in WebKitWebView widget where to place the popup, and GTK takes care
+        of everything. This removes the custom positioning code (as it is not needed anymore),
+        which did GdkScreen-relative calculations that GTK4 does not support.
+
+        No new tests needed.
+
+        * Shared/glib/WebContextMenuItemGlib.h:
+        * UIProcess/API/glib/WebKitWebView.cpp:
+        (contextMenuDismissed): Change parameter from GtkMenuShell to GtkMenuShell to GtkWidget.
+        (webkitWebViewPopulateContextMenu): Connect to the GtkPopover::closed signal instead of
+        GtkMenuShell::deactivate.
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (activeContextMenuClosed): Renamed from activeContextMenuUnmapped(), changed parameter
+        from GtkMenuShell to GtkWidget, and compare with WebContextMenuProxyGtk::gtkWidget().
+        (activeContextMenuUnmapped): Renamed to activeContextMenuClosed().
+        (webkitWebViewBaseSetActiveContextMenuProxy): Connect to the GtkPopover::closed signal
+        instead of GtkMenuShell::deactivate.
+        (webkitWebViewBaseGetActiveContextMenuProxy):
+        * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
+        * UIProcess/API/gtk/WebKitWebViewGtk.cpp:
+        * UIProcess/gtk/WebContextMenuProxyGtk.cpp: Arrange to use GtkPopoverMenu instead of
+        GtkMenuShell.
+        * UIProcess/gtk/WebContextMenuProxyGtk.cpp:
+        (WebKit::WebContextMenuProxyGtk::populate):
+        (WebKit::WebContextMenuProxyGtk::showContextMenuWithItems): Simplify using
+        m_context.menuLocation() to obtain the location where to make the context menu popup
+        next to, which allows removing the ::menuPositionFunction() callback as well.
+        (WebKit::WebContextMenuProxyGtk::WebContextMenuProxyGtk):
+        (WebKit::WebContextMenuProxyGtk::~WebContextMenuProxyGtk):
+        * UIProcess/gtk/WebContextMenuProxyGtk.h: Remove declarations for ::menuPositionFunction()
+        and ::m_popupPosition, which are now unneeded.
+        (WebKit::WebContextMenuProxyGtk::gtkWidget const): Renamed from ::gtkMenu(), and made it
+        return a GtkWidget.
+
 2020-04-29  Commit Queue  <[email protected]>
 
         Unreviewed, reverting r260650.

Modified: trunk/Source/WebKit/Shared/glib/WebContextMenuItemGlib.h (260888 => 260889)


--- trunk/Source/WebKit/Shared/glib/WebContextMenuItemGlib.h	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/Shared/glib/WebContextMenuItemGlib.h	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Igalia S.L.
+ * Copyright (C) 2015, 2020 Igalia S.L.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,10 +29,10 @@
 #include <wtf/glib/GRefPtr.h>
 #include <wtf/glib/GUniquePtr.h>
 
-#if !USE(GTK4)
+#if PLATFORM(GTK) && !USE(GTK4)
 typedef struct _GtkAction GtkAction;
+#endif // PLATFORM(GTK) && !USE(GTK4)
 typedef struct _GAction GAction;
-#endif
 
 namespace WebKit {
 

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp (260888 => 260889)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,8 +1,7 @@
 /*
- * Copyright (C) 2011 Igalia S.L.
  * Portions Copyright (c) 2011 Motorola Mobility, Inc.  All rights reserved.
  * Copyright (C) 2014 Collabora Ltd.
- * Copyright (C) 2017 Igalia S.L.
+ * Copyright (C) 2011, 2017, 2020 Igalia S.L.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -2580,16 +2579,13 @@
 }
 
 #if PLATFORM(GTK)
-#if !USE(GTK4)
-static void contextMenuDismissed(GtkMenuShell*, WebKitWebView* webView)
+static void contextMenuDismissed(GtkWidget*, WebKitWebView* webView)
 {
     g_signal_emit(webView, signals[CONTEXT_MENU_DISMISSED], 0, NULL);
 }
-#endif
 
 void webkitWebViewPopulateContextMenu(WebKitWebView* webView, const Vector<WebContextMenuItemData>& proposedMenu, const WebHitTestResultData& hitTestResultData, GVariant* userData)
 {
-#if !USE(GTK4)
     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
     WebContextMenuProxyGtk* contextMenuProxy = webkitWebViewBaseGetActiveContextMenuProxy(webViewBase);
     ASSERT(contextMenuProxy);
@@ -2609,11 +2605,10 @@
     webkitContextMenuPopulate(contextMenu.get(), contextMenuItems);
     contextMenuProxy->populate(contextMenuItems);
 
-    g_signal_connect(contextMenuProxy->gtkMenu(), "deactivate", G_CALLBACK(contextMenuDismissed), webView);
+    g_signal_connect(contextMenuProxy->gtkWidget(), "closed", G_CALLBACK(contextMenuDismissed), webView);
 
     // Clear the menu to make sure it's useless after signal emission.
     webkit_context_menu_remove_all(contextMenu.get());
-#endif
 }
 #elif PLATFORM(WPE)
 void webkitWebViewPopulateContextMenu(WebKitWebView* webView, const Vector<WebContextMenuItemData>& proposedMenu, const WebHitTestResultData& hitTestResultData, GVariant* userData)

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp (260888 => 260889)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,8 +1,8 @@
 /*
  * Copyright (C) 2010 Apple Inc. All rights reserved.
  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
- * Copyright (C) 2011 Igalia S.L.
  * Copyright (C) 2013 Gustavo Noronha Silva <[email protected]>.
+ * Copyright (C) 2011, 2020 Igalia S.L.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -190,9 +190,7 @@
     AttachmentSide inspectorAttachmentSide { AttachmentSide::Bottom };
     unsigned inspectorViewSize { 0 };
     GUniquePtr<GdkEvent> contextMenuEvent;
-#if !USE(GTK4)
     WebContextMenuProxyGtk* activeContextMenuProxy { nullptr };
-#endif
     InputMethodFilter inputMethodFilter;
     KeyBindingTranslator keyBindingTranslator;
     TouchEventsMap touchEvents;
@@ -1860,10 +1858,9 @@
         gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
 }
 
-#if !USE(GTK4)
-static void activeContextMenuUnmapped(GtkMenu* menu, WebKitWebViewBase* webViewBase)
+static void activeContextMenuClosed(GtkWidget* widget, WebKitWebViewBase* webViewBase)
 {
-    if (webViewBase->priv->activeContextMenuProxy && webViewBase->priv->activeContextMenuProxy->gtkMenu() == menu)
+    if (webViewBase->priv->activeContextMenuProxy && webViewBase->priv->activeContextMenuProxy->gtkWidget() == widget)
         webViewBase->priv->activeContextMenuProxy = nullptr;
 }
 
@@ -1870,7 +1867,7 @@
 void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase, WebContextMenuProxyGtk* contextMenuProxy)
 {
     webkitWebViewBase->priv->activeContextMenuProxy = contextMenuProxy;
-    g_signal_connect_object(contextMenuProxy->gtkMenu(), "unmap", G_CALLBACK(activeContextMenuUnmapped), webkitWebViewBase, static_cast<GConnectFlags>(0));
+    g_signal_connect_object(contextMenuProxy->gtkWidget(), "closed", G_CALLBACK(activeContextMenuClosed), webkitWebViewBase, static_cast<GConnectFlags>(0));
 }
 
 WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase)
@@ -1877,7 +1874,6 @@
 {
     return webkitWebViewBase->priv->activeContextMenuProxy;
 }
-#endif
 
 GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebViewBase)
 {

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h (260888 => 260889)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h	2020-04-29 10:06:54 UTC (rev 260889)
@@ -53,10 +53,8 @@
 void webkitWebViewBaseExitFullScreen(WebKitWebViewBase*);
 bool webkitWebViewBaseIsFullScreen(WebKitWebViewBase*);
 void webkitWebViewBaseSetInspectorViewSize(WebKitWebViewBase*, unsigned size);
-#if !USE(GTK4)
 void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase*, WebKit::WebContextMenuProxyGtk*);
 WebKit::WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase*);
-#endif
 GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase*);
 void webkitWebViewBaseSetInputMethodState(WebKitWebViewBase*, Optional<WebKit::InputMethodState>&&);
 void webkitWebViewBaseUpdateTextInputState(WebKitWebViewBase*);

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewGtk.cpp (260888 => 260889)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewGtk.cpp	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewGtk.cpp	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Igalia S.L.
+ * Copyright (C) 2017, 2020 Igalia S.L.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public

Modified: trunk/Source/WebKit/UIProcess/gtk/WebContextMenuProxyGtk.cpp (260888 => 260889)


--- trunk/Source/WebKit/UIProcess/gtk/WebContextMenuProxyGtk.cpp	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/UIProcess/gtk/WebContextMenuProxyGtk.cpp	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Igalia S.L.
+ * Copyright (C) 2011, 2020 Igalia S.L.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -47,7 +47,6 @@
 namespace WebKit {
 using namespace WebCore;
 
-#if !USE(GTK4)
 static void contextMenuItemActivatedCallback(GAction* action, GVariant*, WebPageProxy* page)
 {
     auto* stateType = g_action_get_state_type(action);
@@ -68,7 +67,7 @@
     GRefPtr<GMenuItem> gMenuItem;
     GAction* action = ""
     ASSERT(action);
-    g_action_map_add_action(G_ACTION_MAP(gtk_widget_get_action_group(GTK_WIDGET(m_menu), gContextMenuItemGroup)), action);
+    g_action_map_add_action(G_ACTION_MAP(m_actionGroup.get()), action);
 
     switch (menuItem.type()) {
     case ActionType:
@@ -129,7 +128,7 @@
 void WebContextMenuProxyGtk::populate(const Vector<WebContextMenuItemGlib>& items)
 {
     GRefPtr<GMenu> menu = buildMenu(items);
-    gtk_menu_shell_bind_model(GTK_MENU_SHELL(m_menu), G_MENU_MODEL(menu.get()), nullptr, TRUE);
+    gtk_popover_bind_model(m_menu, G_MENU_MODEL(menu.get()), nullptr);
 }
 
 void WebContextMenuProxyGtk::populate(const Vector<Ref<WebContextMenuItem>>& items)
@@ -157,13 +156,11 @@
         }
         }
     }
-    gtk_menu_shell_bind_model(GTK_MENU_SHELL(m_menu), G_MENU_MODEL(menu.get()), nullptr, TRUE);
+    gtk_popover_bind_model(m_menu, G_MENU_MODEL(menu.get()), nullptr);
 }
-#endif
 
 void WebContextMenuProxyGtk::show()
 {
-#if !USE(GTK4)
     Vector<Ref<WebContextMenuItem>> proposedAPIItems;
     for (auto& item : m_context.menuItems()) {
         if (item.action() != ContextMenuItemTagShareMenu)
@@ -171,12 +168,10 @@
     }
 
     m_page->contextMenuClient().getContextMenuFromProposedMenu(*m_page, WTFMove(proposedAPIItems), WebContextMenuListenerProxy::create(this).get(), m_context.webHitTestResultData(), m_page->process().transformHandlesToObjects(m_userData.object()).get());
-#endif
 }
 
 void WebContextMenuProxyGtk::showContextMenuWithItems(Vector<Ref<WebContextMenuItem>>&& items)
 {
-#if !USE(GTK4)
     if (!items.isEmpty())
         populate(items);
 
@@ -185,35 +180,27 @@
     if (!childCount)
         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, GTK_WIDGET(m_webView), nullptr);
-    gtk_menu_popup(m_menu, nullptr, nullptr, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, event ? event->button.button : 3, event ? event->button.time : GDK_CURRENT_TIME);
-#endif
+    const GdkRectangle rect = { m_context.menuLocation().x(), m_context.menuLocation().y(), 1, 1 };
+    gtk_popover_set_pointing_to(m_menu, &rect);
+    gtk_popover_popup(m_menu);
 }
 
 WebContextMenuProxyGtk::WebContextMenuProxyGtk(GtkWidget* webView, WebPageProxy& page, ContextMenuContextData&& context, const UserData& userData)
     : WebContextMenuProxy(WTFMove(context), userData)
-#if !USE(GTK4)
     , m_webView(webView)
     , m_page(&page)
-    , m_menu(GTK_MENU(gtk_menu_new()))
-#endif
+    , m_menu(GTK_POPOVER(gtk_popover_menu_new()))
 {
-#if !USE(GTK4)
+    gtk_popover_set_position(m_menu, GTK_POS_BOTTOM);
+    gtk_popover_set_relative_to(m_menu, m_webView);
     GRefPtr<GSimpleActionGroup> group = adoptGRef(g_simple_action_group_new());
     gtk_widget_insert_action_group(GTK_WIDGET(m_menu), gContextMenuItemGroup, G_ACTION_GROUP(group.get()));
     webkitWebViewBaseSetActiveContextMenuProxy(WEBKIT_WEB_VIEW_BASE(m_webView), this);
-#endif
 }
 
 WebContextMenuProxyGtk::~WebContextMenuProxyGtk()
 {
-#if !USE(GTK4)
-    gtk_menu_popdown(m_menu);
+    gtk_popover_popdown(m_menu);
 
     for (auto& handler : m_signalHandlers)
         g_signal_handler_disconnect(handler.value, handler.key);
@@ -221,27 +208,7 @@
 
     gtk_widget_insert_action_group(GTK_WIDGET(m_menu), gContextMenuItemGroup, nullptr);
     gtk_widget_destroy(GTK_WIDGET(m_menu));
-#endif
 }
 
-#if !USE(GTK4)
-void WebContextMenuProxyGtk::menuPositionFunction(GtkMenu* menu, gint* x, gint* y, gboolean* pushIn, WebContextMenuProxyGtk* popupMenu)
-{
-    GtkRequisition menuSize;
-    gtk_widget_get_preferred_size(GTK_WIDGET(menu), &menuSize, 0);
-
-    GdkScreen* screen = gtk_widget_get_screen(popupMenu->m_webView);
-    *x = popupMenu->m_popupPosition.x();
-    if ((*x + menuSize.width) >= gdk_screen_get_width(screen))
-        *x -= menuSize.width;
-
-    *y = popupMenu->m_popupPosition.y();
-    if ((*y + menuSize.height) >= gdk_screen_get_height(screen))
-        *y -= menuSize.height;
-
-    *pushIn = FALSE;
-}
-#endif
-
 } // namespace WebKit
 #endif // ENABLE(CONTEXT_MENUS)

Modified: trunk/Source/WebKit/UIProcess/gtk/WebContextMenuProxyGtk.h (260888 => 260889)


--- trunk/Source/WebKit/UIProcess/gtk/WebContextMenuProxyGtk.h	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Source/WebKit/UIProcess/gtk/WebContextMenuProxyGtk.h	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Igalia S.L.
+ * Copyright (C) 2011, 2020 Igalia S.L.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
 
 #include "WebContextMenuItemGlib.h"
 #include "WebContextMenuProxy.h"
+#include <WebCore/GtkVersioning.h>
 #include <WebCore/IntPoint.h>
 #include <wtf/HashMap.h>
 #include <wtf/glib/GRefPtr.h>
@@ -49,28 +50,23 @@
     }
     ~WebContextMenuProxyGtk();
 
-#if !USE(GTK4)
     void populate(const Vector<WebContextMenuItemGlib>&);
-    GtkMenu* gtkMenu() const { return m_menu; }
-#endif
+    GtkWidget* gtkWidget() const { return GTK_WIDGET(m_menu); }
 
 private:
     WebContextMenuProxyGtk(GtkWidget*, WebPageProxy&, ContextMenuContextData&&, const UserData&);
     void show() override;
     void showContextMenuWithItems(Vector<Ref<WebContextMenuItem>>&&) override;
-#if !USE(GTK4)
     void append(GMenu*, const WebContextMenuItemGlib&);
     GRefPtr<GMenu> buildMenu(const Vector<WebContextMenuItemGlib>&);
     void populate(const Vector<Ref<WebContextMenuItem>>&);
     Vector<WebContextMenuItemGlib> populateSubMenu(const WebContextMenuItemData&);
-    static void menuPositionFunction(GtkMenu*, gint*, gint*, gboolean*, WebContextMenuProxyGtk*);
 
     GtkWidget* m_webView;
     WebPageProxy* m_page;
-    GtkMenu* m_menu;
-    WebCore::IntPoint m_popupPosition;
+    GtkPopover* m_menu;
     HashMap<unsigned long, void*> m_signalHandlers;
-#endif
+    GRefPtr<GSimpleActionGroup> m_actionGroup { adoptGRef(g_simple_action_group_new()) };
 };
 
 

Modified: trunk/Tools/ChangeLog (260888 => 260889)


--- trunk/Tools/ChangeLog	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Tools/ChangeLog	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,3 +1,17 @@
+2020-04-29  Adrian Perez de Castro  <[email protected]>
+
+        [GTK] Misplaced right click menu on web page due to deprecated gtk_menu_popup()
+        https://bugs.webkit.org/show_bug.cgi?id=170553
+
+        Minor adaptations needed in the API tests to account for the differences between
+        GtkMenuShell and GtkPopoverMenu.
+
+        Reviewed by Carlos Garcia Campos.
+
+        * TestWebKitAPI/Tests/WebKitGtk/TestContextMenu.cpp:
+        (lookupWidgetsWalkChild): Added.
+        (lookupWidgets): Added.
+
 2020-04-28  Said Abou-Hallawa  <[email protected]>
 
         Upgrade motionmark1.1.plan to r260656

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitGtk/TestContextMenu.cpp (260888 => 260889)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitGtk/TestContextMenu.cpp	2020-04-29 09:06:59 UTC (rev 260888)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitGtk/TestContextMenu.cpp	2020-04-29 10:06:54 UTC (rev 260889)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Igalia S.L.
+ * Copyright (C) 2012, 2020 Igalia S.L.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,6 +26,28 @@
 
 static WebKitTestServer* kServer;
 
+struct LookupWidgetsData {
+    void (*walkChildren)(GtkContainer*, GtkCallback, void*);
+    Function<bool(GtkWidget*)> predicate;
+    Vector<GtkWidget*> result;
+};
+
+static void lookupWidgetsWalkChild(GtkWidget* child, void* userdata)
+{
+    auto& data = ""
+    if (data.predicate(child))
+        data.result.append(child);
+    else if (GTK_IS_CONTAINER(child))
+        data.walkChildren(GTK_CONTAINER(child), lookupWidgetsWalkChild, userdata);
+}
+
+static Vector<GtkWidget*> lookupWidgets(GtkWidget* widget, Function<bool(GtkWidget*)>&& predicate, bool internal = false)
+{
+    LookupWidgetsData data = "" ? gtk_container_forall : gtk_container_foreach, WTFMove(predicate)};
+    lookupWidgetsWalkChild(widget, &data);
+    return WTFMove(data.result);
+}
+
 class ContextMenuTest: public WebViewTest {
 public:
     enum ContextMenuItemStateFlags {
@@ -94,7 +116,7 @@
         quitMainLoop();
     }
 
-    GtkMenu* getPopupMenu()
+    GtkPopover* getPopoverMenu()
     {
         GUniquePtr<GList> toplevels(gtk_window_list_toplevels());
         for (GList* iter = toplevels.get(); iter; iter = g_list_next(iter)) {
@@ -101,12 +123,18 @@
             if (!GTK_IS_WINDOW(iter->data))
                 continue;
 
-            GtkWidget* child = gtk_bin_get_child(GTK_BIN(iter->data));
-            if (!GTK_IS_MENU(child))
-                continue;
+            // Popovers are internal to the GtkContainer where the webview resides,
+            // gtk_container_forall() is the only way to enumerate internal children.
+            GtkPopover *popover = nullptr;
+            gtk_container_forall(GTK_CONTAINER(iter->data),
+                [](GtkWidget* child, void* data) {
+                    auto** popover = reinterpret_cast<GtkPopover**>(data);
+                    if (GTK_IS_POPOVER_MENU(child) && !*popover)
+                        *popover = GTK_POPOVER(child);
+                }, &popover);
 
-            if (gtk_menu_get_attach_widget(GTK_MENU(child)) == GTK_WIDGET(m_webView))
-                return GTK_MENU(child);
+            if (popover && gtk_popover_get_relative_to(popover) == GTK_WIDGET(m_webView))
+                return popover;
         }
         g_assert_not_reached();
         return 0;
@@ -551,24 +579,32 @@
         return false;
     }
 
-    GtkMenuItem* getMenuItem(GtkMenu* menu, const gchar* itemLabel)
+    GtkButton* getMenuItem(GtkPopover* popover, const gchar* itemLabel)
     {
-        GUniquePtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu)));
-        for (GList* iter = items.get(); iter; iter = g_list_next(iter)) {
-            GtkMenuItem* child = GTK_MENU_ITEM(iter->data);
-            if (g_str_equal(itemLabel, gtk_menu_item_get_label(child)))
-                return child;
-        }
-        g_assert_not_reached();
-        return 0;
+        auto items = lookupWidgets(GTK_WIDGET(popover),
+            [itemLabel](GtkWidget* widget) {
+                if (!GTK_IS_BUTTON(widget))
+                    return false;
+                const char* label = gtk_button_get_label(GTK_BUTTON(widget));
+                if (!label) {
+                    const auto labels = lookupWidgets(GTK_WIDGET(widget),
+                        [](GtkWidget* child) { return GTK_IS_LABEL(child); });
+                    g_assert_cmpuint(1, ==, labels.size());
+                    label = gtk_label_get_label(GTK_LABEL(labels[0]));
+                }
+                return GTK_IS_BUTTON(widget) && g_strcmp0(label, itemLabel) == 0;
+            }, true);
+
+        g_assert_cmpuint(items.size(), >, 0);
+        return items.size() ? GTK_BUTTON(items[0]) : nullptr;
     }
 
     void activateMenuItem()
     {
         g_assert_nonnull(m_itemToActivateLabel);
-        GtkMenu* menu = getPopupMenu();
-        GtkMenuItem* item = getMenuItem(menu, m_itemToActivateLabel);
-        gtk_menu_shell_activate_item(GTK_MENU_SHELL(menu), GTK_WIDGET(item), TRUE);
+        auto* menu = getPopoverMenu();
+        auto* item = getMenuItem(menu, m_itemToActivateLabel);
+        gtk_button_clicked(item);
         m_itemToActivateLabel = nullptr;
     }
 
@@ -612,6 +648,10 @@
     static void actionToggledCallback(ContextMenuCustomTest* test)
     {
         test->m_toggled = true;
+
+        // For toggle actions the popover menu is NOT dismissed automatically, as to show visual feedback to the user
+        // (i.e. the check marker). Dismiss it here to trigger contextMenuDismissedCallback() and continue the test.
+        gtk_popover_popdown(test->getPopoverMenu());
     }
 
     void setAction(GtkAction* action)
@@ -619,10 +659,12 @@
         m_action = action;
         m_gAction = nullptr;
         m_expectedTarget = nullptr;
+        G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
         if (GTK_IS_TOGGLE_ACTION(action))
             g_signal_connect_swapped(action, "toggled", G_CALLBACK(actionToggledCallback), this);
         else
             g_signal_connect_swapped(action, "activate", G_CALLBACK(actionActivatedCallback), this);
+        G_GNUC_END_IGNORE_DEPRECATIONS;
     }
 
     void setAction(GAction* action, const char* title, GVariant* target = nullptr)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to