Title: [158713] trunk
Revision
158713
Author
[email protected]
Date
2013-11-05 19:50:51 -0800 (Tue, 05 Nov 2013)

Log Message

AX: media controls accessibility needs more work
https://bugs.webkit.org/show_bug.cgi?id=123749

Patch by James Craig <[email protected]> on 2013-11-05
Reviewed by Jer Noble.

Updated some of the control labels/roles to improve accessibility.
  - Volume slider is now keyboard/screenreader accessible.
  - muteButton was a checkbox toggling checked state, now a button that toggles label "mute/unmute"
  - fullscreenButton was a checkbox toggling checked state, now a button that toggles label "display/exit full screen"
  - captionButton was a checkbox, now a popup button that launches the newly accessible menu.
Subtitles menu is now keyboard/screenreader accessible (uses roaming tabindex).
Render dump expectations changed because volume slider is now hidden via...
...opacity/size (to make accessible without hover) instead of display:none.

Updated existing test coverage.

Source/WebCore:

* Modules/mediacontrols/mediaControlsApple.css:
(audio::-webkit-media-controls-panel .volume-box):
(audio::-webkit-media-controls-panel .volume-box:active):
(audio::-webkit-media-controls-toggle-closed-captions-button):
(audio::-webkit-media-controls-closed-captions-container .list):
(audio::-webkit-media-controls-closed-captions-container li:focus):
* Modules/mediacontrols/mediaControlsApple.js:
(Controller.prototype.createControls):
(Controller.prototype.handleFullscreenChange):
(Controller.prototype.handleMuteButtonClicked):
(Controller.prototype.handleMinButtonClicked):
(Controller.prototype.handleMaxButtonClicked):
(Controller.prototype.handleVolumeSliderChange):
(Controller.prototype.buildCaptionMenu):
(Controller.prototype.focusSiblingCaptionItem):
(Controller.prototype.handleCaptionItemKeyUp):

LayoutTests:

* platform/mac/accessibility/media-element-expected.txt:
* platform/mac/media/audio-controls-rendering-expected.txt:
* platform/mac/media/controls-after-reload-expected.txt:
* platform/mac/media/controls-strict-expected.txt:
* platform/mac/media/controls-styling-strict-expected.txt:
* platform/mac/media/controls-without-preload-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (158712 => 158713)


--- trunk/LayoutTests/ChangeLog	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/LayoutTests/ChangeLog	2013-11-06 03:50:51 UTC (rev 158713)
@@ -1,3 +1,28 @@
+2013-11-05  James Craig  <[email protected]>
+
+        AX: media controls accessibility needs more work
+        https://bugs.webkit.org/show_bug.cgi?id=123749
+
+        Reviewed by Jer Noble.
+
+        Updated some of the control labels/roles to improve accessibility.
+          - Volume slider is now keyboard/screenreader accessible.
+          - muteButton was a checkbox toggling checked state, now a button that toggles label "mute/unmute"
+          - fullscreenButton was a checkbox toggling checked state, now a button that toggles label "display/exit full screen"
+          - captionButton was a checkbox, now a popup button that launches the newly accessible menu.
+        Subtitles menu is now keyboard/screenreader accessible (uses roaming tabindex).
+        Render dump expectations changed because volume slider is now hidden via... 
+        ...opacity/size (to make accessible without hover) instead of display:none.
+
+        Updated existing test coverage.
+
+        * platform/mac/accessibility/media-element-expected.txt:
+        * platform/mac/media/audio-controls-rendering-expected.txt:
+        * platform/mac/media/controls-after-reload-expected.txt:
+        * platform/mac/media/controls-strict-expected.txt:
+        * platform/mac/media/controls-styling-strict-expected.txt:
+        * platform/mac/media/controls-without-preload-expected.txt:
+
 2013-11-05  Ryosuke Niwa  <[email protected]>
 
         Add a test to obtain offsetWidth of expanded table cell

