22# License: New BSD License.
33# Website: http://code.google.com/p/cefpython/
44
5- # If you try to keep PyBrowser() objects inside c_vector you will
5+ # If you try to keep PyBrowser() objects inside cpp_vector you will
66# get segmentation faults, as they will be garbage collected.
77
88cdef dict g_pyBrowsers = {}
@@ -23,7 +23,8 @@ cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser):
2323
2424 for id , pyBrowser in g_pyBrowsers.items():
2525 if not pyBrowser.cefBrowser.get():
26- Debug(" GetPyBrowser(): removing an empty CefBrowser reference, browserId=%s " % id )
26+ Debug(" GetPyBrowser(): removing an empty CefBrowser reference, "
27+ " browserId=%s " % id )
2728 del g_pyBrowsers[id ]
2829
2930 Debug(" GetPyBrowser(): creating new PyBrowser, browserId=%s " % browserId)
@@ -74,11 +75,13 @@ IF CEF_VERSION == 3:
7475
7576 cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(
7677 CefRefPtr[CefBrowser] cefBrowser) except * :
77- cdef CefRefPtr[CefBrowserHost] cefBrowserHost = cefBrowser.get().GetHost()
78+ cdef CefRefPtr[CefBrowserHost] cefBrowserHost = (
79+ cefBrowser.get().GetHost())
7880 if < void * > cefBrowserHost != NULL and cefBrowserHost.get():
7981 return cefBrowserHost
80- raise Exception (" GetCefBrowserHost() failed: this method of Browser object "
81- " can only be called in the browser process." )
82+ raise Exception (" GetCefBrowserHost() failed: this method of "
83+ " Browser object can only be called in the "
84+ " browser process." )
8285
8386cdef class PyBrowser:
8487 cdef CefRefPtr[CefBrowser] cefBrowser
@@ -96,29 +99,38 @@ cdef class PyBrowser:
9699 cdef public int gwlExStyle
97100 cdef public tuple windowRect
98101
102+ cdef void * imageBuffer
103+
99104 cdef CefRefPtr[CefBrowser] GetCefBrowser(self ) except * :
100105 if < void * > self .cefBrowser != NULL and self .cefBrowser.get():
101106 return self .cefBrowser
102- raise Exception (" PyBrowser.GetCefBrowser() failed: CefBrowser was destroyed" )
107+ raise Exception (" PyBrowser.GetCefBrowser() failed: CefBrowser "
108+ " was destroyed" )
103109
104110 IF CEF_VERSION == 3 :
105111
106112 cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(self ) except * :
107- cdef CefRefPtr[CefBrowserHost] cefBrowserHost = self .GetCefBrowser().get().GetHost()
113+ cdef CefRefPtr[CefBrowserHost] cefBrowserHost = (
114+ self .GetCefBrowser().get().GetHost())
108115 if < void * > cefBrowserHost != NULL and cefBrowserHost.get():
109116 return cefBrowserHost
110- raise Exception (" PyBrowser.GetCefBrowserHost() failed: this method "
111- " can only be called in the browser process." )
117+ raise Exception (" PyBrowser.GetCefBrowserHost() failed: this "
118+ " method can only be called in the browser process." )
112119
113120 def __init__ (self ):
114121 self .clientCallbacks = {}
115122 self .allowedClientCallbacks = []
116123 self .userData = {}
117124
125+ def __del__ (self ):
126+ if self .imageBuffer:
127+ free(self .imageBuffer)
128+
118129 cpdef py_void SetClientCallback(self , py_string name, object callback):
119130 if not self .allowedClientCallbacks:
120131 # CefLoadHandler.
121- self .allowedClientCallbacks += [" OnLoadEnd" , " OnLoadError" , " OnLoadStart" ]
132+ self .allowedClientCallbacks += [" OnLoadEnd" , " OnLoadError" ,
133+ " OnLoadStart" ]
122134
123135 # CefKeyboardHandler.
124136 self .allowedClientCallbacks += [" OnKeyEvent" ]
@@ -127,32 +139,43 @@ cdef class PyBrowser:
127139 self .allowedClientCallbacks += [" OnUncaughtException" ]
128140
129141 # CefRequestHandler.
130- self .allowedClientCallbacks += [" OnBeforeBrowse" , " OnBeforeResourceLoad" ,
131- " OnResourceRedirect" , " OnResourceResponse" , " OnProtocolExecution" ,
132- " GetDownloadHandler" , " GetAuthCredentials" , " GetCookieManager" ]
142+ self .allowedClientCallbacks += [" OnBeforeBrowse" ,
143+ " OnBeforeResourceLoad" , " OnResourceRedirect" ,
144+ " OnResourceResponse" , " OnProtocolExecution" ,
145+ " GetDownloadHandler" , " GetAuthCredentials" ,
146+ " GetCookieManager" ]
133147
134148 # CefDisplayHandler.
135- self .allowedClientCallbacks += [" OnAddressChange" , " OnConsoleMessage" ,
136- " OnContentsSizeChange" , " OnNavStateChange" , " OnStatusMessage" ,
137- " OnTitleChange" , " OnTooltip" ]
149+ self .allowedClientCallbacks += [" OnAddressChange" ,
150+ " OnConsoleMessage" , " OnContentsSizeChange" ,
151+ " OnNavStateChange" , " OnStatusMessage" , " OnTitleChange" ,
152+ " OnTooltip" ]
138153
139154 # LifespanHandler.
140- self .allowedClientCallbacks += [" DoClose" , " OnAfterCreated" , " OnBeforeClose" ,
141- " RunModal" ]
155+ self .allowedClientCallbacks += [" DoClose" , " OnAfterCreated" ,
156+ " OnBeforeClose" , " RunModal" ]
157+
158+ # RenderHandler
159+ self .allowedClientCallbacks += [" GetViewRect" , " GetScreenRect" ,
160+ " GetScreenPoint" , " OnPopupShow" , " OnPopupSize" ,
161+ " OnPaint" , " OnCursorChange" ]
142162
143163 if name not in self .allowedClientCallbacks:
144- raise Exception (" Browser.SetClientCallback() failed: unknown callback: %s " % name)
164+ raise Exception (" Browser.SetClientCallback() failed: unknown "
165+ " callback: %s " % name)
145166
146167 self .clientCallbacks[name] = callback
147168
148169 cpdef py_void SetClientHandler(self , object clientHandler):
149170 if not hasattr (clientHandler, " __class__" ):
150- raise Exception (" Browser.SetClientHandler() failed: __class__ attribute missing" )
171+ raise Exception (" Browser.SetClientHandler() failed: __class__ "
172+ " attribute missing" )
151173 cdef dict methods = {}
152174 cdef py_string key
153175 cdef object method
154176 cdef tuple value
155- for value in inspect.getmembers(clientHandler, predicate = inspect.ismethod):
177+ for value in inspect.getmembers(clientHandler,
178+ predicate = inspect.ismethod):
156179 key = value[0 ]
157180 method = value[1 ]
158181 if key and key[0 ] != ' _' :
@@ -192,8 +215,9 @@ cdef class PyBrowser:
192215 self .GetCefBrowser().get().ClearHistory()
193216
194217 cpdef py_void CloseBrowser(self ):
195- # In cefclient/cefclient_win.cpp there is only ParentWindowWillClose() called.
196- # CloseBrowser() is called only for popups.
218+ # In cefclient/cefclient_win.cpp there is only
219+ # ParentWindowWillClose() called. CloseBrowser() is called
220+ # only for popups.
197221 if self .GetUserData(" __outerWindowHandle" ):
198222 IF CEF_VERSION == 1 :
199223 Debug(" CefBrowser::ParentWindowWillClose()" )
@@ -214,29 +238,33 @@ cdef class PyBrowser:
214238 cpdef py_void CloseDevTools(self ):
215239 self .GetCefBrowser().get().CloseDevTools()
216240
217- cpdef py_void Find(self , int searchId, py_string searchText, py_bool forward,
218- py_bool matchCase, py_bool findNext):
241+ cpdef py_void Find(self , int searchId, py_string searchText,
242+ py_bool forward, py_bool matchCase,
243+ py_bool findNext):
219244 cdef CefString cefSearchText
220245 PyToCefString(searchText, cefSearchText)
221- self .GetCefBrowser().get().Find(searchId, cefSearchText, bool (forward),
222- bool (matchCase), bool (findNext))
246+ self .GetCefBrowser().get().Find(searchId, cefSearchText,
247+ bool (forward), bool (matchCase), bool (findNext))
223248
224249 cpdef PyFrame GetFocusedFrame(self ):
225- assert IsCurrentThread(TID_UI), " Browser.GetFocusedFrame() may only be called on the UI thread"
250+ assert IsCurrentThread(TID_UI), (
251+ " Browser.GetFocusedFrame() may only be called on UI thread" )
226252 return GetPyFrame(self .GetCefBrowser().get().GetFocusedFrame())
227253
228254 cpdef PyFrame GetFrame(self , py_string name):
229- assert IsCurrentThread(TID_UI), " Browser.GetFrame() may only be called on the UI thread"
255+ assert IsCurrentThread(TID_UI), (
256+ " Browser.GetFrame() may only be called on the UI thread" )
230257 cdef CefString cefName
231258 PyToCefString(name, cefName)
232259 return GetPyFrame(self .GetCefBrowser().get().GetFrame(cefName))
233260
234261 cpdef list GetFrameNames(self ):
235- assert IsCurrentThread(TID_UI), " Browser.GetFrameNames() may only be called on the UI thread"
236- cdef c_vector[CefString] cefNames
262+ assert IsCurrentThread(TID_UI), (
263+ " Browser.GetFrameNames() may only be called on the UI thread" )
264+ cdef cpp_vector[CefString] cefNames
237265 self .GetCefBrowser().get().GetFrameNames(cefNames)
238266 cdef list names = []
239- cdef c_vector [CefString].iterator iterator = cefNames.begin()
267+ cdef cpp_vector [CefString].iterator iterator = cefNames.begin()
240268 cdef CefString cefString
241269 while iterator != cefNames.end():
242270 cefString = deref(iterator)
@@ -276,7 +304,8 @@ cdef class PyBrowser:
276304
277305 cpdef double GetZoomLevel(self ) except * :
278306 IF CEF_VERSION == 1 :
279- assert IsCurrentThread(TID_UI), " Browser.GetZoomLevel() may only be called on the UI thread"
307+ assert IsCurrentThread(TID_UI), (
308+ " Browser.GetZoomLevel() may only be called on UI thread" )
280309 cdef double zoomLevel
281310 IF CEF_VERSION == 1 :
282311 zoomLevel = self .GetCefBrowser().get().GetZoomLevel()
@@ -307,7 +336,8 @@ cdef class PyBrowser:
307336 IF CEF_VERSION == 1 :
308337
309338 cpdef py_bool IsPopupVisible(self ):
310- assert IsCurrentThread(TID_UI), " Browser.IsPopupVisible() may only be called on the UI thread"
339+ assert IsCurrentThread(TID_UI), (
340+ " Browser.IsPopupVisible() may only be called on UI thread" )
311341 return self .GetCefBrowser().get().IsPopupVisible()
312342
313343 cpdef py_bool IsWindowRenderingDisabled(self ):
@@ -359,7 +389,8 @@ cdef class PyBrowser:
359389 windowHandle = self .GetWindowHandle()
360390
361391 # Offscreen browser will have an empty window handle.
362- assert windowHandle, " Browser.ToggleFullscreen() failed: no window handle found"
392+ assert windowHandle, (
393+ " Browser.ToggleFullscreen() failed: no window handle found" )
363394
364395 cdef HWND hwnd = < HWND>< int > int (windowHandle)
365396 cdef RECT rect
@@ -369,7 +400,8 @@ cdef class PyBrowser:
369400
370401 # Logic copied from chromium > fullscreen_handler.cc >
371402 # FullscreenHandler::SetFullscreenImpl:
372- # http://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/fullscreen_handler.cc
403+ # http://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/
404+ # fullscreen_handler.cc
373405
374406 cdef py_bool for_metro = False
375407
@@ -389,11 +421,14 @@ cdef class PyBrowser:
389421 removeStyle = WS_CAPTION | WS_THICKFRAME
390422 removeExStyle = (WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE
391423 | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)
392- SetWindowLong(hwnd, GWL_STYLE, self .gwlStyle & ~ (removeStyle))
393- SetWindowLong(hwnd, GWL_EXSTYLE, self .gwlExStyle & ~ (removeExStyle))
424+ SetWindowLong(hwnd, GWL_STYLE,
425+ self .gwlStyle & ~ (removeStyle))
426+ SetWindowLong(hwnd, GWL_EXSTYLE,
427+ self .gwlExStyle & ~ (removeExStyle))
394428
395429 if not for_metro:
396- # MONITOR_DEFAULTTONULL, MONITOR_DEFAULTTOPRIMARY, MONITOR_DEFAULTTONEAREST
430+ # MONITOR_DEFAULTTONULL, MONITOR_DEFAULTTOPRIMARY,
431+ # MONITOR_DEFAULTTONEAREST
397432 monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST)
398433 GetMonitorInfo(monitor, & monitorInfo)
399434 left = monitorInfo.rcMonitor.left
@@ -408,10 +443,90 @@ cdef class PyBrowser:
408443
409444 if not for_metro:
410445 (left, top, right, bottom) = self .windowRect
411- SetWindowPos(hwnd, NULL , int (left), int (top), int (right- left), int (bottom- top),
446+ SetWindowPos(hwnd, NULL ,
447+ int (left), int (top),
448+ int (right- left), int (bottom- top),
412449 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED)
413450
414451 if self .maximized:
415452 SendMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0 )
416453
417454 self .isFullscreen = int (not bool (self .isFullscreen))
455+
456+ # Off-screen rendering.
457+
458+ IF CEF_VERSION == 1 :
459+
460+ cpdef tuple GetSize(self , PaintElementType paintElementType):
461+ assert IsCurrentThread(TID_UI), (
462+ " Browser.GetSize(): this method should only be called "
463+ " on the UI thread" )
464+ cdef int width = 0
465+ cdef int height = 0
466+ cdef cpp_bool ret = self .GetCefBrowser().get().GetSize(
467+ paintElementType, width, height)
468+ if ret:
469+ return (width, height)
470+ else :
471+ return ()
472+
473+ cpdef py_void SetSize(self , PaintElementType paintElementType,
474+ int width, int height):
475+ self .GetCefBrowser().get().SetSize(paintElementType, width, height)
476+
477+ cpdef py_void Invalidate(self , list dirtyRect):
478+ assert len (dirtyRect) == 4 , (
479+ " Browser.Invalidate() failed, dirtyRect is invalid" )
480+ cdef CefRect cefRect = CefRect(
481+ dirtyRect[0 ], dirtyRect[1 ], dirtyRect[2 ], dirtyRect[3 ])
482+ self .GetCefBrowser().get().Invalidate(cefRect)
483+
484+ cpdef PaintBuffer GetImage(self , PaintElementType paintElementType,
485+ int width, int height):
486+ assert IsCurrentThread(TID_UI), (
487+ " Browser.GetImage(): this method should only be called "
488+ " on the UI thread" )
489+
490+ IF UNAME_SYSNAME == " Windows" :
491+ return self .GetImage_Windows(paintElementType, width, height)
492+ ELSE :
493+ return None
494+
495+ IF CEF_VERSION == 1 and UNAME_SYSNAME == " Windows" :
496+
497+ cdef PaintBuffer GetImage_Windows(self ,
498+ PaintElementType paintElementType, int width, int height):
499+ if not self .imageBuffer:
500+ print (" Browser.imageBuffer = malloc(%d )" % (width* height* 4 ))
501+ self .imageBuffer = < void * > malloc(width* height* 4 )
502+ cdef cpp_bool ret = self .GetCefBrowser().get().GetImage(
503+ paintElementType, width, height, self .imageBuffer)
504+ cdef PaintBuffer paintBuffer
505+ if ret:
506+ paintBuffer = CreatePaintBuffer(
507+ self .imageBuffer, width, height)
508+ return paintBuffer
509+ else :
510+ return None
511+
512+ # Sending mouse/key events.
513+
514+ IF CEF_VERSION == 1 :
515+
516+ cpdef py_void SendKeyEvent(self ):
517+ pass
518+
519+ cpdef py_void SendMouseClickEvent(self ):
520+ pass
521+
522+ cpdef py_void SendMouseMoveEvent(self ):
523+ pass
524+
525+ cpdef py_void SendMouseWheelEvent(self ):
526+ pass
527+
528+ cpdef py_void SendFocusEvent(self ):
529+ pass
530+
531+ cpdef py_void SendCaptureLostEvent(self ):
532+ pass
0 commit comments