You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 line
2.5 KiB

  1. #!/bin/bash
  2. export PATH="$HOME/.local/bin:$PATH"
  3. # epochMillis: print the amount of millis since epoch time on the std output stream.
  4. epochMillis(){
  5. echo $(($(date +%s%N)/1000000))
  6. }
  7. # queue: array holding the focused window ids in order, the most recent focus is on index 0.
  8. queue=( )
  9. queueLimit=8
  10. # pushOnQueue: insert a window id on index 0 of the queue. This function also removes the given id if was already present, the queue is an ordered set.
  11. # arg 1: window id to insert.
  12. pushOnQueue(){
  13. if [ "$1" = "0x0" ]
  14. then
  15. return
  16. fi
  17. newQueue=( "$1" )
  18. for i in "${queue[@]}"
  19. do
  20. if [ "$1" = "$i" ]
  21. then
  22. continue
  23. fi
  24. newQueue=( ${newQueue[@]:0} "$i" )
  25. done
  26. queue=( "${newQueue[@]:0:$queueLimit}" )
  27. }
  28. # markQueue: put i3 marks using the window ids stored on the queue. The windows are marked using "_prevFocusX" where X is a integer corresponding with the index of the element on the queue. The previously focused window (the most recent) is marked using "_prevFocus0". This function also cleans the queue from windows that can't be marked (e.g. windows that have been closed).
  29. markQueue(){
  30. queueCopy=( "${queue[@]}" )
  31. queue=( )
  32. j=0
  33. for i in "${queueCopy[@]}"
  34. do
  35. i3-msg "unmark _prevFocus$j" 1>/dev/null 2>&1
  36. if i3-msg "[id=$i] mark --add _prevFocus$j" 2>/dev/null | grep -i "\"success\":true" 1>/dev/null 2>&1
  37. then
  38. queue=( ${queue[@]:0} "$i" )
  39. j=$(($j + 1))
  40. fi
  41. done
  42. }
  43. lastTime=$(epochMillis)
  44. # permanence: period in millis used to determine if a window is worthy to be saved on the queue. This enables i3 window fast navigation without saving unworthy window ids.
  45. permanence=1000
  46. # main loop: read activated window ids continuously.
  47. xprop -root -spy _NET_ACTIVE_WINDOW |
  48. while read line
  49. do
  50. currentTime=$(epochMillis)
  51. period=$(($currentTime-$lastTime))
  52. lastTime=$currentTime
  53. # previousFocus: window id of the previously focused (activated) window.
  54. previousFocus=$currentFocus
  55. # currentFocus: window id of the window that has just being activated.
  56. currentFocus=$(echo "$line" | awk -F' ' '{printf $NF}')
  57. # push the previousFocus id to the queue if the time spent on the previous window was greater than permanence. Check also to allow fast switching between two windows.
  58. if [ $period -gt $permanence -o "$currentFocus" = "${queue[0]}" ]
  59. then
  60. pushOnQueue "$previousFocus"
  61. fi
  62. # if the currentFocus is marked as the previous window (_prevFocus0 or queue[0]) then swap the first two elements on the queue to allow switching.
  63. if [ "${queue[0]}" = "$currentFocus" ]
  64. then
  65. queue=( ${queue[1]} ${queue[0]} ${queue[@]:2} )
  66. fi
  67. markQueue
  68. done