diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataProcessor.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataProcessor.cs index 4df1819c..45790129 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataProcessor.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataProcessor.cs @@ -74,6 +74,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData { settings.Proctoring.WindowVisibility = WindowVisibility.Hidden; } + + if (settings.Proctoring.Zoom.Enabled && !settings.Proctoring.Zoom.ReceiveVideo) + { + settings.Proctoring.WindowVisibility = WindowVisibility.Hidden; + } } private void RemoveLegacyBrowsers(AppSettings settings) diff --git a/SafeExamBrowser.Proctoring/ProctoringController.cs b/SafeExamBrowser.Proctoring/ProctoringController.cs index 8ab3c461..f73ab60e 100644 --- a/SafeExamBrowser.Proctoring/ProctoringController.cs +++ b/SafeExamBrowser.Proctoring/ProctoringController.cs @@ -185,7 +185,14 @@ namespace SafeExamBrowser.Proctoring if (settings.WindowVisibility == WindowVisibility.AllowToShow || settings.WindowVisibility == WindowVisibility.Hidden) { - window.Hide(); + if (settings.Zoom.Enabled) + { + window.HideWithDelay(); + } + else + { + window.Hide(); + } } IconResource = new XamlIconResource { Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ProctoringNotification_Active.xaml") }; diff --git a/SafeExamBrowser.UserInterface.Contracts/Proctoring/IProctoringWindow.cs b/SafeExamBrowser.UserInterface.Contracts/Proctoring/IProctoringWindow.cs index cb1e8ce9..bae9b51f 100644 --- a/SafeExamBrowser.UserInterface.Contracts/Proctoring/IProctoringWindow.cs +++ b/SafeExamBrowser.UserInterface.Contracts/Proctoring/IProctoringWindow.cs @@ -15,6 +15,12 @@ namespace SafeExamBrowser.UserInterface.Contracts.Proctoring /// public interface IProctoringWindow : IWindow { + /// + /// First moves the window to the background and then hides it after a timeout. This might be necessary to allow the meeting client to + /// finish its initialization work and start the microphone as well as the camera before being hidden. + /// + void HideWithDelay(); + /// /// Sets the window title to the given value. /// diff --git a/SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringWindow.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringWindow.xaml.cs index 1a554407..7892d226 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringWindow.xaml.cs +++ b/SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringWindow.xaml.cs @@ -7,6 +7,7 @@ */ using System.ComponentModel; +using System.Threading.Tasks; using System.Windows; using SafeExamBrowser.UserInterface.Contracts.Proctoring; using SafeExamBrowser.UserInterface.Contracts.Windows; @@ -59,6 +60,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Windows Dispatcher.Invoke(base.Hide); } + public void HideWithDelay() + { + Dispatcher.Invoke(() => this.MoveToBackground()); + Task.Delay(10000).ContinueWith(_ => Hide()); + } + public void SetTitle(string title) { Dispatcher.Invoke(() => Title = title ?? ""); diff --git a/SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringWindow.xaml.cs b/SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringWindow.xaml.cs index cc58b86d..92a39782 100644 --- a/SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringWindow.xaml.cs +++ b/SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringWindow.xaml.cs @@ -7,6 +7,7 @@ */ using System.ComponentModel; +using System.Threading.Tasks; using System.Windows; using SafeExamBrowser.UserInterface.Contracts.Proctoring; using SafeExamBrowser.UserInterface.Contracts.Windows; @@ -59,6 +60,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Windows Dispatcher.Invoke(base.Hide); } + public void HideWithDelay() + { + Dispatcher.Invoke(() => this.MoveToBackground()); + Task.Delay(10000).ContinueWith(_ => Hide()); + } + public void SetTitle(string title) { Dispatcher.Invoke(() => Title = title ?? ""); diff --git a/SafeExamBrowser.UserInterface.Shared/Utilities/WindowExtensions.cs b/SafeExamBrowser.UserInterface.Shared/Utilities/WindowExtensions.cs index 6258af4b..2ba3a97b 100644 --- a/SafeExamBrowser.UserInterface.Shared/Utilities/WindowExtensions.cs +++ b/SafeExamBrowser.UserInterface.Shared/Utilities/WindowExtensions.cs @@ -20,8 +20,11 @@ namespace SafeExamBrowser.UserInterface.Shared.Utilities private const uint MF_GRAYED = 0x00000001; private const uint MF_ENABLED = 0x00000000; private const uint SC_CLOSE = 0xF060; + private const uint SWP_SHOWWINDOW = 0x0040; private const int WS_SYSMENU = 0x80000; + private static readonly IntPtr HWND_BOTTOM = new IntPtr(1); + public static void DisableCloseButton(this Window window) { var helper = new WindowInteropHelper(window); @@ -41,6 +44,17 @@ namespace SafeExamBrowser.UserInterface.Shared.Utilities SetWindowLong(helper.Handle, GWL_STYLE, style); } + public static void MoveToBackground(this Window window) + { + var helper = new WindowInteropHelper(window); + var x = (int) window.TransformFromPhysical(window.Left, 0).X; + var y = (int) window.TransformFromPhysical(0, window.Top).Y; + var width = (int) window.TransformFromPhysical(window.Width, 0).X; + var height = (int) window.TransformFromPhysical(0, window.Height).Y; + + SetWindowPos(helper.Handle, HWND_BOTTOM, x, y, width, height, SWP_SHOWWINDOW); + } + [DllImport("user32.dll")] private static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable); @@ -52,5 +66,8 @@ namespace SafeExamBrowser.UserInterface.Shared.Utilities [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + + [DllImport("user32.dll")] + private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); } }