Modified: trunk/LayoutTests/platform/mac/accessibility/media-element-expected.txt (158712 => 158713)


--- trunk/LayoutTests/platform/mac/accessibility/media-element-expected.txt	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/LayoutTests/platform/mac/accessibility/media-element-expected.txt	2013-11-06 03:50:51 UTC (rev 158713)
@@ -54,12 +54,20 @@
                     role: AXRole: AXStaticText
 
 
+            description: AXDescription: Volume
+            role: AXRole: AXSlider
+
+
+                description: AXDescription: 
+                role: AXRole: AXValueIndicator
+
+
             description: AXDescription: Mute
-            role: AXRole: AXCheckBox
+            role: AXRole: AXButton
 
 
             description: AXDescription: Display Full Screen
-            role: AXRole: AXCheckBox
+            role: AXRole: AXButton
 
 
 

Modified: trunk/LayoutTests/platform/mac/media/audio-controls-rendering-expected.txt (158712 => 158713)


--- trunk/LayoutTests/platform/mac/media/audio-controls-rendering-expected.txt	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/LayoutTests/platform/mac/media/audio-controls-rendering-expected.txt	2013-11-06 03:50:51 UTC (rev 158713)
@@ -43,6 +43,13 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (184,44) size 22x22
   RenderFlexibleBox {DIV} at (176,2) size 22x22
+layer at (184,44) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (170,51) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (187,47) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]
 layer at (8,85) size 320x25
@@ -74,6 +81,13 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (304,87) size 22x22
   RenderFlexibleBox {DIV} at (296,2) size 22x22
+layer at (304,87) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (290,94) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (307,90) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]
 layer at (8,128) size 320x100
@@ -107,5 +121,12 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (304,205) size 22x22
   RenderFlexibleBox {DIV} at (296,2) size 22x22
+layer at (304,205) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (290,212) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (307,208) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]

Modified: trunk/LayoutTests/platform/mac/media/controls-after-reload-expected.txt (158712 => 158713)


--- trunk/LayoutTests/platform/mac/media/controls-after-reload-expected.txt	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/LayoutTests/platform/mac/media/controls-after-reload-expected.txt	2013-11-06 03:50:51 UTC (rev 158713)
@@ -39,6 +39,13 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (274,259) size 22x22
   RenderFlexibleBox {DIV} at (266,2) size 22x22
+layer at (274,259) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (260,266) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (277,262) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]
 layer at (305,262) size 16x16

Modified: trunk/LayoutTests/platform/mac/media/controls-strict-expected.txt (158712 => 158713)


--- trunk/LayoutTests/platform/mac/media/controls-strict-expected.txt	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/LayoutTests/platform/mac/media/controls-strict-expected.txt	2013-11-06 03:50:51 UTC (rev 158713)
@@ -39,6 +39,13 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (274,267) size 22x22
   RenderFlexibleBox {DIV} at (266,2) size 22x22
+layer at (274,267) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (260,274) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (277,270) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]
 layer at (305,270) size 16x16

Modified: trunk/LayoutTests/platform/mac/media/controls-styling-strict-expected.txt (158712 => 158713)


--- trunk/LayoutTests/platform/mac/media/controls-styling-strict-expected.txt	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/LayoutTests/platform/mac/media/controls-styling-strict-expected.txt	2013-11-06 03:50:51 UTC (rev 158713)
@@ -43,6 +43,13 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (274,267) size 22x22
   RenderFlexibleBox {DIV} at (266,2) size 22x22
+layer at (274,267) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (260,274) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (277,270) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]
 layer at (305,270) size 16x16
@@ -76,6 +83,13 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (598,267) size 22x22
   RenderFlexibleBox {DIV} at (266,2) size 22x22
+layer at (598,267) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (584,274) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (601,270) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]
 layer at (629,270) size 16x16

Modified: trunk/LayoutTests/platform/mac/media/controls-without-preload-expected.txt (158712 => 158713)


--- trunk/LayoutTests/platform/mac/media/controls-without-preload-expected.txt	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/LayoutTests/platform/mac/media/controls-without-preload-expected.txt	2013-11-06 03:50:51 UTC (rev 158713)
@@ -39,6 +39,13 @@
   RenderBlock {DIV} at (0,0) size 6x6 [bgcolor=#FFFFFF]
 layer at (274,259) size 22x22
   RenderFlexibleBox {DIV} at (266,2) size 22x22
+layer at (274,259) size 2x22
+  RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)]
+    RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)]
+      RenderFlexibleBox {DIV} at (1,1) size 0x8
+        RenderBlock {DIV} at (0,0) size 0x8
+layer at (260,266) size 8x8
+  RenderBlock {DIV} at (-8,0) size 8x8
 layer at (277,262) size 16x16
   RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF]
 layer at (305,262) size 16x16

Modified: trunk/Source/WebCore/ChangeLog (158712 => 158713)


--- trunk/Source/WebCore/ChangeLog	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/Source/WebCore/ChangeLog	2013-11-06 03:50:51 UTC (rev 158713)
@@ -1,3 +1,38 @@
+2013-11-05  James Craig  <[email protected]>
+
+        AX: media controls accessibility needs more work
+        https://bugs.webkit.org/show_bug.cgi?id=123749
+
+        Reviewed by Jer Noble.
+
+        Updated some of the control labels/roles to improve accessibility.
+          - Volume slider is now keyboard/screenreader accessible.
+          - muteButton was a checkbox toggling checked state, now a button that toggles label "mute/unmute"
+          - fullscreenButton was a checkbox toggling checked state, now a button that toggles label "display/exit full screen"
+          - captionButton was a checkbox, now a popup button that launches the newly accessible menu.
+        Subtitles menu is now keyboard/screenreader accessible (uses roaming tabindex).
+        Render dump expectations changed because volume slider is now hidden via... 
+        ...opacity/size (to make accessible without hover) instead of display:none.
+
+        Updated existing test coverage.
+
+        * Modules/mediacontrols/mediaControlsApple.css:
+        (audio::-webkit-media-controls-panel .volume-box):
+        (audio::-webkit-media-controls-panel .volume-box:active):
+        (audio::-webkit-media-controls-toggle-closed-captions-button):
+        (audio::-webkit-media-controls-closed-captions-container .list):
+        (audio::-webkit-media-controls-closed-captions-container li:focus):
+        * Modules/mediacontrols/mediaControlsApple.js:
+        (Controller.prototype.createControls):
+        (Controller.prototype.handleFullscreenChange):
+        (Controller.prototype.handleMuteButtonClicked):
+        (Controller.prototype.handleMinButtonClicked):
+        (Controller.prototype.handleMaxButtonClicked):
+        (Controller.prototype.handleVolumeSliderChange):
+        (Controller.prototype.buildCaptionMenu):
+        (Controller.prototype.focusSiblingCaptionItem):
+        (Controller.prototype.handleCaptionItemKeyUp):
+
 2013-11-05  Andreas Kling  <[email protected]>
 
         Move some plugin-specific code from RenderWidget to RenderEmbeddedObject.

Modified: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css (158712 => 158713)


--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css	2013-11-06 03:50:51 UTC (rev 158713)
@@ -172,7 +172,6 @@
     position: absolute;
     box-sizing: border-box;
     height: 22px;
-    width: 114px;
     bottom: 0;
     left: 0;
 
@@ -194,9 +193,12 @@
     -webkit-justify-content: flex-end;
 
     opacity: 0;
-    display: none;
+    /* make zero width (rather than display:none) for AX and FKA */
+    width: 0; /* will become 114px when shown */
+
 }
 
+/* FIXME: needs CSS4 !subject selector to show when slider inside .volume-box is focused */
 video::-webkit-media-controls-panel .mute-box:hover .volume-box,
 video::-webkit-media-controls-panel .volume-box:hover,
 video::-webkit-media-controls-panel .volume-box:active,
