Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Window loses Focus when switching Virtual Desktops #37

Open
arakis opened this issue Apr 21, 2023 · 6 comments
Open

Window loses Focus when switching Virtual Desktops #37

arakis opened this issue Apr 21, 2023 · 6 comments

Comments

@arakis
Copy link

arakis commented Apr 21, 2023

Actual

When switching between two desktops, it always loses focus of the last used app of the new desktop. NO window is focused after switching.

Example: VD 1 have Notepad focused, on VD 2 the calculator. Currently i'm on VD1. When switching to VD2, NO window is focused. If i move back, NO window is focused (you see this on the task bar).

Expected

The last focused app should reminded and re-focused when switching to that desktop.

What works

When using build-in key combination CTRL+WIN+Left/Right, it works as expected.

Analysis

It happens regardles if i move away with build-in command and jump back via VD.ahk, or first jump away via VD.ahk and switches back with build-in command.

Background information

  • AHK 2.0.2
  • VD.ahk latest v2_port (5f130ff), but also happens on commit 788978e.
  • Windows 11
  • Single Display
  • Used Key Combination for jumping away and back: WIN+NumpadEnd/-Down/-PgDn
#NumpadEnd::VD.goToDesktopNum(1) ;1
#NumpadDown::VD.goToDesktopNum(2) ;2
#NumpadPgDn::VD.goToDesktopNum(3) ;3

I do not think this has todo with the WIN-Key, because when i move windows to other desktop via:

#NumpadLeft::VD.MoveWindowToDesktopNum("A",1) ;4
#NumpadClear::VD.MoveWindowToDesktopNum("A",2) ;5
#NumpadRight::VD.MoveWindowToDesktopNum("A",3) ;6

The next Windows of the current VD is focused, like expected.

Ideas

Ciantic/VirtualDesktopAccessor#4:

  • Send ALT+ESC or call AllowSetForegroundWindow(ASFW_ANY) before calling GoToDesktopNumber() could work. Don't get confused with "build-in command have bug in windows 10 implementation" - it build-in command in windows 11 works correctly.

I tried this:

;switch desktop
NumpadEnd::{ ;1
    VD.goToDesktopNum(1)
    ;Send !{Esc} 
    Sleep 1
    Send "!{Esc}" ; ALT+Esc activates last window
}
NumpadDown::{ ;2
    VD.goToDesktopNum(2)
    ;Send !{Esc} 
    Sleep 1
    Send "!{Esc}" ; ALT+Esc activates last window
}
NumpadPgDn::{ ;3
    VD.goToDesktopNum(3)
    ;Send !{Esc} 
    Sleep 1
    Send "!{Esc}" ; ALT+Esc activates last window
}

It seems to work, but in some (unpredictable) cases, it will restore the wrong window, and using higher sleep values does not solve that.

@FuPeiJiang
Copy link
Owner

@arakis
I can't reproduce on Windows 11 nor Windows 10

;you should first Run this, then Read this
;Ctrl + F: jump to #useful stuff

;#SETUP START
#SingleInstance force
ListLines 0
SendMode "Input"
SetWorkingDir A_ScriptDir
KeyHistory 0
#WinActivateForce

ProcessSetPriority "H"

SetWinDelay -1
SetControlDelay -1


;include the library
#Include %A_LineFile%\..\VD.ah2
; or
; #Include %A_LineFile%\..\_VD.ahk
; ...{startup code}
; VD.init()

; VD.ahk : calls `VD.init()` on #Include
; _VD.ahk : `VD.init()` when you want, like after a GUI has rendered, for startup performance reasons

;you should WinHide invisible programs that have a window.
try WinHide "Malwarebytes Tray Application"
;#SETUP END

VD.createUntil(3) ;create until we have at least 3 VD

return

foo(desktopNum) {
    VD.goToDesktopNum(desktopNum)
    ToolTip WinGetTitle("A") " ahk_class " WinGetClass("A") " ahk_exe " WinGetProcessName("A")
}

#NumpadEnd::foo(1)
#NumpadDown::foo(2)
#NumpadPgDn::foo(3)

f3::Exitapp

What's the active window after switch ?
is it that no window is active ?
is it an invisible window ?

@FuPeiJiang
Copy link
Owner

the next step in debugging would be to put

ToolTip WinGetTitle("ahk_id " theHwnd) " ahk_class " WinGetClass("ahk_id " theHwnd) " ahk_exe " WinGetProcessName("ahk_id " theHwnd)

above

WinActivate "ahk_id " theHwnd

in the function _activateWindowUnder

@arakis
Copy link
Author

arakis commented May 1, 2023

Thank you for the debugging script. I tried the initial script, without modifying the _activateWindowUnder method. I found now the reason, but not the solution.
The reason is that application: https://apps.microsoft.com/store/detail/virtual-desktop-indicator/9NHCL1XQWXF1?hl=en-us&gl=us
It's a small utility app, that shows the active desktop after switching. After switch, a small window will shown, and then disappiers after some seconds. That utility window is never visible in "alt-tab"-List, so it should be impossible to focus it - but AutoHotkey does! Because the utility app it's a commercial, closed source app, it would be impossible to debug the problem further. But I'm still asking me why this problem never occurs, when using the built-in windows shortcut. In other words: Without the autohotkey script, the correct windows will always be focused (and never the utility app), regardless how fast i switch between the VD with the build-in windows shortcut.

@arakis
Copy link
Author

arakis commented May 1, 2023

I have now an idea, but for that I need to learn the AutoHotkey Script language a little bit more:
Sending the ALT+ESC conditionally when the VirtualDesktopIndicator.exe is focused. Or finding other ways to unfocus the app, if it's focused.

FuPeiJiang added a commit that referenced this issue May 4, 2023
@FuPeiJiang
Copy link
Owner

@arakis
it should work now

But I'm still asking me why this problem never occurs, when using the built-in windows shortcut. In other words: Without the autohotkey script, the correct windows will always be focused (and never the utility app), regardless how fast i switch between the VD with the build-in windows shortcut.

nice question

The reason is that application: apps.microsoft.com/store/detail/virtual-desktop-indicator/9NHCL1XQWXF1?hl=en-us&gl=us

thanks, I used the free trial to figure out

turns out, if you set GW_OWNER to the desktop window (which has className:#32769)
it will disappear from taskbar, alt+tab list, and appear on all desktops, this is how to set it:

SetWindowLongPtrW(hWnd, GWLP_HWNDPARENT, (LONG_PTR)GetDesktopWindow());

notice how it's GWLP_HWNDPARENT instead of GW_OWNER, the name is misleading
https://stackoverflow.com/questions/133122/how-to-change-a-window-owner-using-its-handle#comment-24839121
> GWL_HWNDPARENT changes the OWNER, not the parent, of a window

@arakis
Copy link
Author

arakis commented May 7, 2023

@FuPeiJiang thank you very, very much, it works! I appreciate your work and the effort you invested in nailing down this problem. Can I buy you a coffee? :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants