Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GTK+ 3.22 Port #9

Closed
jiri-janousek opened this issue Nov 11, 2017 · 31 comments
Closed

GTK+ 3.22 Port #9

jiri-janousek opened this issue Nov 11, 2017 · 31 comments

Comments

@jiri-janousek
Copy link
Contributor

gcc -std=c99 -Wall -Werror -o Release/cefcapi.out -I. -I.. -Wl,-rpath,. -L./Release examples/main_linux.c -lX11 -lcef `pkg-config --libs --cflags gtk+-3.0`
cd Release/ && ./cefcapi.out && cd ../

Process args: none (Main process)

initialize_cef_app
initialize_cef_base_ref_counted
cef_base_ref_counted_t.size = 72
cef_execute_process, argc=1
cef_base_ref_counted_t.add_ref
cef_base_ref_counted_t.release
cef_initialize
on_before_command_line_processing
on_register_custom_schemes
get_browser_process_handler

Process args: --type=zygote --no-sandbox --lang=en-US --log-file=/home/fenryxo/dev/projects/cef/cefcapi/Release/debug.log --log-severity=warning 

initialize_cef_app
initialize_cef_base_ref_counted
cef_base_ref_counted_t.size = 72
cef_execute_process, argc=6
cef_base_ref_counted_t.add_ref
cef_base_ref_counted_t.release
on_before_command_line_processing
on_register_custom_schemes
get_resource_bundle_handler
initialize_gtk
[1111/165611.209405:ERROR:nss_util.cc(747)] After loading Root Certs, loaded==false: NSS error code: -8018
create_gtk_window
initialize_client_handler
initialize_cef_base_ref_counted
cef_base_ref_counted_t.size = 152
cef_browser_host_create_browser
cef_run_message_loop
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
Segmentation fault

It would be great if we managed to make CEF work with GTK+ 3. I'm afraid I don't have enough experience with CEF to do it on my own.

@cztomczak
Copy link
Owner

Do these x11 errors also appear when using GTK 2?
Looks like window handle may be invalid. Make sure that the GTK window is realized and that xid is valid.

@jiri-janousek
Copy link
Contributor Author

Do these x11 errors also appear when using GTK 2?

No, only with GTK+ 3.

Looks like window handle may be invalid. Make sure that the GTK window is realized and that xid is valid.

The window handle is valid. The window is realized in examples/gtk.h:58. Also, the very first error is BadMatch (8), not BadWindow (3).

@cztomczak
Copy link
Owner

You can set parent window to NULL and CEF will create a window of its own such case. Set here NULL instead of xid:

window_info.parent_window = NULL;

Does it work then?

@cztomczak
Copy link
Owner

Take a look at hello world examples for GTK 3. Things might work a bit differently there. See for example here: https://developer.gnome.org/gtk3/stable/gtk-getting-started.html
Window is being created during "activate" event. In CEF Python gtk3 example works fine and has a similar structure as official GTK 3 examples, window is created in "startup" event and realized/shown in "activate" event along with embedding of browser.

@cztomczak
Copy link
Owner

@jiri-janousek
Copy link
Contributor Author

The result is the same with the GTK+ 3 Hello World exmaple. Both the original and the new example

  • crash with X errors when a valid xid is passed - the printed xid is not zero and I can see the window on the screen if I delay cef_do_message_loop_work().
  • show an extra fully functional CEF window when 0 is passed as window_info.parent_window.

So, for whatever reason, CEF seems not to like a valid window id.

Cefpython uses C++ API and its window_info.SetAsChild(xid) method. I'm wondering whether this method does something extra except for setting window_info members.

@cztomczak
Copy link
Owner

What OS and gtk3 version are you using?

@jiri-janousek
Copy link
Contributor Author

Debian 9 Stretch, GTK+ 3.22.11.

@cztomczak
Copy link
Owner

Can you try with GTK 3.10?

@jiri-janousek
Copy link
Contributor Author

Can you try with GTK 3.10?

Sure, I need to download Ubuntu 14.04 first.

Anyway, there are some experiments I tried yesterday.

Tracebacks from gdb:

Both logs contain

XSync
CefWindowX11::CefWindowX11 w 85983235, x 0, y 0, w 800, h 600 => 81788929
XSync

which comes from my modifications of CefWindowX11::CefWindowX11() (libcef/browser/native/window_x11.cc)

