【问题标题】:Using CEF3 with wxWidgets (and GTK) on Linux在 Linux 上将 CEF3 与 wxWidgets(和 GTK)一起使用
【发布时间】:2016-12-01 20:56:51
【问题描述】:

我从this branch of wxWidgets from GitHub user hokein 开始,因为它似乎可以满足我对旧版本 CEF 的要求。基本上,我正在尝试使用 cef_3.2526.1354 实现 wxWebViewChromium(使用 CEF 作为后端的 wxWebView),因为这是我们要在应用程序中使用的版本。我在使用 Hyper-V 的 VM 中运行带有 GNOME 的 CentOS 7。

来自上面链接的存储库的原始代码(webview_chromium.cpp 的一部分)

#ifdef __WXGTK__
m_widget = gtk_scrolled_window_new( NULL, NULL );
g_object_ref( m_widget );
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW( m_widget );
// Hide the scroll bar.
gtk_scrolled_window_set_policy( scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
GtkWidget* view_port = gtk_viewport_new( NULL, NULL );
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
                                       view_port );
info.SetAsChild( view_port );
m_parent->DoAddChild( this );
PostCreation( size );

gtk_widget_show( view_port );
#endif

当我尝试编译并将其与 cef_3.2526.1354 链接时,我收到了与 info.SetAsChild(viewport); 行相关的错误。我给它传递了一个GtkWidget*,它期待着cef_window_handle_t, CefRect

到目前为止我所做的尝试

我根据GtkWidget* view_port 创建了这样的 CefRect:

GtkAllocation gtk_alloc;
gtk_widget_get_allocation(view_port, &gtk_alloc);
CefRect cef_rect (
    (int)gtk_alloc.x,
    (int)gtk_alloc.y,
    (int)gtk_alloc.width,
    (int)gtk_alloc.height
);

CEF 库代码中的 typedef 表明 cef_window_handle_tunsigned long,但 CEF documentation 说它是 GtkWidget*... 我猜是同一件事,但这导致了一些最初的混淆.起初我以为我需要从底层 X11 窗口传递 X11 窗口 id (XID),但这产生了运行时错误:

Gdk: gdkdrawable-x11.c:952 drawable is not a pixmap or window

只需将 GtkWidget* 转换为 unsigned long 而不是使用底层 X11 窗口 ID 即可消除此错误,因此我认为这是函数所期望的。

我目前的代码(webview_chromium.cpp 的一部分)

#ifdef __WXGTK__
m_widget = gtk_scrolled_window_new( NULL, NULL );
g_object_ref( m_widget );
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW( m_widget );
// Hide the scroll bar.
gtk_scrolled_window_set_policy( scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
GtkWidget* view_port = gtk_viewport_new( NULL, NULL );
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
                                       view_port );

GtkAllocation gtk_alloc;
gtk_widget_get_allocation(view_port, &gtk_alloc);
CefRect cef_rect (
    (int)gtk_alloc.x,
    (int)gtk_alloc.y,
    (int)gtk_alloc.width,
    (int)gtk_alloc.height
);

info.SetAsChild(
    (unsigned long) view_port,
    cef_rect
);

m_parent->DoAddChild( this );
PostCreation( size );

// gtk_widget_show(view_port);
gtk_widget_show_all(m_widget);
gtk_widget_show_all(view_port);
#endif

发生了什么

我能够编译、链接和运行应用程序。我可以看到 wxWidgets 窗口,并且可以像任何普通窗口一样最小化、最大化、调整大小和关闭窗口。窗户里什么都没有——它只是一个普通的、灰色的、空荡荡的窗户。我期待(或希望)看到 CEF 浏览器。在我用来启动应用程序的终端中,我收到以下消息:

[0727/132200:ERROR:browser_main_loop.cc(203)] Running without SUID sandbox! See https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment for more information on developing with sandbox on.

此 URL 似乎不再有任何用处。如果我从命令行启动./cefclient --no-sandbox,我会收到相同的错误消息,但 CEF 客户端按预期工作。如果我从命令行启动 ./cefclient(不禁用沙箱),我会收到相同的消息,除了 ERROR 显示为 FATAL 并且 CEF 客户端不起作用(彻底崩溃)。

我的问题

我对@9​​87654342@ 文件的修改有什么问题吗?此文件中是否还有其他任何地方我应该查找可能需要更新以使其与 cef_3.2526.1354 一起使用的内容?如何解决我看到的这个空窗口?

谢谢!

更新

Czarek Tomczak 告诉我这个版本的 CEF 需要一个 X11 窗口句柄,所以我修改了我的代码如下。

#ifdef __WXGTK__
m_widget = gtk_scrolled_window_new( NULL, NULL );
g_object_ref( m_widget );
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW( m_widget );
// Hide the scroll bar.
gtk_scrolled_window_set_policy( scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
GtkWidget* view_port = gtk_viewport_new( NULL, NULL );
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
                                       view_port );

gtk_widget_show_all(m_widget);
gtk_widget_show_all(view_port);

GtkAllocation gtk_alloc;
gtk_widget_get_allocation(view_port, &gtk_alloc);
CefRect cef_rect (
    (int)gtk_alloc.x,
    (int)gtk_alloc.y,
    (int)gtk_alloc.width,
    (int)gtk_alloc.height
);

info.SetAsChild(
    gdk_x11_drawable_get_xid(gtk_widget_get_window(view_port)),
    cef_rect
);

m_parent->DoAddChild( this );
PostCreation( size );

#endif

但这仍然导致下面的运行时错误,与之前一样的空白窗口输出。

