為了使GNU/Linux桌面環境下加載的程序較少以節省內存資源和提高啟動時間,我目前並不使用重量級的桌面環境KDE和Gnome,甚至連登錄窗界面gdm或xdm都不用,而是直接啟動到控制台,登錄后調用startx進入X視窗環境。所使用的工具組合列舉如下:
- X視窗環境啟動:startx
- 窗口管理器:Sawfish
- amixer:系統音量設置
- 鍵盤與鼠標配置:xmodmap
- 網絡管理器:wicd(需刪除NetworkManager)
- xscreensaver:屏幕保護程序
- 類似於Windows的底部工具欄:perlpanel
- shutter:截屏工具
- amor:屏幕寵物玩具
- workrave:定時休息、活動提醒工具,用於緩解視疲勞,身體疲勞
- xclock:桌面模擬或數字時鍾
- knotes:桌面即時貼
在~/.bashrc中設置音頻
首先介紹登錄到控制台時,在~/.bashrc中定義的一些環境變量,它們會在啟動X Window后,由amixer命令使用,用於系統音量控制。
# Default sound device export DEFAULT_SOUND=numid=3,iface=MIXER,name="'Master Playback Volume'" # Max sound for the two channels supported by the sound card declare -i MAX_SOUND_VOLUME export MAX_SOUND_VOLUME=65536 # Default sound volume percentage for the two channels when starting X window declare -i DEFAULT_LSOUND_VOLUME_PERCENTAGE DEFAULT_RSOUND_VOLUME_PERCENTAGE export DEFAULT_LSOUND_VOLUME_PERCENTAGE=40 export DEFAULT_RSOUND_VOLUME_PERCENTAGE=40 # Default sound volume for the two channels when starting X window declare -i DEFAULT_LSOUND_VOLUME DEFAULT_RSOUND_VOLUME export DEFAULT_LSOUND_VOLUME=$(($MAX_SOUND_VOLUME * $DEFAULT_LSOUND_VOLUME_PERCENTAGE / 100)) export DEFAULT_RSOUND_VOLUME=$(($MAX_SOUND_VOLUME * $DEFAULT_RSOUND_VOLUME_PERCENTAGE / 100)) # Whether play init sound when starting X window export STARTX_INIT_SOUND=1
# Aliases for starting X with or without sound
alias xs="export STARTX_INIT_SOUND=1; startx"
alias xq="export STARTX_INIT_SOUND=0; startx"
針對以上代碼解釋如下:
1. DEFAULT_SOUND變量包含了指定操作系統ALSA聲卡驅動調音器設備的編號與名稱。amixer以該值為參數,可以控制相應音頻的音量。該設備信息可以在命令行執行amixer contents顯示出來,如下所示。可以看出,默認音頻設備音量的最小值為0,最大值為65536(2字節),最小調整量為1,當前左、右聲道音量值均為17790。
numid=4,iface=MIXER,name='Master Playback Switch' ; type=BOOLEAN,access=rw------,values=1 : values=on numid=3,iface=MIXER,name='Master Playback Volume' ; type=INTEGER,access=rw------,values=2,min=0,max=65536,step=1 : values=17790,17790 numid=2,iface=MIXER,name='Capture Switch' ; type=BOOLEAN,access=rw------,values=1 : values=on numid=1,iface=MIXER,name='Capture Volume' ; type=INTEGER,access=rw------,values=2,min=0,max=65536,step=1 : values=28174,28174
2. MAX_SOUND_VOLUME變量存儲了最大音量值65536。
3. DEFAULT_LSOUND_VOLUME_PERCENTAGE與DEFAULT_RSOUND_VOLUME_PERCENTAGE分別為左、右聲道的默認音量百分比,目前設為40%。
4. DEFAULT_LSOUND_VOLUME與DEFAULT_RSOUND_VOLUME分別為左、右聲道的默認音量整數值。
5. STARTX_INIT_SOUND變量為1時,在調用startx進入X Window時,會自動播放歡迎音樂;為0時則不播放。播放命令在~/.xinitrc中設置。
6. 創建了兩個aliases,xs為調用startx時播放歡迎音樂,xq則不播放。
設置~/.xinitrc
在控制台登錄后,有了~/.bashrc中的設置,就可以調用xs或xq來啟動startx進入X Window視窗環境。啟動過程中的相關配置與必要程序加載是在~/.xinitrc中設置的。其內容如下:
# Export ibus environment variables export XMODIFIERS=@im=ibus export GTK_IM_MODULE=ibus export QT_IM_MODULE=ibus # Load NVIDIA configurations nvidia-settings --load-config-only # Load keyboard and mouse configurations xmodmap ~/.xmodmaprc & # Load X server resources xrdb ~/.Xresources & # Load image(s) as desktop wallpaper # set_wallpaper.sh -r 0 -w 1920 -h 1080 -x 1280 -y 0 $picture/wallpapers/sunflower.jpg & set_multi_wallpapers.sh -t 300 & # Set the default sound volume amixer cset numid=3,iface=MIXER,name='Master Playback Volume' $DEFAULT_LSOUND_VOLUME,$DEFAULT_RSOUND_VOLUME & # Play welcome sound: Steve Jobs' speech if [ "$STARTX_INIT_SOUND" = 1 ]; then mplayer $music/speech/steve\ jobs\ in\ harvard\ clip.mp3 < /dev/null > /dev/null & fi # Adjust touchpad pressure sensitivity if [ "$cur_host_name" = "QuantumBoy" ]; then synclient PressureMotionMinZ=8 synclient PressureMotionMaxZ=80 fi # Start window manager sawfish --display=:0
針對以上代碼解釋如下:
1. 導出ibus輸入法相關的環境變量。
2. 執行nvidia-settings加載NVIDIA配置。
3. 使用xmodmap加載鍵盤與鼠標配置,主要是交換Caps Lock與左Control鍵,交換鼠標左右鍵。具體內容參見這里。
4. 使用xrdb加載視窗資源文件~/.Xresources,其中針對不同的程序設置X顯示參數,設置光標主題。其內容如下:
Xcursor.theme: oxy-green XClock.Clock.hourColor: red XClock.Clock.minuteColor: green XClock.Clock.minorColor: blue XClock.Clock.majorColor: black
5. 啟動set_multi_wallpapers.sh腳本加載動態壁紙,或調用set_wallpaper.sh加載單張壁紙。具體內容參見這里。
6. 使用amixer設置系統默認音量。左右聲道的音量值來自環境變量DEFAULT_LSOUND_VOLUME和DEFAULT_RSOUND_VOLUME。
7. 根據環境變量STARTX_INIT_SOUND的值判斷是否加播放啟動音頻。目前,我播放的是喬布斯說的stay hungray、stay foolish那段話。
8. 根據電腦的主機名判斷,如果使用的是自己的筆記本電腦ZaReason Ultralap 440的話,則執行synclient命令設置觸摸板壓力閾值。
9. 最后,啟動Sawfish窗口管理器。
Sawfish設置:~/.sawfishrc
Sawfish是一款輕量級的窗口管理器,基於librep庫支持使用Lisp語言對其進行配置:包括窗口顯示屬性,快捷鍵綁定等。所以,所謂的輕量級實際上是高性能、省資源,但其功能可以通過編程配置得極為強大。下面介紹我在~/.sawfishrc文件對其的配置。其中主要實現的功能有:
1. 將常用程序綁定到指定的快捷上。按下快捷鍵后,若與其關聯的程序未啟動,則將其啟動並放到前端;若已啟動,則將其提升到前端。該功能的實現依賴於jump-or-exec模塊。有了這個功能,則無需頻繁地使用鼠標在不同的窗口間切換了,非常方便。目前,我綁定的快捷鍵如下:
- Win+1:命令行終端程序Konsole;
- Win+2:文件管理器Dolphin;
- Win+3:文本編輯器Emacs;
- Win+4:多國語言電子詞典Stardict或Goldendict;
- Win+5:網頁瀏覽器Iceweasel,它是Mozilla Firefox在Debian下的名稱;
- Win+6:郵件客戶端(亦是RSS閱讀器、日歷、任務管理,類似於微軟的Outlook)Icedove,它是Mozilla Thunderbird在Debian下的名稱;
- Win+7:辦公軟件LibreOffice;
- Win+8:圖片、照片瀏覽器Gwenview。該軟件比Windows下的圖片查看器好很多:可以看GIF動畫,亦可以直接看視頻;
- Win+9:音頻播放器Audacious,播放無損音樂ape、flac的不二之選;
- Win+0:調用tv_nomen.sh腳本程序播放有線電視,參見這里。
以上功能與設置的代碼如下。其中的display-close-message函數用於在屏幕上顯示已啟動程序的名稱,給用戶以信息反饋,並在指定時間后自動關閉。
;; Load jump-or-exec module (require 'jump-or-exec) ;; Display a message which can automatically disappear (defun display-close-message (message seconds &optional attributes) "display MESSAGE for SECONDS seconds and make the message disappeared. The default display-message don't close the message window automatically" (interactive) (display-message message attributes) (make-timer (lambda () (display-message)) seconds)) ;; KDE terminal konsole (bind-keys global-keymap "Super-1" `(jump-or-exec "^Konsole@" ,(lambda () (display-close-message "Start KDE terminal..." alert-msg-time alert-msg-attrib) (system "konsole &")) ,(lambda (wind) (display-window wind)))) ;; Dolphin file manager (bind-keys global-keymap "Super-2" `(jump-or-exec "Dolphin$" ,(lambda () (display-close-message "Start Dolphin file manager..." alert-msg-time alert-msg-attrib) (system "dolphin &")) ,(lambda (wind) (display-window wind)))) ;; Emacs text editor (bind-keys global-keymap "Super-3" `(jump-or-exec "^Emacs@" ,(lambda () (display-close-message "Start Emacs text editor..." alert-msg-time alert-msg-attrib) (system "emacs &")) ,(lambda (wind) (display-window wind)))) ;; Stardict (bind-keys global-keymap "Super-4" `(jump-or-exec "^StarDict$" ,(lambda () (display-close-message "Start Stardict electronic dictionary..." alert-msg-time alert-msg-attrib) (system "stardict &")) ,(lambda (wind) (display-window wind)))) ;; Iceweasel (bind-keys global-keymap "Super-5" `(jump-or-exec "Iceweasel$" ,(lambda () (display-close-message "Start Iceweasel web browser..." alert-msg-time alert-msg-attrib) (system "iceweasel &")) ,(lambda (wind) (display-window wind)))) ;; Icedove (bind-keys global-keymap "Super-6" `(jump-or-exec "(Mozilla Thunderbird)|(Icedove)" ,(lambda () (display-close-message "Start Icedove mail and news..." alert-msg-time alert-msg-attrib) (system "icedove &")) ,(lambda (wind) (display-window wind)))) ;; LibreOffice (bind-keys global-keymap "Super-7" `(jump-or-exec "LibreOffice" ,(lambda () (display-close-message "Start LibreOffice..." alert-msg-time alert-msg-attrib) (system "libreoffice &")) ,(lambda (wind) (display-window wind)))) ;; Gwenview (bind-keys global-keymap "Super-8" `(jump-or-exec "Gwenview$" ,(lambda () (display-close-message "Start Gwenview image viewer..." alert-msg-time alert-msg-attrib) (system "gwenview &")) ,(lambda (wind) (display-window wind)))) ;; Audacious (bind-keys global-keymap "Super-9" `(jump-or-exec "Audacious" ,(lambda () (display-close-message "Start Audacious music player..." alert-msg-time alert-msg-attrib) (system "audacious &")) ,(lambda (wind) (display-window wind)))) ;; TV (bind-keys global-keymap "Super-0" `(jump-or-exec "MPlayer TV" ,(lambda () (display-close-message "Start TV..." alert-msg-time alert-msg-attrib) (system "tv_nomen.sh &")) ,(lambda (wind) (display-window wind))))
2. 在進入X Window時自動加載指定程序,相當於Windows中的自啟動項目。目前我加載的程序有:
- ibus輸入法;
- 網絡管理器wicd-gtk;
- 允許觸摸板點擊腳本enable_tapbutton.sh(僅在我的ZaReason Ultralap 440筆記本電腦上有效);
- xscreensaver屏幕保護程序,其中包含了非常酷的屏保特效,我目前使用的是3D駭客帝國;
- 類似於Windows的底部工具欄:perlpanel
- shutter:截屏工具
- amor:屏幕寵物玩具
- workrave:定時休息、活動提醒工具,用於緩解視疲勞,身體疲勞
- xclock:桌面模擬或數字時鍾
- knotes:桌面即時貼
相關配置代碼如下:
;; Define startup programs (setq startup-programs '( ;; Start ibus input method: -x option starts ibus XIM server, -r option ;; replaces existing daemon. In addition, the following environment ;; variables should be set, otherwise, KDE programs cannot use ibus input ;; method. ("ibus-daemon" "-xrd") ;; Start wicd network manager ("wicd-gtk" "-t") ;; Enable touchpad tapping ("enable_tapbutton.sh") ;; Start screensaver ("xscreensaver" "-no-splash") ;; Start panel ("perlpanel") ;; Start Shutter for taking snapshots ("shutter") ;; Start amor toy: white kitty ("amor") ;; Start xclock ("xclock") ;; Start knotes ("knotes") ;; Start workrave ("workrave"))) ;; Execute startup programs one by one (mapc (lambda (program) (apply start-process (make-process standard-output) program)) startup-programs) ;; Make sure active processes are killed before sawfish exits (add-hook 'before-exit-hook (lambda () (mapc stop-process (active-processes))))
3. 音量控制:目前音量控制綁定的快捷鍵如下
- Win+]:運行volume-up-by-ratio,增加音量1%
- Win+[:運行volume-down-by-ratio,減小音量1%
- Win+\:運行toggle-volume-mute,在當靜音與當前音量間切換
其所關聯的Sawfish函數會調用amixer命令來完成指定的操作。具體可以查閱amixer相關幫助。Sawfish代碼如下:
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; System sound volume related variables and functions ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (setq max-volume (string->number (getenv "MAX_SOUND_VOLUME"))) (setq min-volume 0) (setq current-left-volume 0) (setq current-right-volume 0) (setq left-volume-before-mute 0) (setq right-volume-before-mute 0) (setq volume-adjust-ratio-step 0.01) (setq toggle-mute-flag nil) ;; Get volume for both left and right channels and store them into variables (defun get-volume() "Get the volume string" (interactive) (let* ((res-stream (make-string-output-stream)) (proc (make-process res-stream)) (res-str) (res-str-splitted)) (call-process proc nil "/usr/local/bin/scripts/get_volume.sh") (setq res-str (get-output-stream-string res-stream)) (setq res-str-splitted (string-split "," (substring res-str 0 (- (length res-str) 1)))) (setq current-left-volume (string->number (nth 0 res-str-splitted))) (setq current-right-volume (string->number (nth 1 res-str-splitted))))) (get-volume) ;; Get volume percentage string (defun get-volume-percentage-str (vol) "Get the percentage of the specified volume quantity in string format" (interactive) (concat (number->string (round (* (/ vol max-volume) 100))) "%")) ;; Set volume by ratio (defun set-volume-by-ratio (lft-vol rt-vol) "Set volume by percentage" (interactive) (system (concat "amixer cset " (getenv "DEFAULT_SOUND") " " (number->string (* max-volume lft-vol)) "," (number->string (* max-volume rt-vol)) " &")) (get-volume)) ;; Set volume by value (defun set-volume-by-value (lft-vol rt-vol) "Set volume by value" (interactive) (system (concat "amixer cset " (getenv "DEFAULT_SOUND") " " (number->string lft-vol) "," (number->string rt-vol) " &")) (get-volume)) ;; Increase volume by ratio (defun volume-up-by-ratio (vol) "Increase volume by ratio" (interactive) (let ((tmp-lft-vol) (tmp-rt-vol)) (get-volume) (setq tmp-lft-vol (+ current-left-volume (* max-volume vol))) (setq tmp-rt-vol (+ current-right-volume (* max-volume vol))) ;; Detect if the volume is larger than max-volume (if (> tmp-lft-vol max-volume) (setq tmp-lft-vol max-volume)) (if (> tmp-rt-vol max-volume) (setq tmp-rt-vol max-volume)) (set-volume-by-value tmp-lft-vol tmp-rt-vol))) ;; Decrease volume by ratio (defun volume-down-by-ratio (vol) "Decrease volume by ratio" (interactive) (let ((tmp-lft-vol) (tmp-rt-vol)) (get-volume) (setq tmp-lft-vol (- current-left-volume (* max-volume vol))) (setq tmp-rt-vol (- current-right-volume (* max-volume vol))) ;; Detect if the volume is smaller than min-volume (if (< tmp-lft-vol min-volume) (setq tmp-lft-vol min-volume)) (if (< tmp-rt-vol min-volume) (setq tmp-rt-vol min-volume)) (set-volume-by-value tmp-lft-vol tmp-rt-vol))) ;; Mute volume (defun volume-mute () "Mute system sound" (interactive) (set-volume-by-value min-volume min-volume)) ;; Unmute volume (defun volume-unmute () "Unmute system sound" (interactive) (set-volume-by-value left-volume-before-mute right-volume-before-mute)) ;; Full volume (defun volume-max () "Set to max sound volume" (interactive) (set-volume-by-value max-volume max-volume)) ;; Toggle mute (defun toggle-volume-mute () "Toggle between current sound volume and mute" (interactive) (get-volume) (if (and (= current-left-volume min-volume) (= current-right-volume min-volume)) (if toggle-mute-flag (progn (volume-unmute) (setq toggle-mute-flag nil) (display-close-message (concat "Sound restored to L:" (get-volume-percentage-str current-left-volume) " R:" (get-volume-percentage-str current-right-volume)) alert-msg-short-time alert-msg-attrib))) (progn (setq left-volume-before-mute current-left-volume) (setq right-volume-before-mute current-right-volume) (volume-mute) (setq toggle-mute-flag t) (display-close-message "Mute" alert-msg-short-time alert-msg-attrib)))) ;; Increase sound volume (bind-keys global-keymap "Super-]" `(progn (volume-up-by-ratio volume-adjust-ratio-step) (display-close-message (concat "Volume L:" (get-volume-percentage-str current-left-volume) " R:" (get-volume-percentage-str current-right-volume)) alert-msg-short-time alert-msg-attrib))) ;; Decrease sound volume (bind-keys global-keymap "Super-[" `(progn (volume-down-by-ratio volume-adjust-ratio-step) (display-close-message (concat "Volume L:" (get-volume-percentage-str current-left-volume) " R:" (get-volume-percentage-str current-right-volume)) alert-msg-short-time alert-msg-attrib))) ;; Toggle sound mute and unmute (bind-keys global-keymap "Super-\\" `(toggle-volume-mute))
以上代碼中還用到了自己編寫的腳本get_volume.sh用於獲取系統當前音量,具體如下:
#!/bin/bash amixer cget $DEFAULT_SOUND | gawk '{if(match($0, /values=([[:digit:]]+,[[:digit:]]+)/, res) != 0) print res[1];}'
4. 關閉與激活屏幕保護程序:看電影的時候就不要啟動屏保了,所以需要這樣的功能。綁定的快捷鍵為Win+p。相關配置如下。
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; xscreensaver related variables and functions ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (setq xscreensaver-enabled t) (defun enable-xscreensaver () "Enable xscreensaver" (interactive) (system "exec /usr/bin/xscreensaver -no-splash &") (setq xscreensaver-enabled t)) (defun disable-xscreensaver () "Disable xscreensaver" (interactive) (system "exec /usr/bin/xscreensaver-command -exit &") (setq xscreensaver-enabled nil)) (defun toggle-xscreensaver-activation () "Activate/deactivate xscreensaver" (interactive) (if xscreensaver-enabled (disable-xscreensaver) (enable-xscreensaver))) (bind-keys global-keymap "Super-p" `(progn (toggle-xscreensaver-activation) (if xscreensaver-enabled (display-close-message "Screensaver enabled!" alert-msg-short-time alert-msg-attrib) (display-close-message "Screensaver disabled!" alert-msg-short-time alert-msg-attrib))))
5. 關閉與激活觸控板按鈕(僅對筆記本電腦有效),快捷鍵為Win+z。相關配置如下:
;; ;;;;;;;;;;;;;;;;;;;; ;; Touchpad operation ;; ;;;;;;;;;;;;;;;;;;;; (setq tapbutton-enabled t) ;; Toggle tap button function of the touchpad (bind-keys global-keymap "Super-z" `(progn (system "toggle_tapbutton.sh &") (setq tapbutton-enabled (not tapbutton-enabled)) (if tapbutton-enabled (display-close-message "Tap button enabled!" alert-msg-short-time alert-msg-attrib) (display-close-message "Tap button disabled!" alert-msg-short-time alert-msg-attrib))))
其中調用了自己編寫的腳本程序toggle_tapbutton.sh與enable_tapbutton.sh,其內容分別為:
#!/bin/bash script_name="toggle_tapbutton.sh" script_usage=$(cat <<EOF $script_name EOF ) script_function=$(cat <<EOF This script is used to disable/enable the finger tap function of Synaptics touchpad. EOF ) script_doc=$(cat <<EOF -h Display this help. EOF ) script_examples=$(cat <<EOF EOF ) state_prefix="===" warning_prefix="***" error_prefix="!!!" function display_help() { if [ -n "$script_usage" ]; then echo -e "Usage: $script_usage" fi if [ -n "$script_function" ]; then echo -e "$script_function" fi if [ -n "$script_doc" ] ; then echo -e "\n$script_doc" fi if [ -n "$script_examples" ]; then echo -e "\nExamples" echo -e "$script_examples" fi } # Process command options while getopts ":h" opt; do case $opt in h ) display_help exit 0 ;; \? ) display_help exit 1 ;; esac done shift $(($OPTIND - 1)) # Start execute the command if [ $OSTYPE = 'linux-gnu' ]; then tap1=`synclient -l | grep TapButton1 | cut -d '=' -f 2 | tr -d [:space:]` tap2=`synclient -l | grep TapButton2 | cut -d '=' -f 2 | tr -d [:space:]` tap3=`synclient -l | grep TapButton3 | cut -d '=' -f 2 | tr -d [:space:]` if [ "$tap1" = "0" ] && [ "$tap2" = "0" ] && [ "$tap3" = "0" ]; then enable_tapbutton.sh else disable_tapbutton.sh fi exit 0 fi echo "$warning_prefix Operating system or host name is not supported!"
#!/bin/bash script_name="enable_tapbutton.sh" script_usage=$(cat <<EOF $script_name EOF ) script_function=$(cat <<EOF This script is used to enable the finger tap function of Synaptics touchpad. EOF ) script_doc=$(cat <<EOF -h Display this help. EOF ) script_examples=$(cat <<EOF EOF ) state_prefix="===" warning_prefix="***" error_prefix="!!!" function display_help() { if [ -n "$script_usage" ]; then echo -e "Usage: $script_usage" fi if [ -n "$script_function" ]; then echo -e "$script_function" fi if [ -n "$script_doc" ] ; then echo -e "\n$script_doc" fi if [ -n "$script_examples" ]; then echo -e "\nExamples" echo -e "$script_examples" fi } # Process command options while getopts ":h" opt; do case $opt in h ) display_help exit 0 ;; \? ) display_help exit 1 ;; esac done shift $(($OPTIND - 1)) # Start execute the command if [ $OSTYPE = 'linux-gnu' ]; then synclient TapButton1=3 synclient TapButton2=1 synclient TapButton3=2 echo "$state_prefix Finger tapping on touchpad has been enabled!" exit 0 fi echo "$warning_prefix Operating system or host name is not supported!"
6. 窗口與桌面操作函數與快捷鍵:其中一些功能是Sawfish自帶的,直接在設置對話窗口中綁定即可。
- Win+e:顯示當前窗口信息,包括名稱、大小、位置、組編號
;; Display window position and dimension (defun display-window-paras () "Display the position, dimension and group ID of the current window." (interactive) (let* ((cur-win (input-focus)) (win-width (car (window-dimensions cur-win))) (win-height (cdr (window-dimensions cur-win))) (win-x (car (window-position cur-win))) (win-y (cdr (window-position cur-win)))) (display-message (concat "Name: " (window-name cur-win) "\n" "Dimension: " (number->string win-width) "x" (number->string win-height) "\n" "Position: " (number->string win-x) "x" (number->string win-y) "\n" "Group ID: " (number->string (window-actual-group-id cur-win))) alert-msg-attrib))) (bind-keys window-keymap "Super-e" `(display-window-paras))
- Win+c:將窗口放置於屏幕(Screen)中心。其中調用了current-head-dimension與current-head-offset,所以可以支持多個顯示器。
;; Center to screen (defun center-to-screen (cur-win) "Center the current window to the current screen" (interactive "%f") (let* ((screen-width (car (current-head-dimensions cur-win))) (screen-height (cdr (current-head-dimensions cur-win))) (screen-x (car (current-head-offset cur-win))) (screen-y (cdr (current-head-offset cur-win))) (win-width (car (window-dimensions cur-win))) (win-height (cdr (window-dimensions cur-win))) (win-x (car (window-position cur-win))) (win-y (cdr (window-position cur-win)))) ;; Adjust x position (if (>= win-width screen-width) (setq win-x screen-x) (setq win-x (round (+ (/ (- screen-width win-width) 2) screen-x)))) ;; Adjust y position (if (>= win-height screen-height) (setq win-y screen-y) (setq win-y (round (+ (/ (- screen-height win-height) 2) screen-y)))) ;; Modify window position (move-window-to cur-win win-x win-y)))
- Win+f:顯示與隱藏窗口邊框。在一些電影上可以看到黑客用的電腦程序沒有窗口邊框。
;; Toggle window type between default and unframed (defun toggle-window-frame (cur-win) "Toggle window type between default and unframed" (interactive) (if (= (window-type cur-win) 'unframed) (set-window-type cur-win 'default) (set-window-type cur-win 'unframed))) (bind-keys window-keymap "Super-f" `(toggle-window-frame (input-focus)))
- Win+Ctrl+1~9:將窗口添加到指定組,這就像是在玩星際編隊。
;; Window group related functions (bind-keys window-keymap "Super-C-1" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 1)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-2" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 2)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-3" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 3)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-4" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 4)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-5" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 5)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-6" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 6)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-7" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 7)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-8" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 8)) alert-msg-time alert-msg-attrib)))) (bind-keys window-keymap "Super-C-9" `(progn (let ((cur-win (input-focus))) (add-window-to-group cur-win 1) (display-close-message (concat "Window " (window-name (input-focus)) " added to group " (number->string 9)) alert-msg-time alert-msg-attrib))))
- Win+i:最小化窗口
(defun iconify-current-group (cur-win) "Iconify current window group" (interactive "%f") (iconify-group cur-win))
- Win+m:在最大化與窗口當前大小間切換
- Win+Shift+v:將窗口在垂直方向上放大
- Win+Shift+h:將窗口在水平方向上放大
- Win+k:殺掉當前窗口
- Win+t:在窗口提升一層與下降一層間切換
- Win+d:顯示桌面
- Win+s:在窗口正常狀態與收起狀態間切換。所謂的收起即將窗口內容隱藏,只剩下標題欄
- Ctrl+Alt+left, right, up, down:在四個桌面間切換
- Win+left, right, up, down:讓當前窗口向不同方向移動直至碰到屏幕邊界或另一個窗口的邊界
- Win+w:顯示所有桌面菜單
- Win+SPC:顯示當前窗口菜單
- Win+r:顯示Sawfish桌面右鍵菜單
- Win+a:顯示系統應用菜單
- Win+TAB:在窗口間循環
- Win+Ctrl+TAB:在窗口間反向循環
- Win+l:顯示窗口列表菜單
- Win+`:執行Sawfish函數
- Ctrl+Alt+r:重啟Sawfish
- Ctrl+Alt+q:退出Sawfish
7. 顯示筆記本電池信息:調用了acpi命令,快捷鍵為Win+b,代碼如下:
;; Display batter information by calling acpi (defun display-batter-info () "Display batter information by calling acpi" (interactive) (let* ((res-stream (make-string-output-stream)) (proc (make-process res-stream)) (res-str)) (call-process proc nil "acpi" "-i" "-b") (setq res-str (get-output-stream-string res-stream)) (display-message res-str alert-msg-attrib))) (bind-keys global-keymap "Super-b" `(display-batter-info))
8. 添加窗口hook(before-add-window-hook)對符合匹配條件的窗口賦以特殊屬性,如令其不顯示在窗口循環列表中、自啟動后保持最大化、指定窗口初始大小、將窗口固定顯示在桌面某個位置等。需要用到正則表達式模塊rep.regexp匹配字符串,以及sawfish.wm.commands.groups和sawfish.wm.frames模塊獲取窗口屬性。相關配置如下:
(require 'rep.regexp) (require 'sawfish.wm.commands.groups) (require 'sawfish.wm.frames) (defun get-wm-window-type (win) "Get the _NET_WM_WINDOW_TYPE property of a window" (interactive) (aref (nth 2 (get-x-property win '_NET_WM_WINDOW_TYPE)) 0)) (defun get-wm-property (win prop) "Get the x window property of a window" (interactive) (nth 2 (get-x-property win prop))) ;; Set LibreOffice Impress window property ;; Remove window frame of LibreOffice Impress window when it is in fullscreen ;; presentation. (add-hook 'before-add-window-hook (lambda (w) (if (and (string-match "^soffice" (get-wm-property w 'WM_CLASS)) (= (get-wm-window-type w) '_NET_WM_WINDOW_TYPE_NORMAL)) (set-window-type w 'unframed))) t) ;; Set FreeRDP window property (add-hook 'before-add-window-hook (lambda (w) (if (string-match "^FreeRDP" (get-wm-property w 'WM_NAME)) (progn (set-window-type w 'unframed)))) t) ;; Set xclock window property (add-hook 'before-add-window-hook (lambda (w) (if (string-match "^xclock$" (get-wm-property w 'WM_NAME)) (progn (mark-window-as-dock w) (window-put w 'task-list-skip t) (set-window-type w 'unframed)))) t) ;; Set Audacious window property (add-hook 'before-add-window-hook (lambda (w) (if (string-match "[aA]udacious" (get-wm-property w 'WM_NAME)) (progn (mark-window-as-desktop w) (window-put w 'task-list-skip t)))) t) ;; Set Workrave window property (add-hook 'before-add-window-hook (lambda (w) (if (and (string-match "[wW]orkrave" (get-wm-property w 'WM_CLASS)) (string-match "[wW]orkrave" (get-wm-property w 'WM_NAME))) (progn (mark-window-as-dock w) (window-put w 'task-list-skip t)))) t) ;; Set full-window online video window property (played in Iceweasel) (add-hook 'before-add-window-hook (lambda (w) (if (string-match "plugin-container" (get-wm-property w 'WM_NAME)) (progn (maximize-window-fullscreen w))))) ;; Set Wesnoth full-window property (add-hook 'before-add-window-hook (lambda (w) (if (string-match "The Battle for Wesnoth" (get-wm-property w 'WM_NAME)) (progn (set-window-type w 'unframed) (move-window-to w 1280 0)))))
總結
由本文介紹可以看出,通過將GNU/Linux下不同的工具組合起來,如startx、Sawfish、xmodmap、amixer等,便可以實現節省系統資源、高效、方便的桌面操作環境。