LinuxSir.Org

LinuxSir.Org (http://www.linuxsir.org/bbs/index.php)
-   Linux 基础建设讨论专版 (http://www.linuxsir.org/bbs/forumdisplay.php?f=31)
-   -   X Window 系统使用指南(转贴) (http://www.linuxsir.org/bbs/showthread.php?t=95059)

freesky64 04-03-15 12:43

第16章 实际的使用Resource
本文出自: 作者:cuteyu 整理 (2001-10-09 10:00:00)
前一章解释X resources的规则----为什麽需要它们,结构如何工作和
resource规格的格式。本章中继续讨论resources ,但较强调实用性:我们告
诉你如何及何处设定resources 预设值,来影响你的系统的一部份或全部。在
本章结束前,我们将完成一些□例,点出你可能常见的错误,并告诉你如何克
服它们。

在这些□例中,我们假设你自己的工作站叫做venus ,并且大部份时间你
是使用它。从venus 的显示器,你可在远方的机器saturn和mars上执行client
应用程式且和venus 共享档案系统;neptune 则不可,我们曾在第4章描述过。

当你在本章中时,记得resource结构是:传递资讯给应用程式,通常这些
资讯是用来传递一些比较感兴趣的预设值(例如色彩和字型),但只要应用程
式取得协调你就能使用这种设施传递任何资讯。所以我们一般状况下倾向於把
”resource规格””预设值”(defaults)”resource”这三个名词视为同一含
意。


16.1 在何处储存resource的预设值

在上一章我们只告诉你输入resource规格到”一个资料库”,但未告诉你
如何做。事实上有几个不同的地方可以储存预设值:这些”地方”通常是一个
你可以用任何编辑器修改的简单的文字档案,但有一个特殊的位置需要特殊的
工具来设定它,我们先很快的给你一个概念,再讨论细节部份。

首先它的架构非常的复杂:包含命令列选项总共有八种设定resource方法,
但有两个重点需要注意:

1 .你最好只使用其中的一或二种设置,只要你做完启始设定,你将只
须改变预设的设定。

2 .系统是被设计来掌握许多不同模式的工作,和满足那些在许多显示器
上工作或在一台显示器上工作而存取远方机器的使用者的。

总结来说,这些设置是提供来让系统尽可能富於*性,但任何时刻你将只
须存取其中的子集合而已。


16.1.1 设定Resource的八种方法

总共有八种方法设定resource,但它们可分为下面几类:

.应用程式专属的(Application-specific)resource:resource的表列,
限定档案只能被特定的应用程式读取。

.Server专属的resource:应用设定,不管应用程式在那一种主机上执行。

.主机专属的设定(Host-specific-setting) :对应用程式在主机上执行
有关的设定,和显示器无关。

.命令列选项:在执行时期做一次关闭(one-off) 设定。

应用程式专属的resource -- 方法1 和方法2

Toolkit 程式初始时在和应用程式直接相关的两个档案中寻找resource,
这些档案只能被特定的应用程式读取:

1 .应用程式--类别(Application-class) resource档案:这个档案包含
了机器一般性(site-wide) 对应用程式的类别之预设值,通常为系统
管理者所设定。它的名称就是应用程式类别的名称,在标准安装的系
统中它是储存在目录/usr/lib/X11/app-defaults 中,例如xterm 的
相关档案为:

/usr/lib/X11/app-defaults/XTerm

在core版中,有一个相关於Xmh 的此种档案,观察此档案可以看所使
用之设定的型态。

2 .你自己拥有的应用程式专属的resource档案:这个档案的名称和上述
相同,但它存放在不同的地方----由shell 变数$XAPPLRESDIR所指定
的目录,如果未定义,则放在home目录。例如对Xmh 类别的程式,它
的档案放在下列二者之一:

$XAPPLRESDIR/Xmh
$HOME/Xmh

你可以使用此种档案,处理方法1 中你不喜欢的 site-wide档案使其无
效。

Server专属的Resource -- 方法3 和方法4

这是对你目前工作的Server(显示器)做有关的设定。键盘的设定通常是
server专属的(因为不同的显示器有不同的键盘)。另一个server专属的特徵
为显示器是彩色或单色。

Resource和这些有关的项目会被所有与这个终端机相关的应用程式应用到,
并且不论应用程式在何主机上执行。(例如,如果你使用的显示器为单色,则
不管你的应用程式在何处执行,你还是不会要它使用彩色。)

储存server专属设定的方法是:

3 .server的RESOURCE_MANAGER性质(property):(你可在12章中xprop
的输出看到),使用下述的xrdb程式,你可以在server的根视窗的
RESOURCE_MANAGER性质中储存resource设定。它的优点如下:

(a) 你不需编辑任何档案即可设定预设值。(当你为了了解系统而实
验系统时特别有用)

(b) resource被server掌握,所以不论应用程式在那一部主机上执行,
均能被所有的应用程式应用。在我们的□例中,在neptune 的
情况下特别有用,甚至在不和我们的显示机器venus 共享档案系
统时,它仍然自动地选出为了使用此显示器所必需的resource设定。

4 .你的$HOME/.Xdefaults档案:(只有在根视窗没有RESOURCE_MANAGER
性质定义的情况下使用)。如果你对xrdb尚不熟悉,你便可以此档取
代,但你必须在每一部你执行client应用程式的机器上均设定一个。

主机专属设定 -- 方法5 和方法6

主机专属预设值和server专属相反,不管应用程式所使用机器的终端机为
何,只要应用程式在此主机上执行,均使用主机专属预设值,你可以用它们来:

.让应用程式在不同的机器上对不同的档案系统作计算,例如:被一个应
用程式读取的资料档案可能在不同的主机上保持不同的位置。

.区分显示在同一个萤幕上不同的主机的视窗(这些视窗可能由同一个应
用程式执行),例如:你可以要所有在mars机器上执行的xterm 的视窗
为红色的边框,而在saturn上执行的视窗为黄边。

.调高一个相同的应用程式在不同的client机器上版本的差异,例如:
xterm 在venus 是标准的MIT 版,但在neptune 机器上是由第三集团修
改过以适应机器结构的产品,这两版的xterm 可能并不完全相容。

主机专属Resource储存在:

5 .由$XENVIRONMENT 来的档案名称:如果shell 变数$ENVIRONMENT有被
定义,它会被解释为一个含有resource设定的档案之完整的路径名称。

6 .你的$HOME/.Xdefaults-thishost 档案:(当$XENVIRONMENT 未被定
义时使用)。注意它和我们先前的档案有所不同,它必须附加上主机
名称,例如,如果你在neptune 执行应用程式而在venus 显示(假设
RESOURCE MANAGER性质未定义),则server专属 resource 读取自:

.Xdefaults

而主机专属resource则是:

.Xdefaults-neptune

两者均在neptune 的家目录(home directory)中。

注意:在不同的小节中,我们曾说过类似”server专属resource读取自...”
这可能造成误导:”如果你实际需要,你可以放置任何型态的resource设定到
任何的档案或资料库。”我们真正的意思是你应该放置机器特性或不论甚麽的
resource到任何地方,如果你这样做,你将获得你需要的动作。

命令列选项 -- 方法7 和方法8

最後,你可以藉著命令列选项设定应用程式的值。通常当你设定预设值时
,为的是你不需要使用选项为你的程式作X相关的设定。但你实际上可以用它
们来:

.一次关闭(one-off) ,例如:你暂时性地在萤幕上需要一个极小的xedit。

.为了区别在相同应用程式中各自的成员,你已看过一个这样的例子,当
我们使用命令

xterm -name demo

来设定应用程式的成员名称给demo,将造成以应用程式名称为demo的
resource取代xterm 的resource。

命令列选项分为下列两种:

7 .应用程式专属选项:例如xclock的-chime的xpr 或-scale。

8 .Toolkit 标准选项:所有用到Toolkit 的应用程式均接受一些标准的
命令列选项,我们看过其中的大部份,包括-fg, -bg, -display,
-geometry 等等,标准选项的清单在”X Toolkit Intrinsics ”手
册的2.3 节中。

在其中有一个选项-xrm,重要的足以用一个小节来描述。

Toolkit 标准选项-xrm

大多数一般的resource均能被命令列选项明确地设定,例如你可以用
-bg colour设定视窗背景颜色。但无论如何,有一些resource并没有符合的选
项。为了克服这点,Toolkit 提供一个 "捕捉遗漏" (catch all) 的选项-xrm
(X Resource Manager 缩写)。

-xrm以一个引数当做resource规格,就如同你在预设值档案中输入的相同,
例如:你可以输入:

xclock -xrm "*update:30"



xclock -update 30

是相等的。

在同一命令列你可以使用数次-xrm,但每一次只能包含一个resource规格,
例如:

xclock -xrm "*update:30" -xrm "*chime:on"

-xrm的好处在於你可以用它来设定任何resource供应用程式使用,尤其是
那些和命令列选项不符合的resource。其中一些非常有用的像:

iconX, iconY:视窗表徵图左上角x,y 座标的位置。

iconPixmap:被用来当作视窗表徵图的位元映像的名称,你可以用它
来指定任何的位元映像当作应用程式表徵图。(位元映像
为已有或利用bitmap程式建立。)例如:命令

xedit -iconic -xrm "*IconPixmap:cntr_ptr"\
-xrm "*iconX:500"\
-xrm "*iconY:400"

的意义为将xedit 设定以表徵图开始启始,表徵图的左上角
座标为(500,400) (在大多数的显示器会在萤幕中央),使
用名为cntr_ptr的位元映像来当作表徵图。

backgroundPixmap:设定用一个位元映像当作背景。

borderPixmap:设定以一个位元映像当作视窗的边,例如:

xclock -bw 20 -xrm "*backgroundPixmap: scales"\
-xrm "*borderPixmap: cntr_ptr"

执行xclock,用一个宽达20个像素的边框,视窗的背景为鱼鳞
(fish-scales) 图案,边框则用cntr_ptr的位元映像。

所有的这些resource当然也可用类别指定。(如IconX ,BorderPixmap等等。)

注意:请记住,-xrm只有在程式有用到Toolkit 才可应用。


16.1.2 设定Resource不同方法的摘要

现在我们将如何对一个指定应用程式resource设定的八种方法作一摘要:

应用程式专属resource:它们被两个档案掌握,且仅能被Toolkit 使用,
其中一个档案通常由系统管理者设定,另一个由你自己设定。

server专属的resource:不是存在根视窗的RESOURCE_MANAGER性质中,便
是在你的$HOME/.Xdefaults档案中。

主机专属resource:如果shell 变数$XENVIRONMENT 有定义的话,存在其
所定义的档案中,否则在你的$HOME/.Xdefaults-host 档案。

一次关闭设定:用应用程式的本身命令列选项来设定,和用Toolkit 标准
命令列选项,包含”捕捉遗漏”-xrm.

它们以下列顺序处理:

if (程式使用Toolkit )
读取 /usr/lib/X11/app-defaults/class档案 (1)
读取你的 $HOME/class档案 (2)
if (RESOURCE_MANAGER性质被定义)
处理内含的指定 (3)
else
读取你的$HOME/.Xdefaults档案 (4)
if (shell 变数XENVIRONMENT被定义)
读取所定义名称的档案 (5)
else
读取你的$HOME/.Xdefaults-host 档案 (6)
if (程式使用Toolkit )
处理标准的resource选项,包含-xrm (7)
处理应用程式本身的选项 (8)

现在我们将更详细的看一个较不熟悉的方法 -- 用来储存server本身
resource的方法。


16.2 在Server上储存预设值 -- xrdb

大部份预设值的结构均和档案有关,当应用程式启始时,不同的档案被读
取且其内容被处理,这种方式的缺点为你希望所有的client在一个特定的
server上使用同一组的预设值,但client所执行的机器上如果没有一个共同的
档案系统,你该怎麽办?

答案是在server本身储存预设值。X的性质设施是一个具有一般性目的的
结构。(记住,一个”性质(property)”是一小段已知格式资料的名称,被储
存在server),指定由server根视窗的RESOURCE_MANAGER性质载入,且当应用
程式启始时系统会注意此事。当视窗系统启始时,RESOURCE_MANAGER性质未定
义:如果你要使用这个设施,你必须明确地设定它。

并没有一个一般性的工具来操作一个性质,所以X提供了一个特殊的程式
来处理resource性质,它就是xrdb(the X Resource DataBase 公用程式)。


16.2.1 xrdb能为你做什麽

为了方便起见,本章剩馀的部份,我们只把RESOURCE_MANAGER性质和它的
内容当成”资料库”。

xrdb的功能非常简单,它让你能:

.设定一个新的资料库。

.看目前有那些resource在资料库中。

.在现存的资料库加入一个新的resource。

.完全去除资料库。

这些是基本操作,且很容易完成。当然也有一些更进一步的功能可以很精
确地让你控制resource,但我们先来讨论基本操作。


16.2.2 使用xrdb的基本功能

xrdb的操作类似大多数Unix的程式:它从一个档案或标准输入读取输入资
料,并且你可以用命令列选项来控制它的操作模式,它所读取的输入是我们曾经看
过的一系列resource设定,不过比较特别的是它把这些设定载入资料库,让我们看
一看它主要的功能:

设定一个新的资料库:输入下面命令两者之一:

xrdb filename
xrdb < filename

用以将一个档案中的设定载入到一个资料库中,如果只键入xrdb,表示你将由
标准输入(通常为键盘)直接输入设定,稍後我们将说明xrdb所接受的档案格
式,但现在先把输入resource设定当作和.Xdefaults档案或-xrm引数相同的方
法,例如,你可以用下列的方式定义xclock设定:

venus% xrdb
xclocks*Background: pink
xclock*update: 30
xclock*backgroundPixmap: cntr_ptr
<end-of-file>

通常你用一个档案当作xrdb的输入,也就是说,xrdb从一个档案载入预设
值作为你的视窗系统初始化的一部份。如果你很有经验,直接输入它的设定也
许容易些。

查看现存资料库中的内容,输入命令:

xrdb -query

则xrdb将以明白本文格式(plain text format) 印出资料库的内容(-query可
以缩写为 -q )。

(你可能记得也可以在根视窗用xprop 来看资料库的内容,但xprop 的输
出格式不太灵巧,它给你其它一大堆你不需要的资讯。)

如果需要,你可以抓取xrdb的输出到一个档案,编辑它,更改设定後可再
用它当作xrdb的输入。(下一项功能告诉你一个更好的方法)

注意:查看资料库,你必须使用选项-query。如果你忽略这个选项而只输
入xrdb,将造成会清除资料库,且xrdb在等待你自标准输入键入你
新的设定。

在现存资料库加入新的设定:加入新的设定到资料库且不要破坏原有的设
定,使用命令:

xrdb -merge filename

(-merge可缩写为-m,如果你省略档案名称,xrdb会自标准输入读取。)
xrdb自指定的档案中读取resource设定,并加入现存的资料库中;对於资料库
中已存在的resource,如果有新的设定,旧值会为新值取代,否则则不会变动。

完全移去资料库:如同先前所述,当系统结束时资料库会自动消失,但如
果你在系统仍在执行时移去资料库,使用命令:

xrdb -remove

本节介绍xrdb基本的功能,下一节我们介绍当你熟悉系统时,你可能需要
的更进一步的功能。

16.2.3 xrdb的档案格式

你已知道大多数的格式细节 -- 你可以用标准的resource规格的形式

characteristic: value

上述的格式你已看过多次,但xrdb有两个额外的规则:

1 .注解(comments):每一行的开头如果是惊叹号(!)会被忽略,所以
你可以此当作注解。

2 .xrdb预设将它的输入列传到C 前处理器。

让我们进一步看一看前处理器的过程。

xrdb前处理它的输入列

让我们看一看一个你可能碰到的典型问题。假设在一般的场景,你使用下
列显示器:

venus 彩色萤幕,正常解析度
saturn 单色萤幕,正常解析度
mars 彩色萤幕,高解析度

以上三者共享一个共同网路档案系统,当你在一个显示器上启动X,你需
要定义预设值来反应显示器的特徵。例如:在高解析度萤幕你可能需要较大的
预设字型,或是你不需要在单色系统上定义彩色预设值。

如何做呢?让我们看一看,如果你能使用.Xdefaults-host 档案:在
.Xdefaults-venus我们包含了彩色指定,而在.Xdefaults-saturn 我们只放入
单色型态的参数。行得通吗?当然,但是是有限度的:它只能掌握应用程式在
和server相同的机器上执行,如果应用程式在其它的机器上执行会得到它们主
机上的预设档案。所以如果你使用venus 且在saturn启始远方的client,将会
用到.Xdefault-saturn而错失所有的彩色指定。

你能够只使用.Xdefault 档案来区分机器吗?不能,因为三台主机共享相
同的档案系统,所以$HOME/.Xdefaults会被venus 获得也会被其它的机器获得。

答案是在resource处理程序的某些地方,有一个结构可以分辨出所使用
server的某些特徵。xrdb可以用相当简单的办法做到这点,它先定义一些说明
server特徵的C 前处理器符号,而後将它所有的输入传递到前处理器,最後将
处理过的资料载入资料库。指南页列出所有的xrdb定义的前处理器的符号,但
在此处我们需要用到的是:

X_RESOLUTION=n:n是每公尺长萤幕有多少像素。(根据我们的server,我
们正常解析度的萤幕为每□90个像素,相当於每公尺3454个像素。)

COLOR :只有萤幕支援彩色才被定义。

WIDTH,HEIGHT:萤幕的宽度和高度,单位为像素。

图16-1显示我们如何在xrdb的输入档案使用这些。(我们命名为
$HOME/.Xresources ,稍後我们仍将再度用到。)它可以正确地做到我们所想
要的 -- 它正确掌握了所有我们的显示器,不论是彩色或高解析度或两者都有。

一些要点值得注意:

┌—————————————————————┐
│ P197 FIG 16.1 │
│ │
│ 图16-1 利用前处理器命令的Resource档案 │
└—————————————————————┘

.你可以使用所有前处理器的功能。例如,我们使用它的表示掌握
(expression-handling) 能力:

#if X_RESOLUTION > 3600

.你可以在档案中任何地方使用前处理器符号,并不只是前面有# 号的列,
例如,当

xload*Width: WIDTH

在venus 上xrdb执行到时,它将会读取成:

xload:Width: 1152

所以由预设值可知,xload 视窗宽度将和萤幕宽度相同,高为80个像素,
且在萤幕的正上方。

注意:大多数Unix前处理器定义了一些和它们机器结构与作业系统相关的
符号,这些可能会干扰到你,特别是Unix通常定义的符号,现在
xrdb定义HOST为显示器名称中主机名称的部份,所以你可能认为你
可以像这样使用一个resource规格:

demo*title: X demo using display HOST

比方在venus 上,预期它相当於:

demo*title: X demo using display venus

事实上,在我们的机器上会得到

demo*title: X demo using display 1

原因为显示器名称是unix:0.0,所以主机名称部份为unix,但前处
理器已定义了unix,所以整个解释的顺序为:

HOST -> unix -> 1

你可以用xrdb的-u选项来解除符号的定义,用以克服这点,也就是

xrdb -Unix < filename

但即使如此,主机名称仍为unix,除非你明确地指定显示器:

xrdb -display venus:0 < filename

另一个会产生干扰的□例,如何你输入规格

xedit*Font: *-sun-screen-*

使用xrdb,现在用一个xrdb -query ,你可以看到在资料库中实际
地设定:

xedit*Font: *-1-screen-*

在我们sun 的机器上,前处理器定义成另一个符号。如果你使用和你的机
器相关的名称,你可能也会得到相同的效应。(如果你决定不需要前处理器的
功能,你可以用xrdb的-nocpp选项停止它的功能。)


16.2.4 如何将资料库设定和你的xrdb输入档连接在一起

藉著像前述在一个含有大量前处理器命令的档案执行xrdb,你初始化了资
料库,在稍後的期间,交谈式的使用xrdb,你将对资料库做大量的更动,现在
你需要记录这些设定,且将之与原来的输入档连接,以备将来之用。

如果你只使用xrdb -query ,你只能获得目前的设定:所有在输入档中的
条件指令列若和现在的server不符则不会被包含。例如在saturn上执行前述的
档案,则所有色彩和高解析度的设定,均被忽略(当然以 #开头的也不例外),
为了克服这点,xrdb提供-edit 选项,例如命令:

xrdb -edit myresf

连接目前在资料库中的值到档案myresf内存在的内容,它藉著比对resource指
定特徵值的部份做到这点:如果在档案中某一行和资料库中某一项特徵相同,
则档案中值的部份会被在资料库中的值取代,用此方法,所有的以 #开头的列
和条件设定均会保留在档案中。

注意:前处理器完全不可以使用-edit 选项,那会导致问题,我们看一
下当我们使用venus ,且以前述档案初始化资料库时,会发生什麽
情况,假设我们做了更动:

venus% xrdb -merge
XTerm*font: *-courier-medium-r-*-140-*
<end-of-file>

然後用命令:

xrdb -edit myresf

将设定更改的部份放回档案,我们看到两件事:

1 .前处理器符号在规格中值的部份会被字面(literal)值取代,
例如:

xload*Width: 1152 会被

xload*Width: WIDTH 取代

2 .在规格中只要特性符合,值均会被取代,甚至那些在条件段中
目前尚未应用到的也不例外。例如,在前述档案,设定
XTerm*font的那两行(一行在高解析度那段,一行在正常显示
器那段)都会被更改,即使我们只需要改变正常显示器也不例
外。


16.3 一些常见的错误和如何修正它们

特别是当你对系统是新手的时候,resource看起来相当的复杂。当有些状
况不能正常执行,而系统无法帮助你查觉是什麽错误,或你在何处犯了错误,
这里列出一些常见错误的明细,并提出如何修正它们。

.如果你未设定一个应用程式的名称和类别,确定在你的resource规格之
前加一个星号,(如果你省略这个星号,将没有任何东西会对应这个规
格)这个错误在你使用-xrm时特别常见,例如:

xclock -xrm "update:3" (错误)
xclock -xrm "*update:3" (正确)

.并非所有的应用程式均使用Toolkit ,非Toolkit 的程式不使用类别,
且它们的属性名称也可能不同。例如,规格

*geometry: 300*400+500+600

对xclock,xlogo 有效,但对xcalc 无效,因它不使用Toolkit ,xcalc
使用属性名称Geometry(开头为大写的G ),因为在这种情况,Toolkit
类别名称和xcalc 的属性名称相同,所以单独一个规格

*Geometry: 300*400+500+600

可以对所有这类的应用程式有效。

.你可能在规格中用了错误的属性或Widget的名称,特别是容易把类别名
称和成员名称搞混,例如:以下两者均错:

xclock*Update: 10
xclock*interval: 10

其它常见的错误如:

xterm*Text*background:blue

它不能执行的原因为xterm 并未使用Text widget ,xterm 正常的视窗
和Tektronix 的视窗分别使用widget类别 VT100和Tek 。最後,当你
知道一个widget是什麽类别,你可能对成员名称假设错误,不是widget
本身便是其中之一的属性。试著更换类别名称来修正这个问题。

.即使你已设定实际的widget和属性名称或类别,应用程式可能以不是你
预期的方式使用它们。例如:你可能设定如下:

xterm*Width: 40
xterm*Height: 10

意图用比平常较小的视窗启动xterm ,但它不能执行,xterm 只能在
Tektronix window应用这些值,无法在正常的视窗。

.你可能所有的设定完全正确,但仍然什麽也没发生,例如:

xmh -xrm "*inc.Label: Include"

是一个正确的方式,执行xmh 并指定label 为inc 盒的必须被"Include"。
但在标准系统的发行版,是没有任何动作发生的,原因是xmh 有一个应
用程式设定预设值档案/usr/lib/X11/app-defaults/Xmh ,其中有一行:

xmh*inc.label:Incorporate New Mail

这个规格较我们的设定有较高优先。

.将规格

*Width: 200

单独包含在资料库将导致大多数的Toolkit 程式启始失败,且有一个
讯息说它的"shell widget has zero height or width" 。如果你设定
height和width 二者之一,你必须也设定另外一个。

.如果你用编辑器建立一个resource档案,你可能省略了最後一个new line
这将导致当你试图用xrdb载入它时整个档案均被忽略。为了避免如此,
当载入resource时,用一个命令列像:

xrdb resfile; xrdb -query

如果xrdb无法列印出resfile 中的内容,就是有问题了。

.你可能忘了用-xrm选项的引数来获得resource规格,有时有人会把
resource规格放入一个档案,而以档案名称为-xrm的引数,预期它自此
档案中读取resources。

.最後,一个非常人性的错误,当你发生问题,你通常会循环动作:编辑
resource档案... 储存它... 载入resource到资料库... 执行应用程式
和看一看发生什麽状况。”其中载入resource到资料库”常常会被忽略
以致你更为困惑。

16.4 结论

本章中,你已看过了所有你能设定resource的地方,为何有这麽多种的方
法,如何决定设定放置在何处。你看到如何使用xrdb程式在server实际地储存
预设值,它们在何处被server所有的client存取,甚至它们可以在远方的机器
上执行。最後,有一些关於常见错误的实际提示,告诉你什麽需要注意。

你现在处於实际使用resources ,和剪裁你的系统适合你的口味,resource
结构功能非常强大且有无限的*性,所以它可让你定制任何你需要的事。刚开
始不妨试一些像字型或色彩之类简单的设定,当你熟於基本的结构时,再转到
更高水准的例子。

下一章将告诉你如何使用特别形式的resource规格 -- Translations(转
译),来剪裁你的键盘以适於特别的应用程式。

=====
(http://www.fanqiang.com) 进入【UNIX论坛】

freesky64 04-03-15 12:44

第17章 定制你的键盘和滑鼠 -- 转译
本文出自: 作者:cuteyu 整理 (2001-10-09 12:00:01)
电脑的键盘通常含有一些 "特殊功能" (special function)键,在此有一
些方法来 "制定"(program)这些特殊功能键,使它们能完成特定的功能以适合
你工作的方式。例如,你可以定义一些键来输入那些你常用的命令,或只需按
一个键便能够输入一些程式的片段。

在X中,你能制定的不只是功能键而已,其它一般的键和滑鼠的按钮也都
可制定。对每一个应用程式,你均可指定特别的功能给键盘和滑鼠按钮,或两
者之组合。 (例如在 xedit中你可以结合SHIFT 键和滑鼠的右按钮来让你向前
移动一个单字)。 所有使用X Toolkit的程式均允许使用者利用一个被称之为
键盘转译 (translations) 的设施来执行此种定义,且此种定义藉著正规的
resources 结构传递给应用程式。 (那些不使用X Toolkit的应用程式,同样
地也可以用相同的设施来制定, 但它们需个别的定义所以不能广泛地应用,从
现在起,我们假设每当讨论有关转译的种种,均为对那些使用X Toolkit的应
用程式而言。)

就如同所有的 resources一样,转译是当应用程式执行时才被处置。例如
你可以拥有数个具备不同转译设定的 xedit,在同时一起执行。( 你可以让一
个xedit 适合编辑本文,另一个适合编辑程式码,而另一个适合编辑文书)。

本章讨论转译 -- 包刮它们的定义格式,如何将它们设定到应用程式,和
它们所涵盖功能的□围。我们首先以实例来介绍,逐渐地导引你看到不同的角
度。而後比较正式和详细地讨论转译。最後,我们列出当你使用转译时常会碰
到的错误,并给你一些如何克服这些问题的提示。

17.1 实际使用转译

Toolkit 转译结构最简单的用途便是让你制定你键盘的键。例如,当你使
用xterm 为一个执行一般shell 命令的视窗时,你可能希望定义一些特殊功能
键来输入你常用的命令,且希望指定的关系如下:

当我按下这个键时... 我希望这个字串被输入

F1 rm core *.tmp <newline>

利用Toolkit 达到此目的方法为:指定一个值给使用转译的widget中的resources
。此值设定应用程式中所必需的定制 (customisation),且被Toolkit 的 Trans-
lation Manager (转译管理器) 所处理。此 resources属於类别Translation,
且其成员名称几乎一定是translations。

在下一节我们将看到设定到resources 中的值的格式。

17.1.1 如何对一个应用程式指定转译

对前述xterm 的例子,我们定义 (在即将被应用程式读入的resource资料
库中或一些resource档案中) 一个规格类似:

xterm*VT100*Translations: (contd.)
<key>F1: string("rm core *.tmp") 注意:不完整!!

其意为在任何类别 VT100的 xterm widget 中,当键 F1 被按下时,插入
字串 "rm core *.tmp")。

不幸的是,并没有这麽简单,转译管理器会把上面的规格解释为 "去掉所
有现存的转译,且加入... " ,所以所有正常的像 " A键是插入一个 A" 这种
系结 (binding)都会消失。为了克服这点,你必需使用一些被称为 directive
(指引)的语法插入在 resource 值之前:

xterm*VT100*Translations: #override(contd.)
<key>F1: string("rm core *.tmp")

通常你会希望保持大部份现存的系结,而只是把你明确指定的值覆盖上去
,所以你一般都是在你的转译表中,指定 #override。

现在这个规格可以开始工作了,藉著启始一个 xterm且把此规格 (在两个
单引号 (')中间的部份) 当成选项 -xrm 的引数来测试它:

xterm -xrm 'xterm*VT100*Translations: ... 等等'

按下特殊功能键 F1,你将看到指定的字串成功的插入,但并未包含新列字元
(newline) ,你可以用一点语法的技巧来克服它,像:

xterm*VT100*Translations: #override(contd.)
<key>F1: string("rm core *.tmp")string(0xd)

这解释了以下两点:

1. string()的作用和它的引数相关。你可以直接输入本文 (例如 string(lpq))
,但如果本文包含空白或非字母字元,则必需在本文前後加上双引号。
如果引数是以 "0X" 开头,则将其後解释为十六进位,并插入相对的
ASCII 字元。(例如,0xd是RETURN)

2. 在你指定此功能时可结合一个以上的作用,在上例,我们用到 string()
作用两次,如果我们知道其它的作用,我们也一样可以系结起来。

定义许多的转译在一起

你可以根据需求在一个表中定义许多的转译。假设,我们在前面的转译中增加
系结:

当我按下这个键时... 我希望这个字串被输入

F2 lpq-Plpa3 <newline>

对此的转译为:

<Key>F2: string("lpq-Plpa3")string(0xd)

所以可以将本列加入前面的表中。但是转译管理器的格式规则告诉我们必需将
两个转译以 "\n" 分开且独立成为一列:

xterm*VT100*Translations: #override(contd.)
<key>F1: string("rm core *.tmp")sting(0xd) \n(cond.)
<Key>F2: string("lpq-Plpa3")string(0xd)

以上的形式将造成管理上的困难,你可以藉著包含 "隐藏的新列字元" 来使它
具可读性一些: (新列字元以倒斜线 "\"处理)

xterm*VT100*Translations: #override\n\
<key>F1: string("rm core *.tmp")sting(0xd)\n\
<Key>F2: string("lpq-Plpa3")string(0xd)

你可以放置任意多个你所需的 "隐藏的新列字元" , 且几乎在任何地方均可,
它们只是被忽略而已。 (只要和转译管理器相关,甚至你每隔一个单字便使用
一个也没关系。但千万不要在一个规格的 resource 特徵部份使用它们,它们
无法被resource manager解释,也没有相同的效果。) 如果你感觉有些混淆,
不用担心。简单地说,resource结构需要的是要在一列中的一个resource规格
的 "值" 的部份,而转译管理器以分开的列来分开 (也就是以\n终结),而使用
者刚好以每一个实际分开的列代表一个意义以增加可读性,所以规则很简单:
在除了最後一列的每一个转译列均加上一个 "\n\"。

17.1.2 转译可系结许多型式的作用

上述的 xterm□例,展示了如何能够当你按下一个键时,插入任意的字串。但
转译结构的功能比这更多 -- 它可以系结任何widget所提供的作用到按键,让
我们详细一点地看一下这些作用。

前述的例子,我们在 xterm的 VT100 widget完成了键F1和F2在 string()
上的对应。我们将仍以 xterm为例,说明更多的作用。

查阅xterm 的指南页,在标题KEY TRANSLATIONS 和 KEY/BUTTON BINDINGS
你将发现列有数个作用。我们将定义一个转译对应键F3到insert-selection()
作用之上,所以我们可以用键盘来取代滑鼠,将先前 "剪"下的本文 "贴"出。
指南页告诉我们此作用需要一个引数,从列出的预设系结,我们可以看出预设
的 "剪贴" 结构为使用 CUT_BUFFER0, 所以我们将CUT_BUFFER0当作引数。我们
的resource规格是:

xterm*VT100*Translations: #override\n\
<key>F3: insert-selection(CUT_BUFFER0)

到目前为止,这只是一点小小的便利。然而,假定说你花了许多时间在本文文
件上工作,你用 tbl格式化,你用 nroff在萤幕上预视 (preview)它们,用
troff 排版,且将输出送到你的一个用过滤器 (filter) 为tr2printer的印表
机上。设定转译为:

xterm*VT100*Translations: #override\n\
<key>F3: string("ed") insert-selection(CUT_BUFFER0)\
string(0xd)\n\
<key>F4: string("tbl") insert-selection(CUT_BUFFER0)\
string("| nroff -man") string(0xd)\n\
<key>F5: string("tbl") insert-selection(CUT_BUFFER0)\
string("| troff -man -t | tr2printer") string(0dx)

xterm 会确定这些转译是以xrdb自资料库载入或是在一个resource档案中,并
加以处理。现在当你启始xterm,用滑鼠 "剪"取你所需的工作的档案名称。接
下来,便可按F3键编辑它,按F4键预视它,和按F5键在硬拷贝上排版它。

更多的widget作用□例 -- xbiff

查阅xbiff 的指南页:在ACTIONS 的标题下,你将看到Mailbox widget所支援
作用的名单。它惟一预设的转译为当你按下任何按钮时降下信件 (mail)的旗帜
(flag)(作用unset())。我们将设定转译让你以键盘来运用这些作用,将这些作
用对应到 "?" 和 "UP" "DOWN"两个方向键如下:

? check() 有新的信件吗?
UP set() 升起信件的旗帜
DOWN unset() 降下信件的旗帜

以下是相关的转译表:

xbiff*Mailbox*Translations: #override\n\
<Key>?: check()\n\
<Key>Down: unset()\n\
<Key>Up: set()

以此测试之:用xrdb从你的resource资料库载入这些设定,然後启动xbiff ,
将指标移到视窗内。重复地按下Up和Down游标控制键以升起和降下信件旗
帜。

找出有哪些作用被提供

你对widget作用将和widget名称遭遇相同的问题:如何找出某个widget到底提
供哪些作用以及它们能做些什麽?同样地,没有一个完美的解答,但有一个合
理的方法来处理:

1. 查看应用程式的指南页。大多数的应用程式有它们自己专门的作用文件
。例如:xbiff 有一节叫做ACTION,而xterm 有两节关於转译和作用的
文件 -- KEY TRANSLATIONS 和 KEY/BUTTON BINDING。

2. 最初的指南页可能给你提示,或甚至直接告诉你它用到何种widget的类
别,所以你可以查看它的widget set文件中的特定的widget。(在 core
版中惟一的widget set为Athena,所以你在此不易出错)。即使指南页未
告诉你widget的类别,当你对系统熟悉之後,你将对一个widget是否为
标准型态较具有概念,如果还是不行 ...

3. 查看程式的原始码,看看用到什麽widget的类别,以及widget提供了哪
些作用。

17.1.3 转译系结作用到一序列事件,不只是单一键

我们已经看到转译让你设定插入,转译结构也能让你系结这些作用:它可以是
单一的键,或是一序列的键,或者是事实上一序列任何的X事件。

让我们继续以xbiff 为例,看看如何转译一序列的键盘字元。例如我们定
义字元字串的转译如下:

look check()
raise set()
lower unset()

以下为相关的转译表:

xbiff*Mailbox*Translation: #override\n\
<Key>l,<Key>o,<Key>o,<Key>k: check()\n\
<Key>r,<Key>a,<Key>i,<Key>s,<Key>e: set()
<Key>l,<Key>o,<Key>w,<Key>e,<Key>r: unset()

以此测试之 -- 载入设定和启动xbiff ,将指标移到视窗内。现在你可藉
著输入完整的字串来升起和降下旗帜。例如键入五个字元 r, a, i, s, e以升
起旗帜。对xbiff 的两个表有几点值得说明:

. 键的名称可以用不同的方式指定。正常的印出字元直接指定 (如"<Key>w")
, 其它的字元则拼出全名(如"<Key>Down").附录A "文件指引" 告诉你
在何处**到键的名称,但在本节下面有更简单的方法。

. 对字元字串,你必需一一指定,并以逗点分开
(如"<Key>l,<Key>o,<Key>o,<Key>k").

. 转译可允许相同开头的键,例如 "look" 和 "lower" 均拥有相同的开头
"lo",对转译管理器不会形成问题。

找出键的名称

找出转译所需的键的名称,最简单的方法为执行xev ,将指标移到视窗内,按
下你所需的键,则键的名称会出现在括弧内字串keysym和一个十六进位数之後
。例如在xev 的视窗内按下游标控制键DOWN,它的输出如图17 - 1,在其中你
会看到

(keysym 0xff54, Down)

也就是说,键的名称为Down。

┌————————————————┐
│ P209. fig 17 - 1 │
│ │
│ │
│ │
│ 图 17 - 1 xev 显示键名称的输出 │
└————————————————┘

你可以在转译中使用任何型态的事件

到目前为止,我们所写的转译都是系结作用到一个按下的键盘字元。但我们曾
说过,转译结构可系结作用到任何事件,而不只於按下键盘而已。可能的事件
型态非常的多,在此我们只提及一小部份:

型态 意义

<Key> 按下一个键
<KeyDown> 按下一个键 (只是另一个名称)
<KeyUp> 放松一个键
<BtnDown> 按下一个滑鼠按钮
<BtnUp> 放松一个滑鼠按钮
<Enter> 指标进入视窗内
<Leave> 指标移出视窗外

我们已经使用过按下一个键的事件,让我们系结xbiff 作用到滑鼠按钮以取代之:

xbiff*Mailbox*Translations: #override\n\
<BtnDown>Button1: unset()\n\
<BtnDown>Button2: check()\n\
<BtnDown>Button3: set()

你可以看到语法和前面相似:你先给定一般性的事件型态 (例如 <Key> 或
<BtnDown>),其後跟著你所需事件的事件细节部份 (例如s 和Button3) (
Button 1, 2, 3分别对应到左、中、右按钮)

对一序列的事件的转译

就如同我们定义了一序列按下键事件的转译(set,unset和check),我们当然
也可以定义一序列的滑鼠事件。事实上你转译的一序列的事件可以任意组合在
一起,你可以在一个转译的左边随意混合事件的型态。所以你可以定义如下的
转译表:

xbiff*Mailbox*Translations: #override\n\
<BtnDown>Button1, <Key>?, <BtnDown>Button3: check()\n\
<BtnDown>Button1: <Key>u, <BtnDown>Button3: unset()\n\
<BtnDown>Button1: <Key>s, <BtnDown>Button3: set()

也就是说,用到check(),你必需依序先按下按钮1 (左按钮),然後按下"?"
键 ,最後按下按钮3 (右按钮)。 这个□例并不是很好,但对於一些危险或不
可取消 (irreversible) 的作用 (例如删除一个档案,或是覆写一个缓冲区的
内容) ,你可以依照这种方式来使用转译。你需要使用一个非常谨慎的命令序
列,才能用到此作用,这样使得使用者不可能因意外而输入此命令。

使用非键盘和非滑鼠事件的转译

通常你是对按下或放松滑鼠按钮或键盘的键定义转译。但我们曾经说过,你可
以对任何事件设定转译,例如指标移入或移出一个widget的视窗。让我们以
xman的主选项视窗 (图10 - 3) 为□例来解释它。这是一个相当人为的□例,
因为它没有任何用途。但无论如何,它很容易被看出在做些什麽操作。

查看xman的指南页,在X DEFAULTS标题下,你将看到概括的xman所用到的widget
的名称和类别:主选择项视窗widget的名称叫topBox,类别名为Command。这
是一个好的猜测,因为在选单操作盒的方法。我们可用第15章所提过的技巧
来确认它,使用以下的命令:

xman -xrm "*Command*backgroundPixmap: scales"

且所有的Command widget将会有鱼鳞状的背景)。

这和我们先前的□例有一个重要的不同:我们所用到的作用不是由特定的应用
程式指定,而是由标准的widget提供 (本例中为Command widget,在 "X
Toolkit Athena Widget"使用手册中有描述)。

在我们定义任何东西之前,先来看一看此widget预设的功用,以便我们能
够了解有些什麽事发生和有哪些widget的作用会做。启动xman,移动指标进入
Help 盒,你会看到盒的外框变成高亮度 -- 这是highlight() 在作用。将指
标移出,盒的外框恢复正常 -- 这是unhighlight() 作用。将指标再度移入
Help 盒,按下一个滑鼠按钮,保持按住不放。则盒内的色彩反转 (盒内的文
字变成预设的背景色,而原来视窗的背景变成视窗的前景色)。-- 这是set()
在作用。继续保持按住滑鼠按钮,将指标移出视窗外,盒内色彩恢复正常 --
这是reset() 在作用。一个正常 "碰触一下" (clicking on) Help盒的次序为:

1. 移动指标进入盒中:highlight()将外框变为高亮度。

2. 按下按钮:set() 反转盒中的色彩。

3. 松开按钮:notify()开始作用,造成程式建立求助视窗(help window)
。在进行中时,盒的色彩保持反相。当视窗建立完成之後,reset()反
转盒内的色彩为正常,但外框仍保持高亮度。

4. 将指标移出视窗:unhighlight()将外框恢复正常。

现在你了解了有哪些作用,我们将定义一些转译来改变原先进出视窗的作
用:

*Command*translations: #override\n\
<EnterWindow>: reset()\n\
<LeaveWindow>: set()

用这个奇怪的转译表,当你一开始移动指标进入盒中,什麽事也不会发生,但
当你移出指标时,色彩会反转。如果你再度移动指标进入盒中,色彩会变回正
常。其它的作用和前述相同。

使用修饰键来修饰事件规格

有时你指定的转译希望能同时按下一或多个修饰键 (modifiers) ,例如你要系
结一个作用到和META键同时按下的一个键,或是当CTRL和SHIFT 同时按下的滑
鼠按钮。到目前为止我们还没有任何办法可指定如此。我们不能用事件序列达
成这点,因为它是依序定义的,而我们需要的是指定同时,例如 "按下X 键且
CTRL键同时被按下"。

欲在转译中指定修饰键,你只需在事件名称之前加上你所需的修饰键名。
例如在xterm 中,定义meta-i为 "贴" 上一次 "剪" 的本文,使用:

*VT100*Translations: #override\
Meta <Key>i: insert-selection(PRIMARY, CUT_BUFFER0)

因为这种修饰键/事件型态的组合十分常见,转译管理器允许使用一种缩写的
形式。相等於上面第二列的写法为:

<Meta>i: insert-selection(PRIMARY, CUT_BUFFER0)

我们可以对滑鼠事件做同样的处理。让我们对xedit 定义转译,使得使用
滑鼠可以在本文上方便地移动,我们首先的尝试如下:

*Text*Translation: #override\
Shift <Btn1Down>: forward-character()\n\
Shift <Btn2Down>: forward-word()\n\
Shift <Btn3Down>: next-line()\n\
Ctrl <Btn1Down>: backward-character()\n\
Ctrl <Btn2Down>: backward-word()\n\
Ctrl <Btn3Down>: previous-line()

如果你测试它,奇怪的现象会发生 -- 游标好像会自行其是,而且本文的片段
会一下子被选择,一下子又取消选择。发生这种现象的原因是Text widget 的
预设系结仍然会作用,它包含的转译像:

<Btn1Up>: extend-end(PRIMARY, CUT_BUFFER0)

你可能认为这不会影响你,因为当你松开按钮时你总是按著SHIFT 键或CTRL键
。但事实上会作用:转译管理器对於你未定义的修饰键解释为你不在乎它们的
影响,所以松开Button1 时会对应到上述的规格。为了克服这点,我们对那些
可能不小心便会发生的按钮松开事件定义转译,并系结到一个空 (null) 作用
。这些转译当被对应到时会盖掉预设的转译。对使用Text widget 我们需再增
加两列,才是一个完整的转译表:

*Text*Translation: #override\
Shift <Btn1Down>: forward-character()\n\
Shift <Btn2Down>: forward-word()\n\
Shift <Btn3Down>: next-line()\n\
Ctrl <Btn1Down>: backward-character()\n\
Ctrl <Btn2Down>: backward-word()\n\
Ctrl <Btn3Down>: previous-line()\n\
Shift <BtnUp>: do-nothing()\n\
Ctrl <BtnUp>: do-nothing()

这解释了下列几点:

.我们对滑鼠事件使用了缩写的语法,也就是先前的语法像<BtnDown>Button1
以<Btn1Down>取代。转译管理器容许一些缩写的语法存在。 (我们在前
面看到的 <Meta> 也是一例)。

.我们用 do-nothing() 当作一个哑 (dummy)作用,就好像它是列在Text
widget的文件中一般。事实上这个作用是不存在的,因此会导致错误的
讯息出现,但因为我们本来就是要用它来什麽事也不做的,所以无需介
意。

.对於我们方才指定的哑作用,我们用了一个事件 <BtnUp>便代表了三个
按钮。相同地,转译管理器把从缺的修饰规格的解释为 "对任何",在一
个事件中缺少细节部份 (例如在规格"<BtnUp>Button1"中"Button1"的部
份) 解释为 "对任何所有的细节部份"。

这点在转译中有一个非常常用的形式为:

<Key>: ...

因为缺少细节部份,所以可被用於所有按下键 (key-press)事件,也就
是对所有的键。事实上在Text widget 上有一个预设的转译为:

<Key>: insert-char()

insert-char()作用的功能为当一个键被按下时,插入相对应的ASCII字
元。

17.1.4 复合的转译表及□例

到目前为止,我们把所有的转译均应用於整体的widget类别。但你能对个别的
widget指定转译,就如同resource一般。在此我们将对xman定义更多的转译。
我们将对Help盒widget (对应作用到助忆(mnemonic)字元)只用到键盘事件,对
Quit盒只用到视窗事件。为了达到此点,我们将对转译应用到的widget 给予明
确的名称。我们的转译表如下:

*Help*translations: \
<Key>h: highlight()\n\
<Key>u: unhighlight()\n\
<Key>n: notify()\n\
<Key>s: set()\n\
<Key>r: reset()\n\
<Key>LineFeed: set() notify()

Quit*translations: #override\n\
<EnterWindow>: reset()\n\
<LeaveWindaw>: set()

有几点特别的语法需要注意:

.在此我们对相同类别中不同的widget指定不同的转译,所以我们需要知
道成员 (instance) 名称。不幸的是,这些成员名称 (Help,Quit,
Manual Page)并不明显。如果它们在文件中找不到 (本例即找不到),那
你只能用猜的或是去查看原始程式了。

.对於Help,我们省略了常用的#override,因为我们对此widget不需要考
虑任何预设的系结。特别的是,当指标进入视窗时,我们不要此widget
呈现高亮度,如此我们才能看出这个转译的效用。

.由於省略 #override,我们将这个转译规格移至第一列。(如果不这麽作
,而且对第一列仍以\n\ 作结束,我们将得到错误:

X Toolkit Warning: translation table syntax er-
ror: Missing ':' after event sequence.
X Toolkit Warning: ... found while parsing ''

因为\n是用来区隔转译规格或类似像 #override 指令的)。而将此列和
第一个规格以隐藏的新列字元区隔,就如同:

*Help*translations: \
<Key>h: highlight()\n\
...

.对LineFeed那一列的转译,包含了复合的作用,和前面xterm 中复合的
string()作用类似。

我们已大致涵盖了你所常用的转译。基本的概念很简单,生成它们的结构
也不复杂,但它们非常的令人迷惑。原因是它是一个发展中的糸统,随著发行
版本所附的文件并不是很多。下一节重复本节所述的,本节均以例子来介绍观
念,下一节我们将对转译的规则,作比较正式的描述。

17.2 转译 -- 格式和规则

转译是一个由Toolkit 提供的一般性结构,它让使用者指定当某些特定的事件
由widget接收到时,一个widget应完成何种作用。Toolkit 中处理转译的部份
被称之为转译管理器。

转译由widget指定,它的确是一个widget的每一个成员。一个转译的集合
称之为一个转译表,而这个表藉著标准的resource结构传递给应用程式。widget
(对转译而言意味深长) 会有一个Translation 类别的resource属性,通常的
成员名称为translation。这个转译resource期待的一个值即为一个转译表。就
像所有其它的resource一般,你可以在同一个应用程式对不同的widget指定不同
的resource,而且你能以类别名称或成员名称或二者混合来指定它们。

每一个widget定义了它所提供的作用,不论是在数量或型态上,它们都是
极富变化的。

转译可被各种不同型态的事件指定,不仅只於键盘和滑鼠事件而已。任何
序列的事件均能被处理,就如同单一事件一般。

转译和转译表在 " X Toolkit Intrinsics " 使用手册附录B一节中,有
简洁地描述。它不是初学者查看转译的好地方,但它含有完整的事件型态、修
饰名称等等的表列,在此不再赘述。

17.2.1 转译表的格式
一个转译表大体上的格式如下:

[optional-directive\n] list-of-translations

每一个 list-of-translations 由一或多个转译组成,格式如下:

event-sequence : list-of-actions

当event-sequence发生时,规格中的list-of-actions 会由widget所完成。如
果在一个表中,有多於一个的转译,每一个需以 "\n" 区隔开。

我们首先来看一下选项的指令,然後看一下list-of-translations的细节
部份。

17.2.2 转译指引 -- #override 等等

选项指引 (directive) 告诉转译管理器,它应对任何已设定之相关widget在此
转译集合中应如何处理。

#replace : 清除所有现存的对应,只采用在转译表中所含有的。(只使用新
的)。

#override : 强制留下现有的对应,加入转译表中。如果在表中有任何项
目设定,旧有的即被覆写。也就是说,旧有的被新有的取代。 (结合
旧有的和新的,但新的比较重要)。

#augment : 强制留下现有的对应,加入转译表中。如果在表中有任何项
目设定在现有的设定存在,使用旧的而忽略新的。 (结合旧有的和新的
,但旧的比较重要)。

如果未设定指引,预设为 #replace 。

17.2.3 个别的转译规格格式

每一个转译的格式为:

event-sequence : list-of-actions

让我们来看一看此规格的两个部份。

事件和事件序列(event-sequence)的格式

一个事件序列包含一或多个事件规格(event-specs), 其格式为:

[modifiers] <event-type> [repeat-count] [detail]

除了事件型态(event type)外,均为可选择。(<>中为必需)。

modifiers : 这是基本设计中比较精巧的部份,我们在下一段说明。

event-type : 指定我们有兴趣的事件的型态,例如按键(<KeyDown>)、
松开按钮(<BtnUp>)或指标离开视窗(<Leave>)等等。

detail : 指定我们有兴趣的特定型态。如果你省略细节栏(detail field
),事件规格将对应到任何detail,如此,<Key>将对应到所有的按键
事件。此格式指定到每一个事件型态。对指定事件型态的细节栏为:

.对<Key>、<KeyUp>和<KeyDown>事件,细节如果不是键的名称(例如
"<Key>s"),便是 keysym (keysym是按键以开头为"0x"的十六进位
数表示,将於下一章详细解释)。

.对於按钮事件,细节就是按钮的名称,也就是 Button1 ... Button5
中的一个。例如我们先前使用过的"<BtnDown>Button1"。

型态/细节的缩写:常用於转译管理器的一些事件型态和细节的组合,允许
你对它们使用缩写:

缩写 相等的全名

<Btn1Down> <BtnDown>Button1
...
<Btn5Down> <BtnDown>Button5
<Btn1Up> <BtnUp>Button1
...
<Btn5Up> <BtnUp>Button5

repeat-count : 这指定了事件需要的次数。如果被指定,它们被包含在
括弧之中。例如:

<Btn1Down>(2)

指定需对一号按钮(button-1)碰触两次。如果你在後面再加上加号(+)
,其意为碰触的数目需大於或等於指定。例如:

<Btn1Down>(3+)

意为需碰触三或更多次。预设的重复次数为一次。

一个事件序列以一或多个事件规格组成,以逗点分开。当这个事件的序列
在其widget发生时,相关的作用便会运作。

当序列发生时,转译管理器会根据一些规则决定它自己是否被满足。我们
用一个例子以便仔细地观察,假设你对两个字元序列set 和unset定义了转译:

.概略地说,如果个别的事件依序发生,转译管理器会被满足,其它的事
件 (那些你未指定的事件) 如果在指定的序列中间发生,不会妨碍序列
被满足。例如,set 可被sweat 和serpent 对应。

.如果介於其间的未指定事件,启动了转译表中的另一个事件序列,转译
管理器会放弃原先的序列,而尝试著去满足新的序列。例如,set 不会
被sauerkraut对应,因为u 会使得转译管理器对应到unset。

.如果在一个事件的集合中有超过一个的事件序列发生,转译管理器只会
应用到一个转译:

- 如果一个序列对应到结束 (右端),较短的那个序列只有在不包含於
较长的序列才会发生。所以如果unset 被对应到,对set 转译将不会
作用。

- 如果一个序列是在另一个序列的中间发生,例如,如果你定义序列
at和rate,则较长的那个永远不会被对应到。

事件修饰键

修饰键 (modifiers)是一些键或按钮,系指当主要事件发生时,那些必需被按
下才会让转译管理器满足的键或按钮。你可以对键、按钮、移动、进出视窗等
事件指定修饰键。常见的修饰键为:

Button1 ... Button5
Ctrl Shift Meta
Lock

如果你未指定任何的修饰键,转译管理器会解释为: "当事件发生时,不
论修饰键是否被按下,均会被接受"。例如,<BtnDown>会被满足,不论当时
SHIFT 或META键是否有被按下。

如果你真的需要指定 "只有在没有修饰键被按下时才接受此事件"。则需使
用虚拟修饰键 (pseudo-modifier) None。例如,None <BtnDown> 会使得当按
钮按下时若META键也被按下则不会满足。

对一个事件指定一些修饰键意为 "只要符合转译中指定的修饰键,其它的
修饰键不需介意"。它并没有 "一定要完全恰好符合才可以"的意思。例如,
Ctrl <Key>a 在你按下 meta-ctl-shift-a 时仍会被满足。

如果你真的要指定 "只有刚好符合修饰键的才要",在修饰键之前加一个惊
叹号 (!)。例如,!Ctrl <Key>a 在你按下 meta-ctl-shift-a 时不会被满足。

对一个修饰键的集合 (可能是空集合) 作限制,意为 "除了这些修饰键不
不接受",需要在不接受的修饰键之前加一个(~)号。例如,Shift~Meta <Key>t
会被ctl-shift-t满足,不会被meta-shift-t满足。

键事件通常忽略大小写,如果你要区分,需在之前加一个冒号(:)。例如,
不论 H或 h均可符合<Key>H,但只有H 才符合 :<Key>H。

就如同对常用的事件型态/细节配对有缩写一般,转译管理器对常用的修
饰键/事件型态配对同样地提供缩写:

缩写 相等的全名

<Ctrl> Ctrl <KeyDown>
<Shift> Shift <KeyDown>
<Meta> Meta <KeyDown>
<Btn1Motion> Button1 <Motion>
...
<Btn5Motion> Button5 <Motion>
<BtnMotion> 任何按钮的 <Motion>

作用的格式和作用的表列

每一个转译在一或多个作用之上系结一个序列的一或多个事件。在表列中的个
别作用是以空白分开的。 (不可用逗点分开,那将会导致错误)。

个别的作用格式如下:

action-name(parameters)

即使没有参数被指定,在作用名称 (action-name)後的括弧,仍然不可省略。
例如:

start-selection()

如果在作用名称和左括弧中间留有空白,你将会得到一个错误。

作用名称只包含了字母、数字、钱号($)、底线(_)四种字元。每一个widget
提供它自己的作用集合 (如果有的话) ,且自我包含这些作用名称的硬码
(hard-coded)表列。

参数(parameters)是一个零到多个字元字串的表列,中间以逗点分开。参
数的意义为对特定的作用作指定 (事实上大多数的作用并没有任何参数) 。参
数字串可以不加引号,例如:

insert-selection(PRIMARY)

或者前後加上双引号,这种情形通常为参数字串内包含了空白或一个逗点,例
如:

string("plot<x,y>")

没有一个一般性的方法,让你在参数字串中的任何位置包含一个双引号,虽然
像这样 string(ab"cd)'将双引号放在字串中间是可被处理的。也没有一般性的
方法在同一个参数字串中同时包含字串和双引号。因为如此,有些widget在解
释它们自己的参数时,可以自行加入它们自己的语法规则。例如:对xterm 的
VT100 widget的 string()作用,如果一个不带双引号且开头为 "0x"的字串,
此字串被解释为代表一个ASCII 字元的十六进位数。

在此结束我们对转译规格及格式的描述。由此,你应有能力了解在不同X
手册列出的转译,且可写你自己的转译。为了帮助你,下节列出你常见的问题
,以及如何克服它们。

17.3 在转译规格中常见的问题

转译在观念上简单,但实际上很混乱。即使你常常使用,语法仍然复杂而难解。
无论如何,如果你是初学者,最好的方式是你以别人的转译当作自己的转译的
基础。在指南页中有几个对xbiff、xdm(目前尚未介绍过,将於第20章介绍
)、xterm 的转译□例,将对你有所帮助。

如果你发现你的转译有错误的话,有几点值得去检查:

.转译只能应用在使用Toolkit的程式上。如果你试图对非Toolkit应用程
式定义转译,看起来不会有任何问题,只是转译不会作用而已。

让我们来看一下为什麽,以对xcalc (这是一个非Toolkit程式)使用转译
为例。你对一个resource名称像 *xcalc*translations定义一个转译表,
且用xrdb载入至你的资料库。xrdb并不会抱怨,因为它不知道是那一个
应用程式使用到resource,它只会设定资料库,稍後供Resource Manager
查询。现在你执行xcalc ,它对转译是一无所知,所以不会向资料库查
询转译,当然也绝不会编译它们了。

.不要省略 #override,除非你确实知道你要做什麽。如果你因错误省略
它,例如在xedit 中,你将发现没有任何的键可输入任何的东西 (因为
预设的转译 "<Key>:insert-char()"被去掉了)。

.检查你对每一列均有终结。如果你在转译表中的一列忽略了"\n\"或"\n"
,在其後所有的转译都会被忽略。如果你在最後一列的末端加上一个倒
斜线(\) ,或是省略了档案中最後一个新列字元(newline),整个转译表
都会被忽略。(不过这是xrdb的问题,而非转译管理器的问题)。

这种错误在你编辑一个现存的转译表时特别容易发生。

.当你定义的转译和预设有冲突时,可能会导致奇怪的行为,特别是对滑
鼠按钮事件,每一次按下或"Down"事件,会相关到一个松开或"Up"事件
,当你对此部份没有明确定义时,可能会有一个预设的系结仍然存在,
(键盘的按下和松开也是成对的事件) .所以:

1.检查预设系结的文件。

2.如果你只对按下/松开配对的一半指定一个转译,确定另一半并非预设
转译的一部份,如果是的话,需对它明确地指定一个转译。

3.如果你仍然不能解决,暂时由表中移去#override,这将去掉所有的预
设转译,让你了解问题是由於和预设转译冲突所造成,还是因为你的
转译表有错误。

.转译管理器对语法不正确的问题,无法很好的告诉你原因何在。例如如
   果你有一个转译像:

<Key>F6: string("abc""def")

参数的语法并不正确,F6键将没有作用,但你也看不到错误讯息。

.如果你转译一序列的事件,且需要对每一个均指定修饰键,你必需明确
地对每一个都指定。例如如果你需要一个转译使用ctl-X ctl-K:

Ctrl <Key>X, Ctrl <Key>K: ...

而如果你使用:

Ctrl <Key>X, <Key>K: ...

你的指定为 ctl-X K

.检查你所需的widget是否有你指定的名称和类别。例如对xterm ,你可
以在一个表的开头指定:

xterm*Text*translations:

这将什麽事也没作,xterm 正规视窗widget的类别VT100。通常,不论
xrdb或转译管理器均不会有反应,因为看起来没错。

.转译可能指定正确,也可以工作,但它的作用和你预期的不符。例如对
xterm 的转译:

Meta Ctrl <Key>m: mode-menu()

是正确的,且会工作。但mode-menu()实际上检查滑鼠左或中按钮是否有
招唤它,其它方面不做任何事。

.在一个转译中不指定修饰键,并不意味著当修饰键按下时转译会无效。
它真正的意义为: "我并不在乎有没有修饰键" 。如果需要的话,使用
"None",""或!符号。使用时要小心预设的转译是否会妨碍到你。

.转译是针对widget而指定的,所有在转译中的作用必需由widget提供。
在你指定转译resource名称的地方很容易忘掉这一点。例如:

xman*translations: \
<EnterWindow>: reset()\n\
<LeaveWindow>: set()

将导致许多错误:set()和reset()作用只有被Command widget定义,但
xman有数种其它型态的widget可接受转译,且转译管理器会抱怨这些
widget并未提供set()和reset()。解决之道为更完整些的指定resource
名称,例如在本例为 xman*Command*translations 。

.对任何给定的resource,当resource资料库被询问时,Resource Manager
会传回一个值给widget,这个传回的值的 "特徵值" (characteristic)
(resource名称)大多与widget的和属性的完整类别/成员名称相符。所
以你对所有的Text widget指定一个一般性的转译後,又对xedit指定一
个转译,希望它们并存是不可能的,只有一个转译表会传给widget。例
如:

*Text*Translation: #override\
(对Text一般性的转译)
...
xedit*Text*Translation: #override\
(对xedit 的Text特定的转译)
...

你只能得到在xedit 中特定的转译,或是在别处得到一般性的转译。

#override 会有所混淆,它的意义为 "把转译加入现存的之中" 。但这
完全由转译管理器处理,当时候到时,转译管理器会决定传递哪个值给
由Resource Manager所造的widget。对Resource Manager而言,#override
只是传递给widget值的部份中的一个文字字串而已。

因为你使用resource来指定转译,所以错误可能在两个领域均会发生。为
了减少错误的□围,当你对转译颇有经验时,在你已载入转译resource之後,
最好能明确地列印出你的resource资料库。例如:如果你对xprog 写入转译,
且转译在档案mytrans 中,以下列命令来执行程式:

xrdb mytrans ; xrdb -q ; xprog ...

17.4 结论

这漫长的一章涵盖了被X Toolkit 所使用的标准转译结构,它让你指定
按下一个键或按钮会有什麽影响。这些转译指定到每一个widget,且你藉著使
用标准resource结构传送转译表给widget。你看到如何对一个键盘的键、滑鼠
按钮和其它像移动一个指标进入视窗的事件作指定转译。然後我们藉著指定不
同状态的修饰键所造成的影响,比较严谨地定义我们需要转译的事件。

本章的第二个部份涵盖相同的领域,但较为正式,且详细解释在转译规格
中,可用到的语法,特别是修饰键。

最後,我们简列使用转译常见的问题,及一些如何解决它们的建议。

本章包含了许多材料。它们运用了极少的观念,但语法复杂,易生错误,
且不显而易见。如果一开始觉得困难,不必担心。从一些简单的转译著手 (也
许是xterm),且以指南页中的□例或别人的转译表为基础来发展修改。当你有
经验之後会进展快速;你将洞悉语法且能看出其後会发生什麽状况。

=====
(http://www.fanqiang.com) 进入【UNIX论坛】

freesky64 04-03-15 12:49

第18章 键盘和滑鼠 -- 对应和参数
本文出自: 作者:cuteyu 整理 (2001-10-09 15:00:01)
在前章我们看到了Toolkit 所提供的转译结构,它让你对一个应用程式的个别
成员,定制你的键盘和滑鼠。在本章,我们来看另一种较低层次的定制,它是
由server所管理,称之为对应(mapping) ,你只需要告诉server你的键盘所需
的不同的配置,它就会被每一个连接到你server上的应用程式应用到。例如:
取代通常的QWERTY键盘,你可能希望重新安排键盘以适应那些对键盘并不熟悉
的使用者 (你可能把键盘按ABCDEF... 重新排过,当然键盘按钮上所印的字也
需更改成相符)。你也能对一些Control,Shift等等的修饰键作指定。对滑鼠
按钮,一样有一个相关的对应,可将 "逻辑的" 按钮对应到实际动作。整体而
言,你使用这些键盘和滑鼠的对应的频率,将小於转译。

此外,尚有非常常用的第三种型态的定制可用:你可以设定有关你键盘和
滑鼠各种不同的参数。例如响铃声音的大小,按下键时是否有滴答声等等。

在本章,我们先描述键盘、滑鼠和修饰键的对应,接下来描述你如何使用
xset程式,来定义类似像键盘有无滴答声的参数设定。

18.1 键盘和滑鼠对应 -- xmodmap

server本身处理一个层次的定制,它对於所有使用到此server或显示器的应用程
式均发生效用:这就是键盘对应 (keyboard mapping)。

每一个键,有一个单独的码对应它,称之为键码(keycode)。键和键码之间
的关系是绝对固定的。 (粗略来说,你可以说 "键码就是键")。

连接到每一个键码 (或键)的是一个keysym的表列。一个keysym是一个代表
印在键盘符号上的数字常数。在预设的情况,大多数的键只有一个keysym 与之
对应,例如 SHIFT,A,B,Delete,Linefeed等等。keysym既非ASCII或EBCDIC
字元,也非server用以维持keysym和字元的关系。你可以对每一个键有两个
keysym。在预设对应中,有很多连接到两个keysym的键,例如冒号(:) 和分号(;)
,7 和 &等等。对一个键附属的keysym表列中,第一个keysym是未按下修饰键
的状况下的键。第二个keysym是指当SHIFT (或Lock)已被同时按下时的键,如
果在表列中只有一项,且为字母,则系统自动假设第二项为相对的大写字母。
超过两项的keysym并没有特别的意义,键盘和keysym之间的关系被称之为键盘
对应。

尽量地以server处理一般的键和keysyms 。它对键码没有附属意义,且它
自己本身不会使用对应从键码对应至keysyms :它只是传递资讯给client应用
程式。特别的是,server对ASCII 或其它的字元集合 (character sets) 毫无
概念;它只是说明 "某键被按下,某修饰键也同时被按下,keysym表列中某
keysym和某键相关" 。它是client (典型的使用标准的X Library) 对keysym
和修饰键附属的意义:例如,它决定如果keysym产生时ctrl也被按下,它必需
被解释为ASCII 字元 hex 0x1,也就是说ctl-A。 特定的client可以决定特殊
的修饰键的意义;例如在xterm 中,当你和MTEA键同时按下一个键,程式将此
转换为ESC 後面跟随著被按下的字元。 (也就是说,如果你按下meta-A,实际
上会产生两个字元 ASCII 0x1b, ASCII 0x41)。

server在此领域内提供一个额外的设施。你可以定义让server将键码解释
成修饰键,例如 "当键码为若干的键被按下时,它相同於CONTROL修饰键被实际
按下"。这种定义并不互斥:如果你定义键F7为Shift 修饰键,它并不会影响任
何现存的修饰键。此种设施称之为修饰键对应 (modifier mapping)。X提供八
个修饰键:Shift、Lock(caps-lock)、Control、Mod1到Mod5。习惯上,Mod1被
解释为Meta。

最後,对滑鼠按钮有一个类似的指标对应 (pointer mapping)。对每一个
实际的按钮,你可以对它们指定一个相关的逻辑按钮数字。

实际上,如果你改变你的键盘或滑鼠的对应,你相当於是说制造厂商对你
的输入装置配置不当,你将把它修正为适合你所需要的。当然,如果你改变了
对应,你应该把对应键上面所印的符号也随之修改;不过,通常更改的都是一
些控制和修饰键,所以就不是那麽需要了。换句话说,如果你改变了对应,使
得键盘配置和一个特定国家标准 (例如:法国或德国) 相符,你必需更换实际
键盘上的符号。

你可以预期得到,改变键盘对应是一件相当稀罕的事,你可能设定它一次
之後就不再改变它。在以下几节,我们将很快的看一看如何使用程式xmodmap
,查看现有的对应和修改它们。

18.1.1 查看现有的对应

你使用xmodmap 来列出现有的对应,就如同改变它们一样。你可以指定不同的
命令列选项,来选择想要印出的不同的对应:

列出现有键的对应:指定 -pk选项。

列出现有修饰键的对应:指定 -pm选项 (或是什麽选项也不选,因为这是
xmodmap的预设作用)。

列出现有指标 (按钮)的对应:指定 -pp选项。

例如,将所有的对应一起印出,使用命令:

xmodmap -pm -pk -pp

列出键、修饰键、指标的对应之□例如图18 - 1,18 - 2,18 - 3。(键对应只
有列出一部份,因为完整的对应实在太长了。)

┌————————————————————┐
│ p228 fig 18.1 │
│ │
│ 图18-1 列出键盘对应的□例 │
└————————————————————┘

┌————————————————————┐
│ p229 fig 18.2 │
│ │
│ 图18-2 列出修饰键对应的□例 │
└————————————————————┘

┌————————————————————┐
│ p229 fig 18.3 │
│ │
│ 图18-3 列出指标对应的□例 │
└————————————————————┘

18.1.2 执行 xmodmap 改变对应 -- 一般性选项

当xmodmap 用来改变或设定对应,它可以处理一或多个表式 (expression) 的
作用。你可以把这些输入在一个档案中,假设此档案名称叫myfile,可用下列
命令两者之一:

xmodmap myfile
xmodmap - <myfile

第二列的短横线是必需的,如果少了它,程式将只完成预设的作用 (列出修饰
键的对应) 。除了在档案中输入规格之外,你也可以在命令列中用 -e 选项直
接指定它们:

xmodmap -e expression
xmodmap -e expression-1 -e expression-2

为了得到更多有关xmodmap 作用的资讯,可以指定冗赘 (verbose)选项,-v 或
-verbose。你可以藉著使用 -n 选项不实际的改变对应而获得相同的列印输出
(printout) 。 (此功能和Unix中make命令的 -n 选项相同,其意为 "假装执
行我要求你做的事,正确的告诉我你将如何进行,但并不实际地完成作用")。
这个选项对新手或不确定自己是否做的正确的情况非常有用。

每一个表式的语法并不相同,但一般性的格式为:

keyword target = value(s)

(等号的两边均需为空白)。

18.1.3 改变指标对应

指标对应是一个逻辑按钮数字的表列。 (逻辑的button-1我们称为LEFT,逻辑
的 button-2 称为MIDDLE等等,实际的 button-1 是滑鼠左边的按钮,button-2
是隔壁的按钮等等,所以预设的逻辑的按钮和实际的一致)。在表列中的第一个
项目是逻辑的按钮和实际的 button-1 的关系,下一个则是对实际的 button-2
的关系,以此类推。例如,颠倒按钮的次序,使用命令:

xmodmap -e "pointer = 3 2 1 "

结果按下滑鼠右边的按钮,会被解释成LEFT。

18.1.4 改变键对应

xmodmap 让你将一个键 (也就是说键码) 连结到一个新的keysym表列,使用表
式:

keycode keycode = keysym-1 [keysym-2 ...]

安排keysym-1连结到键时没有修饰键,当SHIFT 按下时keysym-2连结到键,如果
还有下一个keysym的话,对keycode 而言是第三顺位等等。 (请记住,在前两个
之後的keysym,系统并未附属特别的意义,应用程式如果需要的话可以附属意义
)。

让我们举实际的例子。一些键盘把一些非字母数字 (alphanumeric)键放在
不标准的地方,所以我们假设你要将F6键重定义当没有修饰键按下时为 "9",
当SHIFT 按下时为 "("。要写入这个xmodmap 的表式,你需要知道三件事:F6
的键码,和 "9"与 "("的keysym。我们在第12章提到过,执行xev 便可获得
这些:分别按下"F6", "9", "("三个键,你便可得到它们的键码和keysym。然
後将它们放入你的表式中。例如在我们的系统中我们使用命令:

xmodmap -e "keycode 21 = 9 parenleft"

为了容易一些,你通常不需要查问键码,xmodmap 允许你使用下列格式:

keysym target-keysym = keysym-1 [keysym-2 ...]

它的意义为 "附属在此键的keysym表列现在改由target-keysym来附属"。例如
针对我们方才的□例,我们可以用:

xmodmap -e "keysym F6 = 9 parenleft"

如果你将相同的keysym附属到数个键,xmodmap 会搞混掉,像这种情况你应坚
持使用keycode ... 这种符号表示法。

18.1.5 改变修饰键对应

在server中修饰键对应是一个表列的集合,每个修饰键有一个表列。对一个修
饰键的表列中,包含了所有当此修饰键被按下时会有意义的键 (键码) 。xmodmap
允许你在一个表列中增加项目,去除项目,或完全清除一个表列。对此三个操
作的格式为:

add modifier = list-of-keysyms
remove modifier = list-of-keysyms
clear modifier

不幸的是,语法有点儿混淆,因为取代你所需的键码,你必需指定keysym附属
到键码。

举一个例子:假如你需要在你键盘的右边有一个第二个的Ctrl键。在我们
的键盘上有一个Alternate 键没有被用来做任何事,所以我们将修改它,命令
为:

xmodmap -e "add Control = Alt_R"

为了多解释一些情况,让我们假设你没有一个多馀的键,但有一个第二个的
Meta键在键盘的右手边,而我们要用它。我们首先必需去除它的Mod1对应 (你
必须使用 "Mod1" ,"Meta"没有用) ,而後将它加入Control 对应。 (如果有
需要的话,我们可以拥有双重的对应,所以在Control-Meta组合键时才会有作
用,在一些编辑器中常会用到)。命令为:

remove Mod1 = Meta_r
add Control = Meta_r

将上述命令列放入一个比方说叫mymaps的档案中,执行命令xmodmap mymaps。
它可以工作,但如果你用xmodmap -pm 去查看,你会发觉Control 和Meta混合
在一起,所以最好改变键上的keysym为:

remove Mod1 = Meta_R
add Control = Meta_R
keysym Meta_R = Control_R

在xmodmap 的指南页中,有几个更多的交换修饰键的□例。

注意:当增加一个键到修饰键对应,keysym只是用来指定xmodmap 中的键
。它完全是xmodmap 本地的,且只是一个符号而已:只有当相关的键码传递到
server,才实际上的改变对应。同样地,keysym 和 keycode 表式对修饰键对
应绝对没有影响。一个常见的错误是执行下面这个命令:

xmodmap -e "keysym F1 = Contrl_R"

期望F1键能像一个control 键般作用。它不会 -- 因为你相当於告诉系统 "我
已经把这个符号印在F1键上面" 而已。你应该这样作:

xmodmap -e "add Control = F1"

如果你合并上一列的命令会使得对应表列看起来清楚些。

我们对不同对应的处理的描述到此告一结束。



18.2 键盘和滑鼠参数设定 -- xset

最後我们来看一看最平常的设施,对你的键盘、滑鼠和萤幕设定不同的参数的
设施。这些参数使用xset程式 (我们曾经用来控制server的字型搜寻路径) 来
设定。在以下的叙述,我们只用一组引数来展示xset,但你可以同时指定多组
你所要的不同定义的设定。

控制终端机响铃

用xset你可以让铃声响或不响,设定它的音调 (pitch),和它持续的时间 (假
设你的机器提供这些操作):

让铃声不响 xset -b
xset b off

让铃声能响 xset b
xset b on

设定铃声的音量 xset b vol
(最大音量之vol%) 例:xset b 50

设定铃声的音量,和 xset b vol p
音调(单位Hertz(赫)) 例:xset b 50 300

设定铃声的音量,音调, xset b vol p d
和持续的时间(单位百万 例:xset b 50 300 100
分之一秒)

控制键的滴答(click)

让键的滴答不作用 xset -c
xset c off

让键的滴答作用 xset c
xset c on

设定滴答声的音量 xset c vol
(最大音量之vol%) 例:xset c 50

控制键的自动重复(auto-repeat)

让键的自动重复不作用 xset -r
xset r off

让键的自动重复作用 xset r
xset r on

滑鼠参数 -- 加速和门槛

指标在萤幕上的移动和滑鼠的移动是成比例的。加速 (multiplier) 是应用在
指标移动上的一个乘数,例如你的加速是四,当你移动滑鼠时,指标将以正常
四倍的速度移动。 (如果指标正常时移动n 个像素,现在则会移动 4 X n个像
素)。

当你希望在萤幕上将指标移动一段长距离时,相当高的加速是很方便,但
当你要作一些细部的指引时,它看起来就很笨拙 -- 指标看起来在来回跳动。
为了克服此点,server提供了一个门槛 (threshold):如果当指标一次移动超
过门槛个像素,加速也会被带进来执行。

设定滑鼠的加速到a xset m a
例:xset m 5

设定加速,设定门槛到t xset m a t
例:xset m 5 10

控制萤幕节约器结构

萤幕节约器 (screen saver)是一种设施,它意图降低一个固定的图样(pattern)
老是燃烧你萤幕的萤光体的机率。它的理念为萤幕损害大都起因於让系统□置
(idle)一长段时间,所以萤幕节约器在一段特定的时间内如果没有输入动作後
,不是整体性的闪动萤幕,便是显示一个不同的图样。

如果你选择的是显示一个不同的图样,根视窗的背景涵盖整个萤幕,一个
大X 的游标出现在萤幕上,且会周期性的移动。当大X 游标在移动时,会改变
大小,而且背景也会随机的变动。 (在背景图样较小时你可能不会注意到,但
若比较大时,你可以看到它在跳动)。

当萤幕节约器结束作用後,如果要花许多的时间才能重画应用视窗,你可
以指定只有在重画萤幕而不需产生任何曝光(exposure)事件 (也就是不必要求
应用程式重画它们自己的视窗) 的情况下,萤幕节约器才会作用。 这只应用
於显示不同的图样的情况,整体性的闪动萤幕纯为硬体作用,不会影响到应用
程式。

让萤幕节约器能作用 xset s

让萤幕节约器不能作用 xset s off

用萤幕闪动的方式 xset s blank

只有在无曝光事件下才作用 xset s noexpose

允许有曝光事件下仍然作用 xset s expose

用不同图样的方式 xset s noblank

当系统□置t 秒後作用 xset s t
例:xset s 600

每p 秒之後改变图样 xset s t p
例:xset s 600 10

让我们将这些组合起来,假设我们希望萤幕节约器在系统□置80秒後开始作用
,用不同的图样的方式,周期为3 秒,不介意曝光事件是否发生:

xset s noblank s 80 3 s expose

注意:xset s 并不提供 on 这个值。



18.3 结论

本章的第一个部份,告诉你如何改变从实际的到逻辑的键和按钮的对应,这些
对应可被client应用程式解释。你看到如何使用xmodmap 来列出或改变每一个
键盘的键、修饰键和滑鼠按钮的对应。这些对应由server维护,所以可以被每
一个使用到此server的应用程式应用到。这种结构让你有改变键盘配置的自由
,不论是个人的喜好或是一个额外的标准。

在本章的第二个部份,你看到如何使用xset对一些常见的特性作设定,如
键的滴答声、终端机的响铃、萤幕节约器和滑鼠的速度 ("加速")。

===== (http://www.fanqiang.com) 进入【UNIX论坛】

freesky64 04-03-15 12:50

第19章 进一步介绍 uwm 和如何定制它
本文出自: 作者:cuteyu 整理 (2001-10-10 07:00:00)
在第6章,你学到如何使用uwm 来完成基础的视窗建构工作需求,而能以一个
舒服的方式使用视窗。现在我们继续谈视窗,集中於两个主要的□围:

1.此程式所提供的一些特别的特色,特别是:

.不使用选单,直接使用滑鼠建构视窗。

.我们尚未描述过的一些选单选择。

.编辑现存表徵图的标题。

2.如何定制uwm ,包含:

.对任何你所需的命令定义你自己的选单。

.将各种不同的视窗管理器功能系结到滑鼠按钮和修饰键 (SHIFT,
CONTROL 等等)。

19.1 uwm 的新特色

现在我们来讨论一些在先前介绍视窗管理器时,为了保持尽量地简单,而省略
的标准的uwm 功能。

19.1.1 不使用uwm 的选单来管理视窗

直到目前,你仍然依赖著uwm 的选单来建构你的视窗 -- 移动它们、对它们重
定大小等等。如果所有的情况都使用选单,是相当慢的,所以uwm 提供你可直
接完成它任何命令的选项。

你可以使用滑鼠按钮和修饰键,来指定你要执行的功能,和所要操作的视
窗。你现在应该已非常熟悉各种不同的视窗管理器功能和它们如何工作,所以
我们将很快地说明如何不使用选单来选择这些功能。

Move:移动一个视窗

1.按下META键,保持按住。
2.指标位置所在的视窗将被移动。
3.用右按钮,拖拽视窗到新的位置。

Resize:重定一个视窗的大小
1.按下META键,保持按住。
2.指标位置所在的视窗将被重定大小。
3.用中按钮,拖拽视窗的外框到新的大小。

Lower:将一个视窗送到堆叠的底部
1.按下META键,保持按住。
2.将欲被送到堆叠的底部的视窗,碰触一下左按钮。

Raise:将一个视窗升到堆叠的顶端。
1.按下META键,保持按住。
2.将欲被送到堆叠的顶端的视窗,碰触一下右按钮。

Circulate up:将最底层被遮蔽的视窗升到最上层,你有两种选择:
1.按下META键,保持按住。
2.在根视窗上,碰触一下右按钮。

1.同时按下META和SHIFT 键,保持按住。
2.在萤幕上的任何地方,碰触一下右按钮。

Circulate Down:将最上层的视窗移到最底层,作法同Circulate Up,但
改为左按钮。

Iconify:之前我们曾提过两种形式的表徵图化,一种是视窗曾经表徵图
化过(已定义过表徵图的位置) ,另一种为对 "新" 的视窗表徵图化


表徵图化一个新的视窗:

1.按下META键,保持按住。
2.将指标位置移至欲被表徵图化的视窗。
3.按下LEFT按钮,保持按住...
4. ... 拖拽表徵图的外框到你所需的位置。
5.松开按钮和META键。

注意它和Lower 操作程序的不同点,在此你是按下... 拖拽... 松开滑
鼠按钮,而对Lower ,你只是碰触一下按钮。

表徵图化一个曾经表徵图化过的的视窗:

1.同时按下META和CTRL键,保持按住。
2.在你欲表徵图化的视窗上,碰触一下左按钮。

(如果你对先前并未表徵图化的视窗作这个操作,或经由resource结构
无法取得表徵图的位置,表徵图将出现在指标所在的位置)。

De-Iconify:将表徵图还原为它的视窗 (在视窗原来的位置):

1.按下META键,保持按住。
2.在表徵图上,碰触一下中按钮。

如果你觉得这些对滑鼠按钮功能的结合十分笨拙且不易记忆,别担心,很
多人都是如此。有更好的法子,刚才那些只是预设的设定,你可以完全由自己
来建构。在本章的後半部,我们将告诉你如何做。现在我们先来看一看,在标
准选单的一些功能和它们能做些什麽。

19.1.2 一些更多的选单选择

这是一些我们在第6章中没有解释的标准的选单选择。

Focus:让你设定键盘的焦点(focus),也就是说,将键盘附属於一个视窗
,所以不论萤幕上的指标在何处,键盘的输入总是在同一个视窗。一
般键盘的输入总是指向目前指标所在的视窗。

设定焦点到一个特定的视窗:选择focus ,出现手指形游标,在你所
欲指定的视窗碰触一下按钮。

恢复正常:选择focus ,在背景视窗上碰触一下。

Restart:停止uwm ,重新启动它,重新读入建构档 (下节说明) 且执行它
。在你改变建构档且希望马上执行新的设定时 (否则将等到你重新启
动一个新的周期) 使用此选择。

Freeze:暂停萤幕上所有的显示,当你要对你的萤幕摄影时可以使用这个
选择。欲重新恢复显示,使用 ...

Unfreeze:重新恢复显示,所有的视窗会立即更新。

Exit:中止uwm 。当你要杀掉uwm 时使用,例如在启动一个不同的视窗管
理器之前。

Perferences 选单

我们在第6章提过,有两种方法叫用uwm 的WindowOps选单 -- 在背景视
窗上按下中按钮,或在按住META和SHIFT 两个键的情况下,在任何地方碰触一
下中按钮。用第二种方法让你呼叫出第二个选单,只要将指标移到WindowOps
选单的外边,标头为Preferences 的视窗就会出现。

在Preference中的选择,只是一些xset程式中设定滑鼠和键盘的选项而已。

注意:Lock On 和 Lock Off选择是和记录有关的,可能会导致一个错误
的讯息在你的主控台视窗印出。

19.1.3 改变现存表徵图上的标题

uwm 的预设表徵图 -- 灰色的盒中有一个名称 -- 如果你对同一个应用程式执
行数次拷贝後会有缺点,例如有三个xterm 的表徵图,你无法明确的区分它们
。为了克服这点,uwm 允许你可以编辑表徵图中的字串为你所需的任何字串。
(这只能在uwm 自己预设的表徵图使用,例如你无法编辑在xclock的特定表徵
图中的字串)。

欲编辑在一个表徵图中的名称:

1.将指标移至所欲编辑的表徵图。
2.键入你所希望的任何文字。
3.你可以去掉文字,不论是先前存在或方才才输入的,方法如下:

去掉前一个字元:按DELETE。
去掉整个名称:按ctl-U。

19.2 定制uwm

uwm 具有高度的可建构性。你可以将整个□围的参数和定义储存在一个建构档
中,当uwm 启始时会将之读入。我们前节曾经提过,你可以在中途改变建构档
,藉著在WindowOps选单中Restart选项,告诉uwm 重新读入它。

uwm 的建构档

预设uwm 有两个建构档,其中之一为

/usr/lib/X11/uwm/system.uwmrc

通常由系统管理者设定,且第一个被读入。另一个

$HOME/.uwmrc

是你自己的建构档。两个档案均需要存在,uwm 硬性规定了预设设定。

注意:如果你用不正确的语法设定一个建构档,当uwm 读入时,你会得到
一个错误讯息像:

uwm: /usr/nmm/.uwmrc: 38: syntax error
uwm: Bad .uwmrc file...aborting

uwm 将不会启动。当在一个新的周期启动时,这没有什麽大问题。然而,如果
你是在中途重新设定uwm ,你可以结束但没有视窗管理器,且没有xterm ,没
有编辑视窗来编辑这个错误的档案,无法启始其它的视窗。如果此种情况发生
,你必需从其它的终端机或机器关闭X,或毁坏 (crash)你的系统。

uwm 的命令列选项

如果你不需要系统建构档案,也不需要任何预设的设定,你可以藉著uwm 的命
令列选项 -b 抑制它们。

如果你要使用其它的档案,就像两个预设的建构档一般,你可以用
-f filename 来指定它。

19.2.1 系结功能到键和按钮

uwm 让你定义当一个特定的滑鼠按钮按下时,有某个功能会作用,例如当你在
一个视窗中碰触一下中按钮,它将被升到堆叠的顶层。这种系结结构和Toolkit
转译并没有牵连,它完全由uwm 本身来完成。

为了让这些结构更有用,你可以指定其它的条件来运用更多的功能,或许一个
修饰键 (像META) 需被按下,或许作用只发生在指标位於一个表徵图上而非应
用程式视窗或背景视窗。我们已实际的看过这些例子:

此功能发生 ... 只有在这些 ... 只有指标在 ... 当这个
於... 修饰键被按下, 此种型态的视窗 滑鼠事件发
而且... ,而且... 生时

Resize META 一般视窗 按住中按钮
且移动

WindowOps 没有 背景视窗 按住中按钮
选单

WindowOps META 和 没有关系 按住中按钮
选单 SHIFT

你藉著你的 .uwmrc(或其它的建构档)所包含的系结规格来指定系结。规格
的格式和上面的表格类似,就像:

uwm-function = modifiers : window context : mouse events
( uwm 功能 = 修饰键 : 视窗的环境 : 滑鼠事件 )

这些元素为:

uwm 功能:uwm 的内建功能之一的名称。例如功能f.move即是你用以移动视
窗的功能,f.lower 将视窗降低一层等等。这些功能将於下更完整地描
述。

功能名称必需跟随著一个等号(=)。

修饰键:在运用上述功能时,当指定的滑鼠事件发生时,必需被按下的修饰键
表列。正确的修饰键名称为:

ctrl(或c),对CONTROL键。

meta(或m或mod1),对META键。

shift(或s),对SHIFT键。

lock(或l),对CAPSLOCK键。

这些名称必需正确的列出。你可以使用一或二个修饰键,如果你使用两个
键,用一个 "|"符号来分开它们。

你可以省略整个修饰键表列 (即此功能对应於滑鼠事件发生时并没有修饰
键被按下),但尾端的冒号 ":" 不可省略。

视窗的环境:限制只有指标在萤幕上指定位置的型态符合特定条件时,功能
才会发生。正确的环境如下:

window(或w):指标必需位於一个应用视窗中。

icon(或i):指标必需位於一个表徵图中。

root(或r):指标必需位於根视窗或背景视窗中。

你可以指定任何数目的环境,用 "|" 来区隔它们。如果你没有指定,则功能
的发生与指标位置无关。

滑鼠事件:何种滑鼠事件对应到此功能。指定的事件为一个按钮名称 -- 任何的

left(或l)

middle(或m)

right(或r)

跟随著一个动作:

down : 当按钮被按下时会符合。
up : 当按钮被松开时会符合。
delta : 当按钮被按下且移动超过一定数目的像素时会符合。

所有的这些你已实际使用过它们,在本章开头所描述的一些作用的系结为:

f.resize = meta : window : middle delta
f.iconify = meta : icon : middle up
f.raise = meta : window|icon : right down

uwm 的预设系结在档案 $TOP/clients/uwm/default.uwmrc,见图19 - 1。

┌————————————————————┐
│ p242-243 fig 19.1 │
│ │
│ 图19-1 预设的 .uwmrc 建构档 │
└————————————————————┘

uwm 的内建功能

uwm 的指南页列出可应用的功能。你已经从图19 - 1见过其中大部份,你可以
看出,功能是和WindowOps及Preferences中的选项相关。

然而,有一个有关pushing视窗(f.pushleft, f.pushup等等)的功能集合你
从未见过。pushing的意思为:你朝一个特定的方向移动一个视窗,移动的距离
固定。这和f.move不同的是,後者以交谈的方式,指定视窗移动的方向和距离。

预设f.pushdown系结到同时按下CONTROL和META键,且按住中按钮。试它几
次,你将发现你的视窗稍微移动了一点 -- push 功能对细部移动视窗非常有用。

另一个功能为f.moveopaque。它也移动一个视窗,但不像f.move,它并不会
给你一个指示视窗新的位置的方格,你直接拖拽整个视窗本身。这可以让整个萤
幕清爽些,但比较慢,且一般视窗移动时会有抖动的现像。

19.2.2 定义你自己的选单

f.menu是一个非常强大的uwm 的功能:它让你定义你自己的选单。此选单可选
用到uwm 本身的功能,或任何的shell 命令,或一个特定的动作,像是在一个
剪缓冲区插入本文。

在你的建构档中定义一个选单共有两个步骤。首先你定义选单上所需的
系结,其次你定义选单本身的内容。系结的部份像我们先前所用过的,但在尾
端增加了一栏选单名称。例如WindowOps 选单 (藉著在背景视窗中按下中按钮
来呼叫)的系结是:

f.menu = : root : middle down : "WindowOps"

在此,选单名称既是用以显示选单出现时的名称,也连结到建构档中的选单内
容规格。

选单内容的格式很简单:对每一个选择项,包含了一列当选择项出现在选
单的 "名称" ,和当它被选择到时所做的动作。让我们观察一个缩水的WindowOps
定义:

menu = "WindowOps" {
New Window : !"xterm &"
RefreshScreen : f.refresh
Redraw : f.redraw
Move : f.move
}

从这里,我们可以看到其语法为:

menu = "menu name" {
...
selection lines
...
}

选单名称和系结所指定的相同。选择项列包含了选择项名称,分隔的冒号,和
负责的动作。这些动作为下列三者之一:

1.一个uwm 的功能:只用到它们的名称,在上例为move那一列。

2.一个shell 命令:命令包含在双引号中间 (用shell 的& 语法使其在背
景视窗中执行) 且在前面加一个惊叹号。在上例为xterm 那一列。 (如
果你省& ,uwm 将被悬置 (hang) 起来,等待命令的完成,如果此程式
为X的应用程式,它需要uwm 来安排它的视窗,这将会招致麻烦)。

3.一个本文字串:这将插入到一个 "剪" 的缓冲区,而後你可以像平常一
样的 "贴" 它。

多种的选单连结到同一个键系结

通常你对一个特定的键/按钮的组合,只会系结到一个选单,但你可以对同一个
系结有多种选单:如果你在一个选单中不选择任何项目且把指标移动到选单的
边上,你将得到下一个选单。你已经实际地看过这种例子:在同时按下META和
SHIFT 键的情况下按下中按钮,你可以得到WindowOps 选单,然後是Preferences
选单。

系结多种选单非常的容易,只要在定义每一个系结时当作其它的系结并不
存在,而在定义选单的内容时用标准的方式即可。例如uwm 的预设设定包含了
系结:

f.menu = meta | shift : : middle down : "WindowOps"
f.menu = meta | shift : : middle down : "Preferences"

注意一个选单只能定义一次,但你可以用它来做任意多次的系结。 (查看预设
设定,你将看到WindowOps 选单被定义了一次但使用到两次)。

指定选单的颜色

你可以指定在一个选单中所用的色彩。对选单名称标题、每一个选择项、指标
所在的高亮度选择项,你都可以指定一个前景和背景色彩。一个有色彩的选单
的格式如下:

menu = "menu name" (head-fg : head-bg : hilite-bg : hilite-fg) {
...
selection-name : (item-fg : item-bg) : action
...
}

以下为一个混合的□例,使你的WindowOps 能拥有更多的色彩:

menu = "WindowOps" (yellow : blue : red : green) {
New Window : !"xterm &"
RefreshScreen : f.refresh
Redraw : (navy : magenta) : f.redraw
Move : f.move
}

此选单标题为蓝底黄字,大多数的选择项为白底黑字 (预设值),只有 "Move"
选择项为紫红色底海蓝色字,而目前指标所在的选择项为绿底红字。

19.2.3 控制uwm 的参数变数

到目前为止,你可以用指定滑鼠和键的前後关系,来改变所指定的功能。在此
有一个另一种型态的uwm 的定制:你可以藉此改变许多内建功能操作的作法 (
mode) 和风格 (style),例如你可以指定在resize或move操作下,指示视窗新
的位置的九宫格,改变为只是一个外框而已。在指南页中有列出所有的变数和
它的意义,在此我们只提一些特别有用的,和解释一些比较模糊的。

让预设建构档中的设定无效:uwm 并没有结构抑制读取系统和使用者建构
档。(-b 不会影响 $HOME/.uwmrc)。欲取消早先档案中的设定,可以含入uwm
的变数resetbinding、resetmenus和resetvariables,将会分别的取消早先定
义的系结、选单和变数。 (确定你将这些变数放在档案的顶端,否则它将取消
在档案中所有在它之前的定义)。

限制视窗和表徵图在萤幕的□围以内:X允许你指定你的视窗位於萤幕的
任何位置,甚至部份或全部在萤幕之外,这样有时会引起麻烦。当你建立一个
视窗,uwm 并未提供任何的帮助。但当你使用f.newiconify对一个表徵图作解
除表徵图化,如果变数normalw 被设定,则视窗会被完整的放在萤幕中,且尽
量接近你用指标指定的位置。 (如果你包含了normali 变数,同样可用於表徵
图)。

控制push作用:预设f.pushxxx 功能将一个视窗往适当的方向推动一个像
素的距离。你可以藉著指定 push=num 来推动num 个像素。你也可以完全地改
变操作的作法:取代通常的推动固定数目的像素的作法 (叫做pushabsolute)
,你可以指定pushrelative:这种情况视窗会被推动num 分之一大小的视窗。
例如如果你指定

push=5
pushrelative

则一个f.pushup将把视窗向上推动视窗本身高度五分之一的距离。

防止uwm 功能锁定应用程式:预设一些uwm 的操作,像resize和move会导
致所有其它的client应用程式被冻结,也就是说,防止它们输出到它们的视窗
。你可以藉著指定nofreeze取消它。

如果你需要获得一些uwm 所属短暂视窗的视窗倾印,则这是必需的 (如在
图6 - 6 的resize盒)。 它的副作用为当使用resize和move时,外框格会大量
的闪动,以致难以看到。

19.3 结论


本章告诉你如何使用一些更多的uwm 的功能,现在你对系统有更多的经验且可
以利用它们。特别是看到不用预设选单如何建构视窗,它使你工作的更迅速。

本章的第二个部份,列出你如何能定制uwm :如何附属uwm 的内建功能到
指定修饰键和滑鼠动作的组合,如何定义一般性的选单,如何使用uwm 的参数
变数修改操作的作法。

在结束之前说一点题外话,uwm 和 xterm、xclock、xedit等一样,只是server
的一个client程式而已。所以,远端地执行uwm 是可能的,例如在saturn执行
uwm ,但是指定 -display venus:0,所以它是venus 的视窗管理器。这解释
了网路元素深殖於系统,在一般工作站,这只是好奇,但在X终端机 (它不提
供一般性目的的处理 (processes)) 它实际地需要。

我们现在接近尾声:你已有所有你执行视窗系统的所需的功能。你有视窗管理
器、应用程式、便利的工具、视窗有关的公用程式、大□围的设施所以可以修
改以适合你的显示器、你网路上的建构和你比较喜欢的工作。下一章,我们将
会把目前所学的放在一起,告诉你如何管理你完整的工作周期,且我们将包含
定义uwm 选单和perferences的实际的□例。

=====
(http://www.fanqiang.com) 进入【UNIX论坛】

freesky64 04-03-15 12:51

第20章 全部放在一起 -- xdm
本文出自: 作者:cuteyu 整理 (2001-10-10 08:00:00)
现在我们已涵盖了你需要用到X的所有个别的项目,你知道如何启动系统,
如何设定一个视窗管理器的执行,如何执行应用程式,如何从不同的角度定制
系统,最後,如何退出系统。

本章中,我们把这些分开的部份放在一起,且描述一个完整的档案设定,
用来定制涵盖所有的□例功能系统机器环境。在本章我们将看到我们所要介绍
给你的最後一个X的工具:显示管理器(display manager) -- xdm,它提供一
个精巧和清楚的方法在你的机器上启动X。


20.1 我们需要做些什麽

当我们启动之後,我们需要安排萤幕,让一些我们在整个执行期间中都会
使用的应用程式适得其所,让一些偶然用到的则以表徵图为开始时的表示方式。
我们需要执行视窗管理器,对某些种类的功能做一些设定。详细来说,我们需
要下列的程式:

.一个xterm 的主控台,在萤幕左上角。

.uwm 在背景下执行。

.一个我们的(正常)编辑器的全萤幕xterm 视窗,以表徵图启始。

.在右上角一个(较一般为小)的时钟。

.xbiff 在时钟之下。

.一个计算器在右下角。

.一个用到我们所有最小的字型的表徵图化的xterm ,它的高度为screen高。

.在xbiff 之下,排列我们使用远方机器的频率图。

除了程式之外的项目:

.设定背景视窗为亮灰色。

.启动键盘滴答(key-click) 的功能。

.从我们常用的网路主机存取到我们的server。

.载入我们对所有client用到的server设定的resource,在16章我们定义
的$HOME/.Xresources 档案中,根视窗RESOURCE_MANAGER性质之上。

.启动一个screen saver。

并且我们需要uwm 有选单让我们能够:

.容易地存取在网路上其它的主机。

.变更一些键盘和滑鼠的设定,且设定背景视窗的颜色。

.启动那些我们偶而会用到的应用程式。

.启动一些被选定的示□程式。

对这些我们自己的设定,在我们网路上其它的使用者需要不同的初始设定,
所以我们需要安排每一个使用者依他们自己的喜好设定,理想上,使用者应能
自行设定而毋需藉系统管理者的帮助,下一节我们来看程式xdm 如何能帮助我
们达成这些目的。


20.2 xdm -- X显示管理器(X Display Manager)的概观

xdm 管理一或多个显示器,xdm 可在同一机器或远方的机器上执行。它可
以做到所有xinit 能做到的,而且更多。它所隐含的概念为它应控制当你在X
工作时的完整周期 (session),意即从你进入直到结束视窗系统的周期。(用
xinit ,有效周期为当你执行xinit 开始,到你结束(logout)最初的xterm
视窗和关闭server。)

xdm 较这更进一步:你可以用它执行一个不确定的周期。当一个结束,下
一个便准备开始。实际上,如果你有需要,它让你不变地指定一个显示器。

xdm 完全取代xinit 。从现在起你可忘掉xinit ,而且不再需要使用它,
我们在最初使用xinit 的原因为它较易观察和了解系统的运作。

xdm 是一个非常灵活的程式,你几乎可用它建构任何你所需要的,在进一
步深入之前,让我们观察一个□例周期的预设行为,然後我们来看一看你如
何改进当一个使用者进入X系统所看到的初始介面。


20.2.1 一个用xdm 的□例周期

我们将使用xdm 来设定在我们机器上执行的X。你的机器已经启动,但尚
未有视窗系统在其上执行。用下列的命令启始xdm

xdm

xdm 开始执行,你几乎立刻又看到你的shell 提示。然後萤幕背景变更为
通常灰色形式,且你看到一个大的X游标,所以你知道server已经启始。

接下来是一长段修止状态 -- 大约接续15秒或更久 -- 而後突然间一个带
著欢迎标题的视窗出现了,要求你的登录名称(login name)和密码(password),
如图20-1(这是xdm 的authentication widget )。输入你的使用者名称和密
码,又过了一会儿,你可以看到一个xterm 视窗在左上角出现,就如同图5-3
一般,从现在起,你工作的方式和以前相同 -- 启动你的视窗管理器,执行应
用程式等等。

┌——————————————————————┐
│ FIG 20.1 P.251 │
│ │
│ 图20-1 xdm 的 authentication widget │
└——————————————————————┘


当你需要结束时,你也可用像以前相同的方式结束:logout最初始的xterm
视窗。但这里xdm 和xinit 有不相同的地方,代之关掉server的是,回到非X
的环境,萤幕回到最初始灰色的背景,过一下子之後,你又再度看到X的登录
视窗。事实上,xdm 是执行一个循环的周期。

注意:就像许多的Unix程式,最大的登录名称长度为8 个字元 -- 如果超
过这个长度,login 将会失败。(如果你的实际login 程式允许你使用较长的
名称,这种限制也许让你感到奇怪。)

关闭xdm

有时你可能需要完全地关闭X。为了做到这点,你需要关闭xdm 。

在MIT 版中的server,会依循如果收到Unix讯号SIGTERM ,便会执行中止
程序。xdm 利用到这点:如果你送给它一个SIGTERM ,它将中止所有它所控制
的server後离开。这就是你中止系统的方法。

欲实际地中止xdm ,可以在一个xterm 视窗(在你的机器上)用ps来找出
xdm 的process-id,而後用kill送给它SIGTERM (你将看到数个xdm 处理的执
行:那个最年轻的便是你要的,也就是说,最低的process-id)。例如,在我
们的机器上执行中止的动作:

venus% ps ax 1 grep xdm
1997 ? IW 0:00 xdm
1998 ? IW 0:00 xdm
2000 ? IW 0:00 xdm
2078 p0 S 0:00 grep xdm
venus% kill -TERM 1997

你所有的应用程式将被强迫中止,server也随之关闭。

注意:当相关於X的每一件事都结束後,你的萤幕可能只显示通常X背景
的灰色形式,没有任何的shell 提示或任何事。不要被愚弄了:你的shell 已
准备好接受你的命令 -- 按下RETURN键你将会看到。(因为在你以交谈式下
xdm 命令之後,shell 已将提示号送出,所以不再重覆 -- 除非你按下RETURN)。


20.3 有关xdm 的更多

我们在前所述为xdm 的预设模式的操作,所以看起来并没有比xinit 提供
得更多,如果你使用一个正常的工作站或显示器,一些外貌将不是很有趣。无
论如何,X终端机(x-terminal)是一个日渐增加的大众化设备,而xdm 可大量
地简化管理类似的系统。X终端机通常没有它自己的档案系统,且不能支援一
般目的的程式,必需在网路的某处执行包含视窗管理器和显示管理器的控制终
端机软体,xdm 正是符合此需要的软体。

xdm 在下列这些场合较xinit 为优:

.它可控制数个server,也暗示说,其中有一些为远方的server,也许是
在X终端机或相当小的工作站上。

.它提供密码来存取系统,同样地,在X终端机上非常有用(但在一个你
已经login 的工作站会有一点困扰。)

.它提供无限期的X的周期。你可以建构显示器经常性地以X操作,所以
使用者毋需担心如何启始系统。

.它具有高度的建构性,系统管理者可以设定依机器特性的启始和结束程
序,掌握这些项目以供记帐(accounting),授权(authorization) ,档
案系统等之用,且能让每一个个别的使用者全□围性地修定他们所需的
自己的环境。

.从使用者的观点,它提供一个乾净而简单的方法来启动系统。

所以大体上,xdm 主要是一个系统管理工具,但它也提供让一个普通使用
者定制他所希望的一致和一贯地系统架构。

xdm 的指南页包含了大量的有关如何使用系统的教学资讯和指引,在此我
们不再重覆,我们将在以下的章节说明如何正确地建构xdm 以提供在本章一开
头所描述的环境。

xdm 真的非常有*性,且你可以用许多不同的方式选择设定,我们将使用
最简单的处理,并试著大致和指南页的描述保持一致,偶而我们在一些档
案中使用不同的名称,用以强调此名称并非硬性的规定。

在我们工作的周期中,请对我们事实上在扮演两个不同的角色保持概念:
第一是系统管理者,对於使用系统的任何人来设定xdm ,第二是一般的使用者
,为我们自己的需求设定xdm 。


20.3.1 系统管理者对xdm 的建构

预设xdm 先查看档案

/usr/lib/X11/xdm/xdm-config

如果它存在,会把它当成多设定几个其它参数的resource档案。我们将使用它,
因为它可简化我们的工作。

指南页会列出所有你能藉xdm-config档案设定的参数,但我们较有兴趣的有:

.包含一个server的目录的档案名称。

.当任何错误发生时,xdm 用来记录的档案名称。

.包含和启始系统有关的档案系统名称。

.当server启动後执行程式的名称,这个程式定义了你的”周期” -- 当
这个程式中止时,xdm 视其意义为你的周期已结束,且回到它login 时
的顺序,预设这个程式为xterm ,就和使用xinit 一样,你的周期持续
直到你logout你初始的xterm 。

这是我们已在系统上定义的设定:

DisplayManager.severs: /usr/lib/X11/xdm/our-server
DisplayManager.errorLogFile: /usr/lib/X11/xdm/errors
DisplayManager*resources: /usr/lib/X11/xdm/our-resources
DisplayManager*session: /usr/lib/X11/xdm/our-session

(我们已选择保持所有xdm 相关的档案在目录/usr/lib/X11/xdm,这只是代表
名称,你可以用任何你喜欢的目录。)

所以你可以看到我们使用xdm-config,实际上是一个两步骤的处理方法,
首先我们定义在xdm-config中的一些档案名称,接著我们来设定方才命名的档
案。现在我们来看一下我们在xdm-config中定义的每一个resource。

xdm 的server的名单

这个被DisplayManager.servers设定的档案的resources 包含了一个xdm
能管理的server的名单。每一列中包含了server的名称(也就是显示器),
server的型态(type),和型态有关的项目。

型态指出了显示器是本地的或远方的。和是否为无限或单一的周期(详见
xdm 指南页)。我们将使用型态localTransient -- 单一周期在本地显示器上
-- 因为以此方式,如果发生任何错误,我们不致於陷入无穷回圈中。稍後,
当我们每件事都设定好且执行无误的话,我们会将型态改为本地而循环的周期。

对本地的显示器而言,和型态相关的讯息是在此显示器上执行的server程
式的名称及其任何所需的引数。对远方的显示器,此讯息可被忽略,但你仍需
输入一个假的(dummy) 程式名称。

所以,在我们所建立的档案/usr/lib/xdm/our-servers包含这一行:

:0 localTransient /usr/bin/X11/X :0

(如果我们喜欢执行循环周期,此档案便不再需要 -- 预设设定会做到我们所
需要的 -- 所以我们在建构档中不需定义DisplayManagers.servers resource。)

xdm 的错误登录档案

此档案从xdm 和xdm 的周期程式接收所有错误的讯息,且如果你的xdm 设
定工作发生问题的话,这是第一个需要查看的地方。

当你开始设定你的系统,对此档案设定任何人均可写入,否则,有问题的
程式可能因没有写入许可而无法在档案中记录。

启始时的resource档案

此档案包含一个resource的名单,在Authentication Widget 启始之前被
xrdb载入。因此,你能用它来为那些widget设定resource。(你当然也能放置
任何其它的resource规格,但通常周期程式的使用者设定载入时会凌驾其上,
所以通常不把其它的规格放在这里。)

authentication widget resource的预设设定在某些情况是很细的,但为
了举例,我们只设定和bunner不同的标题,我们建立我们的档案

/usr/bin/X11/xdm/our-resources 包含一行:

xlogin.Login.greeting:X-Window on the Plants network

xdm 的"Session(周期)"程式

你可以指定任何程式为你周期中所需的程式,可是当周期结束,你通常选
择一个程式让你能启始其它的程式,你能依赖xdm 的预设设定执行xterm ,但
这种方式每当xterm 执行时你仍必需手动所有你的设定。我们需要定义我们的
周期程式来做所有我们的设定,且保持活动(active)的状态直到我们结束它为
止,但记住,我们希望使用者如果需要能定义他们自己的周期程式,所以我们
将使用两阶段的处理,如果是系统管理者,我们将设定一个一般性目的,基础
的,周期程式来召换一个使用者自己的程式(如果它存在),但其它方面将执
行一个合理预设。当个别的使用者,我们将定义我们自己的设定周期,它将被
xdm 的一般目的程式执行(我们在另外一节讨论它)。

我们的基本的site-wide 周期程式非常简单,如果使用者有设定档案
$HOME/.Xsession 的常规我们便使用之,否则,我们将执行合理的预设 -- 启
动uwm 而後传递控制到一个xterm(xterm为我们指定在萤幕左上方的那一个)
。但在做之前,我们先检查是否使用者设定了档案$HOME/.Xresources(其它的
常规),如果有的话,我们用xrdb载入它。一个完整的程式名单如图20-2。

┌——————————————————————┐
│ FIG 20.2 P.257 │
│ │
│ 图20-2 程式/usr/lib/X11/xdm/our-session │
└——————————————————————┘

20.3.2 我们自己对於xdm 的建构

现在我们改变角色:我们不再是系统管理者,而是一个使用者。我们可以
依赖系统管理者已定义之预设周期,但我们比较喜欢定义自己的周期,所以我
们要获取那些说明我们所需的起始设定。

我们的实例.Xsession

我们已建立我们自己的$HOME/.Xsession,如图20-3,且此萤幕初始的建构
在它执行之後会如图20-4。此程式的操作十分直接,但当你自行设定时有一些
要点需要注意,且当你建立site-wide 周期程式也是一样。我们假设你的周期
程式是一个shell :虽非必定,但通常都是(除非你要写一个xetrm 的复杂的
代替品)。

┌——————————————————————┐
│ FIG 20.3 P.258 │
│ │
│ 图20-3 $HOME/.Xsession 程式 │
└——————————————————————┘

┌——————————————————————┐
│ FIG 20.4 P.259 │
│ │
│ 图20-4 我们初始化後的萤幕 │
└——————————————————————┘

.档案中的命令依序排列,所以最後一行所执行的是一个程式,它可以持
续整个你的周期。(因为,当此程式结束,则周期程式结束,且每一件
事也均将结束)。

.除了在背景中最後的命令所有的命令均被执行,也就是说,在命令列最
後加一个ampersand(&) 号。如果你不这样做,此周期将从不获取过去
的任何不确定地执行的程式。例如:在我们的实例程式,如果我们在uwm
那一行省略"&" 号,uwm 会启动,但在uwm 结束时,它的下一行将不会
继续执行,绝不!

.最後的命令必为exec的命令,所以它继续执行且保持你的周期继续活动。
(如果你像其它命令一样在背景中执行它,它会好好的执行,但此周期
程式执行至档案结束将会中断,而结束周期。如果你不用exec,且省略
"&" 号,则它会执行且此周期将完美地持续工作,你只是较你所需的多
执行了一个处理,就如同你仍有最後的程式(last program)和周期程式
本身。)

.对所有的程式建立视窗时设定geometry规格 -- 否则当它们启动时你将
以”手动”方式指定它们的位置。

.在档案中最後一行的程式通常用来启动xterm ,因为它定义了你周期的
生命期,在你执行X时此视窗总是存在,所以你通常设定两个特别的选
项:

1 .使用-C选项使得xterm 为一个”主控台”,所以系统讯息会在它的
视窗显示。

2 .设定-ls 选项使它的shell 为login shell 。如此使得shell 读入
你的.login或.profile,所以你的环境变数会适当地设定。(如果
你不这样做,你只有一点儿定义:DISPLAY,HOME,USER,PATH和SHELL.)

3 .此周期程式档案必需有执行许可。使用上述site-wide 周期程式,
这对使用者周期script不是绝对需要,它实际是对site-wide 程式
本身。(如果那不能执行,你只能获得xdm 的预设设定。)

在装设你的.Xsession 和依赖它启始你的视窗周期之前,最好能够从一个
xterm 视窗启动你的.Xsession 以严格测试它。

20.4 我们自己的uwm 建构

我们需要设定四个uwm 选单:一是连接到其它的主机,二是执行一些X的
应用程式,三是设定一些键盘和滑鼠参数(有点儿像预设的Preference选单),
四是执行展示程式。

对我们的”主机”选单,我们现在希望只要藉著从选单中选取主机名称便
可在任何主机上启动xterm 。我们常常需在mars上做一些系统管理,所以我们
将设定选择在其上为超级使用者(super user),我们将在左下角建立一个超级
使用者视窗,但对一般的xterm ,我们省略geometry规格,所以当它建立时,
我们可以明确地定位它。我们将以META-SHIFT-LEFT 系结 (bind) 此选单。所
以在我们的$HOME/.uwmrc中我们包含了此列。如图20 - 5.

┌——————————————————————┐
│ FIG 20.5 P.260 │
│ │
│ 图20-5 在$HOME/.uwmrc的主机选单 │
└——————————————————————┘

其它三个选单我们不常用,所以我们均以META-SHIFT-MIDDLE 系结它们,
这没什麽特别,但注意Misc. 不包含一个内建的混杂的uwm 和shell 命令。这
些对应到.uwmrc的项目如图20 - 6。

┌——————————————————————┐
│ FIG 20.6 P.261 │
│ │
│ 图20-6 在$HOME/.uwmrc中其它的选单 │
└——————————————————————┘

uwmrc 剩馀的部份 (见图20 - 7),我们用以设定定制系结和一般视窗建构
操作的参数。注意下列几点:

.我们选择一个较预设稍大的字型 (用"menufont=fixed"),降低选单选项
中的空白空间 (用"vmenupad=1"),所以选单不会很大。(menufont 可能
未在指南页中描述)

.我们设定所有的选单,系结和变数可被重设(用resetmenus等等),这
清除了uwm 的建构,所以我们不用混杂的预设建构和我们自己的建构做
结束。

.如果可能,我们较愿意使用滑鼠的UP事件函数而非DOWN:这种方式你能
藉著在松开按钮之前按下其它的按钮,来改变你的主意或中止操作。
(但你不能将move操作系结到一个UP事件。)

.我们已包含一些定义uwm 选单的功能 -- 一个是杀掉应用程式视窗,另
一个是重新启始uwm 。它们不是必要的,但当你对系统很有经验时会很
有用。

┌——————————————————————┐
│ FIG 20.7 P.262 │
│ │
│ 图20-7 在$HOME/.uwmrc中系结和参数的设定 │
└——————————————————————┘

20.5 结论

你已涵盖了core版中所有使用者层次的程式和如何使用它们。

你现在能够自行设定和修订成你所需的系统。大部份的修订局限於你的家
目录(home directory)中的三个档案 -- .Xsession, .Xresources和.Uwmrc
-- 所以它很容易控制你的环境,且可在你的系统管理者所设定的任何设计下
执行。

我们涵盖了一大堆的材料,且有许多的新观念包含进来,所以你尚未能完
全吸收它,这不是我们所预期的,现在因为你已用过系统一段期间,所以回头
重读系统的观念概观,你将发现你了解更多,且你可看到在系统表面之後的动
机。

当你使用系统越多次,你将发现有一些面貌是你不喜欢的,但这些系统并
没有。有一些工具和视窗相关程式可简化你的工作,且有一些应用程式对X提
供介面有大利益,但不包含在此版本中,别失望! -- 看contrib 版软体来取
代它。现在你知道基本系统的限制和能力,看一看其他的人利用它们做了什麽
,这也是你可能需要系统做的。

本书的目的是让你有一个开始 -- 它并无意当一本完整的参考手册。在某
些地方我们忽略了一些程式不常用的细节和那些对初学者易产生混淆和较复杂
的部份。但现在你能回头重读系统提供的文件,指南页和其它的资料是非常庞
大的,如果你知道你要做什麽和只是要某一点复习一下你的记忆,或找出某些
事如何正确的执行,你将在其中的某处找到它们。现在你已会使用系统和中止
系统,你能明白参考手册的意义,为了帮助你找出你自己贯通文件的方法,我
们有一个附录包含了在这个版本中的资料名单,告诉你在何处找到它们,和如
何更进一步的去探讨系统。

所以,现在我们只剩下一句话给您:祝一切顺利!
(http://www.fanqiang.com) 进入【UNIX论坛】


所有时间均为[北京时间]。现在的时间是 22:17

Powered by vBulletin 版本 3.6.8
版权所有 ©2000 - 2010, Jelsoft Enterprises Ltd.
官方中文技术支持: vBulletin 中文
版权所有 ©2002 - 2009, LinuxSir.Org