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)