diff --git a/SafeExamBrowser.Browser/BrowserApplicationController.cs b/SafeExamBrowser.Browser/BrowserApplicationController.cs index 8ecced98..63d44006 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationController.cs +++ b/SafeExamBrowser.Browser/BrowserApplicationController.cs @@ -13,6 +13,7 @@ using CefSharp; using SafeExamBrowser.Contracts.Behaviour; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.UserInterface; namespace SafeExamBrowser.Browser @@ -23,10 +24,12 @@ namespace SafeExamBrowser.Browser private IList instances = new List(); private ISettings settings; private IUserInterfaceFactory uiFactory; + private IText text; - public BrowserApplicationController(ISettings settings, IUserInterfaceFactory uiFactory) + public BrowserApplicationController(ISettings settings, IText text, IUserInterfaceFactory uiFactory) { this.settings = settings; + this.text = text; this.uiFactory = uiFactory; } @@ -56,7 +59,7 @@ namespace SafeExamBrowser.Browser { foreach (var instance in instances) { - instance.OnTerminated -= Instance_OnTerminated; + instance.Terminated -= Instance_Terminated; instance.Window.Close(); } @@ -65,17 +68,13 @@ namespace SafeExamBrowser.Browser private void CreateNewInstance() { - var control = new BrowserControl("www.duckduckgo.com"); - var window = uiFactory.CreateBrowserWindow(control, settings.Browser); - var instance = new BrowserApplicationInstance("DuckDuckGo"); - - instance.RegisterWindow(window); - instance.OnTerminated += Instance_OnTerminated; + var instance = new BrowserApplicationInstance(settings.Browser, text, uiFactory, instances.Count == 0); button.RegisterInstance(instance); instances.Add(instance); - window.Show(); + instance.Terminated += Instance_Terminated; + instance.Window.Show(); } private void Button_OnClick(Guid? instanceId = null) @@ -90,7 +89,7 @@ namespace SafeExamBrowser.Browser } } - private void Instance_OnTerminated(Guid id) + private void Instance_Terminated(Guid id) { instances.Remove(instances.FirstOrDefault(i => i.Id == id)); } diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs index afe99d3c..716241c1 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs +++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs @@ -8,28 +8,70 @@ using System; using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Configuration.Settings; +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.UserInterface; namespace SafeExamBrowser.Browser { public class BrowserApplicationInstance : IApplicationInstance { + private IBrowserControl control; + private IBrowserWindow window; + public Guid Id { get; private set; } public string Name { get; private set; } - public IWindow Window { get; private set; } + public IWindow Window { get { return window; } } - public event TerminationEventHandler OnTerminated; + public event TerminationEventHandler Terminated; + public event NameChangedEventHandler NameChanged; - public BrowserApplicationInstance(string name) + public BrowserApplicationInstance(IBrowserSettings settings, IText text, IUserInterfaceFactory uiFactory, bool isMainInstance) { Id = Guid.NewGuid(); - Name = name; + + control = new BrowserControl(settings, text); + control.AddressChanged += Control_AddressChanged; + control.TitleChanged += Control_TitleChanged; + + window = uiFactory.CreateBrowserWindow(control, settings); + window.IsMainWindow = isMainInstance; + window.Closing += () => Terminated?.Invoke(Id); + window.AddressChanged += Window_AddressChanged; + window.ReloadRequested += Window_ReloadRequested; + window.BackwardNavigationRequested += Window_BackwardNavigationRequested; + window.ForwardNavigationRequested += Window_ForwardNavigationRequested; } - public void RegisterWindow(IWindow window) + private void Control_AddressChanged(string address) { - Window = window; - Window.OnClose += () => OnTerminated?.Invoke(Id); + window.UpdateAddress(address); + } + + private void Control_TitleChanged(string title) + { + window.UpdateTitle(title); + NameChanged?.Invoke(title); + } + + private void Window_AddressChanged(string address) + { + control.NavigateTo(address); + } + + private void Window_ReloadRequested() + { + control.Reload(); + } + + private void Window_BackwardNavigationRequested() + { + control.NavigateBackwards(); + } + + private void Window_ForwardNavigationRequested() + { + control.NavigateForwards(); } } } diff --git a/SafeExamBrowser.Browser/BrowserContextMenuHandler.cs b/SafeExamBrowser.Browser/BrowserContextMenuHandler.cs new file mode 100644 index 00000000..ebb5a784 --- /dev/null +++ b/SafeExamBrowser.Browser/BrowserContextMenuHandler.cs @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017 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 CefSharp; +using SafeExamBrowser.Contracts.I18n; +using IBrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.IBrowserSettings; + +namespace SafeExamBrowser.Browser +{ + /// + /// See https://cefsharp.github.io/api/57.0.0/html/T_CefSharp_IContextMenuHandler.htm. + /// + internal class BrowserContextMenuHandler : IContextMenuHandler + { + private const int DEV_CONSOLE_COMMAND = (int) CefMenuCommand.UserFirst + 1; + + private IBrowserSettings settings; + private IText text; + + public BrowserContextMenuHandler(IBrowserSettings settings, IText text) + { + this.settings = settings; + this.text = text; + } + + public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model) + { + model.Clear(); + + if (settings.AllowDeveloperConsole) + { + model.AddItem((CefMenuCommand) DEV_CONSOLE_COMMAND, text.Get(Key.Browser_ShowDeveloperConsole)); + } + } + + public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags) + { + if ((int) commandId == DEV_CONSOLE_COMMAND) + { + browser.ShowDevTools(); + + return true; + } + + return false; + } + + public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame) + { + } + + public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback) + { + return false; + } + } +} diff --git a/SafeExamBrowser.Browser/BrowserControl.cs b/SafeExamBrowser.Browser/BrowserControl.cs index 0f36a774..7e84efc8 100644 --- a/SafeExamBrowser.Browser/BrowserControl.cs +++ b/SafeExamBrowser.Browser/BrowserControl.cs @@ -6,17 +6,70 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using System.Windows.Forms; +using System; using CefSharp.WinForms; +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.UserInterface; +using IBrowserSettings = SafeExamBrowser.Contracts.Configuration.Settings.IBrowserSettings; namespace SafeExamBrowser.Browser { class BrowserControl : ChromiumWebBrowser, IBrowserControl { - public BrowserControl(string url) : base(url) + private AddressChangedHandler addressChanged; + private IBrowserSettings settings; + private TitleChangedHandler titleChanged; + private IText text; + + event AddressChangedHandler IBrowserControl.AddressChanged { - Dock = DockStyle.Fill; + add { addressChanged += value; } + remove { addressChanged -= value; } + } + + event TitleChangedHandler IBrowserControl.TitleChanged + { + add { titleChanged += value; } + remove { titleChanged -= value; } + } + + public BrowserControl(IBrowserSettings settings, IText text) : base(settings.StartUrl) + { + this.settings = settings; + this.text = text; + + Initialize(); + } + + public void NavigateBackwards() + { + GetBrowser().GoBack(); + } + + public void NavigateForwards() + { + GetBrowser().GoForward(); + } + + public void NavigateTo(string address) + { + if (!String.IsNullOrWhiteSpace(address) && Uri.IsWellFormedUriString(address, UriKind.RelativeOrAbsolute)) + { + Load(address); + } + } + + public void Reload() + { + GetBrowser().Reload(); + } + + private void Initialize() + { + AddressChanged += (o, args) => addressChanged?.Invoke(args.Address); + TitleChanged += (o, args) => titleChanged?.Invoke(args.Title); + + MenuHandler = new BrowserContextMenuHandler(settings, text); } } } diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj index 943aa3a8..5d206b91 100644 --- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj +++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj @@ -67,6 +67,7 @@ + Component diff --git a/SafeExamBrowser.Configuration/Settings/BrowserSettings.cs b/SafeExamBrowser.Configuration/Settings/BrowserSettings.cs index 9a1eb38d..7fe549b6 100644 --- a/SafeExamBrowser.Configuration/Settings/BrowserSettings.cs +++ b/SafeExamBrowser.Configuration/Settings/BrowserSettings.cs @@ -23,24 +23,26 @@ namespace SafeExamBrowser.Configuration.Settings public bool AllowAddressBar => true; - public bool AllowBackwardNavigation => false; + public bool AllowBackwardNavigation => true; - public bool AllowDebugConsole => true; + public bool AllowDeveloperConsole => true; - public bool AllowForwardNavigation => false; + public bool AllowForwardNavigation => true; - public bool AllowReloading => false; + public bool AllowReloading => true; public string CachePath { get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), settings.AppDataFolderName, "Cache"); } } - public bool FullScreenMode => throw new NotImplementedException(); + public bool FullScreenMode => false; public string LogFile { get { return Path.Combine(settings.LogFolderPath, $"{settings.RuntimeIdentifier}_Browser.txt"); } } + + public string StartUrl => "www.duckduckgo.com"; } } diff --git a/SafeExamBrowser.Contracts/Configuration/IApplicationInstance.cs b/SafeExamBrowser.Contracts/Configuration/IApplicationInstance.cs index af69fcea..476dfc7c 100644 --- a/SafeExamBrowser.Contracts/Configuration/IApplicationInstance.cs +++ b/SafeExamBrowser.Contracts/Configuration/IApplicationInstance.cs @@ -12,6 +12,7 @@ using SafeExamBrowser.Contracts.UserInterface; namespace SafeExamBrowser.Contracts.Configuration { public delegate void TerminationEventHandler(Guid id); + public delegate void NameChangedEventHandler(string name); public interface IApplicationInstance { @@ -28,16 +29,16 @@ namespace SafeExamBrowser.Contracts.Configuration /// /// Event fired when the application instance has been terminated. /// - event TerminationEventHandler OnTerminated; + event TerminationEventHandler Terminated; + + /// + /// Event fired when the name or (document) title of the application instance has changed. + /// + event NameChangedEventHandler NameChanged; /// /// The main window of the application instance. /// IWindow Window { get; } - - /// - /// Registers the given window as the main window of the application instance. - /// - void RegisterWindow(IWindow window); } } diff --git a/SafeExamBrowser.Contracts/Configuration/Settings/IBrowserSettings.cs b/SafeExamBrowser.Contracts/Configuration/Settings/IBrowserSettings.cs index 07aeb3c1..f33df0f9 100644 --- a/SafeExamBrowser.Contracts/Configuration/Settings/IBrowserSettings.cs +++ b/SafeExamBrowser.Contracts/Configuration/Settings/IBrowserSettings.cs @@ -21,9 +21,9 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings bool AllowBackwardNavigation { get; } /// - /// Determines whether the user should be allowed to open the debug console of a browser window. + /// Determines whether the user should be allowed to open the developer console of a browser window. /// - bool AllowDebugConsole { get; } + bool AllowDeveloperConsole { get; } /// /// Determines whether the user should be allowed to navigate forwards in a browser window. @@ -49,5 +49,10 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings /// Determines whether the main browser window should be rendered in fullscreen mode, i.e. without window frame. /// bool FullScreenMode { get; } + + /// + /// The start URL with which a new browser window should be loaded. + /// + string StartUrl { get; } } } diff --git a/SafeExamBrowser.Contracts/I18n/Key.cs b/SafeExamBrowser.Contracts/I18n/Key.cs index 70475318..f90221a5 100644 --- a/SafeExamBrowser.Contracts/I18n/Key.cs +++ b/SafeExamBrowser.Contracts/I18n/Key.cs @@ -13,6 +13,7 @@ namespace SafeExamBrowser.Contracts.I18n /// public enum Key { + Browser_ShowDeveloperConsole, MessageBox_ShutdownError, MessageBox_ShutdownErrorTitle, MessageBox_SingleInstance, diff --git a/SafeExamBrowser.Contracts/UserInterface/IBrowserControl.cs b/SafeExamBrowser.Contracts/UserInterface/IBrowserControl.cs index e6501147..cdb7ece3 100644 --- a/SafeExamBrowser.Contracts/UserInterface/IBrowserControl.cs +++ b/SafeExamBrowser.Contracts/UserInterface/IBrowserControl.cs @@ -8,7 +8,39 @@ namespace SafeExamBrowser.Contracts.UserInterface { + public delegate void AddressChangedHandler(string address); + public delegate void TitleChangedHandler(string title); + public interface IBrowserControl { + /// + /// Event fired when the address of the browser control changes. + /// + event AddressChangedHandler AddressChanged; + + /// + /// Event fired when the current page (and thus the title) of the browser control changes. + /// + event TitleChangedHandler TitleChanged; + + /// + /// Navigates to the previous page in the browser control history. + /// + void NavigateBackwards(); + + /// + /// Navigates to the next page in the browser control history. + /// + void NavigateForwards(); + + /// + /// Navigates to the specified web address. + /// + void NavigateTo(string address); + + /// + /// Reloads the current web page. + /// + void Reload(); } } diff --git a/SafeExamBrowser.Contracts/UserInterface/IBrowserWindow.cs b/SafeExamBrowser.Contracts/UserInterface/IBrowserWindow.cs index 7d920d84..5c200537 100644 --- a/SafeExamBrowser.Contracts/UserInterface/IBrowserWindow.cs +++ b/SafeExamBrowser.Contracts/UserInterface/IBrowserWindow.cs @@ -8,7 +8,43 @@ namespace SafeExamBrowser.Contracts.UserInterface { + public delegate void ActionRequestedHandler(); + public interface IBrowserWindow : IWindow { + /// + /// Event fired when the user changed the URL. + /// + event AddressChangedHandler AddressChanged; + + /// + /// Event fired when the user would like to navigate backwards. + /// + event ActionRequestedHandler BackwardNavigationRequested; + + /// + /// Event fired when the user would like to navigate forwards. + /// + event ActionRequestedHandler ForwardNavigationRequested; + + /// + /// Event fired when the user would like to reload the current page. + /// + event ActionRequestedHandler ReloadRequested; + + /// + /// Determines whether this window is the main browser window. + /// + bool IsMainWindow { get; set; } + + /// + /// Updates the address bar of the browser window to the given value; + /// + void UpdateAddress(string adress); + + /// + /// Sets the title of the browser window to the given value; + /// + void UpdateTitle(string title); } } diff --git a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs index baa6c258..e40bac2d 100644 --- a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs +++ b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs @@ -20,7 +20,7 @@ namespace SafeExamBrowser.Contracts.UserInterface ITaskbarButton CreateApplicationButton(IApplicationInfo info); /// - /// Creates a new browser window loaded with the given browser control. + /// Creates a new browser window loaded with the given browser control and settings. /// IBrowserWindow CreateBrowserWindow(IBrowserControl control, IBrowserSettings settings); diff --git a/SafeExamBrowser.Contracts/UserInterface/IWindow.cs b/SafeExamBrowser.Contracts/UserInterface/IWindow.cs index 986d16b0..8bb88b77 100644 --- a/SafeExamBrowser.Contracts/UserInterface/IWindow.cs +++ b/SafeExamBrowser.Contracts/UserInterface/IWindow.cs @@ -8,14 +8,14 @@ namespace SafeExamBrowser.Contracts.UserInterface { - public delegate void WindowCloseHandler(); + public delegate void WindowClosingHandler(); public interface IWindow { /// /// Event fired when the window is closing. /// - event WindowCloseHandler OnClose; + event WindowClosingHandler Closing; /// /// Brings the window to the foreground. diff --git a/SafeExamBrowser.Core/I18n/Text.xml b/SafeExamBrowser.Core/I18n/Text.xml index 39de7e61..61400cf4 100644 --- a/SafeExamBrowser.Core/I18n/Text.xml +++ b/SafeExamBrowser.Core/I18n/Text.xml @@ -1,24 +1,25 @@  - An unexpected error occurred during the shutdown procedure! Please consult the application log for more information... - Shutdown Error - An unexpected error occurred during the startup procedure! Please consult the application log for more information... - Startup Error - About Safe Exam Browser - Initializing browser - Initializing process monitoring - Initializing taskbar - Initializing window monitoring - Initializing working area - Restoring working area - Initiating shutdown procedure - Starting event handling - Initiating startup procedure - Stopping event handling - Stopping process monitoring - Stopping window monitoring - Terminating browser - Waiting for Windows explorer to start up - Waiting for Windows explorer to shut down - Version + Open Console + An unexpected error occurred during the shutdown procedure! Please consult the application log for more information... + Shutdown Error + An unexpected error occurred during the startup procedure! Please consult the application log for more information... + Startup Error + About Safe Exam Browser + Initializing browser + Initializing process monitoring + Initializing taskbar + Initializing window monitoring + Initializing working area + Restoring working area + Initiating shutdown procedure + Starting event handling + Initiating startup procedure + Stopping event handling + Stopping process monitoring + Stopping window monitoring + Terminating browser + Waiting for Windows explorer to start up + Waiting for Windows explorer to shut down + Version \ No newline at end of file diff --git a/SafeExamBrowser.UserInterface/BrowserWindow.xaml b/SafeExamBrowser.UserInterface/BrowserWindow.xaml index f09eba9e..57f6697b 100644 --- a/SafeExamBrowser.UserInterface/BrowserWindow.xaml +++ b/SafeExamBrowser.UserInterface/BrowserWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface" mc:Ignorable="d" - Title="BrowserWindow" Height="500" Width="500" WindowState="Maximized"> + Title="BrowserWindow" Height="500" Width="500" WindowState="Maximized" Icon=".\Images\Chromium.ico"> diff --git a/SafeExamBrowser.UserInterface/BrowserWindow.xaml.cs b/SafeExamBrowser.UserInterface/BrowserWindow.xaml.cs index 1cf2a2ff..4d9efea8 100644 --- a/SafeExamBrowser.UserInterface/BrowserWindow.xaml.cs +++ b/SafeExamBrowser.UserInterface/BrowserWindow.xaml.cs @@ -7,6 +7,7 @@ */ using System.Windows; +using System.Windows.Controls; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.UserInterface; @@ -14,9 +15,33 @@ namespace SafeExamBrowser.UserInterface { public partial class BrowserWindow : Window, IBrowserWindow { + private bool isMainWindow; private IBrowserSettings settings; + public WindowClosingHandler closing; - public event WindowCloseHandler OnClose; + public bool IsMainWindow + { + get + { + return isMainWindow; + } + set + { + isMainWindow = value; + ApplySettings(); + } + } + + public event AddressChangedHandler AddressChanged; + public event ActionRequestedHandler BackwardNavigationRequested; + public event ActionRequestedHandler ForwardNavigationRequested; + public event ActionRequestedHandler ReloadRequested; + + event WindowClosingHandler IWindow.Closing + { + add { closing += value; } + remove { closing -= value; } + } public BrowserWindow(IBrowserControl browserControl, IBrowserSettings settings) { @@ -36,6 +61,26 @@ namespace SafeExamBrowser.UserInterface Activate(); } + public void UpdateAddress(string url) + { + Dispatcher.Invoke(() => + { + UrlTextBox.TextChanged -= UrlTextBox_TextChanged; + UrlTextBox.Text = url; + UrlTextBox.TextChanged += UrlTextBox_TextChanged; + }); + } + + public void UpdateTitle(string title) + { + Dispatcher.Invoke(() => Title = title); + } + + private void UrlTextBox_TextChanged(object sender, TextChangedEventArgs e) + { + AddressChanged?.Invoke(UrlTextBox.Text); + } + private void InitializeBrowserWindow(IBrowserControl browserControl) { if (browserControl is System.Windows.Forms.Control) @@ -43,8 +88,26 @@ namespace SafeExamBrowser.UserInterface BrowserControlHost.Child = browserControl as System.Windows.Forms.Control; } + Closing += (o, args) => closing?.Invoke(); + UrlTextBox.TextChanged += UrlTextBox_TextChanged; + ReloadButton.Click += (o, args) => ReloadRequested?.Invoke(); + BackButton.Click += (o, args) => BackwardNavigationRequested?.Invoke(); + ForwardButton.Click += (o, args) => ForwardNavigationRequested?.Invoke(); + + ApplySettings(); + } + + private void ApplySettings() + { + if (IsMainWindow && settings.FullScreenMode) + { + MaxHeight = SystemParameters.WorkArea.Height; + ResizeMode = ResizeMode.NoResize; + WindowState = WindowState.Maximized; + WindowStyle = WindowStyle.None; + } + UrlTextBox.IsEnabled = settings.AllowAddressBar; - UrlTextBox.Visibility = settings.AllowAddressBar ? Visibility.Visible : Visibility.Collapsed; ReloadButton.IsEnabled = settings.AllowReloading; ReloadButton.Visibility = settings.AllowReloading ? Visibility.Visible : Visibility.Collapsed; @@ -54,8 +117,6 @@ namespace SafeExamBrowser.UserInterface ForwardButton.IsEnabled = settings.AllowForwardNavigation; ForwardButton.Visibility = settings.AllowForwardNavigation ? Visibility.Visible : Visibility.Collapsed; - - Closing += (o, args) => OnClose?.Invoke(); } } } diff --git a/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml b/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml index 67808356..d309c7d8 100644 --- a/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml +++ b/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml @@ -37,7 +37,7 @@ - + diff --git a/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml.cs b/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml.cs index 6a7b0be6..ba963f3a 100644 --- a/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml.cs +++ b/SafeExamBrowser.UserInterface/Controls/ApplicationButton.xaml.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; +using System.Windows.Media; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.UserInterface; using SafeExamBrowser.UserInterface.Utilities; @@ -37,7 +38,7 @@ namespace SafeExamBrowser.UserInterface.Controls var instanceButton = new ApplicationInstanceButton(instance, info); instanceButton.Click += (id) => OnClick?.Invoke(id); - instance.OnTerminated += (id) => Instance_OnTerminated(id, instanceButton); + instance.Terminated += (id) => Instance_OnTerminated(id, instanceButton); instances.Add(instance); InstanceStackPanel.Children.Add(instanceButton); @@ -49,13 +50,24 @@ namespace SafeExamBrowser.UserInterface.Controls { Button.ToolTip = info.Tooltip; Button.Content = IconResourceLoader.Load(info.IconResource); - + Button.MouseEnter += (o, args) => InstancePopup.IsOpen = instances.Count > 1; Button.MouseLeave += (o, args) => InstancePopup.IsOpen &= InstancePopup.IsMouseOver || ActiveBar.IsMouseOver; ActiveBar.MouseLeave += (o, args) => InstancePopup.IsOpen &= InstancePopup.IsMouseOver || Button.IsMouseOver; InstancePopup.MouseLeave += (o, args) => InstancePopup.IsOpen = false; - InstancePopup.Opened += (o, args) => ActiveBar.Width = Double.NaN; - InstancePopup.Closed += (o, args) => ActiveBar.Width = 40; + + InstancePopup.Opened += (o, args) => + { + ActiveBar.Width = Double.NaN; + Background = (Brush) new BrushConverter().ConvertFrom("#2AFFFFFF"); + }; + + InstancePopup.Closed += (o, args) => + { + ActiveBar.Width = 40; + Background = (Brush) new BrushConverter().ConvertFrom("#00000000"); + }; + InstanceStackPanel.SizeChanged += (o, args) => { if (instances.Count > 9) diff --git a/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml b/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml index 58d24d64..dd2616a5 100644 --- a/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml +++ b/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml @@ -10,7 +10,7 @@ - + diff --git a/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml.cs b/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml.cs index 58a20fb2..38adbd36 100644 --- a/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml.cs +++ b/SafeExamBrowser.UserInterface/Controls/ApplicationInstanceButton.xaml.cs @@ -36,7 +36,16 @@ namespace SafeExamBrowser.UserInterface.Controls { Icon.Content = IconResourceLoader.Load(info.IconResource); Text.Text = instance.Name; - Button.ToolTip = $"{instance.Name} - {info.Name}"; + Button.ToolTip = instance.Name; + + instance.NameChanged += (name) => + { + Dispatcher.Invoke(() => + { + Text.Text = name; + Button.ToolTip = name; + }); + }; } private void Button_Click(object sender, RoutedEventArgs e) diff --git a/SafeExamBrowser.UserInterface/Images/Chromium.ico b/SafeExamBrowser.UserInterface/Images/Chromium.ico new file mode 100644 index 00000000..46025b80 Binary files /dev/null and b/SafeExamBrowser.UserInterface/Images/Chromium.ico differ diff --git a/SafeExamBrowser.UserInterface/SafeExamBrowser.UserInterface.csproj b/SafeExamBrowser.UserInterface/SafeExamBrowser.UserInterface.csproj index 452abed7..74f6cc2d 100644 --- a/SafeExamBrowser.UserInterface/SafeExamBrowser.UserInterface.csproj +++ b/SafeExamBrowser.UserInterface/SafeExamBrowser.UserInterface.csproj @@ -163,5 +163,8 @@ + + + \ No newline at end of file diff --git a/SafeExamBrowser/CompositionRoot.cs b/SafeExamBrowser/CompositionRoot.cs index c9494ec9..841bcb97 100644 --- a/SafeExamBrowser/CompositionRoot.cs +++ b/SafeExamBrowser/CompositionRoot.cs @@ -63,10 +63,11 @@ namespace SafeExamBrowser text = new Text(textResource); aboutInfo = new AboutNotificationInfo(text); - browserController = new BrowserApplicationController(settings, uiFactory); + browserController = new BrowserApplicationController(settings, text, uiFactory); processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods); windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)), nativeMethods); workingArea = new WorkingArea(new ModuleLogger(logger, typeof(WorkingArea)), nativeMethods); + eventController = new EventController(new ModuleLogger(logger, typeof(EventController)), processMonitor, Taskbar, windowMonitor, workingArea); ShutdownController = new ShutdownController(logger, settings, text, uiFactory); StartupController = new StartupController(logger, settings, text, uiFactory);