Compare commits

...

14 commits
5.64 ... master

5 changed files with 74 additions and 31 deletions

View file

@ -60,7 +60,6 @@
* Dual Position Switching functionality:
* Click the desktop window to bring the foreground window to its previous background position and Z-order.
* Shift + Click the desktop window to bring the foreground window to its *second* last background position. This is useful if the previous background position is mis-captured due to invoking start menu or other popups.
* Ctrl + Click the desktop window to bring the foreground window to its previous Z-order while keeping the current location and size.
* To cancel Dual Position Switching:

View file

@ -34,7 +34,7 @@ namespace PersistentWindows.Common
public int UserForcedRestoreLatency = 0;
private const int CaptureLatency = 3000; // delay in milliseconds from window OS move to capture
private const int UserMoveLatency = 1000; // delay in milliseconds from user move/minimize/unminimize/maximize to capture, must < CaptureLatency
private const int ForegroundTimerLatency = UserMoveLatency / 5;
private const int ForegroundTimerLatency = UserMoveLatency / 4;
private const int MaxUserMoves = 4; // max user window moves per capture cycle
private const int MinWindowOsMoveEvents = 12; // threshold of window move events initiated by OS per capture cycle
private const int MaxSnapshots = 38; // 0-9, a-z, ` (for redo last auto restore) and final one for undo last snapshot restore
@ -161,7 +161,7 @@ namespace PersistentWindows.Common
private static Dictionary<IntPtr, string> windowProcessName = new Dictionary<IntPtr, string>();
private Process process;
private ProcessPriorityClass processPriority;
public ProcessPriorityClass processPriority;
private string appDataFolder;
public bool redirectAppDataFolder = false;
@ -483,6 +483,10 @@ namespace PersistentWindows.Common
}
else if (fullScreenGamingWindow == IntPtr.Zero)
{
//create window event may be delayed
if (hwnd != IntPtr.Zero && !noRestoreWindows.Contains(hwnd))
CaptureWindow(hwnd, 0, DateTime.Now, curDisplayKey);
StartCaptureTimer();
//speed up initial capture
@ -518,12 +522,12 @@ namespace PersistentWindows.Common
if (!ctrl_key_pressed && !alt_key_pressed)
{
//restore window to previous background position
SwitchForeBackground(hwnd, secondBackGround:shift_key_pressed);
SwitchForeBackground(hwnd);
}
else if (ctrl_key_pressed && !alt_key_pressed)
{
//restore to previous background zorder with current size/pos
SwitchForeBackground(hwnd, strict_dps_check: false, updateBackgroundPos: true, secondBackGround:shift_key_pressed);
SwitchForeBackground(hwnd, strict_dps_check: false, updateBackgroundPos: true);
}
else if (!ctrl_key_pressed && alt_key_pressed && !shift_key_pressed)
{
@ -594,8 +598,6 @@ namespace PersistentWindows.Common
public bool Start(bool auto_restore_from_db, bool auto_restore_last_capture_at_startup)
{
process = Process.GetCurrentProcess();
processPriority = process.PriorityClass;
string productName = System.Windows.Forms.Application.ProductName;
appDataFolder = redirectAppDataFolder ? "." :
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), productName);
@ -769,8 +771,6 @@ namespace PersistentWindows.Common
Log.Event("Restore finished in pass {0} with {1} windows recovered for display setting {2}", restorePass, numWindowRestored, curDisplayKey);
sessionActive = true;
WriteDataDump();
if (!wasRestoringSnapshot && !wasRestoringFromDB)
{
if (!snapshotTakenTime.ContainsKey(curDisplayKey))
@ -865,6 +865,7 @@ namespace PersistentWindows.Common
(s, e) =>
{
process.PriorityClass = ProcessPriorityClass.High;
EndDisplaySession();
WriteDataDump();
Log.Event("Session ending");
};
@ -873,6 +874,9 @@ namespace PersistentWindows.Common
this.displaySettingsChangingHandler =
(s, e) =>
{
if (fastRestore)
process.PriorityClass = ProcessPriorityClass.High;
if (!freezeCapture)
{
lastDisplayChangeTime = DateTime.Now;
@ -895,9 +899,6 @@ namespace PersistentWindows.Common
this.displaySettingsChangedHandler =
(s, e) =>
{
if (fastRestore)
process.PriorityClass = ProcessPriorityClass.High;
string displayKey = GetDisplayKey();
Log.Event("Display settings changed {0}", displayKey);
@ -1502,7 +1503,9 @@ namespace PersistentWindows.Common
lock(captureLock)
foreach (var kid in deadAppPos.Keys)
{
var appPos = deadAppPos[kid].Last<ApplicationDisplayMetrics>();
var appPos = deadAppPos[kid].LastOrDefault<ApplicationDisplayMetrics>();
if (appPos == null)
continue;
if (!procName.Equals(appPos.ProcessName))
continue;
@ -1571,10 +1574,11 @@ namespace PersistentWindows.Common
{
foreach (var dm in monitorApplications[curDisplayKey][h])
{
if (style != dm.Style && dm.Style != 0)
if (IsMinimized(hwnd) != dm.IsMinimized)
continue;
if (ext_style != dm.ExtStyle && dm.ExtStyle != 0)
if (User32.IsWindowVisible(hwnd) == dm.IsInvisible)
continue;
if (dm.ProcessName == procName)
{
proc_name_match_cnt++;
@ -1935,6 +1939,10 @@ namespace PersistentWindows.Common
// ignore non-window object (caret etc)
return;
bool ctrl_key_pressed = (User32.GetKeyState(0x11) & 0x8000) != 0;
bool alt_key_pressed = (User32.GetKeyState(0x12) & 0x8000) != 0;
bool shift_key_pressed = (User32.GetKeyState(0x10) & 0x8000) != 0;
{
switch (eventType)
{
@ -1989,7 +1997,8 @@ namespace PersistentWindows.Common
if (dm.SnapShotFlags == 0)
dm.CaptureTime = DateTime.Now; //for inheritence in LIFO stile
deadApps[display_config][hwnd] = monitorApplications[display_config][hwnd];
if (!ctrl_key_pressed)
deadApps[display_config][hwnd] = monitorApplications[display_config][hwnd];
windowTitle.Remove((IntPtr)monitorApplications[display_config][hwnd].Last().WindowId);
windowTitle.Remove(hwnd);
@ -2063,9 +2072,6 @@ namespace PersistentWindows.Common
#endif
// suppress capture for taskbar operation
bool ctrl_key_pressed = (User32.GetKeyState(0x11) & 0x8000) != 0;
bool alt_key_pressed = (User32.GetKeyState(0x12) & 0x8000) != 0;
bool shift_key_pressed = (User32.GetKeyState(0x10) & 0x8000) != 0;
if (ctrl_key_pressed && alt_key_pressed)
return;
@ -2611,7 +2617,7 @@ namespace PersistentWindows.Common
Log.Event("Bring foreground window {0} to bottom", GetWindowTitle(hwnd));
}
public void SwitchForeBackground(IntPtr hwnd, bool strict_dps_check = true, bool toForeground=false, bool updateBackgroundPos=false, bool secondBackGround = false)
public void SwitchForeBackground(IntPtr hwnd, bool strict_dps_check = true, bool toForeground=false, bool updateBackgroundPos=false)
{
if (hwnd == IntPtr.Zero || IsTaskBar(hwnd))
return;
@ -2636,8 +2642,6 @@ namespace PersistentWindows.Common
if (toForeground && IsTaskBar(front_hwnd))
return; //already foreground
IntPtr firstBackgroundWindow = IntPtr.Zero;
for (; prevIndex >= 0; --prevIndex)
{
var metrics = monitorApplications[curDisplayKey][hwnd][prevIndex];
@ -2646,8 +2650,16 @@ namespace PersistentWindows.Common
continue;
}
if (!toForeground)
{
RECT screenPosition = new RECT();
User32.GetWindowRect(hwnd, ref screenPosition);
if (screenPosition.Equals(metrics.ScreenPosition))
continue;
}
IntPtr prevZwnd = metrics.PrevZorderWindow;
if (prevZwnd != front_hwnd && (prevZwnd == IntPtr.Zero || prevZwnd != firstBackgroundWindow))
if (prevZwnd != front_hwnd)
{
if (toForeground)
{
@ -2656,12 +2668,6 @@ namespace PersistentWindows.Common
}
else
{
if (secondBackGround)
{
firstBackgroundWindow = prevZwnd;
secondBackGround = false;
continue;
}
if (IsTaskBar(front_hwnd) && IsTaskBar(prevZwnd))
return; //#266, ignore taskbar (as prev-zwindow) change due to window maximize
@ -3696,6 +3702,7 @@ namespace PersistentWindows.Common
0, 0, 0, UIntPtr.Zero);
Log.Error("restore full screen window {0}", GetWindowTitle(hwnd));
/*
Thread.Sleep(3 * double_clck_interval);
style = User32.GetWindowLong(hwnd, User32.GWL_STYLE);
@ -3720,6 +3727,7 @@ namespace PersistentWindows.Common
}
Log.Error("fail to restore full screen window {0}", GetWindowTitle(hwnd));
*/
}
private void RestoreSnapWindow(IntPtr hwnd, RECT target_pos)

View file

@ -56,6 +56,15 @@ if not errorlevel 1 goto wait_to_finish";
pwp = new PersistentWindowProcessor();
var process = Process.GetCurrentProcess();
pwp.processPriority = process.PriorityClass;
process.PriorityClass = ProcessPriorityClass.High;
var timer = new System.Threading.Timer(state =>
{
process.PriorityClass = pwp.processPriority;
});
timer.Change(10000, System.Threading.Timeout.Infinite);
bool splash = true;
int delay_restart = 0;
int relaunch_delay = 0;

View file

@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PersistentWindows")]
[assembly: AssemblyCopyright("Copyright © 2014 - 2024, PersistentWindows")]
[assembly: AssemblyCopyright("Copyright © 2014 - 2025, PersistentWindows")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.64.*")]
[assembly: AssemblyVersion("5.65.*")]

View file

@ -7,6 +7,7 @@ using System.Timers;
using System.IO;
using System.IO.Compression;
using System.Drawing;
using System.Reflection;
using PersistentWindows.Common.Diagnostics;
using PersistentWindows.Common.WinApiBridge;
@ -21,6 +22,7 @@ namespace PersistentWindows.SystrayShell
public bool toggleIcon = false;
private int skipUpgradeCounter = 0;
private bool initialCheckUpgrade = true;
private bool pauseUpgradeCounter = false;
public bool autoUpgrade = false;
@ -196,6 +198,31 @@ namespace PersistentWindows.SystrayShell
{
if (skipUpgradeCounter == 0)
{
if (initialCheckUpgrade)
{
initialCheckUpgrade = false;
var dst_dir = Path.Combine($"{Program.AppdataFolder}", "upgrade");
var upgrade_exe = Path.Combine(dst_dir, $"{Application.ProductName}.exe");
if (Directory.Exists(dst_dir) && File.Exists(upgrade_exe))
{
var version = AssemblyName.GetAssemblyName(upgrade_exe).Version;
string[] latest = version.ToString().Split('.');
int latest_major = Int32.Parse(latest[0]);
int latest_minor = Int32.Parse(latest[1]);
string[] current = Application.ProductVersion.Split('.');
int current_major = Int32.Parse(current[0]);
int current_minor = Int32.Parse(current[1]);
if (latest_major > current_major ||
latest_major == current_major && latest_minor > current_minor)
{
//upgrade version already downloaded, skip the initial notice to give user more time to make decision
skipUpgradeCounter++;
return;
}
}
}
CheckUpgradeSafe();
}