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.

80 lines
2.5 KiB

  1. #!/bin/bash
  2. # epochMillis: print the amount of millis since epoch time on the std output stream.
  3. epochMillis(){
  4. echo $(($(date +%s%N)/1000000))
  5. }
  6. # queue: array holding the focused window ids in order, the most recent focus is on index 0.
  7. queue=( )
  8. queueLimit=8
  9. # 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.
  10. # arg 1: window id to insert.
  11. pushOnQueue(){
  12. if [ "$1" = "0x0" ]
  13. then
  14. return
  15. fi
  16. newQueue=( "$1" )
  17. for i in "${queue[@]}"
  18. do
  19. if [ "$1" = "$i" ]
  20. then
  21. continue
  22. fi
  23. newQueue=( ${newQueue[@]:0} "$i" )
  24. done
  25. queue=( "${newQueue[@]:0:$queueLimit}" )
  26. }
  27. # 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).
  28. markQueue(){
  29. queueCopy=( "${queue[@]}" )
  30. queue=( )
  31. j=0
  32. for i in "${queueCopy[@]}"
  33. do
  34. i3-msg "unmark _prevFocus$j" 1>/dev/null 2>&1
  35. if i3-msg "[id=$i] mark --add _prevFocus$j" 2>/dev/null | grep -i "\"success\":true" 1>/dev/null 2>&1
  36. then
  37. queue=( ${queue[@]:0} "$i" )
  38. j=$(($j + 1))
  39. fi
  40. done
  41. }
  42. lastTime=$(epochMillis)
  43. # 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.
  44. permanence=1000
  45. # main loop: read activated window ids continuously.
  46. xprop -root -spy _NET_ACTIVE_WINDOW |
  47. while read line
  48. do
  49. currentTime=$(epochMillis)
  50. period=$(($currentTime-$lastTime))
  51. lastTime=$currentTime
  52. # previousFocus: window id of the previously focused (activated) window.
  53. previousFocus=$currentFocus
  54. # currentFocus: window id of the window that has just being activated.
  55. currentFocus=$(echo "$line" | awk -F' ' '{printf $NF}')
  56. # 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.
  57. if [ $period -gt $permanence -o "$currentFocus" = "${queue[0]}" ]
  58. then
  59. pushOnQueue "$previousFocus"
  60. fi
  61. # 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.
  62. if [ "${queue[0]}" = "$currentFocus" ]
  63. then
  64. queue=( ${queue[1]} ${queue[0]} ${queue[@]:2} )
  65. fi
  66. markQueue
  67. done