# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. # License: New BSD License. # Website: http://code.google.com/p/cefpython/ IF CEF_VERSION == 1: # In CEF 1 there are both KT_KEYDOWN and KEYEVENT_KEYDOWN, and # these are different constants, making a bit of confusion. # In CEF 1 KT_ is for SendKeyEvent, KEYEVENT_ is for OnKeyEvent(). # In CEF 3 there are only KEYEVENT_* constants. KEYTYPE_KEYDOWN = cef_types.KT_KEYDOWN KEYTYPE_KEYUP = cef_types.KT_KEYUP KEYTYPE_CHAR = cef_types.KT_CHAR # Both CEF 1 and CEF 3. # cef_mouse_button_type_t, SendMouseClickEvent(). MOUSEBUTTON_LEFT = cef_types.MBT_LEFT MOUSEBUTTON_MIDDLE = cef_types.MBT_MIDDLE MOUSEBUTTON_RIGHT = cef_types.MBT_RIGHT # If you try to keep PyBrowser() objects inside cpp_vector you will # get segmentation faults, as they will be garbage collected. cdef dict g_pyBrowsers = {} IF CEF_VERSION == 3: # Unused function warning in CEF 1. cdef PyBrowser GetPyBrowserById(int browserId): if browserId in g_pyBrowsers: return g_pyBrowsers[browserId] return None cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser): global g_pyBrowsers if cefBrowser == NULL or not cefBrowser.get(): Debug("GetPyBrowser(): returning None") return None cdef PyBrowser pyBrowser cdef int browserId cdef int id browserId = cefBrowser.get().GetIdentifier() if browserId in g_pyBrowsers: return g_pyBrowsers[browserId] for id, pyBrowser in g_pyBrowsers.items(): if not pyBrowser.cefBrowser.get(): Debug("GetPyBrowser(): removing an empty CefBrowser reference, " "browserId=%s" % id) del g_pyBrowsers[id] Debug("GetPyBrowser(): creating new PyBrowser, browserId=%s" % browserId) pyBrowser = PyBrowser() pyBrowser.cefBrowser = cefBrowser g_pyBrowsers[browserId] = pyBrowser # Inherit client callbacks and javascript bindings # from parent browser. # Checking __outerWindowHandle as we should not inherit # client callbacks and javascript bindings if the browser # was created explicitily by calling CreateBrowserSync(). # Popups inherit client callbacks by default. # Popups inherit javascript bindings only when "bindToPopups" # constructor param was set to True. cdef WindowHandle openerHandle cdef dict clientCallbacks cdef JavascriptBindings javascriptBindings cdef PyBrowser tempPyBrowser if pyBrowser.IsPopup() and \ not pyBrowser.GetUserData("__outerWindowHandle"): openerHandle = pyBrowser.GetOpenerWindowHandle() for id, tempPyBrowser in g_pyBrowsers.items(): if tempPyBrowser.GetWindowHandle() == openerHandle: clientCallbacks = tempPyBrowser.GetClientCallbacksDict() if clientCallbacks: pyBrowser.SetClientCallbacksDict(clientCallbacks) javascriptBindings = tempPyBrowser.GetJavascriptBindings() if javascriptBindings: if javascriptBindings.GetBindToPopups(): pyBrowser.SetJavascriptBindings(javascriptBindings) return pyBrowser IF CEF_VERSION == 3: # Unused function warning in CEF 1. cdef void RemovePyBrowser(int browserId) except *: # Called from LifespanHandler_OnBeforeClose(). # TODO: call this function also in CEF 1. global g_pyBrowsers if browserId in g_pyBrowsers: if len(g_pyBrowsers) == 1: # This is the last browser remaining. if g_sharedRequestContext.get(): # A similar release is done in Shutdown and CloseBrowser. Debug("RemovePyBrowser: releasing shared request context") g_sharedRequestContext.Assign(NULL) Debug("del g_pyBrowsers[%s]" % browserId) del g_pyBrowsers[browserId] else: Debug("RemovePyBrowser() FAILED: browser not found, id = %s" \ % browserId) cpdef PyBrowser GetBrowserByWindowHandle(WindowHandle windowHandle): cdef PyBrowser pyBrowser for browserId in g_pyBrowsers: pyBrowser = g_pyBrowsers[browserId] if (pyBrowser.GetWindowHandle() == windowHandle or pyBrowser.GetUserData("__outerWindowHandle") == long(windowHandle)): return pyBrowser return None cdef public void PyBrowser_ShowDevTools(CefRefPtr[CefBrowser] cefBrowser ) except * with gil: # Called from ClientHandler::OnContextMenuCommand cdef PyBrowser pyBrowser try: pyBrowser = GetPyBrowser(cefBrowser) pyBrowser.ShowDevTools() except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) # ----------------------------------------------------------------------------- cdef class PyBrowser: cdef CefRefPtr[CefBrowser] cefBrowser cdef public dict clientCallbacks cdef public list allowedClientCallbacks cdef public JavascriptBindings javascriptBindings cdef public dict userData # Properties used by ToggleFullscreen(). cdef public int isFullscreen cdef public int maximized cdef public int gwlStyle cdef public int gwlExStyle cdef public tuple windowRect # C-level attributes are initialized to 0 automatically. cdef void* imageBuffer cdef CefRefPtr[CefBrowser] GetCefBrowser(self) except *: if self.cefBrowser != NULL and self.cefBrowser.get(): return self.cefBrowser raise Exception("PyBrowser.GetCefBrowser() failed: CefBrowser " "was destroyed") IF CEF_VERSION == 3: cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(self) except *: cdef CefRefPtr[CefBrowserHost] cefBrowserHost = ( self.GetCefBrowser().get().GetHost()) if cefBrowserHost != NULL and cefBrowserHost.get(): return cefBrowserHost raise Exception("PyBrowser.GetCefBrowserHost() failed: this " "method can only be called in the browser " "process.") def __init__(self): self.clientCallbacks = {} self.allowedClientCallbacks = [] self.userData = {} def __dealloc__(self): if self.imageBuffer: free(self.imageBuffer) cpdef py_void SetClientCallback(self, py_string name, object callback): IF CEF_VERSION == 1: self.SetClientCallback_CEF1(name, callback) ELIF CEF_VERSION == 3: self.SetClientCallback_CEF3(name, callback) # ------------------------------------------------------------------------- # CEF 1 # ------------------------------------------------------------------------- cpdef py_void SetClientCallback_CEF1(self, py_string name, object callback): if not self.allowedClientCallbacks: # CefLoadHandler. self.allowedClientCallbacks += ["OnLoadEnd", "OnLoadError", "OnLoadStart"] # CefKeyboardHandler. self.allowedClientCallbacks += ["OnKeyEvent"] # CefV8ContextHandler. self.allowedClientCallbacks += ["OnContextCreated", "OnContextReleased" ,"OnUncaughtException"] # CefRequestHandler. self.allowedClientCallbacks += ["OnBeforeBrowse", "OnBeforeResourceLoad", "OnResourceRedirect", "OnResourceResponse", "OnProtocolExecution", "GetDownloadHandler", "GetAuthCredentials", "GetCookieManager"] # CefDisplayHandler. self.allowedClientCallbacks += ["OnAddressChange", "OnConsoleMessage", "OnContentsSizeChange", "OnNavStateChange", "OnStatusMessage", "OnTitleChange", "OnTooltip"] # LifespanHandler. self.allowedClientCallbacks += ["DoClose", "OnAfterCreated", "OnBeforeClose", "RunModal"] # RenderHandler self.allowedClientCallbacks += ["GetViewRect", "GetScreenRect", "GetScreenPoint", "OnPopupShow", "OnPopupSize", "OnPaint", "OnCursorChange"] # DragHandler self.allowedClientCallbacks += ["OnDragStart", "OnDragEnter"] if name not in self.allowedClientCallbacks: raise Exception("Browser.SetClientCallback() failed: unknown " "callback: %s" % name) self.clientCallbacks[name] = callback # ------------------------------------------------------------------------- # CEF 3 # ------------------------------------------------------------------------- cpdef py_void SetClientCallback_CEF3(self, py_string name, object callback): if not self.allowedClientCallbacks: # DisplayHandler self.allowedClientCallbacks += [ "OnAddressChange", "OnTitleChange", "OnTooltip", "OnStatusMessage", "OnConsoleMessage"] # KeyboardHandler self.allowedClientCallbacks += ["OnPreKeyEvent", "OnKeyEvent"]; # RequestHandler # NOTE: OnCertificateError and OnBeforePluginLoad are not # included as they must be set using # cefpython.SetGlobalClientCallback(). self.allowedClientCallbacks += ["OnBeforeResourceLoad", "OnResourceRedirect", "GetAuthCredentials", "OnQuotaRequest", "OnProtocolExecution", "GetResourceHandler", "OnBeforeBrowse", "OnRendererProcessTerminated", "OnPluginCrashed"] # RequestContextHandler self.allowedClientCallbacks += ["GetCookieManager"] # LoadHandler self.allowedClientCallbacks += ["OnLoadingStateChange", "OnLoadStart", "OnLoadEnd", "OnLoadError"] # LifespanHandler # NOTE: OnAfterCreated not included as it must be set using # cefpython.SetGlobalClientCallback(). self.allowedClientCallbacks += ["OnBeforePopup", "RunModal", "DoClose", "OnBeforeClose"] # RenderHandler self.allowedClientCallbacks += ["GetRootScreenRect", "GetViewRect", "GetScreenPoint", "GetScreenInfo", "OnPopupShow", "OnPopupSize", "OnPaint", "OnCursorChange", "OnScrollOffsetChanged"] # JavascriptDialogHandler self.allowedClientCallbacks += ["OnJavascriptDialog", "OnBeforeUnloadJavascriptDialog", "OnResetJavascriptDialogState", "OnJavascriptDialogClosed"] if name not in self.allowedClientCallbacks: raise Exception("Browser.SetClientCallback() failed: unknown " "callback: %s" % name) self.clientCallbacks[name] = callback cpdef py_void SetClientHandler(self, object clientHandler): if not hasattr(clientHandler, "__class__"): raise Exception("Browser.SetClientHandler() failed: __class__ " "attribute missing") cdef dict methods = {} cdef py_string key cdef object method cdef tuple value for value in inspect.getmembers(clientHandler, predicate=inspect.ismethod): key = value[0] method = value[1] if key and key[0] != '_': self.SetClientCallback(key, method) cpdef object GetClientCallback(self, py_string name): if name in self.clientCallbacks: return self.clientCallbacks[name] cpdef py_void SetClientCallbacksDict(self, dict clientCallbacks): self.clientCallbacks = clientCallbacks cpdef dict GetClientCallbacksDict(self): return self.clientCallbacks cpdef py_void SetJavascriptBindings(self, JavascriptBindings bindings): self.javascriptBindings = bindings IF CEF_VERSION == 1: if self.GetUserData("__v8ContextCreated"): Debug("Browser.SetJavascriptBindings(): v8 context already" "created, calling Rebind()") self.javascriptBindings.Rebind() ELIF CEF_VERSION == 3: self.javascriptBindings.Rebind() cpdef JavascriptBindings GetJavascriptBindings(self): return self.javascriptBindings # -------------- # CEF API. # -------------- cpdef py_bool CanGoBack(self): return self.GetCefBrowser().get().CanGoBack() cpdef py_bool CanGoForward(self): return self.GetCefBrowser().get().CanGoForward() IF CEF_VERSION == 1: cpdef object ClearHistory(self): self.GetCefBrowser().get().ClearHistory() cpdef py_void ParentWindowWillClose(self): IF CEF_VERSION == 1: self.GetCefBrowser().get().ParentWindowWillClose() ELIF CEF_VERSION == 3: self.GetCefBrowserHost().get().ParentWindowWillClose() cpdef py_void CloseBrowser(self, py_bool forceClose=False): IF CEF_VERSION == 1: Debug("CefBrowser::CloseBrowser(%s)" % forceClose) self.GetCefBrowser().get().CloseBrowser(bool(forceClose)) ELIF CEF_VERSION == 3: # ParentWindowWillClose() should be called by user when # implementing LifespanHandler::DoClose(). # | Debug("CefBrowser::ParentWindowWillClose()") # | self.GetCefBrowserHost().get().ParentWindowWillClose() if len(g_pyBrowsers) == 1: # This is the last browser remaining. if g_sharedRequestContext.get(): # A similar release is done in Shutdown # and RemovePyBrowser. Debug("CloseBrowser: releasing shared request context") g_sharedRequestContext.Assign(NULL) Debug("CefBrowser::CloseBrowser(%s)" % forceClose) self.GetCefBrowserHost().get().CloseBrowser(bool(forceClose)) IF CEF_VERSION == 1: cpdef py_void CloseDevTools(self): self.GetCefBrowser().get().CloseDevTools() def ExecuteFunction(self, *args): self.GetMainFrame().ExecuteFunction(*args) cpdef py_void ExecuteJavascript(self, py_string jsCode, py_string scriptUrl="", int startLine=0): self.GetMainFrame().ExecuteJavascript(jsCode, scriptUrl, startLine) cpdef py_void Find(self, int searchId, py_string searchText, py_bool forward, py_bool matchCase, py_bool findNext): cdef CefString cefSearchText PyToCefString(searchText, cefSearchText) IF CEF_VERSION == 3: self.GetCefBrowserHost().get().Find(searchId, cefSearchText, bool(forward), bool(matchCase), bool(findNext)) ELIF CEF_VERSION == 1: self.GetCefBrowser().get().Find(searchId, cefSearchText, bool(forward), bool(matchCase), bool(findNext)) cpdef PyFrame GetFocusedFrame(self): assert IsThread(TID_UI), ( "Browser.GetFocusedFrame() may only be called on UI thread") return GetPyFrame(self.GetCefBrowser().get().GetFocusedFrame()) cpdef PyFrame GetFrame(self, py_string name): assert IsThread(TID_UI), ( "Browser.GetFrame() may only be called on the UI thread") cdef CefString cefName PyToCefString(name, cefName) return GetPyFrame(self.GetCefBrowser().get().GetFrame(cefName)) IF CEF_VERSION == 3: cpdef object GetFrameByIdentifier(self, object identifier): return GetPyFrame(self.GetCefBrowser().get().GetFrame( long(identifier))) cpdef list GetFrameNames(self): assert IsThread(TID_UI), ( "Browser.GetFrameNames() may only be called on the UI thread") cdef cpp_vector[CefString] cefNames self.GetCefBrowser().get().GetFrameNames(cefNames) cdef list names = [] cdef cpp_vector[CefString].iterator iterator = cefNames.begin() cdef CefString cefString while iterator != cefNames.end(): cefString = deref(iterator) names.append(CefToPyString(cefString)) preinc(iterator) return names cpdef list GetFrames(self): cdef list names = self.GetFrameNames() cdef PyFrame frame cdef list frames = [] for name in names: frame = self.GetFrame(name) frames.append(frame) return frames cpdef int GetIdentifier(self) except *: return self.GetCefBrowser().get().GetIdentifier() cpdef PyFrame GetMainFrame(self): return GetPyFrame(self.GetCefBrowser().get().GetMainFrame()) cpdef WindowHandle GetOpenerWindowHandle(self) except *: cdef WindowHandle hwnd IF CEF_VERSION == 1: hwnd = self.GetCefBrowser().get().GetOpenerWindowHandle() ELIF CEF_VERSION == 3: hwnd = self.GetCefBrowserHost().get().GetOpenerWindowHandle() return hwnd cpdef WindowHandle GetOuterWindowHandle(self) except *: if self.GetUserData("__outerWindowHandle"): return self.GetUserData("__outerWindowHandle") else: return self.GetWindowHandle() cpdef py_string GetUrl(self): return self.GetMainFrame().GetUrl() cpdef object GetUserData(self, object key): if key in self.userData: return self.userData[key] return None cpdef WindowHandle GetWindowHandle(self) except *: cdef WindowHandle hwnd IF CEF_VERSION == 1: hwnd = self.GetCefBrowser().get().GetWindowHandle() ELIF CEF_VERSION == 3: hwnd = self.GetCefBrowserHost().get().GetWindowHandle() return hwnd cpdef double GetZoomLevel(self) except *: IF CEF_VERSION == 1: assert IsThread(TID_UI), ( "Browser.GetZoomLevel() may only be called on UI thread") cdef double zoomLevel IF CEF_VERSION == 1: zoomLevel = self.GetCefBrowser().get().GetZoomLevel() ELIF CEF_VERSION == 3: zoomLevel = self.GetCefBrowserHost().get().GetZoomLevel() return zoomLevel cpdef py_void GoBack(self): self.GetCefBrowser().get().GoBack() cpdef py_void GoForward(self): self.GetCefBrowser().get().GoForward() cpdef py_bool HasDocument(self): return self.GetCefBrowser().get().HasDocument() IF CEF_VERSION == 1: cpdef py_void HidePopup(self): self.GetCefBrowser().get().HidePopup() cpdef py_bool IsFullscreen(self): return bool(self.isFullscreen) cpdef py_bool IsPopup(self): return self.GetCefBrowser().get().IsPopup() IF CEF_VERSION == 1: cpdef py_bool IsPopupVisible(self): assert IsThread(TID_UI), ( "Browser.IsPopupVisible() may only be called on UI thread") return self.GetCefBrowser().get().IsPopupVisible() cpdef py_bool IsWindowRenderingDisabled(self): IF CEF_VERSION == 1: return self.GetCefBrowser().get().IsWindowRenderingDisabled() ELIF CEF_VERSION == 3: return self.GetCefBrowserHost().get().IsWindowRenderingDisabled() cpdef py_string LoadUrl(self, py_string url): self.GetMainFrame().LoadUrl(url) cpdef py_void Navigate(self, py_string url): self.LoadUrl(url) IF CEF_VERSION == 3: cpdef py_void Print(self): self.GetCefBrowserHost().get().Print() cpdef py_void Reload(self): self.GetCefBrowser().get().Reload() cpdef py_void ReloadIgnoreCache(self): self.GetCefBrowser().get().ReloadIgnoreCache() cpdef py_void SetFocus(self, enable): IF CEF_VERSION == 1: self.GetCefBrowser().get().SetFocus(bool(enable)) ELIF CEF_VERSION == 3: self.GetCefBrowserHost().get().SetFocus(bool(enable)) cpdef py_void SetUserData(self, object key, object value): self.userData[key] = value cpdef py_void SetZoomLevel(self, double zoomLevel): IF CEF_VERSION == 1: self.GetCefBrowser().get().SetZoomLevel(zoomLevel) ELIF CEF_VERSION == 3: self.GetCefBrowserHost().get().SetZoomLevel(zoomLevel) cpdef py_void ShowDevTools(self): cdef CefString cefUrl = self.GetCefBrowserHost().get().GetDevToolsURL(\ True) cdef py_string url = CefToPyString(cefUrl) # Example url returned: # | http://localhost:54008/devtools/devtools.html?ws=localhost:54008 # | /devtools/page/1538ed984a2a4a90e5ed941c7d142a12 # Let's replace "localhost" with "127.0.0.1", using the ip address # which is more reliable. url = url.replace("localhost:", "127.0.0.1:") jsCode = ("window.open('%s');" % url) self.GetMainFrame().ExecuteJavascript(jsCode) cpdef py_void StopLoad(self): self.GetCefBrowser().get().StopLoad() cpdef py_void StopFinding(self, py_bool clearSelection): IF CEF_VERSION == 3: self.GetCefBrowserHost().get().StopFinding(bool(clearSelection)) ELIF CEF_VERSION == 1: self.GetCefBrowser().get().StopFinding(bool(clearSelection)) cpdef py_void ToggleFullscreen(self): IF UNAME_SYSNAME == "Windows": self.ToggleFullscreen_Windows() IF UNAME_SYSNAME == "Windows": cpdef py_void ToggleFullscreen_Windows(self): cdef WindowHandle windowHandle if self.GetUserData("__outerWindowHandle"): windowHandle = self.GetUserData("__outerWindowHandle") else: windowHandle = self.GetWindowHandle() # Offscreen browser will have an empty window handle. assert windowHandle, ( "Browser.ToggleFullscreen() failed: no window handle " "found") cdef HWND hwnd = int(windowHandle) cdef RECT rect cdef HMONITOR monitor cdef MONITORINFO monitorInfo monitorInfo.cbSize = sizeof(monitorInfo) # Logic copied from chromium > fullscreen_handler.cc > # FullscreenHandler::SetFullscreenImpl: # http://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/ # fullscreen_handler.cc cdef py_bool for_metro = False if not self.isFullscreen: self.maximized = IsZoomed(hwnd) if self.maximized: SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) self.gwlStyle = GetWindowLong(hwnd, GWL_STYLE) self.gwlExStyle = GetWindowLong(hwnd, GWL_EXSTYLE) GetWindowRect(hwnd, &rect) self.windowRect = (rect.left, rect.top, rect.right, rect.bottom) cdef int removeStyle, removeExStyle cdef int left, top, right, bottom if not self.isFullscreen: removeStyle = WS_CAPTION | WS_THICKFRAME removeExStyle = (WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) SetWindowLong(hwnd, GWL_STYLE, self.gwlStyle & ~(removeStyle)) SetWindowLong(hwnd, GWL_EXSTYLE, self.gwlExStyle & ~(removeExStyle)) if not for_metro: # MONITOR_DEFAULTTONULL, MONITOR_DEFAULTTOPRIMARY, # MONITOR_DEFAULTTONEAREST monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) GetMonitorInfo(monitor, &monitorInfo) left = monitorInfo.rcMonitor.left top = monitorInfo.rcMonitor.top right = monitorInfo.rcMonitor.right bottom = monitorInfo.rcMonitor.bottom SetWindowPos(hwnd, NULL, left, top, right-left, bottom-top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED) else: SetWindowLong(hwnd, GWL_STYLE, int(self.gwlStyle)) SetWindowLong(hwnd, GWL_EXSTYLE, int(self.gwlExStyle)) if not for_metro: (left, top, right, bottom) = self.windowRect SetWindowPos(hwnd, NULL, int(left), int(top), int(right-left), int(bottom-top), SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED) if self.maximized: SendMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0) self.isFullscreen = int(not bool(self.isFullscreen)) # Off-screen rendering. IF CEF_VERSION == 1: cpdef tuple GetSize(self, PaintElementType paintElementType): assert IsThread(TID_UI), ( "Browser.GetSize(): this method should only be called " "on the UI thread") cdef int width = 0 cdef int height = 0 cdef cpp_bool ret = self.GetCefBrowser().get().GetSize( paintElementType, width, height) if ret: return (width, height) else: return (0, 0) cpdef py_void SetSize(self, PaintElementType paintElementType, int width, int height): self.GetCefBrowser().get().SetSize(paintElementType, width, height) cpdef py_void Invalidate(self, list dirtyRect): assert len(dirtyRect) == 4, ( "Browser.Invalidate() failed, dirtyRect is invalid") cdef CefRect cefRect = CefRect( dirtyRect[0], dirtyRect[1], dirtyRect[2], dirtyRect[3]) self.GetCefBrowser().get().Invalidate(cefRect) IF CEF_VERSION == 1 and UNAME_SYSNAME == "Windows": cpdef PaintBuffer GetImage(self, PaintElementType paintElementType, int width, int height): assert IsThread(TID_UI), ( "Browser.GetImage(): this method should only be called " "on the UI thread") IF UNAME_SYSNAME == "Windows": return self.GetImage_Windows(paintElementType, width, height) ELSE: return None cdef PaintBuffer GetImage_Windows(self, PaintElementType paintElementType, int width, int height): if not self.imageBuffer: self.imageBuffer = malloc(width*height*4) cdef cpp_bool ret = self.GetCefBrowser().get().GetImage( paintElementType, width, height, self.imageBuffer) cdef PaintBuffer paintBuffer if ret: paintBuffer = CreatePaintBuffer( self.imageBuffer, width, height) return paintBuffer else: return None # Sending mouse/key events. IF CEF_VERSION == 1: cpdef py_void SendKeyEvent(self, cef_types.cef_key_type_t keyType, tuple keyInfo, int modifiers): cdef CefKeyInfo cefKeyInfo IF UNAME_SYSNAME == "Windows": assert len(keyInfo) == 3, "Invalid keyInfo param" cefKeyInfo.key = keyInfo[0] cefKeyInfo.sysChar = keyInfo[1] cefKeyInfo.imeChar = keyInfo[2] ELIF UNAME_SYSNAME == "Darwin": cefKeyInfo.keyCode = keyInfo[0] cefKeyInfo.character = keyInfo[1] cefKeyInfo.characterNoModifiers = keyInfo[2] ELIF UNAME_SYSNAME == "Linux": cefKeyInfo.key = keyInfo[0] ELSE: raise Exception("Invalid UNAME_SYSNAME") self.GetCefBrowser().get().SendKeyEvent(keyType, cefKeyInfo, modifiers) cpdef py_void SendMouseClickEvent(self, int x, int y, cef_types.cef_mouse_button_type_t mouseButtonType, py_bool mouseUp, int clickCount, int modifiers=0): self.GetCefBrowser().get().SendMouseClickEvent(x, y, mouseButtonType, bool(mouseUp), clickCount) cpdef py_void SendMouseMoveEvent(self, int x, int y, py_bool mouseLeave, int modifiers=0): self.GetCefBrowser().get().SendMouseMoveEvent(x, y, bool(mouseLeave)) cpdef py_void SendMouseWheelEvent(self, int x, int y, int deltaX, int deltaY, int modifiers=0): self.GetCefBrowser().get().SendMouseWheelEvent(x, y, deltaX, deltaY) cpdef py_void SendFocusEvent(self, py_bool setFocus): self.GetCefBrowser().get().SendFocusEvent(bool(setFocus)) cpdef py_void SendCaptureLostEvent(self): self.GetCefBrowser().get().SendCaptureLostEvent() ELIF CEF_VERSION == 3: cpdef py_void SendKeyEvent(self, dict pyEvent): cdef CefKeyEvent cefEvent if "type" in pyEvent: cefEvent.type = int(pyEvent["type"]) if "modifiers" in pyEvent: cefEvent.modifiers = long(pyEvent["modifiers"]) if ("windows_key_code" in pyEvent) and UNAME_SYSNAME == "Windows": cefEvent.windows_key_code = int(pyEvent["windows_key_code"]) if "native_key_code" in pyEvent: cefEvent.native_key_code = int(pyEvent["native_key_code"]) if "is_system_key" in pyEvent: cefEvent.is_system_key = bool(pyEvent["is_system_key"]) if "character" in pyEvent: cefEvent.character = int(pyEvent["character"]) if "unmodified_character" in pyEvent: cefEvent.unmodified_character = \ int(pyEvent["unmodified_character"]) if "focus_on_editable_field" in pyEvent: cefEvent.focus_on_editable_field = \ bool(pyEvent["focus_on_editable_field"]) self.GetCefBrowserHost().get().SendKeyEvent(cefEvent) cpdef py_void SendMouseClickEvent(self, int x, int y, cef_types.cef_mouse_button_type_t mouseButtonType, py_bool mouseUp, int clickCount, int modifiers=0): cdef CefMouseEvent mouseEvent mouseEvent.x = x mouseEvent.y = y mouseEvent.modifiers = modifiers self.GetCefBrowserHost().get().SendMouseClickEvent(mouseEvent, mouseButtonType, bool(mouseUp), clickCount) cpdef py_void SendMouseMoveEvent(self, int x, int y, py_bool mouseLeave, int modifiers=0): cdef CefMouseEvent mouseEvent mouseEvent.x = x mouseEvent.y = y mouseEvent.modifiers = modifiers self.GetCefBrowserHost().get().SendMouseMoveEvent(mouseEvent, bool(mouseLeave)) cpdef py_void SendMouseWheelEvent(self, int x, int y, int deltaX, int deltaY, int modifiers=0): cdef CefMouseEvent mouseEvent mouseEvent.x = x mouseEvent.y = y mouseEvent.modifiers = modifiers self.GetCefBrowserHost().get().SendMouseWheelEvent(mouseEvent, deltaX, deltaY) cpdef py_void SendFocusEvent(self, py_bool setFocus): self.GetCefBrowserHost().get().SendFocusEvent(bool(setFocus)) cpdef py_void SendCaptureLostEvent(self): self.GetCefBrowserHost().get().SendCaptureLostEvent() # ENDIF CEF_VERSION == 3 / Sending mouse/key events. IF CEF_VERSION == 3: cpdef py_void StartDownload(self, py_string url): self.GetCefBrowserHost().get().StartDownload(PyToCefStringValue( url)) cpdef py_void SetMouseCursorChangeDisabled(self, py_bool disabled): self.GetCefBrowserHost().get().SetMouseCursorChangeDisabled( bool(disabled)) cpdef py_bool IsMouseCursorChangeDisabled(self): return self.GetCefBrowserHost().get().IsMouseCursorChangeDisabled() cpdef py_void WasResized(self): self.GetCefBrowserHost().get().WasResized() cpdef py_void WasHidden(self, py_bool hidden): self.GetCefBrowserHost().get().WasHidden(bool(hidden)) cpdef py_void NotifyScreenInfoChanged(self): self.GetCefBrowserHost().get().NotifyScreenInfoChanged() # virtual CefTextInputContext GetNSTextInputContext() =0; # virtual void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent) =0; # virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) =0; cdef void SendProcessMessage(self, cef_process_id_t targetProcess, object frameId, py_string messageName, list pyArguments ) except *: cdef CefRefPtr[CefProcessMessage] message = \ CefProcessMessage_Create(PyToCefStringValue(messageName)) # This does not work, no idea why, the CEF implementation # seems not to allow it, both Assign() and swap() do not work: # | message.get().GetArgumentList().Assign(arguments.get()) # | message.get().GetArgumentList().swap(arguments) cdef CefRefPtr[CefListValue] messageArguments = \ message.get().GetArgumentList() PyListToExistingCefListValue(self.GetIdentifier(), frameId, pyArguments, messageArguments) Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( messageName, message.get().GetArgumentList().get().GetSize())) cdef cpp_bool success = \ self.GetCefBrowser().get().SendProcessMessage( targetProcess, message) if not success: raise Exception("Browser.SendProcessMessage() failed: "\ "messageName=%s" % messageName)