Merge branch 'master' of https://github.com/SafeExamBrowser/seb-win-refactoring
This commit is contained in:
		
						commit
						66bd6a2d90
					
				
					 48 changed files with 683 additions and 103 deletions
				
			
		|  | @ -26,6 +26,7 @@ namespace SafeExamBrowser.I18n.Contracts | ||||||
| 		Browser_PrintNotAllowed, | 		Browser_PrintNotAllowed, | ||||||
| 		Browser_Tooltip, | 		Browser_Tooltip, | ||||||
| 		BrowserWindow_BackwardButton, | 		BrowserWindow_BackwardButton, | ||||||
|  | 		BrowserWindow_CloseButton, | ||||||
| 		BrowserWindow_DeveloperConsoleMenuItem, | 		BrowserWindow_DeveloperConsoleMenuItem, | ||||||
| 		BrowserWindow_Downloading, | 		BrowserWindow_Downloading, | ||||||
| 		BrowserWindow_DownloadCancelled, | 		BrowserWindow_DownloadCancelled, | ||||||
|  | @ -37,6 +38,9 @@ namespace SafeExamBrowser.I18n.Contracts | ||||||
| 		BrowserWindow_HomeButton, | 		BrowserWindow_HomeButton, | ||||||
| 		BrowserWindow_MenuButton, | 		BrowserWindow_MenuButton, | ||||||
| 		BrowserWindow_ReloadButton, | 		BrowserWindow_ReloadButton, | ||||||
|  | 		BrowserWindow_SearchNext, | ||||||
|  | 		BrowserWindow_SearchPrevious, | ||||||
|  | 		BrowserWindow_SearchTextBox, | ||||||
| 		BrowserWindow_UrlTextBox, | 		BrowserWindow_UrlTextBox, | ||||||
| 		BrowserWindow_ZoomLevelReset, | 		BrowserWindow_ZoomLevelReset, | ||||||
| 		BrowserWindow_ZoomMenuItem, | 		BrowserWindow_ZoomMenuItem, | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ | ||||||
|         Drucken ist nicht erlaubt gemäss der aktiven Konfiguration. |         Drucken ist nicht erlaubt gemäss der aktiven Konfiguration. | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="Browser_Tooltip"> |     <Entry key="Browser_Tooltip"> | ||||||
|         Browser Applikation |         Geöffnete Websites | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> |     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> | ||||||
|         Entwickler-Konsole |         Entwickler-Konsole | ||||||
|  | @ -69,6 +69,9 @@ | ||||||
|     <Entry key="BrowserWindow_MenuButton"> |     <Entry key="BrowserWindow_MenuButton"> | ||||||
|         Menü |         Menü | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_CloseButton"> | ||||||
|  |         Schliessen | ||||||
|  |     </Entry> | ||||||
|     <Entry key="BrowserWindow_UrlTextBox"> |     <Entry key="BrowserWindow_UrlTextBox"> | ||||||
|         URL eingeben |         URL eingeben | ||||||
|     </Entry> |     </Entry> | ||||||
|  | @ -84,6 +87,15 @@ | ||||||
|     <Entry key="BrowserWindow_ZoomMenuMinus"> |     <Entry key="BrowserWindow_ZoomMenuMinus"> | ||||||
|         Zoom verkleinern |         Zoom verkleinern | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchTextBox"> | ||||||
|  |         Text eingeben zum Suchen | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchNext"> | ||||||
|  |         Nächstes Suchresultat | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchPrevious"> | ||||||
|  |         Vorheriges Suchresultat | ||||||
|  |     </Entry> | ||||||
|     <Entry key="Build"> |     <Entry key="Build"> | ||||||
|         Build |         Build | ||||||
|     </Entry> |     </Entry> | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ | ||||||
|         Printing is not allowed according to the current configuration. |         Printing is not allowed according to the current configuration. | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="Browser_Tooltip"> |     <Entry key="Browser_Tooltip"> | ||||||
|         Browser Application |         Open Webpages | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> |     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> | ||||||
|         Developer Console |         Developer Console | ||||||
|  | @ -69,6 +69,9 @@ | ||||||
|     <Entry key="BrowserWindow_MenuButton"> |     <Entry key="BrowserWindow_MenuButton"> | ||||||
|         Menu |         Menu | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_CloseButton"> | ||||||
|  |         Close | ||||||
|  |     </Entry> | ||||||
|     <Entry key="BrowserWindow_UrlTextBox"> |     <Entry key="BrowserWindow_UrlTextBox"> | ||||||
|         Enter URL |         Enter URL | ||||||
|     </Entry> |     </Entry> | ||||||
|  | @ -84,6 +87,15 @@ | ||||||
|     <Entry key="BrowserWindow_ZoomMenuMinus"> |     <Entry key="BrowserWindow_ZoomMenuMinus"> | ||||||
|         Decrease Page Zoom |         Decrease Page Zoom | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchTextBox"> | ||||||
|  |         Enter text to search | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchNext"> | ||||||
|  |         Next search result | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchPrevious"> | ||||||
|  |         Previous search result | ||||||
|  |     </Entry> | ||||||
|     <Entry key="Build"> |     <Entry key="Build"> | ||||||
|         Build |         Build | ||||||
|     </Entry> |     </Entry> | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ | ||||||
|         Application du navigateur |         Application du navigateur | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> |     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> | ||||||
|         Console de développement |         Sites web ouverts | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="BrowserWindow_Downloading"> |     <Entry key="BrowserWindow_Downloading"> | ||||||
|         Chargement… |         Chargement… | ||||||
|  | @ -69,6 +69,9 @@ | ||||||
|     <Entry key="BrowserWindow_MenuButton"> |     <Entry key="BrowserWindow_MenuButton"> | ||||||
|         Menu |         Menu | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_CloseButton"> | ||||||
|  |         Fermer | ||||||
|  |     </Entry> | ||||||
|     <Entry key="BrowserWindow_UrlTextBox"> |     <Entry key="BrowserWindow_UrlTextBox"> | ||||||
|         Entrer l'URL |         Entrer l'URL | ||||||
|     </Entry> |     </Entry> | ||||||
|  | @ -84,6 +87,15 @@ | ||||||
|     <Entry key="BrowserWindow_ZoomMenuMinus"> |     <Entry key="BrowserWindow_ZoomMenuMinus"> | ||||||
|         Diminuer zoom |         Diminuer zoom | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchTextBox"> | ||||||
|  |         Saisir du texte pour rechercher | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchNext"> | ||||||
|  |         Résultat de recherche prochain | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchPrevious"> | ||||||
|  |         Résultat de recherche précédent | ||||||
|  |     </Entry> | ||||||
|     <Entry key="Build"> |     <Entry key="Build"> | ||||||
|         Build |         Build | ||||||
|     </Entry> |     </Entry> | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ | ||||||
|         Applicazione browser |         Applicazione browser | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> |     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> | ||||||
|         Console di sviluppo |         Siti web aperti | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="BrowserWindow_Downloading"> |     <Entry key="BrowserWindow_Downloading"> | ||||||
|         Download in corso ... |         Download in corso ... | ||||||
|  | @ -69,6 +69,9 @@ | ||||||
|     <Entry key="BrowserWindow_MenuButton"> |     <Entry key="BrowserWindow_MenuButton"> | ||||||
|         Menu |         Menu | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_CloseButton"> | ||||||
|  |         Chiudere | ||||||
|  |     </Entry> | ||||||
|     <Entry key="BrowserWindow_UrlTextBox"> |     <Entry key="BrowserWindow_UrlTextBox"> | ||||||
|         Inserisci URL |         Inserisci URL | ||||||
|     </Entry> |     </Entry> | ||||||
|  | @ -84,6 +87,15 @@ | ||||||
|     <Entry key="BrowserWindow_ZoomMenuMinus"> |     <Entry key="BrowserWindow_ZoomMenuMinus"> | ||||||
|         Diminuire zoom |         Diminuire zoom | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchTextBox"> | ||||||
|  |         Immettere il testo da cercare | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchNext"> | ||||||
|  |         Risultato della ricerca successiva | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchPrevious"> | ||||||
|  |         Risultato della ricerca precedente | ||||||
|  |     </Entry> | ||||||
|     <Entry key="Build"> |     <Entry key="Build"> | ||||||
|         Build |         Build | ||||||
|     </Entry> |     </Entry> | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ | ||||||
|         根据当前配置不允许打印。 |         根据当前配置不允许打印。 | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="Browser_Tooltip"> |     <Entry key="Browser_Tooltip"> | ||||||
|         浏览器应用程序 |         开放网站 | ||||||
|     </Entry> |     </Entry> | ||||||
|     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> |     <Entry key="BrowserWindow_DeveloperConsoleMenuItem"> | ||||||
|         开发者控制台 |         开发者控制台 | ||||||
|  | @ -66,6 +66,9 @@ | ||||||
|     <Entry key="BrowserWindow_MenuButton"> |     <Entry key="BrowserWindow_MenuButton"> | ||||||
|         菜单 |         菜单 | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_CloseButton"> | ||||||
|  |         关闭 | ||||||
|  |     </Entry> | ||||||
|     <Entry key="BrowserWindow_UrlTextBox"> |     <Entry key="BrowserWindow_UrlTextBox"> | ||||||
|         输入网址 |         输入网址 | ||||||
|     </Entry> |     </Entry> | ||||||
|  | @ -81,6 +84,15 @@ | ||||||
|     <Entry key="BrowserWindow_ZoomMenuMinus"> |     <Entry key="BrowserWindow_ZoomMenuMinus"> | ||||||
|         减少页面缩放 |         减少页面缩放 | ||||||
|     </Entry> |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchTextBox"> | ||||||
|  |         输入文本进行搜索 | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchNext"> | ||||||
|  |         下一个搜索结果 | ||||||
|  |     </Entry> | ||||||
|  |     <Entry key="BrowserWindow_SearchPrevious"> | ||||||
|  |         前一个搜索结果 | ||||||
|  |     </Entry> | ||||||
|     <Entry key="Build"> |     <Entry key="Build"> | ||||||
|         生成 |         生成 | ||||||
|     </Entry> |     </Entry> | ||||||
|  |  | ||||||
|  | @ -35,7 +35,9 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 			Icon.Content = IconResourceLoader.Load(window?.Icon ?? application.Icon); | 			Icon.Content = IconResourceLoader.Load(window?.Icon ?? application.Icon); | ||||||
| 			Text.Text = window?.Title ?? application.Name; | 			Text.Text = window?.Title ?? application.Name; | ||||||
| 			Button.Click += (o, args) => Clicked?.Invoke(this, EventArgs.Empty); | 			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) | 			if (window != null) | ||||||
| 			{ | 			{ | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ | ||||||
|                     <TextBlock x:Name="AudioDeviceName" Foreground="White" Margin="5" TextAlignment="Center" /> |                     <TextBlock x:Name="AudioDeviceName" Foreground="White" Margin="5" TextAlignment="Center" /> | ||||||
|                     <StackPanel Orientation="Horizontal" Height="40"> |                     <StackPanel Orientation="Horizontal" Height="40"> | ||||||
|                         <Button x:Name="MuteButton" Background="Transparent" Foreground="White" Padding="5" Template="{StaticResource ActionCenterButton}" Width="40"> |                         <Button x:Name="MuteButton" Background="Transparent" Foreground="White" Padding="5" Template="{StaticResource ActionCenterButton}" Width="40"> | ||||||
|                             <ContentControl x:Name="PopupIcon" /> |                             <ContentControl x:Name="PopupIcon" Focusable="False" /> | ||||||
|                         </Button> |                         </Button> | ||||||
|                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" |                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" | ||||||
|                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="250" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted" /> |                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="250" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted" /> | ||||||
|  |  | ||||||
|  | @ -49,13 +49,39 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			audio.VolumeChanged += Audio_VolumeChanged; | 			audio.VolumeChanged += Audio_VolumeChanged; | ||||||
| 			Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; | 			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; | 			MuteButton.Click += MuteButton_Click; | ||||||
| 			MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml") }; | 			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") }; | 			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.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; | 			Volume.ValueChanged += Volume_ValueChanged; | ||||||
| 
 | 
 | ||||||
