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,16 +60,18 @@ 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); | ||||
| 
 | ||||
| 			if (settings.EnableTaskbar) | ||||
| 			{ | ||||
| 				logger.Info("Initializing taskbar..."); | ||||
| 
 | ||||
| 				AddAboutNotification(); | ||||
| 				taskbar.ShowClock = settings.ShowClock; | ||||
| 
 | ||||
|  | @ -94,15 +94,22 @@ namespace SafeExamBrowser.Client.Operations | |||
| 				{ | ||||
| 					AddPowerSupplyControl(); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				logger.Info("Taskbar is disabled, skipping initialization."); | ||||
| 			} | ||||
| 
 | ||||
| 			return OperationResult.Success; | ||||
| 		} | ||||
| 
 | ||||
| 		public OperationResult Revert() | ||||
| 		{ | ||||
| 			logger.Info("Terminating taskbar..."); | ||||
| 			StatusChanged?.Invoke(TextKey.OperationStatus_TerminateTaskbar); | ||||
| 
 | ||||
| 			if (settings.EnableTaskbar) | ||||
| 			{ | ||||
| 				logger.Info("Terminating taskbar..."); | ||||
| 				aboutController.Terminate(); | ||||
| 
 | ||||
| 				if (settings.AllowApplicationLog) | ||||
|  | @ -124,6 +131,11 @@ namespace SafeExamBrowser.Client.Operations | |||
| 				{ | ||||
| 					powerSupply.Terminate(); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				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…
	
	Add table
		
		Reference in a new issue
	
	 dbuechel
						dbuechel