SEBWIN-312: Removed IApplicationInstance from API as it is irrelevant to the shell (which cares only about applications and their windows).
This commit is contained in:
parent
fa9b84ba68
commit
4503cbe778
36 changed files with 374 additions and 488 deletions
|
@ -11,7 +11,7 @@ using SafeExamBrowser.Core.Contracts;
|
|||
namespace SafeExamBrowser.Applications.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler used to indicate that the icon of an <see cref="IApplicationInstance"/> has changed.
|
||||
/// Event handler used to indicate that an icon has changed.
|
||||
/// </summary>
|
||||
public delegate void IconChangedEventHandler(IconResource icon);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
namespace SafeExamBrowser.Applications.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler used to inform about the existence of a new <see cref="IApplicationInstance"/>.
|
||||
/// Event handler used to indicate that a title has changed to a new value.
|
||||
/// </summary>
|
||||
public delegate void InstanceStartedEventHandler(IApplicationInstance instance);
|
||||
public delegate void TitleChangedEventHandler(string title);
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
namespace SafeExamBrowser.Applications.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler used to indicate that a name has changed to a new value.
|
||||
/// Event handler used to indicate that the windows of an application have changed.
|
||||
/// </summary>
|
||||
public delegate void NameChangedEventHandler(string name);
|
||||
public delegate void WindowsChangedEventHandler();
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Applications.Contracts.Events;
|
||||
|
||||
namespace SafeExamBrowser.Applications.Contracts
|
||||
|
@ -21,9 +22,14 @@ namespace SafeExamBrowser.Applications.Contracts
|
|||
ApplicationInfo Info { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Fired when a new <see cref="IApplicationInstance"/> has started.
|
||||
/// Event fired when the windows of the application have changed.
|
||||
/// </summary>
|
||||
event InstanceStartedEventHandler InstanceStarted;
|
||||
event WindowsChangedEventHandler WindowsChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Returns all windows of the application.
|
||||
/// </summary>
|
||||
IEnumerable<IApplicationWindow> GetWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Performs any initialization work, if necessary.
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* 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.Applications.Contracts.Events;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Applications.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines an instance of an application which can be accessed via the shell.
|
||||
/// </summary>
|
||||
public interface IApplicationInstance
|
||||
{
|
||||
/// <summary>
|
||||
/// The icon resource for this instance.
|
||||
/// </summary>
|
||||
IconResource Icon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The unique identifier for the application instance.
|
||||
/// </summary>
|
||||
InstanceIdentifier Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name or document title of the application instance.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the icon of the application instance has changed.
|
||||
/// </summary>
|
||||
event IconChangedEventHandler IconChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the name or (document) title of the application instance has changed.
|
||||
/// </summary>
|
||||
event NameChangedEventHandler NameChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the application instance has been terminated.
|
||||
/// </summary>
|
||||
event InstanceTerminatedEventHandler Terminated;
|
||||
|
||||
/// <summary>
|
||||
/// Makes this instance the currently active one and brings it to the foreground.
|
||||
/// </summary>
|
||||
void Activate();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the application instance.
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Terminates the application instance.
|
||||
/// </summary>
|
||||
void Terminate();
|
||||
}
|
||||
}
|
44
SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs
Normal file
44
SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.Applications.Contracts.Events;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Applications.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a window of an <see cref="IApplication"/>.
|
||||
/// </summary>
|
||||
public interface IApplicationWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// The icon of the window.
|
||||
/// </summary>
|
||||
IconResource Icon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The title of the window.
|
||||
/// </summary>
|
||||
string Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the icon of the window has changed.
|
||||
/// </summary>
|
||||
event IconChangedEventHandler IconChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the title of the window has changed.
|
||||
/// </summary>
|
||||
event TitleChangedEventHandler TitleChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Brings the window to the foreground and activates it.
|
||||
/// </summary>
|
||||
void Activate();
|
||||
}
|
||||
}
|
|
@ -55,14 +55,13 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Events\IconChangedEventHandler.cs" />
|
||||
<Compile Include="Events\InstanceStartedEventHandler.cs" />
|
||||
<Compile Include="Events\InstanceTerminatedEventHandler.cs" />
|
||||
<Compile Include="Events\NameChangedEventHandler.cs" />
|
||||
<Compile Include="Events\TitleChangedEventHandler.cs" />
|
||||
<Compile Include="Events\WindowsChangedEventHandler.cs" />
|
||||
<Compile Include="FactoryResult.cs" />
|
||||
<Compile Include="IApplication.cs" />
|
||||
<Compile Include="IApplicationFactory.cs" />
|
||||
<Compile Include="ApplicationInfo.cs" />
|
||||
<Compile Include="IApplicationInstance.cs" />
|
||||
<Compile Include="IApplicationWindow.cs" />
|
||||
<Compile Include="InstanceIdentifier.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -20,22 +20,27 @@ namespace SafeExamBrowser.Applications
|
|||
{
|
||||
private string executablePath;
|
||||
private IModuleLogger logger;
|
||||
private IList<IApplicationInstance> instances;
|
||||
private IList<ExternalApplicationInstance> instances;
|
||||
private IProcessFactory processFactory;
|
||||
|
||||
public ApplicationInfo Info { get; }
|
||||
public event WindowsChangedEventHandler WindowsChanged;
|
||||
|
||||
public event InstanceStartedEventHandler InstanceStarted;
|
||||
public ApplicationInfo Info { get; }
|
||||
|
||||
internal ExternalApplication(string executablePath, ApplicationInfo info, IModuleLogger logger, IProcessFactory processFactory)
|
||||
{
|
||||
this.executablePath = executablePath;
|
||||
this.Info = info;
|
||||
this.logger = logger;
|
||||
this.instances = new List<IApplicationInstance>();
|
||||
this.instances = new List<ExternalApplicationInstance>();
|
||||
this.processFactory = processFactory;
|
||||
}
|
||||
|
||||
public IEnumerable<IApplicationWindow> GetWindows()
|
||||
{
|
||||
return Enumerable.Empty<IApplicationWindow>();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// Nothing to do here for now.
|
||||
|
@ -53,7 +58,6 @@ namespace SafeExamBrowser.Applications
|
|||
|
||||
instance.Initialize();
|
||||
instances.Add(instance);
|
||||
InstanceStarted?.Invoke(instance);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -6,57 +6,34 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
namespace SafeExamBrowser.Applications
|
||||
{
|
||||
internal class ExternalApplicationInstance : IApplicationInstance
|
||||
internal class ExternalApplicationInstance
|
||||
{
|
||||
private const int ONE_SECOND = 1000;
|
||||
|
||||
private IconResource icon;
|
||||
private InstanceIdentifier id;
|
||||
private ILogger logger;
|
||||
private IProcess process;
|
||||
private Timer timer;
|
||||
|
||||
public IconResource Icon { get; }
|
||||
public InstanceIdentifier Id { get; }
|
||||
public string Name { get; private set; }
|
||||
|
||||
public event IconChangedEventHandler IconChanged { add { } remove { } }
|
||||
public event NameChangedEventHandler NameChanged;
|
||||
public event InstanceTerminatedEventHandler Terminated;
|
||||
|
||||
public ExternalApplicationInstance(IconResource icon, InstanceIdentifier id, ILogger logger, IProcess process)
|
||||
internal ExternalApplicationInstance(IconResource icon, InstanceIdentifier id, ILogger logger, IProcess process)
|
||||
{
|
||||
this.Icon = icon;
|
||||
this.Id = id;
|
||||
this.icon = icon;
|
||||
this.id = id;
|
||||
this.logger = logger;
|
||||
this.process = process;
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
internal void Initialize()
|
||||
{
|
||||
var success = process.TryActivate();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
logger.Warn("Failed to activate instance!");
|
||||
}
|
||||
process.Terminated += Process_Terminated;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
InitializeEvents();
|
||||
logger.Info("Initialized application instance.");
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
internal void Terminate()
|
||||
{
|
||||
const int MAX_ATTEMPTS = 5;
|
||||
const int TIMEOUT_MS = 500;
|
||||
|
@ -65,7 +42,7 @@ namespace SafeExamBrowser.Applications
|
|||
|
||||
if (!terminated)
|
||||
{
|
||||
FinalizeEvents();
|
||||
process.Terminated -= Process_Terminated;
|
||||
|
||||
for (var attempt = 0; attempt < MAX_ATTEMPTS && !terminated; attempt++)
|
||||
{
|
||||
|
@ -91,37 +68,7 @@ namespace SafeExamBrowser.Applications
|
|||
private void Process_Terminated(int exitCode)
|
||||
{
|
||||
logger.Info($"Application instance has terminated with exit code {exitCode}.");
|
||||
FinalizeEvents();
|
||||
Terminated?.Invoke(Id);
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
timer = new Timer(ONE_SECOND);
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
timer.Start();
|
||||
process.Terminated += Process_Terminated;
|
||||
}
|
||||
|
||||
private void FinalizeEvents()
|
||||
{
|
||||
timer.Elapsed -= Timer_Elapsed;
|
||||
timer.Stop();
|
||||
process.Terminated -= Process_Terminated;
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
var success = process.TryGetWindowTitle(out var title);
|
||||
var hasChanged = Name?.Equals(title, StringComparison.Ordinal) != true;
|
||||
|
||||
if (success && hasChanged)
|
||||
{
|
||||
Name = title;
|
||||
NameChanged?.Invoke(Name);
|
||||
}
|
||||
|
||||
timer.Start();
|
||||
// TODO: Terminated?.Invoke(Id); -> Remove from application!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace SafeExamBrowser.Browser
|
|||
public ApplicationInfo Info { get; private set; }
|
||||
|
||||
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
||||
public event InstanceStartedEventHandler InstanceStarted;
|
||||
public event WindowsChangedEventHandler WindowsChanged;
|
||||
|
||||
public BrowserApplication(
|
||||
AppConfig appConfig,
|
||||
|
@ -60,6 +60,11 @@ namespace SafeExamBrowser.Browser
|
|||
this.uiFactory = uiFactory;
|
||||
}
|
||||
|
||||
public IEnumerable<IApplicationWindow> GetWindows()
|
||||
{
|
||||
return new List<IApplicationWindow>(instances);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var cefSettings = InitializeCefSettings();
|
||||
|
@ -119,9 +124,9 @@ namespace SafeExamBrowser.Browser
|
|||
|
||||
instance.Initialize();
|
||||
instances.Add(instance);
|
||||
InstanceStarted?.Invoke(instance);
|
||||
|
||||
logger.Info($"Created browser instance {instance.Id}.");
|
||||
WindowsChanged?.Invoke();
|
||||
}
|
||||
|
||||
private CefSettings InitializeCefSettings()
|
||||
|
@ -156,6 +161,7 @@ namespace SafeExamBrowser.Browser
|
|||
{
|
||||
instances.Remove(instances.FirstOrDefault(i => i.Id == id));
|
||||
logger.Info($"Browser instance {id} was terminated.");
|
||||
WindowsChanged?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -27,7 +27,7 @@ using SafeExamBrowser.UserInterface.Contracts.MessageBox;
|
|||
|
||||
namespace SafeExamBrowser.Browser
|
||||
{
|
||||
internal class BrowserApplicationInstance : IApplicationInstance
|
||||
internal class BrowserApplicationInstance : IApplicationWindow
|
||||
{
|
||||
private const double ZOOM_FACTOR = 0.2;
|
||||
|
||||
|
@ -49,20 +49,22 @@ 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; }
|
||||
internal BrowserInstanceIdentifier Id { get; private set; }
|
||||
|
||||
public IconResource Icon { get; private set; }
|
||||
public string Title { get; private set; }
|
||||
|
||||
internal event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
||||
internal event PopupRequestedEventHandler PopupRequested;
|
||||
internal event InstanceTerminatedEventHandler Terminated;
|
||||
|
||||
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
||||
public event IconChangedEventHandler IconChanged;
|
||||
public event NameChangedEventHandler NameChanged;
|
||||
public event PopupRequestedEventHandler PopupRequested;
|
||||
public event InstanceTerminatedEventHandler Terminated;
|
||||
public event TitleChangedEventHandler TitleChanged;
|
||||
|
||||
public BrowserApplicationInstance(
|
||||
AppConfig appConfig,
|
||||
BrowserSettings settings,
|
||||
InstanceIdentifier id,
|
||||
BrowserInstanceIdentifier id,
|
||||
bool isMainInstance,
|
||||
IMessageBox messageBox,
|
||||
IModuleLogger logger,
|
||||
|
@ -84,18 +86,18 @@ namespace SafeExamBrowser.Browser
|
|||
|
||||
public void Activate()
|
||||
{
|
||||
window?.BringToForeground();
|
||||
window.BringToForeground();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
internal void Initialize()
|
||||
{
|
||||
InitializeControl();
|
||||
InitializeWindow();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
internal void Terminate()
|
||||
{
|
||||
window?.Close();
|
||||
window.Close();
|
||||
}
|
||||
|
||||
private void InitializeControl()
|
||||
|
@ -194,9 +196,9 @@ namespace SafeExamBrowser.Browser
|
|||
|
||||
private void Control_TitleChanged(string title)
|
||||
{
|
||||
Name = title;
|
||||
window.UpdateTitle(Name);
|
||||
NameChanged?.Invoke(Name);
|
||||
Title = title;
|
||||
window.UpdateTitle(Title);
|
||||
TitleChanged?.Invoke(Title);
|
||||
}
|
||||
|
||||
private void DisplayHandler_FaviconChanged(string uri)
|
||||
|
@ -267,7 +269,7 @@ namespace SafeExamBrowser.Browser
|
|||
if (url == this.url)
|
||||
{
|
||||
window.UpdateTitle($"*** {title} ***");
|
||||
NameChanged?.Invoke($"*** {title} ***");
|
||||
TitleChanged?.Invoke($"*** {title} ***");
|
||||
}
|
||||
|
||||
messageBox.Show(message, title, parent: window);
|
||||
|
|
|
@ -6,12 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.Applications.Contracts.Events
|
||||
namespace SafeExamBrowser.Browser.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler used to indicate that an <see cref="IApplicationInstance"/> has terminated.
|
||||
/// </summary>
|
||||
public delegate void InstanceTerminatedEventHandler(InstanceIdentifier id);
|
||||
internal delegate void InstanceTerminatedEventHandler(BrowserInstanceIdentifier id);
|
||||
}
|
|
@ -65,6 +65,7 @@
|
|||
<Compile Include="BrowserApplicationInstance.cs" />
|
||||
<Compile Include="BrowserInstanceIdentifier.cs" />
|
||||
<Compile Include="Events\FaviconChangedEventHandler.cs" />
|
||||
<Compile Include="Events\InstanceTerminatedEventHandler.cs" />
|
||||
<Compile Include="Events\PopupRequestedEventArgs.cs" />
|
||||
<Compile Include="Events\PopupRequestedEventHandler.cs" />
|
||||
<Compile Include="Events\ProgressChangedEventHandler.cs" />
|
||||
|
|
|
@ -17,14 +17,14 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
public partial class ActionCenterApplicationButton : UserControl
|
||||
{
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
private IApplicationWindow window;
|
||||
|
||||
internal event EventHandler Clicked;
|
||||
|
||||
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationInstance instance = null)
|
||||
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationWindow window = null)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
this.window = window;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationInstanceButton();
|
||||
|
@ -33,28 +33,28 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
private void InitializeApplicationInstanceButton()
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(info.Icon);
|
||||
Text.Text = instance?.Name ?? info.Name;
|
||||
Text.Text = window?.Title ?? info.Name;
|
||||
Button.Click += (o, args) => Clicked?.Invoke(this, EventArgs.Empty);
|
||||
Button.ToolTip = instance?.Name ?? info.Tooltip;
|
||||
Button.ToolTip = window?.Title ?? info.Tooltip;
|
||||
|
||||
if (instance != null)
|
||||
if (window != null)
|
||||
{
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
window.IconChanged += Window_IconChanged;
|
||||
window.TitleChanged += Window_TitleChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
private void Window_IconChanged(IconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
private void Window_TitleChanged(string title)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Text.Text = name;
|
||||
Button.ToolTip = name;
|
||||
Text.Text = title;
|
||||
Button.ToolTip = title;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" x:Name="ApplicationName" Background="{StaticResource BackgroundTransparentEmphasisBrush}" FontWeight="Bold" Padding="5" TextAlignment="Center" />
|
||||
<ContentControl Grid.Row="1" x:Name="ApplicationButton" FontWeight="Bold" />
|
||||
<StackPanel Grid.Row="2" x:Name="InstancePanel" Background="{StaticResource BackgroundTransparentEmphasisBrush}" Orientation="Vertical" />
|
||||
<StackPanel Grid.Row="2" x:Name="WindowPanel" Background="{StaticResource BackgroundTransparentEmphasisBrush}" Orientation="Vertical" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -29,40 +29,42 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
{
|
||||
var button = new ActionCenterApplicationButton(application.Info);
|
||||
|
||||
application.InstanceStarted += Application_InstanceStarted;
|
||||
application.WindowsChanged += Application_WindowsChanged;
|
||||
button.Clicked += (o, args) => application.Start();
|
||||
ApplicationName.Text = application.Info.Name;
|
||||
ApplicationName.Visibility = Visibility.Collapsed;
|
||||
ApplicationButton.Content = button;
|
||||
}
|
||||
|
||||
private void Application_InstanceStarted(IApplicationInstance instance)
|
||||
private void Application_WindowsChanged()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var button = new ActionCenterApplicationButton(application.Info, instance);
|
||||
|
||||
button.Clicked += (o, args) => instance.Activate();
|
||||
instance.Terminated += (_) => RemoveInstance(button);
|
||||
InstancePanel.Children.Add(button);
|
||||
|
||||
ApplicationName.Visibility = Visibility.Visible;
|
||||
ApplicationButton.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
Dispatcher.InvokeAsync(Update);
|
||||
}
|
||||
|
||||
private void RemoveInstance(ActionCenterApplicationButton button)
|
||||
private void Update()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
InstancePanel.Children.Remove(button);
|
||||
var windows = application.GetWindows();
|
||||
|
||||
if (InstancePanel.Children.Count == 0)
|
||||
{
|
||||
ApplicationName.Visibility = Visibility.Collapsed;
|
||||
ApplicationButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
});
|
||||
WindowPanel.Children.Clear();
|
||||
|
||||
foreach (var window in windows)
|
||||
{
|
||||
var button = new ActionCenterApplicationButton(application.Info, window);
|
||||
|
||||
button.Clicked += (o, args) => window.Activate();
|
||||
WindowPanel.Children.Add(button);
|
||||
}
|
||||
|
||||
if (WindowPanel.Children.Count == 0)
|
||||
{
|
||||
ApplicationName.Visibility = Visibility.Collapsed;
|
||||
ApplicationButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplicationName.Visibility = Visibility.Visible;
|
||||
ApplicationButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskViewInstanceControl"
|
||||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskViewWindowControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
@ -14,15 +14,13 @@ using SafeExamBrowser.UserInterface.Shared.Utilities;
|
|||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class TaskViewInstanceControl : UserControl
|
||||
public partial class TaskViewWindowControl : UserControl
|
||||
{
|
||||
private IApplicationInstance instance;
|
||||
private IApplicationWindow window;
|
||||
|
||||
internal InstanceIdentifier Id => instance.Id;
|
||||
|
||||
public TaskViewInstanceControl(IApplicationInstance instance)
|
||||
public TaskViewWindowControl(IApplicationWindow window)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.window = window;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeControl();
|
||||
|
@ -30,7 +28,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
|
||||
internal void Activate()
|
||||
{
|
||||
instance.Activate();
|
||||
window.Activate();
|
||||
}
|
||||
|
||||
internal void Deselect()
|
||||
|
@ -49,21 +47,21 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
|
||||
private void InitializeControl()
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(instance.Icon);
|
||||
Title.Text = instance.Name;
|
||||
Icon.Content = IconResourceLoader.Load(window.Icon);
|
||||
Title.Text = window.Title;
|
||||
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
window.IconChanged += Instance_IconChanged;
|
||||
window.TitleChanged += Instance_TitleChanged;
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
private void Instance_TitleChanged(string title)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Title.Text = name);
|
||||
Dispatcher.InvokeAsync(() => Title.Text = title);
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(instance.Icon));
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(window.Icon));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,10 +16,10 @@
|
|||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="InstancePopup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Popup x:Name="WindowPopup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="0.75,0.75,0.75,0">
|
||||
<ScrollViewer x:Name="InstanceScrollViewer" MaxHeight="400" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="InstanceStackPanel" />
|
||||
<ScrollViewer MaxHeight="400" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="WindowStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
@ -20,7 +21,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
public partial class TaskbarApplicationControl : UserControl, IApplicationControl
|
||||
{
|
||||
private IApplication application;
|
||||
private IApplicationInstance single;
|
||||
private IApplicationWindow single;
|
||||
|
||||
public TaskbarApplicationControl(IApplication application)
|
||||
{
|
||||
|
@ -34,71 +35,64 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
{
|
||||
var originalBrush = Button.Background;
|
||||
|
||||
application.InstanceStarted += Application_InstanceStarted;
|
||||
application.WindowsChanged += Application_WindowsChanged;
|
||||
|
||||
Button.Click += Button_Click;
|
||||
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.MouseEnter += (o, args) => WindowPopup.IsOpen = WindowStackPanel.Children.Count > 0;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = WindowPopup.IsMouseOver));
|
||||
Button.ToolTip = application.Info.Tooltip;
|
||||
InstancePopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => InstancePopup.IsOpen = IsMouseOver));
|
||||
WindowPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = IsMouseOver));
|
||||
|
||||
InstancePopup.Opened += (o, args) =>
|
||||
WindowPopup.Opened += (o, args) =>
|
||||
{
|
||||
Background = Brushes.LightGray;
|
||||
Button.Background = Brushes.LightGray;
|
||||
};
|
||||
|
||||
InstancePopup.Closed += (o, args) =>
|
||||
WindowPopup.Closed += (o, args) =>
|
||||
{
|
||||
Background = originalBrush;
|
||||
Button.Background = originalBrush;
|
||||
};
|
||||
}
|
||||
|
||||
private void Application_InstanceStarted(IApplicationInstance instance)
|
||||
private void Application_WindowsChanged()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var button = new TaskbarApplicationInstanceButton(instance, application.Info);
|
||||
|
||||
instance.Terminated += (_) => RemoveInstance(button);
|
||||
InstanceStackPanel.Children.Add(button);
|
||||
|
||||
if (single == default(IApplicationInstance))
|
||||
{
|
||||
single = instance;
|
||||
}
|
||||
});
|
||||
Dispatcher.InvokeAsync(Update);
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (InstanceStackPanel.Children.Count == 0)
|
||||
if (WindowStackPanel.Children.Count == 0)
|
||||
{
|
||||
application.Start();
|
||||
}
|
||||
else if (InstanceStackPanel.Children.Count == 1)
|
||||
else if (WindowStackPanel.Children.Count == 1)
|
||||
{
|
||||
single.Activate();
|
||||
single?.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var windows = application.GetWindows();
|
||||
|
||||
WindowStackPanel.Children.Clear();
|
||||
|
||||
foreach (var window in windows)
|
||||
{
|
||||
WindowStackPanel.Children.Add(new TaskbarApplicationWindowButton(window));
|
||||
}
|
||||
|
||||
if (WindowStackPanel.Children.Count == 1)
|
||||
{
|
||||
single = windows.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
InstancePopup.IsOpen = true;
|
||||
single = default(IApplicationWindow);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveInstance(TaskbarApplicationInstanceButton button)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
InstanceStackPanel.Children.Remove(button);
|
||||
|
||||
if (InstanceStackPanel.Children.Count == 0)
|
||||
{
|
||||
single = default(IApplicationInstance);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskbarApplicationInstanceButton"
|
||||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskbarApplicationWindowButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
@ -14,15 +14,13 @@ using SafeExamBrowser.UserInterface.Shared.Utilities;
|
|||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class TaskbarApplicationInstanceButton : UserControl
|
||||
public partial class TaskbarApplicationWindowButton : UserControl
|
||||
{
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
private IApplicationWindow window;
|
||||
|
||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, ApplicationInfo info)
|
||||
public TaskbarApplicationWindowButton(IApplicationWindow window)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
this.window = window;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationInstanceButton();
|
||||
|
@ -31,16 +29,16 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
private void InitializeApplicationInstanceButton()
|
||||
{
|
||||
Button.Click += Button_Click;
|
||||
Button.ToolTip = instance.Name;
|
||||
Icon.Content = IconResourceLoader.Load(info.Icon);
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
Text.Text = instance.Name;
|
||||
Button.ToolTip = window.Title;
|
||||
Icon.Content = IconResourceLoader.Load(window.Icon);
|
||||
window.IconChanged += Instance_IconChanged;
|
||||
window.TitleChanged += Window_TitleChanged;
|
||||
Text.Text = window.Title;
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
instance.Activate();
|
||||
window.Activate();
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
|
@ -48,12 +46,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
private void Window_TitleChanged(string title)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Text.Text = name;
|
||||
Button.ToolTip = name;
|
||||
Text.Text = title;
|
||||
Button.ToolTip = title;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -112,8 +112,8 @@
|
|||
<Compile Include="Controls\TaskbarApplicationControl.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarApplicationInstanceButton.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationInstanceButton.xaml</DependentUpon>
|
||||
<Compile Include="Controls\TaskbarApplicationWindowButton.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationWindowButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarAudioControl.xaml.cs">
|
||||
<DependentUpon>TaskbarAudioControl.xaml</DependentUpon>
|
||||
|
@ -142,8 +142,8 @@
|
|||
<Compile Include="Controls\TaskbarWirelessNetworkControl.xaml.cs">
|
||||
<DependentUpon>TaskbarWirelessNetworkControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskViewInstanceControl.xaml.cs">
|
||||
<DependentUpon>TaskViewInstanceControl.xaml</DependentUpon>
|
||||
<Compile Include="Controls\TaskViewWindowControl.xaml.cs">
|
||||
<DependentUpon>TaskViewWindowControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LockScreen.xaml.cs">
|
||||
<DependentUpon>LockScreen.xaml</DependentUpon>
|
||||
|
@ -229,7 +229,7 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarApplicationInstanceButton.xaml">
|
||||
<Page Include="Controls\TaskbarApplicationWindowButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
|
@ -317,7 +317,7 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Resource>
|
||||
<Page Include="Controls\TaskViewInstanceControl.xaml">
|
||||
<Page Include="Controls\TaskViewWindowControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
|
|
|
@ -19,21 +19,22 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
{
|
||||
public partial class TaskView : Window, ITaskView
|
||||
{
|
||||
private LinkedListNode<TaskViewInstanceControl> current;
|
||||
private LinkedList<TaskViewInstanceControl> controls;
|
||||
private List<IApplicationInstance> instances;
|
||||
private IList<IApplication> applications;
|
||||
private LinkedListNode<TaskViewWindowControl> current;
|
||||
private LinkedList<TaskViewWindowControl> controls;
|
||||
|
||||
public TaskView()
|
||||
{
|
||||
controls = new LinkedList<TaskViewInstanceControl>();
|
||||
instances = new List<IApplicationInstance>();
|
||||
applications = new List<IApplication>();
|
||||
controls = new LinkedList<TaskViewWindowControl>();
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Add(IApplication application)
|
||||
{
|
||||
application.InstanceStarted += Application_InstanceStarted;
|
||||
application.WindowsChanged += Application_WindowsChanged;
|
||||
applications.Add(application);
|
||||
}
|
||||
|
||||
public void Register(ITaskViewActivator activator)
|
||||
|
@ -43,9 +44,9 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
activator.PreviousActivated += Activator_Previous;
|
||||
}
|
||||
|
||||
private void Application_InstanceStarted(IApplicationInstance instance)
|
||||
private void Application_WindowsChanged()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Add(instance));
|
||||
Dispatcher.InvokeAsync(Update);
|
||||
}
|
||||
|
||||
private void Activator_Deactivated()
|
||||
|
@ -63,11 +64,6 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
Dispatcher.InvokeAsync(SelectPrevious);
|
||||
}
|
||||
|
||||
private void Instance_Terminated(InstanceIdentifier id)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Remove(id));
|
||||
}
|
||||
|
||||
private void ActivateAndHide()
|
||||
{
|
||||
Activate();
|
||||
|
@ -75,24 +71,6 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
Hide();
|
||||
}
|
||||
|
||||
private void Add(IApplicationInstance instance)
|
||||
{
|
||||
instance.Terminated += Instance_Terminated;
|
||||
instances.Add(instance);
|
||||
Update();
|
||||
}
|
||||
|
||||
private void Remove(InstanceIdentifier id)
|
||||
{
|
||||
var instance = instances.FirstOrDefault(i => i.Id == id);
|
||||
|
||||
if (instance != default(IApplicationInstance))
|
||||
{
|
||||
instances.Remove(instance);
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectNext()
|
||||
{
|
||||
ShowConditional();
|
||||
|
@ -119,7 +97,7 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
|
||||
private void ShowConditional()
|
||||
{
|
||||
if (instances.Any() && Visibility != Visibility.Visible)
|
||||
if (controls.Any() && Visibility != Visibility.Visible)
|
||||
{
|
||||
Show();
|
||||
Activate();
|
||||
|
@ -128,22 +106,31 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
|
||||
private void Update()
|
||||
{
|
||||
var max = Math.Ceiling(Math.Sqrt(instances.Count));
|
||||
var stack = new Stack<IApplicationInstance>(instances);
|
||||
var windows = new Stack<IApplicationWindow>();
|
||||
|
||||
foreach (var application in applications)
|
||||
{
|
||||
foreach (var window in application.GetWindows())
|
||||
{
|
||||
windows.Push(window);
|
||||
}
|
||||
}
|
||||
|
||||
var max = Math.Ceiling(Math.Sqrt(windows.Count));
|
||||
|
||||
controls.Clear();
|
||||
Rows.Children.Clear();
|
||||
|
||||
for (var rowCount = 0; rowCount < max && stack.Any(); rowCount++)
|
||||
for (var rowCount = 0; rowCount < max && windows.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++)
|
||||
for (var columnIndex = 0; columnIndex < max && windows.Any(); columnIndex++)
|
||||
{
|
||||
var instance = stack.Pop();
|
||||
var control = new TaskViewInstanceControl(instance);
|
||||
var window = windows.Pop();
|
||||
var control = new TaskViewWindowControl(window);
|
||||
|
||||
controls.AddLast(control);
|
||||
row.Children.Add(control);
|
||||
|
@ -158,7 +145,7 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
Left = (SystemParameters.WorkArea.Width - Width) / 2 + SystemParameters.WorkArea.Left;
|
||||
Top = (SystemParameters.WorkArea.Height - Height) / 2 + SystemParameters.WorkArea.Top;
|
||||
|
||||
if (!instances.Any())
|
||||
if (!windows.Any())
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
|
|
@ -17,14 +17,14 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
public partial class ActionCenterApplicationButton : UserControl
|
||||
{
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
private IApplicationWindow window;
|
||||
|
||||
internal event EventHandler Clicked;
|
||||
|
||||
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationInstance instance = null)
|
||||
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationWindow window = null)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
this.window = window;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationInstanceButton();
|
||||
|
@ -33,28 +33,28 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
private void InitializeApplicationInstanceButton()
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(info.Icon);
|
||||
Text.Text = instance?.Name ?? info.Name;
|
||||
Text.Text = window?.Title ?? info.Name;
|
||||
Button.Click += (o, args) => Clicked?.Invoke(this, EventArgs.Empty);
|
||||
Button.ToolTip = instance?.Name ?? info.Tooltip;
|
||||
Button.ToolTip = window?.Title ?? info.Tooltip;
|
||||
|
||||
if (instance != null)
|
||||
if (window != null)
|
||||
{
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
window.IconChanged += Window_IconChanged;
|
||||
window.TitleChanged += Window_TitleChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
private void Window_IconChanged(IconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
private void Window_TitleChanged(string title)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Text.Text = name;
|
||||
Button.ToolTip = name;
|
||||
Text.Text = title;
|
||||
Button.ToolTip = title;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" x:Name="ApplicationName" Background="{StaticResource BackgroundTransparentEmphasisBrush}" FontWeight="Bold" Padding="5" TextAlignment="Center" />
|
||||
<ContentControl Grid.Row="1" x:Name="ApplicationButton" FontWeight="Bold" />
|
||||
<StackPanel Grid.Row="2" x:Name="InstancePanel" Background="{StaticResource BackgroundTransparentEmphasisBrush}" Orientation="Vertical" />
|
||||
<StackPanel Grid.Row="2" x:Name="WindowPanel" Background="{StaticResource BackgroundTransparentEmphasisBrush}" Orientation="Vertical" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -29,40 +29,42 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
{
|
||||
var button = new ActionCenterApplicationButton(application.Info);
|
||||
|
||||
application.InstanceStarted += Application_InstanceStarted;
|
||||
application.WindowsChanged += Application_WindowsChanged;
|
||||
button.Clicked += (o, args) => application.Start();
|
||||
ApplicationName.Text = application.Info.Name;
|
||||
ApplicationName.Visibility = Visibility.Collapsed;
|
||||
ApplicationButton.Content = button;
|
||||
}
|
||||
|
||||
private void Application_InstanceStarted(IApplicationInstance instance)
|
||||
private void Application_WindowsChanged()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var button = new ActionCenterApplicationButton(application.Info, instance);
|
||||
|
||||
button.Clicked += (o, args) => instance.Activate();
|
||||
instance.Terminated += (_) => RemoveInstance(button);
|
||||
InstancePanel.Children.Add(button);
|
||||
|
||||
ApplicationName.Visibility = Visibility.Visible;
|
||||
ApplicationButton.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
Dispatcher.InvokeAsync(Update);
|
||||
}
|
||||
|
||||
private void RemoveInstance(ActionCenterApplicationButton button)
|
||||
private void Update()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
InstancePanel.Children.Remove(button);
|
||||
var windows = application.GetWindows();
|
||||
|
||||
if (InstancePanel.Children.Count == 0)
|
||||
{
|
||||
ApplicationName.Visibility = Visibility.Collapsed;
|
||||
ApplicationButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
});
|
||||
WindowPanel.Children.Clear();
|
||||
|
||||
foreach (var window in windows)
|
||||
{
|
||||
var button = new ActionCenterApplicationButton(application.Info, window);
|
||||
|
||||
button.Clicked += (o, args) => window.Activate();
|
||||
WindowPanel.Children.Add(button);
|
||||
}
|
||||
|
||||
if (WindowPanel.Children.Count == 0)
|
||||
{
|
||||
ApplicationName.Visibility = Visibility.Collapsed;
|
||||
ApplicationButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplicationName.Visibility = Visibility.Visible;
|
||||
ApplicationButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskViewInstanceControl"
|
||||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskViewWindowControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
@ -14,15 +14,13 @@ using SafeExamBrowser.UserInterface.Shared.Utilities;
|
|||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskViewInstanceControl : UserControl
|
||||
public partial class TaskViewWindowControl : UserControl
|
||||
{
|
||||
private IApplicationInstance instance;
|
||||
private IApplicationWindow window;
|
||||
|
||||
internal InstanceIdentifier Id => instance.Id;
|
||||
|
||||
public TaskViewInstanceControl(IApplicationInstance instance)
|
||||
public TaskViewWindowControl(IApplicationWindow window)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.window = window;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeControl();
|
||||
|
@ -30,7 +28,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
|
||||
internal void Activate()
|
||||
{
|
||||
instance.Activate();
|
||||
window.Activate();
|
||||
}
|
||||
|
||||
internal void Deselect()
|
||||
|
@ -49,21 +47,21 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
|
||||
private void InitializeControl()
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(instance.Icon);
|
||||
Title.Text = instance.Name;
|
||||
Icon.Content = IconResourceLoader.Load(window.Icon);
|
||||
Title.Text = window.Title;
|
||||
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
window.IconChanged += Instance_IconChanged;
|
||||
window.TitleChanged += Instance_TitleChanged;
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
private void Instance_TitleChanged(string title)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Title.Text = name);
|
||||
Dispatcher.InvokeAsync(() => Title.Text = title);
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(instance.Icon));
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(window.Icon));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,10 +16,10 @@
|
|||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="InstancePopup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Popup x:Name="WindowPopup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="0.75,0.75,0.75,0">
|
||||
<ScrollViewer x:Name="InstanceScrollViewer" MaxHeight="400" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="InstanceStackPanel" />
|
||||
<ScrollViewer MaxHeight="400" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="WindowStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
@ -20,7 +21,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
public partial class TaskbarApplicationControl : UserControl, IApplicationControl
|
||||
{
|
||||
private IApplication application;
|
||||
private IApplicationInstance single;
|
||||
private IApplicationWindow single;
|
||||
|
||||
public TaskbarApplicationControl(IApplication application)
|
||||
{
|
||||
|
@ -34,71 +35,64 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
{
|
||||
var originalBrush = Button.Background;
|
||||
|
||||
application.InstanceStarted += Application_InstanceStarted;
|
||||
application.WindowsChanged += Application_WindowsChanged;
|
||||
|
||||
Button.Click += Button_Click;
|
||||
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.MouseEnter += (o, args) => WindowPopup.IsOpen = WindowStackPanel.Children.Count > 0;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = WindowPopup.IsMouseOver));
|
||||
Button.ToolTip = application.Info.Tooltip;
|
||||
InstancePopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => InstancePopup.IsOpen = IsMouseOver));
|
||||
WindowPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = IsMouseOver));
|
||||
|
||||
InstancePopup.Opened += (o, args) =>
|
||||
WindowPopup.Opened += (o, args) =>
|
||||
{
|
||||
Background = Brushes.LightGray;
|
||||
Button.Background = Brushes.LightGray;
|
||||
};
|
||||
|
||||
InstancePopup.Closed += (o, args) =>
|
||||
WindowPopup.Closed += (o, args) =>
|
||||
{
|
||||
Background = originalBrush;
|
||||
Button.Background = originalBrush;
|
||||
};
|
||||
}
|
||||
|
||||
private void Application_InstanceStarted(IApplicationInstance instance)
|
||||
private void Application_WindowsChanged()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var button = new TaskbarApplicationInstanceButton(instance, application.Info);
|
||||
|
||||
instance.Terminated += (_) => RemoveInstance(button);
|
||||
InstanceStackPanel.Children.Add(button);
|
||||
|
||||
if (single == default(IApplicationInstance))
|
||||
{
|
||||
single = instance;
|
||||
}
|
||||
});
|
||||
Dispatcher.InvokeAsync(Update);
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (InstanceStackPanel.Children.Count == 0)
|
||||
if (WindowStackPanel.Children.Count == 0)
|
||||
{
|
||||
application.Start();
|
||||
}
|
||||
else if (InstanceStackPanel.Children.Count == 1)
|
||||
else if (WindowStackPanel.Children.Count == 1)
|
||||
{
|
||||
single.Activate();
|
||||
single?.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var windows = application.GetWindows();
|
||||
|
||||
WindowStackPanel.Children.Clear();
|
||||
|
||||
foreach (var window in windows)
|
||||
{
|
||||
WindowStackPanel.Children.Add(new TaskbarApplicationWindowButton(window));
|
||||
}
|
||||
|
||||
if (WindowStackPanel.Children.Count == 1)
|
||||
{
|
||||
single = windows.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
InstancePopup.IsOpen = true;
|
||||
single = default(IApplicationWindow);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveInstance(TaskbarApplicationInstanceButton button)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
InstanceStackPanel.Children.Remove(button);
|
||||
|
||||
if (InstanceStackPanel.Children.Count == 0)
|
||||
{
|
||||
single = default(IApplicationInstance);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarApplicationInstanceButton"
|
||||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarApplicationWindowButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
@ -14,15 +14,13 @@ using SafeExamBrowser.UserInterface.Shared.Utilities;
|
|||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarApplicationInstanceButton : UserControl
|
||||
public partial class TaskbarApplicationWindowButton : UserControl
|
||||
{
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
private IApplicationWindow window;
|
||||
|
||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, ApplicationInfo info)
|
||||
public TaskbarApplicationWindowButton(IApplicationWindow window)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
this.window = window;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationInstanceButton();
|
||||
|
@ -31,16 +29,16 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
private void InitializeApplicationInstanceButton()
|
||||
{
|
||||
Button.Click += Button_Click;
|
||||
Button.ToolTip = instance.Name;
|
||||
Icon.Content = IconResourceLoader.Load(info.Icon);
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
Text.Text = instance.Name;
|
||||
Button.ToolTip = window.Title;
|
||||
Icon.Content = IconResourceLoader.Load(window.Icon);
|
||||
window.IconChanged += Instance_IconChanged;
|
||||
window.TitleChanged += Window_TitleChanged;
|
||||
Text.Text = window.Title;
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
instance.Activate();
|
||||
window.Activate();
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
|
@ -48,12 +46,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
private void Window_TitleChanged(string title)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Text.Text = name;
|
||||
Button.ToolTip = name;
|
||||
Text.Text = title;
|
||||
Button.ToolTip = title;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -113,8 +113,8 @@
|
|||
<Compile Include="Controls\TaskbarApplicationControl.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarApplicationInstanceButton.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationInstanceButton.xaml</DependentUpon>
|
||||
<Compile Include="Controls\TaskbarApplicationWindowButton.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationWindowButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarAudioControl.xaml.cs">
|
||||
<DependentUpon>TaskbarAudioControl.xaml</DependentUpon>
|
||||
|
@ -143,8 +143,8 @@
|
|||
<Compile Include="Controls\TaskbarWirelessNetworkControl.xaml.cs">
|
||||
<DependentUpon>TaskbarWirelessNetworkControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskViewInstanceControl.xaml.cs">
|
||||
<DependentUpon>TaskViewInstanceControl.xaml</DependentUpon>
|
||||
<Compile Include="Controls\TaskViewWindowControl.xaml.cs">
|
||||
<DependentUpon>TaskViewWindowControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LockScreen.xaml.cs">
|
||||
<DependentUpon>LockScreen.xaml</DependentUpon>
|
||||
|
@ -283,7 +283,7 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarApplicationInstanceButton.xaml">
|
||||
<Page Include="Controls\TaskbarApplicationWindowButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
|
@ -359,7 +359,7 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Resource>
|
||||
<Page Include="Controls\TaskViewInstanceControl.xaml">
|
||||
<Page Include="Controls\TaskViewWindowControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
|
|
|
@ -19,21 +19,22 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
{
|
||||
public partial class TaskView : Window, ITaskView
|
||||
{
|
||||
private LinkedListNode<TaskViewInstanceControl> current;
|
||||
private LinkedList<TaskViewInstanceControl> controls;
|
||||
private List<IApplicationInstance> instances;
|
||||
private IList<IApplication> applications;
|
||||
private LinkedListNode<TaskViewWindowControl> current;
|
||||
private LinkedList<TaskViewWindowControl> controls;
|
||||
|
||||
public TaskView()
|
||||
{
|
||||
controls = new LinkedList<TaskViewInstanceControl>();
|
||||
instances = new List<IApplicationInstance>();
|
||||
applications = new List<IApplication>();
|
||||
controls = new LinkedList<TaskViewWindowControl>();
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Add(IApplication application)
|
||||
{
|
||||
application.InstanceStarted += Application_InstanceStarted;
|
||||
application.WindowsChanged += Application_WindowsChanged;
|
||||
applications.Add(application);
|
||||
}
|
||||
|
||||
public void Register(ITaskViewActivator activator)
|
||||
|
@ -43,9 +44,9 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
activator.PreviousActivated += Activator_Previous;
|
||||
}
|
||||
|
||||
private void Application_InstanceStarted(IApplicationInstance instance)
|
||||
private void Application_WindowsChanged()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Add(instance));
|
||||
Dispatcher.InvokeAsync(Update);
|
||||
}
|
||||
|
||||
private void Activator_Deactivated()
|
||||
|
@ -63,11 +64,6 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
Dispatcher.InvokeAsync(SelectPrevious);
|
||||
}
|
||||
|
||||
private void Instance_Terminated(InstanceIdentifier id)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Remove(id));
|
||||
}
|
||||
|
||||
private void ActivateAndHide()
|
||||
{
|
||||
Activate();
|
||||
|
@ -75,24 +71,6 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
Hide();
|
||||
}
|
||||
|
||||
private void Add(IApplicationInstance instance)
|
||||
{
|
||||
instance.Terminated += Instance_Terminated;
|
||||
instances.Add(instance);
|
||||
Update();
|
||||
}
|
||||
|
||||
private void Remove(InstanceIdentifier id)
|
||||
{
|
||||
var instance = instances.FirstOrDefault(i => i.Id == id);
|
||||
|
||||
if (instance != default(IApplicationInstance))
|
||||
{
|
||||
instances.Remove(instance);
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectNext()
|
||||
{
|
||||
ShowConditional();
|
||||
|
@ -119,7 +97,7 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
|
||||
private void ShowConditional()
|
||||
{
|
||||
if (instances.Any() && Visibility != Visibility.Visible)
|
||||
if (controls.Any() && Visibility != Visibility.Visible)
|
||||
{
|
||||
Show();
|
||||
Activate();
|
||||
|
@ -128,22 +106,31 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
|
||||
private void Update()
|
||||
{
|
||||
var max = Math.Ceiling(Math.Sqrt(instances.Count));
|
||||
var stack = new Stack<IApplicationInstance>(instances);
|
||||
var windows = new Stack<IApplicationWindow>();
|
||||
|
||||
foreach (var application in applications)
|
||||
{
|
||||
foreach (var window in application.GetWindows())
|
||||
{
|
||||
windows.Push(window);
|
||||
}
|
||||
}
|
||||
|
||||
var max = Math.Ceiling(Math.Sqrt(windows.Count));
|
||||
|
||||
controls.Clear();
|
||||
Rows.Children.Clear();
|
||||
|
||||
for (var rowCount = 0; rowCount < max && stack.Any(); rowCount++)
|
||||
for (var rowCount = 0; rowCount < max && windows.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++)
|
||||
for (var columnIndex = 0; columnIndex < max && windows.Any(); columnIndex++)
|
||||
{
|
||||
var instance = stack.Pop();
|
||||
var control = new TaskViewInstanceControl(instance);
|
||||
var window = windows.Pop();
|
||||
var control = new TaskViewWindowControl(window);
|
||||
|
||||
controls.AddLast(control);
|
||||
row.Children.Add(control);
|
||||
|
@ -158,7 +145,7 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
Left = (SystemParameters.WorkArea.Width - Width) / 2 + SystemParameters.WorkArea.Left;
|
||||
Top = (SystemParameters.WorkArea.Height - Height) / 2 + SystemParameters.WorkArea.Top;
|
||||
|
||||
if (!instances.Any())
|
||||
if (!windows.Any())
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
|
|
@ -40,12 +40,6 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
/// </summary>
|
||||
event ProcessTerminatedEventHandler Terminated;
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to activate the process (i.e. bring its main window to the foreground). This may only work for interactive processes which have
|
||||
/// a main window. Returns <c>true</c> if the process was successfully activated, otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
bool TryActivate();
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to gracefully terminate the process by closing its main window. This will only work for interactive processes which have a main
|
||||
/// window. Optionally waits the specified amount of time for the process to terminate. Returns <c>true</c> if the process has terminated,
|
||||
|
@ -53,12 +47,6 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
/// </summary>
|
||||
bool TryClose(int timeout_ms = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to retrieve the title of the main window of the process. This will only work if for interactive processes which have a main
|
||||
/// window. Returns <c>true</c> if the title was successfully retrieved, otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
bool TryGetWindowTitle(out string title);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to immediately kill the process. Optionally waits the specified amount of time for the process to terminate. Returns <c>true</c>
|
||||
/// if the process has terminated, otherwise <c>false</c>.
|
||||
|
|
Loading…
Reference in a new issue