public void MoveWorkspaceToMonitor(Workspace workspace, Monitor newMonitor, bool showOnNewMonitor = true, bool switchTo = true) { var oldMonitor = workspace.Monitor; if (oldMonitor != newMonitor && oldMonitor.Workspaces.Count() > 1) { // unswitch the current workspace if (CurrentWorkspace != workspace && switchTo) { CurrentWorkspace.IsCurrentWorkspace = false; // remove windows from ALT-TAB menu and Taskbar if (CurrentWorkspace.hideFromAltTabWhenOnInactiveWorkspaceCount > 0) { CurrentWorkspace.GetWindows().Where(w => w.hideFromAltTabAndTaskbarWhenOnInactiveWorkspace).ForEach(w => w.ShowInAltTabAndTaskbar(false)); } } // if the workspace to be moved is visible on the old monitor, switch to another one if (oldMonitor.CurrentVisibleWorkspace == workspace) { var oldMonitorNewWorkspace = oldMonitor.Workspaces.First(ws => !ws.IsWorkspaceVisible); ShowHideWindows(workspace, oldMonitorNewWorkspace, false); oldMonitor.SwitchToWorkspace(oldMonitorNewWorkspace); } // remove from old/add to new monitor oldMonitor.RemoveWorkspace(workspace); workspace.Monitor = newMonitor; newMonitor.AddWorkspace(workspace); if (switchTo || showOnNewMonitor) // if the workspace must be switched to, it must be shown too { // switch to the workspace now on the new monitor ShowHideWindows(newMonitor.CurrentVisibleWorkspace, workspace, true); newMonitor.SwitchToWorkspace(workspace); } // switch to the moved workspace if (CurrentWorkspace != workspace && switchTo) { workspace.IsCurrentWorkspace = true; // add windows to ALT-TAB menu and Taskbar if (workspace.hideFromAltTabWhenOnInactiveWorkspaceCount > 0) { workspace.GetWindows().Where(w => w.hideFromAltTabAndTaskbarWhenOnInactiveWorkspace).ForEach(w => w.ShowInAltTabAndTaskbar(true)); } CurrentWorkspace = workspace; } if (CurrentWorkspace == workspace && config.MoveMouseOverMonitorsOnSwitch) { Utilities.MoveMouseToMiddleOf(workspace.Monitor.Bounds); } // reposition the windows on the workspace workspace.Reposition(); Workspace.DoWorkspaceMonitorChanged(workspace, oldMonitor, newMonitor); } }
private void ShowHideWindows(Workspace oldWorkspace, Workspace newWorkspace, bool setForeground) { var winPosInfo = NativeMethods.BeginDeferWindowPos(newWorkspace.GetWindowsCount() + oldWorkspace.GetWindowsCount()); var showWindows = newWorkspace.GetWindows(); foreach (var window in showWindows.Where(Utilities.WindowIsNotHung)) { winPosInfo = window.GetOwnedWindows().Aggregate(winPosInfo, (current, hWnd) => NativeMethods.DeferWindowPos(current, 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_SHOWWINDOW)); if (window.redrawOnShow) { window.Redraw(); } } var hideWindows = oldWorkspace.sharedWindowsCount > 0 && newWorkspace.sharedWindowsCount > 0 ? oldWorkspace.GetWindows().Except(showWindows) : oldWorkspace.GetWindows(); // if the window is not visible we shouldn't add it to hiddenApplications as EVENT_OBJECT_HIDE won't be sent foreach (var window in hideWindows.Where(Utilities.IsVisibleAndNotHung)) { hiddenApplications.Add(window.hWnd); winPosInfo = window.GetOwnedWindows().Aggregate(winPosInfo, (current, hWnd) => NativeMethods.DeferWindowPos(current, 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); // activates the topmost non-minimized window if (setForeground) { DoForTopmostWindowForWorkspace(newWorkspace, ForceForegroundWindow); } }