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

[gtk3.py] Blank window, browser embedding fails due to invalid X11 handle #393

Open
cztomczak opened this issue Aug 23, 2017 · 10 comments
Open

Comments

@cztomczak
Copy link
Owner

cztomczak commented Aug 23, 2017

This issue occurs on some of machines. There is no error in console logs. When ran with --debug flag you can see many X11 errors after the call to CreateBrowserSync. Thus it looks like the X11 window handle is invalid. See example log:

[0815/213053.597125:INFO:x11.cpp(9)] [Browser process] X error received: type 0,
serial 177, error_code 8, request_code 1, minor_code 0

Issue #446 ("Support linking to GTK 3 when building CEF from sources and when building cefpython module") might resolve this issue. But still some GTK 3 versions will just fail.

The original reporter didn't provide OS information, but I guess this is only Linux issue.

There was a similar issue in gtk2.py (GTK 2) example reported on the Forum here and the solution was to show the window before embedding browser, so that window is realized and X11 window handle is available.

I cannot reproduce this issue on my Ubuntu 14.04 with CEF Python v57.0, thus I cannot debug this.

Issue originally reported on the Forum:
https://groups.google.com/d/topic/cefpython/Oa1kybcNdh4/discussion

@gzfrancisco
Copy link

I can reproduce the error. Anyone know how to fix it?

[0221/192104.776178:INFO:x11.cpp(9)] [Browser process] X error received: type 0, serial 151, error_code 8, request_code 1, minor_code 0

@cztomczak
Copy link
Owner Author

@gzfrancisco Two things to try:

  1. Install all system updates
  2. Embed browser only after window is shown and verify that window handle is valid

To debug this further please create a topic on the Forum for your case. The original reporter had still issues in his script that weren't fixed (window was not resized properly).

@gzfrancisco
Copy link

I just did that. The script runs but the window doesn't appear.
Only after remove CreateBrowserSync the window appears empty(obviously).

What can it be?

@cztomczak
Copy link
Owner Author

It might be that the specific GTK 3 version that is used is broken. There is this issue in cefcapi project that states that GTK 3.15 and later are broken with CEF. But 3.10 works fine. If you want to use latest then there is a comment with a solution which is to use the default X visual instead of GTK's blessed one. You can try that. I don't have python code for that. See: cztomczak/cefcapi#9

@cztomczak
Copy link
Owner Author

Might be related to: #347

@cztomczak
Copy link
Owner Author

Issue #446 ("Support linking to GTK 3 when building CEF from sources and when building cefpython module") might resolve this issue. But still some GTK 3 versions will just fail.

@haimgel
Copy link

haimgel commented Nov 1, 2018

It seems like GTK 3.15 just flat out refuses to provide a real root window visual. No matter how I tried to get it, it always substituted a RGBA visual, which caused this bug.

However, doing something like this works:
self.window.set_visual(self.window.get_screen().lookup_visual(0x21))

E.g. if you find out the true ID of the root window visual (not using GTK), CEF window can be embedded into GTK window.

I also tried compiling CEF + CEF Python from sources with the same GTK version that I use, it didn't help at all.

@rocker71
Copy link

I ran into this problem for wxPython, fresh Ubuntu 18.04, cefpython3 from pip. I can't really submit a patch, but in general, I coded the above solution referenced by @haimgel . It's more difficult to do from Wx, or there is a better way and I haven't found it. Ultimately, I created a fresh ScrolledWindow for the browser to parent. I also had to modify the OnSize routine accordingly to resize my new parent scroll window. Finally, after this, I was able to replace the call to "wx.CallLater" to the embed_browser routine, with a simple call to "wx.CallAfter". The wx.CallAfter will happen ASAP as soon as rendering occurs, so the handles needed will be available, and I think its more reliable.

Note, I'm using python3 (3.6.5 comes on Ubuntu 18.04), so I don't know if this is compatible at all with python2.7. But I suspect the same technique would work.

In the "if LINUX" section at top of code:

if LINUX:
  import gi
  gi.require_version('Gtk','3.0')
  from gi.repository import Gtk , Gdk , GdkX11

For "embed_browser":

def embed_browser(self):
        print("right before embed browser")
        window_info = cef.WindowInfo()
        (width, height) = self.browser_panel.GetClientSize().Get()
        assert self.browser_panel.GetHandle(), "Window handle not available"
        handle_to_use = self.browser_panel.GetHandle()
        display = Gdk.Display.get_default()
        window = GdkX11.X11Window.foreign_new_for_display(display,handle_to_use)
        self.gtk_window = gtk_window = Gtk.Window()
        def callback(gtk_window,window):
          print("inside callback")
          gtk_window.set_window(window)
          gtk_window.set_visual( gtk_window.get_screen().lookup_visual(0x21))
        gtk_window.connect("realize",callback,window)
        gtk_window.set_has_window(True)
        gtk_window.show()
 
        sw = Gtk.ScrolledWindow()
        sw.show()
        gtk_window.add(sw)
        sw.set_visual( sw.get_screen().lookup_visual(0x21))
        self.sw = sw
        self.Show()
        window_info.SetAsChild(sw.get_window().get_xid(),
                               [0, 0, width, height])
        self.browser = cef.CreateBrowserSync(window_info,
                                             url="https://www.google.com/")
        self.browser.SetClientHandler(FocusHandler())

For OnSize:

   def OnSize(self, _):
        if not self.browser:
            return
        if WINDOWS:
            cef.WindowUtils.OnSize(self.browser_panel.GetHandle(),
                                   0, 0, 0)
        elif LINUX:
            (x, y) = (0, 0)
            (width, height) = self.browser_panel.GetSize().Get()
            self.browser.SetBounds(x, y, width, height)
            self.sw.get_window().move_resize(x,y,width,height)
        self.browser.NotifyMoveOrResizeStarted()

@mattkol
Copy link

mattkol commented Jan 16, 2020

@cztomczak @rocker71 this was quite helpful!
Thanks.

@nicolaspapp
Copy link

@rocker71 That's a very interesting approach. I have managed to replicate it also in Ubuntu 18.04.
The only think I notice is that resizing is not working properly. Any ideas on that? Looks the windows is resizing but not the browser

image

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

No branches or pull requests

6 participants