| 			if (audio.HasOutputDevice) | 			if (audio.HasOutputDevice) | ||||||
|  | @ -114,6 +140,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 			this.muted = muted; | 			this.muted = muted; | ||||||
| 
 | 
 | ||||||
| 			Button.ToolTip = info; | 			Button.ToolTip = info; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, info); | ||||||
| 			Text.Text = info; | 			Text.Text = info; | ||||||
| 			Volume.ValueChanged -= Volume_ValueChanged; | 			Volume.ValueChanged -= Volume_ValueChanged; | ||||||
| 			Volume.Value = Math.Round(volume * 100); | 			Volume.Value = Math.Round(volume * 100); | ||||||
|  | @ -121,14 +148,18 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			if (muted) | 			if (muted) | ||||||
| 			{ | 			{ | ||||||
|  | 				var tooltip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip); | ||||||
|  | 				MuteButton.ToolTip = tooltip; | ||||||
|  | 				System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip); | ||||||
| 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 				MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip); |  | ||||||
| 				PopupIcon.Content = IconResourceLoader.Load(MutedIcon); | 				PopupIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
|  | 				var tooltip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip); | ||||||
|  | 				MuteButton.ToolTip = tooltip; | ||||||
|  | 				System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip); | ||||||
| 				ButtonIcon.Content = LoadIcon(volume); | 				ButtonIcon.Content = LoadIcon(volume); | ||||||
| 				MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip); |  | ||||||
| 				PopupIcon.Content = LoadIcon(volume); | 				PopupIcon.Content = LoadIcon(volume); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -43,6 +43,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 			CultureCodeTextBlock.Text = layout.CultureCode; | 			CultureCodeTextBlock.Text = layout.CultureCode; | ||||||
| 			CultureNameTextBlock.Text = layout.CultureName; | 			CultureNameTextBlock.Text = layout.CultureName; | ||||||
| 			LayoutNameTextBlock.Text = layout.LayoutName; | 			LayoutNameTextBlock.Text = layout.LayoutName; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, layout.CultureName); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,7 +6,9 @@ | ||||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | using System; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  | using System.Windows.Automation; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
| using System.Windows.Media; | using System.Windows.Media; | ||||||
| using SafeExamBrowser.I18n.Contracts; | using SafeExamBrowser.I18n.Contracts; | ||||||
|  | @ -49,10 +51,36 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 					LayoutsStackPanel.Children[0].Focus(); | 					LayoutsStackPanel.Children[0].Focus(); | ||||||
| 				})); | 				})); | ||||||
| 			}; | 			}; | ||||||
| 			Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver)); | 			var lastOpenedBySpacePress = false; | ||||||
| 			Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver)); | 			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.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) | 		private void Keyboard_LayoutChanged(IKeyboardLayout layout) | ||||||
|  | @ -96,6 +124,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			Text.Text = layout.CultureName; | 			Text.Text = layout.CultureName; | ||||||
| 			Button.ToolTip = tooltip; | 			Button.ToolTip = tooltip; | ||||||
|  | 			AutomationProperties.SetName(Button, tooltip); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | ||||||
|  |  | ||||||
|  | @ -34,5 +34,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 			NetworkNameTextBlock.Text = network.Name; | 			NetworkNameTextBlock.Text = network.Name; | ||||||
| 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		public void SetFocus() | ||||||
|  | 		{ | ||||||
|  | 			Button.Focus(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -45,10 +45,50 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			adapter.Changed += () => Dispatcher.InvokeAsync(Update); | 			adapter.Changed += () => Dispatcher.InvokeAsync(Update); | ||||||
| 			Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; | 			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; | ||||||
| 			Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver)); | 			Button.PreviewKeyDown += (o, args) => | ||||||
| 			Popup.Opened += (o, args) => Grid.Background = Brushes.Gray; | 			{ | ||||||
| 			Popup.Closed += (o, args) => Grid.Background = originalBrush; | 				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); | 			WirelessIcon.Child = GetWirelessIcon(0); | ||||||
| 
 | 
 | ||||||
| 			Update(); | 			Update(); | ||||||
|  | @ -121,7 +161,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 		{ | 		{ | ||||||
| 			Button.ToolTip = text; | 			Button.ToolTip = text; | ||||||
| 			Text.Text = 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) | 		private UIElement GetWirelessIcon(int signalStrength) | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenter | ||||||
| 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | ||||||
| 			Text.Text = tooltip; | 			Text.Text = tooltip; | ||||||
| 			Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? 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) | 		private void RenderCharge(double charge, BatteryChargeStatus status) | ||||||
|  |  | ||||||
|  | @ -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") }; | 			RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") }; | ||||||
| 			Icon.Content = IconResourceLoader.Load(LoweredIcon); | 			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.PreviewMouseLeftButtonUp += NotificationButton_PreviewMouseLeftButtonUp; | ||||||
| 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | ||||||
| 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | ||||||
| 
 | 
 | ||||||
| 			Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			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.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); | 			Text.Text = text.Get(TextKey.Notification_ProctoringHandLowered); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			Button.MouseEnter += (o, args) => WindowPopup.IsOpen = WindowStackPanel.Children.Count > 0; | 			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.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = WindowPopup.IsMouseOver || ActiveBar.IsMouseOver)); | ||||||
| 			Button.ToolTip = application.Tooltip; | 			Button.ToolTip = application.Tooltip; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, application.Tooltip); | ||||||
| 			WindowPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(WindowPopup_PlacementCallback); | 			WindowPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(WindowPopup_PlacementCallback); | ||||||
| 			WindowPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = IsMouseOver)); | 			WindowPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = IsMouseOver)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ | ||||||
|                     <TextBlock x:Name="AudioDeviceName" Margin="5" TextAlignment="Center" /> |                     <TextBlock x:Name="AudioDeviceName" Margin="5" TextAlignment="Center" /> | ||||||
|                     <StackPanel Orientation="Horizontal" Height="40"> |                     <StackPanel Orientation="Horizontal" Height="40"> | ||||||
|                         <Button x:Name="MuteButton" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" Width="40"> |                         <Button x:Name="MuteButton" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" Width="40"> | ||||||
|                             <ContentControl x:Name="PopupIcon" /> |                             <ContentControl x:Name="PopupIcon" Focusable="False" /> | ||||||
|                         </Button> |                         </Button> | ||||||
|                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" KeyDown="Volume_KeyDown" |                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" KeyDown="Volume_KeyDown" | ||||||
|                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="250" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted" /> |                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="250" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted" /> | ||||||
|  |  | ||||||
|  | @ -48,12 +48,34 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 
 | 
 | ||||||
| 			audio.VolumeChanged += Audio_VolumeChanged; | 			audio.VolumeChanged += Audio_VolumeChanged; | ||||||
| 			Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; | 			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; | 			MuteButton.Click += MuteButton_Click; | ||||||
| 			MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml") }; | 			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") }; | 			NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_NoDevice.xaml") }; | ||||||
| 			Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			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; | 			Volume.ValueChanged += Volume_ValueChanged; | ||||||
| 
 | 
 | ||||||
| 			Popup.Opened += (o, args) => | 			Popup.Opened += (o, args) => | ||||||
|  | @ -67,6 +89,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				Button.Background = originalBrush; | 				Button.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			if (audio.HasOutputDevice) | 			if (audio.HasOutputDevice) | ||||||
|  | @ -132,19 +155,24 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			this.muted = muted; | 			this.muted = muted; | ||||||
| 
 | 
 | ||||||
| 			Button.ToolTip = info; | 			Button.ToolTip = info; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, info); | ||||||
| 			Volume.ValueChanged -= Volume_ValueChanged; | 			Volume.ValueChanged -= Volume_ValueChanged; | ||||||
| 			Volume.Value = Math.Round(volume * 100); | 			Volume.Value = Math.Round(volume * 100); | ||||||
| 			Volume.ValueChanged += Volume_ValueChanged; | 			Volume.ValueChanged += Volume_ValueChanged; | ||||||
| 
 | 
 | ||||||
| 			if (muted) | 			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); | 				PopupIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 			} | 			} | ||||||
| 			else | 			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); | 				PopupIcon.Content = LoadIcon(volume); | ||||||
| 				ButtonIcon.Content = LoadIcon(volume); | 				ButtonIcon.Content = LoadIcon(volume); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ | ||||||
|             <RowDefinition Height="1*" /> |             <RowDefinition Height="1*" /> | ||||||
|             <RowDefinition Height="1*" /> |             <RowDefinition Height="1*" /> | ||||||
|         </Grid.RowDefinitions> |         </Grid.RowDefinitions> | ||||||
|         <TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" Focusable="True" AutomationProperties.HelpText="{Binding Path=Time}" /> |         <TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" Focusable="True" AutomationProperties.Name="{Binding Path=Time}" /> | ||||||
|         <TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" HorizontalAlignment="Center" VerticalAlignment="Top" Focusable="True" AutomationProperties.HelpText="{Binding Path=Date}" /> |         <TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" HorizontalAlignment="Center" VerticalAlignment="Top" Focusable="True" AutomationProperties.Name="{Binding Path=Date}" /> | ||||||
|     </Grid> |     </Grid> | ||||||
| </UserControl> | </UserControl> | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			CultureCodeTextBlock.Text = layout.CultureCode; | 			CultureCodeTextBlock.Text = layout.CultureCode; | ||||||
| 			CultureNameTextBlock.Text = layout.CultureName; | 			CultureNameTextBlock.Text = layout.CultureName; | ||||||
| 			LayoutNameTextBlock.Text = layout.LayoutName; | 			LayoutNameTextBlock.Text = layout.LayoutName; | ||||||
| 			System.Windows.Automation.AutomationProperties.SetHelpText(Button, layout.LayoutName); | 			System.Windows.Automation.AutomationProperties.SetName(Button, layout.CultureName); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ using System; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.Windows; | using System.Windows; | ||||||
|  | using System.Windows.Automation; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
| using System.Windows.Controls.Primitives; | using System.Windows.Controls.Primitives; | ||||||
| using System.Windows.Media; | using System.Windows.Media; | ||||||
|  | @ -53,9 +54,31 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 					((LayoutsStackPanel.Children[0] as ContentControl).Content as UIElement).Focus(); | 					((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.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) => | 			Popup.Opened += (o, args) => | ||||||
| 			{ | 			{ | ||||||
|  | @ -67,6 +90,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				Button.Background = originalBrush; | 				Button.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -120,6 +144,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 
 | 
 | ||||||
| 			LayoutCultureCode.Text = layout.CultureCode; | 			LayoutCultureCode.Text = layout.CultureCode; | ||||||
| 			Button.ToolTip = tooltip; | 			Button.ToolTip = tooltip; | ||||||
|  | 			AutomationProperties.SetName(Button, tooltip); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | ||||||
|  |  | ||||||
|  | @ -34,5 +34,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			NetworkNameTextBlock.Text = network.Name; | 			NetworkNameTextBlock.Text = network.Name; | ||||||
| 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		public void SetFocus() | ||||||
|  | 		{ | ||||||
|  | 			Button.Focus(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -45,22 +45,56 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			var originalBrush = Button.Background; | 			var originalBrush = Button.Background; | ||||||
| 
 | 
 | ||||||
| 			adapter.Changed += () => Dispatcher.InvokeAsync(Update); | 			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.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.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); | 			WirelessIcon.Child = GetWirelessIcon(0); | ||||||
| 
 | 
 | ||||||
| 			Popup.Opened += (o, args) => | 			Popup.Opened += (o, args) => | ||||||
| 			{ | 			{ | ||||||
| 				Background = Brushes.LightGray; | 				Background = Brushes.LightGray; | ||||||
| 				Button.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) => | 			Popup.Closed += (o, args) => | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				Button.Background = originalBrush; | 				Button.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			Update(); | 			Update(); | ||||||
|  | @ -87,8 +121,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 				if (network.Status == ConnectionStatus.Connected) | 				if (network.Status == ConnectionStatus.Connected) | ||||||
| 				{ | 				{ | ||||||
| 					WirelessIcon.Child = GetWirelessIcon(network.SignalStrength); | 					WirelessIcon.Child = GetWirelessIcon(network.SignalStrength); | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name)); | ||||||
| 					Button.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, Button.ToolTip as string); |  | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				WirelessNetworksStackPanel.Children.Add(button); | 				WirelessNetworksStackPanel.Children.Add(button); | ||||||
|  | @ -98,7 +131,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				case ConnectionType.Wired: | 				case ConnectionType.Wired: | ||||||
| 					Button.IsEnabled = false; | 					Button.IsEnabled = false; | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWiredConnected); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected)); | ||||||
| 					WiredIcon.Visibility = Visibility.Visible; | 					WiredIcon.Visibility = Visibility.Visible; | ||||||
| 					WirelessIcon.Visibility = Visibility.Collapsed; | 					WirelessIcon.Visibility = Visibility.Collapsed; | ||||||
| 					break; | 					break; | ||||||
|  | @ -109,7 +142,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 					break; | 					break; | ||||||
| 				default: | 				default: | ||||||
| 					Button.IsEnabled = false; | 					Button.IsEnabled = false; | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkNotAvailable); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkNotAvailable)); | ||||||
| 					WiredIcon.Visibility = Visibility.Visible; | 					WiredIcon.Visibility = Visibility.Visible; | ||||||
| 					WirelessIcon.Visibility = Visibility.Collapsed; | 					WirelessIcon.Visibility = Visibility.Collapsed; | ||||||
| 					break; | 					break; | ||||||
|  | @ -118,19 +151,20 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			switch (adapter.Status) | 			switch (adapter.Status) | ||||||
| 			{ | 			{ | ||||||
| 				case ConnectionStatus.Connected: | 				case ConnectionStatus.Connected: | ||||||
|  | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected)); | ||||||
| 					NetworkStatusIcon.Rotation = 0; | 					NetworkStatusIcon.Rotation = 0; | ||||||
| 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green); | 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green); | ||||||
| 					NetworkStatusIcon.Spin = false; | 					NetworkStatusIcon.Spin = false; | ||||||
| 					break; | 					break; | ||||||
| 				case ConnectionStatus.Connecting: | 				case ConnectionStatus.Connecting: | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnecting); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnecting)); | ||||||
| 					NetworkStatusIcon.Rotation = 0; | 					NetworkStatusIcon.Rotation = 0; | ||||||
| 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray); | 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray); | ||||||
| 					NetworkStatusIcon.Spin = true; | 					NetworkStatusIcon.Spin = true; | ||||||
| 					NetworkStatusIcon.SpinDuration = 2; | 					NetworkStatusIcon.SpinDuration = 2; | ||||||
| 					break; | 					break; | ||||||
| 				default: | 				default: | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkDisconnected); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkDisconnected)); | ||||||
| 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange); | 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange); | ||||||
| 					NetworkStatusIcon.Spin = false; | 					NetworkStatusIcon.Spin = false; | ||||||
| 					WirelessIcon.Child = GetWirelessIcon(0); | 					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) | 		private UIElement GetWirelessIcon(int signalStrength) | ||||||
| 		{ | 		{ | ||||||
| 			var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0")); | 			var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0")); | ||||||
|  |  | ||||||
|  | @ -41,6 +41,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 		{ | 		{ | ||||||
| 			IconButton.ToolTip = notification.Tooltip; | 			IconButton.ToolTip = notification.Tooltip; | ||||||
| 			IconButton.Content = IconResourceLoader.Load(notification.IconResource); | 			IconButton.Content = IconResourceLoader.Load(notification.IconResource); | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(this, notification.Tooltip); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -101,7 +101,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			Button.ToolTip = tooltip; | 			Button.ToolTip = tooltip; | ||||||
| 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | ||||||
| 			Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? 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) | 		private void RenderCharge(double charge, BatteryChargeStatus status) | ||||||
|  |  | ||||||
|  | @ -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") }; | 			RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") }; | ||||||
| 			Icon.Content = IconResourceLoader.Load(LoweredIcon); | 			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.PreviewMouseLeftButtonUp += NotificationButton_PreviewMouseLeftButtonUp; | ||||||
| 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | ||||||
| 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | ||||||
| 
 | 
 | ||||||
| 			Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			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) => | 			Popup.Opened += (o, args) => | ||||||
| 			{ | 			{ | ||||||
| 				Background = Brushes.LightGray; | 				Background = Brushes.LightGray; | ||||||
|  | @ -71,6 +93,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				NotificationButton.Background = originalBrush; | 				NotificationButton.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ | ||||||
|                                         <ColumnDefinition Width="Auto" /> |                                         <ColumnDefinition Width="Auto" /> | ||||||
|                                     </Grid.ColumnDefinitions> |                                     </Grid.ColumnDefinitions> | ||||||
|                                     <TextBlock Grid.Column="0" x:Name="FindMenuText" HorizontalAlignment="Left" Margin="10,0" VerticalAlignment="Center" /> |                                     <TextBlock Grid.Column="0" x:Name="FindMenuText" HorizontalAlignment="Left" Margin="10,0" VerticalAlignment="Center" /> | ||||||
|                                     <Button Grid.Column="1" x:Name="FindMenuButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}" TabIndex="33"> |                                     <Button Grid.Column="1" x:Name="FindMenuButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}" TabIndex="33" AutomationProperties.LabeledBy="{Binding ElementName=FindMenuText}"> | ||||||
|                                         <fa:ImageAwesome Icon="Search" /> |                                         <fa:ImageAwesome Icon="Search" /> | ||||||
|                                     </Button> |                                     </Button> | ||||||
|                                 </Grid> |                                 </Grid> | ||||||
|  |  | ||||||
|  | @ -244,8 +244,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows | ||||||
| 			Dispatcher.Invoke(() => | 			Dispatcher.Invoke(() => | ||||||
| 			{ | 			{ | ||||||
| 				ZoomLevel.Text = $"{value}%"; | 				ZoomLevel.Text = $"{value}%"; | ||||||
| 				var zoomButtonHelpText = text.Get(TextKey.BrowserWindow_ZoomLevelReset).Replace("%%ZOOM%%", value.ToString("0")); | 				var zoomButtonName = text.Get(TextKey.BrowserWindow_ZoomLevelReset).Replace("%%ZOOM%%", value.ToString("0")); | ||||||
| 				ZoomResetButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, zoomButtonHelpText); | 				ZoomResetButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, zoomButtonName); | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -477,9 +477,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows | ||||||
| 			HomeButton.Click += (o, args) => HomeNavigationRequested?.Invoke(); | 			HomeButton.Click += (o, args) => HomeNavigationRequested?.Invoke(); | ||||||
| 			Loaded += BrowserWindow_Loaded; | 			Loaded += BrowserWindow_Loaded; | ||||||
| 			MenuButton.Click += MenuButton_Click; | 			MenuButton.Click += MenuButton_Click; | ||||||
| 			MenuButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver)); |  | ||||||
| 			MenuPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			MenuPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | ||||||
| 			MenuPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver)); | 			MenuPopup.LostFocus += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsKeyboardFocusWithin)); | ||||||
| 			KeyDown += BrowserWindow_KeyDown; | 			KeyDown += BrowserWindow_KeyDown; | ||||||
| 			KeyUp += BrowserWindow_KeyUp; | 			KeyUp += BrowserWindow_KeyUp; | ||||||
| 			LocationChanged += (o, args) => { DownloadsPopup.IsOpen = false; MenuPopup.IsOpen = false; }; | 			LocationChanged += (o, args) => { DownloadsPopup.IsOpen = false; MenuPopup.IsOpen = false; }; | ||||||
|  | @ -512,7 +511,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows | ||||||
| 			var javascript = @"
 | 			var javascript = @"
 | ||||||
| if (typeof __SEB_focusElement === 'undefined') { | if (typeof __SEB_focusElement === 'undefined') { | ||||||
|   __SEB_focusElement = function (forward) { |   __SEB_focusElement = function (forward) { | ||||||
| 	if (!document.body) { return; } | 	if (!document.body) | ||||||
|  | 		return; | ||||||
| 	var items = [].map | 	var items = [].map | ||||||
| 	  .call(document.body.querySelectorAll(['input', 'select', 'a[href]', 'textarea', 'button', '[tabindex]']), function(el, i) { return { el, i } }) | 	  .call(document.body.querySelectorAll(['input', 'select', 'a[href]', 'textarea', 'button', '[tabindex]']), function(el, i) { return { el, i } }) | ||||||
| 	  .filter(function(e) { return e.el.tabIndex >= 0 && !e.el.disabled && e.el.offsetParent; }) | 	  .filter(function(e) { return e.el.tabIndex >= 0 && !e.el.disabled && e.el.offsetParent; }) | ||||||
|  | @ -640,13 +640,13 @@ if (typeof __SEB_focusElement === 'undefined') { | ||||||
| 		private void LoadText() | 		private void LoadText() | ||||||
| 		{ | 		{ | ||||||
| 			DeveloperConsoleText.Text = text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem); | 			DeveloperConsoleText.Text = text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem); | ||||||
| 			DeveloperConsoleButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem)); | 			DeveloperConsoleButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem)); | ||||||
| 			FindCaseSensitiveCheckBox.Content = text.Get(TextKey.BrowserWindow_FindCaseSensitive); | 			FindCaseSensitiveCheckBox.Content = text.Get(TextKey.BrowserWindow_FindCaseSensitive); | ||||||
| 			FindMenuText.Text = text.Get(TextKey.BrowserWindow_FindMenuItem); | 			FindMenuText.Text = text.Get(TextKey.BrowserWindow_FindMenuItem); | ||||||
| 			FindMenuButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_FindMenuItem)); | 			FindMenuButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_FindMenuItem)); | ||||||
| 			ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem); | 			ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem); | ||||||
| 			ZoomInButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_ZoomMenuPlus)); | 			ZoomInButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ZoomMenuPlus)); | ||||||
| 			ZoomOutButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_ZoomMenuMinus)); | 			ZoomOutButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ZoomMenuMinus)); | ||||||
| 			ReloadButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ReloadButton)); | 			ReloadButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ReloadButton)); | ||||||
| 			BackwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_BackwardButton)); | 			BackwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_BackwardButton)); | ||||||
| 			ForwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ForwardButton)); | 			ForwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ForwardButton)); | ||||||
|  | @ -654,6 +654,10 @@ if (typeof __SEB_focusElement === 'undefined') { | ||||||
| 			HomeButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_HomeButton)); | 			HomeButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_HomeButton)); | ||||||
| 			MenuButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_MenuButton)); | 			MenuButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_MenuButton)); | ||||||
| 			UrlTextBox.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_UrlTextBox)); | 			UrlTextBox.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_UrlTextBox)); | ||||||
|  | 			FindTextBox.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_SearchTextBox)); | ||||||
|  | 			FindPreviousButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_SearchPrevious)); | ||||||
|  | 			FindNextButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_SearchNext)); | ||||||
|  | 			FindbarCloseButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_CloseButton)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -35,7 +35,9 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 			Icon.Content = IconResourceLoader.Load(window?.Icon ?? application.Icon); | 			Icon.Content = IconResourceLoader.Load(window?.Icon ?? application.Icon); | ||||||
| 			Text.Text = window?.Title ?? application.Name; | 			Text.Text = window?.Title ?? application.Name; | ||||||
| 			Button.Click += (o, args) => Clicked?.Invoke(this, EventArgs.Empty); | 			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) | 			if (window != null) | ||||||
| 			{ | 			{ | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ | ||||||
|                     <TextBlock x:Name="AudioDeviceName" Foreground="White" Margin="5" TextAlignment="Center" /> |                     <TextBlock x:Name="AudioDeviceName" Foreground="White" Margin="5" TextAlignment="Center" /> | ||||||
|                     <StackPanel Orientation="Horizontal" Height="60" Margin="5,0"> |                     <StackPanel Orientation="Horizontal" Height="60" Margin="5,0"> | ||||||
|                         <Button x:Name="MuteButton" Background="Transparent" Foreground="White" Padding="5" Template="{StaticResource ActionCenterButton}" Width="60"> |                         <Button x:Name="MuteButton" Background="Transparent" Foreground="White" Padding="5" Template="{StaticResource ActionCenterButton}" Width="60"> | ||||||
|                             <ContentControl x:Name="PopupIcon" /> |                             <ContentControl x:Name="PopupIcon" Focusable="False" /> | ||||||
|                         </Button> |                         </Button> | ||||||
|                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" |                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" | ||||||
|                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="125" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted"> |                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="125" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted"> | ||||||
|  |  | ||||||
|  | @ -49,13 +49,39 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			audio.VolumeChanged += Audio_VolumeChanged; | 			audio.VolumeChanged += Audio_VolumeChanged; | ||||||
| 			Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; | 			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; | 			MuteButton.Click += MuteButton_Click; | ||||||
| 			MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml") }; | 			MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml") }; | ||||||
| 			NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Light_NoDevice.xaml") }; | 			NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;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.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; | 			Volume.ValueChanged += Volume_ValueChanged; | ||||||
| 
 | 
 | ||||||
