accessibility

This commit is contained in:
Jonas Sourlier 2021-11-24 08:42:07 +01:00
parent a4d1904b81
commit d040615c6e
17 changed files with 384 additions and 0 deletions

View file

@ -6,8 +6,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using SafeExamBrowser.Applications.Contracts;
using SafeExamBrowser.Browser.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.Events;
namespace SafeExamBrowser.Browser.Contracts
{
@ -30,5 +32,15 @@ namespace SafeExamBrowser.Browser.Contracts
/// Event fired when the browser application detects a request to terminate SEB.
/// </summary>
event TerminationRequestedEventHandler TerminationRequested;
/// <summary>
/// Event fired when the user tries to focus the taskbar.
/// </summary>
event LoseFocusRequestedEventHandler LoseFocusRequested;
/// <summary>
/// Transfers the focus to the browser window.
/// </summary>
void Focus(bool forward);
}
}

View file

@ -75,6 +75,10 @@
<Project>{30b2d907-5861-4f39-abad-c4abf1b3470e}</Project>
<Name>SafeExamBrowser.Settings</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.UserInterface.Contracts\SafeExamBrowser.UserInterface.Contracts.csproj">
<Project>{c7889e97-6ff6-4a58-b7cb-521ed276b316}</Project>
<Name>SafeExamBrowser.UserInterface.Contracts</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -27,6 +27,7 @@ using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Settings.Browser.Proxy;
using SafeExamBrowser.Settings.Logging;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
using SafeExamBrowser.WindowsApi.Contracts;
@ -58,6 +59,7 @@ namespace SafeExamBrowser.Browser
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
public event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
public event LoseFocusRequestedEventHandler LoseFocusRequested;
public event TerminationRequestedEventHandler TerminationRequested;
public event WindowsChangedEventHandler WindowsChanged;
@ -195,6 +197,7 @@ namespace SafeExamBrowser.Browser
window.ResetRequested += Window_ResetRequested;
window.SessionIdentifierDetected += (i) => SessionIdentifierDetected?.Invoke(i);
window.TerminationRequested += () => TerminationRequested?.Invoke();
window.LoseFocusRequested += (forward) => LoseFocusRequested?.Invoke(forward);
window.InitializeControl();
windows.Add(window);
@ -457,5 +460,13 @@ namespace SafeExamBrowser.Browser
CreateNewWindow();
logger.Info("Successfully reset browser.");
}
public void Focus(bool forward)
{
windows.ForEach(window =>
{
window.Focus(forward);
});
}
}
}

View file

@ -143,5 +143,14 @@ namespace SafeExamBrowser.Browser
{
control.BrowserCore.SetZoomLevel(level);
}
/// <summary>
/// Executes the given Javascript code in the browser.
/// </summary>
public async void ExecuteJavascript(string javascript, System.Action<dynamic> callback)
{
var result = await this.control.EvaluateScriptAsync(javascript);
callback(result);
}
}
}

View file