...
XSync(xdisplay_, 0);
printf("XSync\n");
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
swa.background_pixmap = None;
swa.override_redirect = false;
xwindow_ = XCreateWindow(xdisplay_, parent_xwindow_, bounds.x(), bounds.y(),
                           bounds.width(), bounds.height(),
                           0,               // border width
                           CopyFromParent,  // depth
                           InputOutput,
                           CopyFromParent,  // visual
                           CWBackPixmap | CWOverrideRedirect, &swa);
printf("CefWindowX11::CefWindowX11 w %u, x %d, y %d, w %u, h %u => %u\n",
(unsigned) parent_xwindow_,
bounds.x(), bounds.y(), bounds.width(), bounds.height(), (unsigned) xwindow_);
XSync(xdisplay_, 0);
printf("XSync\n");
...

and that means that the very first child window of the passed parent window has been created without any issues (no X errors emitted).

@cztomczak
Copy link
Owner

Looks to me there is an issue with embedding with newer GTK / XLib. Try these to workaround the issue:

  1. Try a different gtk widget structure. For example create GTK container in the window and embed CEF inside that container, see gtk_container_add.
  2. Call gtk_plug_new(xid) before embedding CEF
  3. Set window_info.parent_window to NULL and then after CEF is embedded reparent windows (using maybe XReparentWindow).

@jiri-janousek
Copy link
Contributor Author

Can you try with GTK 3.10?

Sure, I need to download Ubuntu 14.04 first.

It indeed does work with GTK+ 3.10.8-0ubuntu1.6 (Ubuntu 14.04). I'll now go up from 3.10 to find the first GTK+ release that does not work. I hope I will then understand the issue better and will try the suggested workarounds. Thanks for your tips.

@jiri-janousek
Copy link
Contributor Author

@cztomczak, I've identified the very first failing revision - GNOME/gtk@dae447728d between GTK+ 3.15.1 and 3.15.2. GTK+ changed the selection of default window visuals (need to study more what that means) and I guess that CEF uses incompatible visuals somewhere (hence the BadMatch X error).

@cztomczak
Copy link
Owner

@jiri-janousek
Copy link
Contributor Author

  • Disabling GPU does not help.
  • But using the default X visual instead of the GTK+'s blessed one works (at least with GTK+ revid dae447728d and 3.22.11):
GtkWidget* create_gtk_window(char* title, int width, int height) {
    printf("create_gtk_window\n");
    // Create window.
    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    ...
    // GTK+ > 3.15.1 uses an X11 visual optimized for GTK+'s OpenGL stuff
    // since revid dae447728d: https://github.com/GNOME/gtk/commit/dae447728d
    // However, it breaks CEF: https://github.com/cztomczak/cefcapi/issues/9
    // Let's use the default X11 visual instead the GTK's blessed one.
    GdkScreen* screen = gdk_screen_get_default();
    GList* visuals = gdk_screen_list_visuals(screen);
    printf("n visuals: %u\n", g_list_length(visuals));
    GdkX11Screen* x11_screen = GDK_X11_SCREEN(screen);
    g_assert(x11_screen != NULL);
    Visual* default_xvisual = DefaultVisual(GDK_SCREEN_XDISPLAY(x11_screen),
        GDK_SCREEN_XNUMBER(x11_screen));
    GdkVisual* default_visual = NULL;
    int i = 0;
    while (visuals != NULL) {
	GdkVisual* visual = GDK_X11_VISUAL (visuals->data);
        if (default_xvisual->visualid == gdk_x11_visual_get_xvisual(
           GDK_X11_VISUAL (visuals->data))->visualid) {
           printf("Default visual %d\n", i);
           default_visual = visual;
        }
        i++;
        visuals = visuals->next;
    }
    gtk_widget_set_visual(GTK_WIDGET(window), default_visual);
    gtk_widget_show_all(window);
    return vbox;
}
  • I'm going to prepare pull requests to add a working GTK+ 3 example here.

@jiri-janousek
Copy link
Contributor Author

So, I'm proposing following changes. Should I submit them as 5 separate pull requests or combine them somewhow?

  1. Update CEF headers to the latest stable CEF.
  2. Add some useful debug info (window xid, GTK version).
  3. Add a gtk3 target to the linux Makefile and modify the linux example to be buildable with both GTK+ 2 & 3 (using GTK_CHECK_VERSION macro).
  4. Add the X11 visual workaround for the GTK+ 3 example.
  5. Add a "modern" GTK+ 3 example that uses GtkApplication stuff.