Gdk: gdkdrawable-x11.c:952 drawable is not a pixmap or window

任何为我指明正确方向的帮助将不胜感激。我还尝试在这里创建一个实际的 GtkWindow ,而不是在其中创建一个带有视口的滚动窗口。这消除了上述运行时错误,但它打开了第二个窗口,这两个窗口都是空白的。我需要在一个窗口中完成所有这些工作。

更新 2

在 Czarek Tomczak、他发布的链接和 this FAQ 的帮助下,我已经能够将 CEF 浏览器嵌入到 GtkWidget 中,但我只有在创建时才能完成这项工作小部件作为顶级 GTK 窗口,如下所示:

m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);

m_widget 是我要创建的 wxWebView 的主要小部件。这个问题是现在 CEF 浏览器出现在它自己的 GTK 窗口中,但我真正需要的是 CEF 浏览器适合我添加 wxWebViewChromium 小部件的wxBoxSizer。为了让它工作到现在,我将 Create 方法中的一些代码拆分到 OnSize 方法中,这样我就可以在 GtkWidget 实现后获取 GtkWidget 的 XID,并在发生这种情况后创建 CEF 浏览器。 OnSize 方法连接到wxEVT_SIZE。我的代码现在如下。

Create 方法的更新部分

// Actual creation of CEF browser moved to OnSize function so we
// can guarantee the widgets have been realized
this->Bind(wxEVT_SIZE, &wxWebViewChromium::OnSize, this);

// Works but as a top-level GTK window only
m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);

// None of these work
//m_widget = gtk_drawing_area_new();
//m_widget = gtk_vbox_new(false, 0);

g_object_ref( m_widget );

OnSize 方法的更新部分

if (!cef_browser_created)
{
    cef_browser_created = true;

    CefBrowserSettings browsersettings;
    CefWindowInfo info;

    XSetErrorHandler(XErrorHandlerImpl);
    XSetIOErrorHandler(XIOErrorHandlerImpl);

    gtk_widget_realize(m_widget);

    ::Window xwindow = GTK_WINDOW_XID(gtk_widget_get_window(m_widget));
    DCHECK(xwindow);

    GtkAllocation gtk_alloc;
    gtk_widget_get_allocation(m_widget, &gtk_alloc);
    CefRect cef_rect (
        (int)gtk_alloc.x,
        (int)gtk_alloc.y,
        (int)gtk_alloc.width,
        (int)gtk_alloc.height
    );

    info.SetAsChild(xwindow, cef_rect);
    m_parent->DoAddChild( this );
    PostCreation( size );

    CefBrowserHost::CreateBrowserSync(
        info,
        static_cast<CefRefPtr<CefClient> >(m_clientHandler),
        create_url.ToStdString(),
        browsersettings,
        NULL
    );
}

当我尝试制作除顶级 GTK 小部件以外的 m_widget 时(如上面 Create 方法的代码的注释部分所示),我在运行时收到以下错误.

Gtk: IA__gtk_widget_realize: assertion 'GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
Gdk: gdkdrawable-x11.c:952 drawable is not a pixmap or window
Check failed: xwindow.

如何使这个窗口出现在我的 wxBoxSizer 中,而不是作为它自己的 GTK 顶级窗口?

【问题讨论】:

  • 基本上你自己在这里。 Chromium 实施是作为 GSoC 的一部分完成的,执行这项工作的学生消失了。该分支甚至没有合并,因为没有人维护代码,更不用说对其进行更新并验证一切正常。您可以尝试在 wxForum 上发帖或发送电子邮件至 wx-dev/wx-users 以获得更多曝光。或者尝试搜索 ML 档案 - 最近有人尝试在 Chromium 上做一些工作,并尝试在 ML 中提出一些问题。

标签: c++ linux gtk wxwidgets chromium-embedded


【解决方案1】:

CEF 需要 X11 窗口句柄。以前版本的 CEF 中需要 GtkWidget 句柄。该 wiki 页面上的文档似乎已过时。在将 X11 句柄传递给 CEF 之前,请确保它是有效的(显示窗口)。

我只能建议看一下cefclient示例应用程序中GTK窗口是如何创建的:

https://bitbucket.org/chromiumembedded/cef/src/98f59f47fd395c170f389eba36f2ef2e06a500a8/tests/cefclient/browser/root_window_gtk.cc?at=master&fileviewer=file-view-default#root_window_gtk.cc-233

还可以看看 CreateBrowser() - 它使用 GetXWindowForWidget():

https://bitbucket.org/chromiumembedded/cef/src/98f59f47fd395c170f389eba36f2ef2e06a500a8/tests/cefclient/browser/browser_window_std_gtk.cc?at=master&fileviewer=file-view-default#browser_window_std_gtk.cc-91

【讨论】:

  • 非常感谢您的帮助!不幸的是,我仍然得到相同的空白窗口。我更新了我原来的问题,详细说明了我根据您的帖子所做的修改。你认为你可以快速看看我是否做得正确?
  • @David 更新答案
  • 非常感谢您迄今为止的帮助。我已经能够通过将 m_widget 创建为顶级 GTK 窗口来使 CEF 浏览器出现,但我真的希望将其嵌入到包含我的 wxWebViewChromium 小部件的 wxBoxSizer 中。你知道我该怎么做吗?我更新了我的问题以反映我迄今为止所做的更改。
猜你喜欢
  • 2021-09-30
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
  • 2021-12-06
  • 2013-06-18
  • 2020-05-07
相关资源
最近更新 更多