@ -31,6 +31,7 @@ using SafeExamBrowser.Settings.Browser.Filter;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
using Syroot.Windows.IO;
@ -80,6 +81,7 @@ namespace SafeExamBrowser.Browser
internal event PopupRequestedEventHandler PopupRequested;
internal event ResetRequestedEventHandler ResetRequested;
internal event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
internal event LoseFocusRequestedEventHandler LoseFocusRequested;
internal event TerminationRequestedEventHandler TerminationRequested;
public event IconChangedEventHandler IconChanged;
@ -162,6 +164,7 @@ namespace SafeExamBrowser.Browser
keyboardHandler.ZoomInRequested += ZoomInRequested;
keyboardHandler.ZoomOutRequested += ZoomOutRequested;
keyboardHandler.ZoomResetRequested += ZoomResetRequested;
keyboardHandler.TabPressed += TabPressed;
resourceHandler.SessionIdentifierDetected += (id) => SessionIdentifierDetected?.Invoke(id);
requestHandler.QuitUrlVisited += RequestHandler_QuitUrlVisited;
requestHandler.RequestBlocked += RequestHandler_RequestBlocked;
@ -198,6 +201,7 @@ namespace SafeExamBrowser.Browser
window.FindRequested += Window_FindRequested;
window.ForwardNavigationRequested += Window_ForwardNavigationRequested;
window.HomeNavigationRequested += HomeNavigationRequested;
window.LoseFocusRequested += Window_LoseFocusRequested;
window.ReloadRequested += ReloadRequested;
window.ZoomInRequested += ZoomInRequested;
window.ZoomOutRequested += ZoomOutRequested;
@ -655,6 +659,11 @@ namespace SafeExamBrowser.Browser
Control.NavigateForwards();
}
private void Window_LoseFocusRequested(bool forward)
{
LoseFocusRequested?.Invoke(forward);
}
private void ZoomInRequested()
{
if (settings.AllowPageZoom && CalculateZoomPercentage() < 300)
@ -688,6 +697,43 @@ namespace SafeExamBrowser.Browser
}
}
private void TabPressed(object sender, bool shiftPressed)
{
this.Control.ExecuteJavascript("document.activeElement.tagName", result =>
{
var tagName = result.Result as string;
if (tagName != null)
{
if (tagName.ToUpper() == "BODY")
{
// this means the user is now at the start of the focus / tabIndex chain in the website
if (shiftPressed)
{
window.FocusToolbar(!shiftPressed);
}
else
{
this.LoseFocusRequested?.Invoke(true);
}
}
}
});
}
internal void Focus(bool forward)
{
if (forward)
{
window.FocusToolbar(forward);
}
else
{
window.FocusBrowser();
this.Activate();
}
}
private double CalculateZoomPercentage()
{
return (zoomLevel * 25.0) + 100.0;

View file

@ -20,6 +20,9 @@ namespace SafeExamBrowser.Browser.Handlers
internal event ActionRequestedEventHandler ZoomInRequested;
internal event ActionRequestedEventHandler ZoomOutRequested;
internal event ActionRequestedEventHandler ZoomResetRequested;
internal event System.EventHandler<bool> TabPressed;
private int? currentKeyDown = null;
public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int keyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
{
@ -52,8 +55,14 @@ namespace SafeExamBrowser.Browser.Handlers
{
ZoomResetRequested?.Invoke();
}
if (keyCode == (int)Keys.Tab && keyCode == currentKeyDown)
{
TabPressed?.Invoke(this, shift);
}
}
currentKeyDown = null;
return false;
}
@ -66,6 +75,11 @@ namespace SafeExamBrowser.Browser.Handlers
return true;
}
if (type == KeyType.RawKeyDown || type == KeyType.KeyDown)
{
currentKeyDown = keyCode;
}
return false;
}
}

View file

@ -188,6 +188,7 @@ namespace SafeExamBrowser.Client
Browser.ConfigurationDownloadRequested += Browser_ConfigurationDownloadRequested;
Browser.SessionIdentifierDetected += Browser_SessionIdentifierDetected;
Browser.TerminationRequested += Browser_TerminationRequested;
Browser.LoseFocusRequested += Browser_LoseFocusRequested; ;
ClientHost.ExamSelectionRequested += ClientHost_ExamSelectionRequested;
ClientHost.MessageBoxRequested += ClientHost_MessageBoxRequested;
ClientHost.PasswordRequested += ClientHost_PasswordRequested;
@ -198,6 +199,7 @@ namespace SafeExamBrowser.Client
displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged;
runtime.ConnectionLost += Runtime_ConnectionLost;
systemMonitor.SessionSwitched += SystemMonitor_SessionSwitched;
taskbar.LoseFocusRequested += Taskbar_LoseFocusRequested;
taskbar.QuitButtonClicked += Shell_QuitButtonClicked;
foreach (var activator in context.Activators.OfType<ITerminationActivator>())
@ -211,6 +213,16 @@ namespace SafeExamBrowser.Client
}
}
private void Taskbar_LoseFocusRequested(bool forward)
{
this.Browser.Focus(forward);
}
private void Browser_LoseFocusRequested(bool forward)
{
this.taskbar.Focus(forward);
}
private void DeregisterEvents()
{
actionCenter.QuitButtonClicked -= Shell_QuitButtonClicked;

View file

@ -61,6 +61,11 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
/// </summary>
void Destroy();
/// <summary>
/// Executes the given Javascript code in the browser.
/// </summary>
void ExecuteJavascript(string javascript, System.Action<dynamic> callback);
/// <summary>
/// Attempts to find the given term on the current page according to the specified parameters.
/// </summary>

View file

@ -10,6 +10,7 @@ using System;
using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
using SafeExamBrowser.UserInterface.Contracts.Browser.Events;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.Windows;
namespace SafeExamBrowser.UserInterface.Contracts.Browser
@ -64,6 +65,11 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
/// </summary>
event ActionRequestedEventHandler HomeNavigationRequested;
/// <summary>
/// Event fired when the browser window wants to lose focus to the taskbar.
/// </summary>
event LoseFocusRequestedEventHandler LoseFocusRequested;
/// <summary>
/// Event fired when the user would like to reload the current page.
/// </summary>
@ -123,5 +129,16 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
/// Updates the display value of the current page zoom. Value is expected to be in percentage.
/// </summary>
void UpdateZoomLevel(double value);
/// <summary>
/// Sets the focus to the toolbar.
/// </summary>
/// <param name="forward">If true, the first focusable control on the toolbar gets focused. If false, the last one.</param>
void FocusToolbar(bool forward);
/// <summary>
/// Sets the focus to the browser.
/// </summary>
void FocusBrowser();
}
}

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace SafeExamBrowser.UserInterface.Contracts.Events
{
/// <summary>
/// Event handler used to indicate that the user wants to move the focus away from the item.
/// </summary>
public delegate void LoseFocusRequestedEventHandler(bool forward);
}

