Home | Blog | Software | Reviews and Features | Forum | Help | Donate | About us
topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • November 18, 2017, 07:23 PM
  • Proudly celebrating 10 years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Last post Author Topic: Desperate app request - restore window positions after wake from sleep scrambles  (Read 3702 times)

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
This thread describes a problem that quite a few people seem to be suffering from, where window positions get scrambled on multi-monitor setups when the monitors wake up from sleep:
http://www.donationc....msg407109#msg407109

It doesn't happen and I think it's some side effect of some monitors not waking up fast enough.

The app will have to do the following:
1. Periodically store the positions of all windows on screen.
2. Detect when the monitors wake up from sleep.
3. After some delay after waking up, automatically restore the window positions (including maximization state, etc.)
4. I'm guessing it will need some way of allowing user to exclude certain apps from processing (i'm guessing some apps might misbehave or have hidden windows that shouldn't be processed, etc.)

Lintalist

  • Participant
  • Joined in 2015
  • *
  • Posts: 46
    • View Profile
    • Donate to Member
Haven't tried it but here is a "AutoHotkey script that will save your window positions and then restore them to the saved position" https://github.com/KroniK907/WindowSaver

I'm assuming it has to be slightly modified to say safe window positions every X minutes - there is a wrapper for power events here https://autohotkey.c...events-like-standby/ which may proof useful if you want it fully automated. Otherwise adding a hotkey to "restore" the latest state quickly after a sleep is probably easier :)

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Nice find, Lintalist.
That looks like it's 95% of the solution.
Now if I can just get one of the ahk coders here to add the other 5% I'll be golden.  :up:

app103

  • That scary taskbar girl
  • Global Moderator
  • Joined in 2006
  • *****
  • Posts: 5,720
    • View Profile
    • Donate to Member
Now if I can just get one of the ahk coders here to add the other 5% I'll be golden.

Would this work for about 2.5%?

http://www.donationc...60.msg34720#msg34720

In other words, launching the AHK script after a set length of user idle time, but a shorter than when your monitors would go to sleep (almost like a screensaver)?

Then all you'd need is something to run it to restore, after a set length of time after user activity is detected, just slightly longer than it takes for your monitors to fully wake up.


This does what you need: http://www.donationc...60.msg34720#msg34720

Can be used to set the timeout to run the ahk script after a set length of user idle time, and then run to restore the windows after keyboard/mouse activity detected. It does both, so now you have your 100%. :)
« Last Edit: April 14, 2017, 10:18 AM by app103, Reason: found something better »

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
I'm not sure.. I think still missing is something that restores window positions only after the monitors wake up from sleep, and then after some delay..

And the procedure for saving window positions -- since it's going to be happening so frequently, it would be nice if it was all one process rather than something launching another exe every 30 seconds..

app103

  • That scary taskbar girl
  • Global Moderator
  • Joined in 2006
  • *****
  • Posts: 5,720
    • View Profile
    • Donate to Member
What causes the monitors to wake? User activity?

How long do they take to wake after keyboard/mouse activity?

Set the time to wakeup time + 5 seconds before running the restore.

That way, if you move the mouse or tap any key on the keyboard, it will then wait long enough for your monitors to wake, before running the restore.

skrommel

  • Fastest code in the west
  • Developer
  • Joined in 2005
  • ***
  • Posts: 932
    • View Profile
    • Donate to Member
 :) WinPosSaver saves the window positions every minute, and restores the layout after sleep or hibernation.

WinPosSaver.gifDesperate app request - restore window positions after wake from sleep scrambles

You can quickly test it by using Save layout and Load layout from the menu.

This is the first draft, so please report errors. I have plenty of ideas for it, like saving and loading multiple layouts, option to automatically restart the programs when loading layouts, detecting when monitors are added and removed...

26.07.2017: Added monitor sleep detection. Also logs power changes to Log.txt

Skrommel
« Last Edit: July 25, 2017, 11:55 PM by skrommel »

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Ok well first of all, I am thrilled, thrilled, thrilled to see the amazing skrommel working on this idea.. I suffer from this problem to this day, and it drives me crazy.  I would love to have a solution.
I do imagine it will take some iteration and quite a bit of experimentation to get it working flawlessly, but Im happy to test.  Downloading now.

Just a heads up, before I even use it I will report one thing -- DC Members skwire (the *other* ahk master on this forum) worked with me a bit on trying to identify the nature of the problem, and one unpleasant thing we discovered is that the windows displaychange messages that are broadcast whenever resolution/monitor changes happen, would occasionally FAIL TO REPORT a change, at least on my machine.  This means that any solution to this problem cannot rely on those messages being 100% accurate.

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
ps. I would love the ahk code so I can help tweak and experiment!

skrommel

  • Fastest code in the west
  • Developer
  • Joined in 2005
  • ***
  • Posts: 932
    • View Profile
    • Donate to Member
Uploaded the sourcecode. So your displays disconnect when they go to sleep, and not when the PC sleeps? That could possibly be detected in the program by watching the mouse and keyboard inactivity?

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Let me get skwire to upload the tool he wrote for me to WM_DISPLAYCHANGE events and log monitor positions, it's what we used to try to figure out what was going on..

Let me try to describe my setup:

I have 4 monitors.  My pc never sleeps or hibernates, but the monitors to go to sleep and turn off after about 30 minutes.  So when I wake up after 8 hours, and first come to the pc, that is when windows move all over the place.  Presumably because one or more of the monitors does not wake up in time.

Importantly: The movement of windows seems NOT to happen when the monitors first go to sleep.. it happens only at the time of waking up(!)
It seems at wake up time is when windows gets confused.

Here is what we saw one day when looking at the WM_DISPLAYCHANGE events:

The situation after a few hours of sleep:

Code: Text [Select]
  1. Hourly check...
  2. 2017-05-10 09:52:44 AM ------------------------------
  3.  
  4. Monitor Count:  4
  5. Primary Monitor:        1
  6.  
  7. Monitor:        #1
  8. Name:   \\.\DISPLAY1
  9. Res:    2560 x 1440
  10. Left:   0 (0 working)
  11. Top:    0 (0 working)
  12. Right:  2560 (2560 working)
  13. Bottom: 1440 (1410 working)
  14.  
  15. Monitor:        #2
  16. Name:   \\.\DISPLAY5
  17. Res:    2560 x 1440
  18. Left:   2560 (2560 working)
  19. Top:    0 (0 working)
  20. Right:  5120 (5120 working)
  21. Bottom: 1440 (1410 working)
  22.  
  23. Monitor:        #3
  24. Name:   \\.\DISPLAY6
  25. Res:    1440 x 2560
  26. Left:   -1440 (-1440 working)
  27. Top:    -601 (-601 working)
  28. Right:  0 (0 working)
  29. Bottom: 1959 (1929 working)
  30.  
  31. Monitor:        #4
  32. Name:   \\.\DISPLAY2
  33. Res:    1920 x 1080
  34. Left:   -3360 (-3360 working)
  35. Top:    180 (180 working)
  36. Right:  -1440 (-1440 working)
  37. Bottom: 1260 (1260 working)

Everything is fine at this point.. but here is what happens when i press keyboard and "wake up" the monitors:

Code: Text [Select]
  1. WM_DISPLAYCHANGE event...
  2. 2017-05-10 10:02:05 AM ------------------------------
  3.  
  4. Monitor Count:  3
  5. Primary Monitor:        1
  6.  
  7. Monitor:        #1
  8. Name:   \\.\DISPLAY1
  9. Res:    1920 x 1080
  10. Left:   0 (0 working)
  11. Top:    0 (0 working)
  12. Right:  1920 (2560 working)
  13. Bottom: 1080 (1410 working)
  14.  
  15. Monitor:        #2
  16. Name:   \\.\DISPLAY5
  17. Res:    2560 x 1440
  18. Left:   2560 (2560 working)
  19. Top:    0 (0 working)
  20. Right:  5120 (5120 working)
  21. Bottom: 1440 (1410 working)
  22.  
  23. Monitor:        #3
  24. Name:   \\.\DISPLAY6
  25. Res:    1440 x 2560
  26. Left:   -1440 (-1440 working)
  27. Top:    -601 (-601 working)
  28. Right:  0 (0 working)
  29. Bottom: 1959 (1929 working)


Note that it has actually "lost" one of my monitors at this point.. And even more frustrating, another WM_DISPLAYCHANGE event is *NOT* sent when it eventually sees it a few seconds later..



SO I am guessing that the procedure will have to look something like this:

1. Save windows positions occasionally.
2. When a WM_DISPLAYCHANGE event occurs, do NOT assume it is a correct thing.. Instead, use it to start a timer, which will RECHECK monitor situation after a few seconds.
3. After the delay has passed and the monitors come back, get current real monitor locations and restore any windows locations that have changed.



So I can think of a few ways a program could work that would make me happy, perhaps the simplest would be something like this:
a) let me tell the program when my monitors are in there "normal" configuration (ie just select a menu operation).
b) when the monitors are in this state, the program can save windows locations periodically -- or in fact since we know that the OS doesn't actually have any problem while the monitors are asleep, you could simply save window positions ONCE, when the monitors fall asleep]
c) when you get a WM_DISPLAYCHANGE message, set a timer that has you check monitor configurations occasionally, and WAIT UNTIL THE "GOOD" (normal) monitor configuration comes back
d) that is when the windows should be restored.

Step C is the key part -- you are essentially detecting a WM_DISPLAYCHANGE message as a "signal" that the monitors are in an UNSTABLE state that is likely to bounce around for the next few seconds, and cannot be trusted.  This is where MS Windows messes up windows positions.  So then the key is to just WAIT until the monitors come back to their "normal" configuration (and don't assume you will get a WM_DISPLAYCHANGE message when they do, you just have to wait a few seconds and/or check their state).  Then when the monitors are back to "normal" the window positions can be restored.

Does that make sense?

skrommel

  • Fastest code in the west
  • Developer
  • Joined in 2005
  • ***
  • Posts: 932
    • View Profile
    • Donate to Member
Try the latest version. I added monitor sleep detection, and logs power events to log.txt.

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Ideally once the basic operations were working, one could experiment with ways to reduce unneeded operations and cpu usage..  That is, it would be nice if one could find ways to only have to save window positions once right before the problem (which might be possible if one could get a signal that happened when monitors fall asleep, or only once after the computer has been idle for at least monitor-sleep-time, say 30 minutes), so that window positions would not have to be saved frequently during normal pc use.

And another tweak would be to eventually not use my suggestion of the user specifying when the monitors are in the the "normal" configuration, perhaps by this same mechanism -- by assuming that when you do your one-time save of window positions after some long idle time (or after monitor sleep time), then THAT is the normal configuration, and updating what you consider the normal configuration when the monitors fall asleep...

Again both ideas are based on my observation that the problem happens at the time that the monitors WAKE UP from being asleep -- not when they fall asleep.

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
And needless to say, your application would have other uses besides saving my sanity -- i'm sure there are people that would like to be able to save and restore window positions manually to help them with different tasks.  But let's leave those people for later -- I am the one in need of saving at the moment :)

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Quote
Try the latest version. I added monitor sleep detection, and logs power events to log.txt.

Will do.

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Just a quick first report:

Miraculously, using WinPosSaver to save window positions, and then moving them, changing min/max states  around, and then using WinPosSaver to restore them.. Worked flawlessly.  :huh:

I did not expect that at all.. I expected lots of problems with different windows not restoring their maximized state, and other oddities..

So yeah, great success so far..  Now it's a matter of getting it to automatically save before the monitor problem, and automatically restore after.

skrommel

  • Fastest code in the west
  • Developer
  • Joined in 2005
  • ***
  • Posts: 932
    • View Profile
    • Donate to Member
Have you checked the log.txt? Does all power events register?

If not, I can make a pure "wait for keypress/mousemove after idle for 30 minutes", and just watch the number of monitors connected.

There's a two second time gap to save things before the system shuts down, so it should be possible, but some part of the code can't get it's information during this time, and crashes.

By just saving the hWnds after x minutes of idle and restoring them when there's activity + a delay, it should work.

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Ok so here are the results from waking up this morning:

The log does seem to have triggered an event when the monitors woke up:
20170726070222 - PBT_POWERSETTINGCHANGE - Monitor: Off <-- in the middle of the night
20170726111030 - PBT_POWERSETTINGCHANGE - Monitor: On <-- last event and when the monitors woke up

Observed behavior was as follows: When the monitors woke up this morning, window positions got moved around as they normally do.. WinPosSaver did not seem to do anything.



One thing I need some clarification on is as follows:
When I first tried WinPosSaver, I was testing the manual save and load functions.. But I see now that it's saving window positions to file on a timer.. So I guess I really should not expect to be able to save and load manually and have that work..  Perhaps for testing purposes it would be nice if the MANUAL save and load functions used a separate data file from the automatic system.  That would make it easier to test issues..



I'm ready to test the next version when you are ready..

ps. Manually putting the monitors into sleep mode does not seem to be a viable way of testing this issue, because if I manually send them to sleep (via nircmd for example), they wake up fine.  It's only after they've really been off for a couple of hours that they exhibit this wake problem..

skrommel

  • Fastest code in the west
  • Developer
  • Joined in 2005
  • ***
  • Posts: 932
    • View Profile
    • Donate to Member
So it detects the monitor off and on correctly? Maybe a delay before moving the windows around is needed? Or wait for all the monitors to reattach?

skrommel

  • Fastest code in the west
  • Developer
  • Joined in 2005
  • ***
  • Posts: 932
    • View Profile
    • Donate to Member
 :) IdleWinPosSaver is a much simpler solution. Change the idle= line to your monitor idle time. After idling, it waits for a key or mouse action, then it waits for all monitors to reattach, and then it moves the windows.

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Quote
So it detects the monitor off and on correctly?
Yes it seems so..

Quote
Maybe a delay before moving the windows around is needed?
I think so.  The fact that nothing "seemed" to have happened after the monitor woke up makes me think that the script saved the "bad" positions.. possibly it tried to restore positions before the monitors were fully woken up and then the OS moved them around, and then the script memorized the bad positions..



I'm also thinking that if it reliably detects monitor  OFF and ON conditions, it might be possible to autosave positions ONLY at monitor OFF signal.

Let me experiment with your code and add some logging and see what I can see..

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Just saw IdleWinPosSaver.ahk, let me download and look at that too.

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Skrommel, here is my quickly hacked modification of WinPosSaver.
It does a lot more logging, and it does what i suggested above -- it only saves automatically when monitor turns off, and then restores after a delay once when monitor turns on.

Now, it seems to trigger the save and load correctly, but there is a problem:

I earlier reported that the manual save and load tests worked for me, but I see now that is not quite 100% true.  It seems that some windows are not restoring properly.

The most easily reproducible problem is that when i save a layout with a MAXIMIZED window, and then unmaximize and move the window from one monitor to another, when the layout is loaded, it does NOT move the window back to its saved monitor -- instead it maximizes it on the current monitor.

IN FACT, I believe this is a clue to what is going wrong with the Operating system monitor on/off screwup where windows get moved around.

I think the solution is that if a window is not maximimzed and it is being restored back to a maximized state, it needs to FIRST be moved unmaximized to the old monitor location, and only THEN maximized.. Just an idea..



Another clue and strangeness is that the OS keeps a separate record of the unmaximized position and size of a window, separately from the location of the maximized window, and it can be that when the weird moving of windows occurs during wake, that these locations are actually on DIFFERENT monitors(!).  This is something that is not normally possible when you are moving the windows as a user, but you can see it has happened because when you unmaxmize a window that this has happened to, the un-maximized version of the window jumps to another monitor(!). 

I know this may be confusing to follow..  Bottom line is that the save and restore is somehow not restoring the window state perfectly -- something about the maximized window location is not being restored correctly.


[OLD FILE REMOVED SEE SUBSEQUENT POST]
« Last Edit: July 26, 2017, 06:25 PM by mouser »

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
I'm experimenting now with ideas..

mouser

  • First Author
  • Administrator
  • Joined in 2005
  • *****
  • Posts: 37,597
    • View Profile
    • Donate to Member
Ok so following up all everything I wrote, I am having some luck getting the save-load cycle to work even with OS crazy window moving, by explicitly UNMAXIMIZING every maximized window before restoring it.. This creates some god-awfully flying of windows what the state is restored, but it seems to be working.. Now to see if there is a way around explicitly doing that..