Skip to content

Commit e72609c

Browse files
committed
Add accessibility support for both windowed and OSR modes (cztomczak#449).
Add Browser.SetAccessibilityState. Add AccessibilityHandler (OSR mode). Add cef.SetGlobalClientHandler. Add osr_test.py unittest for off-screen rendering mode (cztomczak#59). Refactor main_test.py. Update tools/apidocs.py - generate TOCs by default Update tools/build_distrib.py - run all unit tests
1 parent cb9628b commit e72609c

24 files changed

+816
-244
lines changed

README.md

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -256,63 +256,67 @@ Additional information for v31.2 release:
256256

257257
### API categories
258258

259-
#### Modules
260-
261-
* [cefpython](api/cefpython.md#cefpython) module
262-
263-
264-
#### Settings
265-
266-
* [ApplicationSettings](api/ApplicationSettings.md#application-settings) dictionary
267-
* [BrowserSettings](api/BrowserSettings.md#browser-settings) dictionary
268-
* [CommandLineSwitches](api/CommandLineSwitches.md#command-line-switches) dictionary
269-
270-
271-
#### Classes and objects
272-
273-
* [Browser](api/Browser.md#browser-object) object
274-
* [Callback](api/Callback.md#callback-object) object
275-
* [Cookie](api/Cookie.md#cookie-class) class
276-
* [CookieManager](api/CookieManager.md#cookiemanager-class) class
277-
* [DpiAware](api/DpiAware.md#dpiaware-class) class (Win)
278-
* [DragData](api/DragData.md#dragdata-object) object
279-
* [Frame](api/Frame.md#frame-object) object
280-
* [Image](api/Image.md#image-object) object
281-
* [JavascriptBindings](api/JavascriptBindings.md#javascriptbindings-class) class
282-
* [JavascriptCallback](api/JavascriptCallback.md#javascriptcallback-object) object
283-
* [PaintBuffer](api/PaintBuffer.md#paintbuffer-object) object
284-
* [Request](api/Request.md#request-class) class
285-
* [Response](api/Response.md#response-object) object
286-
* [WebPluginInfo](api/WebPluginInfo.md#webplugininfo-object) object
287-
* [WebRequest](api/WebRequest.md#webrequest-class) class
288-
* [WindowInfo](api/WindowInfo.md#windowinfo-class) class
289-
* [WindowUtils](api/WindowUtils.md#windowutils-class) class
290-
291-
292-
#### Client handlers (interfaces)
293-
294-
* [DisplayHandler](api/DisplayHandler.md#displayhandler-interface)
295-
* [DownloadHandler](api/DownloadHandler.md#downloadhandler)
296-
* [FocusHandler](api/FocusHandler.md#focushandler-interface)
297-
* [JavascriptDialogHandler](api/JavascriptDialogHandler.md#javascriptdialoghandler-interface)
298-
* [KeyboardHandler](api/KeyboardHandler.md#keyboardhandler-interface)
299-
* [LifespanHandler](api/LifespanHandler.md#lifespanhandler-interface)
300-
* [LoadHandler](api/LoadHandler.md#loadhandler-interface)
301-
* [RenderHandler](api/RenderHandler.md#renderhandler-interface)
302-
* [RequestHandler](api/RequestHandler.md#requesthandler-interface)
303-
* [ResourceHandler](api/ResourceHandler.md#resourcehandler-interface)
304-
* [V8ContextHandler](api/V8ContextHandler.md#v8contexthandler-interface)
305-
306-
307-
#### Other interfaces
308-
309-
* [CookieVisitor](api/CookieVisitor.md#cookievisitor-interface) interface
310-
* [StringVisitor](api/StringVisitor.md#stringvisitor-interface) interface
311-
* [WebRequestClient](api/WebRequestClient.md#webrequestclient-interface) interface
312-
259+
#### Modules
260+
261+
* [cefpython](api/cefpython.md#cefpython) module
262+
263+
264+
#### Settings
265+
266+
* [ApplicationSettings](api/ApplicationSettings.md#application-settings) dictionary
267+
* [BrowserSettings](api/BrowserSettings.md#browser-settings) dictionary
268+
* [CommandLineSwitches](api/CommandLineSwitches.md#command-line-switches) dictionary
269+
270+
271+
#### Classes and objects
272+
273+
* [Browser](api/Browser.md#browser-object) object
274+
* [Callback](api/Callback.md#callback-object) object
275+
* [Cookie](api/Cookie.md#cookie-class) class
276+
* [CookieManager](api/CookieManager.md#cookiemanager-class) class
277+
* [DpiAware](api/DpiAware.md#dpiaware-class) class (Win)
278+
* [DragData](api/DragData.md#dragdata-object) object
279+
* [Frame](api/Frame.md#frame-object) object
280+
* [Image](api/Image.md#image-object) object
281+
* [JavascriptBindings](api/JavascriptBindings.md#javascriptbindings-class) class
282+
* [JavascriptCallback](api/JavascriptCallback.md#javascriptcallback-object) object
283+
* [PaintBuffer](api/PaintBuffer.md#paintbuffer-object) object
284+
* [Request](api/Request.md#request-class) class
285+
* [Response](api/Response.md#response-object) object
286+
* [WebPluginInfo](api/WebPluginInfo.md#webplugininfo-object) object
287+
* [WebRequest](api/WebRequest.md#webrequest-class) class
288+
* [WindowInfo](api/WindowInfo.md#windowinfo-class) class
289+
* [WindowUtils](api/WindowUtils.md#windowutils-class) class
290+
291+
292+
#### Client handlers (interfaces)
293+
294+
* [AccessibilityHandler](api/AccessibilityHandler.md#accessibilityhandler-interface)
295+
* [DisplayHandler](api/DisplayHandler.md#displayhandler-interface)
296+
* [DownloadHandler](api/DownloadHandler.md#downloadhandler)
297+
* [FocusHandler](api/FocusHandler.md#focushandler-interface)
298+
* [JavascriptDialogHandler](api/JavascriptDialogHandler.md#javascriptdialoghandler-interface)
299+
* [KeyboardHandler](api/KeyboardHandler.md#keyboardhandler-interface)
300+
* [LifespanHandler](api/LifespanHandler.md#lifespanhandler-interface)
301+
* [LoadHandler](api/LoadHandler.md#loadhandler-interface)
302+
* [RenderHandler](api/RenderHandler.md#renderhandler-interface)
303+
* [RequestHandler](api/RequestHandler.md#requesthandler-interface)
304+
* [ResourceHandler](api/ResourceHandler.md#resourcehandler-interface)
305+
* [V8ContextHandler](api/V8ContextHandler.md#v8contexthandler-interface)
306+
307+
308+
#### Other interfaces
309+
310+
* [CookieVisitor](api/CookieVisitor.md#cookievisitor-interface) interface
311+
* [StringVisitor](api/StringVisitor.md#stringvisitor-interface) interface
312+
* [WebRequestClient](api/WebRequestClient.md#webrequestclient-interface) interface
313+
313314

314315
### API index
315316

317+
* [AccessibilityHandler (interface)](api/AccessibilityHandler.md#accessibilityhandler-interface)
318+
* [_OnAccessibilityTreeChange](api/AccessibilityHandler.md#_onaccessibilitytreechange)
319+
* [_OnAccessibilityLocationChange](api/AccessibilityHandler.md#_onaccessibilitylocationchange)
316320
* [Application settings](api/ApplicationSettings.md#application-settings)
317321
* [accept_language_list](api/ApplicationSettings.md#accept_language_list)
318322
* [app_user_model_id](api/ApplicationSettings.md#app_user_model_id)
@@ -408,6 +412,7 @@ Additional information for v31.2 release:
408412
* [SendMouseWheelEvent](api/Browser.md#sendmousewheelevent)
409413
* [SendFocusEvent](api/Browser.md#sendfocusevent)
410414
* [SendCaptureLostEvent](api/Browser.md#sendcapturelostevent)
415+
* [SetAccessibilityState](api/Browser.md#setaccessibilitystate)
411416
* [SetClientCallback](api/Browser.md#setclientcallback)
412417
* [SetClientHandler](api/Browser.md#setclienthandler)
413418
* [SetFocus](api/Browser.md#setfocus)
@@ -469,6 +474,7 @@ Additional information for v31.2 release:
469474
* [PostDelayedTask](api/cefpython.md#postdelayedtask)
470475
* [QuitMessageLoop](api/cefpython.md#quitmessageloop)
471476
* [SetGlobalClientCallback](api/cefpython.md#setglobalclientcallback)
477+
* [SetGlobalClientHandler](api/cefpython.md#setglobalclienthandler)
472478
* [SetOsModalLoop](api/cefpython.md#setosmodalloop)
473479
* [Shutdown](api/cefpython.md#shutdown)
474480
* [Command line switches](api/CommandLineSwitches.md#command-line-switches)

api/API-categories.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
### Client handlers (interfaces)
4040

41+
* [AccessibilityHandler](AccessibilityHandler.md#accessibilityhandler-interface)
4142
* [DisplayHandler](DisplayHandler.md#displayhandler-interface)
4243
* [DownloadHandler](DownloadHandler.md#downloadhandler)
4344
* [FocusHandler](FocusHandler.md#focushandler-interface)

api/API-index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
# API index
44

5+
* [AccessibilityHandler (interface)](AccessibilityHandler.md#accessibilityhandler-interface)
6+
* [_OnAccessibilityTreeChange](AccessibilityHandler.md#_onaccessibilitytreechange)
7+
* [_OnAccessibilityLocationChange](AccessibilityHandler.md#_onaccessibilitylocationchange)
58
* [Application settings](ApplicationSettings.md#application-settings)
69
* [accept_language_list](ApplicationSettings.md#accept_language_list)
710
* [app_user_model_id](ApplicationSettings.md#app_user_model_id)
@@ -97,6 +100,7 @@
97100
* [SendMouseWheelEvent](Browser.md#sendmousewheelevent)
98101
* [SendFocusEvent](Browser.md#sendfocusevent)
99102
* [SendCaptureLostEvent](Browser.md#sendcapturelostevent)
103+
* [SetAccessibilityState](Browser.md#setaccessibilitystate)
100104
* [SetClientCallback](Browser.md#setclientcallback)
101105
* [SetClientHandler](Browser.md#setclienthandler)
102106
* [SetFocus](Browser.md#setfocus)
@@ -158,6 +162,7 @@
158162
* [PostDelayedTask](cefpython.md#postdelayedtask)
159163
* [QuitMessageLoop](cefpython.md#quitmessageloop)
160164
* [SetGlobalClientCallback](cefpython.md#setglobalclientcallback)
165+
* [SetGlobalClientHandler](cefpython.md#setglobalclienthandler)
161166
* [SetOsModalLoop](cefpython.md#setosmodalloop)
162167
* [Shutdown](cefpython.md#shutdown)
163168
* [Command line switches](CommandLineSwitches.md#command-line-switches)

api/AccessibilityHandler.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
[API categories](API-categories.md) | [API index](API-index.md)
2+
3+
4+
# AccessibilityHandler (interface)
5+
6+
This handler is for use only with off-screen rendering enabled.
7+
See [RenderHandler](RenderHandler.md) for details.
8+
9+
Implement this interface to receive accessibility notification when
10+
accessibility events have been registered. The methods of this class will
11+
be called on the UI thread.
12+
13+
Callbacks in this interface are not associated with any specific browser,
14+
thus you must call cefpython.[SetGlobalClientHandler] or
15+
SetGlobalClientCallback() to use them. The callbacks names were prefixed
16+
with "`_`" to distinguish this special behavior.
17+
18+
For an example of how to implement handler see [cefpython](cefpython.md).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers).
19+
20+
21+
Table of contents:
22+
* [Callbacks](#callbacks)
23+
* [_OnAccessibilityTreeChange](#_onaccessibilitytreechange)
24+
* [_OnAccessibilityLocationChange](#_onaccessibilitylocationchange)
25+
26+
27+
## Callbacks
28+
29+
30+
### _OnAccessibilityTreeChange
31+
32+
| Parameter | Type |
33+
| --- | --- |
34+
| value | list |
35+
| __Return__ | void |
36+
37+
Called after renderer process sends accessibility tree changes to the
38+
browser process.
39+
40+
41+
### _OnAccessibilityLocationChange
42+
43+
| Parameter | Type |
44+
| --- | --- |
45+
| value | list |
46+
| __Return__ | void |
47+
48+
Called after renderer process sends accessibility location changes to the
49+
browser process.
50+

api/Browser.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ Table of contents:
7676
* [SendMouseWheelEvent](#sendmousewheelevent)
7777
* [SendFocusEvent](#sendfocusevent)
7878
* [SendCaptureLostEvent](#sendcapturelostevent)
79+
* [SetAccessibilityState](#setaccessibilitystate)
7980
* [SetClientCallback](#setclientcallback)
8081
* [SetClientHandler](#setclienthandler)
8182
* [SetFocus](#setfocus)
@@ -844,6 +845,44 @@ Send a focus event to the browser.
844845
Send a capture lost event to the browser.
845846

846847

848+
### SetAccessibilityState
849+
850+
| | |
851+
| --- | --- |
852+
| state | cef_state_t |
853+
| __Return__ | void |
854+
855+
cef_state_t enum values defined in cefpython module:
856+
- STATE_DEFAULT
857+
- STATE_ENABLED
858+
- STATE_DISABLED
859+
860+
Description from upstream CEF:
861+
> Set accessibility state for all frames. |accessibility_state| may be
862+
> default, enabled or disabled. If |accessibility_state| is STATE_DEFAULT
863+
> then accessibility will be disabled by default and the state may be further
864+
> controlled with the "force-renderer-accessibility" and
865+
> "disable-renderer-accessibility" command-line switches. If
866+
> |accessibility_state| is STATE_ENABLED then accessibility will be enabled.
867+
> If |accessibility_state| is STATE_DISABLED then accessibility will be
868+
> completely disabled.
869+
>
870+
> For windowed browsers accessibility will be enabled in Complete mode (which
871+
> corresponds to kAccessibilityModeComplete in Chromium). In this mode all
872+
> platform accessibility objects will be created and managed by Chromium's
873+
> internal implementation. The client needs only to detect the screen reader
874+
> and call this method appropriately. For example, on macOS the client can
875+
> handle the @"AXEnhancedUserInterface" accessibility attribute to detect
876+
> VoiceOver state changes and on Windows the client can handle WM_GETOBJECT
877+
> with OBJID_CLIENT to detect accessibility readers.
878+
>
879+
> For windowless browsers accessibility will be enabled in TreeOnly mode
880+
> (which corresponds to kAccessibilityModeWebContentsOnly in Chromium). In
881+
> this mode renderer accessibility is enabled, the full tree is computed, and
882+
> events are passed to CefAccessibiltyHandler, but platform accessibility
883+
> objects are not created. The client may implement platform accessibility
884+
> objects using CefAccessibiltyHandler callbacks if desired.
885+
847886
### SetClientCallback
848887

849888
| Parameter | Type |

api/cefpython.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Table of contents:
2626
* [PostDelayedTask](#postdelayedtask)
2727
* [QuitMessageLoop](#quitmessageloop)
2828
* [SetGlobalClientCallback](#setglobalclientcallback)
29+
* [SetGlobalClientHandler](#setglobalclienthandler)
2930
* [SetOsModalLoop](#setosmodalloop)
3031
* [Shutdown](#shutdown)
3132

@@ -133,7 +134,8 @@ Returns the [CommandLineSwitches](CommandLineSwitches.md) switch that was passed
133134
| name | string |
134135
| __Return__ | object |
135136

136-
Returns a global client callback that was set using SetGlobalClientCallback(). Returns None if callback was not set.
137+
Returns a global client callback that was set using SetGlobalClientCallback()
138+
or SetGlobalClientHandler. Returns None if callback was not set.
137139

138140

139141
### GetModuleDirectory
@@ -290,6 +292,23 @@ Some client callbacks are not associated with any browser. In such case use this
290292
Example of using SetGlobalClientCallback() is provided in the wxpython.py example.
291293

292294

295+
### SetGlobalClientHandler
296+
297+
| Parameter | Type |
298+
| --- | --- |
299+
| handler | object |
300+
| __Return__ | void |
301+
302+
Set client handler object (class instance). Its members will be inspected.
303+
Private methods that are not meant to be callbacks should have their names
304+
prepended with two underscores. Methods with single underscore or no
305+
underscore are treated the same as client callbacks.
306+
307+
You can call this method multiple times to set many handlers. For
308+
example you can create in your code several objects named AccessibilityHandler,
309+
RequestHandler etc.
310+
311+
293312
### SetOsModalLoop
294313

295314
| Parameter | Type |

src/browser.pyx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
include "cefpython.pyx"
66

77
cimport cef_types
8+
from cef_types cimport cef_state_t
89
IF UNAME_SYSNAME == "Linux":
910
cimport x11
1011

@@ -513,6 +514,9 @@ cdef class PyBrowser:
513514
ELSE:
514515
NonCriticalError("SetBounds() not implemented on this platform")
515516

517+
cpdef py_void SetAccessibilityState(self, cef_state_t state):
518+
self.GetCefBrowserHost().get().SetAccessibilityState(state)
519+
516520
cpdef py_void SetFocus(self, enable):
517521
self.GetCefBrowserHost().get().SetFocus(bool(enable))
518522

src/cef_types.pyx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2014 CEF Python, see the Authors file.
2+
# All rights reserved. Licensed under BSD 3-clause license.
3+
# Project website: https://github.com/cztomczak/cefpython
4+
5+
cimport cef_types
6+
7+
STATE_DEFAULT = cef_types.STATE_DEFAULT
8+
STATE_ENABLED = cef_types.STATE_ENABLED
9+
STATE_DISABLED = cef_types.STATE_DISABLED

src/cef_v59..v66_changes.txt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ MISC
7070
NEW FEATURES
7171
------------
7272

73+
+ unittests/osr_test.py - new test for off-screen rendering mode
74+
7375
internal/cef_types.h
7476
+ cef_log_severity_t: new key LOGSEVERITY_DEBUG (no need to expose,
7577
same as LOGSEVERITY_VERBOSE, see code comments in setting.pyx
@@ -81,14 +83,15 @@ internal/cef_types.h
8183
+ cef_referrer_policy_t changes (not exposed, info only)
8284

8385
cef_accessibility_handler.h
84-
- CefAccessibilityHandler
85-
- CefRenderHandler::GetAccessibilityHandler
86+
+ CefAccessibilityHandler
87+
+ CefRenderHandler::GetAccessibilityHandler
88+
+ cefpython.SetGlobalClientHandler
8689

8790
cef_render_handler.h
8891
- OnTextSelectionChanged
8992

9093
cef_browser.h
91-
- SetAccessibilityState
94+
+ SetAccessibilityState
9295
- SetAutoResizeEnabled
9396
- GetExtension
9497
- IsBackgroundHost
@@ -101,9 +104,9 @@ cef_display_handler.h
101104
- OnLoadingProgressChange
102105

103106
cef_drag_data.h
104-
- GetImage (cross-platform)
105-
- GetImageHotspot (cross-platform)
106-
- HasImage (cross-platform)
107+
+ GetImage (cross-platform)
108+
+ GetImageHotspot (cross-platform)
109+
+ HasImage (cross-platform)
107110

108111
cef_extension.h
109112
- CefExtension

0 commit comments

Comments
 (0)