Created
December 19, 2016 06:43
-
-
Save AnishN/989926e5ca3e5a21f830aae6e2187e1b to your computer and use it in GitHub Desktop.
Demo to time python -> javascript -> python calls in CEF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <head> | |
| <style> | |
| html * | |
| { | |
| font-family: Arial; | |
| font-size: 12px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <label>Color: <input type="button" value="Test Callback" onclick="call_js();"></label> | |
| <script> | |
| function call_js() | |
| { | |
| var time_stamp = new Date().getTime()/1000.0; | |
| window.call_py(time_stamp); | |
| } | |
| </script> | |
| </body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from cefpython3 import cefpython as cef | |
| import sys | |
| import pygame | |
| from PIL import Image | |
| from OpenGL.GL import * | |
| from OpenGL.GLU import * | |
| import inspect | |
| import time | |
| class Timer: | |
| start_time = 0 | |
| stop_time = 0 | |
| @classmethod | |
| def start(cls): | |
| Timer.start_time = time.time() | |
| @classmethod | |
| def stop(cls): | |
| Timer.stop_time = time.time() | |
| class CEFSettings: | |
| app_settings = { | |
| "auto_zooming": "system_dpi", | |
| "debug": False, | |
| "locales_dir_path": cef.GetModuleDirectory()+"/locales", | |
| "resources_dir_path": cef.GetModuleDirectory(), | |
| "browser_subprocess_path": "%s/%s" % (cef.GetModuleDirectory(), "subprocess"), | |
| "unique_request_context_per_browser": True, | |
| "downloads_enabled": False, | |
| "remote_debugging_port": 0, | |
| "context_menu": { | |
| "enabled": False, | |
| }, | |
| "ignore_certificate_errors": True, | |
| #"multi_threaded_message_loop": True,#disable this if needed | |
| } | |
| browser_settings = { | |
| "file_access_from_file_urls_allowed": True, | |
| "universal_access_from_file_urls_allowed": True, | |
| } | |
| command_line_settings = { | |
| "disable-gpu": "", | |
| "disable-gpu-compositing": "", | |
| "enable-begin-frame-scheduling": "", | |
| "disable-d3d11": "", | |
| "off-screen-rendering-enabled": "", | |
| "off-screen-frame-rate": "60", | |
| "disable-gpu-vsync": "", | |
| "disable-web-security": "", | |
| } | |
| class Window: | |
| def __init__(self, title, width, height): | |
| self.title = title | |
| self.width = width | |
| self.height = height | |
| cef.DpiAware.SetProcessDpiAware() | |
| cef.Initialize(CEFSettings.app_settings, CEFSettings.command_line_settings) | |
| self.setup_pygame() | |
| self.setup_ui_texture() | |
| self.setup_cef() | |
| def add_callback(self, callback): | |
| callback_name = callback.__name__ | |
| window.js_bindings.SetFunction(callback_name, callback) | |
| window.js_bindings.SetProperty("sources", {callback_name: inspect.getsource(callback)}) | |
| window.browser.SetJavascriptBindings(window.js_bindings) | |
| def setup_pygame(self): | |
| size = (self.width, self.height) | |
| flags = 0 | |
| flags = pygame.OPENGL | pygame.DOUBLEBUF | |
| pygame.init() | |
| dummy_screen = pygame.display.set_mode((1, 1), flags) | |
| max_msaa = glGetIntegerv(GL_MAX_SAMPLES) | |
| pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLEBUFFERS, 1) | |
| pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLESAMPLES, max_msaa) | |
| self.screen = pygame.display.set_mode(size, flags) | |
| self.window = pygame.display.get_wm_info()["window"] | |
| self.clock = pygame.time.Clock() | |
| def setup_cef(self): | |
| windowInfo = cef.WindowInfo() | |
| windowInfo.SetAsOffscreen(self.window) | |
| windowInfo.SetTransparentPainting(True) | |
| self.browser = cef.CreateBrowserSync(windowInfo, browserSettings=CEFSettings.browser_settings, navigateUrl="file:///transparent-test.html") | |
| #self.browser = cef.CreateBrowser(windowInfo, browserSettings=CEFSettings.browser_settings, navigateUrl="file:///transparent-test.html") | |
| empty_texture = pygame.Surface((self.width, self.height)) | |
| self.client = ClientHandler(self.browser, empty_texture) | |
| self.browser.SetClientHandler(self.client) | |
| self.js_bindings = cef.JavascriptBindings() | |
| def setup_ui_texture(self): | |
| self.cef_tex_id = glGenTextures(1) | |
| glBindTexture(GL_TEXTURE_2D, self.cef_tex_id) | |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) | |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) | |
| glBindTexture(GL_TEXTURE_2D, 0) | |
| def load_html_ui(self, ui_url): | |
| self.browser.LoadUrl(ui_url) | |
| def render_html_ui(self): | |
| glEnable(GL_TEXTURE_2D) | |
| glMatrixMode(GL_PROJECTION) | |
| glLoadIdentity() | |
| glOrtho(0, self.width, self.height, 0, -1, 1) | |
| glMatrixMode(GL_MODELVIEW) | |
| glLoadIdentity() | |
| glBindTexture(GL_TEXTURE_2D, self.cef_tex_id) | |
| tex_surface = pygame.image.tostring(self.client.texture, "RGBA") | |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_surface) | |
| glBegin(GL_QUADS) | |
| glTexCoord(0, 0) | |
| glVertex(0, 0, 0) | |
| glTexCoord(0, 1) | |
| glVertex(0, self.height, 0) | |
| glTexCoord(1, 1) | |
| glVertex(self.width, self.height, 0) | |
| glTexCoord(1, 0) | |
| glVertex(self.width, 0, 0) | |
| glEnd() | |
| glBindTexture(GL_TEXTURE_2D, 0) | |
| def update(self, app_func): | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| cef.Shutdown() | |
| pygame.quit() | |
| sys.exit() | |
| elif event.type == pygame.MOUSEBUTTONDOWN: | |
| mouse_x, mouse_y = event.pos | |
| if event.button == 1: | |
| self.browser.SendMouseClickEvent(mouse_x, mouse_y, cef.MOUSEBUTTON_LEFT, False, 1) | |
| Timer.start() | |
| elif event.type == pygame.MOUSEBUTTONUP: | |
| mouse_x, mouse_y = event.pos | |
| if event.button == 1: | |
| self.browser.SendMouseClickEvent(mouse_x, mouse_y, cef.MOUSEBUTTON_LEFT, True, 1) | |
| elif event.type == pygame.MOUSEMOTION: | |
| mouse_x, mouse_y = event.pos | |
| self.browser.SendMouseMoveEvent(mouse_x, mouse_y, True) | |
| cef.MessageLoopWork() | |
| glClearColor(1, 1, 1, 1) | |
| glClear(GL_COLOR_BUFFER_BIT) | |
| glEnable(GL_BLEND) | |
| glEnable(GL_MULTISAMPLE) | |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) | |
| app_func() | |
| self.render_html_ui() | |
| pygame.display.set_caption("CEF Callback Test") | |
| pygame.display.flip() | |
| class ClientHandler: | |
| def __init__(self, browser, texture): | |
| self.browser = browser | |
| self.texture = texture | |
| def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width, height): | |
| data = buffer.GetString(mode="rgba", origin="bottom-left") | |
| img = Image.frombuffer('RGBA', (width, height), data, 'raw', 'BGRA') | |
| img = pygame.image.fromstring(img.tobytes(), (width, height), "RGBA", True) | |
| self.texture = img | |
| def GetViewRect(self, browser, rect): | |
| width, height = self.texture.get_size() | |
| rect.extend([0, 0, width, height]) | |
| return True | |
| def call_py(js_time): | |
| Timer.stop() | |
| start_time = Timer.start_time | |
| stop_time = Timer.stop_time | |
| js_time = float(js_time) | |
| py_js = js_time - start_time | |
| js_py = stop_time - js_time | |
| total = stop_time - start_time | |
| print py_js, js_py, total | |
| def main_loop(): | |
| pass | |
| if __name__ == "__main__": | |
| window = Window("PyOpenGL + CEFPython Test", 800, 600) | |
| window.load_html_ui("file:///message-test.html") | |
| window.add_callback(call_py) | |
| while True: | |
| window.update(main_loop) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment