首頁 > 軟體

我在GNU/Linux下使用的桌面環境工具組合

2020-06-16 17:51:54

為了使GNU/Linux桌面環境下載入的程式較少以節省記憶體資源和提高啟動時間,我目前並不使用重量級的桌面環境KDE和Gnome,甚至連登入窗介面gdm或xdm都不用,而是直接啟動到控制台,登入後呼叫startx進入X視窗環境。所使用的工具組合列舉如下:

  1. X視窗環境啟動:startx
  2. 視窗管理器:Sawfish
  3. amixer:系統音量設定
  4. 鍵盤與滑鼠設定:xmodmap
  5. 網路管理器:wicd(需刪除NetworkManager)
  6. xscreensaver:螢幕保護裝置
  7. 類似於Windows的底部工具列:perlpanel
  8. shutter:截圖工具
  9. amor:螢幕寵物玩具
  10. workrave:定時休息、活動提醒工具,用於緩解視疲勞,身體疲勞
  11. xclock:桌面模擬或數位時鐘
  12. 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載入單張桌布。具體內容參見這裡 http://www.linuxidc.com/Linux/2015-10/123910.htm

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模組。有了這個功能,則無需頻繁地使用滑鼠在不同的視窗間切換了,非常方便。目前,我繫結的快捷鍵如下:

  1. Win+1:命令列終端程式Konsole;
  2. Win+2:檔案管理器Dolphin;
  3. Win+3:文字編輯器Emacs;
  4. Win+4:多國語言電子詞典Stardict或Goldendict;
  5. Win+5:網頁瀏覽器Iceweasel,它是Mozilla Firefox在Debian下的名稱;
  6. Win+6:郵件用戶端(亦是RSS閱讀器、日曆、任務管理,類似於微軟的Outlook)Icedove,它是Mozilla Thunderbird在Debian下的名稱;
  7. Win+7:辦公軟體LibreOffice;
  8. Win+8:圖片、照片瀏覽器Gwenview。該軟體比Windows下的圖片檢視器好很多:可以看GIF動畫,亦可以直接看視訊;
  9. Win+9:音訊播放器Audacious,播放無失真音樂ape、flac的不二之選;
  10. 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等,便可以實現節省系統資源、高效、方便的桌面操作環境。

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-10/123909.htm


IT145.com E-mail:sddin#qq.com