View file

@ -63,6 +63,7 @@
<Compile Include="Browser\IBrowserControl.cs" />
<Compile Include="Browser\IBrowserWindow.cs" />
<Compile Include="Events\ActionRequestedEventHandler.cs" />
<Compile Include="Events\LoseFocusRequestedEventHandler.cs" />
<Compile Include="FileSystemDialog\FileSystemDialogResult.cs" />
<Compile Include="FileSystemDialog\FileSystemElement.cs" />
<Compile Include="FileSystemDialog\FileSystemOperation.cs" />

View file

@ -7,6 +7,7 @@
*/
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
namespace SafeExamBrowser.UserInterface.Contracts.Shell
@ -31,6 +32,11 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
/// </summary>
event QuitButtonClickedEventHandler QuitButtonClicked;
/// <summary>
/// Event fired when the Taskbar wants to lose focus.
/// </summary>
event LoseFocusRequestedEventHandler LoseFocusRequested;
/// <summary>
/// Adds the given application control to the taskbar.
/// </summary>
@ -70,5 +76,10 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
/// Shows the taskbar.
/// </summary>
void Show();
/// <summary>
/// Puts the focus on the taskbar.
/// </summary>
void Focus(bool forward = true);
}
}

View file

@ -16,11 +16,13 @@ using System.Windows.Interop;
using System.Windows.Media.Imaging;
using SafeExamBrowser.Core.Contracts.Resources.Icons;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
using SafeExamBrowser.UserInterface.Contracts.Browser.Events;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.Windows;
using SafeExamBrowser.UserInterface.Contracts.Windows.Events;
using SafeExamBrowser.UserInterface.Desktop.Controls.Browser;
@ -36,6 +38,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
private WindowClosedEventHandler closed;
private WindowClosingEventHandler closing;
private bool browserControlGetsFocusFromTaskbar = false;
private WindowSettings WindowSettings
{
@ -56,6 +59,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
public event ActionRequestedEventHandler ZoomInRequested;
public event ActionRequestedEventHandler ZoomOutRequested;
public event ActionRequestedEventHandler ZoomResetRequested;
public event LoseFocusRequestedEventHandler LoseFocusRequested;
event WindowClosedEventHandler IWindow.Closed
{
@ -199,6 +203,26 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
}
}
private void BrowserWindow_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Tab && Toolbar.IsKeyboardFocusWithin)
{
if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
{
var firstActiveElementInToolbar = Toolbar.PredictFocus(FocusNavigationDirection.Right);
if (firstActiveElementInToolbar is System.Windows.UIElement)
{
var control = firstActiveElementInToolbar as System.Windows.UIElement;
if (control.IsKeyboardFocusWithin)
{
this.LoseFocusRequested?.Invoke(false);
e.Handled = true;
}
}
}
}
}
private void BrowserWindow_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.F5)
@ -215,6 +239,21 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
{
ShowFindbar();
}
if (e.Key == Key.Tab)
{
if (BrowserControlHost.IsFocused && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
{
if (Findbar.Visibility == Visibility.Hidden || (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
{
Toolbar.Focus();
}
else if (Toolbar.Visibility == Visibility.Hidden)
{
Findbar.Focus();
}
}
}
}
private void BrowserWindow_Loaded(object sender, RoutedEventArgs e)
@ -324,6 +363,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
MenuButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver));
MenuPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
MenuPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver));
KeyDown += BrowserWindow_KeyDown;
KeyUp += BrowserWindow_KeyUp;
LocationChanged += (o, args) => { DownloadsPopup.IsOpen = false; MenuPopup.IsOpen = false; };
ReloadButton.Click += (o, args) => ReloadRequested?.Invoke();
@ -338,6 +378,41 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
ZoomInButton.Click += (o, args) => ZoomInRequested?.Invoke();
ZoomOutButton.Click += (o, args) => ZoomOutRequested?.Invoke();
ZoomResetButton.Click += (o, args) => ZoomResetRequested?.Invoke();
BrowserControlHost.GotKeyboardFocus += BrowserControlHost_GotKeyboardFocus;
}
private void BrowserControlHost_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
var forward = !this.browserControlGetsFocusFromTaskbar;
// focus the first / last element on the page
var javascript = @"
if (typeof __SEB_focusElement === 'undefined') {
__SEB_focusElement = function (forward) {
var items = [].map
.call(document.body.querySelectorAll(['input', 'select', 'a[href]', 'textarea', 'button', '[tabindex]']), function(el, i) { return { el, i } })
.filter(function(e) { return e.el.tabIndex >= 0 && !e.el.disabled && e.el.offsetParent; })
.sort(function(a,b) { return a.el.tabIndex === b.el.tabIndex ? a.i - b.i : (a.el.tabIndex || 9E9) - (b.el.tabIndex || 9E9); })
var item = items[forward ? 1 : items.length - 1];
setTimeout(function () { item.focus(); }, 20);
}
}";
var control = BrowserControlHost.Child as IBrowserControl;
control.ExecuteJavascript(javascript, result =>
{
if (!result.Success)
{
//logger.Error($"Javascript error {result.Message}!");
}
});
control.ExecuteJavascript("__SEB_focusElement(" + forward.ToString().ToLower() + ")", result =>
{
if (!result.Success)
{
//logger.Error($"Javascript error {result.Message}!");
}
});
}
private void ApplySettings()
@ -444,5 +519,42 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
FindMenuText.Text = text.Get(TextKey.BrowserWindow_FindMenuItem);
ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem);
}
public void FocusToolbar(bool forward)
{
this.Dispatcher.BeginInvoke((Action)(async () =>
{
this.Activate();
await Task.Delay(50);
// focus all elements in the toolbar, such that the last element that is enabled gets focus
var buttons = new System.Windows.Controls.Control[] { ForwardButton, BackwardButton, ReloadButton, UrlTextBox, MenuButton, };
for (var i = forward ? 0 : buttons.Length - 1; i >= 0 && i < buttons.Length; i += forward ? 1 : -1)
{
if (buttons[i].IsEnabled && buttons[i].Visibility == Visibility.Visible)
{
buttons[i].Focus();
break;
}
}
}));
}
public void FocusBrowser()
{
this.Dispatcher.BeginInvoke((Action)(async () =>
{
this.FocusToolbar(false);
await Task.Delay(100);
this.browserControlGetsFocusFromTaskbar = true;
var focusedElement = FocusManager.GetFocusedElement(this) as UIElement;
focusedElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
await Task.Delay(150);
this.browserControlGetsFocusFromTaskbar = false;
}));
}
}
}

