private void ProcessDisplayChanges(ScreenSetupReason reason) { lock (displaySetupLock) { IsSettingDisplays = true; while (pendingDisplayEvents > 0) { if (HaveDisplaysChanged()) { DisplaySetup(reason); } else { // if this is only a DPI change, screens will be the same but we still need to reposition RefreshWindows(reason, false); SetDisplayWorkAreas(); } pendingDisplayEvents--; } IsSettingDisplays = false; } }
private void setScreenProperties(ScreenSetupReason reason) { // process screen changes if we are on the primary display (or any display in the case of a DPI change, since only the changed display receives that message) // and the designated window. suppress this if we are shutting down (which can trigger this method on multi-dpi setups due to window movements) if ((Screen.Primary || reason == ScreenSetupReason.DpiChange) && processScreenChanges && !Startup.IsShuttingDown) { CairoLogger.Instance.Debug("AppBarWindow: Calling screen setup due to " + reason); WindowManager.Instance.NotifyDisplayChange(); // update Cairo window list based on new screen setup } }
private void SetScreenProperties(ScreenSetupReason reason) { // process screen changes if we are on the primary display and the designated window // (or any display in the case of a DPI change, since only the changed display receives that message and not all windows receive it reliably) // suppress this if we are shutting down (which can trigger this method on multi-dpi setups due to window movements) if (((Screen.Primary && processScreenChanges) || reason == ScreenSetupReason.DpiChange) && !Startup.IsShuttingDown) { WindowManager.Instance.NotifyDisplayChange(reason); // update Cairo window list based on new screen setup } }
private void RefreshWindows(ScreenSetupReason reason, bool displaysChanged) { CairoLogger.Instance.Debug("WindowManager: Refreshing screen information for existing windows"); // TODO: Handle these as events in respective classes // update screens of stale windows if (Settings.Instance.EnableMenuBarMultiMon) { foreach (Screen screen in ScreenState) { MenuBar bar = GetScreenWindow(MenuBarWindows, screen); if (bar != null) { bar.Screen = screen; bar.SetScreenPosition(); } } } else if (MenuBarWindows.Count > 0) { MenuBarWindows[0].Screen = Screen.PrimaryScreen; MenuBarWindows[0].SetScreenPosition(); } if (Settings.Instance.EnableTaskbarMultiMon) { foreach (Screen screen in ScreenState) { Taskbar bar = GetScreenWindow(TaskbarWindows, screen); if (bar != null) { bar.Screen = screen; bar.SetScreenPosition(); } } } else if (TaskbarWindows.Count > 0) { TaskbarWindows[0].Screen = Screen.PrimaryScreen; TaskbarWindows[0].SetScreenPosition(); } // notify event subscribers WindowManagerEventArgs args = new WindowManagerEventArgs { DisplaysChanged = displaysChanged, Reason = reason }; ScreensChanged?.Invoke(this, args); }
public void NotifyDisplayChange(ScreenSetupReason reason) { CairoLogger.Instance.Debug($"WindowManager: Received {reason} notification"); if (reason == ScreenSetupReason.DwmChange) { lock (displaySetupLock) { DwmChanged?.Invoke(this, new WindowManagerEventArgs()); } } else { pendingDisplayEvents++; if (!IsSettingDisplays) { ProcessDisplayChanges(reason); } } }
protected override void SetScreenProperties(ScreenSetupReason reason) { if (reason == ScreenSetupReason.DpiChange) { // DPI change is per-monitor, update ourselves SetScreenPosition(); SetLayoutRounding(); return; } if (Settings.Instance.ShowMultiMon) { // Re-create RetroBar windows based on new screen setup _windowManager.NotifyDisplayChange(reason); } else { // Update window as necessary base.SetScreenProperties(reason); } }
public void NotifyDisplayChange(ScreenSetupReason reason) { ShellLogger.Debug($"WindowManager: Display change notification received ({reason})"); if (reason == ScreenSetupReason.DwmChange) { // RetroBar doesn't care when DWM is toggled return; } _pendingDisplayEvents++; if (_isSettingDisplays) { return; } _isSettingDisplays = true; while (_pendingDisplayEvents > 0) { // Skip re-opening taskbars if the screens haven't changed if (!haveDisplaysChanged()) { _pendingDisplayEvents--; continue; } ReopenTaskbars(); _pendingDisplayEvents--; } _isSettingDisplays = false; ShellLogger.Debug($"WindowManager: Finished processing display events"); }
protected override void SetScreenProperties(ScreenSetupReason reason) { _windowManager.NotifyDisplayChange(reason); // update Cairo window list based on new screen setup }
/// <summary> /// Compares the system screen list to the screens associated with Cairo windows, then creates or destroys windows as necessary. /// Runs at startup and when a WM_DEVICECHANGE, WM_DISPLAYCHANGE, or WM_DPICHANGED message is received by the MenuBar window on the primary display. /// </summary> private void DisplaySetup(ScreenSetupReason reason) { if (reason != ScreenSetupReason.FirstRun && !hasCompletedInitialDisplaySetup) { CairoLogger.Instance.Debug("WindowManager: Display setup ran before startup completed, aborting"); return; } CairoLogger.Instance.Debug("WindowManager: Beginning display setup"); List <string> sysScreens = new List <string>(); List <string> openScreens = new List <string>(); List <string> addedScreens = new List <string>(); List <string> removedScreens = new List <string>(); // update our knowledge of the displays present ScreenState = Screen.AllScreens; if (reason != ScreenSetupReason.FirstRun) { // enumerate screens based on currently open windows openScreens = GetOpenScreens(); sysScreens = GetScreenDeviceNames(); // figure out which screens have been added foreach (string name in sysScreens) { if (!openScreens.Contains(name)) { addedScreens.Add(name); } } // figure out which screens have been removed foreach (string name in openScreens) { if (!sysScreens.Contains(name)) { removedScreens.Add(name); } } // abort if we have no screens or if we are removing all screens without adding new ones if (sysScreens.Count == 0 || (removedScreens.Count >= openScreens.Count && addedScreens.Count == 0)) { CairoLogger.Instance.Debug("WindowManager: Aborted due to no displays present"); return; } // close windows associated with removed screens ProcessRemovedScreens(removedScreens); // refresh existing window screen properties with updated screen information RefreshWindows(reason, true); } // open windows on newly added screens ProcessAddedScreens(addedScreens, reason == ScreenSetupReason.FirstRun); // update each display's work area if we are shell SetDisplayWorkAreas(); CairoLogger.Instance.Debug("WindowManager: Completed display setup"); }