[Solved] How to use CEF 3163 C API with GTK+ 3

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

[Solved] How to use CEF 3163 C API with GTK+ 3

Postby fenryxo » Thu Sep 14, 2017 4:27 pm

I'm trying to use CEF with C API and GTK+ 3 on Debian 9 Stretch, but without any success. If I set cef_window_info_t.parent_window, it crashes. If I don't set it, CEF creates its own window (which works perfectly, however). Am I missing something?

I've built CEF with "use_gtk3=true" to get rid of GTK+ 2 symbols, chromium/src/out/Release_GN_x64/args.gn is therefoe as follows:
Code: Select all
clang_use_chrome_plugins=false
enable_basic_printing=true
enable_nacl=false
enable_print_preview=false
enable_widevine=true
ffmpeg_branding="Chrome"
is_component_build=false
is_debug=false
is_official_build=true
proprietary_codecs=true
symbol_level=1
target_cpu="x64"
use_allocator="none"
use_gconf=false
use_gtk3=true
use_sysroot=false


cefgtk3.c
Code: Select all
/*
 * gcc -g $(pkg-config --cflags --libs glib-2.0 gtk+-3.0) -Iinclude -I. -L. -Wl,--unresolved-symbols=ignore-all  -lcef -o cefgtk3 libcef_dll_wrapper.a cefgtk3.c
 * export LD_LIBRARY_PATH=.; ./cefgtk3
 */
#include <glib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gtk/gtkx.h>
#include "capi/cef_app_capi.h"
#include "capi/cef_browser_capi.h"
#include "capi/cef_client_capi.h"

void dummy_add_ref(cef_base_ref_counted_t* self) {}
int dummy_release(cef_base_ref_counted_t* self) {return 1;}
int dummy_has_one_ref(cef_base_ref_counted_t* self) {return 1;}

void set_dummy_ref_counting (cef_base_ref_counted_t* self, size_t size) {
   self->size = size;
    self->add_ref = dummy_add_ref;
    self->release = dummy_release;
    self->has_one_ref = dummy_has_one_ref;
}

static gboolean on_gtk_widget_delete_event (GtkWidget* _sender, GdkEventAny* event, gpointer self) {
   gtk_main_quit ();
   return FALSE;
}

static gboolean do_work (void* self) {
   cef_do_message_loop_work ();
   return TRUE;
}

int x11_error_handler(Display* display, XErrorEvent* event) {
    printf("X11 error: type=%d, serial=%lu, code=%d\n",
           event->type, event->serial, (int)event->error_code);
    return 0;
}

int x11_io_error_handler(Display* display) {
    return 0;
}

int main (char** argv, int argc) {
   cef_main_args_t main_args = {};
   main_args.argc = 0;
   main_args.argv = NULL;
   cef_app_t app = {};
   set_dummy_ref_counting(&app.base, sizeof(cef_app_t));
   cef_settings_t settings = {sizeof(cef_settings_t)};
   settings.log_severity = LOGSEVERITY_VERBOSE;
   char c_path[] = "./cefsimple";
   cef_string_utf8_to_utf16(c_path, strlen(c_path), &settings.browser_subprocess_path);
   cef_initialize(&main_args, &settings, &app, NULL);
   
   gtk_init(0, NULL);
   XSetErrorHandler(x11_error_handler);
   XSetIOErrorHandler(x11_io_error_handler);
   GtkWindow* window = (GtkWindow*) gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(window, "CEF C API");
   g_signal_connect((GtkWidget*) window, "delete-event", (GCallback) on_gtk_widget_delete_event, NULL);
   gtk_window_set_default_size(window, 800, 600);
   gtk_widget_realize((GtkWidget*) window);
   GtkWidget* vbox = gtk_vbox_new(0, 0);
   gtk_container_add(GTK_CONTAINER(window), vbox);
   gtk_widget_show_all((GtkWidget*) window);
   GdkX11Window* gdk_window = (GdkX11Window*) gtk_widget_get_window((GtkWidget*) window);
   Window xid = gdk_x11_window_get_xid(gdk_window);
   printf ("xid: %d\n", (int) xid);
   
   cef_window_info_t window_info = {};
   window_info.parent_window = xid;
   window_info.width = 800;
   window_info.height = 600;
   cef_client_t client = {};
   set_dummy_ref_counting(&client.base, sizeof(cef_client_t));
   char c_url[] = "https:/google.com";
   cef_string_t url = {};
   cef_string_utf8_to_utf16(c_url, strlen(c_url), &url);
   cef_browser_settings_t browser_settings = {sizeof(cef_browser_settings_t)};
   cef_browser_host_create_browser(&window_info, &client, &url, &browser_settings, NULL);
   
   g_timeout_add_full(G_PRIORITY_DEFAULT, (guint) 30, do_work, NULL, NULL);
   gtk_main ();
   cef_shutdown ();
   return 0;
}


