diff --git a/SafeExamBrowser.Applications.Contracts/ApplicationInfo.cs b/SafeExamBrowser.Applications.Contracts/ApplicationInfo.cs
index b47e66f1..58572d10 100644
--- a/SafeExamBrowser.Applications.Contracts/ApplicationInfo.cs
+++ b/SafeExamBrowser.Applications.Contracts/ApplicationInfo.cs
@@ -28,6 +28,6 @@ namespace SafeExamBrowser.Applications.Contracts
///
/// The resource providing the application icon.
///
- public IconResource IconResource { get; set; }
+ public IconResource Icon { get; set; }
}
}
diff --git a/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs b/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs
index fb8a2b35..c92fcab0 100644
--- a/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs
+++ b/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs
@@ -7,6 +7,7 @@
*/
using SafeExamBrowser.Applications.Contracts.Events;
+using SafeExamBrowser.Core.Contracts;
namespace SafeExamBrowser.Applications.Contracts
{
@@ -15,6 +16,11 @@ namespace SafeExamBrowser.Applications.Contracts
///
public interface IApplicationInstance
{
+ ///
+ /// The icon resource for this instance.
+ ///
+ IconResource Icon { get; }
+
///
/// The unique identifier for the application instance.
///
diff --git a/SafeExamBrowser.Applications/ApplicationFactory.cs b/SafeExamBrowser.Applications/ApplicationFactory.cs
index 810ea3ba..8e061650 100644
--- a/SafeExamBrowser.Applications/ApplicationFactory.cs
+++ b/SafeExamBrowser.Applications/ApplicationFactory.cs
@@ -64,7 +64,7 @@ namespace SafeExamBrowser.Applications
private IApplication BuildApplication(string executablePath, WhitelistApplication settings)
{
var icon = new IconResource { Type = IconResourceType.Embedded, Uri = new Uri(executablePath) };
- var info = new ApplicationInfo { IconResource = icon, Name = settings.DisplayName, Tooltip = settings.Description ?? settings.DisplayName };
+ var info = new ApplicationInfo { Icon = icon, Name = settings.DisplayName, Tooltip = settings.Description ?? settings.DisplayName };
var application = new ExternalApplication(executablePath, info, logger.CloneFor(settings.DisplayName), processFactory);
return application;
diff --git a/SafeExamBrowser.Applications/ExternalApplication.cs b/SafeExamBrowser.Applications/ExternalApplication.cs
index 2bf134bb..7d1a3cfe 100644
--- a/SafeExamBrowser.Applications/ExternalApplication.cs
+++ b/SafeExamBrowser.Applications/ExternalApplication.cs
@@ -44,9 +44,11 @@ namespace SafeExamBrowser.Applications
{
logger.Info("Starting application...");
+ // TODO: Ensure that SEB does not crash if an application cannot be started!!
+
var process = processFactory.StartNew(executablePath);
var id = new ApplicationInstanceIdentifier(process.Id);
- var instance = new ExternalApplicationInstance(id, logger.CloneFor($"{Info.Name} {id}"), process);
+ var instance = new ExternalApplicationInstance(Info.Icon, id, logger.CloneFor($"{Info.Name} {id}"), process);
instance.Initialize();
instances.Add(instance);
diff --git a/SafeExamBrowser.Applications/ExternalApplicationInstance.cs b/SafeExamBrowser.Applications/ExternalApplicationInstance.cs
index 3f3dd083..a9512f2c 100644
--- a/SafeExamBrowser.Applications/ExternalApplicationInstance.cs
+++ b/SafeExamBrowser.Applications/ExternalApplicationInstance.cs
@@ -10,6 +10,7 @@ using System;
using System.Timers;
using SafeExamBrowser.Applications.Contracts;
using SafeExamBrowser.Applications.Contracts.Events;
+using SafeExamBrowser.Core.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.WindowsApi.Contracts;
@@ -24,6 +25,7 @@ namespace SafeExamBrowser.Applications
private IProcess process;
private Timer timer;
+ public IconResource Icon { get; }
public InstanceIdentifier Id { get; }
public string Name { get; }
@@ -31,8 +33,9 @@ namespace SafeExamBrowser.Applications
public event NameChangedEventHandler NameChanged;
public event InstanceTerminatedEventHandler Terminated;
- public ExternalApplicationInstance(InstanceIdentifier id, ILogger logger, IProcess process)
+ public ExternalApplicationInstance(IconResource icon, InstanceIdentifier id, ILogger logger, IProcess process)
{
+ this.Icon = icon;
this.Id = id;
this.logger = logger;
this.process = process;
diff --git a/SafeExamBrowser.Browser/BrowserApplication.cs b/SafeExamBrowser.Browser/BrowserApplication.cs
index 45af2b62..0ccd5098 100644
--- a/SafeExamBrowser.Browser/BrowserApplication.cs
+++ b/SafeExamBrowser.Browser/BrowserApplication.cs
@@ -65,7 +65,7 @@ namespace SafeExamBrowser.Browser
var cefSettings = InitializeCefSettings();
var success = Cef.Initialize(cefSettings, true, default(IApp));
- Info = BuildApplicationInfo();
+ InitializeApplicationInfo();
if (success)
{
@@ -95,11 +95,11 @@ namespace SafeExamBrowser.Browser
logger.Info("Terminated browser.");
}
- private ApplicationInfo BuildApplicationInfo()
+ private void InitializeApplicationInfo()
{
- return new ApplicationInfo
+ Info = new ApplicationInfo
{
- IconResource = new BrowserIconResource(),
+ Icon = new BrowserIconResource(),
Name = "Safe Exam Browser",
Tooltip = text.Get(TextKey.Browser_Tooltip)
};
diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
index a257d967..6dfd1e93 100644
--- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
+++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
@@ -17,6 +17,7 @@ using SafeExamBrowser.Browser.Events;
using SafeExamBrowser.Browser.Filters;
using SafeExamBrowser.Browser.Handlers;
using SafeExamBrowser.Configuration.Contracts;
+using SafeExamBrowser.Core.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Settings.Browser;
@@ -48,6 +49,7 @@ namespace SafeExamBrowser.Browser
get { return isMainInstance ? settings.MainWindow : settings.AdditionalWindow; }
}
+ public IconResource Icon { get; private set; }
public InstanceIdentifier Id { get; private set; }
public string Name { get; private set; }
@@ -108,6 +110,8 @@ namespace SafeExamBrowser.Browser
var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} {Id}");
var requestHandler = new RequestHandler(appConfig, settings.Filter, requestFilter, requestLogger, text);
+ Icon = new BrowserIconResource();
+
displayHandler.FaviconChanged += DisplayHandler_FaviconChanged;
displayHandler.ProgressChanged += DisplayHandler_ProgressChanged;
downloadHandler.ConfigurationDownloadRequested += DownloadHandler_ConfigurationDownloadRequested;
@@ -201,10 +205,10 @@ namespace SafeExamBrowser.Browser
{
if (task.IsCompleted && task.Result.IsSuccessStatusCode)
{
- var icon = new BrowserIconResource(uri);
+ Icon = new BrowserIconResource(uri);
- IconChanged?.Invoke(icon);
- window.UpdateIcon(icon);
+ IconChanged?.Invoke(Icon);
+ window.UpdateIcon(Icon);
}
});
}
diff --git a/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs b/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs
index 0a5b4878..a24e02d9 100644
--- a/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs
+++ b/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs
@@ -98,14 +98,12 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
var terminationActivator = new Mock();
context.Activators.Add(actionCenterActivator.Object);
- context.Activators.Add(taskViewActivator.Object);
context.Activators.Add(terminationActivator.Object);
context.Settings.ActionCenter.EnableActionCenter = true;
sut.Perform();
actionCenterActivator.Verify(a => a.Start(), Times.Once);
- taskViewActivator.Verify(a => a.Start(), Times.Once);
terminationActivator.Verify(a => a.Start(), Times.Once);
}
@@ -176,6 +174,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
[TestMethod]
public void Perform_MustInitializeTaskView()
{
+ // Only start activator if ALT+TAB enabled!
Assert.Fail("TODO");
}
diff --git a/SafeExamBrowser.Client/Operations/ShellOperation.cs b/SafeExamBrowser.Client/Operations/ShellOperation.cs
index f67a9ffc..2eaf78b7 100644
--- a/SafeExamBrowser.Client/Operations/ShellOperation.cs
+++ b/SafeExamBrowser.Client/Operations/ShellOperation.cs
@@ -113,7 +113,7 @@ namespace SafeExamBrowser.Client.Operations
actionCenterActivator.Start();
}
- if (activator is ITaskViewActivator taskViewActivator)
+ if (Context.Settings.Keyboard.AllowAltTab && activator is ITaskViewActivator taskViewActivator)
{
taskView.Register(taskViewActivator);
taskViewActivator.Start();
diff --git a/SafeExamBrowser.UserInterface.Contracts/Shell/ITaskViewActivator.cs b/SafeExamBrowser.UserInterface.Contracts/Shell/ITaskViewActivator.cs
index 8d2ed19e..f00c6d76 100644
--- a/SafeExamBrowser.UserInterface.Contracts/Shell/ITaskViewActivator.cs
+++ b/SafeExamBrowser.UserInterface.Contracts/Shell/ITaskViewActivator.cs
@@ -16,13 +16,18 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
public interface ITaskViewActivator : IActivator
{
///
- /// Fired when the next application instance should be selected.
+ /// Fired when the task view should be hidden.
///
- event ActivatorEventHandler Next;
+ event ActivatorEventHandler Deactivated;
///
- /// Fired when the previous application instance should be selected.
+ /// Fired when the task view should be made visible and the next application instance should be selected.
///
- event ActivatorEventHandler Previous;
+ event ActivatorEventHandler NextActivated;
+
+ ///
+ /// Fired when the task view should be made visible and the previous application instance should be selected.
+ ///
+ event ActivatorEventHandler PreviousActivated;
}
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml.cs
index 0e58921f..1ae6d8a3 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml.cs
@@ -32,7 +32,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
private void InitializeApplicationInstanceButton()
{
- Icon.Content = IconResourceLoader.Load(info.IconResource);
+ Icon.Content = IconResourceLoader.Load(info.Icon);
Text.Text = instance?.Name ?? info.Name;
Button.Click += (o, args) => Clicked?.Invoke(this, EventArgs.Empty);
Button.ToolTip = instance?.Name ?? info.Tooltip;
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationControl.xaml.cs
index dba68797..9eb37158 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationControl.xaml.cs
@@ -37,7 +37,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
application.InstanceStarted += Application_InstanceStarted;
Button.Click += Button_Click;
- Button.Content = IconResourceLoader.Load(application.Info.IconResource);
+ Button.Content = IconResourceLoader.Load(application.Info.Icon);
Button.MouseEnter += (o, args) => InstancePopup.IsOpen = InstanceStackPanel.Children.Count > 1;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => InstancePopup.IsOpen = InstancePopup.IsMouseOver));
Button.ToolTip = application.Info.Tooltip;
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationInstanceButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationInstanceButton.xaml.cs
index a848b3c2..e94bcad8 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationInstanceButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarApplicationInstanceButton.xaml.cs
@@ -32,7 +32,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
{
Button.Click += Button_Click;
Button.ToolTip = instance.Name;
- Icon.Content = IconResourceLoader.Load(info.IconResource);
+ Icon.Content = IconResourceLoader.Load(info.Icon);
instance.IconChanged += Instance_IconChanged;
instance.NameChanged += Instance_NameChanged;
Text.Text = instance.Name;
diff --git a/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml b/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml
index 25723e03..6985444f 100644
--- a/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml
+++ b/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml
@@ -4,9 +4,9 @@
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" AllowsTransparency="True" Background="#74000000" BorderBrush="DodgerBlue" BorderThickness="1" Title="TaskView"
- Height="450" Width="800" WindowStartupLocation="CenterScreen" WindowStyle="None">
+ mc:Ignorable="d" AllowsTransparency="True" Background="#AA000000" BorderBrush="DodgerBlue" BorderThickness="1" Title="TaskView"
+ Topmost="True" Height="450" SizeToContent="WidthAndHeight" Width="800" WindowStartupLocation="CenterScreen" WindowStyle="None">
-
+
diff --git a/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml.cs
index f9e380f3..8f88e170 100644
--- a/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/TaskView.xaml.cs
@@ -6,27 +6,156 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Media;
using SafeExamBrowser.Applications.Contracts;
+using SafeExamBrowser.Core.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
+using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Desktop
{
public partial class TaskView : Window, ITaskView
{
+ private IList instances;
+
public TaskView()
{
InitializeComponent();
+ instances = new List();
}
public void Add(IApplication application)
{
-
+ application.InstanceStarted += Application_InstanceStarted;
}
public void Register(ITaskViewActivator activator)
{
-
+ activator.Deactivated += Activator_Deactivated;
+ activator.NextActivated += Activator_Next;
+ activator.PreviousActivated += Activator_Previous;
+ }
+
+ private void Application_InstanceStarted(IApplicationInstance instance)
+ {
+ Dispatcher.InvokeAsync(() =>
+ {
+ instance.IconChanged += Instance_IconChanged;
+ instance.NameChanged += Instance_NameChanged;
+ instance.Terminated += Instance_Terminated;
+
+ instances.Add(instance);
+ Update();
+ });
+ }
+
+ private void Activator_Deactivated()
+ {
+ Dispatcher.InvokeAsync(Hide);
+ }
+
+ private void Activator_Next()
+ {
+ Dispatcher.InvokeAsync(ShowConditional);
+ }
+
+ private void Activator_Previous()
+ {
+ Dispatcher.InvokeAsync(ShowConditional);
+ }
+
+ private void Instance_IconChanged(IconResource icon)
+ {
+ // TODO Dispatcher.InvokeAsync(...);
+ }
+
+ private void Instance_NameChanged(string name)
+ {
+ // TODO Dispatcher.InvokeAsync(...);
+ }
+
+ private void Instance_Terminated(InstanceIdentifier id)
+ {
+ Dispatcher.InvokeAsync(() =>
+ {
+ var instance = instances.FirstOrDefault(i => i.Id == id);
+
+ if (instance != default(IApplicationInstance))
+ {
+ instances.Remove(instance);
+ Update();
+ }
+ });
+ }
+
+ private void ShowConditional()
+ {
+ if (Visibility != Visibility.Visible && instances.Any())
+ {
+ Show();
+ }
+ }
+
+ private void Update()
+ {
+ var max = Math.Ceiling(Math.Sqrt(instances.Count));
+ var stack = new Stack(instances);
+
+ Rows.Children.Clear();
+
+ for (var rowCount = 0; rowCount < max && stack.Any(); rowCount++)
+ {
+ var row = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center };
+
+ Rows.Children.Add(row);
+
+ for (var columnIndex = 0; columnIndex < max && stack.Any(); columnIndex++)
+ {
+ var instance = stack.Pop();
+ var control = BuildInstanceControl(instance);
+
+ row.Children.Add(control);
+ }
+ }
+
+ UpdateLayout();
+
+ Left = (SystemParameters.WorkArea.Width - Width) / 2 + SystemParameters.WorkArea.Left;
+ Top = (SystemParameters.WorkArea.Height - Height) / 2 + SystemParameters.WorkArea.Top;
+
+ if (!instances.Any())
+ {
+ Hide();
+ }
+ }
+
+ private UIElement BuildInstanceControl(IApplicationInstance instance)
+ {
+ var border = new Border();
+ var stackPanel = new StackPanel();
+ var icon = IconResourceLoader.Load(instance.Icon);
+
+ border.BorderBrush = Brushes.White;
+ border.BorderThickness = new Thickness(1);
+ border.Height = 150;
+ border.Margin = new Thickness(5);
+ border.Padding = new Thickness(2);
+ border.Width = 250;
+ border.Child = stackPanel;
+
+ stackPanel.HorizontalAlignment = HorizontalAlignment.Center;
+ stackPanel.Orientation = Orientation.Vertical;
+ stackPanel.VerticalAlignment = VerticalAlignment.Center;
+ stackPanel.Children.Add(new ContentControl { Content = icon, MaxWidth = 50 });
+ stackPanel.Children.Add(new TextBlock(new Run($"Instance {instance.Name ?? "NULL"}") { Foreground = Brushes.White, FontWeight = FontWeights.Bold }));
+
+ return border;
}
}
}
diff --git a/SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenterApplicationButton.xaml.cs b/SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenterApplicationButton.xaml.cs
index eb31f74a..ec29ac3c 100644
--- a/SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenterApplicationButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenterApplicationButton.xaml.cs
@@ -32,7 +32,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
private void InitializeApplicationInstanceButton()
{
- Icon.Content = IconResourceLoader.Load(info.IconResource);
+ Icon.Content = IconResourceLoader.Load(info.Icon);
Text.Text = instance?.Name ?? info.Name;
Button.Click += (o, args) => Clicked?.Invoke(this, EventArgs.Empty);
Button.ToolTip = instance?.Name ?? info.Tooltip;
diff --git a/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationControl.xaml.cs b/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationControl.xaml.cs
index 8923cf44..1e8db711 100644
--- a/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationControl.xaml.cs
@@ -37,7 +37,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
application.InstanceStarted += Application_InstanceStarted;
Button.Click += Button_Click;
- Button.Content = IconResourceLoader.Load(application.Info.IconResource);
+ Button.Content = IconResourceLoader.Load(application.Info.Icon);
Button.MouseEnter += (o, args) => InstancePopup.IsOpen = InstanceStackPanel.Children.Count > 1;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => InstancePopup.IsOpen = InstancePopup.IsMouseOver));
Button.ToolTip = application.Info.Tooltip;
diff --git a/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationInstanceButton.xaml.cs b/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationInstanceButton.xaml.cs
index e901f343..295d4263 100644
--- a/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationInstanceButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Mobile/Controls/TaskbarApplicationInstanceButton.xaml.cs
@@ -32,7 +32,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
{
Button.Click += Button_Click;
Button.ToolTip = instance.Name;
- Icon.Content = IconResourceLoader.Load(info.IconResource);
+ Icon.Content = IconResourceLoader.Load(info.Icon);
instance.IconChanged += Instance_IconChanged;
instance.NameChanged += Instance_NameChanged;
Text.Text = instance.Name;
diff --git a/SafeExamBrowser.UserInterface.Shared/Activators/TaskViewKeyboardActivator.cs b/SafeExamBrowser.UserInterface.Shared/Activators/TaskViewKeyboardActivator.cs
index afb2f513..e3c0276c 100644
--- a/SafeExamBrowser.UserInterface.Shared/Activators/TaskViewKeyboardActivator.cs
+++ b/SafeExamBrowser.UserInterface.Shared/Activators/TaskViewKeyboardActivator.cs
@@ -17,10 +17,12 @@ namespace SafeExamBrowser.UserInterface.Shared.Activators
{
public class TaskViewKeyboardActivator : KeyboardActivator, ITaskViewActivator
{
+ private bool Activated, BlockActivation, LeftShift, Tab;
private ILogger logger;
- public event ActivatorEventHandler Next;
- public event ActivatorEventHandler Previous;
+ public event ActivatorEventHandler Deactivated;
+ public event ActivatorEventHandler NextActivated;
+ public event ActivatorEventHandler PreviousActivated;
public TaskViewKeyboardActivator(ILogger logger, INativeMethods nativeMethods) : base(nativeMethods)
{
@@ -29,17 +31,82 @@ namespace SafeExamBrowser.UserInterface.Shared.Activators
public void Pause()
{
- Paused = true;
+ BlockActivation = true;
}
public void Resume()
{
- Paused = false;
+ BlockActivation = false;
}
protected override bool Process(Key key, KeyModifier modifier, KeyState state)
{
+ if (IsDeactivation(modifier))
+ {
+ return false;
+ }
+
+ if (IsActivation(key, modifier, state))
+ {
+ return true;
+ }
+
return false;
}
+
+ private bool IsActivation(Key key, KeyModifier modifier, KeyState state)
+ {
+ var changed = false;
+ var pressed = state == KeyState.Pressed && modifier.HasFlag(KeyModifier.Alt);
+
+ switch (key)
+ {
+ case Key.Tab:
+ changed = Tab != pressed;
+ Tab = pressed;
+ break;
+ case Key.LeftShift:
+ changed = LeftShift != pressed;
+ LeftShift = pressed;
+ break;
+ }
+
+ var isActivation = Tab && changed;
+
+ if (isActivation && !BlockActivation)
+ {
+ Activated = true;
+
+ if (LeftShift)
+ {
+ logger.Debug("Detected sequence for previous instance.");
+ PreviousActivated?.Invoke();
+ }
+ else
+ {
+ logger.Debug("Detected sequence for next instance.");
+ NextActivated?.Invoke();
+ }
+ }
+
+ return isActivation;
+ }
+
+ private bool IsDeactivation(KeyModifier modifier)
+ {
+ var isDeactivation = Activated && !modifier.HasFlag(KeyModifier.Alt);
+
+ if (isDeactivation)
+ {
+ Activated = false;
+ LeftShift = false;
+ Tab = false;
+
+ logger.Debug("Detected deactivation sequence.");
+ Deactivated?.Invoke();
+ }
+
+ return isDeactivation;
+ }
}
}