@cztomczak
Copy link
Owner

Great progress Fenryxo! Updating CEF should be a separate PR. Others changes I would divide into two PRs: update old example + add new example.

@jiri-janousek
Copy link
Contributor Author

  1. Add a "modern" GTK+ 3 example that uses GtkApplication stuff.

This can be made later. Closing as the main issue has been addressed.

@cztomczak
Copy link
Owner

cztomczak commented Nov 28, 2018

@fenryxo I am working on an app that uses GTK 3.22 and your fix works good. The x11 default visual resolves issue. I am testing with CEF v70 (3538 branch). However I need transparent windows in my application and I need them to work in windowed mode. When using GTK 2 I can get transparent windows working just fine. However with GTK 3.22 only the default x11 visual seems to work with CEF. When I set a RGBA x11 visual then I get the same issue when using GTK 3 "blessed" visual. In my case with latest CEF v70 and in a C++ app I get a bit different stack trace with issue occuring when showing x11 window:

Received signal 11 SEGV_MAPERR 000000000000
#0 0x7f8b7c82bf7c base::debug::StackTrace::StackTrace()
#1 0x7f8b7c82bae1 base::debug::(anonymous namespace)::StackDumpSignalHandler()
#2 0x7f8b755095d0 <unknown>
#3 0x7f8b7c71adce CefWindowX11::Show()
#4 0x7f8b7c7183ec CefBrowserPlatformDelegateNativeLinux::CreateHostWindow()
#5 0x7f8b7c6539ca CefBrowserHostImpl::CreateInternal()
#6 0x7f8b7c65339b CefBrowserHostImpl::Create()
#7 0x7f8b7c652d85 CefBrowserHost::CreateBrowserSync()
#8 0x7f8b7aa66de0 cef_browser_host_create_browser_sync
#9 0x00000042bd2b CefBrowserHost::CreateBrowserSync()

I still have to debug this further as some symbols are missing. If you have any idea on how to make it work with RGBA visual then it would be greatly appreciated.

@cztomczak
Copy link
Owner

It seems that both our issues occur at a call to FindChild. Recently I've reported an another issue with PyQt / PySide apps and it also crashed at a call to FindChild:

https://bitbucket.org/chromiumembedded/cef/issues/2490/x11-findchild-fails-during-a-call-to

This line code seems to be the culrpit of all the issues:

https://github.com/chromiumembedded/cef/blob/49c149c20b4e95c38a0a4a568e54ee1904412ece/libcef/browser/native/window_x11.cc#L179

This is Marshall's comment:

Looks like XQueryTree is returning no children (it should have a child DesktopWindowTreeHostX11 created by Chromium). In any case the code should be fixed not to crash.

@cztomczak
Copy link
Owner

In your logs the crash also occurs at FindChild:

Thread 1 "cefcapi.out" received signal SIGSEGV, Segmentation fault.
0x00007ffff3856137 in FindChild () at ../../cef/libcef/browser/native/window_x11.cc:45
45	    child_window = children[0];
(gdb) bt
#0  0x00007ffff3856137 in FindChild () at ../../cef/libcef/browser/native/window_x11.cc:45

@cztomczak
Copy link
Owner

Here is the patch to fix FindChild failing:

diff --git a/libcef/browser/native/window_x11.cc b/libcef/browser/native/window_x11.cc
index 2300b1b..4e99e3c 100644
--- a/libcef/browser/native/window_x11.cc
+++ b/libcef/browser/native/window_x11.cc
@@ -40,9 +40,10 @@ const char kXdndProxy[] = "XdndProxy";
   ::Window child_window = x11::None;
   unsigned int nchildren;
   if (XQueryTree(display, window, &root, &parent, &children, &nchildren)) {
-    DCHECK_EQ(1U, nchildren);
-    child_window = children[0];
-    XFree(children);
+    if (children) {
+        child_window = children[0];
+        XFree(children);
+    }
   }
   return child_window;
 }

However now I get an error during a call to XGetWindowAttributes in Chromium code:

