SEBWIN-141: Basic draft of action center including keyboard and touch activators.
This commit is contained in:
parent
04641b9bc7
commit
d99d46d086
80 changed files with 978 additions and 191 deletions
|
@ -19,7 +19,7 @@ using SafeExamBrowser.Contracts.I18n;
|
|||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using BrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.BrowserSettings;
|
||||
|
||||
namespace SafeExamBrowser.Browser
|
||||
|
|
|
@ -24,7 +24,7 @@ using SafeExamBrowser.Contracts.Logging;
|
|||
using SafeExamBrowser.Contracts.Monitoring;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.WindowsApi;
|
||||
|
||||
|
@ -34,6 +34,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
public class ClientControllerTests
|
||||
{
|
||||
private AppConfig appConfig;
|
||||
private Mock<IActionCenter> actionCenter;
|
||||
private Mock<IBrowserApplicationController> browserController;
|
||||
private Mock<IClientHost> clientHost;
|
||||
private Mock<IDisplayMonitor> displayMonitor;
|
||||
|
@ -58,6 +59,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
public void Initialize()
|
||||
{
|
||||
appConfig = new AppConfig();
|
||||
actionCenter = new Mock<IActionCenter>();
|
||||
browserController = new Mock<IBrowserApplicationController>();
|
||||
clientHost = new Mock<IClientHost>();
|
||||
displayMonitor = new Mock<IDisplayMonitor>();
|
||||
|
@ -81,6 +83,7 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
uiFactory.Setup(u => u.CreateSplashScreen(It.IsAny<AppConfig>())).Returns(new Mock<ISplashScreen>().Object);
|
||||
|
||||
sut = new ClientController(
|
||||
actionCenter.Object,
|
||||
displayMonitor.Object,
|
||||
explorerShell.Object,
|
||||
hashAlgorithm.Object,
|
||||
|
@ -632,6 +635,21 @@ namespace SafeExamBrowser.Client.UnitTests
|
|||
splashScreen.VerifySet(s => s.AppConfig = appConfig, Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Startup_MustCorrectlyHandleTaskbar()
|
||||
{
|
||||
operationSequence.Setup(o => o.TryPerform()).Returns(OperationResult.Success);
|
||||
sut.TryStart();
|
||||
|
||||
taskbar.Verify(t => t.Show(), Times.Once);
|
||||
|
||||
taskbar.Reset();
|
||||
operationSequence.Setup(o => o.TryPerform()).Returns(OperationResult.Aborted);
|
||||
sut.TryStart();
|
||||
|
||||
taskbar.Verify(t => t.Show(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WindowMonitor_MustHandleAllowedWindowChangeCorrectly()
|
||||
{
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Notifications
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ using SafeExamBrowser.Client.Operations;
|
|||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@ using Moq;
|
|||
using SafeExamBrowser.Client.Operations;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.Monitoring;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ using SafeExamBrowser.Contracts.I18n;
|
|||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||
{
|
||||
|
@ -33,7 +33,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
private Mock<ISystemComponent<ISystemWirelessNetworkControl>> wirelessNetworkMock;
|
||||
private Mock<ISystemInfo> systemInfoMock;
|
||||
private Mock<ITaskbar> taskbarMock;
|
||||
private Mock<IText> textMock;
|
||||
private Mock<IUserInterfaceFactory> uiFactoryMock;
|
||||
|
||||
private TaskbarOperation sut;
|
||||
|
@ -52,7 +51,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
systemInfoMock = new Mock<ISystemInfo>();
|
||||
taskbarMock = new Mock<ITaskbar>();
|
||||
settings = new TaskbarSettings();
|
||||
textMock = new Mock<IText>();
|
||||
uiFactoryMock = new Mock<IUserInterfaceFactory>();
|
||||
|
||||
settings.AllowApplicationLog = true;
|
||||
|
@ -73,7 +71,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
systemInfoMock.Object,
|
||||
taskbarMock.Object,
|
||||
settings,
|
||||
textMock.Object,
|
||||
uiFactoryMock.Object);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,12 +62,7 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
var success = instances.ClientController.TryStart();
|
||||
|
||||
if (success)
|
||||
{
|
||||
MainWindow = instances.Taskbar;
|
||||
MainWindow.Show();
|
||||
}
|
||||
else
|
||||
if (!success)
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ using SafeExamBrowser.Contracts.Logging;
|
|||
using SafeExamBrowser.Contracts.Monitoring;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.WindowsApi;
|
||||
|
||||
|
@ -32,6 +32,7 @@ namespace SafeExamBrowser.Client
|
|||
{
|
||||
internal class ClientController : IClientController
|
||||
{
|
||||
private IActionCenter actionCenter;
|
||||
private IDisplayMonitor displayMonitor;
|
||||
private IExplorerShell explorerShell;
|
||||
private IHashAlgorithm hashAlgorithm;
|
||||
|
@ -67,6 +68,7 @@ namespace SafeExamBrowser.Client
|
|||
}
|
||||
|
||||
public ClientController(
|
||||
IActionCenter actionCenter,
|
||||
IDisplayMonitor displayMonitor,
|
||||
IExplorerShell explorerShell,
|
||||
IHashAlgorithm hashAlgorithm,
|
||||
|
@ -81,6 +83,7 @@ namespace SafeExamBrowser.Client
|
|||
IUserInterfaceFactory uiFactory,
|
||||
IWindowMonitor windowMonitor)
|
||||
{
|
||||
this.actionCenter = actionCenter;
|
||||
this.displayMonitor = displayMonitor;
|
||||
this.explorerShell = explorerShell;
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
|
@ -109,14 +112,13 @@ namespace SafeExamBrowser.Client
|
|||
if (success)
|
||||
{
|
||||
RegisterEvents();
|
||||
ShowShell();
|
||||
StartBrowser();
|
||||
|
||||
var communication = runtime.InformClientReady();
|
||||
|
||||
if (communication.Success)
|
||||
{
|
||||
splashScreen.Close();
|
||||
|
||||
logger.Info("Application successfully initialized.");
|
||||
logger.Log(string.Empty);
|
||||
}
|
||||
|
@ -132,6 +134,8 @@ namespace SafeExamBrowser.Client
|
|||
logger.Log(string.Empty);
|
||||
}
|
||||
|
||||
splashScreen.Close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -141,7 +145,8 @@ namespace SafeExamBrowser.Client
|
|||
logger.Info("Initiating shutdown procedure...");
|
||||
|
||||
splashScreen = uiFactory.CreateSplashScreen(appConfig);
|
||||
splashScreen.Show();
|
||||
actionCenter.Close();
|
||||
taskbar.Close();
|
||||
|
||||
DeregisterEvents();
|
||||
|
||||
|
@ -197,6 +202,14 @@ namespace SafeExamBrowser.Client
|
|||
}
|
||||
}
|
||||
|
||||
private void ShowShell()
|
||||
{
|
||||
if (Settings.Taskbar.EnableTaskbar)
|
||||
{
|
||||
taskbar.Show();
|
||||
}
|
||||
}
|
||||
|
||||
private void StartBrowser()
|
||||
{
|
||||
logger.Info("Starting browser application...");
|
||||
|
@ -321,7 +334,6 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
private void ClientHost_Shutdown()
|
||||
{
|
||||
taskbar.Close();
|
||||
shutdown.Invoke();
|
||||
}
|
||||
|
||||
|
@ -363,7 +375,6 @@ namespace SafeExamBrowser.Client
|
|||
logger.Error("Lost connection to the runtime!");
|
||||
messageBox.Show(TextKey.MessageBox_ApplicationError, TextKey.MessageBox_ApplicationErrorTitle, icon: MessageBoxIcon.Error);
|
||||
|
||||
taskbar.Close();
|
||||
shutdown.Invoke();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ using SafeExamBrowser.Contracts.Monitoring;
|
|||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.WindowsApi;
|
||||
using SafeExamBrowser.Core.OperationModel;
|
||||
using SafeExamBrowser.Core.Operations;
|
||||
|
@ -48,27 +49,31 @@ namespace SafeExamBrowser.Client
|
|||
{
|
||||
internal class CompositionRoot
|
||||
{
|
||||
private ClientConfiguration configuration;
|
||||
private string logFilePath;
|
||||
private LogLevel logLevel;
|
||||
private string runtimeHostUri;
|
||||
private Guid startupToken;
|
||||
|
||||
private IActionCenter actionCenter;
|
||||
private IBrowserApplicationController browserController;
|
||||
private ClientConfiguration configuration;
|
||||
private IClientHost clientHost;
|
||||
private ILogger logger;
|
||||
private IMessageBox messageBox;
|
||||
private IProcessMonitor processMonitor;
|
||||
private INativeMethods nativeMethods;
|
||||
private IRuntimeProxy runtimeProxy;
|
||||
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
||||
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
||||
private ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork;
|
||||
private ISystemInfo systemInfo;
|
||||
private ITaskbar taskbar;
|
||||
private IText text;
|
||||
private ITextResource textResource;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
private IWindowMonitor windowMonitor;
|
||||
|
||||
internal IClientController ClientController { get; private set; }
|
||||
internal Taskbar Taskbar { get; private set; }
|
||||
|
||||
internal void BuildObjectGraph(Action shutdown)
|
||||
{
|
||||
|
@ -82,18 +87,21 @@ namespace SafeExamBrowser.Client
|
|||
InitializeLogging();
|
||||
InitializeText();
|
||||
|
||||
actionCenter = new ActionCenter();
|
||||
keyboardLayout = new KeyboardLayout(new ModuleLogger(logger, nameof(KeyboardLayout)), text);
|
||||
messageBox = new MessageBox(text);
|
||||
powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)), text);
|
||||
processMonitor = new ProcessMonitor(new ModuleLogger(logger, nameof(ProcessMonitor)), nativeMethods);
|
||||
uiFactory = new UserInterfaceFactory(text);
|
||||
runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), new ModuleLogger(logger, nameof(RuntimeProxy)));
|
||||
taskbar = new Taskbar(new ModuleLogger(logger, nameof(taskbar)));
|
||||
windowMonitor = new WindowMonitor(new ModuleLogger(logger, nameof(WindowMonitor)), nativeMethods);
|
||||
wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, nameof(WirelessNetwork)), text);
|
||||
|
||||
var displayMonitor = new DisplayMonitor(new ModuleLogger(logger, nameof(DisplayMonitor)), nativeMethods);
|
||||
var explorerShell = new ExplorerShell(new ModuleLogger(logger, nameof(ExplorerShell)), nativeMethods);
|
||||
var hashAlgorithm = new HashAlgorithm();
|
||||
|
||||
Taskbar = new Taskbar(new ModuleLogger(logger, nameof(Taskbar)));
|
||||
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
operations.Enqueue(new InitializationOperation(logger));
|
||||
|
@ -104,18 +112,33 @@ namespace SafeExamBrowser.Client
|
|||
operations.Enqueue(new LazyInitializationOperation(BuildClientHostOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildClientHostDisconnectionOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildKeyboardInterceptorOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildMouseInterceptorOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildWindowMonitorOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildProcessMonitorOperation));
|
||||
operations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, Taskbar));
|
||||
operations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, taskbar));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildActionCenterOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildTaskbarOperation));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildBrowserOperation));
|
||||
operations.Enqueue(new ClipboardOperation(logger, nativeMethods));
|
||||
operations.Enqueue(new LazyInitializationOperation(BuildMouseInterceptorOperation));
|
||||
operations.Enqueue(new DelegateOperation(UpdateClientControllerDependencies));
|
||||
|
||||
var sequence = new OperationSequence(logger, operations);
|
||||
|
||||
ClientController = new ClientController(displayMonitor, explorerShell, hashAlgorithm, logger, messageBox, sequence, processMonitor, runtimeProxy, shutdown, Taskbar, text, uiFactory, windowMonitor);
|
||||
ClientController = new ClientController(
|
||||
actionCenter,
|
||||
displayMonitor,
|
||||
explorerShell,
|
||||
hashAlgorithm,
|
||||
logger,
|
||||
messageBox,
|
||||
sequence,
|
||||
processMonitor,
|
||||
runtimeProxy,
|
||||
shutdown,
|
||||
taskbar,
|
||||
text,
|
||||
uiFactory,
|
||||
windowMonitor);
|
||||
}
|
||||
|
||||
internal void LogStartupInformation()
|
||||
|
@ -173,12 +196,41 @@ namespace SafeExamBrowser.Client
|
|||
textResource = new XmlTextResource(path);
|
||||
}
|
||||
|
||||
private IOperation BuildActionCenterOperation()
|
||||
{
|
||||
var aboutInfo = new AboutNotificationInfo(text);
|
||||
var aboutController = new AboutNotificationController(configuration.AppConfig, uiFactory);
|
||||
var logInfo = new LogNotificationInfo(text);
|
||||
var logController = new LogNotificationController(logger, uiFactory);
|
||||
var activators = new IActionCenterActivator[]
|
||||
{
|
||||
new KeyboardActivator(new ModuleLogger(logger, nameof(KeyboardActivator))),
|
||||
new TouchActivator(new ModuleLogger(logger, nameof(TouchActivator)))
|
||||
};
|
||||
var operation = new ActionCenterOperation(
|
||||
actionCenter,
|
||||
activators,
|
||||
logger,
|
||||
aboutInfo,
|
||||
aboutController,
|
||||
logInfo,
|
||||
logController,
|
||||
keyboardLayout,
|
||||
powerSupply,
|
||||
wirelessNetwork,
|
||||
configuration.Settings.ActionCenter,
|
||||
systemInfo,
|
||||
uiFactory);
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
private IOperation BuildBrowserOperation()
|
||||
{
|
||||
var moduleLogger = new ModuleLogger(logger, "BrowserController");
|
||||
var browserController = new BrowserApplicationController(configuration.AppConfig, configuration.Settings.Browser, messageBox, moduleLogger, text, uiFactory);
|
||||
var browserInfo = new BrowserApplicationInfo();
|
||||
var operation = new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory);
|
||||
var operation = new BrowserOperation(browserController, browserInfo, logger, taskbar, uiFactory);
|
||||
|
||||
this.browserController = browserController;
|
||||
|
||||
|
@ -232,12 +284,21 @@ namespace SafeExamBrowser.Client
|
|||
{
|
||||
var aboutInfo = new AboutNotificationInfo(text);
|
||||
var aboutController = new AboutNotificationController(configuration.AppConfig, uiFactory);
|
||||
var keyboardLayout = new KeyboardLayout(new ModuleLogger(logger, nameof(KeyboardLayout)), text);
|
||||
var logController = new LogNotificationController(logger, uiFactory);
|
||||
var logInfo = new LogNotificationInfo(text);
|
||||
var powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)), text);
|
||||
var wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, nameof(WirelessNetwork)), text);
|
||||
var operation = new TaskbarOperation(logger, aboutInfo, aboutController, logInfo, logController, keyboardLayout, powerSupply, wirelessNetwork, systemInfo, Taskbar, configuration.Settings.Taskbar, text, uiFactory);
|
||||
var logController = new LogNotificationController(logger, uiFactory);
|
||||
var operation = new TaskbarOperation(
|
||||
logger,
|
||||
aboutInfo,
|
||||
aboutController,
|
||||
logInfo,
|
||||
logController,
|
||||
keyboardLayout,
|
||||
powerSupply,
|
||||
wirelessNetwork,
|
||||
systemInfo,
|
||||
taskbar,
|
||||
configuration.Settings.Taskbar,
|
||||
uiFactory);
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
using SafeExamBrowser.Contracts.Client;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
|
||||
namespace SafeExamBrowser.Client.Notifications
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
using SafeExamBrowser.Contracts.Client;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
|
||||
namespace SafeExamBrowser.Client.Notifications
|
||||
|
|
91
SafeExamBrowser.Client/Operations/ActionCenterOperation.cs
Normal file
91
SafeExamBrowser.Client/Operations/ActionCenterOperation.cs
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Contracts.Client;
|
||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
internal class ActionCenterOperation : IOperation
|
||||
{
|
||||
private IActionCenter actionCenter;
|
||||
private IEnumerable<IActionCenterActivator> activators;
|
||||
private ILogger logger;
|
||||
private INotificationInfo aboutInfo;
|
||||
private INotificationController aboutController;
|
||||
private INotificationInfo logInfo;
|
||||
private INotificationController logController;
|
||||
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
||||
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
||||
private ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork;
|
||||
private ActionCenterSettings settings;
|
||||
private ISystemInfo systemInfo;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
|
||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public event StatusChangedEventHandler StatusChanged;
|
||||
|
||||
public ActionCenterOperation(
|
||||
IActionCenter actionCenter,
|
||||
IEnumerable<IActionCenterActivator> activators,
|
||||
ILogger logger,
|
||||
INotificationInfo aboutInfo,
|
||||
INotificationController aboutController,
|
||||
INotificationInfo logInfo,
|
||||
INotificationController logController,
|
||||
ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout,
|
||||
ISystemComponent<ISystemPowerSupplyControl> powerSupply,
|
||||
ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork,
|
||||
ActionCenterSettings settings,
|
||||
ISystemInfo systemInfo,
|
||||
IUserInterfaceFactory uiFactory)
|
||||
{
|
||||
this.actionCenter = actionCenter;
|
||||
this.activators = activators;
|
||||
this.logger = logger;
|
||||
this.aboutInfo = aboutInfo;
|
||||
this.aboutController = aboutController;
|
||||
this.logInfo = logInfo;
|
||||
this.logController = logController;
|
||||
this.keyboardLayout = keyboardLayout;
|
||||
this.powerSupply = powerSupply;
|
||||
this.wirelessNetwork = wirelessNetwork;
|
||||
this.systemInfo = systemInfo;
|
||||
this.settings = settings;
|
||||
this.uiFactory = uiFactory;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
foreach (var activator in activators)
|
||||
{
|
||||
actionCenter.Register(activator);
|
||||
activator.Start();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
public OperationResult Revert()
|
||||
{
|
||||
foreach (var activator in activators)
|
||||
{
|
||||
activator.Stop();
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
|||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@ using SafeExamBrowser.Contracts.Core.OperationModel.Events;
|
|||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.Monitoring;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ using SafeExamBrowser.Contracts.I18n;
|
|||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Client.Operations
|
||||
{
|
||||
|
@ -32,7 +32,6 @@ namespace SafeExamBrowser.Client.Operations
|
|||
private ISystemInfo systemInfo;
|
||||
private ITaskbar taskbar;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
private IText text;
|
||||
|
||||
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public event StatusChangedEventHandler StatusChanged;
|
||||
|
@ -49,7 +48,6 @@ namespace SafeExamBrowser.Client.Operations
|
|||
ISystemInfo systemInfo,
|
||||
ITaskbar taskbar,
|
||||
TaskbarSettings settings,
|
||||
IText text,
|
||||
IUserInterfaceFactory uiFactory)
|
||||
{
|
||||
this.aboutInfo = aboutInfo;
|
||||
|
@ -62,37 +60,44 @@ namespace SafeExamBrowser.Client.Operations
|
|||
this.settings = settings;
|
||||
this.systemInfo = systemInfo;
|
||||
this.taskbar = taskbar;
|
||||
this.text = text;
|
||||
this.uiFactory = uiFactory;
|
||||
this.wirelessNetwork = wirelessNetwork;
|
||||
}
|
||||
|
||||
public OperationResult Perform()
|
||||
{
|
||||
logger.Info("Initializing taskbar...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeTaskbar);
|
||||
|
||||
AddAboutNotification();
|
||||
taskbar.ShowClock = settings.ShowClock;
|
||||
|
||||
if (settings.AllowApplicationLog)
|
||||
if (settings.EnableTaskbar)
|
||||
{
|
||||
AddLogNotification();
|
||||
logger.Info("Initializing taskbar...");
|
||||
|
||||
AddAboutNotification();
|
||||
taskbar.ShowClock = settings.ShowClock;
|
||||
|
||||
if (settings.AllowApplicationLog)
|
||||
{
|
||||
AddLogNotification();
|
||||
}
|
||||
|
||||
if (settings.AllowKeyboardLayout)
|
||||
{
|
||||
AddKeyboardLayoutControl();
|
||||
}
|
||||
|
||||
if (settings.AllowWirelessNetwork)
|
||||
{
|
||||
AddWirelessNetworkControl();
|
||||
}
|
||||
|
||||
if (systemInfo.HasBattery)
|
||||
{
|
||||
AddPowerSupplyControl();
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.AllowKeyboardLayout)
|
||||
else
|
||||
{
|
||||
AddKeyboardLayoutControl();
|
||||
}
|
||||
|
||||
if (settings.AllowWirelessNetwork)
|
||||
{
|
||||
AddWirelessNetworkControl();
|
||||
}
|
||||
|
||||
if (systemInfo.HasBattery)
|
||||
{
|
||||
AddPowerSupplyControl();
|
||||
logger.Info("Taskbar is disabled, skipping initialization.");
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
|
@ -100,29 +105,36 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
public OperationResult Revert()
|
||||
{
|
||||
logger.Info("Terminating taskbar...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_TerminateTaskbar);
|
||||
|
||||
aboutController.Terminate();
|
||||
|
||||
if (settings.AllowApplicationLog)
|
||||
if (settings.EnableTaskbar)
|
||||
{
|
||||
logController.Terminate();
|
||||
logger.Info("Terminating taskbar...");
|
||||
aboutController.Terminate();
|
||||
|
||||
if (settings.AllowApplicationLog)
|
||||
{
|
||||
logController.Terminate();
|
||||
}
|
||||
|
||||
if (settings.AllowKeyboardLayout)
|
||||
{
|
||||
keyboardLayout.Terminate();
|
||||
}
|
||||
|
||||
if (settings.AllowWirelessNetwork)
|
||||
{
|
||||
wirelessNetwork.Terminate();
|
||||
}
|
||||
|
||||
if (systemInfo.HasBattery)
|
||||
{
|
||||
powerSupply.Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.AllowKeyboardLayout)
|
||||
else
|
||||
{
|
||||
keyboardLayout.Terminate();
|
||||
}
|
||||
|
||||
if (settings.AllowWirelessNetwork)
|
||||
{
|
||||
wirelessNetwork.Terminate();
|
||||
}
|
||||
|
||||
if (systemInfo.HasBattery)
|
||||
{
|
||||
powerSupply.Terminate();
|
||||
logger.Info("Taskbar was disabled, skipping termination.");
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="App.cs" />
|
||||
<Compile Include="ClientController.cs" />
|
||||
<Compile Include="Operations\ActionCenterOperation.cs" />
|
||||
<Compile Include="Operations\ClientHostDisconnectionOperation.cs" />
|
||||
<Compile Include="Operations\ConfigurationOperation.cs" />
|
||||
<Compile Include="Operations\InitializationOperation.cs" />
|
||||
|
|
|
@ -88,6 +88,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
var settings = new Settings();
|
||||
|
||||
settings.ActionCenter.EnableActionCenter = true;
|
||||
|
||||
settings.Browser.StartUrl = "https://www.safeexambrowser.org/start";
|
||||
settings.Browser.AllowConfigurationDownloads = true;
|
||||
settings.Browser.AllowDeveloperConsole = false;
|
||||
|
@ -139,12 +141,12 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
settings.Taskbar.AllowApplicationLog = false;
|
||||
settings.Taskbar.AllowKeyboardLayout = true;
|
||||
settings.Taskbar.AllowWirelessNetwork = false;
|
||||
settings.Taskbar.EnableTaskbar = true;
|
||||
settings.Taskbar.ShowClock = true;
|
||||
|
||||
// TODO: Default values for testing of alpha version only, remove for final release!
|
||||
settings.Browser.AllowDeveloperConsole = true;
|
||||
settings.Browser.MainWindowSettings.AllowAddressBar = true;
|
||||
settings.KioskMode = KioskMode.None;
|
||||
settings.Taskbar.AllowApplicationLog = true;
|
||||
|
||||
return settings;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Applications
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@ using SafeExamBrowser.Contracts.Core;
|
|||
namespace SafeExamBrowser.Contracts.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// The information about a (third-party) application which can be accessed via the <see cref="UserInterface.Taskbar.ITaskbar"/>.
|
||||
/// The information about a (third-party) application which can be accessed via the shell.
|
||||
/// </summary>
|
||||
public interface IApplicationInfo
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ using SafeExamBrowser.Contracts.UserInterface.Windows;
|
|||
namespace SafeExamBrowser.Contracts.Applications
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines an instance of a (third-party) application which can be accessed via the <see cref="UserInterface.Taskbar.ITaskbar"/>.
|
||||
/// Defines an instance of a (third-party) application which can be accessed via the shell.
|
||||
/// </summary>
|
||||
public interface IApplicationInstance
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Client
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@ using SafeExamBrowser.Contracts.Core;
|
|||
namespace SafeExamBrowser.Contracts.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// The information about a notification which is part of the <see cref="UserInterface.Taskbar.ITaskbar"/>.
|
||||
/// The information about a notification.
|
||||
/// </summary>
|
||||
public interface INotificationInfo
|
||||
{
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Configuration.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines all configuration options for the <see cref="UserInterface.Shell.IActionCenter"/>.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ActionCenterSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the action center itself is enabled and visible to the user.
|
||||
/// </summary>
|
||||
public bool EnableActionCenter { get; set; }
|
||||
}
|
||||
}
|
|
@ -17,6 +17,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
|||
[Serializable]
|
||||
public class Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// All action center-related settings.
|
||||
/// </summary>
|
||||
public ActionCenterSettings ActionCenter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The hash code of the administrator password for the settings.
|
||||
/// </summary>
|
||||
|
@ -74,6 +79,7 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
|||
|
||||
public Settings()
|
||||
{
|
||||
ActionCenter = new ActionCenterSettings();
|
||||
Browser = new BrowserSettings();
|
||||
Keyboard = new KeyboardSettings();
|
||||
Mouse = new MouseSettings();
|
||||
|
|
|
@ -11,7 +11,7 @@ using System;
|
|||
namespace SafeExamBrowser.Contracts.Configuration.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines all configuration options for the <see cref="UserInterface.Taskbar.ITaskbar"/>.
|
||||
/// Defines all configuration options for the <see cref="UserInterface.Shell.ITaskbar"/>.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TaskbarSettings
|
||||
|
@ -31,6 +31,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
|||
/// </summary>
|
||||
public bool AllowWirelessNetwork { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the taskbar itself is enabled and visible to the user.
|
||||
/// </summary>
|
||||
public bool EnableTaskbar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the current date and time will be rendered in the taskbar.
|
||||
/// </summary>
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<Compile Include="Configuration\DataResources\IResourceLoader.cs" />
|
||||
<Compile Include="Configuration\DataResources\IResourceSaver.cs" />
|
||||
<Compile Include="Configuration\SaveStatus.cs" />
|
||||
<Compile Include="Configuration\Settings\ActionCenterSettings.cs" />
|
||||
<Compile Include="Configuration\Settings\BrowserWindowSettings.cs" />
|
||||
<Compile Include="Configuration\Settings\UserInterfaceMode.cs" />
|
||||
<Compile Include="Applications\Events\IconChangedEventHandler.cs" />
|
||||
|
@ -186,26 +187,29 @@
|
|||
<Compile Include="UserInterface\Browser\IBrowserWindow.cs" />
|
||||
<Compile Include="UserInterface\MessageBox\IMessageBox.cs" />
|
||||
<Compile Include="UserInterface\IProgressIndicator.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\Events\ApplicationButtonClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\Events\KeyboardLayoutSelectedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\Events\NotificationButtonClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\Events\WindowClosingEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\Events\WirelessNetworkSelectedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\Events\QuitButtonClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\ActivatorEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\ApplicationButtonClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\KeyboardLayoutSelectedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\NotificationButtonClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\IActionCenter.cs" />
|
||||
<Compile Include="UserInterface\Shell\IActionCenterActivator.cs" />
|
||||
<Compile Include="UserInterface\Windows\Events\WindowClosingEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\WirelessNetworkSelectedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Shell\Events\QuitButtonClickedEventHandler.cs" />
|
||||
<Compile Include="UserInterface\Windows\IPasswordDialog.cs" />
|
||||
<Compile Include="UserInterface\Windows\IPasswordDialogResult.cs" />
|
||||
<Compile Include="UserInterface\Windows\IRuntimeWindow.cs" />
|
||||
<Compile Include="UserInterface\MessageBox\MessageBoxResult.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\INotificationButton.cs" />
|
||||
<Compile Include="UserInterface\Shell\INotificationButton.cs" />
|
||||
<Compile Include="UserInterface\Windows\ISplashScreen.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ISystemKeyboardLayoutControl.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ISystemPowerSupplyControl.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ISystemControl.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ISystemWirelessNetworkControl.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ITaskbar.cs" />
|
||||
<Compile Include="UserInterface\Shell\ISystemKeyboardLayoutControl.cs" />
|
||||
<Compile Include="UserInterface\Shell\ISystemPowerSupplyControl.cs" />
|
||||
<Compile Include="UserInterface\Shell\ISystemControl.cs" />
|
||||
<Compile Include="UserInterface\Shell\ISystemWirelessNetworkControl.cs" />
|
||||
<Compile Include="UserInterface\Shell\ITaskbar.cs" />
|
||||
<Compile Include="I18n\ITextResource.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\IApplicationButton.cs" />
|
||||
<Compile Include="UserInterface\Shell\IApplicationButton.cs" />
|
||||
<Compile Include="UserInterface\IUserInterfaceFactory.cs" />
|
||||
<Compile Include="UserInterface\Windows\IWindow.cs" />
|
||||
<Compile Include="UserInterface\MessageBox\MessageBoxAction.cs" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.SystemComponents
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ using SafeExamBrowser.Contracts.Configuration.Settings;
|
|||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler fired by an <see cref="IActionCenterActivator"/> to control the visibility of the <see cref="IActionCenter"/>.
|
||||
/// </summary>
|
||||
public delegate void ActivatorEventHandler();
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that an <see cref="IApplicationButton"/> has been clicked, optionally specifying the ID of the selected instance (if
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that a particular <see cref="IKeyboardLayout"/> has been selected by the user.
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the user clicked on a <see cref="INotificationButton"/> in the <see cref="ITaskbar"/>.
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler used to define the control flow when the <see cref="ITaskbar"/>'s quit button is clicked.
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that a particular <see cref="IWirelessNetwork"/> has been selected by the user.
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// The action center is a user interface element via which the user can access and control various aspects of the application.
|
||||
/// </summary>
|
||||
public interface IActionCenter
|
||||
{
|
||||
/// <summary>
|
||||
/// Closes the action center.
|
||||
/// </summary>
|
||||
void Close();
|
||||
|
||||
/// <summary>
|
||||
/// Makes the action center invisible.
|
||||
/// </summary>
|
||||
void Hide();
|
||||
|
||||
/// <summary>
|
||||
/// Registers the specified activator to control the visibility of the action center.
|
||||
/// </summary>
|
||||
void Register(IActionCenterActivator activator);
|
||||
|
||||
/// <summary>
|
||||
/// Makes the action center visible.
|
||||
/// </summary>
|
||||
void Show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// A module which can be used to control the visibility of the <see cref="IActionCenter"/>.
|
||||
/// </summary>
|
||||
public interface IActionCenterActivator
|
||||
{
|
||||
/// <summary>
|
||||
/// Fired when the action center should be made visible.
|
||||
/// </summary>
|
||||
event ActivatorEventHandler Activate;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the action center should be made invisible.
|
||||
/// </summary>
|
||||
event ActivatorEventHandler Deactivate;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the action center visibility should be toggled.
|
||||
/// </summary>
|
||||
event ActivatorEventHandler Toggle;
|
||||
|
||||
/// <summary>
|
||||
/// Starts monitoring user input events.
|
||||
/// </summary>
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Stops monitoring user input events.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
}
|
||||
}
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// The button of a (third-party) application which can be loaded into the <see cref="ITaskbar"/>.
|
|
@ -6,9 +6,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// The button of a notification which can be loaded into the <see cref="ITaskbar"/>.
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// The control of a system component which can be loaded into the <see cref="ITaskbar"/>.
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// The control of the keyboard layout system component.
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// The control of the power supply system component.
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// The control of the wireless network system component.
|
|
@ -6,13 +6,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the functionality of the application taskbar. The taskbar is the main user interface element via which the user can access
|
||||
/// the browser, third-party applications, system controls and so on.
|
||||
/// The taskbar is a user interface element via which the user can access and control various aspects of the application.
|
||||
/// </summary>
|
||||
public interface ITaskbar
|
||||
{
|
||||
|
@ -55,5 +54,10 @@ namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
|||
/// Moves the taskbar to the bottom of and resizes it according to the current working area.
|
||||
/// </summary>
|
||||
void InitializeBounds();
|
||||
|
||||
/// <summary>
|
||||
/// Shows the taskbar.
|
||||
/// </summary>
|
||||
void Show();
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar.Events
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Windows.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that a window is about to be closed.
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Windows
|
||||
{
|
||||
|
|
|
@ -89,7 +89,18 @@ namespace SafeExamBrowser.Runtime
|
|||
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||
var sessionSequence = new RepeatableOperationSequence(logger, sessionOperations);
|
||||
|
||||
RuntimeController = new RuntimeController(appConfig, logger, messageBox, bootstrapSequence, sessionSequence, runtimeHost, serviceProxy, sessionContext, shutdown, text, uiFactory);
|
||||
RuntimeController = new RuntimeController(
|
||||
appConfig,
|
||||
logger,
|
||||
messageBox,
|
||||
bootstrapSequence,
|
||||
sessionSequence,
|
||||
runtimeHost,
|
||||
serviceProxy,
|
||||
sessionContext,
|
||||
shutdown,
|
||||
text,
|
||||
uiFactory);
|
||||
}
|
||||
|
||||
internal void LogStartupInformation()
|
||||
|
@ -126,11 +137,30 @@ namespace SafeExamBrowser.Runtime
|
|||
var xmlParser = new XmlParser(ModuleLogger(nameof(XmlParser)));
|
||||
var xmlSerializer = new XmlSerializer(ModuleLogger(nameof(XmlSerializer)));
|
||||
|
||||
configuration = new ConfigurationRepository(certificateStore, new HashAlgorithm(), repositoryLogger, executable.Location, programCopyright, programTitle, programVersion);
|
||||
configuration = new ConfigurationRepository(
|
||||
certificateStore,
|
||||
new HashAlgorithm(),
|
||||
repositoryLogger,
|
||||
executable.Location,
|
||||
programCopyright,
|
||||
programTitle,
|
||||
programVersion);
|
||||
appConfig = configuration.InitializeAppConfig();
|
||||
|
||||
configuration.Register(new BinaryParser(compressor, new HashAlgorithm(), ModuleLogger(nameof(BinaryParser)), passwordEncryption, publicKeyEncryption, symmetricEncryption, xmlParser));
|
||||
configuration.Register(new BinarySerializer(compressor, ModuleLogger(nameof(BinarySerializer)), passwordEncryption, publicKeyEncryption, symmetricEncryption, xmlSerializer));
|
||||
configuration.Register(new BinaryParser(
|
||||
compressor,
|
||||
new HashAlgorithm(),
|
||||
ModuleLogger(nameof(BinaryParser)),
|
||||
passwordEncryption,
|
||||
publicKeyEncryption,
|
||||
symmetricEncryption, xmlParser));
|
||||
configuration.Register(new BinarySerializer(
|
||||
compressor,
|
||||
ModuleLogger(nameof(BinarySerializer)),
|
||||
passwordEncryption,
|
||||
publicKeyEncryption,
|
||||
symmetricEncryption,
|
||||
xmlSerializer));
|
||||
configuration.Register(new XmlParser(ModuleLogger(nameof(XmlParser))));
|
||||
configuration.Register(new XmlSerializer(ModuleLogger(nameof(XmlSerializer))));
|
||||
configuration.Register(new FileResourceLoader(ModuleLogger(nameof(FileResourceLoader))));
|
||||
|
|
|
@ -12,7 +12,7 @@ using System.Windows.Forms;
|
|||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@ using System.Timers;
|
|||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using PowerLineStatus = System.Windows.Forms.PowerLineStatus;
|
||||
using SystemInformation = System.Windows.Forms.SystemInformation;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ using System.Timers;
|
|||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SimpleWifi;
|
||||
using SimpleWifi.Win32;
|
||||
using SimpleWifi.Win32.Interop;
|
||||
|
|
|
@ -10,8 +10,8 @@ using System.Windows;
|
|||
using System.Windows.Documents;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
{
|
||||
|
|
12
SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml
Normal file
12
SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Desktop.ActionCenter"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop"
|
||||
mc:Ignorable="d" Title="ActionCenter" Height="1000" Width="400" Background="#EEF0F0F0" AllowsTransparency="True" WindowStyle="None"
|
||||
Topmost="True" ResizeMode="NoResize">
|
||||
<Grid>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
137
SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml.cs
Normal file
137
SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml.cs
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Animation;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
{
|
||||
public partial class ActionCenter : Window, IActionCenter
|
||||
{
|
||||
public ActionCenter()
|
||||
{
|
||||
InitializeComponent();
|
||||
RegisterEvents();
|
||||
}
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
Dispatcher.Invoke(base.Close);
|
||||
}
|
||||
|
||||
public new void Hide()
|
||||
{
|
||||
Dispatcher.Invoke(HideAnimated);
|
||||
}
|
||||
|
||||
public void Register(IActionCenterActivator activator)
|
||||
{
|
||||
activator.Activate += Activator_Activate;
|
||||
activator.Deactivate += Activator_Deactivate;
|
||||
activator.Toggle += Activator_Toggle;
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(ShowAnimated);
|
||||
}
|
||||
|
||||
private void HideAnimated()
|
||||
{
|
||||
var storyboard = new Storyboard();
|
||||
var animation = new DoubleAnimation
|
||||
{
|
||||
EasingFunction = new CircleEase { EasingMode = EasingMode.EaseOut },
|
||||
From = 0,
|
||||
To = -Width,
|
||||
Duration = new Duration(TimeSpan.FromMilliseconds(500))
|
||||
};
|
||||
|
||||
Storyboard.SetTarget(animation, this);
|
||||
Storyboard.SetTargetProperty(animation, new PropertyPath(LeftProperty));
|
||||
|
||||
storyboard.Children.Add(animation);
|
||||
storyboard.Completed += (o, args) => Dispatcher.Invoke(base.Hide);
|
||||
storyboard.Begin();
|
||||
}
|
||||
|
||||
private void ShowAnimated()
|
||||
{
|
||||
var storyboard = new Storyboard();
|
||||
var animation = new DoubleAnimation
|
||||
{
|
||||
EasingFunction = new CircleEase { EasingMode = EasingMode.EaseOut },
|
||||
From = -Width,
|
||||
To = 0,
|
||||
Duration = new Duration(TimeSpan.FromMilliseconds(500))
|
||||
};
|
||||
|
||||
Storyboard.SetTarget(animation, this);
|
||||
Storyboard.SetTargetProperty(animation, new PropertyPath(LeftProperty));
|
||||
|
||||
InitializeBounds();
|
||||
base.Show();
|
||||
Activate();
|
||||
|
||||
storyboard.Children.Add(animation);
|
||||
storyboard.Completed += (o, args) => Dispatcher.Invoke(Activate);
|
||||
storyboard.Begin();
|
||||
}
|
||||
|
||||
private void InitializeBounds()
|
||||
{
|
||||
Height = SystemParameters.WorkArea.Height;
|
||||
Top = 0;
|
||||
Left = -Width;
|
||||
}
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
Deactivated += (o, args) => HideAnimated();
|
||||
}
|
||||
|
||||
private void Activator_Activate()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (Visibility != Visibility.Visible)
|
||||
{
|
||||
ShowAnimated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Activator_Deactivate()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (Visibility == Visibility.Visible)
|
||||
{
|
||||
HideAnimated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Activator_Toggle()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (Visibility != Visibility.Visible)
|
||||
{
|
||||
ShowAnimated();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideAnimated();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@ using SafeExamBrowser.Contracts.I18n;
|
|||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
|
@ -117,33 +117,12 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
|
||||
private void InitializeBrowserWindow(IBrowserControl browserControl)
|
||||
{
|
||||
var originalBrush = MenuButton.Background;
|
||||
|
||||
if (browserControl is System.Windows.Forms.Control control)
|
||||
{
|
||||
BrowserControlHost.Child = control;
|
||||
}
|
||||
|
||||
BackwardButton.Click += (o, args) => BackwardNavigationRequested?.Invoke();
|
||||
Closing += (o, args) => closing?.Invoke();
|
||||
ForwardButton.Click += (o, args) => ForwardNavigationRequested?.Invoke();
|
||||
MenuButton.Click += (o, args) => MenuPopup.IsOpen = !MenuPopup.IsOpen;
|
||||
MenuButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver));
|
||||
MenuPopup.Closed += (o, args) => { MenuButton.Background = originalBrush; };
|
||||
MenuPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = IsMouseOver));
|
||||
MenuPopup.Opened += (o, args) => { MenuButton.Background = Brushes.LightGray; };
|
||||
KeyUp += BrowserWindow_KeyUp;
|
||||
ReloadButton.Click += (o, args) => ReloadRequested?.Invoke();
|
||||
UrlTextBox.GotKeyboardFocus += (o, args) => UrlTextBox.SelectAll();
|
||||
UrlTextBox.GotMouseCapture += UrlTextBox_GotMouseCapture;
|
||||
UrlTextBox.LostKeyboardFocus += (o, args) => UrlTextBox.Tag = null;
|
||||
UrlTextBox.LostFocus += (o, args) => UrlTextBox.Tag = null;
|
||||
UrlTextBox.KeyUp += UrlTextBox_KeyUp;
|
||||
UrlTextBox.MouseDoubleClick += (o, args) => UrlTextBox.SelectAll();
|
||||
ZoomInButton.Click += (o, args) => ZoomInRequested?.Invoke();
|
||||
ZoomOutButton.Click += (o, args) => ZoomOutRequested?.Invoke();
|
||||
ZoomResetButton.Click += (o, args) => ZoomResetRequested?.Invoke();
|
||||
|
||||
RegisterEvents();
|
||||
ApplySettings();
|
||||
LoadIcons();
|
||||
LoadText();
|
||||
|
@ -174,6 +153,31 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
}
|
||||
}
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
var originalBrush = MenuButton.Background;
|
||||
|
||||
BackwardButton.Click += (o, args) => BackwardNavigationRequested?.Invoke();
|
||||
Closing += (o, args) => closing?.Invoke();
|
||||
ForwardButton.Click += (o, args) => ForwardNavigationRequested?.Invoke();
|
||||
MenuButton.Click += (o, args) => MenuPopup.IsOpen = !MenuPopup.IsOpen;
|
||||
MenuButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver));
|
||||
MenuPopup.Closed += (o, args) => { MenuButton.Background = originalBrush; };
|
||||
MenuPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = IsMouseOver));
|
||||
MenuPopup.Opened += (o, args) => { MenuButton.Background = Brushes.LightGray; };
|
||||
KeyUp += BrowserWindow_KeyUp;
|
||||
ReloadButton.Click += (o, args) => ReloadRequested?.Invoke();
|
||||
UrlTextBox.GotKeyboardFocus += (o, args) => UrlTextBox.SelectAll();
|
||||
UrlTextBox.GotMouseCapture += UrlTextBox_GotMouseCapture;
|
||||
UrlTextBox.LostKeyboardFocus += (o, args) => UrlTextBox.Tag = null;
|
||||
UrlTextBox.LostFocus += (o, args) => UrlTextBox.Tag = null;
|
||||
UrlTextBox.KeyUp += UrlTextBox_KeyUp;
|
||||
UrlTextBox.MouseDoubleClick += (o, args) => UrlTextBox.SelectAll();
|
||||
ZoomInButton.Click += (o, args) => ZoomInRequested?.Invoke();
|
||||
ZoomOutButton.Click += (o, args) => ZoomOutRequested?.Invoke();
|
||||
ZoomResetButton.Click += (o, args) => ZoomResetRequested?.Invoke();
|
||||
}
|
||||
|
||||
private void ApplySettings()
|
||||
{
|
||||
if (isMainWindow)
|
||||
|
|
|
@ -14,8 +14,8 @@ using System.Windows.Controls;
|
|||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
|
|
|
@ -10,7 +10,7 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.Core;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
|
|
|
@ -12,8 +12,8 @@ using System.Threading.Tasks;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.Client;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
|
|
|
@ -11,7 +11,7 @@ using System.Windows.Controls;
|
|||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@ using System;
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
|
|
|
@ -14,8 +14,8 @@ using System.Windows.Controls;
|
|||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
|
|
|
@ -10,8 +10,8 @@ using System.ComponentModel;
|
|||
using System.Windows;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
{
|
||||
|
|
|
@ -11,8 +11,8 @@ using System.Windows.Documents;
|
|||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
|
|
|
@ -68,6 +68,9 @@
|
|||
<Compile Include="AboutWindow.xaml.cs">
|
||||
<DependentUpon>AboutWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ActionCenter.xaml.cs">
|
||||
<DependentUpon>ActionCenter.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="BrowserWindow.xaml.cs">
|
||||
<DependentUpon>BrowserWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -126,6 +129,10 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ActionCenter.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="BrowserWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -10,8 +10,8 @@ using System.Windows;
|
|||
using System.Windows.Documents;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d"
|
||||
Title="Taskbar" Background="#FFF0F0F0" Height="40" Width="750" WindowStyle="None" Topmost="True" Visibility="Visible"
|
||||
ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico">
|
||||
mc:Ignorable="d" Title="Taskbar" Background="#FFF0F0F0" Height="40" Width="750" WindowStyle="None" Topmost="True" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
|
@ -94,6 +94,11 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
});
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(base.Show);
|
||||
}
|
||||
|
||||
private void QuitButton_Clicked(CancelEventArgs args)
|
||||
{
|
||||
QuitButtonClicked?.Invoke(args);
|
||||
|
|
|
@ -18,7 +18,7 @@ using SafeExamBrowser.Contracts.I18n;
|
|||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Controls;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace SafeExamBrowser.WindowsApi.Constants
|
|||
/// See https://docs.microsoft.com/de-de/windows/desktop/SecAuthZ/access-mask
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
internal enum ACCESS_MASK : uint
|
||||
internal enum AccessMask : uint
|
||||
{
|
||||
DESKTOP_NONE = 0,
|
||||
DESKTOP_READOBJECTS = 0x0001,
|
|
@ -32,6 +32,20 @@ namespace SafeExamBrowser.WindowsApi.Constants
|
|||
/// </summary>
|
||||
internal const int MIN_ALL = 419;
|
||||
|
||||
/// <summary>
|
||||
/// Bitmask to evaluate the origin of a mouse event.
|
||||
///
|
||||
/// See https://docs.microsoft.com/en-us/windows/desktop/tablet/system-events-and-mouse-messages.
|
||||
/// </summary>
|
||||
internal const uint MOUSEEVENTF_MASK = 0xFFFFFF00;
|
||||
|
||||
/// <summary>
|
||||
/// The constant for a mouse event generated by a touch interface.
|
||||
///
|
||||
/// See https://docs.microsoft.com/en-us/windows/desktop/tablet/system-events-and-mouse-messages.
|
||||
/// </summary>
|
||||
internal const uint MOUSEEVENTF_FROMTOUCH = 0xFF515700;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the default priority class for processes, i.e. a process with no special scheduling needs.
|
||||
///
|
||||
|
|
24
SafeExamBrowser.WindowsApi/Constants/VirtualKeyCode.cs
Normal file
24
SafeExamBrowser.WindowsApi/Constants/VirtualKeyCode.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.WindowsApi.Constants
|
||||
{
|
||||
/// <remarks>
|
||||
/// See https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes.
|
||||
/// </remarks>
|
||||
internal enum VirtualKeyCode
|
||||
{
|
||||
A = 0x41,
|
||||
Delete = 0x2E,
|
||||
LeftAlt = 0xA4,
|
||||
LeftControl = 0xA2,
|
||||
LeftWindows = 0x5B,
|
||||
RightAlt = 0xA5,
|
||||
RightControl = 0xA3
|
||||
}
|
||||
}
|
|
@ -13,5 +13,5 @@ namespace SafeExamBrowser.WindowsApi.Delegates
|
|||
/// <remarks>
|
||||
/// See https://docs.microsoft.com/de-de/windows/desktop/api/winuser/nc-winuser-hookproc
|
||||
/// </remarks>
|
||||
internal delegate IntPtr HookDelegate(int code, IntPtr wParam, IntPtr lParam);
|
||||
internal delegate IntPtr HookDelegate(int nCode, IntPtr wParam, IntPtr lParam);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace SafeExamBrowser.WindowsApi
|
|||
{
|
||||
logger.Debug($"Attempting to create new desktop '{name}'...");
|
||||
|
||||
var handle = User32.CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0, (uint) ACCESS_MASK.GENERIC_ALL, IntPtr.Zero);
|
||||
var handle = User32.CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0, (uint) AccessMask.GENERIC_ALL, IntPtr.Zero);
|
||||
|
||||
if (handle == IntPtr.Zero)
|
||||
{
|
||||
|
|
110
SafeExamBrowser.WindowsApi/KeyboardActivator.cs
Normal file
110
SafeExamBrowser.WindowsApi/KeyboardActivator.cs
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Delegates;
|
||||
using SafeExamBrowser.WindowsApi.Types;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
{
|
||||
public class KeyboardActivator : IActionCenterActivator
|
||||
{
|
||||
private bool A, LeftWindows;
|
||||
private IntPtr handle;
|
||||
private HookDelegate hookDelegate;
|
||||
private ILogger logger;
|
||||
|
||||
public event ActivatorEventHandler Activate { add { } remove { } }
|
||||
public event ActivatorEventHandler Deactivate { add { } remove { } }
|
||||
public event ActivatorEventHandler Toggle;
|
||||
|
||||
public KeyboardActivator(ILogger logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
var hookReadyEvent = new AutoResetEvent(false);
|
||||
var hookThread = new Thread(() =>
|
||||
{
|
||||
var sleepEvent = new AutoResetEvent(false);
|
||||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
var module = process.MainModule;
|
||||
var moduleHandle = Kernel32.GetModuleHandle(module.ModuleName);
|
||||
|
||||
// IMPORTANT:
|
||||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
hookDelegate = new HookDelegate(LowLevelKeyboardProc);
|
||||
|
||||
handle = User32.SetWindowsHookEx(HookType.WH_KEYBOARD_LL, hookDelegate, moduleHandle, 0);
|
||||
hookReadyEvent.Set();
|
||||
|
||||
while (true)
|
||||
{
|
||||
sleepEvent.WaitOne();
|
||||
}
|
||||
});
|
||||
|
||||
hookThread.SetApartmentState(ApartmentState.STA);
|
||||
hookThread.IsBackground = true;
|
||||
hookThread.Start();
|
||||
|
||||
hookReadyEvent.WaitOne();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
User32.UnhookWindowsHookEx(handle);
|
||||
}
|
||||
|
||||
private IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0)
|
||||
{
|
||||
var changed = false;
|
||||
var keyData = (KBDLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
|
||||
var pressed = IsPressed(wParam.ToInt32());
|
||||
|
||||
switch (keyData.KeyCode)
|
||||
{
|
||||
case (uint) VirtualKeyCode.A:
|
||||
changed = A != pressed;
|
||||
A = pressed;
|
||||
break;
|
||||
case (uint) VirtualKeyCode.LeftWindows:
|
||||
changed = LeftWindows != pressed;
|
||||
LeftWindows = pressed;
|
||||
break;
|
||||
}
|
||||
|
||||
if (A && LeftWindows && changed)
|
||||
{
|
||||
logger.Debug("Detected toggle sequence for action center.");
|
||||
Toggle?.Invoke();
|
||||
|
||||
return (IntPtr) 1;
|
||||
}
|
||||
}
|
||||
|
||||
return User32.CallNextHookEx(handle, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
private bool IsPressed(int wParam)
|
||||
{
|
||||
return wParam == Constant.WM_KEYDOWN || wParam == Constant.WM_SYSKEYDOWN;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,12 +17,6 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
|
|||
{
|
||||
internal class KeyboardHook
|
||||
{
|
||||
private const int LEFT_CTRL = 162;
|
||||
private const int RIGHT_CTRL = 163;
|
||||
private const int LEFT_ALT = 164;
|
||||
private const int RIGHT_ALT = 165;
|
||||
private const int DELETE = 46;
|
||||
|
||||
private bool altPressed, ctrlPressed;
|
||||
private HookDelegate hookDelegate;
|
||||
|
||||
|
@ -40,7 +34,7 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
|
|||
var module = process.MainModule;
|
||||
var moduleHandle = Kernel32.GetModuleHandle(module.ModuleName);
|
||||
|
||||
// IMORTANT:
|
||||
// IMPORTANT:
|
||||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
hookDelegate = new HookDelegate(LowLevelKeyboardProc);
|
||||
|
@ -108,16 +102,16 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
|
|||
{
|
||||
var keyCode = keyData.KeyCode;
|
||||
|
||||
if (keyCode == LEFT_CTRL || keyCode == RIGHT_CTRL)
|
||||
if (keyCode == (uint) VirtualKeyCode.LeftControl || keyCode == (uint) VirtualKeyCode.RightControl)
|
||||
{
|
||||
ctrlPressed = IsPressed(wParam);
|
||||
}
|
||||
else if (keyCode == LEFT_ALT || keyCode == RIGHT_ALT)
|
||||
else if (keyCode == (uint) VirtualKeyCode.LeftAlt || keyCode == (uint) VirtualKeyCode.RightAlt)
|
||||
{
|
||||
altPressed = IsPressed(wParam);
|
||||
}
|
||||
|
||||
if (ctrlPressed && altPressed && keyCode == DELETE)
|
||||
if (ctrlPressed && altPressed && keyCode == (uint) VirtualKeyCode.Delete)
|
||||
{
|
||||
// When the Secure Attention Sequence is pressed, the WM_KEYUP / WM_SYSKEYUP messages for CTRL and ALT get lost...
|
||||
ctrlPressed = false;
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
|
|||
var module = process.MainModule;
|
||||
var moduleHandle = Kernel32.GetModuleHandle(module.ModuleName);
|
||||
|
||||
// IMORTANT:
|
||||
// IMPORTANT:
|
||||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
hookDelegate = new HookDelegate(LowLevelMouseProc);
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
|
|||
|
||||
internal void Attach()
|
||||
{
|
||||
// IMORTANT:
|
||||
// IMPORTANT:
|
||||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
eventDelegate = new EventDelegate(LowLevelSystemProc);
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
<Compile Include="Constants\Constant.cs" />
|
||||
<Compile Include="Constants\HookType.cs" />
|
||||
<Compile Include="Constants\ThreadAccess.cs" />
|
||||
<Compile Include="Constants\VirtualKeyCode.cs" />
|
||||
<Compile Include="Delegates\EnumDesktopDelegate.cs" />
|
||||
<Compile Include="Delegates\EnumWindowsDelegate.cs" />
|
||||
<Compile Include="Delegates\EventDelegate.cs" />
|
||||
|
@ -61,11 +62,13 @@
|
|||
<Compile Include="Desktop.cs" />
|
||||
<Compile Include="DesktopFactory.cs" />
|
||||
<Compile Include="ExplorerShell.cs" />
|
||||
<Compile Include="KeyboardActivator.cs" />
|
||||
<Compile Include="Monitoring\MouseHook.cs" />
|
||||
<Compile Include="Monitoring\SystemHook.cs" />
|
||||
<Compile Include="Process.cs" />
|
||||
<Compile Include="ProcessFactory.cs" />
|
||||
<Compile Include="Constants\ACCESS_MASK.cs" />
|
||||
<Compile Include="Constants\AccessMask.cs" />
|
||||
<Compile Include="TouchActivator.cs" />
|
||||
<Compile Include="Types\Bounds.cs" />
|
||||
<Compile Include="Types\EXECUTION_STATE.cs" />
|
||||
<Compile Include="Types\KBDLLHOOKSTRUCT.cs" />
|
||||
|
|
121
SafeExamBrowser.WindowsApi/TouchActivator.cs
Normal file
121
SafeExamBrowser.WindowsApi/TouchActivator.cs
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Delegates;
|
||||
using SafeExamBrowser.WindowsApi.Types;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
{
|
||||
public class TouchActivator : IActionCenterActivator
|
||||
{
|
||||
private HookDelegate hookDelegate;
|
||||
private IntPtr handle;
|
||||
private bool isDown;
|
||||
private ILogger logger;
|
||||
|
||||
public event ActivatorEventHandler Activate;
|
||||
public event ActivatorEventHandler Deactivate { add { } remove { } }
|
||||
public event ActivatorEventHandler Toggle { add { } remove { } }
|
||||
|
||||
public TouchActivator(ILogger logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
var hookReadyEvent = new AutoResetEvent(false);
|
||||
var hookThread = new Thread(() =>
|
||||
{
|
||||
var sleepEvent = new AutoResetEvent(false);
|
||||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
var module = process.MainModule;
|
||||
var moduleHandle = Kernel32.GetModuleHandle(module.ModuleName);
|
||||
|
||||
// IMPORTANT:
|
||||
// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
|
||||
// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
|
||||
hookDelegate = new HookDelegate(LowLevelMouseProc);
|
||||
|
||||
handle = User32.SetWindowsHookEx(HookType.WH_MOUSE_LL, hookDelegate, moduleHandle, 0);
|
||||
hookReadyEvent.Set();
|
||||
|
||||
while (true)
|
||||
{
|
||||
sleepEvent.WaitOne();
|
||||
}
|
||||
});
|
||||
|
||||
hookThread.SetApartmentState(ApartmentState.STA);
|
||||
hookThread.IsBackground = true;
|
||||
hookThread.Start();
|
||||
|
||||
hookReadyEvent.WaitOne();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
User32.UnhookWindowsHookEx(handle);
|
||||
}
|
||||
|
||||
private IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0 && !Ignore(wParam.ToInt32()))
|
||||
{
|
||||
var message = wParam.ToInt32();
|
||||
var mouseData = (MSLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
|
||||
var position = $"{mouseData.Point.X}/{mouseData.Point.Y}";
|
||||
var extraInfo = mouseData.DwExtraInfo.ToUInt32();
|
||||
var isTouch = (extraInfo & Constant.MOUSEEVENTF_MASK) == Constant.MOUSEEVENTF_FROMTOUCH;
|
||||
|
||||
if (isTouch)
|
||||
{
|
||||
if (message == Constant.WM_LBUTTONUP)
|
||||
{
|
||||
isDown = false;
|
||||
}
|
||||
|
||||
if (message == Constant.WM_LBUTTONDOWN && 0 < mouseData.Point.X && mouseData.Point.X < 50)
|
||||
{
|
||||
isDown = true;
|
||||
Task.Delay(100).ContinueWith(_ => CheckPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return User32.CallNextHookEx(handle, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
private void CheckPosition()
|
||||
{
|
||||
var position = new POINT();
|
||||
|
||||
User32.GetCursorPos(ref position);
|
||||
|
||||
if (isDown && position.X > 200)
|
||||
{
|
||||
logger.Debug("Detected activation gesture for action center.");
|
||||
Activate?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private bool Ignore(int wParam)
|
||||
{
|
||||
// For performance reasons, ignore mouse movement and wheel rotation...
|
||||
return wParam == Constant.WM_MOUSEMOVE || wParam == Constant.WM_MOUSEWHEEL;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,6 +48,9 @@ namespace SafeExamBrowser.WindowsApi
|
|||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool GetCursorPos(ref POINT pt);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern IntPtr GetThreadDesktop(int dwThreadId);
|
||||
|
||||
|
|
Loading…
Reference in a new issue