@@ -204,7 +206,8 @@
 audio::-webkit-media-controls-panel .volume-box:hover,
 audio::-webkit-media-controls-panel .volume-box:active {
     opacity: 1;
-    display: inherit;
+    /* resize to usable amount (rather than display:none) for AX and FKA */
+    width: 114px;
 }
 
 audio::-webkit-media-controls-volume-slider,
@@ -268,8 +271,8 @@
     width: 16px;
     height: 16px;
     margin: 0 7px;
-
     background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 102 105"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.46875" stop-color="rgb(216, 216, 216)"/><stop offset="0.46875" stop-color="rgb(208, 208, 208)"/><stop offset="0.53125" stop-color="rgb(208, 208, 208)"/><stop offset="0.53125" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M98.766,43.224c0-23.163-21.775-41.94-48.637-41.94c-26.859,0-48.635,18.777-48.635,41.94c0,18.266,13.546,33.796,32.444,39.549c1.131,8.356,26.037,24.255,22.864,19.921c-4.462-6.096-5.159-13.183-5.07-17.566C77.85,84.397,98.766,65.923,98.766,43.224z" fill="url(#gradient)"/></svg>');
+    outline: 0;
 }
 
 video::-webkit-media-controls-closed-captions-container,
@@ -294,7 +297,7 @@
 video::-webkit-media-controls-closed-captions-container .list,
 audio::-webkit-media-controls-closed-captions-container .list {
     display: block;
-    font-family: "Helvetica Bold", Helvetica;
+    font-family: "Helvetica Bold", Helvetica, sans-serif;
     font-size: 10pt;
     -webkit-user-select: none;
 }
@@ -337,6 +340,12 @@
     border-bottom: 1px solid transparent;
 }
 
+video::-webkit-media-controls-closed-captions-container li:focus,
+audio::-webkit-media-controls-closed-captions-container li:focus {
+    outline: 0;
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(255, 255, 255, 0.3)), color-stop(1, rgba(255, 255, 255, 0.2)));
+}
+
 video::-webkit-media-controls-closed-captions-container li:hover,
 audio::-webkit-media-controls-closed-captions-container li:hover {
     background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgb(79, 112, 246)), color-stop(1, rgb(26, 68, 243)));

Modified: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js (158712 => 158713)


--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js	2013-11-06 03:36:32 UTC (rev 158712)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js	2013-11-06 03:50:51 UTC (rev 158713)
@@ -76,6 +76,19 @@
         thumbnailTrack: 'thumbnail-track',
         volumeBox: 'volume-box',
     },
+    KeyCodes: {
+        enter: 13,
+        escape: 27,
+        space: 32,
+        pageUp: 33,
+        pageDown: 34,
+        end: 35,
+        home: 36,
+        left: 37,
+        up: 38,
+        right: 39,
+        down: 40
+    },
 
     // Localized string accessor
     UIString: function(s){
@@ -88,23 +101,26 @@
         // FIXME: Move localization to ext strings file <http://webkit.org/b/120956>
         'Aborted': 'Aborted',
         'Audio Playback': 'Audio Playback',
+        'Captions': 'Captions',
         'Display Full Screen': 'Display Full Screen',
         'Duration': 'Duration',
+        'Elapsed': 'Elapsed',
         'Error': 'Error',
+        'Exit Full Screen': 'Exit Full Screen',
         'Fast Forward': 'Fast Forward',
         'Loading': 'Loading',
         'Maximum Volume': 'Maximum Volume',
         'Minimum Volume': 'Minimum Volume',
         'Mute': 'Mute',
+        'Pause': 'Pause',
         'Play': 'Play',
-        'Pause': 'Pause',
+        'Remaining': 'Remaining',
         'Rewind': 'Rewind',
         'Rewind %%sec%% Seconds': 'Rewind %%sec%% Seconds',
-        'Show Captions': 'Show Captions',
         'Stalled': 'Stalled',
+        'Subtitles': 'Subtitles',
         'Suspended': 'Suspended',
-        'Elapsed': 'Elapsed',
-        'Remaining': 'Remaining',
+        'Unmute': 'Unmute',
         'Video Playback': 'Video Playback',
         'Volume': 'Volume',
         'Waiting': 'Waiting'
@@ -301,8 +317,6 @@
         var muteButton = this.controls.muteButton = document.createElement('button');
         muteButton.setAttribute('pseudo', '-webkit-media-controls-mute-button');
         muteButton.setAttribute('aria-label', this.UIString('Mute'));
-        muteButton.setAttribute('role', 'checkbox');
-        muteButton.setAttribute('aria-checked', 'false');
         this.listenFor(muteButton, 'click', this.handleMuteButtonClicked);
 
         var minButton = this.controls.minButton = document.createElement('button');
@@ -329,16 +343,13 @@
 
         var captionButton = this.controls.captionButton = document.createElement('button');
         captionButton.setAttribute('pseudo', '-webkit-media-controls-toggle-closed-captions-button');
-        captionButton.setAttribute('aria-label', this.UIString('Show Captions'));
-        captionButton.setAttribute('role', 'checkbox');
-        captionButton.setAttribute('aria-checked', 'false');
+        captionButton.setAttribute('aria-label', this.UIString('Captions'));
+        captionButton.setAttribute('aria-haspopup', 'true');
         this.listenFor(captionButton, 'click', this.handleCaptionButtonClicked);
 
         var fullscreenButton = this.controls.fullscreenButton = document.createElement('button');
         fullscreenButton.setAttribute('pseudo', '-webkit-media-controls-fullscreen-button');
         fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen'));
-        fullscreenButton.setAttribute('role', 'checkbox');
-        fullscreenButton.setAttribute('aria-checked', 'false');
         this.listenFor(fullscreenButton, 'click', this.handleFullscreenButtonClicked);
     },
 
@@ -519,11 +530,11 @@
 
         if (this.isFullScreen()) {
             this.controls.fullscreenButton.classList.add(this.ClassNames.exit);
-            this.controls.fullscreenButton.setAttribute('aria-checked', 'true');
+            this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Exit Full Screen'));
             this.setControlsType(Controller.FullScreenControls);
         } else {
             this.controls.fullscreenButton.classList.remove(this.ClassNames.exit);
-            this.controls.fullscreenButton.setAttribute('aria-checked', 'false');
+            this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen'));
             this.setControlsType(Controller.InlineControls);
         }
     },
@@ -668,14 +679,14 @@
     {
         this.video.muted = !this.video.muted;
         if (this.video.muted)
-            this.controls.muteButton.setAttribute('aria-checked', 'true');
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Unmute'));
     },
 
     handleMinButtonClicked: function(event)
     {
         if (this.video.muted) {
             this.video.muted = false;
-            this.controls.muteButton.setAttribute('aria-checked', 'false');
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute'));
         }
         this.video.volume = 0;
     },
@@ -684,7 +695,7 @@
     {
         if (this.video.muted) {
             this.video.muted = false;
-            this.controls.muteButton.setAttribute('aria-checked', 'false');
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute'));
         }
         this.video.volume = 1;
     },
@@ -693,7 +704,7 @@
     {
         if (this.video.muted) {
             this.video.muted = false;
-            this.controls.muteButton.setAttribute('aria-checked', 'false');
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute'));
         }
         this.video.volume = this.controls.volume.value;
     },
@@ -928,16 +939,22 @@
         list.classList.add(this.ClassNames.list);
 
         var heading = document.createElement('h3');
+        heading.id = 'webkitMediaControlsClosedCaptionsHeading'; // for AX menu label
         list.appendChild(heading);
-        heading.innerText = 'Subtitles';
+        heading.innerText = this.UIString('Subtitles');
 
         var ul = document.createElement('ul');