bool NativeViewGLSurfaceGLX::Initialize(GLSurfaceFormat format) {
  XWindowAttributes attributes;
  if (!XGetWindowAttributes(gfx::GetXDisplay(), parent_window_, &attributes)) {
    LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
               << ".";
    return false;
  }

Ref: https://cs.chromium.org/chromium/src/ui/gl/gl_surface_glx.cc?l=579&rcl=2e348902bd9ebac4f3e4d15665c4b32d67d88389

@cztomczak
Copy link
Owner

Reported issue on the CEF Forum: https://magpcss.org/ceforum/viewtopic.php?f=6&t=16402

@jiri-janousek
Copy link
Contributor Author

Hello @cztomczak, I no longer use the original approach - forcing GTK+ to use the default X Visual. Instead, I force CEF to use the visual selected by GTK+ (tiliado/cef@d53adf7 & tiliado/valacef@1184840). If I recall correctly, the reason for that was an issue with transparency - GTK+ 3 client-side decorations didn't work correctly with the default X Visual.

It seems that both our issues occur at a call to FindChild.

Looks like XQueryTree is returning no children (it should have a child DesktopWindowTreeHostX11 created by Chromium).

I think that no X window is actually created because of conflicting X visuals, so there is simply no window to find. All subsequent X calls should fail as well because of invalid window id.

@cztomczak
Copy link
Owner

@fenryxo Thanks. With your patch I am able to get it working with default GTK 3 visual. However I still can't get whole window transparency to work.

@cztomczak
Copy link
Owner

cztomczak commented Nov 30, 2018

I get a transparent GTK 3 window working with such code:

GdkScreen *gtk_screen = gtk_window_get_screen( m_window );
GdkVisual *rgba_visual = gdk_screen_get_rgba_visual( gtk_screen );
gtk_widget_set_visual( m_widget_window, rgba_visual );
GtkCssProvider *provider = gtk_css_provider_new();
GError *error = NULL;
gtk_css_provider_load_from_data( provider,
    "#main-window { background-color: rgba(0, 0, 0, 0); }",
    -1, &error );
g_assert_no_error( error );
gtk_style_context_add_provider_for_screen(
    gdk_screen_get_default(),
    GTK_STYLE_PROVIDER( provider ),
    GTK_STYLE_PROVIDER_PRIORITY_USER );
g_object_unref( provider );
gtk_widget_set_name( m_widget_window, "main-window" );

Then I embed CEF browser inside it and the background becomes white.

I then try apply your patch and call override functions to set RGBA visual and I still see white background:

GdkScreen* screen = gdk_screen_get_default();
GdkVisual *rgba_visual = gdk_screen_get_rgba_visual( screen );
VisualID xvisualid = gdk_x11_visual_get_xvisual(
        GDK_X11_VISUAL(rgba_visual))->visualid;
cef_override_system_visual(xvisualid);
cef_override_rgba_visual(xvisualid);

Overriding with GTK 3 visual also doesn't work, the background is still white:

GdkVisual* system_visual = gtk_widget_get_visual( m_widget_window );
VisualID xvisualid = gdk_x11_visual_get_xvisual(
        GDK_X11_VISUAL(system_visual))->visualid;
cef_override_system_visual(xvisualid);
cef_override_rgba_visual(xvisualid);

@jiri-janousek
Copy link
Contributor Author

Is the white background painted by GTK or CEF?

@jiri-janousek
Copy link
Contributor Author

My understanding of the docs for cef_settings_t.background_color is that transparent background should not work for windowed rendering (emphasis mine):

Background color used for the browser before a document is loaded and when no document color is specified. The alpha component must be either fully opaque (0xFF) or fully transparent (0x00). If the alpha component is fully opaque then the RGB components will be used as the background color. If the alpha component is fully transparent for a windowed browser then the default value of opaque white be used. If the alpha component is fully transparent for a windowless (off-screen) browser then transparent painting will be enabled.

@cztomczak
Copy link
Owner

cztomczak commented Sep 24, 2019

@fenryxo Thanks. Just a follow up. I managed to get transparency working, but without GTK. It required additional code patching in Chromium and CEF.

@jiri-janousek
Copy link
Contributor Author

Thanks for letting me know. Are the patches in upstream CEF repo?

@cztomczak
Copy link
Owner

cztomczak commented Sep 29, 2019

It was part of a proprietary system, but I can let you know what needs to be done. In that specific system I couldn't make it work with GTK 3, but it worked in cefclient with GTK 2. There is a PR in CEF that adds transparency support, but only when running app in Views mode (--use-views switch): https://bitbucket.org/chromiumembedded/cef/pull-requests/136/add-support-for-windowed-mode-transparency/diff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants