/* * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ using System; using System.Windows.Forms; using Microsoft.Win32; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; using SafeExamBrowser.Contracts.Monitoring.Events; using SafeExamBrowser.Contracts.SystemComponents; using SafeExamBrowser.Contracts.WindowsApi; using OperatingSystem = SafeExamBrowser.Contracts.SystemComponents.OperatingSystem; namespace SafeExamBrowser.Monitoring.Display { public class DisplayMonitor : IDisplayMonitor { private IBounds originalWorkingArea; private ILogger logger; private INativeMethods nativeMethods; private ISystemInfo systemInfo; private string wallpaper; public event DisplayChangedEventHandler DisplayChanged; public DisplayMonitor(ILogger logger, INativeMethods nativeMethods, ISystemInfo systemInfo) { this.logger = logger; this.nativeMethods = nativeMethods; this.systemInfo = systemInfo; } public void InitializePrimaryDisplay(int taskbarHeight) { InitializeWorkingArea(taskbarHeight); InitializeWallpaper(); } public void PreventSleepMode() { nativeMethods.PreventSleepMode(); logger.Info("Disabled sleep mode and display timeout."); } public void ResetPrimaryDisplay() { ResetWorkingArea(); ResetWallpaper(); } public void StartMonitoringDisplayChanges() { SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged; logger.Info("Started monitoring display changes."); } public void StopMonitoringDisplayChanges() { SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged; logger.Info("Stopped monitoring display changes."); } private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) { logger.Info("Display change detected!"); DisplayChanged?.Invoke(); } private void InitializeWorkingArea(int taskbarHeight) { var identifier = GetIdentifierForPrimaryDisplay(); if (originalWorkingArea == null) { originalWorkingArea = nativeMethods.GetWorkingArea(); LogWorkingArea($"Saved original working area for {identifier}", originalWorkingArea); } var area = new Bounds { Left = 0, Top = 0, Right = Screen.PrimaryScreen.Bounds.Width, Bottom = Screen.PrimaryScreen.Bounds.Height - taskbarHeight }; LogWorkingArea($"Trying to set new working area for {identifier}", area); nativeMethods.SetWorkingArea(area); LogWorkingArea($"Working area of {identifier} is now set to", nativeMethods.GetWorkingArea()); } private void InitializeWallpaper() { if (systemInfo.OperatingSystem == OperatingSystem.Windows7) { var path = nativeMethods.GetWallpaperPath(); if (!String.IsNullOrEmpty(path)) { wallpaper = path; logger.Info($"Saved wallpaper image: {wallpaper}."); } nativeMethods.RemoveWallpaper(); logger.Info("Removed current wallpaper."); } } private void ResetWorkingArea() { var identifier = GetIdentifierForPrimaryDisplay(); if (originalWorkingArea != null) { nativeMethods.SetWorkingArea(originalWorkingArea); LogWorkingArea($"Restored original working area for {identifier}", originalWorkingArea); } else { logger.Warn($"Could not restore original working area for {identifier}!"); } } private void ResetWallpaper() { if (systemInfo.OperatingSystem == OperatingSystem.Windows7 && !String.IsNullOrEmpty(wallpaper)) { nativeMethods.SetWallpaper(wallpaper); logger.Info($"Restored wallpaper image: {wallpaper}."); } } private string GetIdentifierForPrimaryDisplay() { var display = Screen.PrimaryScreen.DeviceName?.Replace(@"\\.\", string.Empty); return $"{display} ({Screen.PrimaryScreen.Bounds.Width}x{Screen.PrimaryScreen.Bounds.Height})"; } private void LogWorkingArea(string message, IBounds area) { logger.Info($"{message}: Left = {area.Left}, Top = {area.Top}, Right = {area.Right}, Bottom = {area.Bottom}."); } } }