View file

@ -6,6 +6,7 @@
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar"
xmlns:s="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" Title="Taskbar" Background="{DynamicResource BackgroundBrush}" Height="40" Width="750" WindowStyle="None" Topmost="True"
KeyDown="Window_KeyDown" KeyUp="Window_KeyUp"
ResizeMode="NoResize" Icon="../Images/SafeExamBrowser.ico">
<Window.Resources>
<ResourceDictionary>

View file

@ -6,10 +6,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.ComponentModel;
using System.Windows;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
using SafeExamBrowser.UserInterface.Shared.Utilities;
@ -20,6 +22,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
{
private bool allowClose;
private ILogger logger;
private bool isQuitButtonFocusedAtKeyDown;
private bool isFirstChildFocusedAtKeyDown;
public bool ShowClock
{
@ -31,6 +35,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
set { Dispatcher.Invoke(() => QuitButton.Visibility = value ? Visibility.Visible : Visibility.Collapsed); }
}
public event LoseFocusRequestedEventHandler LoseFocusRequested;
public event QuitButtonClickedEventHandler QuitButtonClicked;
internal Taskbar(ILogger logger)
@ -159,5 +164,82 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
Loaded += (o, args) => InitializeBounds();
QuitButton.Clicked += QuitButton_Clicked;
}
private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
this.isQuitButtonFocusedAtKeyDown = this.QuitButton.IsKeyboardFocusWithin;
this.isFirstChildFocusedAtKeyDown = this.ApplicationStackPanel.Children[0].IsKeyboardFocusWithin;
}
private void Window_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Tab)
{
var shift = System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.LeftShift);
if (!shift && this.ApplicationStackPanel.Children[0].IsKeyboardFocusWithin && this.isQuitButtonFocusedAtKeyDown)
{
this.LoseFocusRequested?.Invoke(true);
e.Handled = true;
}
else if (shift && this.QuitButton.IsKeyboardFocusWithin && this.isFirstChildFocusedAtKeyDown)
{
this.LoseFocusRequested?.Invoke(false);
e.Handled = true;
}
}
this.isQuitButtonFocusedAtKeyDown = false;
this.isFirstChildFocusedAtKeyDown = false;
}
void ITaskbar.Focus(bool forward)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
base.Activate();
if (forward)
{
this.SetFocusWithin(this.ApplicationStackPanel.Children[0]);
}
else
{
this.QuitButton.Focus();
}
}));
}
private bool SetFocusWithin(UIElement uIElement)
{
if (uIElement.Focusable)
{
uIElement.Focus();
return true;
}
if (uIElement is System.Windows.Controls.Panel)
{
var panel = uIElement as System.Windows.Controls.Panel;
for (var i = 0; i < panel.Children.Count; i++)
{
if (this.SetFocusWithin(panel.Children[i]))
{
return true;
}
}
return false;
}
else if (uIElement is System.Windows.Controls.ContentControl)
{
var control = uIElement as System.Windows.Controls.ContentControl;
var content = control.Content as UIElement;
if (content != null)
{
return this.SetFocusWithin(content);
}
}
return false;
}
}
}