| 			if (audio.HasOutputDevice) | 			if (audio.HasOutputDevice) | ||||||
|  | @ -113,6 +139,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 			this.muted = muted; | 			this.muted = muted; | ||||||
| 
 | 
 | ||||||
| 			Button.ToolTip = info; | 			Button.ToolTip = info; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, info); | ||||||
| 			Text.Text = info; | 			Text.Text = info; | ||||||
| 			Volume.ValueChanged -= Volume_ValueChanged; | 			Volume.ValueChanged -= Volume_ValueChanged; | ||||||
| 			Volume.Value = Math.Round(volume * 100); | 			Volume.Value = Math.Round(volume * 100); | ||||||
|  | @ -120,14 +147,18 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			if (muted) | 			if (muted) | ||||||
| 			{ | 			{ | ||||||
|  | 				var tooltip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip); | ||||||
|  | 				MuteButton.ToolTip = tooltip; | ||||||
|  | 				System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip); | ||||||
| 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 				MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceUnmuteTooltip); |  | ||||||
| 				PopupIcon.Content = IconResourceLoader.Load(MutedIcon); | 				PopupIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
|  | 				var tooltip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip); | ||||||
|  | 				MuteButton.ToolTip = tooltip; | ||||||
|  | 				System.Windows.Automation.AutomationProperties.SetName(MuteButton, tooltip); | ||||||
| 				ButtonIcon.Content = LoadIcon(volume); | 				ButtonIcon.Content = LoadIcon(volume); | ||||||
| 				MuteButton.ToolTip = text.Get(TextKey.SystemControl_AudioDeviceMuteTooltip); |  | ||||||
| 				PopupIcon.Content = LoadIcon(volume); | 				PopupIcon.Content = LoadIcon(volume); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -43,6 +43,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 			CultureCodeTextBlock.Text = layout.CultureCode; | 			CultureCodeTextBlock.Text = layout.CultureCode; | ||||||
| 			CultureNameTextBlock.Text = layout.CultureName; | 			CultureNameTextBlock.Text = layout.CultureName; | ||||||
| 			LayoutNameTextBlock.Text = layout.LayoutName; | 			LayoutNameTextBlock.Text = layout.LayoutName; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, layout.CultureName); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,7 +6,9 @@ | ||||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | using System; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  | using System.Windows.Automation; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
| using System.Windows.Media; | using System.Windows.Media; | ||||||
| using SafeExamBrowser.I18n.Contracts; | using SafeExamBrowser.I18n.Contracts; | ||||||
|  | @ -49,10 +51,36 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 					LayoutsStackPanel.Children[0].Focus(); | 					LayoutsStackPanel.Children[0].Focus(); | ||||||
| 				})); | 				})); | ||||||
| 			}; | 			}; | ||||||
| 			Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver)); | 			var lastOpenedBySpacePress = false; | ||||||
| 			Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver)); | 			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.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) | 		private void Keyboard_LayoutChanged(IKeyboardLayout layout) | ||||||
|  | @ -96,6 +124,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			Text.Text = layout.CultureName; | 			Text.Text = layout.CultureName; | ||||||
| 			Button.ToolTip = tooltip; | 			Button.ToolTip = tooltip; | ||||||
|  | 			AutomationProperties.SetName(Button, tooltip); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | ||||||
|  |  | ||||||
|  | @ -34,5 +34,10 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 			NetworkNameTextBlock.Text = network.Name; | 			NetworkNameTextBlock.Text = network.Name; | ||||||
| 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		public void SetFocus() | ||||||
|  | 		{ | ||||||
|  | 			Button.Focus(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -45,10 +45,50 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 
 | 
 | ||||||
| 			adapter.Changed += () => Dispatcher.InvokeAsync(Update); | 			adapter.Changed += () => Dispatcher.InvokeAsync(Update); | ||||||
| 			Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; | 			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; | ||||||
| 			Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver)); | 			Button.PreviewKeyDown += (o, args) => | ||||||
| 			Popup.Opened += (o, args) => Grid.Background = Brushes.Gray; | 			{ | ||||||
| 			Popup.Closed += (o, args) => Grid.Background = originalBrush; | 				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); | 			WirelessIcon.Child = GetWirelessIcon(0); | ||||||
| 
 | 
 | ||||||
| 			Update(); | 			Update(); | ||||||
|  | @ -121,7 +161,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 		{ | 		{ | ||||||
| 			Button.ToolTip = text; | 			Button.ToolTip = text; | ||||||
| 			Text.Text = 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) | 		private UIElement GetWirelessIcon(int signalStrength) | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | ||||||
| 			Text.Text = tooltip; | 			Text.Text = tooltip; | ||||||
| 			Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? 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) | 		private void RenderCharge(double charge, BatteryChargeStatus status) | ||||||
|  |  | ||||||
|  | @ -55,15 +55,41 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenter | ||||||
| 			RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") }; | 			RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") }; | ||||||
| 			Icon.Content = IconResourceLoader.Load(LoweredIcon); | 			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.PreviewMouseLeftButtonUp += NotificationButton_PreviewMouseLeftButtonUp; | ||||||
| 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | ||||||
| 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | ||||||
| 
 | 
 | ||||||
| 			Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			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.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); | 			Text.Text = text.Get(TextKey.Notification_ProctoringHandLowered); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			Button.MouseEnter += (o, args) => WindowPopup.IsOpen = WindowStackPanel.Children.Count > 0; | 			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.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = WindowPopup.IsMouseOver || ActiveBar.IsMouseOver)); | ||||||
| 			Button.ToolTip = application.Tooltip; | 			Button.ToolTip = application.Tooltip; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, application.Tooltip); | ||||||
| 			WindowPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(WindowPopup_PlacementCallback); | 			WindowPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(WindowPopup_PlacementCallback); | ||||||
| 			WindowPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = IsMouseOver)); | 			WindowPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => WindowPopup.IsOpen = IsMouseOver)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ | ||||||
|                     <TextBlock x:Name="AudioDeviceName" Margin="5" TextAlignment="Center" /> |                     <TextBlock x:Name="AudioDeviceName" Margin="5" TextAlignment="Center" /> | ||||||
|                     <StackPanel Orientation="Horizontal" Height="60" Margin="5,0"> |                     <StackPanel Orientation="Horizontal" Height="60" Margin="5,0"> | ||||||
|                         <Button x:Name="MuteButton" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" Width="60"> |                         <Button x:Name="MuteButton" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" Width="60"> | ||||||
|                             <ContentControl x:Name="PopupIcon" /> |                             <ContentControl x:Name="PopupIcon" Focusable="False" /> | ||||||
|                         </Button> |                         </Button> | ||||||
|                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" KeyDown="Volume_KeyDown" |                         <Slider x:Name="Volume" Grid.Column="1" Orientation="Horizontal" TickFrequency="1" Maximum="100" IsSnapToTickEnabled="True" KeyDown="Volume_KeyDown" | ||||||
|                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="125" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted"> |                                 IsMoveToPointEnabled="True" VerticalAlignment="Center" Width="125" Thumb.DragStarted="Volume_DragStarted" Thumb.DragCompleted="Volume_DragCompleted"> | ||||||
|  |  | ||||||
|  | @ -48,12 +48,34 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 
 | 
 | ||||||
