0
votes

I started with this branch of wxWidgets from GitHub user hokein since it seems to do what I'm looking for with older versions of CEF. Basically, I'm trying to implement wxWebViewChromium (a wxWebView using CEF as a back-end) using cef_3.2526.1354 since this is the version we want to use in our application. I'm running CentOS 7 with GNOME in a VM using Hyper-V.

Original code from the repository linked above (part of 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

When I tried to compile and link this with cef_3.2526.1354, I was getting errors related to the info.SetAsChild(viewport); line. I was passing it a GtkWidget* and it was expecting cef_window_handle_t, CefRect.

What I've tried so far

I created the CefRect like this based on the GtkWidget* 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
);

The typedef from the CEF library code indicates that cef_window_handle_t is an unsigned long, but the CEF documentation says it's a GtkWidget*... Which I guess are the same thing, but this led to some initial confusion. At first I thought that I needed to pass the X11 window id (XID) from the underlying X11 window, but this produced a runtime error:

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

Simply casting the GtkWidget* as an unsigned long instead of using the underlying X11 window ID removed this error, so I think that this is what the function was expecting.

My code currently (part of 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

What's happening

I am able to compile, link, and run the application. I can see the wxWidgets window, and I can minimize, maximize, resize, and close the window just like any normal window. There is nothing in the window - it is just a plain, grey, empty window. I am expecting (or hoping) to see the CEF browser. In the terminal that I used to launch the application, I get the following message:

[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.

This URL no longer seems to be of any use. If I launch ./cefclient --no-sandbox from the command line I get the same error message, but the CEF client works as expected. If I launch ./cefclient from the command line (without disabling sandbox), I get this same message except instead of ERROR it says FATAL and the CEF client does not work (crashes outright).

My questions

Have I done anything wrong with my modifications to the webview_chromium.cpp file? Is there anywhere else in this file that I should look for things that I might need to update to get this working with cef_3.2526.1354? How can I troubleshoot this empty window that I'm seeing?

Thanks!

UPDATE

Czarek Tomczak informed me that this version of CEF is expecting an X11 window handle, so I have modified my code as follows.

#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

But this is still leading to the run-time error below, with the same blank window output as before.

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

Any help pointing me in the right direction would be much appreciated. I have also tried creating an actual GtkWindow here instead of a scrolled window with a viewport inside it. This gets rid of the above run-time error, but it opens a second window, both of which are blank. I need all of this to work within one window.

UPDATE 2

With some help from Czarek Tomczak, the links he posted, and this FAQ I have gotten to a point where I am able to embed the CEF browser into a GtkWidget, but I am only able to make this work if I create the widget as a top-level GTK window like this:

m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);

Where m_widget is the main widget of the wxWebView I'm trying to create. The issue with this is that now the CEF browser is coming up in its own GTK window, but what I really need is for the CEF browser to fit into the wxBoxSizer that I am adding my wxWebViewChromium widget to. To get this working to this point I split out some of the code from the Create method into the OnSize method so that I could get the XID of the GtkWidget after the GtkWidget was realized, and create the CEF browser after this happened. The OnSize method is connected to wxEVT_SIZE. My code is now as follows.

Updated portion of Create Method

// 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 );

Updated portion of OnSize Method

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
    );
}

When I try to make m_widget something other than a top-level GTK widget (as shown in the commented-out portions of the code for the Create method above), I get the following error at run-time.

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.

How can I make this window appear inside my wxBoxSizer instead of as its own GTK top-level window?

1
basically you are on you own here. The Chromium implementation was done as part of the GSoC and the student who performed the job is disappear. The branch is not even merged because there is no one to maintain the code let alone make an update to it and verify that everything works. You can try to post on wxForum or send an E-mail to wx-dev/wx-users to have more exposure. Or try to search the ML archives - someone very recently tried to do some work on Chromium and tried to ask some questions in ML.Igor

1 Answers

1
votes

CEF expects X11 window handle. GtkWidget handle was required in previous versions of CEF. The documentation on that wiki page seems to be outdated. Make sure the X11 handle is valid (show the window) before passing it to CEF.

I can only suggest to take a look at how GTK window is created in cefclient sample application:

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

Also take a look at CreateBrowser() - it uses 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