Result:
Code: Select all
[0914/230827.817794:VERBOSE1:zygote_main_linux.cc(537)] ZygoteMain: initializing 0 fork delegates
[0914/230827.818141:INFO:cpu_info.cc(50)] Available number of cores: 6
[0914/230827.863448:VERBOSE1:proxy_config_service_linux.cc(854)] All gsettings tests OK. Will get proxy config from gsettings.
[0914/230827.863931:VERBOSE1:proxy_config_service_linux.cc(1608)] Obtained proxy settings from GSETTINGS
[0914/230827.863989:VERBOSE1:pref_proxy_config_tracker_impl.cc(154)] 0x562bf1d13070: set chrome proxy config service to 0x562bf1d9d200
xid: 79691779
[0914/230827.941855:ERROR:nss_util.cc(747)] After loading Root Certs, loaded==false: NSS error code: -8018
[0914/230827.942328:VERBOSE1:multi_log_ct_verifier.cc(75)] Adding CT log: Google 'Aviator' log
...
[0914/230827.970803:VERBOSE1:webrtc_internals.cc(108)] Could not get the download directory.
X11 error: type=0, serial=200, code=8
X11 error: type=0, serial=202, code=3
X11 error: type=0, serial=203, code=3
X11 error: type=0, serial=204, code=3
X11 error: type=0, serial=205, code=3
X11 error: type=0, serial=206, code=3
X11 error: type=0, serial=207, code=3
X11 error: type=0, serial=208, code=3
X11 error: type=0, serial=219, code=3
X11 error: type=0, serial=221, code=3
X11 error: type=0, serial=222, code=3
X11 error: type=0, serial=223, code=3
X11 error: type=0, serial=224, code=3
X11 error: type=0, serial=228, code=3
X11 error: type=0, serial=229, code=3

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f57f1a009f7 in FindChild () at ../../cef/libcef/browser/native/window_x11.cc:45
45       child_window = children[0];
[Current thread is 1 (Thread 0x7f57f804dac0 (LWP 18659))]
#0  0x00007f57f1a009f7 in FindChild () at ../../cef/libcef/browser/native/window_x11.cc:45
#1  Show () at ../../cef/libcef/browser/native/window_x11.cc:182
#2  0x00007f57f19fd275 in CreateHostWindow ()
    at ../../cef/libcef/browser/native/browser_platform_delegate_native_linux.cc:93
#3  0x00007f57f1922c3f in CreateHostWindow () at ../../cef/libcef/browser/browser_host_impl.cc:3006
#4  CreateInternal () at ../../cef/libcef/browser/browser_host_impl.cc:367
#5  0x00007f57f19221a9 in Create () at ../../cef/libcef/browser/browser_host_impl.cc:318
#6  0x00007f57f1921e2a in CreateBrowserSync () at ../../cef/libcef/browser/browser_host_impl.cc:267
#7  0x00007f57f1921868 in CreateBrowserWithHelper () at ../../cef/libcef/browser/browser_host_impl.cc:134
#8  0x00007f57f1a25cfb in Run () at ../../base/callback.h:91
#9  RunTask () at ../../base/debug/task_annotator.cc:59
#10 0x00007f57f1a3fab2 in RunTask () at ../../base/message_loop/message_loop.cc:422
#11 0x00007f57f1a3fea2 in DeferOrRunPendingTask () at ../../base/message_loop/message_loop.cc:433
#12 0x00007f57f1a401a6 in DoWork () at ../../base/message_loop/message_loop.cc:540
#13 0x00007f57f1a415ad in base::MessagePumpGlib::Run(base::MessagePump::Delegate*) ()
    at ../../base/message_loop/message_pump_glib.cc:313
#14 0x00007f57f1a5c5d0 in Run () at ../../base/run_loop.cc:111
#15 0x00007f57f1939efa in CefBrowserMessageLoop::DoMessageLoopIteration() ()
    at ../../cef/libcef/browser/browser_message_loop.cc:116
#16 0x0000562bf03290e6 in do_work (self=0x0) at cefgtk3.c:33
#17 0x00007f57f5c8e123 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#18 0x00007f57f5c8d6aa in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#19 0x00007f57f5c8da60 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#20 0x00007f57f5c8dd82 in g_main_loop_run () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#21 0x00007f57f7823d55 in gtk_main () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#22 0x0000562bf03294ab in main (argv=0x1, argc=299476808) at cefgtk3.c:87
Last edited by fenryxo on Sat Dec 09, 2017 9:38 am, edited 1 time in total.
fenryxo
Newbie
 
Posts: 5
Joined: Thu Sep 14, 2017 12:39 pm

Re: How to use CEF 3163 C API with GTK+ 3

Postby Czarek » Fri Sep 15, 2017 1:28 am

Have you checked that the GTK window is realized and its window handle is valid?
Maintainer of the CEF Python, PHP Desktop and CEF C API projects. My LinkedIn.
User avatar
Czarek
Virtuoso
 
Posts: 1927
Joined: Sun Nov 06, 2011 2:12 am

Re: How to use CEF 3163 C API with GTK+ 3

Postby fenryxo » Fri Sep 15, 2017 7:04 am

Czarek wrote:Have you checked that the GTK window is realized and its window handle is valid?


"gtk_widget_get_realized((GtkWidget*) window)" returns true, I can see the (empty) GTK window on my screen and the printed window id matches the id from "wmctrl -lx" command.

Here is the modified example:
Code: Select all
void dummy_add_ref(cef_base_ref_counted_t* self) {}
int dummy_release(cef_base_ref_counted_t* self) {return 1;}
int dummy_has_one_ref(cef_base_ref_counted_t* self) {return 1;}

void set_dummy_ref_counting (cef_base_ref_counted_t* self, size_t size) {
   self->size = size;
    self->add_ref = dummy_add_ref;
    self->release = dummy_release;
    self->has_one_ref = dummy_has_one_ref;
}

static gboolean on_gtk_widget_delete_event (GtkWidget* _sender, GdkEventAny* event, gpointer self) {
   gtk_main_quit ();
   return FALSE;
}

static gboolean do_work(void* user_data) {
   GtkWindow* window = (GtkWindow*) user_data;
   gboolean realized = gtk_widget_get_realized((GtkWidget*) window);
   printf("GtkWindow realized: %d\n", (int) realized);
   GdkX11Window* gdk_window = (GdkX11Window*) gtk_widget_get_window((GtkWidget*) window);
   Window xid = gdk_x11_window_get_xid(gdk_window);
   printf("xid: %d\n", (int) xid);
   cef_do_message_loop_work ();
   return TRUE;
}

int x11_error_handler(Display* display, XErrorEvent* event) {
    printf("X11 error: type=%d, serial=%lu, code=%d\n",
           event->type, event->serial, (int)event->error_code);
    return 0;
}

int x11_io_error_handler(Display* display) {
    return 0;
}

static gboolean quit_loop(void* user_data) {
   g_main_loop_quit((GMainLoop*) user_data);
   return FALSE;
}

