Skip to content

Instantly share code, notes, and snippets.

@AnishN
Created December 19, 2016 06:43
Show Gist options
  • Select an option

  • Save AnishN/989926e5ca3e5a21f830aae6e2187e1b to your computer and use it in GitHub Desktop.

Select an option

Save AnishN/989926e5ca3e5a21f830aae6e2187e1b to your computer and use it in GitHub Desktop.
Demo to time python -> javascript -> python calls in CEF
<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>
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