我在GNU/Linux下使用的桌面环境工具组合
为了使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=,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=
# 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=
export DEFAULT_RSOUND_VOLUME_PERCENTAGE=
# 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 / ))
export DEFAULT_RSOUND_VOLUME=$(($MAX_SOUND_VOLUME * $DEFAULT_RSOUND_VOLUME_PERCENTAGE / ))
# 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 -w -h -x -y $picture/wallpapers/sunflower.jpg &
set_multi_wallpapers.sh -t &
# Set the default sound volume
amixer cset numid=,iface=MIXER,name='Master Playback Volume' $DEFAULT_LSOUND_VOLUME,$DEFAULT_RSOUND_VOLUME &
# Play welcome sound: Steve Jobs' speech
if [ "$STARTX_INIT_SOUND" = ]; 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=
synclient PressureMotionMaxZ=
fi # Start window manager
sawfish --display=:
针对以上代码解释如下:
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 ;;
\? ) display_help
exit ;;
esac
done
shift $(($OPTIND - )) # Start execute the command
if [ $OSTYPE = 'linux-gnu' ]; then
tap1=`synclient -l | grep TapButton1 | cut -d '=' -f | tr -d [:space:]`
tap2=`synclient -l | grep TapButton2 | cut -d '=' -f | tr -d [:space:]`
tap3=`synclient -l | grep TapButton3 | cut -d '=' -f | tr -d [:space:]` if [ "$tap1" = "" ] && [ "$tap2" = "" ] && [ "$tap3" = "" ]; then
enable_tapbutton.sh
else
disable_tapbutton.sh
fi exit
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 ;;
\? ) display_help
exit ;;
esac
done
shift $(($OPTIND - )) # Start execute the command
if [ $OSTYPE = 'linux-gnu' ]; then
synclient TapButton1=
synclient TapButton2=
synclient TapButton3=
echo "$state_prefix Finger tapping on touchpad has been enabled!" exit
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等,便可以实现节省系统资源、高效、方便的桌面操作环境。
我在GNU/Linux下使用的桌面环境工具组合的更多相关文章
- GNU/Linux下Freeplane的界面渲染问题
如下图所示,思维导图软件Freeplane在GNU/Linux下默认的界面渲染效果是很差的,即便将Preferences → Appearance → Antialias设置为Antialias al ...
- 在GNU/Linux下将CD音乐转为mp3
以前我欣赏古典音乐都是听的CD,因而珍藏了不少光盘以及下载到电脑上的ape与flac格式的音乐文件.随着手机硬件性能(如电池续航能力.处理器速度.音质.存储容量等)和软件功能(音乐播放器对于曲目的管理 ...
- LibOpenCM3(一) Linux下命令行开发环境配置
目录 LibOpenCM3(一) Linux下命令行开发环境配置 本文使用 Linux 环境, 硬件为 STM32F103 系列开发板 LibOpenCM3 介绍 LibOpenCM3 是GPL协议( ...
- Linux下配置PHP开发环境
转载于: http://www.uxtribe.com/php/405.html 该站下有系列PHP文章. 在Linux下搭建PHP环境比Windows下要复杂得多.除了安装Apache,PHP等软件 ...
- (转)Linux下设置和查看环境变量
原文地址:<Linux下设置和查看环境变量> Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1. 永久的:需要修改配置文件,变量永久生效. 2. 临时的:使用e ...
- linux下搭建python机器学习环境
前言 在 linux 下搭建 python 机器学习环境还是比较容易的,考虑到包依赖的问题,最好建立一个虚拟环境作为机器学习工作环境,在建立的虚拟环境中,再安装各种需要的包,主要有以下6个(这是看这个 ...
- Windows10下配置Linux下C语言开发环境
今天为大家介绍如在Windows10下配置Linux下C语言开发环境,首先安装linux子系统:启用开发者模式 1.打开设置 2.点击更新和安全3.点击开发者选项 4.启用开发人员模式 5.更改系统功 ...
- windows和linux下 Python2,Python3 的环境及安装
目录 windows和linux下 Python2,Python3 的环境及安装 window下安装 一. 手动安装 二. pip安装 linux下 安装 更新Python 笔者有话 windows和 ...
- linux下安装lnmp集成环境
linux下安装lnmp集成环境 教程地址:https://www.cnblogs.com/peteremperor/p/6750204.html 必须要用root用户,否则权限不够无法安装 安装最新 ...
随机推荐
- 随机生成n个不相等的随机数
在计算机视觉中,(例如8点算法)经常用到RANSAC算法在N个数据中找到最合适的一组n(n<N)个数据对,使某项指标达到最大.解决这个问题需要随机的在N个数据对中采样.本文实现一种线性的,复杂度 ...
- Exchange 2016 创建日程,远程服务器返回错误: (401) 未经授权
背景:在测试环境中一切正常,使用的是Exchange2013,上生产环境Exchange2016,部署后产生如下错误: Microsoft.Exchange.WebServices.Data.Serv ...
- Ubuntu环境搭建1
Ubuntu环境搭建(一) 其实每次重装Ubuntu系统的时候都要进行一次基本到环境配置,而且每次总会忘记一些环境配置到东西,所以就写下这个博文,方便自己以后重装系统的时候回顾,同时也给大家做为重装系 ...
- 仿腾讯微博的一个弹出框 v0.1 beta
仿腾讯微博的一个弹出框 v0.1 beta 代码写的不太好,新手请大家海涵,只为博君一笑,勿放在心上. 写在这里留作纪念,也许以后用的到. 效果 CSS .prompt{ position: ab ...
- Linux学习之系统的构建
实验环境:ubuntu 12.04 LTS 内核版本:linux-3.9.4 因为一直以来都对Linux的工作机理比较感兴趣,所以正好这两天有机会好好的研究一下,那闲话不多说,直接进入正题. 俗话说的 ...
- Nginx之旅系列 - Nginx日志功能 PK Linux内核printk
题记:Nginx之旅系列是用来记录Nginx从使用到源码学习的点点滴滴,分享学习Nginx的快乐 Nginx 首页: http://nginx.org/ Nginx日志功能 PK Linux内核pri ...
- C++malloc,calloc,realloc,free函数
在进行C/c++编程的时候,需要程序员对内存的了解比较清楚,经常需要操作的内存可分为下面几个类别: 1.堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等, ...
- java中的instanceof
instanceof是Java.php的一个二元操作符(运算符),和==,>,<是同一类东西.由于它是由字母组成的,所以也是Java的保留关键字.它的作用是判断其左边对象是否为其右边类的实 ...
- [nodejs,expressjs,angularjs2] LOL英雄列表数据抓取及查询显示应用
新手练习,尝试使用angularjs2 [angularjs2 数据绑定,监听数据变化自动修改相应dom值,非常方便好用,但与传统js(jquery)的使用方法会很不同,Dom操作也不太习惯] 应用效 ...
- Python wifi掉线重连接
原理很简单,通过python执行dos命令 : ping 和 netsh 需要用到os和time模块 代码如下: >>> import os >>> print ' ...