Giter Club home page Giter Club logo

Comments (25)

lpke avatar lpke commented on July 20, 2024 2

In case anyone else really wants this, and is as frustrated as I was about the lack of options out there, I've written an Autohotkey script that can do it.

#Requires AutoHotkey v2.0

calc_padding := 20 ; minimum direction/alignment overlap for target windows

#h::FocusWin("left")
#l::FocusWin("right")
#k::FocusWin("up")
#j::FocusWin("down")

; ==== DEVELOPMENT SHORTCUTS ====
; Reload this script
; #+r:: {
;   Reload
; }
; Get active window position data
; #+t:: {
;   aID := WinGetID("A")
;   WinGetFullPos(&aXL, &aXR, &aYT, &aYB, &aW, &aH, aID)
;   discounted := WinIsDiscounted(aID, &visible, &desktop, &taskbar, &startmenu)

;   MsgBox(
;     "XL:  " aXL "`n"
;     "XR:  " aXR "`n"
;     "YT:  " aYT "`n"
;     "YB:  " aYB "`n"
;     "W:  "  aW  "`n"
;     "H:  "  aH  "`n"
;     "`n"
;     "ID:  " aID "`n"
;     "`n"
;     "Visible:  " visible "`n"
;     "Desktop:  " desktop "`n"
;     "Taskbar:  " taskbar "`n"
;     "Startmenu:  " startmenu "`n"
;     "`n"
;     "Discounted:  " discounted
;   )
; }

WinGetFullPos(&xl, &xr, &yt, &yb, &w, &h, id) {
  WinGetPos(&xl, &yt, &w, &h, id)
  xr := xl + w
  yb := yt + h
  return
}

OverlapAxis(axis, padding, aXL, aXR, aYT, aYB, tXL, tXR, tYT, tYB) {
  if (axis = "Y" && (tYB >= (aYT + padding) && (tYT + padding) <= aYB))
    return true
  if (axis = "X" && (tXR >= (aXL + padding) && (tXL + padding) <= aXR))
    return true
  return false
}

WinIsDiscounted(id, &visible, &desktop, &taskbar, &startmenu) {
  wclass := WinGetClass(id)
  wstyle := WinGetStyle("ahk_id" id)
  WS_VISIBLE := 0x10000000

  visible := (wstyle & WS_VISIBLE) ? true : false
  desktop := (wclass = "Progman" || wclass = "WorkerW")
  taskbar := (wclass = "Shell_TrayWnd" || wclass = "Shell_SecondaryTrayWnd")
  startmenu := (wclass = "DV2ControlHost" || wclass = "Windows.UI.Core.CoreWindow")

  return !visible || desktop || taskbar || startmenu
}

FocusWin(direction) {
  aID := WinGetID("A") ; get ID of active window
  WinGetFullPos(&aXL, &aXR, &aYT, &aYB, &aW, &aH, aID) ; get pos/size of active window
  
  ids_arr := WinGetList() ; get all window IDs (returns array of id strings)

  ; values to update during the loop
  closest_id := ""
  closest_distance := 999999999

  ; loop through all windows
  ; validity checks are made early as possible for performance
  for (tID in ids_arr) {
    is_active_win := tID == aID
    if (is_active_win)
      continue
    is_discounted_win := WinIsDiscounted(tID, &visible, &desktop, &taskbar, &startmenu)
    if (is_discounted_win)
      continue

    WinGetFullPos(&tXL, &tXR, &tYT, &tYB, &tW, &tH, tID) ; get pos/size of target window

    switch direction
    {
      case "left": is_direction := aXL - tXL >= calc_padding
      case "right": is_direction := tXR - aXR >= calc_padding
      case "up": is_direction := aYT - tYT >= calc_padding
      case "down": is_direction := tYB - aYB >= calc_padding
    }
    if (!is_direction)
      continue
    switch direction
    {
      case "left": is_aligned := OverlapAxis("Y", calc_padding, aXL, aXR, aYT, aYB, tXL, tXR, tYT, tYB)
      case "right": is_aligned := OverlapAxis("Y", calc_padding, aXL, aXR, aYT, aYB, tXL, tXR, tYT, tYB)
      case "up": is_aligned := OverlapAxis("X", calc_padding, aXL, aXR, aYT, aYB, tXL, tXR, tYT, tYB)
      case "down": is_aligned := OverlapAxis("X", calc_padding, aXL, aXR, aYT, aYB, tXL, tXR, tYT, tYB)
    }
    if (!is_aligned)
      continue

    switch direction
    {
      case "left": distance := aXL - tXR
      case "right": distance := tXL - aXR
      case "up": distance := aYT - tYB
      case "down": distance := tYT - aYB
    }

    ; update closest values if window is closer and to the left
    if (distance < closest_distance) {
        closest_id := tID
        closest_distance := distance
    }
  }
  
  ; activate closest window
  if (closest_id)
    WinActivate("ahk_id" closest_id)

  return
}

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024 1

This would be a nice addition indeed, I will investigate This...

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024 1

Here is a first test build I wrote in an hour this morning.
I use a conical region to determine what is right/left/top/bottom of a window, For me it seems to be a good algorithm. Might use some more work. I did not try your ahk script, I directly wrote something from scratch.

AltSnap1.62test1_i386.zip
AltSnap1.62test1_x64.zip

Of course as usual replace AltSnap.exe and hooks.dll with the versions above and in the Keyboard tab you will have the option to configure the Focus left/right/top/bottom window in the Shortcut for action: drop list.

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024 1

@RamonUnch, the test8 works as intended as I tried with no overlapping windows and windows overlapped a little bit. The algorithms is what I intended to have to be able to move the focus to. I don't find any odd behavior so far. Thank you so much!

from altsnap.

lpke avatar lpke commented on July 20, 2024

I'll give this a test later, thank you!

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

@RamonUnch, I was trying to play with using command line L/R direction change the focus fine.
AltSnap.exe -afFocusR and AltSnap.exe -afFocusL

However, when I try to move focus up/down -afFocusT and -afFocusB, it does not change focus. Actually, it is hard to tell where the focus is after these commands in up/down direction.

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

For me it works relyably.
Maybe try with the latest test build:
AltSnap1.62test5_x64.zip
AltSnap1.62test5_i386.zip

Also here is a visual description on how it should work:
ImageFocusLTRB
Same logic applies to right and top.

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

also those actions were designed for keyboard shortcuts in mind. You can setup those shortcuts directly in AltSnap.

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

I tried with keyboard and also with the latest release (test5) and still cannot navigate in T/B direction. I attached my config in the comment. Can you please check?

By the way, I am using external monitor with 150% DPI and grid 2x2 layout. I tried with 4 notepad window laid out neatly using Altsnap. There is no other layout manager such as FancyZone in the play.

AltSnap.ini.txt

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

image
Here are how these 4 notepad laid out for testing. There is not any overlap. LR direction always works. Except sometime, the focus changes between RB and LT intead of LB and RB. So there are some strange things going on.

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

I still cannot reproduce but I see some problems with the current system.
I will make a logging version to test on your machine.
Also I will work on improving the window selection algorithm.

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

AltSnap1.62test5_LOG_x64.zip
See what you get in the ad.log file that will be created when you use the FocusL/T/R/B actions...
Each line you should see the window that AltSnap tries to focus.

from altsnap.

Ichisich avatar Ichisich commented on July 20, 2024

Currently, seems, pretty unreliable in which window gets focused.
Needs probably more cones, TL/TR/BL/BR

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

This version removes overlap between directions and prioritize the pure cardinal position over diagonals.
Like this you get more directional while still being able to move along all windows (in theory).

Also let me know if you see strange windows appear in the ad.log file. Normally only AltTabable windows should appear.
AltSnap1.62test6_LOG_x64.zip
AltSnap1.62test6_LOG_i386.zip

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

It is better than before. It can still get focused the wrong window. I initially focused on TL and issued to focusB. It moved down currectly. I issued focusT and it focused top window correctly. I then move the focus to the right top window. It got the TR (top right) window correctly. But now when I issued focusB, and tried to move the focus to BR (bottom right) it moves focus to the BL (bottom left). Now if I move the focus to T or B, it switches the focus between TR and BL (diagonally) all the time. ad.log is attached.
ad.log

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

Thanks for the log file, so it seems the only problem comes from bad selection algorithm.
Here is a version with a slightly thinner beam, as well as two others versions with even smaller beam for testing.
So you can try first test7 then see if half beam fits you better then decide if maybe 2/3rd or 1/3 beam are better. You only need to replace the hooks.dll file
Square_beam

hooks1.62test7_2_3rd_beam_x64.zip
hooks1.62test7_3rd_beam_x64.zip
hooks1.62test7_half_beam_x64.zip
hooks1.62test7_x64.zip

It is a two step process, first AltSnap tries to find the closest window inside the beam, then if it was unable to find any window, it create 45 degree regions and selects the next closest window within those regions. thus covering the whole space.

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

@RamonUnch, thank you for additional dlls. I found the hooks1.6test7_x64 version works better than 1/3, 1/2, and 2/3.

Actually, I have a very reliable way to reproduce this issue with the layout below. I found that I can focus on all 3 of them reliably, if I move focus from TL(left top) -> BL (left-bottom) -> TL (left top) -> TR (top right). But the problem happens when I try to move focus from TR to BL (focusB), it found the BL diagonally. After that, BL can only move focus to TR (focusT), it will ignore the TL window that is directly above. This is reproducible every time for me. I think the order of scanning diagonally versus straight can be improved.

image

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

You mean that you would like to be able to go from BL to TR by using the FocusR action?
This would make some sense indeed I would just need to use the diagonals from the window itself instead of fixed 45° angle for the cones.

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

Actually the above is already possible so it would be going from TR to BL with the FocusB action...

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

However using the the window diagonals as cone is not necessary a very good idea because it means that each window would have a different cones based on its dimentions which would be confusing. Would be nice only in this specific case. Also monitor's diagonal angle could be used, not sure as well it it is a good idea.

Maybe I can add a third step that tries with an even larger cone if it fails in the 45° cone but I am not sure it is a good idea either. Because it would go back to the first problem that if you have overlap in the regions then you may have windows that become impossible to select in some cases.

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

The current implementation with hooks1.62test7_x64.zip can move focus between BL and TR using focusT or focusB. However, after that, while in BL, I issued the focusT to try to focus the window TL that is directly above, it focused the TR instead. When the focus moved from TR to BL. The BL can only move focus to back TR instead of TL when issuing focusT from it. This is confusing.

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

@RamonUnch , there is a demo of this issue. Keys about bound with Ctrl+Win+Alt+H, J, K, L for left, down, top, and right.
focus_moving_issue

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

That is very strange, I am unable to reproduce: When I hit Ctrl+Win+Alt+K from BL, I only get TL selected and never TR.
Actually in theory it should be impossible to go from BL to TR with the FocusT action.

Try with opening in notepad files with different names so that we can check in the ad.log file which one AltSnap tries to focus.
Use this build to have a log:
hooks1.62test7_LOG_x64.zip

from altsnap.

ZhichaoHong avatar ZhichaoHong commented on July 20, 2024

Here are the screenshot and log file. To reproduce, I toggled the between TL and BL a few times. Then I move to TR from TL. Then focusB forces TR to BL as there is no other window directly under it. After that, FocusB/T will only move focus between BL and TR. I named the files in notepad with the windows location they represent. So the log file will be more helpful.

image

ad.log

from altsnap.

RamonUnch avatar RamonUnch commented on July 20, 2024

Try again with this build? At this point math seems to be non-reproducible because it SocusT should not be able to do BL->TR and FocusB should not even be able to do TR->BL.

hooks1.62test8_LOG_x64.zip
hooks1.62test8_x64.zip

from altsnap.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.