Merge pull request #278 from yolpsoftware/master
Proof-of-concept desktop keyboard navigation
This commit is contained in:
commit
043187f4ec
44 changed files with 764 additions and 46 deletions
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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.Browser.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);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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.Browser.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler used to indicate that the user pressed the tab key to move the focus forward or backward.
|
||||
/// </summary>
|
||||
public delegate void TabPressedEventHandler(bool forward);
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Applications.Contracts;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
|
||||
|
@ -30,5 +31,16 @@ 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.
|
||||
/// <paramref name="forward">If true, the first focusable element in the browser window receives focus (passing forward of focus). Otherwise, the last element.</paramref>
|
||||
/// </summary>
|
||||
void Focus(bool forward);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
<Compile Include="Events\DownloadEventArgs.cs" />
|
||||
<Compile Include="Events\DownloadFinishedCallback.cs" />
|
||||
<Compile Include="Events\DownloadRequestedEventHandler.cs" />
|
||||
<Compile Include="Events\TabPressedEventHandler.cs" />
|
||||
<Compile Include="Events\LoseFocusRequestedEventHandler.cs" />
|
||||
<Compile Include="Events\SessionIdentifierDetectedEventHandler.cs" />
|
||||
<Compile Include="Events\TerminationRequestedEventHandler.cs" />
|
||||
<Compile Include="Filters\IRequestFilter.cs" />
|
||||
|
|
|
@ -58,6 +58,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 +196,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 +459,13 @@ namespace SafeExamBrowser.Browser
|
|||
CreateNewWindow();
|
||||
logger.Info("Successfully reset browser.");
|
||||
}
|
||||
|
||||
public void Focus(bool forward)
|
||||
{
|
||||
windows.ForEach(window =>
|
||||
{
|
||||
window.Focus(forward);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ using SafeExamBrowser.Configuration.Contracts;
|
|||
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Browser;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Browser.Events;
|
||||
|
||||
namespace SafeExamBrowser.Browser
|
||||
|
@ -143,5 +144,19 @@ namespace SafeExamBrowser.Browser
|
|||
{
|
||||
control.BrowserCore.SetZoomLevel(level);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the given Javascript code in the browser.
|
||||
/// </summary>
|
||||
public async void ExecuteJavascript(string javascript, Action<JavascriptResult> callback)
|
||||
{
|
||||
var result = await this.control.EvaluateScriptAsync(javascript);
|
||||
callback(new JavascriptResult()
|
||||
{
|
||||
Message = result.Message,
|
||||
Result = result.Result,
|
||||
Success = result.Success
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,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 +163,8 @@ namespace SafeExamBrowser.Browser
|
|||
keyboardHandler.ZoomInRequested += ZoomInRequested;
|
||||
keyboardHandler.ZoomOutRequested += ZoomOutRequested;
|
||||
keyboardHandler.ZoomResetRequested += ZoomResetRequested;
|
||||
keyboardHandler.TabPressed += TabPressed;
|
||||
keyboardHandler.FocusAddressBarRequested += FocusAddressBarRequested;
|
||||
resourceHandler.SessionIdentifierDetected += (id) => SessionIdentifierDetected?.Invoke(id);
|
||||
requestHandler.QuitUrlVisited += RequestHandler_QuitUrlVisited;
|
||||
requestHandler.RequestBlocked += RequestHandler_RequestBlocked;
|
||||
|
@ -189,7 +192,7 @@ namespace SafeExamBrowser.Browser
|
|||
|
||||
internal void InitializeWindow()
|
||||
{
|
||||
window = uiFactory.CreateBrowserWindow(Control, settings, isMainWindow);
|
||||
window = uiFactory.CreateBrowserWindow(Control, settings, isMainWindow, this.logger);
|
||||
window.AddressChanged += Window_AddressChanged;
|
||||
window.BackwardNavigationRequested += Window_BackwardNavigationRequested;
|
||||
window.Closed += Window_Closed;
|
||||
|
@ -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;
|
||||
|
@ -454,6 +458,11 @@ namespace SafeExamBrowser.Browser
|
|||
}
|
||||
}
|
||||
|
||||
private void FocusAddressBarRequested()
|
||||
{
|
||||
window.FocusAddressBar();
|
||||
}
|
||||
|
||||
private ChromiumHostControl LifeSpanHandler_CreatePopup()
|
||||
{
|
||||
var args = new PopupRequestedEventArgs();
|
||||
|
@ -655,6 +664,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 +702,43 @@ namespace SafeExamBrowser.Browser
|
|||
}
|
||||
}
|
||||
|
||||
private void TabPressed(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;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
using System.Windows.Forms;
|
||||
using CefSharp;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
using SafeExamBrowser.UserInterface.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Browser.Handlers
|
||||
|
@ -20,6 +21,10 @@ namespace SafeExamBrowser.Browser.Handlers
|
|||
internal event ActionRequestedEventHandler ZoomInRequested;
|
||||
internal event ActionRequestedEventHandler ZoomOutRequested;
|
||||
internal event ActionRequestedEventHandler ZoomResetRequested;
|
||||
internal event ActionRequestedEventHandler FocusAddressBarRequested;
|
||||
internal event TabPressedEventHandler TabPressed;
|
||||
|
||||
private int? currentKeyDown = null;
|
||||
|
||||
public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int keyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
|
||||
{
|
||||
|
@ -38,6 +43,11 @@ namespace SafeExamBrowser.Browser.Handlers
|
|||
HomeNavigationRequested?.Invoke();
|
||||
}
|
||||
|
||||
if (ctrl && keyCode == (int) Keys.L)
|
||||
{
|
||||
FocusAddressBarRequested?.Invoke();
|
||||
}
|
||||
|
||||
if ((ctrl && keyCode == (int) Keys.Add) || (ctrl && keyCode == (int) Keys.Oemplus) || (ctrl && shift && keyCode == (int) Keys.D1))
|
||||
{
|
||||
ZoomInRequested?.Invoke();
|
||||
|
@ -52,8 +62,14 @@ namespace SafeExamBrowser.Browser.Handlers
|
|||
{
|
||||
ZoomResetRequested?.Invoke();
|
||||
}
|
||||
|
||||
if (keyCode == (int)Keys.Tab && keyCode == currentKeyDown)
|
||||
{
|
||||
TabPressed?.Invoke(shift);
|
||||
}
|
||||
}
|
||||
|
||||
currentKeyDown = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -66,6 +82,11 @@ namespace SafeExamBrowser.Browser.Handlers
|
|||
return true;
|
||||
}
|
||||
|
||||
if (type == KeyType.RawKeyDown || type == KeyType.KeyDown)
|
||||
{
|
||||
currentKeyDown = keyCode;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -226,6 +238,7 @@ namespace SafeExamBrowser.Client
|
|||
Browser.ConfigurationDownloadRequested -= Browser_ConfigurationDownloadRequested;
|
||||
Browser.SessionIdentifierDetected -= Browser_SessionIdentifierDetected;
|
||||
Browser.TerminationRequested -= Browser_TerminationRequested;
|
||||
Browser.LoseFocusRequested -= Browser_LoseFocusRequested;
|
||||
}
|
||||
|
||||
if (ClientHost != null)
|
||||
|
|
|
@ -24,12 +24,19 @@ namespace SafeExamBrowser.I18n.Contracts
|
|||
Browser_LoadErrorTitle,
|
||||
Browser_Name,
|
||||
Browser_Tooltip,
|
||||
BrowserWindow_BackwardButton,
|
||||
BrowserWindow_DeveloperConsoleMenuItem,
|
||||
BrowserWindow_Downloading,
|
||||
BrowserWindow_DownloadCancelled,
|
||||
BrowserWindow_DownloadComplete,
|
||||
BrowserWindow_DownloadsButton,
|
||||
BrowserWindow_FindCaseSensitive,
|
||||
BrowserWindow_FindMenuItem,
|
||||
BrowserWindow_ForwardButton,
|
||||
BrowserWindow_HomeButton,
|
||||
BrowserWindow_MenuButton,
|
||||
BrowserWindow_ReloadButton,
|
||||
BrowserWindow_UrlTextBox,
|
||||
BrowserWindow_ZoomMenuItem,
|
||||
Build,
|
||||
ExamSelectionDialog_Cancel,
|
||||
|
|
|
@ -48,6 +48,27 @@
|
|||
<Entry key="BrowserWindow_FindMenuItem">
|
||||
Seite durchsuchen...
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ReloadButton">
|
||||
Neu laden
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_BackwardButton">
|
||||
Rückwärts
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ForwardButton">
|
||||
Vorwärts
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_DownloadsButton">
|
||||
Download
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_HomeButton">
|
||||
Home
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_MenuButton">
|
||||
Menü
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_UrlTextBox">
|
||||
URL eingeben
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ZoomMenuItem">
|
||||
Seiten-Zoom
|
||||
</Entry>
|
||||
|
|
|
@ -48,6 +48,27 @@
|
|||
<Entry key="BrowserWindow_FindMenuItem">
|
||||
Search page...
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ReloadButton">
|
||||
Reload
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_BackwardButton">
|
||||
Backward
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ForwardButton">
|
||||
Forward
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_DownloadsButton">
|
||||
Download
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_HomeButton">
|
||||
Home
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_MenuButton">
|
||||
Menu
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_UrlTextBox">
|
||||
Enter URL
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ZoomMenuItem">
|
||||
Page Zoom
|
||||
</Entry>
|
||||
|
|
|
@ -48,6 +48,27 @@
|
|||
<Entry key="BrowserWindow_FindMenuItem">
|
||||
Rechercher dans la page...
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ReloadButton">
|
||||
Recharger
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_BackwardButton">
|
||||
En arrière
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ForwardButton">
|
||||
Avant
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_DownloadsButton">
|
||||
Télécharger
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_HomeButton">
|
||||
Accueil
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_MenuButton">
|
||||
Menu
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_UrlTextBox">
|
||||
Entrer l'URL
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ZoomMenuItem">
|
||||
Zoom de la page
|
||||
</Entry>
|
||||
|
|
|
@ -48,6 +48,27 @@
|
|||
<Entry key="BrowserWindow_FindMenuItem">
|
||||
Pagina di ricerca ...
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ReloadButton">
|
||||
Ricarica
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_BackwardButton">
|
||||
Indietro
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ForwardButton">
|
||||
Avanti
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_DownloadsButton">
|
||||
Scaricare
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_HomeButton">
|
||||
Home
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_MenuButton">
|
||||
Menu
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_UrlTextBox">
|
||||
Inserisci URL
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ZoomMenuItem">
|
||||
Zoom della pagina
|
||||
</Entry>
|
||||
|
|
|
@ -45,6 +45,27 @@
|
|||
<Entry key="BrowserWindow_DownloadComplete">
|
||||
下载完成
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ReloadButton">
|
||||
重新加载
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_BackwardButton">
|
||||
向后
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ForwardButton">
|
||||
前进
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_DownloadsButton">
|
||||
下载
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_HomeButton">
|
||||
首页
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_MenuButton">
|
||||
菜单
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_UrlTextBox">
|
||||
输入网址
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_ZoomMenuItem">
|
||||
页面缩放
|
||||
</Entry>
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Contracts.Browser.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// The data resulting from a Javascript expression evaluation.
|
||||
/// </summary>
|
||||
public class JavascriptResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates if the Javascript was evaluated successfully or not.
|
||||
/// </summary>
|
||||
public bool Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The error message, in case of an unsuccessful evaluation of the Javascript expression.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The data item returned by the Javascript expression.
|
||||
/// </summary>
|
||||
public dynamic Result { get; set; }
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Browser.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Contracts.Browser
|
||||
|
@ -61,6 +62,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<JavascriptResult> callback);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find the given term on the current page according to the specified parameters.
|
||||
/// </summary>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
using SafeExamBrowser.Core.Contracts.Resources.Icons;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Browser.Events;
|
||||
|
@ -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,18 @@ 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();
|
||||
|
||||
void FocusAddressBar();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace SafeExamBrowser.UserInterface.Contracts
|
|||
/// <summary>
|
||||
/// Creates a new browser window loaded with the given browser control and settings.
|
||||
/// </summary>
|
||||
IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow);
|
||||
IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow, ILogger logger);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an exam selection dialog for the given exams.
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Browser\Data\DownloadItemState.cs" />
|
||||
<Compile Include="Browser\Data\JavascriptResult.cs" />
|
||||
<Compile Include="Browser\Events\AddressChangedEventHandler.cs" />
|
||||
<Compile Include="Browser\Events\FindRequestedEventHandler.cs" />
|
||||
<Compile Include="Browser\Events\LoadFailedEventHandler.cs" />
|
||||
|
@ -110,6 +111,10 @@
|
|||
<Project>{ac77745d-3b41-43e2-8e84-d40e5a4ee77f}</Project>
|
||||
<Name>SafeExamBrowser.Applications.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Browser.Contracts\SafeExamBrowser.Browser.Contracts.csproj">
|
||||
<Project>{5fb5273d-277c-41dd-8593-a25ce1aff2e9}</Project>
|
||||
<Name>SafeExamBrowser.Browser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Configuration.Contracts\SafeExamBrowser.Configuration.Contracts.csproj">
|
||||
<Project>{7d74555e-63e1-4c46-bd0a-8580552368c8}</Project>
|
||||
<Name>SafeExamBrowser.Configuration.Contracts</Name>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="250">
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="250" IsTabStop="True">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid x:Name="Grid" Background="{StaticResource ActionCenterDarkBrush}" Height="64" Margin="2">
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}" KeyUp="Popup_KeyUp">
|
||||
<Border Background="Gray">
|
||||
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="LayoutsStackPanel" />
|
||||
|
|
|
@ -41,7 +41,14 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
|
|||
InitializeLayouts();
|
||||
|
||||
keyboard.LayoutChanged += Keyboard_LayoutChanged;
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.Click += (o, args) =>
|
||||
{
|
||||
Popup.IsOpen = !Popup.IsOpen;
|
||||
this.Dispatcher.BeginInvoke((System.Action)(() =>
|
||||
{
|
||||
LayoutsStackPanel.Children[0].Focus();
|
||||
}));
|
||||
};
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
||||
|
@ -90,5 +97,14 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
|
|||
Text.Text = layout.CultureName;
|
||||
Button.ToolTip = tooltip;
|
||||
}
|
||||
|
||||
private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Enter || e.Key == System.Windows.Input.Key.Escape)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
Button.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}" KeyDown="Popup_KeyDown">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="1,1,1,0">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Name="AudioDeviceName" Margin="5" TextAlignment="Center" />
|
||||
|
@ -24,7 +24,7 @@
|
|||
<Button x:Name="MuteButton" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" Width="40">
|
||||
<ContentControl x:Name="PopupIcon" />
|
||||
</Button>
|
||||
<Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True"
|
||||
<Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" KeyDown="Volume_KeyDown"
|
||||
IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="250" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted" />
|
||||
<TextBlock Grid.Column="2" FontWeight="DemiBold" FontSize="16" Text="{Binding ElementName=Volume, Path=Value}"
|
||||
TextAlignment="Center" VerticalAlignment="Center" Width="40" />
|
||||
|
@ -33,7 +33,7 @@
|
|||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True" Width="40">
|
||||
<ContentControl x:Name="ButtonIcon" />
|
||||
<ContentControl x:Name="ButtonIcon" Focusable="False" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
|
|||
{
|
||||
Background = Brushes.LightGray;
|
||||
Button.Background = Brushes.LightGray;
|
||||
Volume.Focus();
|
||||
};
|
||||
|
||||
Popup.Closed += (o, args) =>
|
||||
|
@ -167,5 +168,23 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
|
|||
|
||||
return IconResourceLoader.Load(resource);
|
||||
}
|
||||
|
||||
private void Popup_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Escape)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
Button.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void Volume_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Enter)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
Button.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" />
|
||||
<TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" HorizontalAlignment="Center" VerticalAlignment="Top" />
|
||||
<TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" Focusable="True" AutomationProperties.HelpText="{Binding Path=Time}" />
|
||||
<TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" HorizontalAlignment="Center" VerticalAlignment="Top" Focusable="True" AutomationProperties.HelpText="{Binding Path=Date}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -14,24 +14,22 @@
|
|||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Height="40" Padding="10,0" Template="{StaticResource TaskbarButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="IsCurrentTextBlock" Grid.Column="0" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden">•</TextBlock>
|
||||
<TextBlock x:Name="CultureCodeTextBlock" Grid.Column="1" FontWeight="Bold" HorizontalAlignment="Left" Margin="10,0,5,0" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="2" VerticalAlignment="Center">
|
||||
<TextBlock x:Name="CultureNameTextBlock" HorizontalAlignment="Left" Margin="5,0,10,0" TextDecorations="Underline" VerticalAlignment="Center" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<fa:ImageAwesome Foreground="Gray" Height="10" Icon="KeyboardOutline" Margin="5,0" />
|
||||
<TextBlock x:Name="LayoutNameTextBlock" Foreground="Gray" HorizontalAlignment="Left" Margin="0,0,10,0" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<Button x:Name="Button" Background="Transparent" Height="40" Padding="10,0" Template="{StaticResource TaskbarButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="IsCurrentTextBlock" Grid.Column="0" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden">•</TextBlock>
|
||||
<TextBlock x:Name="CultureCodeTextBlock" Grid.Column="1" FontWeight="Bold" HorizontalAlignment="Left" Margin="10,0,5,0" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="2" VerticalAlignment="Center">
|
||||
<TextBlock x:Name="CultureNameTextBlock" HorizontalAlignment="Left" Margin="5,0,10,0" TextDecorations="Underline" VerticalAlignment="Center" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<fa:ImageAwesome Foreground="Gray" Height="10" Icon="KeyboardOutline" Margin="5,0" />
|
||||
<TextBlock x:Name="LayoutNameTextBlock" Foreground="Gray" HorizontalAlignment="Left" Margin="0,0,10,0" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Button>
|
||||
</UserControl>
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
|
|||
CultureCodeTextBlock.Text = layout.CultureCode;
|
||||
CultureNameTextBlock.Text = layout.CultureName;
|
||||
LayoutNameTextBlock.Text = layout.LayoutName;
|
||||
System.Windows.Automation.AutomationProperties.SetHelpText(Button, layout.LayoutName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Custom" PlacementTarget="{Binding ElementName=Button}" KeyUp="Popup_KeyUp">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="1,1,1,0">
|
||||
<ScrollViewer x:Name="LayoutsScrollViewer" MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="LayoutsStackPanel" />
|
||||
|
|
|
@ -45,7 +45,14 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
|
|||
InitializeLayouts();
|
||||
|
||||
keyboard.LayoutChanged += Keyboard_LayoutChanged;
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.Click += (o, args) =>
|
||||
{
|
||||
Popup.IsOpen = !Popup.IsOpen;
|
||||
Task.Delay(200).ContinueWith(_ => this.Dispatcher.BeginInvoke((System.Action)(() =>
|
||||
{
|
||||
((LayoutsStackPanel.Children[0] as ContentControl).Content as UIElement).Focus();
|
||||
})));
|
||||
};
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
|
@ -114,5 +121,14 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
|
|||
LayoutCultureCode.Text = layout.CultureCode;
|
||||
Button.ToolTip = tooltip;
|
||||
}
|
||||
|
||||
private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Enter || e.Key == System.Windows.Input.Key.Escape)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
Button.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="40">
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="40" Focusable="true" IsTabStop="True">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Automation;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
|
@ -101,6 +102,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
|
|||
Button.ToolTip = tooltip;
|
||||
PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed;
|
||||
Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
|
||||
AutomationProperties.SetHelpText(this, Button.ToolTip as string);
|
||||
}
|
||||
|
||||
private void RenderCharge(double charge, BatteryChargeStatus status)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
x:Name="root"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="40">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
|
@ -15,6 +16,7 @@
|
|||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Click="Button_Click" Background="{StaticResource BackgroundBrush}" HorizontalAlignment="Stretch"
|
||||
Template="{StaticResource TaskbarButton}" VerticalAlignment="Stretch" />
|
||||
Template="{StaticResource TaskbarButton}" VerticalAlignment="Stretch"
|
||||
AutomationProperties.Name="{Binding Path=(AutomationProperties.Name), ElementName=root}"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -509,6 +509,14 @@
|
|||
<Project>{ac77745d-3b41-43e2-8e84-d40e5a4ee77f}</Project>
|
||||
<Name>SafeExamBrowser.Applications.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Browser.Contracts\SafeExamBrowser.Browser.Contracts.csproj">
|
||||
<Project>{5fb5273d-277c-41dd-8593-a25ce1aff2e9}</Project>
|
||||
<Name>SafeExamBrowser.Browser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Browser\SafeExamBrowser.Browser.csproj">
|
||||
<Project>{04e653f1-98e6-4e34-9dd7-7f2bc1a8b767}</Project>
|
||||
<Name>SafeExamBrowser.Browser</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Configuration.Contracts\SafeExamBrowser.Configuration.Contracts.csproj">
|
||||
<Project>{7d74555e-63e1-4c46-bd0a-8580552368c8}</Project>
|
||||
<Name>SafeExamBrowser.Configuration.Contracts</Name>
|
||||
|
|
|
@ -80,9 +80,9 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
}
|
||||
}
|
||||
|
||||
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow)
|
||||
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow, ILogger logger)
|
||||
{
|
||||
return Application.Current.Dispatcher.Invoke(() => new BrowserWindow(control, settings, isMainWindow, text));
|
||||
return Application.Current.Dispatcher.Invoke(() => new BrowserWindow(control, settings, isMainWindow, text, logger));
|
||||
}
|
||||
|
||||
public IExamSelectionDialog CreateExamSelectionDialog(IEnumerable<Exam> exams)
|
||||
|
|
|
@ -62,15 +62,15 @@
|
|||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" x:Name="ZoomText" HorizontalAlignment="Left" Margin="10,0" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" x:Name="ZoomInButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<Button Grid.Column="1" x:Name="ZoomInButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}" TabIndex="30">
|
||||
<fa:ImageAwesome Icon="SearchPlus" />
|
||||
</Button>
|
||||
<Button Grid.Column="2" x:Name="ZoomResetButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<Button Grid.Column="2" x:Name="ZoomResetButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}" TabIndex="31">
|
||||
<Viewbox Stretch="Uniform">
|
||||
<TextBlock x:Name="ZoomLevel" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button Grid.Column="3" x:Name="ZoomOutButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<Button Grid.Column="3" x:Name="ZoomOutButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}" TabIndex="32">
|
||||
<fa:ImageAwesome Icon="SearchMinus" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
@ -80,7 +80,7 @@
|
|||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" x:Name="FindMenuText" HorizontalAlignment="Left" Margin="10,0" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" x:Name="FindMenuButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<Button Grid.Column="1" x:Name="FindMenuButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}" TabIndex="33">
|
||||
<fa:ImageAwesome Icon="Search" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
@ -90,7 +90,7 @@
|
|||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" x:Name="DeveloperConsoleText" HorizontalAlignment="Left" Margin="10,0" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" x:Name="DeveloperConsoleButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<Button Grid.Column="1" x:Name="DeveloperConsoleButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}" TabIndex="34">
|
||||
<fa:ImageAwesome Icon="Wrench" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
|
|
@ -8,14 +8,17 @@
|
|||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
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;
|
||||
|
@ -33,9 +36,13 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
|||
private readonly bool isMainWindow;
|
||||
private readonly BrowserSettings settings;
|
||||
private readonly IText text;
|
||||
private readonly ILogger logger;
|
||||
private readonly IBrowserControl browserControl;
|
||||
|
||||
private WindowClosedEventHandler closed;
|
||||
private WindowClosingEventHandler closing;
|
||||
private bool browserControlGetsFocusFromTaskbar = false;
|
||||
private IInputElement tabKeyDownFocusElement = null;
|
||||
|
||||
private WindowSettings WindowSettings
|
||||
{
|
||||
|
@ -56,6 +63,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
|
||||
{
|
||||
|
@ -69,11 +77,13 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
|||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
internal BrowserWindow(IBrowserControl browserControl, BrowserSettings settings, bool isMainWindow, IText text)
|
||||
internal BrowserWindow(IBrowserControl browserControl, BrowserSettings settings, bool isMainWindow, IText text, ILogger logger)
|
||||
{
|
||||
this.isMainWindow = isMainWindow;
|
||||
this.settings = settings;
|
||||
this.text = text;
|
||||
this.logger = logger;
|
||||
this.browserControl = browserControl;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeBrowserWindow(browserControl);
|
||||
|
@ -199,6 +209,33 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
|||
}
|
||||
}
|
||||
|
||||
private void BrowserWindow_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Tab)
|
||||
{
|
||||
var hasShift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
|
||||
if (Toolbar.IsKeyboardFocusWithin && hasShift)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tabKeyDownFocusElement = FocusManager.GetFocusedElement(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
tabKeyDownFocusElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void BrowserWindow_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.F5)
|
||||
|
@ -215,6 +252,65 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
|||
{
|
||||
ShowFindbar();
|
||||
}
|
||||
|
||||
if (e.Key == Key.Tab)
|
||||
{
|
||||
var hasCtrl = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
|
||||
var hasShift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
|
||||
if (BrowserControlHost.IsFocused && hasCtrl)
|
||||
{
|
||||
if (Findbar.Visibility == Visibility.Hidden || hasShift)
|
||||
{
|
||||
Toolbar.Focus();
|
||||
}
|
||||
else if (Toolbar.Visibility == Visibility.Hidden)
|
||||
{
|
||||
Findbar.Focus();
|
||||
}
|
||||
}
|
||||
else if (MenuPopup.IsKeyboardFocusWithin)
|
||||
{
|
||||
var focusedElement = FocusManager.GetFocusedElement(this);
|
||||
var focusedControl = focusedElement as System.Windows.Controls.Control;
|
||||
var prevFocusedControl = tabKeyDownFocusElement as System.Windows.Controls.Control;
|
||||
if (focusedControl != null && prevFocusedControl != null)
|
||||
{
|
||||
//var commonAncestor = focusedControl.FindCommonVisualAncestor(prevFocusedControl);
|
||||
//var nextTab = GetNextTab(MenuPopup, this, true);
|
||||
if (!hasShift && focusedControl.TabIndex < prevFocusedControl.TabIndex)
|
||||
{
|
||||
MenuPopup.IsOpen = false;
|
||||
FocusBrowser();
|
||||
}
|
||||
else if (hasShift && focusedControl.TabIndex > prevFocusedControl.TabIndex)
|
||||
{
|
||||
MenuPopup.IsOpen = false;
|
||||
MenuButton.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get next tab order element. Copied from https://stackoverflow.com/questions/5756448/in-wpf-how-can-i-get-the-next-control-in-the-tab-order
|
||||
/// </summary>
|
||||
/// <param name="e">The element to get next tab order</param>
|
||||
/// <param name="container">The container element owning 'e'. Make sure this is a container of 'e'.</param>
|
||||
/// <param name="goDownOnly">True if search only itself and inside of 'container'; otherwise false.
|
||||
/// If true and next tab order element is outside of 'container', result in null.</param>
|
||||
/// <returns>Next tab order element or null if not found</returns>
|
||||
public DependencyObject GetNextTab(DependencyObject e, DependencyObject container, bool goDownOnly)
|
||||
{
|
||||
var navigation = typeof(FrameworkElement)
|
||||
.GetProperty("KeyboardNavigation", BindingFlags.NonPublic | BindingFlags.Static)
|
||||
.GetValue(null);
|
||||
|
||||
var method = navigation
|
||||
.GetType()
|
||||
.GetMethod("GetNextTab", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
return method.Invoke(navigation, new object[] { e, container, goDownOnly }) as DependencyObject;
|
||||
}
|
||||
|
||||
private void BrowserWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
|
@ -320,10 +416,11 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
|||
ForwardButton.Click += (o, args) => ForwardNavigationRequested?.Invoke();
|
||||
HomeButton.Click += (o, args) => HomeNavigationRequested?.Invoke();
|
||||
Loaded += BrowserWindow_Loaded;
|
||||
MenuButton.Click += (o, args) => MenuPopup.IsOpen = !MenuPopup.IsOpen;
|
||||
MenuButton.Click += MenuButton_Click;
|
||||
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 +435,48 @@ 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 MenuButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MenuPopup.IsOpen = !MenuPopup.IsOpen;
|
||||
ZoomInButton.Focus();
|
||||
}
|
||||
|
||||
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];
|
||||
if (item && item.focus && typeof item.focus !== 'function')
|
||||
throw ('item.focus is not a function, ' + typeof item.focus)
|
||||
setTimeout(function () { item && item.focus && item.focus(); }, 20);
|
||||
}
|
||||
}";
|
||||
this.browserControl.ExecuteJavascript(javascript, result =>
|
||||
{
|
||||
if (!result.Success)
|
||||
{
|
||||
logger.Error($"Javascript error {result.Message}!");
|
||||
}
|
||||
});
|
||||
|
||||
this.browserControl.ExecuteJavascript("__SEB_focusElement(" + forward.ToString().ToLower() + ")", result =>
|
||||
{
|
||||
if (!result.Success)
|
||||
{
|
||||
logger.Error($"Javascript error {result.Message}!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void ApplySettings()
|
||||
|
@ -443,6 +582,58 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
|||
FindCaseSensitiveCheckBox.Content = text.Get(TextKey.BrowserWindow_FindCaseSensitive);
|
||||
FindMenuText.Text = text.Get(TextKey.BrowserWindow_FindMenuItem);
|
||||
ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem);
|
||||
ReloadButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ReloadButton));
|
||||
BackwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_BackwardButton));
|
||||
ForwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ForwardButton));
|
||||
DownloadsButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_DownloadsButton));
|
||||
HomeButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_HomeButton));
|
||||
MenuButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_MenuButton));
|
||||
UrlTextBox.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_UrlTextBox));
|
||||
}
|
||||
|
||||
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;
|
||||
}));
|
||||
}
|
||||
|
||||
public void FocusAddressBar()
|
||||
{
|
||||
this.Dispatcher.BeginInvoke((Action)(async () =>
|
||||
{
|
||||
this.UrlTextBox.Focus();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -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)
|
||||
|
@ -120,7 +125,9 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows
|
|||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
QuitButton.ToolTip = text.Get(TextKey.Shell_QuitButton);
|
||||
var txt = text.Get(TextKey.Shell_QuitButton);
|
||||
QuitButton.ToolTip = txt;
|
||||
QuitButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, txt);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -159,5 +166,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,6 +207,10 @@
|
|||
<Project>{ac77745d-3b41-43e2-8e84-d40e5a4ee77f}</Project>
|
||||
<Name>SafeExamBrowser.Applications.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Browser.Contracts\SafeExamBrowser.Browser.Contracts.csproj">
|
||||
<Project>{5fb5273d-277c-41dd-8593-a25ce1aff2e9}</Project>
|
||||
<Name>SafeExamBrowser.Browser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Configuration.Contracts\SafeExamBrowser.Configuration.Contracts.csproj">
|
||||
<Project>{7d74555e-63e1-4c46-bd0a-8580552368c8}</Project>
|
||||
<Name>SafeExamBrowser.Configuration.Contracts</Name>
|
||||
|
|
|
@ -80,9 +80,9 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
}
|
||||
}
|
||||
|
||||
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow)
|
||||
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow, ILogger logger)
|
||||
{
|
||||
return Application.Current.Dispatcher.Invoke(() => new BrowserWindow(control, settings, isMainWindow, text));
|
||||
return Application.Current.Dispatcher.Invoke(() => new BrowserWindow(control, settings, isMainWindow, text, logger));
|
||||
}
|
||||
|
||||
public IExamSelectionDialog CreateExamSelectionDialog(IEnumerable<Exam> exams)
|
||||
|
|
|
@ -14,8 +14,10 @@ using System.Windows.Controls.Primitives;
|
|||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
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;
|
||||
|
@ -36,6 +38,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows
|
|||
|
||||
private WindowClosedEventHandler closed;
|
||||
private WindowClosingEventHandler closing;
|
||||
private ILogger logger;
|
||||
|
||||
private WindowSettings WindowSettings
|
||||
{
|
||||
|
@ -51,6 +54,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;
|
||||
|
@ -69,11 +73,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows
|
|||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
internal BrowserWindow(IBrowserControl browserControl, BrowserSettings settings, bool isMainWindow, IText text)
|
||||
internal BrowserWindow(IBrowserControl browserControl, BrowserSettings settings, bool isMainWindow, IText text, ILogger logger)
|
||||
{
|
||||
this.isMainWindow = isMainWindow;
|
||||
this.settings = settings;
|
||||
this.text = text;
|
||||
this.logger = logger;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeBrowserWindow(browserControl);
|
||||
|
@ -454,5 +459,25 @@ 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();
|
||||
}
|
||||
|
||||
public void FocusAddressBar()
|
||||
{
|
||||
this.UrlTextBox.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue