Compare commits

..

No commits in common. "master" and "5.61" have entirely different histories.
master ... 5.61

9 changed files with 131 additions and 340 deletions

View file

@ -24,9 +24,8 @@
| -fix_offscreen_window=0 | Turn off auto correction of off-screen windows
| -fix_unminimized_window=0 | Turn off auto restore of unminimized windows. Use this switch to avoid undesirable window shifting during window activation, which comes with Event id 9999 : "restore minimized window ...." in event viewer.
|-auto_restore_new_display_session_from_db=0| Disable window restore from DB upon PC startup or switching display for the first time
|-auto_restore_existing_window_to_last_capture=1 | Turn on auto restore existing window from last capture upon PW start
|-auto_restore_existing_window_to_last_capture=0 | Turn off auto restore upon PW start
|-auto_restore_new_window_to_last_capture=0 | Turn off auto restore new window to last killed position
|-pos_match_threshold 80 | Auto correct new window position to last killed position within range of 80 pixels, default is 40
| auto_restore_missing_windows=1 | When restoring from disk, restore missing windows without prompting the user
| auto_restore_missing_windows=2 | At startup, automatically restore missing windows from disk. The user will be prompted before restoring each missing window
| auto_restore_missing_windows=3 | At startup, automatically restore missing windows from disk without prompting the user
@ -60,6 +59,7 @@
* 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

@ -37,7 +37,6 @@ namespace PersistentWindows.Common
private static POINT lastCursorPos;
private POINT lastWheelCursorPos;
private bool handCursor = false;
private bool ibeamCursor = false;
private int titleHeight;
private Color dfltBackColor;
private bool promptZkey = true;
@ -870,7 +869,6 @@ namespace PersistentWindows.Common
}
else if (Math.Abs(cursorPos.X - lastCursorPos.X) > 3 || Math.Abs(cursorPos.Y - lastCursorPos.Y) > 3)
{
ibeamCursor = false;
//mouse moving, continue monitor
totalWaitSecondsForWhiteColor = 0;
}
@ -908,14 +906,12 @@ namespace PersistentWindows.Common
}
else if (hCursor == Cursors.IBeam.Handle)
{
ibeamCursor = true;
Visible = false;
StartAliveTimer(11, 1000);
return;
}
else if (hCursor == Cursors.Cross.Handle || handCursor)
{
ibeamCursor = false;
StartAliveTimer(7);
return;
}
@ -950,14 +946,6 @@ namespace PersistentWindows.Common
regain_focus = false;
}
if (ibeamCursor && hCursor == Cursors.Default.Handle)
//&& Math.Abs(cursorPos.X - lastCursorPos.X) < 3 && Math.Abs(cursorPos.Y - lastCursorPos.Y) < 3)
{
ibeamCursor = false;
StartAliveTimer(11, 1000);
return;
}
// let tiny hotkey window follow cursor position
ResetHotKeyVirtualDesktop();
ResetHotkeyWindowPos();
@ -980,7 +968,6 @@ namespace PersistentWindows.Common
// hand cursor shape
if (!handCursor)
{
ibeamCursor = false;
handCursor = true;
Left -= 10;
}

View file

@ -26,8 +26,6 @@ namespace PersistentWindows.Common.Models
public bool IsFullScreen { get; set; }
public bool IsMinimized { get; set; }
public bool IsInvisible { get; set; }
public long Style { get; set; }
public long ExtStyle { get; set; }
// for restore window position to display session end time
public DateTime CaptureTime { get; set; }

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 / 4;
private const int ForegroundTimerLatency = UserMoveLatency / 5;
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
@ -42,8 +42,6 @@ namespace PersistentWindows.Common
private const int MaxHistoryQueueLength = 41; // ideally bigger than MaxSnapshots + 2
private const int PauseRestoreTaskbar = 3500; //cursor idle time before dragging taskbar
private const int MinClassNamePrefix = 8; //allow partial class name matching during inheritance
public int MaxDiffPos = 40; //allow matching window of slightly different position
private bool initialized = false;
@ -106,11 +104,10 @@ namespace PersistentWindows.Common
private Timer restoreTimer;
private Timer restoreFinishedTimer;
public bool restoringFromMem = false; // automatic restore from memory or snapshot
private bool restoreSingleWindow = false;
public bool restoringFromDB = false; // manual restore from DB
public bool autoInitialRestoreFromDB = false;
public bool restoringSnapshot = false; // implies restoringFromMem
private Object restoringFullScreenWindow = new object();
private bool restoringFullScreenWindow = false;
public bool showDesktop = false; // show desktop when display changes
public int fixZorder = 1; // 1 means restore z-order only for snapshot; 2 means restore z-order for all; 0 means no z-order restore at all
public int fixZorderMethod = 5; // bit i represent restore method for pass i
@ -161,7 +158,7 @@ namespace PersistentWindows.Common
private static Dictionary<IntPtr, string> windowProcessName = new Dictionary<IntPtr, string>();
private Process process;
public ProcessPriorityClass processPriority;
private ProcessPriorityClass processPriority;
private string appDataFolder;
public bool redirectAppDataFolder = false;
@ -483,10 +480,6 @@ 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
@ -522,12 +515,12 @@ namespace PersistentWindows.Common
if (!ctrl_key_pressed && !alt_key_pressed)
{
//restore window to previous background position
SwitchForeBackground(hwnd);
SwitchForeBackground(hwnd, secondBackGround:shift_key_pressed);
}
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);
SwitchForeBackground(hwnd, strict_dps_check: false, updateBackgroundPos: true, secondBackGround:shift_key_pressed);
}
else if (!ctrl_key_pressed && alt_key_pressed && !shift_key_pressed)
{
@ -598,6 +591,8 @@ 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);
@ -771,6 +766,8 @@ 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,7 +862,6 @@ namespace PersistentWindows.Common
(s, e) =>
{
process.PriorityClass = ProcessPriorityClass.High;
EndDisplaySession();
WriteDataDump();
Log.Event("Session ending");
};
@ -874,9 +870,6 @@ namespace PersistentWindows.Common
this.displaySettingsChangingHandler =
(s, e) =>
{
if (fastRestore)
process.PriorityClass = ProcessPriorityClass.High;
if (!freezeCapture)
{
lastDisplayChangeTime = DateTime.Now;
@ -899,6 +892,9 @@ namespace PersistentWindows.Common
this.displaySettingsChangedHandler =
(s, e) =>
{
if (fastRestore)
process.PriorityClass = ProcessPriorityClass.High;
string displayKey = GetDisplayKey();
Log.Event("Display settings changed {0}", displayKey);
@ -1072,10 +1068,6 @@ namespace PersistentWindows.Common
normalSessions.Add(item);
}
var ticks = Kernel32.GetTickCount64();
if (ticks > 300000) //system up 5min
return true;
if (db_exist && auto_restore_from_db)
{
restoringFromDB = true;
@ -1404,17 +1396,7 @@ namespace PersistentWindows.Common
if (!monitorApplications.ContainsKey(display_key))
monitorApplications[display_key] = new Dictionary<IntPtr, List<ApplicationDisplayMetrics>>();
List<ApplicationDisplayMetrics> app_list = null;
if (monitorApplications[display_key].ContainsKey(hwnd))
{
app_list = monitorApplications[display_key][hwnd];
monitorApplications[display_key].Remove(hwnd);
}
monitorApplications[display_key][hwnd] = deadApps[display_key][kid];
if (app_list != null)
{
monitorApplications[display_key][hwnd].AddRange(app_list);
}
deadApps[display_key].Remove(kid);
//replace prev zorder reference of dead_hwnd with hwnd in monitorApplication
@ -1445,18 +1427,6 @@ namespace PersistentWindows.Common
return r;
}
int LenCommonPrefix(string a, string b)
{
int len = Math.Min(a.Length, b.Length);
int r;
for (r = 0; r < len; ++r)
{
if (a[r] != b[r])
break;
}
return r;
}
private IntPtr FindMatchingKilledWindow(IntPtr hwnd)
{
if (!deadApps.ContainsKey(curDisplayKey))
@ -1488,40 +1458,21 @@ namespace PersistentWindows.Common
if (!string.IsNullOrEmpty(className))
{
int pos_match_cnt = 0;
IntPtr dflt_kid = IntPtr.Zero;
int title_match_cnt = 0;
IntPtr title_match_hid = IntPtr.Zero;
IntPtr pos_match_hid = IntPtr.Zero;
int similar_pos_cnt = 0;
int diff_size = int.MaxValue;
IntPtr similar_pos_hid = IntPtr.Zero;
DateTime last_killed_time = new DateTime(0);
IntPtr last_killed_hid = IntPtr.Zero;
long style = User32.GetWindowLong(hwnd, User32.GWL_STYLE);
long ext_style = User32.GetWindowLong(hwnd, User32.GWL_EXSTYLE);
var deadAppPos = deadApps[curDisplayKey];
lock(captureLock)
foreach (var kid in deadAppPos.Keys)
{
var appPos = deadAppPos[kid].LastOrDefault<ApplicationDisplayMetrics>();
if (appPos == null)
continue;
if (!procName.Equals(appPos.ProcessName))
continue;
if (appPos.Style != 0 && style != appPos.Style)
continue;
if (appPos.ExtStyle != 0 && ext_style != appPos.ExtStyle)
continue;
var appPos = deadAppPos[kid].Last<ApplicationDisplayMetrics>();
if (!className.Equals(appPos.ClassName))
{
if (className.Length != appPos.ClassName.Length)
continue;
if (LenCommonPrefix(className, appPos.ClassName) < MinClassNamePrefix)
continue;
}
continue;
if (!procName.Equals(appPos.ProcessName))
continue;
if (IsMinimized(hwnd) != appPos.IsMinimized)
continue;
@ -1535,76 +1486,26 @@ namespace PersistentWindows.Common
if (rect.Equals(r) && title.Equals(appPos.Title))
return kid;
if (rect.Equals(r))
if (title.Equals(appPos.Title))
{
pos_match_cnt++;
if (title_match_cnt == 0)
title_match_hid = kid;
++title_match_cnt;
}
else if (rect.Equals(r))
pos_match_hid = kid;
}
if (r.Diff(rect) < diff_size)
{
diff_size = r.Diff(rect);
similar_pos_cnt++;
similar_pos_hid = kid;
}
if (appPos.CaptureTime > last_killed_time)
{
last_killed_time = appPos.CaptureTime;
last_killed_hid = kid;
}
else if (dflt_kid == IntPtr.Zero)
dflt_kid = kid;
}
if (pos_match_cnt == 1)
if (title_match_cnt == 1)
return title_match_hid;
if (pos_match_hid != IntPtr.Zero)
return pos_match_hid;
if (diff_size <= MaxDiffPos)
{
Log.Event($"matching window with position diff of {diff_size}");
return similar_pos_hid;
}
if (!monitorApplications.ContainsKey(curDisplayKey))
return IntPtr.Zero;
int proc_name_match_cnt = 0;
int class_name_match_cnt = 0;
int class_name_mismatch_cnt = 0;
foreach(var h in monitorApplications[curDisplayKey].Keys)
{
foreach (var dm in monitorApplications[curDisplayKey][h])
{
if (IsMinimized(hwnd) != dm.IsMinimized)
continue;
if (User32.IsWindowVisible(hwnd) == dm.IsInvisible)
continue;
if (dm.ProcessName == procName)
{
proc_name_match_cnt++;
if (dm.ClassName == className)
class_name_match_cnt++;
else
class_name_mismatch_cnt++;
}
break;
}
}
//force match last killed pos if hwnd is the first live window of the app
if (proc_name_match_cnt == 0)
return last_killed_hid;
//force match most closest pos if hwnd is the first sub window of the app
if (proc_name_match_cnt == 1 && class_name_match_cnt == 0)
return similar_pos_hid;
//force match if hwnd-like window has multiple instantiations but has only one top-level matching candidate
if (similar_pos_cnt == 1 && class_name_match_cnt > 0)
return similar_pos_hid;
if (class_name_match_cnt > 0 && class_name_mismatch_cnt == 0)
return last_killed_hid;
if (dflt_kid != IntPtr.Zero)
return dflt_kid;
}
return IntPtr.Zero;
@ -1785,7 +1686,6 @@ namespace PersistentWindows.Common
//restore fullscreen window only applies if screen resolution has changed since minimize/normalize
if (prevDisplayMetrics.CaptureTime < lastDisplayChangeTime)
lock(restoringFullScreenWindow)
RestoreFullScreenWindow(hwnd, target_rect);
return;
}
@ -1932,13 +1832,6 @@ namespace PersistentWindows.Common
if (!initialized)
return;
if (hwnd == IntPtr.Zero)
return;
if (idObject != 0)
// ignore non-window object (caret etc)
return;
{
switch (eventType)
{
@ -1960,6 +1853,12 @@ namespace PersistentWindows.Common
if (eventType == User32Events.EVENT_OBJECT_DESTROY)
{
if (idObject != 0)
{
// ignore non-window object (caret etc)
return;
}
noRestoreWindows.Remove(hwnd);
debugWindows.Remove(hwnd);
if (fullScreenGamingWindows.Contains(hwnd))
@ -1989,9 +1888,7 @@ namespace PersistentWindows.Common
}
// for matching new window with killed one
var dm = monitorApplications[display_config][hwnd].Last();
if (dm.SnapShotFlags == 0)
dm.CaptureTime = DateTime.Now; //for inheritence in LIFO stile
monitorApplications[display_config][hwnd].Last().ProcessName = windowProcessName[hwnd];
deadApps[display_config][hwnd] = monitorApplications[display_config][hwnd];
@ -2047,9 +1944,6 @@ namespace PersistentWindows.Common
return;
}
if (!CaptureProcessName(hwnd))
return;
if (ignoreProcess.Count > 0)
{
string processName = windowProcessName[hwnd];
@ -2057,6 +1951,9 @@ namespace PersistentWindows.Common
return;
}
if (!CaptureProcessName(hwnd))
return;
#if DEBUG
if (title.Contains("Microsoft Visual Studio")
&& (eventType == User32Events.EVENT_OBJECT_LOCATIONCHANGE
@ -2118,7 +2015,7 @@ namespace PersistentWindows.Common
if (eventType == User32Events.EVENT_OBJECT_LOCATIONCHANGE)
{
if (((remoteSession && !restoreSingleWindow) || restoreTimes >= MinRestoreTimes) && !restoringSnapshot)
if ((remoteSession || restoreTimes >= MinRestoreTimes) && !restoringSnapshot)
{
// restore is not finished as long as window location keeps changing
CancelRestoreFinishedTimer();
@ -2132,14 +2029,22 @@ namespace PersistentWindows.Common
{
case User32Events.EVENT_OBJECT_CREATE:
{
if (idObject != 0)
// ignore non-window object (caret etc)
return;
if (restoringFromDB)
return;
if (freezeCapture || !monitorApplications.ContainsKey(curDisplayKey))
return;
userMove = true;
StartCaptureTimer(UserMoveLatency / 4);
//try to inherit from killed window database
if (FindMatchingKilledWindow(hwnd) != IntPtr.Zero)
{
userMove = true;
StartCaptureTimer(UserMoveLatency / 2);
}
}
break;
@ -2194,9 +2099,6 @@ namespace PersistentWindows.Common
if (fullScreenGamingWindow != IntPtr.Zero)
return;
if (User32.IsZoomed(hwnd))
userMove = true;
if (foreGroundWindow == hwnd)
{
StartCaptureTimer(UserMoveLatency);
@ -2211,12 +2113,6 @@ namespace PersistentWindows.Common
break;
case User32Events.EVENT_SYSTEM_MOVESIZESTART:
if (freezeCapture)
{
Log.Event($"recognize {curDisplayKey} as user session");
freezeCapture = false; //unlock unknown display session as normal
}
if ((User32.GetKeyState(0x11) & 0x8000) != 0 //ctrl key pressed
&& (User32.GetKeyState(0x10) & 0x8000) != 0) //shift key pressed
{
@ -2230,12 +2126,6 @@ namespace PersistentWindows.Common
lastUnminimizeWindow = hwnd;
tidyTabWindows.Remove(hwnd); //no longer hidden by tidytab
if (freezeCapture)
{
Log.Event($"recognize {curDisplayKey} as user session");
freezeCapture = false; //unlock unknown display session as normal
}
if (monitorApplications.ContainsKey(curDisplayKey) && monitorApplications[curDisplayKey].ContainsKey(hwnd))
{
//treat unminimized window as foreground
@ -2264,14 +2154,6 @@ namespace PersistentWindows.Common
if (enableMinimizeToTray)
MinimizeToTray.Create(hwnd);
/*
if (freezeCapture)
{
Log.Event($"recognize {curDisplayKey} as user session");
freezeCapture = false; //unlock unknown display session as normal
}
*/
goto case User32Events.EVENT_SYSTEM_MOVESIZEEND;
case User32Events.EVENT_SYSTEM_MOVESIZEEND:
if (eventType == User32Events.EVENT_SYSTEM_MOVESIZEEND)
@ -2305,37 +2187,15 @@ namespace PersistentWindows.Common
private void TrimQueue(string displayKey, IntPtr hwnd)
{
if (monitorApplications[displayKey][hwnd].Count > MaxHistoryQueueLength)
{
// limit length of snapshot capture history
ulong acc_flags = 0;
for (int i = monitorApplications[displayKey][hwnd].Count - 1; i >= 0; --i)
{
ulong snapshot_flags = monitorApplications[displayKey][hwnd][i].SnapShotFlags;
if (snapshot_flags != 0)
{
if ((snapshot_flags | acc_flags) == acc_flags)
{
Log.Event($"trim redundant snapshot record for {windowTitle[hwnd]}");
monitorApplications[displayKey][hwnd].RemoveAt(i);
}
acc_flags |= snapshot_flags;
}
}
}
while (monitorApplications[displayKey][hwnd].Count > MaxHistoryQueueLength)
{
// limit length of non-snapshot capture history
// limit length of capture history
for (int i = 0; i < monitorApplications[displayKey][hwnd].Count; ++i)
{
ulong snapshot_flags = monitorApplications[displayKey][hwnd][i].SnapShotFlags;
if (snapshot_flags != 0)
continue;
Log.Trace($"trim regular record for {windowTitle[hwnd]}");
if (monitorApplications[displayKey][hwnd][i].SnapShotFlags != 0)
continue; //preserve snapshot record
monitorApplications[displayKey][hwnd].RemoveAt(i);
break; //remove one record in each iteration
break; //remove one record at one time
}
}
}
@ -2615,7 +2475,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)
public void SwitchForeBackground(IntPtr hwnd, bool strict_dps_check = true, bool toForeground=false, bool updateBackgroundPos=false, bool secondBackGround = false)
{
if (hwnd == IntPtr.Zero || IsTaskBar(hwnd))
return;
@ -2640,6 +2500,8 @@ 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];
@ -2648,16 +2510,8 @@ 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)
if (prevZwnd != front_hwnd && (prevZwnd == IntPtr.Zero || prevZwnd != firstBackgroundWindow))
{
if (toForeground)
{
@ -2666,6 +2520,12 @@ 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
@ -2741,37 +2601,14 @@ namespace PersistentWindows.Common
ApplicationDisplayMetrics prevDisplayMetrics;
if (IsWindowMoved(displayKey, hWnd, eventType, now, out curDisplayMetrics, out prevDisplayMetrics))
{
bool new_window = !monitorApplications[displayKey].ContainsKey(hWnd);
if (eventType != 0 || new_window)
curDisplayMetrics.IsValid = true;
if (new_window)
{
//if (windowProcessName[hWnd] == "mstsc" && curDisplayMetrics.IsMinimized && curDisplayMetrics.IsInvisible && !curDisplayMetrics.IsFullScreen)
if (curDisplayMetrics.IsMinimized && curDisplayMetrics.IsInvisible && !curDisplayMetrics.IsFullScreen)
return false; //postpone capture till window is visible
IntPtr kid = FindMatchingKilledWindow(hWnd);
TryInheritWindow(hWnd, curDisplayMetrics.HWnd, kid, curDisplayMetrics);
if (kid == IntPtr.Zero)
monitorApplications[displayKey].Add(hWnd, new List<ApplicationDisplayMetrics>());
}
else
{
TrimQueue(displayKey, hWnd);
}
if (debugWindows.Contains(hWnd))
{
string log = string.Format("Captured {0} '{1}' fullscreen:{2} minimized:{3} visible:{4} at {5} {6, -8}",
curDisplayMetrics.HWnd.ToString("X"),
string log = string.Format("Captured {0,-8} at {1} '{2}' fullscreen:{3} minimized:{4}",
curDisplayMetrics,
curDisplayMetrics.ScreenPosition.ToString(),
curDisplayMetrics.Title,
curDisplayMetrics.IsFullScreen,
curDisplayMetrics.IsMinimized,
!curDisplayMetrics.IsInvisible,
curDisplayMetrics.ScreenPosition.ToString(),
curDisplayMetrics
curDisplayMetrics.IsMinimized
);
Log.Event(log);
@ -2780,6 +2617,19 @@ namespace PersistentWindows.Common
Log.Event(log2);
}
bool new_window = !monitorApplications[displayKey].ContainsKey(hWnd);
if (eventType != 0 || new_window)
curDisplayMetrics.IsValid = true;
if (new_window)
{
monitorApplications[displayKey].Add(hWnd, new List<ApplicationDisplayMetrics>());
}
else
{
TrimQueue(displayKey, hWnd);
}
monitorApplications[displayKey][hWnd].Add(curDisplayMetrics);
ret = true;
}
@ -3194,46 +3044,6 @@ namespace PersistentWindows.Common
return true;
}
private bool TryInheritWindow(IntPtr hwnd, IntPtr realHwnd, IntPtr kid, ApplicationDisplayMetrics curDisplayMetrics)
{
if (kid == IntPtr.Zero)
{
ResolveWindowHandleCollision(hwnd);
}
else
{
var prevDisplayMetrics = InheritKilledWindow(hwnd, realHwnd, kid);
if (hwnd != kid)
{
if (prevDisplayMetrics.Title != curDisplayMetrics.Title)
Log.Error($"{hwnd.ToString("X")} Inherit position data from killed window {prevDisplayMetrics.Title} with different title {curDisplayMetrics.Title} {prevDisplayMetrics.HWnd.ToString("X")}");
else
Log.Error($"{hwnd.ToString("X")} Inherit position data from killed window {prevDisplayMetrics.Title} {prevDisplayMetrics.HWnd.ToString("X")}");
ResolveWindowHandleCollision(hwnd);
}
else
Log.Error($"{hwnd.ToString("X")} Inherit position data from existing window 0x{kid.ToString("X")} for {curDisplayMetrics.Title}");
if (initialized && autoRestoreNewWindowToLastCapture)
{
if (!restoringFromDB && IsResizableWindow(hwnd))
{
Log.Trace($"restore {windowTitle[hwnd]} to last captured position");
restoreSingleWindow = true;
restoringFromMem = true;
RestoreApplicationsOnCurrentDisplays(curDisplayKey, hwnd, prevDisplayMetrics.CaptureTime);
restoreSingleWindow = false;
restoringFromMem = false;
userMove = true;
StartCaptureTimer(UserMoveLatency / 2);
}
}
return true;
}
return false;
}
private bool IsWindowMoved(string displayKey, IntPtr hwnd, User32Events eventType, DateTime time,
out ApplicationDisplayMetrics curDisplayMetrics, out ApplicationDisplayMetrics prevDisplayMetrics)
{
@ -3313,9 +3123,6 @@ namespace PersistentWindows.Common
NeedUpdateWindowPlacement = false,
ScreenPosition = screenPosition,
Style = User32.GetWindowLong(hwnd, User32.GWL_STYLE),
ExtStyle = User32.GetWindowLong(hwnd, User32.GWL_EXSTYLE),
IsTopMost = IsWindowTopMost(hwnd),
NeedClearTopMost = false,
@ -3332,6 +3139,27 @@ namespace PersistentWindows.Common
if (noRestoreWindows.Contains(hwnd))
return false;
IntPtr kid = FindMatchingKilledWindow(hwnd);
bool restore_last = false;
if (kid == IntPtr.Zero)
{
ResolveWindowHandleCollision(hwnd);
}
else
{
prevDisplayMetrics = InheritKilledWindow(hwnd, realHwnd, kid);
if (hwnd != kid)
{
Log.Error($"Inherit position data from killed window 0x{kid.ToString("X")} for {curDisplayMetrics.Title}");
ResolveWindowHandleCollision(hwnd);
}
else
Log.Error($"Inherit position data from existing window 0x{kid.ToString("X")} for {curDisplayMetrics.Title}");
if (initialized && autoRestoreNewWindowToLastCapture)
restore_last = true;
}
//newly created window or new display setting
curDisplayMetrics.WindowId = (uint)realHwnd;
@ -3353,7 +3181,18 @@ namespace PersistentWindows.Common
if (curDisplayMetrics.IsMinimized && prevDisplayMetrics != null && prevDisplayMetrics.IsMinimized)
moved = false;
else
{
moved = true;
if (restore_last && prevDisplayMetrics != null && !restoringFromDB && IsResizableWindow(hwnd))
{
Log.Trace($"restore {windowTitle[hwnd]} to last captured position");
restoringFromMem = true;
RestoreApplicationsOnCurrentDisplays(curDisplayKey, hwnd, prevDisplayMetrics.CaptureTime);
restoringFromMem = false;
return false;
}
}
}
else if (!monitorApplications[displayKey].ContainsKey(hwnd))
{
@ -3668,6 +3507,11 @@ namespace PersistentWindows.Common
*/
}
if (restoringFullScreenWindow)
return;
restoringFullScreenWindow = true;
bool wrong_screen = false;
RECT cur_rect = new RECT();
User32.GetWindowRect(hwnd, ref cur_rect);
@ -3700,9 +3544,10 @@ namespace PersistentWindows.Common
0, 0, 0, UIntPtr.Zero);
Log.Error("restore full screen window {0}", GetWindowTitle(hwnd));
/*
Thread.Sleep(3 * double_clck_interval);
restoringFullScreenWindow = false;
style = User32.GetWindowLong(hwnd, User32.GWL_STYLE);
if ((style & (long)WindowStyleFlags.CAPTION) == 0L)
{
@ -3725,7 +3570,6 @@ namespace PersistentWindows.Common
}
Log.Error("fail to restore full screen window {0}", GetWindowTitle(hwnd));
*/
}
private void RestoreSnapWindow(IntPtr hwnd, RECT target_pos)
@ -4474,7 +4318,6 @@ namespace PersistentWindows.Common
if (restore_fullscreen)
{
if (restoreTimes > 0 && sWindow == null) //#246, let other windows restore first
lock(restoringFullScreenWindow)
RestoreFullScreenWindow(hWnd, rect);
}
else if (restoreTimes >= MinRestoreTimes - 1)

View file

@ -624,9 +624,6 @@ namespace PersistentWindows.Common.WinApiBridge
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hHandle);
[DllImport("kernel32")]
public static extern UInt64 GetTickCount64();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,

View file

@ -61,11 +61,5 @@ namespace PersistentWindows.Common.WinApiBridge
{
return string.Format("({0}, {1}), {2} x {3}", Left, Top, Width, Height);
}
public int Diff(RECT r)
{
int diff = Math.Abs(Left - r.Left) + Math.Abs(Right - r.Right) + Math.Abs(Top - r.Top) + Math.Abs(Bottom - r.Bottom);
return diff / 4;
}
}
}

View file

@ -56,15 +56,6 @@ 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;
@ -83,10 +74,9 @@ if not errorlevel 1 goto wait_to_finish";
bool offscreen_fix = true;
bool fix_unminimized_window = true;
bool enhanced_offscreen_fix = false;
bool set_pos_match_threshold = false;
bool auto_restore_missing_windows = false;
bool auto_restore_from_db_at_startup = false;
bool auto_restore_last_capture_at_startup = false;
bool auto_restore_last_capture_at_startup = true;
bool launch_once_per_process_id = true;
bool check_upgrade = true;
bool auto_upgrade = false;
@ -153,12 +143,6 @@ if not errorlevel 1 goto wait_to_finish";
restore_snapshot = SnapshotCharToId(arg[0]);
continue;
}
else if (set_pos_match_threshold)
{
set_pos_match_threshold = false;
pwp.MaxDiffPos = int.Parse(arg);
continue;
}
switch(arg)
{
@ -276,15 +260,12 @@ if not errorlevel 1 goto wait_to_finish";
case "-redraw_desktop":
redraw_desktop = true;
break;
case "-auto_restore_existing_window_to_last_capture=1":
auto_restore_last_capture_at_startup = true;
case "-auto_restore_existing_window_to_last_capture=0":
auto_restore_last_capture_at_startup = false;
break;
case "-auto_restore_new_window_to_last_capture=0":
pwp.autoRestoreNewWindowToLastCapture = false;
break;
case "-pos_match_threshold":
set_pos_match_threshold = true;
break;
case "-auto_restore_missing_windows":
case "-auto_restore_missing_windows=1":
auto_restore_missing_windows = true;

View file

@ -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.65.*")]
[assembly: AssemblyVersion("5.61.*")]

View file

@ -252,16 +252,7 @@ namespace PersistentWindows.SystrayShell
if (!upgradeDownloaded.ContainsKey(latestVersion))
{
string url = Program.ProjectUrl + "/releases";
var os_version = Environment.OSVersion;
if (os_version.Version.Major < 10)
Process.Start(url);
else if (os_version.Version.Build < 22000)
Process.Start(url);
/* windows 11
else
Process.Start(new ProcessStartInfo(url));
*/
Process.Start(Program.ProjectUrl + "/releases");
var src_file = $"{Program.ProjectUrl}/releases/download/{latestVersion}/{System.Windows.Forms.Application.ProductName}{latestVersion}.zip";
var dst_file = $"{Program.AppdataFolder}/upgrade.zip";