int main (char** argv, int argc) {
   cef_main_args_t main_args = {};
   main_args.argc = 0;
   main_args.argv = NULL;
   cef_app_t app = {};
   set_dummy_ref_counting(&app.base, sizeof(cef_app_t));
   cef_settings_t settings = {sizeof(cef_settings_t)};
   settings.log_severity = LOGSEVERITY_VERBOSE;
   settings.no_sandbox = 1;
   char c_path[] = "./cefsimple";
   cef_string_utf8_to_utf16(c_path, strlen(c_path), &settings.browser_subprocess_path);
   cef_initialize(&main_args, &settings, &app, NULL);
   
   gtk_init(0, NULL);
   XSetErrorHandler(x11_error_handler);
   XSetIOErrorHandler(x11_io_error_handler);
   GtkWindow* window = (GtkWindow*) gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(window, "CEF C API");
   g_signal_connect((GtkWidget*) window, "delete-event", (GCallback) on_gtk_widget_delete_event, NULL);
   gtk_window_set_default_size(window, 800, 600);
   gtk_widget_realize((GtkWidget*) window);
   GtkWidget* vbox = gtk_vbox_new(0, 0);
   gtk_container_add(GTK_CONTAINER(window), vbox);
   gtk_widget_show_all((GtkWidget*) window);
   GdkX11Window* gdk_window = (GdkX11Window*) gtk_widget_get_window((GtkWidget*) window);
   Window xid = gdk_x11_window_get_xid(gdk_window);
   gboolean realized = gtk_widget_get_realized((GtkWidget*) window);
   printf("GtkWindow realized: %d\n", (int) realized);
   printf ("xid: %d\n", (int) xid);
   
   GMainLoop* loop = g_main_loop_new(NULL, TRUE);
   g_timeout_add_full(G_PRIORITY_DEFAULT, (guint) 5000, quit_loop, (void*) loop, NULL);
   g_main_loop_run(loop); // Some time to type `wmctrl -lx` in terminal
   
   cef_window_info_t window_info = {};
   window_info.parent_window = xid;
   window_info.width = 800;
   window_info.height = 600;
   cef_client_t client = {};
   set_dummy_ref_counting(&client.base, sizeof(cef_client_t));
   char c_url[] = "https:/google.com";
   cef_string_t url = {};
   cef_string_utf8_to_utf16(c_url, strlen(c_url), &url);
   cef_browser_settings_t browser_settings = {sizeof(cef_browser_settings_t)};
   cef_browser_host_create_browser(&window_info, &client, &url, &browser_settings, NULL);
   
   g_timeout_add_full(G_PRIORITY_DEFAULT, (guint) 100, do_work, (void*) window, NULL);
   gtk_main ();
   cef_shutdown ();
   return 0;
}
fenryxo
Newbie
 
Posts: 5
Joined: Thu Sep 14, 2017 12:39 pm

Re: How to use CEF 3163 C API with GTK+ 3

Postby fenryxo » Fri Sep 15, 2017 7:23 am

I've looked at xlib manual to try to understand the X errors. It might be possible that CEF fails to create child window (code 8) and then uses the invalid handle further (code 3). But that's only my guess, I'm no expert in Xlib.

"X11 error: type=0, serial=200, code=8"
  • 8 = BadMatch (parameter mismatch)
  • In a graphics request, the root and depth of the graphics context does not match that of the drawable.
  • An InputOnly window is used as a drawable.
  • Some argument or pair of arguments has the correct type and range, but it fails to match in some other way required by the request.
  • An InputOnly window lacks this attribute.

14× "X11 error: type=0, serial=2xx, code=3"
  • 3 = BadWindow (arameter not a Window)
  • A value for a window argument does not name a defined window.
fenryxo
Newbie
 
Posts: 5
Joined: Thu Sep 14, 2017 12:39 pm

Re: [Solved] How to use CEF 3163 C API with GTK+ 3

Postby fenryxo » Sat Dec 09, 2017 9:43 am

In case that anyone would bump into this issue, I have resolved it elsewhere: cztomczak/cefcapi#9 & cztomczak/cefcapi#11
fenryxo
Newbie
 
Posts: 5
Joined: Thu Sep 14, 2017 12:39 pm


Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 35 guests