internal Windawesome() { applications = new Dictionary<IntPtr, LinkedList<Tuple<Workspace, Window>>>(20); hiddenApplications = new HashMultiSet<IntPtr>(); messageHandlers = new Dictionary<int, HandleMessageDelegate>(2); monitors = Screen.AllScreens.Select((_, i) => new Monitor(i)).ToArray(); this.CreateHandle(new CreateParams { Parent = NativeMethods.HWND_MESSAGE, ClassName = "Message" }); HandleStatic = this.Handle; config = new Config(); config.LoadConfiguration(this); var startingWorkspacesCount = config.StartingWorkspaces.Count(); var distinctStartingWorkspaceMonitorsCount = config.StartingWorkspaces.Select(w => w.Monitor).Distinct().Count(); if (distinctStartingWorkspaceMonitorsCount != monitors.Length || distinctStartingWorkspaceMonitorsCount != startingWorkspacesCount) { throw new Exception("Each Monitor should have exactly one corresponding Workspace in StartingWorkspaces, i.e. " + "you should have as many Workspaces in StartingWorkspaces as you have Monitors!"); } CurrentWorkspace = config.StartingWorkspaces.First(w => w.Monitor.screen.Primary); topmostWindows = new WindowBase[config.Workspaces.Length]; Workspace.WindowActivatedEvent += h => topmostWindows[CurrentWorkspace.id - 1] = CurrentWorkspace.GetWindow(h) ?? new WindowBase(h); // add workspaces to their corresponding monitors monitors.ForEach(m => config.Workspaces.Where(w => w.Monitor == m).ForEach(m.AddWorkspace)); // n ^ 2 but hopefully fast enough // set starting workspaces for each monitor config.StartingWorkspaces.ForEach(w => w.Monitor.SetStartingWorkspace(w)); // initialize bars and plugins config.Bars.ForEach(b => b.InitializeBar(this)); config.Plugins.ForEach(p => p.InitializePlugin(this)); // add all windows to their respective workspaces NativeMethods.EnumWindows((hWnd, _) => (Utilities.IsAppWindow(hWnd) && AddWindowToWorkspace(hWnd, finishedInitializing: false)) || true, IntPtr.Zero); // add a handler for when the working area or screen rosolution changes as well as // a handler for the system shutting down/restarting SystemEvents.UserPreferenceChanged += OnUserPreferenceChanged; SystemEvents.DisplaySettingsChanged += OnDisplaySettingsChanged; SystemEvents.SessionEnding += OnSessionEnding; SystemSettingsChanger.ApplyChanges(config); // initialize all workspaces and hide windows not on StartingWorkspaces var windowsToHide = new HashSet<Window>(); foreach (var workspace in config.Workspaces) { workspace.GetWindows().ForEach(w => windowsToHide.Add(w)); workspace.Initialize(); topmostWindows[workspace.id - 1] = workspace.GetWindows().FirstOrDefault(w => !NativeMethods.IsIconic(w.hWnd)) ?? new WindowBase(NativeMethods.shellWindow); } windowsToHide.ExceptWith(config.StartingWorkspaces.SelectMany(ws => ws.GetWindows())); var winPosInfo = NativeMethods.BeginDeferWindowPos(windowsToHide.Count); winPosInfo = windowsToHide.Where(Utilities.WindowIsNotHung).Aggregate(winPosInfo, (current, w) => NativeMethods.DeferWindowPos(current, w.hWnd, IntPtr.Zero, 0, 0, 0, 0, NativeMethods.SWP.SWP_NOACTIVATE | NativeMethods.SWP.SWP_NOMOVE | NativeMethods.SWP.SWP_NOSIZE | NativeMethods.SWP.SWP_NOZORDER | NativeMethods.SWP.SWP_NOOWNERZORDER | NativeMethods.SWP.SWP_HIDEWINDOW)); NativeMethods.EndDeferWindowPos(winPosInfo); // remove windows from ALT-TAB menu and Taskbar config.StartingWorkspaces.Where(ws => ws != CurrentWorkspace).SelectMany(ws => ws.GetWindows()). Where(w => w.hideFromAltTabAndTaskbarWhenOnInactiveWorkspace).ForEach(w => w.ShowInAltTabAndTaskbar(false)); // initialize monitors and switch to the default starting workspaces monitors.ForEach(m => m.Initialize()); Monitor.ShowHideWindowsTaskbar(CurrentWorkspace.ShowWindowsTaskbar); DoForTopmostWindowForWorkspace(CurrentWorkspace, ActivateWindow); CurrentWorkspace.IsCurrentWorkspace = true; // register a shell hook NativeMethods.RegisterShellHookWindow(this.Handle); currentActiveWindow = NativeMethods.GetForegroundWindow(); // register some shell events winEventDelegate = WinEventDelegate; windowDestroyedShownOrHiddenWinEventHook = NativeMethods.SetWinEventHook(NativeMethods.EVENT.EVENT_OBJECT_DESTROY, NativeMethods.EVENT.EVENT_OBJECT_HIDE, IntPtr.Zero, winEventDelegate, 0, 0, NativeMethods.WINEVENT.WINEVENT_OUTOFCONTEXT | NativeMethods.WINEVENT.WINEVENT_SKIPOWNTHREAD); windowMinimizedOrRestoredWinEventHook = NativeMethods.SetWinEventHook(NativeMethods.EVENT.EVENT_SYSTEM_MINIMIZESTART, NativeMethods.EVENT.EVENT_SYSTEM_MINIMIZEEND, IntPtr.Zero, winEventDelegate, 0, 0, NativeMethods.WINEVENT.WINEVENT_OUTOFCONTEXT | NativeMethods.WINEVENT.WINEVENT_SKIPOWNTHREAD); windowFocusedWinEventHook = NativeMethods.SetWinEventHook(NativeMethods.EVENT.EVENT_SYSTEM_FOREGROUND, NativeMethods.EVENT.EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, winEventDelegate, 0, 0, NativeMethods.WINEVENT.WINEVENT_OUTOFCONTEXT | NativeMethods.WINEVENT.WINEVENT_SKIPOWNTHREAD); if (config.CheckForUpdates) { UpdateChecker.CheckForUpdate(); } }
public static void LoadAll(Windawesome windawesome, Config config, IEnumerable<FileInfo> files) { ScriptScope scope = null; ScriptEngine previousLanguage = null; foreach (var file in files) { var engine = GetEngineForFile(file); if (engine != null) { if (scope == null) { scope = engine.CreateScope(); scope.SetVariable("windawesome", windawesome); scope.SetVariable("config", config); } else if (previousLanguage != engine) { var oldScope = scope; scope = engine.CreateScope(); oldScope.GetItems(). Where(variable => variable.Value != null). ForEach(variable => scope.SetVariable(variable.Key, variable.Value)); previousLanguage.Runtime.Globals.GetItems(). Where(variable => variable.Value != null). ForEach(variable => scope.SetVariable(variable.Key, variable.Value)); } scope = engine.ExecuteFile(file.FullName, scope); previousLanguage = engine; } } }