View file

@ -21,6 +21,7 @@ using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
using SafeExamBrowser.UserInterface.Contracts.Browser.Events;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.Windows;
using SafeExamBrowser.UserInterface.Contracts.Windows.Events;
using SafeExamBrowser.UserInterface.Mobile.Controls.Browser;
@ -51,6 +52,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows
public event ActionRequestedEventHandler DeveloperConsoleRequested;
public event FindRequestedEventHandler FindRequested;
public event ActionRequestedEventHandler ForwardNavigationRequested;
public event LoseFocusRequestedEventHandler LoseFocusRequested;
public event ActionRequestedEventHandler HomeNavigationRequested;
public event ActionRequestedEventHandler ReloadRequested;
public event ActionRequestedEventHandler ZoomInRequested;
@ -454,5 +456,20 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows
FindMenuText.Text = text.Get(TextKey.BrowserWindow_FindMenuItem);
ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem);
}
public void FocusToolbar(bool forward)
{
throw new NotImplementedException();
}
public void FocusBrowser()
{
throw new NotImplementedException();
}
public void Debug()
{
throw new NotImplementedException();
}
}
}

View file

@ -10,6 +10,7 @@ using System.ComponentModel;
using System.Windows;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Events;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
using SafeExamBrowser.UserInterface.Shared.Utilities;
@ -31,6 +32,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows
set { Dispatcher.Invoke(() => QuitButton.Visibility = value ? Visibility.Visible : Visibility.Collapsed); }
}
public event LoseFocusRequestedEventHandler LoseFocusRequested;
public event QuitButtonClickedEventHandler QuitButtonClicked;
internal Taskbar(ILogger logger)
@ -159,5 +161,18 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows
Loaded += (o, args) => InitializeBounds();
QuitButton.Clicked += QuitButton_Clicked;
}
void ITaskbar.Focus(bool fromTop)
{
base.Activate();
if (fromTop)
{
this.ApplicationStackPanel.Children[0].Focus();
}
else
{
this.QuitButton.Focus();
}
}
}
}