【发布时间】: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, >k_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_t 是 unsigned 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, >k_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 客户端不起作用(彻底崩溃)。
我的问题
我对@987654342@ 文件的修改有什么问题吗?此文件中是否还有其他任何地方我应该查找可能需要更新以使其与 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, >k_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, >k_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