在Linux上使用带有wxWidgets(和GTK)的CEF3



我从GitHub用户hokein的wxWidgets的这个分支开始,因为它似乎可以用旧版本的CEF实现我想要的功能。基本上,我尝试使用cef3.2526.1354实现wxWebViewChromium(一个使用CEF作为后端的wxWebView),因为这是我们希望在应用程序中使用的版本。我在使用Hyper-V的虚拟机中运行带有GNOME的CentOS 7。

来自上面链接的存储库的原始代码(webview_chrmium.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文档中说它是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客户端不工作(完全崩溃)。

我的问题

我对webview_chromium.cpp文件的修改有什么错误吗?在这个文件中,我是否还有其他地方应该查找可能需要更新的内容,以便使用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、他发布的链接和这个常见问题解答的帮助下,我已经到了可以将CEF浏览器嵌入GtkWidget的地步,但只有当我将该小部件创建为顶级GTK窗口时,我才能做到这一点:

m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);

其中m_widget是我试图创建的wxWebView的主要小部件。这个问题是,现在CEF浏览器出现在它自己的GTK窗口中,但我真正需要的是让CEF浏览器适应我正在添加wxWebViewChromium小部件的wxBoxSizer。为了实现这一点,我将Create方法中的一些代码拆分到OnSize方法中,这样我就可以在GtkWidget实现后获得GtkWidWidget的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
    );
}

当我试图使m_widget成为顶级GTK小部件之外的其他部件时(如上面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顶级窗口?

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

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

https://bitbucket.org/chromiumembedded/cef/src/98f59f47fd395c170f389eba36f2ef2e06a500a8/tests/cefclient/browser/root_window_gtk.cc?at=master&fileviewer=文件视图默认#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=文件视图默认值#browser_window_std_gtk.cc-91

相关内容

  • 没有找到相关文章

最新更新