I started to try to use the implemented off-screen rendering of cef3 for linux. (Since it is available now)
Currently i am working with r1297 of cef.
But to be honest I am quite lost. My knowledge with cython and cef is still small.
I started by making the function SetAsOffscreen() available in linux. After editing cef_linux.h and cef_types_linux.h (by adding functions and variables) I got it to the point on which it compiles without any errors.
But as I thought, it can't be that simple.
When I try to "cefpython.CreateBrowserSync()" cef throws an error: ERROR_REPORT:browser_host_impl.cc(286)] Check failed: false. CefRenderHandler implementation is required
Can someone guess how much work it needs that this can be done? (I just don't have a clue)
What have to be done?
Thanks,
Jegger
My current state is: https://github.com/jegger/cefpython/commit/677bed47c5767e660839a7e08456586b10735940
(or should I use google code? => never used it)
I wrote a short python script (mostly copied from the panda3d example): http://pastebin.com/FpgG9dFH (which uses the kivy framework) to test the changes.
output: http://pastebin.com/y762i3jy
I guess the log looks not bad. But now I don't have a clue how to get to the texture from cef.
Should the function OnPaint() in the ClientHandler class be called? (It doesn't)
Is the displayed ERROR_REPORT from cef important?
Thanks,
Jegger
[0714/135755:ERROR_REPORT:render_widget_host_view_osr.cc(271)] Check failed: false.
As I see in the browser.pyx, the function SetSize() tries to map the function SetSize in: https://code.google.com/p/chromiumembedded/source/browse/branches/1453/cef3/include/cef_browser.h
But there isn't a function like GetSize in this file. In cef1 it seems to be implemented.
Is there a workaround?
Actually I don't understand what you mean. Maybe the real issue is that I don't really understand how cef handles osr.
I assume of the following:
1. init cef
2. set offscreen rendering flag
3. create browser
4. define the size of the texture (for cef) => via SetSize() or GetViewRect()?
5. receive the texture in the function OnPaint of RenderHandler?
Is this correct? I was not able to find any documentation about that yet.
If I assume the way I described above, then GetViewRect(browser, (0,0,width,height)) should be called from the .py ? But GetViewRect seems something like a callback for me which get called from cef?
Thanks,
Jegger
From the .py file I can't do that cause I don't have the browser object yet. I thought of several approaches but either they failed or are just ugly. I wish it would be somehow possible to pass the handler to the function CreateBrowserSync() directly.
What I don't understand: in cefpython.pyx - CreateBrowserSync() there get cef_browser_static.CreateBrowserSync() called. After that somehow GetPyBrowser() in browser.pyx get called. But from where?
What would you think is an appropriate solution?
Regards,
Jegger
I have a hard time calling SetClientHandler() in browser.pyx while the browser is being created.From the .py file I can't do that cause I don't have the browser object yet. I thought of several approaches but either they failed or are just ugly. I wish it would be somehow possible to pass the handler to the function CreateBrowserSync() directly.
self.browser = cefpython.CreateBrowserSync( windowInfo, browserSettings, navigateUrl="about:blank") self.browser.SetClientHandler( ClientHandler(self.browser, self.texture))
self.browser.GetMainFrame().LoadUrl(GetApplicationPath("cefsimple.html")))
/// // Notify the browser that the widget has been resized. The browser will first // call CefRenderHandler::GetViewRect to get the new size and then call // CefRenderHandler::OnPaint asynchronously with the updated regions. This // method is only used when window rendering is disabled. /// /*--cef()--*/ virtual void WasResized() =0;
My current cycle is (line 42 - 70): https://github.com/jegger/cefpython/blob/cef3_linux_osr/cefpython/cef3/linux/binaries_64bit/kivypy.py
Thanks,
Jegger
return RenderHandler_GetViewRect(browser, rect);
rect.x = 0
rect.y = 0
rect.width = 800
rect.height = 600
return True
> Try to pass 0 when calling SetAsOffscreen().
This raises an error. => http://pastebin.com/e8FzFmGa
if not windowInfo.parentWindowHandle:
raise Exception("WindowInfo: parentWindowHandle is not set")
> What kind of handle are you passing to the SetAsOffscreen() method? Is this a pointer to the physical
> window or to the gtk widget? Try both, though I think you have to pass pointer to the gtk widget.
>
This number I wrote was just a dummy number. I thought it doesn't have any impact?
Anyhow, I indicate the windowID now and pass it to SetAsOffscreen(). I use the windowID because in the panda3d example the function getIntHandle() get called which returns the windowID.
(This doesn't rise any error but onPaint() doesn't get called)
As I see just now the datatype seems different on linux. => include/internal/cef_typeds_linux.h => GtkWidget* (as you expected).
I have to admit that I currently have no idea how to get to the pointer of the gtk widget. PyGame is the window provider which kivy is using.
---
I just tried something: https://gist.github.com/jegger/6009801
There I mixed the wxpython example with os-rendering. OnPaint get called!!
It seems that the gtkwidget is requred. I think my issue in this case is that with PyGame I don't have any gtkwidget at all.
Is OSR still possible without gtk on linux? Is gtk absolutely necessary?
Is OSR still possible without gtk on linux? Is gtk absolutely necessary?
Passing NULL should work.
Does SetAsOffscreen(0) result to NULL? - if not; I've overwritten ParentWidget and set it to NULL in cef_linux.h to be sure. => But it's still not working.
I think I try to write a script with an own main loop (without another framework - in this case kivy).
Does cefpython need some special things when running in a other loop? Something that has to be called every frame etc...?
I think I try to write a script with an own main loop (without another framework - in this case kivy).
Does cefpython need some special things when running in a other loop? Something that has to be called every frame etc...?
def messageLoop(self, task):
cefpython.MessageLoopWork()
return Task.cont
Call it in the OnIdle event or similar. -Czarek |
void MessageLoop()
Run the CEF message loop. Use this function instead of an application- provided message loop to get the best balance between performance and CPU usage. This function should only be called on the main application thread (UI thread) and only if cefpython.Initialize() is called with a ApplicationSettings.multi_threaded_message_loop value of false. This function will block until a quit message is received by the system.
void MessageLoopWork()
Perform a single iteration of CEF message loop processing. This function is used to integrate the CEF message loop into an existing application message loop. Care must be taken to balance performance against excessive CPU usage. This function should only be called on the main application thread (UI thread) and only if cefpython.Initialize() is called with aApplicationSettings.multi_threaded_message_loop value of false. This function will not block.
Alternatively you could create a periodic timer (with 10 ms interval) that calls cefpython.MessageLoopWork().
Now OnPaint() get called. But... if I do: buffer.GetString() =>
the return value is very strange: it starts with: 511TV-OUT 32MB?Ɂ?d HGladiac 511TV-OUT 64MB@V??e...
As a result of this, the rendered image is just nonsense: http://jegger.ch/datapool/images/cefpy.png (left bottom corner)
def _saveImage(self): try: from PIL import Image except: print("PIL library not available, can't save image") return (width, height) = self.browser.GetSize(cefpython.PET_VIEW) buffer = self.browser.GetImage(cefpython.PET_VIEW, width, height) image = Image.fromstring( "RGBA", (width,height), buffer.GetString(mode="rgba", origin="top-left"), "raw", "RGBA", 0, 1) image.save("panda3d_image.png", "PNG")
While trying to implement _saveImgae() I saw that include/cef_browser.h only in cef1 has the function GetImage() which seems needed for this.
Long story short: It is working now!
I want to thank you for your support. Even it looks like you did all the work ;) - I at least learned a lot.
---
In RenderHandler_OnPaint() I need the size of the browser. This is in cef1 done by GetSize() -> But this isn't implemented in cef3 as we know. I call GetViewRect() to get the size. Is this a good idea?
https://github.com/jegger/cefpython/blob/9022b264b3c209c126c93f321825b6e66592d88a/cefpython/render_handler.pyx
Thanks,
Jegger
While trying to implement _saveImgae() I saw that include/cef_browser.h only in cef1 has the function GetImage() which seems needed for this.
In RenderHandler_OnPaint() I need the size of the browser. This is in cef1 done by GetSize() -> But this isn't implemented in cef3 as we know. I call GetViewRect() to get the size. Is this a good idea?
https://github.com/jegger/cefpython/blob/9022b264b3c209c126c93f321825b6e66592d88a/cefpython/render_handler.pyx
Regarding PyGame: Kivy uses PyGame as their window provider. But I don't have any PyGame experience.
--
I just pushed this minute a newer version with working mouse/touch support. As kivy is mainly built for touch, this means it has touch support. The keyboard implementation is weak. Writing is possible but other keys like backspace or tab aren't working. What the example does (it is a WIP):
- Launches a website in the size of the window.
- Forwards on_touch_down, on_touch_move, on_touch_up (is working with the mouse to)
- Forwarding key inputs
What I need to do next is: Stable keyboard input, Get a callback when a textinput field is activ (to show the onscreen keyboard in kivy) -> Didn't do any research on this. (I hope this is somehow possible), And do some kind of go_back, go_forward UI.
I will work on that the week after next. (Next, I enjoy my holiday :) ). I am sure I can provide in that week a stable kivy example, as I need that anyway.
Best regards,
Jegger
The kivy example isn't finished yet:
- GoBack() and GoForward() should already be implemented? (If I call them, they don't do anything)
- Keyboard input: CefKeyEvent =>How do I send key like enter, or backspace etc? (the doc of cef(CefKeyEvent) isn't helping me there)
- To get a callback when a textinput field is active: I think thats the same issue like #57 on the cefpython issue tracker?
It's possible that I get myself the answers to the questions above. But if you have some useful tips i'd be glad.
Regards,
Jegger
I had a hard time merging your changes with my current branch. Can't say why - it just run into some wired errors. - Anyway: I just think it would be super cool if you can merge the osr code into your master. Do I have to do anything for that? - I only used pull requests to collaborate (github) before. I have no idea of google code.
The kivy example isn't finished yet:
- GoBack() and GoForward() should already be implemented? (If I call them, they don't do anything)
- Keyboard input: CefKeyEvent =>How do I send key like enter, or backspace etc? (the doc of cef(CefKeyEvent) isn't helping me there)
- To get a callback when a textinput field is active: I think thats the same issue like #57 on the cefpython issue tracker?