PDA

View Full Version : [AutoHotKey] Swapping Between World of Warcraft Windows in Windows 10



Eskimz
04-26-2018, 03:50 AM
Hi guys,

I know this website doesn't tend to have many Autohotkey users but I like the program and I was wondering if someone could help me figure this out. So AHK has 2 commands called WinActivateBottom and WinActivate. There's also has another called WinSet.

https://autohotkey.com/docs/commands/WinActivateBottom.htm
https://autohotkey.com/docs/commands/WinSet.htm

Basically, I have all the functionality working as intended when it comes to broadcasting keys to multiple clients. My issue is trying to get Windows 10 to swap between my 2 clients instantly.

In my World of Warcraft clients I'm using the interface settings to set a foreground and background FPS limit. The background FPS limit is obviously much lower. Also I have both set to fullscreen-windowed mode.

When I swap clients using WinActivateBottom, it does swap the client to the foreground, but there is a delay when it comes to altering the FPS back to the 60fps foreground setting. It's like the Window is being pushed to the foreground but not being focused for a few sec. If I click with my mouse it has a brief lag spike but quickly regains its correct FPS.
When I use:


WinSet, Bottom, ,A

Instead, it works instantly and I can left or right click to instantly re-focus the new window and get correct FPS. I'm wondering why this is. Does anyone have any insight on this? Basically I'm just trying to mimic the windows 10 Alt-Tab functionality but only with my 2 wow windows.

Any insight would be greatly appreciated. Tx.

- Eskimz

mbox_bob
04-26-2018, 05:28 AM
https://autohotkey.com/docs/commands/SetWinDelay.htm

MiRai
04-26-2018, 02:01 PM
It sounds like the typical lag you'd see when a game client has to re-size itself. Unless AHK has some special way to force a render size, similar to what ISBoxer can do, then the game client is going to need to change its resolution every time you swap windows around.

At least, this is what I'm assuming.

mbox_bob
04-26-2018, 04:25 PM
I considered that myself, but assuming "fullscreen-windowed mode" on both clients means they are stacked, rather than one big and one small, forcing a resolution change/reset, then the delay is more likely to be the default 100ms that any of the AHK WinActivate methods pushes in, unless you override it with SetWinDelay. In fact, Set Win Delay calls it out.


[Sets the delay that will occur after each windowing command, such as WinActivate (https://autohotkey.com/docs/commands/WinActivate.htm).

Time in milliseconds, which can be an expression (https://autohotkey.com/docs/Variables.htm#Expressions). Use -1 for no delay at all and 0 for the smallest possible delay. If unset, the default delay is 100.

The reason is doesn't have that delay with "WinSet, Bottom, A", is because the active window you are acting on, is the one you push to the bottom of the stack, so the window that then appears on the top, which is now active, never has the WinActivate routines executed, thus has no default delay.


Mind you, is was mentioned as a "few seconds" lag, so could entirely be a resolution reset. Not enough info was really provided on that front to make a determination as to what is happening.

Eskimz
04-26-2018, 05:19 PM
Hmm, thx for the replies guys ..

Well here's the thing mbox_bob, I already tried that. I tried setting SetWindowDelay to -1 as well as 0 (Unless I was using it wrong), it didn't seem to make any difference. And it says by default the delay is 100. When swapping windows with WinActivateBottom or WinActivate the delay is more than 100 for sure ... its like a full 2 sec before the window seems to speed up to the correct FPS.

Visually, the window swap is pretty much instant with either option, its just the FPS stutter that occurs when I use WinActivate vs forcing the active window to the bottom stack, in which no stutter occurs but I have to "focus" the new top window manually by clicking with the mouse.

I also tried using #WinActivateForce and it didn't seem to do anything either:
https://autohotkey.com/docs/commands/_WinActivateForce.htm


!Tab::
WinSet, Bottom, ,A
Click, RightClick
return


That's an example of what seems to be working instead of this:


!Tab::
#WinActivateForce
SetWinDelay, -1
WinActivateBottom, World of Warcraft
return


Also MiRai I don't think there is a resolution reset. That was the intention of using Fullscreen Windowed mode vs say ... Fullscreen. When I use fullscreen there is no FPS stutter but there is definately a delay that I can visually see while it minimizes one window to Fullscreen the other. It's probably less than 1 second but it's definately there. When I use the pushing the active window to the bottom stack method it's literally an instant swap, it's just the FPS readjustment stutter. I can press alt-Tab and then instantly click and it's done.

The problem with using the WinSet Bottom method is that the right click physically clicks inside the new window frame. Thus if there is a target or something clickable underneath the cursor it will "target it" ya know? I don't want that.

Any other ideas? Thanks again for the insight guys.

MiRai
04-26-2018, 05:36 PM
I considered that myself, but assuming "fullscreen-windowed mode" on both clients means they are stacked, rather than one big and one small, forcing a resolution change/reset
That's a great reason why it wouldn't be what I suggested. https://www.dual-boxing.com/images/icons/icon14.png

mbox_bob
04-26-2018, 07:15 PM
Looking at the source code, there are a bunch of things in the WinActivate that could potentially delay things, and that's not even looking higher up the chain where the default delay stuff is handled. A debug output would be handy, but that in itself would cause delays, which could then change the behaviour.

This is not really a dual-boxing type problem as it stands, and is more a AutoHotKey question, which should probably be queried with them as it would require much more digging into HOW AHK is bringing a Window to the foreground. Win8/Win10 are designed to prevent other windows from focus stealing, so AHK is doing things to get around that and that may be impacting it.

Eskimz
04-26-2018, 07:54 PM
Hmm ... okay well thanks for the input guys. I guess I'm gonna have to look into it more and mess around with some things. Yeah I've tried asking in the AHK forums before ... didn't have much luck in the past. Anyways ... appreciate the responses, thx again.

mbox_bob
04-26-2018, 08:41 PM
Ok, so if you send the A window to the bottom, then the top most window is not currently the focus, so maybe send a WinActivate to that window. Probably means you'd need to track the stack positions yourself so you knew what order the windows should be in, as I can't spot a GetTop or anything useful like that (less of a problem with 2, more a problem with 3+).

If you were attempting to get around the Click Rightclick thing which might target something, does a Keypress work for the focus? A good keypress to send would be F1 (usually set to Target Self in default setup). This may not work at all as the WinSet may not be changing the focus input. If you do need the mouse, then I'd be inclined to save the current mouse position, do some math and get it to leftclick the mouse on the titlebar/border of the window where it is not likely to have any impact, and then put the cursor back where it was.

Another option might be to wrap the WinActivate with some keydown/ups. A bit of a read through the comments in the code suggest if you did a KeyDown ALT, followed by your WinActivate, then a KeyUp ALT, it might all work out (because hitting the ALT key in Windows does some behind the scenes stuff getting it prepped for window swapping!)

Eskimz
04-27-2018, 01:40 AM
These are all good ideas.

The alt thing is was an interesting consideration. I just tried sandwiching WinActivateBottom between Send {Alt Down} and Send {Alt Up}. Didn't seem to have any affect.

I think what's happening is .. Like you said, just sending the active window to the bottom isn't enough because the desktop then becomes the topmost window? Which Is why I am able to click the WoW frame that Was at the bottom to instantly focus it.

The clicking on the titlebar/ border thing sounds like a good idea as a last resort.

You can push the Active Window to the top using
WinSet, Top,, A

or


Winset, Top,, <Window Name>

The problem with this is obviously the WoW windows have the same name ... So when I push one to the bottom ... I don't know how to target the window that was, at the bottom right ... ? Ya know? Maybe I can push both the desktop and the top WoW window to the bottom? but I don't know how to do that either > . <

But yea I'll keep trying to figure something out based on what you said, thanks mbox_bob

mbox_bob
04-27-2018, 02:17 AM
The problem with this is obviously the WoW windows have the same name

Only if you haven't used https://autohotkey.com/docs/commands/WinSetTitle.htm when you start up to give each window a unique name..........

Eskimz
04-27-2018, 03:46 AM
Yea you're right I actually do have a section in the script where it grabs the 2 instances of WoW and assigns 1 as the main and one as the clone:

I'm just gonna post my script so you can see what I'm working with:



; For Dual-Boxing World of Warcraft
; by Rests (aka Eskimz)

;--------------------------------------------------------------------------------


; // Tell user what is about to happen upon start-up //
SplashTextOn, 250, , Preparing to find your Main and Clone windows of WoW.
Sleep, 250
SplashTextOff


; // Grab unique window IDs //
WinGet, wowid, List, World of Warcraft




; // Minimize All WoW windows //
WinMinimize, ahk_id %wowid1%
WinMinimize, ahk_id %wowid2%




; // Determine Main and Clone Windows //
WinActivate, ahk_id %wowid1%
MsgBox, 4, , Is this your WoW Main window? (press Yes or No)
IfMsgBox Yes
idMain = %wowid1%
else
idMain = %wowid2%


If idMain = %wowid1%
{
idClone = %wowid2%
}
else
{
idClone = %wowid1%
}


; // Activate All WoW windows //
WinActivate, ahk_id %idClone%
WinActivate, ahk_id %idMain%




;--------------------------------------------------------------------------------


; // Defines the ClonesPush function //
ClonesPush(strKeys)
{
global idMain
global idClone
IfWinNotActive, ahk_id %idMain%
ControlSend, , %strKeys%, ahk_id %idMain%
IfWinNotActive, ahk_id %idClone%
ControlSend, , %strKeys%, ahk_id %idClone%
}




; // Defines the ClonesClick function //
ClonesClick(strKeys)
{
global idMain
global idClone
IfWinNotActive, ahk_id %idMain%
ControlClick, , ahk_id %idMain%, , %strKeys%, NA
IfWinNotActive, ahk_id %idClone%
ControlClick, , ahk_id %idClone%, , %strKeys%, NA
}




;--------------------------------------------------------------------------------


; // Hotkeys //


*^l::Suspend ; // Ctrl + L Suspends AHK
~!Tab::
WinSet, Bottom, , A
return




; // WoW Hotkeys //


~RButton Up::ClonesPush("=") ; // RClick Up Interact w/ Target


~^WheelUp::ClonesPush("-") ; // Ctrl + Wheel Up Interact w/ Target


~r Up::ClonesPush("r") ; // r
~r::ClonesPush("=") ; // r


~+g::ClonesPush("{Shift Down}g{Shift Up}") ; // Shift + g (Follow)


~Space::ClonesPush("{Space}") ; // Spacebar (Jump)

Should be easier that way so you have more information.

mbox_bob
04-27-2018, 04:48 AM
I actually know very little about AHK, just what I read on the site, and a quick squizz at the source.

A quick look shows me that I'd be inclined to create an Object (https://autohotkey.com/docs/objects/Object.htm) and use that to store the game window ids as I found them, along with renaming window titles (and storing that too), and then use them in the Tab key to determine which window I was on, push that to the bottom, and then activate the next one in my list (if I can I like to set it up for expansion to more than 2).

I've not tried this, and having a quick read of the needed commands, it's not as trivial as I'd like to do this in the AHK script, but it should be relatively easy to create a couple of functions to be rather helpful to the whole process.