+        ul.setAttribute('role', 'menu');
+        ul.setAttribute('aria-labelledby', 'webkitMediaControlsClosedCaptionsHeading');
         list.appendChild(ul);
 
         for (var i = 0; i < tracks.length; ++i) {
             var menuItem = document.createElement('li');
+            menuItem.setAttribute('role', 'menuitemradio');
+            menuItem.setAttribute('tabindex', '-1');
             this.captionMenuItems.push(menuItem);
             this.listenFor(menuItem, 'click', this.captionItemSelected);
+            this.listenFor(menuItem, 'keyup', this.handleCaptionItemKeyUp);
             ul.appendChild(menuItem);
 
             var track = tracks[i];
@@ -950,19 +967,38 @@
             }
 
             if (track === automaticItem) {
-                if (displayMode === 'automatic')
+                if (displayMode === 'automatic') {
                     menuItem.classList.add(this.ClassNames.selected);
+                    menuItem.setAttribute('tabindex', '0');
+                    menuItem.setAttribute('aria-checked', 'true');
+                }
                 continue;
             }
 
             if (displayMode != 'automatic' && track.mode === 'showing') {
                 var trackMenuItemSelected = true;
                 menuItem.classList.add(this.ClassNames.selected);
+                menuItem.setAttribute('tabindex', '0');
+                menuItem.setAttribute('aria-checked', 'true');
             }
+
         }
 
-        if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected)
+        if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected) {
             offMenu.classList.add(this.ClassNames.selected);
+            menuItem.setAttribute('tabindex', '0');
+            menuItem.setAttribute('aria-checked', 'true');
+        }
+        
+        // focus first selected menuitem
+        for (var i = 0, c = this.captionMenuItems.length; i < c; i++) {
+            var item = this.captionMenuItems[i];
+            if (item.classList.contains(this.ClassNames.selected)) {
+                item.focus();
+                break;
+            }
+        }
+        
     },
 
     captionItemSelected: function(event)
@@ -971,6 +1007,51 @@
         this.destroyCaptionMenu();
     },
 
+    focusSiblingCaptionItem: function(event)
+    {
+        var currentItem = event.target;
+        var pendingItem = false;
+        switch(event.keyCode) {
+        case this.KeyCodes.left:
+        case this.KeyCodes.up:
+            pendingItem = currentItem.previousSibling;
+            break;
+        case this.KeyCodes.right:
+        case this.KeyCodes.down:
+            pendingItem = currentItem.nextSibling;
+            break;
+        }
+        if (pendingItem) {
+            currentItem.setAttribute('tabindex', '-1');
+            pendingItem.setAttribute('tabindex', '0');
+            pendingItem.focus();
+        }
+    },
+
+    handleCaptionItemKeyUp: function(event)
+    {
+        switch (event.keyCode) {
+        case this.KeyCodes.enter:
+        case this.KeyCodes.space:
+            this.captionItemSelected(event);
+            break;
+        case this.KeyCodes.escape:
+            this.destroyCaptionMenu();
+            break;
+        case this.KeyCodes.left:
+        case this.KeyCodes.up:
+        case this.KeyCodes.right:
+        case this.KeyCodes.down:
+            this.focusSiblingCaptionItem(event);
+            break;
+        default:
+            return;
+        }
+        // handled
+        event.stopPropagation();
+        event.preventDefault();
+    },
+
     destroyCaptionMenu: function()
     {
         if (!this.captionMenu)
@@ -978,8 +1059,13 @@
 
         this.captionMenuItems.forEach(function(item){
             this.stopListeningFor(item, 'click', this.captionItemSelected);
+            this.stopListeningFor(item, 'keyup', this.handleCaptionItemKeyUp);
         }, this);
 
+        // FKA and AX: focus the trigger before destroying the element with focus
+        if (this.controls.captionButton)
+            this.controls.captionButton.focus();
+
         if (this.captionMenu.parentNode)
             this.captionMenu.parentNode.removeChild(this.captionMenu);
         delete this.captionMenu;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to