| 			audio.VolumeChanged += Audio_VolumeChanged; | 			audio.VolumeChanged += Audio_VolumeChanged; | ||||||
| 			Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; | 			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; | 			MuteButton.Click += MuteButton_Click; | ||||||
| 			MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml") }; | 			MutedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml") }; | ||||||
| 			NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_NoDevice.xaml") }; | 			NoDeviceIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_NoDevice.xaml") }; | ||||||
| 			Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			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; | 			Volume.ValueChanged += Volume_ValueChanged; | ||||||
| 
 | 
 | ||||||
| 			Popup.Opened += (o, args) => | 			Popup.Opened += (o, args) => | ||||||
|  | @ -67,6 +89,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				Button.Background = originalBrush; | 				Button.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			if (audio.HasOutputDevice) | 			if (audio.HasOutputDevice) | ||||||
|  | @ -132,19 +155,24 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			this.muted = muted; | 			this.muted = muted; | ||||||
| 
 | 
 | ||||||
| 			Button.ToolTip = info; | 			Button.ToolTip = info; | ||||||
|  | 			System.Windows.Automation.AutomationProperties.SetName(Button, info); | ||||||
| 			Volume.ValueChanged -= Volume_ValueChanged; | 			Volume.ValueChanged -= Volume_ValueChanged; | ||||||
| 			Volume.Value = Math.Round(volume * 100); | 			Volume.Value = Math.Round(volume * 100); | ||||||
| 			Volume.ValueChanged += Volume_ValueChanged; | 			Volume.ValueChanged += Volume_ValueChanged; | ||||||
| 
 | 
 | ||||||
| 			if (muted) | 			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); | 				PopupIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | 				ButtonIcon.Content = IconResourceLoader.Load(MutedIcon); | ||||||
| 			} | 			} | ||||||
| 			else | 			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); | 				PopupIcon.Content = LoadIcon(volume); | ||||||
| 				ButtonIcon.Content = LoadIcon(volume); | 				ButtonIcon.Content = LoadIcon(volume); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ | ||||||
|             <RowDefinition Height="1*" /> |             <RowDefinition Height="1*" /> | ||||||
|             <RowDefinition Height="1*" /> |             <RowDefinition Height="1*" /> | ||||||
|         </Grid.RowDefinitions> |         </Grid.RowDefinitions> | ||||||
|         <TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" Focusable="True" AutomationProperties.HelpText="{Binding Path=Time}" /> |         <TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" Focusable="True" AutomationProperties.Name="{Binding Path=Time}" /> | ||||||
|         <TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" HorizontalAlignment="Center" VerticalAlignment="Top" Focusable="True" AutomationProperties.HelpText="{Binding Path=Date}" /> |         <TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" HorizontalAlignment="Center" VerticalAlignment="Top" Focusable="True" AutomationProperties.Name="{Binding Path=Date}" /> | ||||||
|     </Grid> |     </Grid> | ||||||
| </UserControl> | </UserControl> | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			CultureCodeTextBlock.Text = layout.CultureCode; | 			CultureCodeTextBlock.Text = layout.CultureCode; | ||||||
| 			CultureNameTextBlock.Text = layout.CultureName; | 			CultureNameTextBlock.Text = layout.CultureName; | ||||||
| 			LayoutNameTextBlock.Text = layout.LayoutName; | 			LayoutNameTextBlock.Text = layout.LayoutName; | ||||||
| 			System.Windows.Automation.AutomationProperties.SetHelpText(Button, layout.LayoutName); | 			System.Windows.Automation.AutomationProperties.SetName(Button, layout.CultureName); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ using System; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.Windows; | using System.Windows; | ||||||
|  | using System.Windows.Automation; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
| using System.Windows.Controls.Primitives; | using System.Windows.Controls.Primitives; | ||||||
| using System.Windows.Media; | using System.Windows.Media; | ||||||
|  | @ -53,9 +54,31 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 					((LayoutsStackPanel.Children[0] as ContentControl).Content as UIElement).Focus(); | 					((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.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) => | 			Popup.Opened += (o, args) => | ||||||
| 			{ | 			{ | ||||||
|  | @ -67,6 +90,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				Button.Background = originalBrush; | 				Button.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -120,6 +144,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 
 | 
 | ||||||
| 			LayoutCultureCode.Text = layout.CultureCode; | 			LayoutCultureCode.Text = layout.CultureCode; | ||||||
| 			Button.ToolTip = tooltip; | 			Button.ToolTip = tooltip; | ||||||
|  | 			AutomationProperties.SetName(Button, tooltip); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | 		private void Popup_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) | ||||||
|  |  | ||||||
|  | @ -34,5 +34,10 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			NetworkNameTextBlock.Text = network.Name; | 			NetworkNameTextBlock.Text = network.Name; | ||||||
| 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | 			SignalStrengthTextBlock.Text = $"{network.SignalStrength}%"; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		public void SetFocus() | ||||||
|  | 		{ | ||||||
|  | 			Button.Focus(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,21 +46,55 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 
 | 
 | ||||||
| 			adapter.Changed += () => Dispatcher.InvokeAsync(Update); | 			adapter.Changed += () => Dispatcher.InvokeAsync(Update); | ||||||
| 			Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen; | 			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; | ||||||
|  | 			})); | ||||||
| 			Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			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); | 			WirelessIcon.Child = GetWirelessIcon(0); | ||||||
| 
 | 
 | ||||||
