1、效果預覽
博主平時用 terminal + vim 作爲開發環境,有時候要同時打開多個窗口(如:coding、log、debug ...),這些窗口沒有平鋪效果,往往亂糟糟的。
本文帶來一個腳本,可以一鍵啓動炫酷的多個平鋪的窗口,可供大家自行延展發展(因爲不同系統的字體可能參數要微調),效果如下:
2、具體實現
2.1 定位鼠標位置
考慮到多個顯示器的情況,我們通過腳本讀取鼠標箭頭位置,然後在其所在窗口展開對應平鋪窗口。
這裏我們會用到 xdotool
,例如,如下命令可以獲取鼠標箭頭位置:
➜ terminal xdotool getmouselocation
x:1602 y:830 screen:0 window:79767574
我們用 sed
將上面返回的字符串中的 x\y 的值吸取出來:
# 獲取鼠標位置
mouse_pos_x=`xdotool getmouselocation | sed "s:x\:\([0-9]*\) y\:\([0-9]*\) .*:\1:g"`
mouse_pos_y=`xdotool getmouselocation | sed "s:x\:\([0-9]*\) y\:\([0-9]*\) .*:\2:g"`
echo "mouse_pos_x = "$mouse_pos_x
echo "mouse_pos_y = "$mouse_pos_y
2.2 獲取屏幕位置
上面我們定位了鼠標的位置,接下來我們要定位屏幕的位置,我們將要用到 xrandr
命令:
➜ terminal xrandr
Screen 0: minimum 320 x 200, current 3200 x 1080, maximum 8192 x 8192
HDMI-1 disconnected (normal left inverted right x axis y axis)
DVI-D-1 connected 1920x1080+1280+0 (normal left inverted right x axis y axis) 509mm x 286mm
1920x1080 60.00*+ 59.96 50.00 59.94 59.93
1920x1080i 60.00 50.00 59.94
...
VGA-1 connected primary 1280x1024+0+0 (normal left inverted right x axis y axis) 338mm x 270mm
1280x1024 60.02*+ 75.02
1280x960 60.00
1280x800 59.97 59.81 59.91
...
我們用 sed
將 1920x1080+1280+0
和 1280x1024+0+0
吸出來:
➜ terminal xrandr | grep " connected" | sed "s:.* connected.* \([0-9]*\)x\([0-9]*\)+\([0-9]*\)+\([0-9]*\).*:\1 \2 \3 \4:g"
1920 1080 1280 0
1280 1024 0 0
將吸取出來的值存起來:
# 通過下面邏輯,可以將所有屏幕的大小和位置全部算出來
# screen [x, y, x_start, y_start, x_end, y_end]
x_index=0
s_index=0
for x in `xrandr | grep " connected" | sed "s:.* connected.* \([0-9]*\)x\([0-9]*\)+\([0-9]*\)+\([0-9]*\).*:\1 \2 \3 \4:g"`
do
echo $x
screen[$s_index]=$x
let x_index++
let s_index++
if [ $((x_index % 4)) -eq 0 ];then
screen[$((s_index+0))]=$((screen[$((s_index-4))]+screen[$((s_index-2))]));
screen[$((s_index+1))]=$((screen[$((s_index-3))]+screen[$((s_index-1))]));
let s_index+=2
fi
done
echo ${screen[@]}
2.3 計算鼠標在哪個窗口
上面兩步已經獲取了鼠標位置和窗口座標,接下來就是一個簡單的算法,來計算點在哪個矩形中的問題了(算法如下):
# 計算座標 (x,y) 是否在某個屏幕中 (x_start,y_start,x_end,y_end)
function point_in_screen(){
local x=$1
local y=$2
local x_start=$3
local y_start=$4
local x_end=$5
local y_end=$6
if (($x >= $x_start)) && (($x <= $x_end)) && (($y >= $y_start)) && (($y <= $y_end)) ; then
return 1
else
return 0
fi
}
這樣,我們就能遍歷鼠標的座標點(x,y)在哪個屏幕中了:
screen_num=$((s_index/6))
index=0
while [ $index -le $screen_num ]
do
point_in_screen $mouse_pos_x $mouse_pos_y ${screen[$((index*6+2))]} ${screen[$((index*6+3))]} ${screen[$((index*6+4))]} ${screen[$((index*6+5))]}
if [ $? == 1 ];then
echo 'the point in scree '$index
create_terminal ${screen[$((index*6))]} ${screen[$((index*6+1))]} ${screen[$((index*6+2))]} ${screen[$((index*6+3))]}
break
fi
let index++
done
我們在獲取屏幕數據時,將一個屏幕的(w
h
x_start
y_start
x_end
y_end
)6 個數據作爲一組存儲,因此用 s_index/6
可以獲取總的屏幕數。
2.4 1920x1080 平鋪效果設計
我有兩個屏幕:1920x1080 和 1280x1024,我的設計如下:
- 在大屏幕中,展開 3 個窗口,就像我們常用的 IDE,有編碼窗口,有輸入交互命令的窗口,有看 log 的窗口;
- 在小屏幕中,展開 3 個窗口,一個用來看文件,進行文件搜索,關鍵詞搜索等,一個進行看天氣,一個用來監控 CPU 和網速;
那麼接下來就是用代碼繪製了!
# 繪製 terminal
function create_terminal(){
SCREEN_W=$1
SCREEN_H=$2
if (( $SCREEN_H == 1080)) && (($SCREEN_W == 1920)) ;then
X_BOARD=15 #窗口與窗口之間的橫向補償(由於存在精度誤差,該值是經驗值)
Y_BOARD=15
LEFT_OFFSET=$3
UP_OFFSET=$4
H=50 #1080
W=189 #1920
win1_pos_x=$((LEFT_OFFSET+X_BOARD))
win1_pos_y=$((UP_OFFSET+Y_BOARD))
win1_size_w=$W
win1_size_h=$((H*2/3))
win2_pos_x=$win1_pos_x
win2_pos_y=$((win1_pos_y + SCREEN_H*2/3 + Y_BOARD -22))
win2_size_w=$((W/2-1))
win2_size_h=$((H/3))
win3_pos_x=$((win1_pos_x+SCREEN_W/2-8))
win3_pos_y=$((win2_pos_y))
win3_size_w=$win2_size_w
win3_size_h=$((win2_size_h-2))
xfce4-terminal --geometry $win1_size_w'x'$win1_size_h'+'$win1_pos_x'+'$win1_pos_y -Tcode -e'bash -c "vim ; bash"'
xfce4-terminal --geometry $win2_size_w'x'$win2_size_h'+'$win2_pos_x'+'$win2_pos_y -Tcmd -e'bash -c "screenfetch ; bash"'
xfce4-terminal --geometry $win3_size_w'x'$win3_size_h'+'$win3_pos_x'+'$win3_pos_y -Tlog -e'bash -c "xdotool key ctrl+shift+t; bash"'
echo $win1_size_w'x'$win1_size_h'+'$win1_pos_x'+'$win1_pos_y
echo $win2_size_w'x'$win2_size_h'+'$win2_pos_x'+'$win2_pos_y
echo $win3_size_w'x'$win3_size_h'+'$win3_pos_x'+'$win3_pos_y
elif (( $SCREEN_H == 1024)) && (($SCREEN_W == 1280)) ;then
...
fi
}
X_BOARD
和Y_BOARD
是窗口與窗口之間的留白,這樣相比於窗口相互緊貼,顯得更高端H
和W
是個經驗值,由於繪製窗口的函數xfce4-terminal
傳如的串口寬、高不是像素點,而是某種好像和字體相關的行、列,因此得根據自己電腦的情況微調- 我們有了窗口像素級起始位置,像素級大小,以及整個屏幕按照字體行列計算的大致行列數 H/W,我們就能計算出三個窗口的起始像素級位置,和窗口的行列級大小(這裏有各種補償,以達到最佳效果)
- 最後調用
xfce4-terminal
進行繪製,在繪製的時候可以帶一些默認執行的語句,例如:vim
,screenfetch
等
2.5 1280x1024 平鋪效果設計
同 1920x1080,繪製 1280x1024 的代碼如下:
X_BOARD=30 #窗口與窗口之間的橫向補償(由於存在精度誤差,該值是經驗值)
Y_BOARD=30
LEFT_OFFSET=$3
UP_OFFSET=$4
H=48 #56 #1024
W=129 #142 #1280
win1_pos_x=$((LEFT_OFFSET+X_BOARD))
win1_pos_y=$((UP_OFFSET+Y_BOARD))
win1_size_w=$((W/2-4))
win1_size_h=$((H-2))
win2_pos_x=$((win1_pos_x + SCREEN_W/2 + X_BOARD - 48))
win2_pos_y=$win1_pos_y
win2_size_w=$win1_size_w
win2_size_h=$((win1_size_h/2))
win3_pos_x=$win2_pos_x
win3_pos_y=$((win1_pos_y + SCREEN_H/2 + Y_BOARD - 40))
win3_size_w=$win2_size_w
win3_size_h=$((win2_size_h-1))
# xwininfo
xfce4-terminal --geometry $win1_size_w'x'$win1_size_h'+'$win1_pos_x'+'$win1_pos_y -Tsys
xfce4-terminal --geometry $win2_size_w'x'$win2_size_h'+'$win2_pos_x'+'$win2_pos_y -Tmem -e'bash -c "curl \"wttr.in/HangZhou?0\";bash"'
xfce4-terminal --geometry $win3_size_w'x'$win3_size_h'+'$win3_pos_x'+'$win3_pos_y -Tinfo -e'bash -c "sampler -c runchart.yml;bash"'
- 天氣用了一個 OpenAPI,這個屬於 github 上一個超大項目,裏面有各種開放 API
- 系統性能,用了
sampler
,大家可以進一步深入研究
3 代碼
本文代碼在:https://github.com/nbtool/cool_terminal
➜ terminal tree
.
├── readme.md
├── runchart.yml
└── run.sh
0 directories, 3 files
參考鏈接
[1]. 本文代碼 GITHUB
[2]. xdotool 介紹
[3]. arch linux 社區 xrandr 介紹
[4]. arch linux 社區 xfce4-terminal 介紹
: ** 如果覺得不錯,幫忙點個支持哈~**