diff --git a/SafeExamBrowser.I18n.Contracts/TextKey.cs b/SafeExamBrowser.I18n.Contracts/TextKey.cs
index b45a251b..da2ce5a7 100644
--- a/SafeExamBrowser.I18n.Contracts/TextKey.cs
+++ b/SafeExamBrowser.I18n.Contracts/TextKey.cs
@@ -26,6 +26,7 @@ namespace SafeExamBrowser.I18n.Contracts
Browser_PrintNotAllowed,
Browser_Tooltip,
BrowserWindow_BackwardButton,
+ BrowserWindow_CloseButton,
BrowserWindow_DeveloperConsoleMenuItem,
BrowserWindow_Downloading,
BrowserWindow_DownloadCancelled,
@@ -37,6 +38,9 @@ namespace SafeExamBrowser.I18n.Contracts
BrowserWindow_HomeButton,
BrowserWindow_MenuButton,
BrowserWindow_ReloadButton,
+ BrowserWindow_SearchNext,
+ BrowserWindow_SearchPrevious,
+ BrowserWindow_SearchTextBox,
BrowserWindow_UrlTextBox,
BrowserWindow_ZoomLevelReset,
BrowserWindow_ZoomMenuItem,
diff --git a/SafeExamBrowser.I18n/Data/de.xml b/SafeExamBrowser.I18n/Data/de.xml
index 2e56014f..f5449e50 100644
--- a/SafeExamBrowser.I18n/Data/de.xml
+++ b/SafeExamBrowser.I18n/Data/de.xml
@@ -31,7 +31,7 @@
Drucken ist nicht erlaubt gemäss der aktiven Konfiguration.
- Browser Applikation
+ Geöffnete Websites
Entwickler-Konsole
@@ -69,6 +69,9 @@
Menü
+
+ Schliessen
+
URL eingeben
@@ -84,6 +87,15 @@
Zoom verkleinern
+
+ Text eingeben zum Suchen
+
+
+ Nächstes Suchresultat
+
+
+ Vorheriges Suchresultat
+
Build
diff --git a/SafeExamBrowser.I18n/Data/en.xml b/SafeExamBrowser.I18n/Data/en.xml
index c4c35e5d..df82cb90 100644
--- a/SafeExamBrowser.I18n/Data/en.xml
+++ b/SafeExamBrowser.I18n/Data/en.xml
@@ -31,7 +31,7 @@
Printing is not allowed according to the current configuration.
- Browser Application
+ Open Webpages
Developer Console
@@ -69,6 +69,9 @@
Menu
+
+ Close
+
Enter URL
@@ -84,6 +87,15 @@
Decrease Page Zoom
+
+ Enter text to search
+
+
+ Next search result
+
+
+ Previous search result
+
Build
diff --git a/SafeExamBrowser.I18n/Data/fr.xml b/SafeExamBrowser.I18n/Data/fr.xml
index a630e7cd..f0d73ffa 100644
--- a/SafeExamBrowser.I18n/Data/fr.xml
+++ b/SafeExamBrowser.I18n/Data/fr.xml
@@ -34,7 +34,7 @@
Application du navigateur
- Console de développement
+ Sites web ouverts
Chargement…
@@ -69,6 +69,9 @@
Menu
+
+ Fermer
+
Entrer l'URL
@@ -84,6 +87,15 @@
Diminuer zoom
+
+ Saisir du texte pour rechercher
+
+
+ Résultat de recherche prochain
+
+
+ Résultat de recherche précédent
+
Build
diff --git a/SafeExamBrowser.I18n/Data/it.xml b/SafeExamBrowser.I18n/Data/it.xml
index c916323b..20fc8a4e 100644
--- a/SafeExamBrowser.I18n/Data/it.xml
+++ b/SafeExamBrowser.I18n/Data/it.xml
@@ -34,7 +34,7 @@
Applicazione browser
- Console di sviluppo
+ Siti web aperti
Download in corso ...
@@ -69,6 +69,9 @@
Menu
+
+ Chiudere
+
Inserisci URL
@@ -84,6 +87,15 @@
Diminuire zoom
+
+ Immettere il testo da cercare
+
+
+ Risultato della ricerca successiva
+
+
+ Risultato della ricerca precedente
+
Build
diff --git a/SafeExamBrowser.I18n/Data/zh.xml b/SafeExamBrowser.I18n/Data/zh.xml
index 72cec036..f6f972ca 100644
--- a/SafeExamBrowser.I18n/Data/zh.xml
+++ b/SafeExamBrowser.I18n/Data/zh.xml
@@ -34,7 +34,7 @@
根据当前配置不允许打印。
- 浏览器应用程序
+ 开放网站
开发者控制台
@@ -66,6 +66,9 @@
菜单
+
+ 关闭
+
输入网址
@@ -81,6 +84,15 @@
减少页面缩放
+
+ 输入文本进行搜索
+
+
+ 下一个搜索结果
+
+
+ 前一个搜索结果
+
生成
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationButton.xaml.cs
index db252715..3ecd0db4 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationButton.xaml.cs
@@ -35,7 +35,9 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
Icon.Content = IconResourceLoader.Load(window?.Icon ?? application.Icon);
Text.Text = window?.Title ?? application.Name;
Button.Click += (o, args) => Clicked?.Invoke(this, EventArgs.Empty);
- Button.ToolTip = window?.Title ?? application.Tooltip;
+ var tooltip = window?.Title ?? application.Tooltip;
+ Button.ToolTip = tooltip;
+ System.Windows.Automation.AutomationProperties.SetName(Button, tooltip);
if (window != null)
{
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml
index d81f0bf8..9a9c49a9 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml
@@ -21,7 +21,7 @@
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml.cs
index 55f7992c..42eb024d 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml.cs
@@ -49,13 +49,39 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
audio.VolumeChanged += Audio_VolumeChanged;
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
- Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
+ var lastOpenedBySpacePress = false;
+ Button.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
+ Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
MuteButton.Click += MuteButton_Click;
MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml") };
NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Light_NoDevice.xaml") };
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
- Popup.Closed += (o, args) => Grid.Background = originalBrush;
+ Popup.Closed += (o, args) =>
+ {
+ Grid.Background = originalBrush;
+ lastOpenedBySpacePress = false;
+ };
Volume.ValueChanged += Volume_ValueChanged;
if (audio.HasOutputDevice)
@@ -114,6 +140,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
this.muted = muted;
Button.ToolTip = info;
+ System.Windows.Automation.AutomationProperties.SetName(Button, info);
Text.Text = info;
Volume.ValueChanged -= Volume_ValueChanged;
Volume.Value = Math.Round(volume * 100);
@@ -121,14 +148,18 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
if (muted)
{
+ var tooltip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip);
+ MuteButton.ToolTip = tooltip;
+ System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip);
ButtonIcon.Content = IconResourceLoader.Load(MutedIcon);
- MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip);
PopupIcon.Content = IconResourceLoader.Load(MutedIcon);
}
else
{
+ var tooltip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip);
+ MuteButton.ToolTip = tooltip;
+ System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip);
ButtonIcon.Content = LoadIcon(volume);
- MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip);
PopupIcon.Content = LoadIcon(volume);
}
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutButton.xaml.cs
index 44a6f756..5e5607f8 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutButton.xaml.cs
@@ -43,6 +43,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
CultureCodeTextBlock.Text = layout.CultureCode;
CultureNameTextBlock.Text = layout.CultureName;
LayoutNameTextBlock.Text = layout.LayoutName;
+ System.Windows.Automation.AutomationProperties.SetName(Button, layout.CultureName);
}
}
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutControl.xaml.cs
index 24eaedf8..d9a5a85a 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutControl.xaml.cs
@@ -6,7 +6,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+using System;
using System.Threading.Tasks;
+using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Media;
using SafeExamBrowser.I18n.Contracts;
@@ -49,10 +51,36 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
LayoutsStackPanel.Children[0].Focus();
}));
};
- Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
+ var lastOpenedBySpacePress = false;
+ Button.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
+ Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
- Popup.Closed += (o, args) => Grid.Background = originalBrush;
+ Popup.Closed += (o, args) =>
+ {
+ Grid.Background = originalBrush;
+ lastOpenedBySpacePress = false;
+ };
}
private void Keyboard_LayoutChanged(IKeyboardLayout layout)
@@ -96,6 +124,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
Text.Text = layout.CultureName;
Button.ToolTip = tooltip;
+ AutomationProperties.SetName(Button, tooltip);
}
private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkButton.xaml.cs
index 8e940f07..ac1dc27a 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkButton.xaml.cs
@@ -34,5 +34,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
NetworkNameTextBlock.Text = network.Name;
SignalStrengthTextBlock.Text = $"{network.SignalStrength}%";
}
+
+ public void SetFocus()
+ {
+ Button.Focus();
+ }
}
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkControl.xaml.cs
index 4a5beafd..0cb17a58 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkControl.xaml.cs
@@ -45,10 +45,50 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
adapter.Changed += () => Dispatcher.InvokeAsync(Update);
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
- Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
- Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
- Popup.Closed += (o, args) => Grid.Background = originalBrush;
+ var lastOpenedBySpacePress = false;
+ Button.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
+ Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
+ Popup.Opened += (o, args) =>
+ {
+ Grid.Background = Brushes.Gray;
+ Task.Delay(100).ContinueWith((task) => Dispatcher.Invoke(() =>
+ {
+ if (WirelessNetworksStackPanel.Children.Count > 0)
+ {
+ var btn = WirelessNetworksStackPanel.Children[0] as NetworkButton;
+ if (btn != null)
+ {
+ btn.SetFocus();
+ }
+ }
+ }));
+ };
+ Popup.Closed += (o, args) =>
+ {
+ Grid.Background = originalBrush;
+ lastOpenedBySpacePress = false;
+ };
WirelessIcon.Child = GetWirelessIcon(0);
Update();
@@ -121,7 +161,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
{
Button.ToolTip = text;
Text.Text = text;
- Button.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text);
+ Button.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text);
}
private UIElement GetWirelessIcon(int signalStrength)
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/PowerSupplyControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/PowerSupplyControl.xaml.cs
index 32dfdd95..79dca71f 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/PowerSupplyControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/PowerSupplyControl.xaml.cs
@@ -87,7 +87,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed;
Text.Text = tooltip;
Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
- this.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, tooltip);
+ this.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, tooltip);
}
private void RenderCharge(double charge, BatteryChargeStatus status)
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/RaiseHandControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/RaiseHandControl.xaml.cs
index 2f8d4aa0..5ed86791 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/RaiseHandControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/RaiseHandControl.xaml.cs
@@ -55,15 +55,41 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter
RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") };
Icon.Content = IconResourceLoader.Load(LoweredIcon);
- NotificationButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
+ var lastOpenedBySpacePress = false;
+ NotificationButton.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
+ NotificationButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
NotificationButton.PreviewMouseLeftButtonUp += NotificationButton_PreviewMouseLeftButtonUp;
NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp;
NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered);
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
- Popup.Closed += (o, args) => Grid.Background = originalBrush;
+ Popup.Closed += (o, args) =>
+ {
+ Grid.Background = originalBrush;
+ lastOpenedBySpacePress = false;
+ };
Text.Text = text.Get(TextKey.Notification_ProctoringHandLowered);
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationControl.xaml.cs
index eb3c1a31..33f5ec03 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationControl.xaml.cs
@@ -44,6 +44,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
Button.MouseEnter += (o, args) => WindowPopup.IsOpen = WindowStackPanel.Children.Count > 0;
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = WindowPopup.IsMouseOver || ActiveBar.IsMouseOver));
Button.ToolTip = application.Tooltip;
+ System.Windows.Automation.AutomationProperties.SetName(Button, application.Tooltip);
WindowPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(WindowPopup_PlacementCallback);
WindowPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = IsMouseOver));
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml
index 229251fc..601e5f1c 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml
@@ -22,7 +22,7 @@
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml.cs
index 541416ad..2eafc925 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml.cs
@@ -48,12 +48,34 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
audio.VolumeChanged += Audio_VolumeChanged;
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
- Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
+ var lastOpenedBySpacePress = false;
+ Button.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
+ Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
MuteButton.Click += MuteButton_Click;
MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml") };
NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_NoDevice.xaml") };
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
Volume.ValueChanged += Volume_ValueChanged;
Popup.Opened += (o, args) =>
@@ -67,6 +89,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{
Background = originalBrush;
Button.Background = originalBrush;
+ lastOpenedBySpacePress = false;
};
if (audio.HasOutputDevice)
@@ -132,19 +155,24 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
this.muted = muted;
Button.ToolTip = info;
+ System.Windows.Automation.AutomationProperties.SetName(Button, info);
Volume.ValueChanged -= Volume_ValueChanged;
Volume.Value = Math.Round(volume * 100);
Volume.ValueChanged += Volume_ValueChanged;
if (muted)
{
- MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip);
+ var tooltip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip);
+ MuteButton.ToolTip = tooltip;
+ System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip);
PopupIcon.Content = IconResourceLoader.Load(MutedIcon);
ButtonIcon.Content = IconResourceLoader.Load(MutedIcon);
}
else
{
- MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip);
+ var tooltip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip);
+ MuteButton.ToolTip = tooltip;
+ System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip);
PopupIcon.Content = LoadIcon(volume);
ButtonIcon.Content = LoadIcon(volume);
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/Clock.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/Clock.xaml
index 93517d0f..ea23411a 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/Clock.xaml
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/Clock.xaml
@@ -11,7 +11,7 @@
-
-
+
+
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutButton.xaml.cs
index ad74c2fa..ea993856 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutButton.xaml.cs
@@ -43,7 +43,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
CultureCodeTextBlock.Text = layout.CultureCode;
CultureNameTextBlock.Text = layout.CultureName;
LayoutNameTextBlock.Text = layout.LayoutName;
- System.Windows.Automation.AutomationProperties.SetHelpText(Button, layout.LayoutName);
+ System.Windows.Automation.AutomationProperties.SetName(Button, layout.CultureName);
}
}
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutControl.xaml.cs
index da280d12..3f4cf0dc 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutControl.xaml.cs
@@ -10,6 +10,7 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
@@ -53,9 +54,31 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
((LayoutsStackPanel.Children[0] as ContentControl).Content as UIElement).Focus();
})));
};
- Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
+ var lastOpenedBySpacePress = false;
+ Button.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
+ Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
Popup.Opened += (o, args) =>
{
@@ -67,6 +90,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{
Background = originalBrush;
Button.Background = originalBrush;
+ lastOpenedBySpacePress = false;
};
}
@@ -120,6 +144,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
LayoutCultureCode.Text = layout.CultureCode;
Button.ToolTip = tooltip;
+ AutomationProperties.SetName(Button, tooltip);
}
private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkButton.xaml.cs
index cc3ec142..bc1d7025 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkButton.xaml.cs
@@ -34,5 +34,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
NetworkNameTextBlock.Text = network.Name;
SignalStrengthTextBlock.Text = $"{network.SignalStrength}%";
}
+
+ public void SetFocus()
+ {
+ Button.Focus();
+ }
}
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkControl.xaml.cs
index 3832f57e..b9bf15d9 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkControl.xaml.cs
@@ -45,22 +45,56 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
var originalBrush = Button.Background;
adapter.Changed += () => Dispatcher.InvokeAsync(Update);
+ var lastOpenedBySpacePress = false;
+ Button.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
- Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
+ Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
WirelessIcon.Child = GetWirelessIcon(0);
Popup.Opened += (o, args) =>
{
Background = Brushes.LightGray;
Button.Background = Brushes.LightGray;
+ Task.Delay(100).ContinueWith((task) => Dispatcher.Invoke(() =>
+ {
+ if (WirelessNetworksStackPanel.Children.Count > 0)
+ {
+ var btn = WirelessNetworksStackPanel.Children[0] as NetworkButton;
+ if (btn != null)
+ {
+ btn.SetFocus();
+ }
+ }
+ }));
};
Popup.Closed += (o, args) =>
{
Background = originalBrush;
Button.Background = originalBrush;
+ lastOpenedBySpacePress = false;
};
Update();
@@ -87,8 +121,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
if (network.Status == ConnectionStatus.Connected)
{
WirelessIcon.Child = GetWirelessIcon(network.SignalStrength);
- Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name);
- Button.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, Button.ToolTip as string);
+ UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name));
}
WirelessNetworksStackPanel.Children.Add(button);
@@ -98,7 +131,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{
case ConnectionType.Wired:
Button.IsEnabled = false;
- Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWiredConnected);
+ UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected));
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
@@ -109,7 +142,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
break;
default:
Button.IsEnabled = false;
- Button.ToolTip = text.Get(TextKey.SystemControl_NetworkNotAvailable);
+ UpdateText(text.Get(TextKey.SystemControl_NetworkNotAvailable));
WiredIcon.Visibility = Visibility.Visible;
WirelessIcon.Visibility = Visibility.Collapsed;
break;
@@ -118,19 +151,20 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
switch (adapter.Status)
{
case ConnectionStatus.Connected:
+ UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected));
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green);
NetworkStatusIcon.Spin = false;
break;
case ConnectionStatus.Connecting:
- Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnecting);
+ UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnecting));
NetworkStatusIcon.Rotation = 0;
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray);
NetworkStatusIcon.Spin = true;
NetworkStatusIcon.SpinDuration = 2;
break;
default:
- Button.ToolTip = text.Get(TextKey.SystemControl_NetworkDisconnected);
+ UpdateText(text.Get(TextKey.SystemControl_NetworkDisconnected));
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange);
NetworkStatusIcon.Spin = false;
WirelessIcon.Child = GetWirelessIcon(0);
@@ -138,6 +172,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
}
}
+ private void UpdateText(string text)
+ {
+ Button.ToolTip = text;
+ Button.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text);
+ }
+
private UIElement GetWirelessIcon(int signalStrength)
{
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NotificationButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NotificationButton.xaml.cs
index 6c1a7f3f..b415cbf0 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NotificationButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NotificationButton.xaml.cs
@@ -41,6 +41,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{
IconButton.ToolTip = notification.Tooltip;
IconButton.Content = IconResourceLoader.Load(notification.IconResource);
+ System.Windows.Automation.AutomationProperties.SetName(this, notification.Tooltip);
}
}
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/PowerSupplyControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/PowerSupplyControl.xaml.cs
index 7c80bb12..d6059666 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/PowerSupplyControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/PowerSupplyControl.xaml.cs
@@ -101,7 +101,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
Button.ToolTip = tooltip;
PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed;
Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
- this.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, tooltip);
+ this.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, tooltip);
}
private void RenderCharge(double charge, BatteryChargeStatus status)
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/RaiseHandControl.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/RaiseHandControl.xaml.cs
index 774cca6e..01aeb2ac 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/RaiseHandControl.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/RaiseHandControl.xaml.cs
@@ -55,13 +55,35 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") };
Icon.Content = IconResourceLoader.Load(LoweredIcon);
- NotificationButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
+ var lastOpenedBySpacePress = false;
+ NotificationButton.PreviewKeyDown += (o, args) =>
+ {
+ if (args.Key == System.Windows.Input.Key.Space) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
+ {
+ lastOpenedBySpacePress = true;
+ }
+ };
+ NotificationButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = Popup.IsMouseOver;
+ }));
NotificationButton.PreviewMouseLeftButtonUp += NotificationButton_PreviewMouseLeftButtonUp;
NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp;
NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered);
Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback);
- Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
+ Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() =>
+ {
+ if (Popup.IsOpen && lastOpenedBySpacePress)
+ {
+ return;
+ }
+ Popup.IsOpen = IsMouseOver;
+ }));
Popup.Opened += (o, args) =>
{
Background = Brushes.LightGray;
@@ -71,6 +93,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{
Background = originalBrush;
NotificationButton.Background = originalBrush;
+ lastOpenedBySpacePress = false;
};
}
diff --git a/SafeExamBrowser.UserInterface.Desktop/Windows/BrowserWindow.xaml b/SafeExamBrowser.UserInterface.Desktop/Windows/BrowserWindow.xaml
index cd4b266d..a7a7753b 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Windows/BrowserWindow.xaml
+++ b/SafeExamBrowser.UserInterface.Desktop/Windows/BrowserWindow.xaml
@@ -80,7 +80,7 @@
-