| 			Popup.Opened += (o, args) => | 			Popup.Opened += (o, args) => | ||||||
| 			{ | 			{ | ||||||
| 				Background = Brushes.LightGray; | 				Background = Brushes.LightGray; | ||||||
| 				Button.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) => | 			Popup.Closed += (o, args) => | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				Button.Background = originalBrush; | 				Button.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			Update(); | 			Update(); | ||||||
|  | @ -87,8 +121,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 				if (network.Status == ConnectionStatus.Connected) | 				if (network.Status == ConnectionStatus.Connected) | ||||||
| 				{ | 				{ | ||||||
| 					WirelessIcon.Child = GetWirelessIcon(network.SignalStrength); | 					WirelessIcon.Child = GetWirelessIcon(network.SignalStrength); | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnected).Replace("%%NAME%%", network.Name)); | ||||||
| 					Button.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, Button.ToolTip as string); |  | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				WirelessNetworksStackPanel.Children.Add(button); | 				WirelessNetworksStackPanel.Children.Add(button); | ||||||
|  | @ -98,7 +131,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				case ConnectionType.Wired: | 				case ConnectionType.Wired: | ||||||
| 					Button.IsEnabled = false; | 					Button.IsEnabled = false; | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWiredConnected); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected)); | ||||||
| 					WiredIcon.Visibility = Visibility.Visible; | 					WiredIcon.Visibility = Visibility.Visible; | ||||||
| 					WirelessIcon.Visibility = Visibility.Collapsed; | 					WirelessIcon.Visibility = Visibility.Collapsed; | ||||||
| 					break; | 					break; | ||||||
|  | @ -109,7 +142,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 					break; | 					break; | ||||||
| 				default: | 				default: | ||||||
| 					Button.IsEnabled = false; | 					Button.IsEnabled = false; | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkNotAvailable); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkNotAvailable)); | ||||||
| 					WiredIcon.Visibility = Visibility.Visible; | 					WiredIcon.Visibility = Visibility.Visible; | ||||||
| 					WirelessIcon.Visibility = Visibility.Collapsed; | 					WirelessIcon.Visibility = Visibility.Collapsed; | ||||||
| 					break; | 					break; | ||||||
|  | @ -118,19 +151,20 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			switch (adapter.Status) | 			switch (adapter.Status) | ||||||
| 			{ | 			{ | ||||||
| 				case ConnectionStatus.Connected: | 				case ConnectionStatus.Connected: | ||||||
|  | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWiredConnected)); | ||||||
| 					NetworkStatusIcon.Rotation = 0; | 					NetworkStatusIcon.Rotation = 0; | ||||||
| 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green); | 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Globe, Brushes.Green); | ||||||
| 					NetworkStatusIcon.Spin = false; | 					NetworkStatusIcon.Spin = false; | ||||||
| 					break; | 					break; | ||||||
| 				case ConnectionStatus.Connecting: | 				case ConnectionStatus.Connecting: | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkWirelessConnecting); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkWirelessConnecting)); | ||||||
| 					NetworkStatusIcon.Rotation = 0; | 					NetworkStatusIcon.Rotation = 0; | ||||||
| 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray); | 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Cog, Brushes.DimGray); | ||||||
| 					NetworkStatusIcon.Spin = true; | 					NetworkStatusIcon.Spin = true; | ||||||
| 					NetworkStatusIcon.SpinDuration = 2; | 					NetworkStatusIcon.SpinDuration = 2; | ||||||
| 					break; | 					break; | ||||||
| 				default: | 				default: | ||||||
| 					Button.ToolTip = text.Get(TextKey.SystemControl_NetworkDisconnected); | 					UpdateText(text.Get(TextKey.SystemControl_NetworkDisconnected)); | ||||||
| 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange); | 					NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.Ban, Brushes.DarkOrange); | ||||||
| 					NetworkStatusIcon.Spin = false; | 					NetworkStatusIcon.Spin = false; | ||||||
| 					WirelessIcon.Child = GetWirelessIcon(0); | 					WirelessIcon.Child = GetWirelessIcon(0); | ||||||
|  | @ -138,6 +172,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		private void UpdateText(string text) | ||||||
|  | 		{ | ||||||
|  | 			Button.ToolTip = text; | ||||||
|  | 			Button.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		private UIElement GetWirelessIcon(int signalStrength) | 		private UIElement GetWirelessIcon(int signalStrength) | ||||||
| 		{ | 		{ | ||||||
| 			var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0")); | 			var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0")); | ||||||
|  |  | ||||||
|  | @ -101,7 +101,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			Button.ToolTip = tooltip; | 			Button.ToolTip = tooltip; | ||||||
| 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | 			PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed; | ||||||
| 			Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? 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) | 		private void RenderCharge(double charge, BatteryChargeStatus status) | ||||||
|  |  | ||||||
|  | @ -55,13 +55,35 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") }; | 			RaisedIcon = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml") }; | ||||||
| 			Icon.Content = IconResourceLoader.Load(LoweredIcon); | 			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.PreviewMouseLeftButtonUp += NotificationButton_PreviewMouseLeftButtonUp; | ||||||
| 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | 			NotificationButton.PreviewMouseRightButtonUp += NotificationButton_PreviewMouseRightButtonUp; | ||||||
| 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | 			NotificationButton.ToolTip = text.Get(TextKey.Notification_ProctoringHandLowered); | ||||||
| 
 | 
 | ||||||
| 			Popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			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) => | 			Popup.Opened += (o, args) => | ||||||
| 			{ | 			{ | ||||||
| 				Background = Brushes.LightGray; | 				Background = Brushes.LightGray; | ||||||
|  | @ -72,6 +94,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls.Taskbar | ||||||
| 			{ | 			{ | ||||||
| 				Background = originalBrush; | 				Background = originalBrush; | ||||||
| 				NotificationButton.Background = originalBrush; | 				NotificationButton.Background = originalBrush; | ||||||
|  | 				lastOpenedBySpacePress = false; | ||||||
| 			}; | 			}; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -244,8 +244,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows | ||||||
| 			Dispatcher.Invoke(() => | 			Dispatcher.Invoke(() => | ||||||
| 			{ | 			{ | ||||||
| 				ZoomLevel.Text = $"{value}%"; | 				ZoomLevel.Text = $"{value}%"; | ||||||
| 				var zoomButtonHelpText = text.Get(TextKey.BrowserWindow_ZoomLevelReset).Replace("%%ZOOM%%", value.ToString("0")); | 				var zoomButtonName = text.Get(TextKey.BrowserWindow_ZoomLevelReset).Replace("%%ZOOM%%", value.ToString("0")); | ||||||
| 				ZoomResetButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, zoomButtonHelpText); | 				ZoomResetButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, zoomButtonName); | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -473,9 +473,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows | ||||||
| 			HomeButton.Click += (o, args) => HomeNavigationRequested?.Invoke(); | 			HomeButton.Click += (o, args) => HomeNavigationRequested?.Invoke(); | ||||||
| 			Loaded += BrowserWindow_Loaded; | 			Loaded += BrowserWindow_Loaded; | ||||||
| 			MenuButton.Click += MenuButton_Click; | 			MenuButton.Click += MenuButton_Click; | ||||||
| 			MenuButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver)); |  | ||||||
| 			MenuPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | 			MenuPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(Popup_PlacementCallback); | ||||||
| 			MenuPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver)); | 			MenuPopup.LostFocus += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsKeyboardFocusWithin)); | ||||||
| 			KeyDown += BrowserWindow_KeyDown; | 			KeyDown += BrowserWindow_KeyDown; | ||||||
| 			KeyUp += BrowserWindow_KeyUp; | 			KeyUp += BrowserWindow_KeyUp; | ||||||
| 			LocationChanged += (o, args) => { DownloadsPopup.IsOpen = false; MenuPopup.IsOpen = false; }; | 			LocationChanged += (o, args) => { DownloadsPopup.IsOpen = false; MenuPopup.IsOpen = false; }; | ||||||
|  | @ -646,13 +645,13 @@ if (typeof __SEB_focusElement === 'undefined') { | ||||||
| 		private void LoadText() | 		private void LoadText() | ||||||
| 		{ | 		{ | ||||||
| 			DeveloperConsoleText.Text = text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem); | 			DeveloperConsoleText.Text = text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem); | ||||||
| 			DeveloperConsoleButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem)); | 			DeveloperConsoleButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_DeveloperConsoleMenuItem)); | ||||||
| 			FindCaseSensitiveCheckBox.Content = text.Get(TextKey.BrowserWindow_FindCaseSensitive); | 			FindCaseSensitiveCheckBox.Content = text.Get(TextKey.BrowserWindow_FindCaseSensitive); | ||||||
| 			FindMenuText.Text = text.Get(TextKey.BrowserWindow_FindMenuItem); | 			FindMenuText.Text = text.Get(TextKey.BrowserWindow_FindMenuItem); | ||||||
| 			FindMenuButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_FindMenuItem)); | 			FindMenuButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_FindMenuItem)); | ||||||
| 			ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem); | 			ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem); | ||||||
| 			ZoomInButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_ZoomMenuPlus)); | 			ZoomInButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ZoomMenuPlus)); | ||||||
| 			ZoomOutButton.SetValue(System.Windows.Automation.AutomationProperties.HelpTextProperty, text.Get(TextKey.BrowserWindow_ZoomMenuMinus)); | 			ZoomOutButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ZoomMenuMinus)); | ||||||
| 			ReloadButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ReloadButton)); | 			ReloadButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ReloadButton)); | ||||||
| 			BackwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_BackwardButton)); | 			BackwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_BackwardButton)); | ||||||
| 			ForwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ForwardButton)); | 			ForwardButton.SetValue(System.Windows.Automation.AutomationProperties.NameProperty, text.Get(TextKey.BrowserWindow_ForwardButton)); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Damian Büchel
						Damian Büchel