# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved.
# License: New BSD License.
# Website: http://code.google.com/p/cefpython/
include "cefpython.pyx"
cimport cef_types
IF UNAME_SYSNAME == "Linux":
cimport x11
# 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 = {}
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():
# noinspection PyUnresolvedReferences
Debug("GetPyBrowser(): returning None")
return None
cdef PyBrowser pyBrowser
cdef int browserId
cdef int identifier
browserId = cefBrowser.get().GetIdentifier()
if browserId in g_pyBrowsers:
return g_pyBrowsers[browserId]
for identifier, pyBrowser in g_pyBrowsers.items():
if not pyBrowser.cefBrowser.get():
# noinspection PyUnresolvedReferences
Debug("GetPyBrowser(): removing an empty CefBrowser reference, "
"browserId=%s" % identifier)
del g_pyBrowsers[identifier]
# noinspection PyUnresolvedReferences
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 identifier, 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
cdef void RemovePyBrowser(int browserId) except *:
# Called from LifespanHandler_OnBeforeClose().
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.
# noinspection PyUnresolvedReferences
Debug("RemovePyBrowser: releasing shared request context")
g_sharedRequestContext.Assign(NULL)
# noinspection PyUnresolvedReferences
Debug("del g_pyBrowsers[%s]" % browserId)
del g_pyBrowsers[browserId]
else:
# noinspection PyUnresolvedReferences
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")
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 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",
"DoClose", "OnBeforeClose"]
# RenderHandler
self.allowedClientCallbacks += ["GetRootScreenRect",
"GetViewRect", "GetScreenPoint", "GetScreenInfo",
"GetScreenRect",
"OnPopupShow", "OnPopupSize", "OnPaint", "OnCursorChange",
"OnScrollOffsetChanged",
"StartDragging", "UpdateDragCursor"]
# JavascriptDialogHandler
self.allowedClientCallbacks += ["OnJavascriptDialog",
"OnBeforeUnloadJavascriptDialog",
"OnResetJavascriptDialogState",
"OnJavascriptDialogClosed"]
# FocusHandler
self.allowedClientCallbacks += ["OnTakeFocus", "OnSetFocus",
"OnGotFocus"]
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
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()
cpdef py_void ParentWindowWillClose(self):
# Method removed in upstream CEF, keeping for BC
pass
cpdef py_void CloseBrowser(self, py_bool forceClose=False):
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))
cpdef py_void CloseDevTools(self):
self.GetCefBrowserHost().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)
self.GetCefBrowserHost().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))
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
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
hwnd = self.GetCefBrowserHost().get().GetWindowHandle()
return hwnd
cpdef double GetZoomLevel(self) except *:
cdef double zoomLevel
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()
cpdef py_bool IsFullscreen(self):
return bool(self.isFullscreen)
cpdef py_bool IsPopup(self):
return self.GetCefBrowser().get().IsPopup()
cpdef py_bool IsWindowRenderingDisabled(self):
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)
cpdef py_void NotifyMoveOrResizeStarted(self):
self.GetCefBrowserHost().get().NotifyMoveOrResizeStarted()
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 SetBounds(self, int x, int y, int width, int height):
if platform.system() == "Linux":
x11.SetX11WindowBounds(self.GetCefBrowser(), x, y, width, height)
else:
raise Exception("SetBounds() not impplemented on this platform")
cpdef py_void SetFocus(self, enable):
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):
self.GetCefBrowserHost().get().SetZoomLevel(zoomLevel)
cpdef py_void ShowDevTools(self):
cdef CefWindowInfo windowInfo
cdef CefRefPtr[ClientHandler] clientHandler =\
new ClientHandler()
cdef CefBrowserSettings settings
cdef CefPoint inspect_element_at
self.GetCefBrowserHost().get().ShowDevTools(
windowInfo, clientHandler, settings,
inspect_element_at)
cpdef py_void StopLoad(self):
self.GetCefBrowser().get().StopLoad()
cpdef py_void StopFinding(self, py_bool clearSelection):
self.GetCefBrowserHost().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
# noinspection PyUnresolvedReferences
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
# noinspection PyUnresolvedReferences
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))
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"])
# Always set CefKeyEvent.windows_key_code in SendKeyEvent, even on
# Linux. When sending key event for 'backspace' on Linux and setting
# "native_key_code", "character", "unmodified_character" it doesn't
# work. It starts working after "windows_key_code" is also sent.
if "windows_key_code" in pyEvent:
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 = int(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 = \
int(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()
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_bool TryCloseBrowser(self):
return self.GetCefBrowserHost().get().TryCloseBrowser()
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()
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)
# -------------------------------------------------------------------------
# OSR drag & drop
# -------------------------------------------------------------------------
cpdef py_void DragTargetDragEnter(self, DragData drag_data, int x, int y,
long long allowed_ops):
cdef CefMouseEvent mouse_event
mouse_event.x = x
mouse_event.y = y
self.GetCefBrowserHost().get().DragTargetDragEnter(
drag_data.cef_drag_data, mouse_event,
allowed_ops)
cpdef py_void DragTargetDragOver(self, int x, int y, long long allowed_ops):
cdef CefMouseEvent mouse_event
mouse_event.x = x
mouse_event.y = y
self.GetCefBrowserHost().get().DragTargetDragOver(
mouse_event, allowed_ops)
cpdef py_void DragTargetDragLeave(self):
self.GetCefBrowserHost().get().DragTargetDragLeave()
cpdef py_void DragTargetDrop(self, int x, int y):
cdef CefMouseEvent mouse_event
mouse_event.x = x
mouse_event.y = y
self.GetCefBrowserHost().get().DragTargetDrop(mouse_event)
cpdef py_void DragSourceEndedAt(self, int x, int y, long long operation):
self.GetCefBrowserHost().get().DragSourceEndedAt(
x, y, operation)
cpdef py_void DragSourceSystemDragEnded(self):
self.GetCefBrowserHost().get().DragSourceSystemDragEnded()