forked from cztomczak/cefpython
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcontext_menu_handler.pyx
More file actions
141 lines (117 loc) · 5.1 KB
/
Copy pathcontext_menu_handler.pyx
File metadata and controls
141 lines (117 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# Copyright (c) 2016 CEF Python, see the Authors file.
# All rights reserved. Licensed under BSD 3-clause license.
# Project website: https://github.com/cztomczak/cefpython
include "../cefpython.pyx"
include "../browser.pyx"
cimport cef_types
from cef_types cimport TID_UI, cef_event_flags_t
# ---------------------------------------------------------------------------
# Minimal CefMenuModel and CefRunContextMenuCallback declarations.
# cef_context_menu_handler.h includes cef_menu_model.h so one block suffices.
# ---------------------------------------------------------------------------
cdef extern from "include/cef_context_menu_handler.h":
# CefMenuModel methods (subset used by RunContextMenu)
cdef cppclass CefMenuModel:
size_t GetCount() noexcept
int GetCommandIdAt(size_t index) noexcept
CefString GetLabelAt(size_t index) noexcept
int GetTypeAt(size_t index) noexcept # returns cef_menu_item_type_t as int
cpp_bool IsEnabledAt(size_t index) noexcept
cdef cppclass CefRunContextMenuCallback:
void Continue(int command_id, cef_event_flags_t event_flags) noexcept
void Cancel() noexcept
# ---------------------------------------------------------------------------
# Python wrapper: RunContextMenuCallback
# ---------------------------------------------------------------------------
cdef class RunContextMenuCallback:
cdef CefRefPtr[CefRunContextMenuCallback] _cb
cdef bint _done
def __init__(self):
self._done = False
def Continue(self, int command_id, int event_flags=0):
if not self._done:
self._done = True
self._cb.get().Continue(command_id,
<cef_event_flags_t>event_flags)
def Cancel(self):
if not self._done:
self._done = True
self._cb.get().Cancel()
cdef RunContextMenuCallback _MakeRunContextMenuCallback(
CefRefPtr[CefRunContextMenuCallback] cb):
cdef RunContextMenuCallback obj = RunContextMenuCallback.__new__(
RunContextMenuCallback)
obj._cb = cb
obj._done = False
return obj
# ---------------------------------------------------------------------------
# Python wrapper: MenuModel (read-only snapshot for RunContextMenu).
# ---------------------------------------------------------------------------
cdef class MenuModel:
# Snapshot taken at callback time so Python code can iterate freely
# without worrying about CEF model lifetime.
cdef list _items # list of dicts
def __init__(self):
self._items = []
def GetCount(self):
return len(self._items)
def GetTypeAt(self, int index):
return self._items[index]['type']
def GetLabelAt(self, int index):
return self._items[index]['label']
def GetCommandIdAt(self, int index):
return self._items[index]['command_id']
def IsEnabledAt(self, int index):
return self._items[index]['enabled']
cdef MenuModel _SnapshotMenuModel(CefRefPtr[CefMenuModel] cef_model):
cdef MenuModel obj = MenuModel.__new__(MenuModel)
cdef size_t count = cef_model.get().GetCount()
cdef size_t i
obj._items = []
for i in range(count):
item_type = int(cef_model.get().GetTypeAt(i))
label = CefToPyString(cef_model.get().GetLabelAt(i))
command_id = cef_model.get().GetCommandIdAt(i)
enabled = bool(cef_model.get().IsEnabledAt(i))
obj._items.append({
'type': item_type,
'label': label,
'command_id': command_id,
'enabled': enabled,
})
return obj
# ---------------------------------------------------------------------------
# CEF menu item type constants exposed to Python (from cef_types.h).
# ---------------------------------------------------------------------------
MENUITEMTYPE_NONE = 0
MENUITEMTYPE_COMMAND = 1
MENUITEMTYPE_CHECK = 2
MENUITEMTYPE_RADIO = 3
MENUITEMTYPE_SEPARATOR = 4
MENUITEMTYPE_SUBMENU = 5
# ---------------------------------------------------------------------------
# C-level dispatch called from context_menu_handler.cpp
# ---------------------------------------------------------------------------
cdef public int ContextMenuHandler_RunContextMenu(
CefRefPtr[CefBrowser] cef_browser,
CefRefPtr[CefMenuModel] cef_model,
CefRefPtr[CefRunContextMenuCallback] cef_callback
) noexcept with gil:
cdef PyBrowser browser
cdef py_bool ret
try:
assert IsThread(TID_UI), "Must be called on the UI thread"
browser = GetPyBrowser(cef_browser, "RunContextMenu")
callback_py = browser.GetClientCallback("RunContextMenu")
if not callback_py:
return 0 # no Python handler — fall back to CEF default
model_py = _SnapshotMenuModel(cef_model)
cb_py = _MakeRunContextMenuCallback(cef_callback)
ret = callback_py(browser=browser,
model=model_py,
callback=cb_py)
return 1 if ret else 0
except:
(exc_type, exc_value, exc_trace) = sys.exc_info()
sys.excepthook(exc_type, exc_value, exc_trace)
return 0