• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            X Window 程式設(shè)計(jì)

            X Window 程式設(shè)計(jì)入門(mén)
            http://cnpa.yzu.edu.tw/~thinker 作者:李圭烽 (Thinker; Thinker.bbs@bbs.yzu.edu.tw) (2001-06-01 17:04:00)

            --------------------------------------------------------------------------------
            這只是入門(mén),僅僅是入門(mén)而已。所以并不是很完全,卻可以給你一個(gè)概觀的了解,讓你知道 X Window programming 過(guò)程和所需的基本知識(shí)。如果你需要更進(jìn)一步的資料,請(qǐng)參考 Xlib - C Language X Interace Referrence。對(duì)於內(nèi)容有任何意見(jiàn),也歡迎指教。本文件由李圭烽(Thinker; Thinker.bbs@bbs.yzu.edu.tw) 所作。作者許可本文件於網(wǎng)路上自由流傳,但保留其它之著作權(quán)力。
             
            版權(quán)宣告 LICENSE.txt 
            第一章 什麼是 X Window  
            第二章 X Programming 的第一步  
            第三章 繪圖(Graphic) 
            第四章 Event 
            第五章 Window 
            第六章 Inter-Client Communication 
            第七章 Resource Manage 
            第八章 輸入裝置 
            第九辛 Window & Session Manager 
            第十章 Take it all together!! 
            未完成 尚在努力......... 



            --------------------------------------------------------------------------------

            相關(guān) link
            Kenton Lee:X Window System Technical Glossary (http://www.rahul.net/kenton/xglossary.html) 
            The FVWM Homepage  (http://www3.hmc.edu/~tkelly/docs/proj/fvwm.html)
            X man pages  (http://www.x.org/consortium/R6doc/man/X11/)
            VXP: Visual X Programming Interface  (http://www.shsu.edu/~stdyxc05/VXP/)

            --------------------------------------------------------------------------------

            版權(quán)宣告 LICENSE.txt 

            本文為文章著作權(quán)宣告

            凡附本文之文章, 皆需完全遵守本文之規(guī)定.
            以下所有參照到附本文之文章時(shí), 皆稱以"原文章"三字代替.

            1. 原文章準(zhǔn)予任何人, 進(jìn)行任何形式的修改.
            2. 原文章準(zhǔn)予任何人, 以電子形式傳送.
            3. 修改原文章所得的文章稱為延伸版.
            4. 所有延伸版皆需附本文.
            5. 最初之原文章, 即非經(jīng)由修改或增加其它文章內(nèi)容,為獨(dú)立創(chuàng)作而
               得之文章.
            6. 最初之原文章的原子形式, 包含紙面出版權(quán)為著作人所有.
            7. 個(gè)人或團(tuán)體, 經(jīng)由單獨(dú)修改或增加原文章內(nèi)容超過(guò) 10% 得一延伸版,則
               該個(gè)人或團(tuán)體得擁有該延伸版的原子形式之商業(yè)出版權(quán).
            8. 個(gè)人或團(tuán)體, 經(jīng)由單獨(dú)修改或增加原文章內(nèi)容, 但修改或增加部分未超
               過(guò) 10% 而得一延伸版, 則個(gè)人或團(tuán)體不具有該延伸版的原子形式之商業(yè)
               出版權(quán).
            9. 非符合 7 和 8 兩款情形的商業(yè)行為, 皆不被允許.
            X Client 和 X Server 
            X Window 為 一 Client-Server 架 構(gòu) 之 GUI 。 Client 指 的 是 在 X Window 下 執(zhí) 行 的 應(yīng) 用 程 式, 需 要 X Server 為 其 服 務(wù) ; Server 指 的是 整 個(gè) 管 理 你 的 桌 面 的 X Window 系 統(tǒng) , 稱 為 X Server 。 X Server 除 了 負(fù) 責(zé) GUI 介 面 之 管 理 和 提 供 Client 端 的 服 務(wù) 之 外 , 并 且 還 管 理 系 統(tǒng) 資 源 ( Resource ) 和 事 件 ( Event ) 之 發(fā) 生 和 傳 遞 。 
            Display 和 Screen
              在 一 個(gè) X Wintow System  可 以 包 含 多 個(gè) Screen , 而 Screen 則 是 一 個(gè)實(shí) 際 的 Monitor 或 是 Device 。 每 個(gè) Display 則 可 以 包 含 多 個(gè) Screen 。 Display 指 的 是 一 群 Screen 和 一 個(gè) pointer ( 一 般 是 滑 鼠 )加 上一 個(gè) 鍵 盤(pán) 的 集 合 。  

            Event 和 Request
              當(dāng) Client 需 要 在 顯 示 幕 上 開(kāi) 一 個(gè) window 或 是 顯 示 一 段 文 字 或圖 形 時(shí) , 則 Client ( 即 X 下 的 應(yīng) 用 程 式 ) 向 Server 提 出 一 個(gè) Request ; Server 收 到 Request 之 後 , 則 依 據(jù) Request 的 內(nèi) 容 , 提 供 相 對(duì) 應(yīng) 的 服 務(wù) 。當(dāng) 使 用 者 在 屬 於 某 一 Client 的 window 內(nèi) , 按 了 一 下 滑 鼠 的 右 鍵 , 或 是 敲 了 鍵 盤(pán) 上 的 一 個(gè) Key , 則 Server 會(huì) 發(fā) 送 一 個(gè) Event 給 該 Client 。 而 Client 只 要 依 據(jù) Server 送 回 來(lái) 的 Event, 即可 判 斷 有 何 事 件 發(fā) 生 , 然 後 依 據(jù) 所 發(fā) 生 的 Event 發(fā) 生 相 對(duì) 應(yīng)的 動(dòng) 作 。  

            X Window 的 網(wǎng) 路 特 性 
              Client 和 Server 不 一 定 要 在 同 一 部 電 腦 上 執(zhí) 行 ; Client 和 Server 可 以 是 接 在 網(wǎng) 路 上 的 兩 臺(tái) 電 腦 。 當(dāng) Client 要 向 Server 發(fā) 出 Request 時(shí) , 可 以 透 過(guò) 網(wǎng) 路 向 執(zhí) 行 Server 的 機(jī) 器 發(fā) 出 Request , 然 後 送 達(dá) 給 Server 處 理 。 同 樣 的 , 當(dāng) Server 要 向 Client 通 知 Event 的 發(fā) 生 時(shí) , 也 可 以 透 過(guò) 網(wǎng) 路 向 Client 傳 送 。 因 此 你 可 以在 A 地 的 電 腦 上 執(zhí) 行 某 一 X Window 應(yīng) 用 程 式 , 而 在 B 地 透 過(guò) X Server 觀 察 程 式 執(zhí) 行 的 結(jié) 果 。  

            一 個(gè) X Window 的 程 式 , 也 就 是 Client , 在 同 一 時(shí) 間 可 以 和 一 個(gè) 以 上 的 Server 溝 通 。 也 可 以 同 時(shí) 和 多 個(gè) Server 建 立 連 接 , 在 多個(gè) Server 上 顯 示 , 并 接 受 多 個(gè) Server 的 訊 息 。 而 X Server 也 可 以在 同 時(shí) 間 內(nèi) , 接 受 多 個(gè) Client 送 來(lái) 的 訊 息 , 并 做 對(duì) 應(yīng) 的 處 理。 

            Window 的 階 層 性 
            X Window 內(nèi) 的 window 是 有 階 層 關(guān)  的 , 這 階 層 關(guān)  可 以 畫(huà) 成 一樹(shù) 狀 圖 。 在 樹(shù) 狀 的 最 上 層 是 root window , 這 個(gè) window 是 Server 所特 有 的 。 除 了 root window 之 外 , 每 個(gè) window 都 有 一 個(gè) parent window , 即 是 在 樹(shù) 狀 圖 上 的 上 一 層 window 。 在 樹(shù) 狀 圖 的 下 一 層 window 稱 為 child window 。 每 個(gè) window 可 以有 多 個(gè) child , 但 不 一 定 每 個(gè) window 都 有 child 。 而 child window 下面 還 可 以 有 child 。   Win 1 和 Win 2 皆 為 root 的 child, root 則 為 Win 1 和 Win 2 的 parent 。 Win 2-1 和 Win 2-2 和 Win 2-3 則 為 Win 2 的 child , Win 2 則 為 Win 2-1 和 Win 2-2 和 Win 2-3 的 parent。而 root 和 Win 1 和 Win 2 則 皆 為 Win 2-1 和 Win 2-2 和 Win 2-3 的 ancestor。而 root 則 為 Win 1 和 Win 2 的 ancestor。  

            在 顯 示 幕 上 , child 永 遠(yuǎn) 在 parent 上 面 ( 即 parent 被 child 蓋 住 ) 。 而 child window 可 以 比 parent window 大 , 但 超 過(guò) parent 的 部 份 , 會(huì) 被 截 掉 而 不 顯 示 在 顯 示 幕 上 。 
             藍(lán) 色 部 分 為 parent window , 而 草 綠 色 部 分 則 為 child window 和 parent window 重 疊 的 部 分 。 在 parent window 外 面 灰 色 部 分 也 為 child window 的 一 部 分 , 但 其 為 超 過(guò) parent window 視 窗  圍 之 外 的 部 分 , 所 以 不 會(huì) 被 顯 示 出 來(lái) 。 草 綠 色 部 分 則 是 顯 示 child window 的 內(nèi) 容 。  


            當(dāng) 顯 示 幕 上 有 多 個(gè) window 存 在 時(shí) , 可 能 會(huì) 發(fā) 生 window 重 疊 的 現(xiàn)象 。 而 在 下 面 的 window 會(huì) 被 在 上 面 的 window 蓋 掉 ; 當(dāng) 上 面 的 window 移 離 目 前 位 子 , 而 使 原 本 被 蓋 的 部 分 重 新 暴 露 出 來(lái) , 這 時(shí) 就 必 需 重 畫(huà) 露 出 來(lái) 的 部 分 。 但 X 并 不 保 證 會(huì) 保 存 你 原 本顯 示 在 window 上 的 資 料 。 因 此 這 時(shí) Client 就 必 需 負(fù) 起 重 畫(huà) 的 責(zé) 任 了 。 當(dāng) X Server 沒(méi) 保 存 重 新 被 暴 露 出 來(lái) 的 部 份 的 資 料 時(shí) , X Server 會(huì) 送 出 Expose Event 給 Client, 通 知 Client 那 些 部 分 需 要 重 畫(huà)。 然 後 Client 就 必 需 決 定 是 否 要 重 畫(huà) , 或 是 采 取 其 它 的 處 理 方 式 。 

            X Window 的 外 觀 
            在 很 多 的 GUI 中 , 如 OS/2 等 , 都 會(huì) 提 供 Button, Scroll Bar, Menu 等 等 的 基 本 元 件 , 以 方 便 建 構(gòu) 程 式 的 外 觀 。 但 在 X 中 并 不 提供 這 樣 的 元 件 ; 相 反 的 , X Window 提 供 的 是 一 套 建 立 外 觀 風(fēng) 格 的 機(jī) 制 。 利 用 這 套 機(jī) 制 , 我 們 可以 建 立 各 種 不 同 風(fēng) 格 的 元 件 。 這 樣 我 們 即 不 必 限 制 在 系 統(tǒng) 內(nèi)定 的 風(fēng) 格 中 , 而 無(wú) 法 做 改 變 。 這 套 機(jī) 制 是 用 大 小 不 同 的 window , 組 合 建 立 如 Button , Scroll Bar 等 等 的 元 件 , 充 滿 了 彈 性 。 
            Window Manager 
            在 X 中 有 一 種 極 為 特 殊 的 程 式 , 稱 為 Window Manager 。 其 作 用 是管 理 Desktop 上 的 各 應(yīng) 用 程 式 的 window , 并 提 供 特 殊 風(fēng) 格 的 window 外 觀 。 不 同 的 Window Manager 有 不 同 的 外 觀 風(fēng) 格 。 因 此 ,我 們 可 以 更 換 不 同 的 Window Manager , 以 得 到 不 同 風(fēng) 格 的 window 外 觀 。 而 一 般 的 Client 則 必 需 和 Window Manager 合 作 , 以 得 到 良好 而 一 致 風(fēng) 格 的 window。 Window Manager 也 是 一 Client 程 式 , 和 一 般 的 Client 相 同 。 只 是 Window Manager 負(fù) 有 特 別 的 任 務(wù) ; 管理 Desktop 和 window 外 觀 。 
            為 了 得 到 良 好 而 風(fēng) 格 一 致 的 window, Client 和 Window Manager 必 需合 作 。 其 合 作 方 式 是 透 過(guò) 由 Client 傳 送 Hint 給 Window Manager , 而 Window Manager 以 後 , 則 會(huì) 參 考 Hint 的 內(nèi) 容 , 給 予 應(yīng) 用 程 式 所開(kāi) 出 的 window 適 當(dāng) 的 外 觀 。 但 Window Manager 不 一 定 會(huì) 依 據(jù) Hint 指 示 處 理 , 純 為 參 考 。 

            X Window 程式設(shè)計(jì)入門(mén)--第二章 X Programming 的第一步
            http://cnpa.yzu.edu.tw/~thinker 作者:李圭烽 (Thinker; Thinker.bbs@bbs.yzu.edu.tw) (2001-06-01 19:00:01)
            Index:
            基本步驟 
            建立一個(gè) display至 X Server 
            取得 display的相關(guān)資料 
            建立視窗 
            和視窗管理程式(Window Manager)溝通 
            顯示視窗 
            關(guān)閉(destroy)視窗 
            關(guān)閉 display 
            例 

            --------------------------------------------------------------------------------

            一個(gè) X 的程式的幾個(gè)基本步驟: 
            main() {
            建立一個(gè) display 至 X Server;
            取得 display 的相關(guān)資料;
            設(shè)定視窗(window)特性(Attributes);
            建立視窗(window);
            和視窗管理程式(window manager)進(jìn)行溝通;
            顯示(map)視窗;
            ......  ......
            ... 程式處理 ...
            .............
            關(guān)閉(destroy)視窗;
            關(guān)閉 display;
            }

            1. 建立一個(gè) display 至 X Server
            在程式開(kāi)始向 X Server 進(jìn)行任何的動(dòng)作之前,程式必需先和 X Server 之間建立一個(gè)連線(connection),我們稱之為 display。 XOpenDisplay 即為 Xlib 提供給我建立 display 的函數(shù)。 
            --------------------------------------------------------------------------------

            Display *XOpenDisplay(display_name)
            char *display_name;

            display_name 指定要連接之 server。如果 display_name 設(shè)定為
            NULL,則內(nèi)定使用環(huán)境變數(shù)(environment variable)
            DISPLAY 的內(nèi)容為連接對(duì)像。


            --------------------------------------------------------------------------------
            呼叫 XOpenDisplay 之後,會(huì)傳回一個(gè) Display 結(jié)構(gòu)。 Display 結(jié)構(gòu) 存放著一些關(guān)於 display 的資訊。 雖然我們可以直接存取 Display 結(jié)構(gòu),但我們不該逕自改變其內(nèi)容。 Xlib 有提供一系列的函數(shù)和巨集 (macro),我應(yīng)該透過(guò)這些函數(shù)和巨集(macro)存取 Display 的內(nèi)容。 以維持 Xlib 的正常運(yùn)作。
            display_name 或是 DISPLAY 環(huán)境變數(shù)(environment variable)的格式 如下: 


            --------------------------------------------------------------------------------

            hostname:number.screen_number

            hostname
            設(shè)定 display 所在主機(jī)(host)之名稱,在主機(jī)名稱之後緊接著的是單
            個(gè)冒號(hào)(:)或是雙冒號(hào)(::)。
            number 指定主機(jī)上,display server 的編號(hào)。一臺(tái)主機(jī)(host)上可能同時(shí)存
            有多個(gè) server,每個(gè) server 都會(huì)給與一個(gè)編號(hào),這個(gè)編號(hào)從零開(kāi)始
            。在 server 的編號(hào)後面有一個(gè)句點(diǎn)(.),這個(gè)依你是否設(shè)定後面的
            screen_number 而決定是否該加。
            screen_number
            每一個(gè) server 可能同時(shí)管理著多個(gè)顯示幕,而每一個(gè)顯示幕我們也給
            與一個(gè)從零開(kāi)始的編號(hào)。screen_number 也就是設(shè)定著這個(gè)編號(hào),做為
            default 的 screen。當(dāng)你使用 DefaultScreen 巨集或是 
            XDefaultScreen 函數(shù)時(shí),即會(huì)存取到這個(gè)值。


            --------------------------------------------------------------------------------
            舉例: 
            Display *display;

            display = XOpenDisplay("cnpa.yzu.edu.tw:0");

            建立與 cnpa.yzu.edu.tw 上第零個(gè) server 的 display。 
            2. 取得 display 的相關(guān)資料
            在我們建立視窗之前,我們必需對(duì)目標(biāo) display 和螢?zāi)?screen)的屬 性狀況有所了解。 我們可以透過(guò) Xlib 所提供的巨集(macro)和函數(shù) (function)取得指定 display 和螢?zāi)?screen)的資料,利用這些資料 以設(shè)定視窗參數(shù),以應(yīng)不同的螢?zāi)唤?gòu)合適的視窗。

            建立視窗,我們必需設(shè)定多種和目標(biāo)螢?zāi)?screen)相關(guān)的參數(shù)。我們就 這些參數(shù)設(shè)定的需要,介紹如何利用 Xlib 來(lái)取得關(guān)於 display 的資 料。


            --------------------------------------------------------------------------------

            DefaultRootWindow(display)

            Window XDefaultRootWindow(display)
            Display *display;

            display 指定至 X server 的連結(jié)(connection),即
            XOpenDisplay 所傳回之結(jié)構(gòu)。


            --------------------------------------------------------------------------------
            傳回預(yù)定螢?zāi)?default screen)的根(root)視窗。每一個(gè)視窗都有父視 窗(parent window),當(dāng)你要在程式開(kāi)啟一個(gè)最上層的視窗(top window);不是程式其它視窗的子視窗。那麼,由於己沒(méi)有其它更上層 的視窗可以當(dāng)父視窗,所以必需設(shè)根視窗(root window)為該視窗的父視窗 (parent window)。我們使用 DefaultRootWindow 取得預(yù)定螢?zāi)坏母?nbsp;窗(root window),可以在建立新視窗時(shí),以任一根視窗(root window) 做為新視窗的父視窗(parent window)。透過(guò)指定父視窗(root window) ,我們也指定了負(fù)責(zé)顯示新視窗的螢?zāi)?screen)。


            --------------------------------------------------------------------------------

            DefaultDepth(display, screen_number)

            int XDefaultDepth(display, screen_number)
            Display *display;
            int screen_number;

            display 指定連至 X Server 的連接(connection)。
            screen_number 指定螢?zāi)坏木幪?hào)。


            --------------------------------------------------------------------------------
            傳回指定螢?zāi)桓暣?root window)的預(yù)定深度(depth)。每個(gè)視窗都有 自己的深度(depth),深度影著該視窗所能顯示的顏色數(shù)。當(dāng)一個(gè)視窗 的的深度大,則其同時(shí)能顯示的顏色總數(shù)也會(huì)隨之增加。但,深度( depth)并非無(wú)限量的增加,會(huì)受限於硬的限制。一般我們會(huì)參考根視 窗(root window)的設(shè)定。


            --------------------------------------------------------------------------------

            DefaultScreenOfDisplay(display)

            Screen *XDefaultScreenOfDisplay(display)
            Display *display;

            display 指定一個(gè) X Server 的連結(jié)(connection)


            --------------------------------------------------------------------------------
            傳回指向預(yù)定螢?zāi)?default screen)的指標(biāo)。預(yù)定螢?zāi)?default screen)即建立 display 時(shí),在 display name 指定的 screen number。


            --------------------------------------------------------------------------------

            DefaultVisualOfScreen(screen)

            Visual *XDefaultVisualOfScreen(screen)
            Screen *screen;

            screen 指定適當(dāng)?shù)?nbsp;Screen 結(jié)構(gòu)。


            --------------------------------------------------------------------------------
            傳回預(yù)定螢?zāi)?default screen)的預(yù)定視覺(jué)(default visual)。在某些 顯示設(shè)備上,允許同時(shí)以多種不同的方式理顏色的顯示。我們可以任意 的方式,將深度(depth)為 8-bits 的圖素(pixel)對(duì)映到顯示的顏色。 也可以將深度(depth)為 24-bits 的圖素(pixel),以紅、黃、藍(lán)各為 8-bits 的方式對(duì)映到實(shí)際的顏色。圖素(pixel)指的是畫(huà)面上的一個(gè)點(diǎn) ,這指的是代表該點(diǎn)顏色的一個(gè)編號(hào)。例如,我們可能以 7 做為RGB 值為 0x9f7071 的顏色的編碼,則任何圖素(pixel)為 7 的點(diǎn),其顏色 則為 RGB 0x7f7071。

            3. 建立視窗
            我現(xiàn)在開(kāi)始建立新視窗(window)。視窗(window)建立之後,并不會(huì)馬上 在我們指定的顯示器(screen)上顯示出來(lái)。我們要經(jīng)過(guò)一道 map 的手 序後,視窗(window)才會(huì)正式在顯示器上顯示出來(lái)。在我們建立視窗( window)之後,在 map 之前,我們可以對(duì)新視窗(window)做一些設(shè)定的 動(dòng)作,以設(shè)定視窗(window)的行為特性。

            建立新視窗(window)要透過(guò) Xlib 所提供的 XCreateWindow 函數(shù)或者 XCreateSimpleWindow 函數(shù),XCreateSimpleWindow 是 XCreateWindow 的簡(jiǎn)化版。這兩個(gè)函數(shù)可用來(lái)建立新的子視窗。 
            --------------------------------------------------------------------------------

            Window XCreateWindow(display, parent, x, y, width, height,
            border_width, depth, class, visual, valuemask,
            attributes)

            Display *display;
            Window parent;
            int x, y;
            unsigned int width, height;
            unsigned int border_width;
            int depth;
            unsigned int class;
            Visual *visual;
            unigned long valuemask;
            XSetWindowAttributes *attributes;

            display 指定到 X Server 的連結(jié)。
            parent 指定父視窗(parent window)。
            x, y 指定視窗邊框(border)的左上角相對(duì)於父視窗(parent
            window的座標(biāo)。也就是以父視窗(parent window)內(nèi)部
            的左上角做為原點(diǎn)所求得的相對(duì)座標(biāo)。此座標(biāo)用來(lái)指
            定視窗的顯示位子。
            width, height 視窗內(nèi)部尺寸的寬度和高度,高度和寬度并不包括邊框
            (border)的部分。這些尺寸不能為度,否則會(huì)造成
            BadValue 的錯(cuò)誤結(jié)果。
            border_width 設(shè)定視窗邊框(border)的寬度,其單位為圖素(pixels)
            ,也就是指定其邊框的寬度是幾個(gè)圖素(pixels)。
            depth 設(shè)定新視窗的顏色深度(depth),若指定 depth 的值為
            CopyFromParent,則深度(depth)將會(huì)從父視窗(parent
            window)取得。
            class 指定視窗的類(lèi)別(class)。你可以指定為 InputOutput
            ,InputOnly 或 CopyFromParent 其中一種。若指定為
            CopyFromParent 則表示將由父視窗(parent window)取
            得。
            visual 設(shè)定視覺(jué)(visual)的種類(lèi)。設(shè)為 CopyFromParent 則會(huì)
            取自父視窗。
            valuemask 用以設(shè)定在 attributes 參數(shù)設(shè)定了那些視窗屬性
            (attribut)的遮罩(mask)。在這個(gè)遮罩(mask),每一
            bit 代表著一項(xiàng)屬性(attribut),我們以 OR 位元運(yùn)算
            ,將代表各項(xiàng)屬性的遮罩(mask)組合起來(lái)。若為零,則
            會(huì)乎略 attributes 參數(shù)。
            attributes 這是一個(gè)存放視窗屬性(attribut)的結(jié)構(gòu)(structure)
            ,配合設(shè)定正確的遮罩(mask),用以設(shè)定視窗的屬性。


            --------------------------------------------------------------------------------

            /* Values */

            typedef struct {
            Pixmap background_pixmap;
            unsigned long background_pixel;
            Pixmap border_pixmap;
            unsigned long border_pixel;
            int bit_gravity;
            int win_gravity;
            int backing__store;
            unsigned long backing_planes;
            unsigned long backing_pixel;
            Bool save_under;
            long event_mask;
            long do_not_propagate_mask;
            Bool override_redirect;
            long event_mask;
            long do_not_propagate_mask;
            Bool override_redirect;
            Colormap colormap;
            Cursor cursor;
            } XSetWindowAttributes;

            /* Window attribute value mask bits */

            #define CWBackPixmap (1L<<0)
            #define CWBackPixel (1L<<1)
            #define CWBorderPixmap (1L<<2)
            #define CWBorderPixel (1L<<3)
            #define CWBitGravity (1L<<4)
            #define CWWinGravity (1L<<5)
            #define CWBackingStore (1L<<6)
            #define CWBackingPlanes (1L<<7)
            #define CWBackingPixel (1L<<8)
            #define CWOverrideRedirect (1L<<9)
            #define CWSaveUnder (1L<<10)
            #define CWEventMask (1L<<11)
            #define CWDontPropagate (1L<<12)
            #define CWColormap (1L<<13)
            #define CWCursor (1L<<14)


            --------------------------------------------------------------------------------
            使用 XCreateWindow 可以建立任一視窗的子視窗(child window)。但在 程式一開(kāi)始時(shí),還沒(méi)有建立任何的視窗,因此也就無(wú)法建立任何視窗的 子視窗。我們使用根視窗(root window)做為父視窗(parent window)建 立其子視窗(child window),以根視窗(root window)的子視窗(child window)做為我們程式最上階層的視窗。

            每個(gè)都有各種的屬性,我們?cè)O(shè)定其屬性即會(huì)改變視窗表現(xiàn)出來(lái)的行為。 例如,深度(depth),邊框(border)的寬度等等的。Xlib 提供 XChangeWindowAttributes 這個(gè)函數(shù),設(shè)定任一 window 大部分的 Attributes(屬性)。 
            --------------------------------------------------------------------------------

            XChangeWindowAttributes(display, w, valuemask, attributes)
            Display *display;
            Window w;
            unsigned long valuemask;
            XSetWindowAttributes *attributes;

            w 指定設(shè)定的 window。
            valuemask 指定在 attributes 這個(gè)參數(shù),設(shè)定了那些 window
            attributes。這個(gè) mask 也是用 OR 運(yùn)算,將所有的屬性的 mask
            (遮罩)值組合起來(lái)。
            attributes 指定儲(chǔ)存屬性設(shè)定值的 XSetWindowAttributes 結(jié)構(gòu)。


            --------------------------------------------------------------------------------

            4. 和視窗管理程式(Window Manager)溝通
            在 X Window 環(huán)境下的程式,由於其視窗外觀并不是直接由 X Server 處理,代而之的是交由 Window Manager 處理。因此,我們的程式,必 需和 Window Manager 溝通合作,才能得到合適的視窗外觀并和其它視 窗和平共處。Window Manager 只會(huì)處理 top window,其它的非 top level 的 window 并不在其處理的圍。
            和 Window Manager 溝通的方式,是透過(guò)傳送 Hint 的方式。因?yàn)?nbsp;Window Manager 對(duì) client 對(duì)其視窗的設(shè)定,并不一定要完全接受, 只是做為參考而已,所以我們稱之為 Hint。除了這些 Hint 之外, 我們還可以透過(guò) Window Manager ,操作 top level 的視窗,使之 縮成 icon ,設(shè)定視窗 title 的名稱等等的。



            --------------------------------------------------------------------------------

            XStoreName(display, w, window_name)
            Display *display;
            Window w;
            char *window_name;

            window_name 指定視窗名稱,此名稱會(huì)被顯示在 title 上。


            --------------------------------------------------------------------------------
            此函數(shù)用來(lái)設(shè)定視窗的名稱,這個(gè)名稱將會(huì)被顯示在該視窗的 title 處。title 就像文章的標(biāo)題一樣,用來(lái)指明此一視窗,讓使用者可以 依據(jù) title 辨別不同的視窗。


            --------------------------------------------------------------------------------

            XSetIconName(display, w, icon_name)
            Display *display;
            Window w;
            char *icon_name;

            icon_name 指定 icon 的名稱,此名稱在視窗縮成 icon 時(shí)顯示
            出來(lái)。


            --------------------------------------------------------------------------------
            XSetIconName 用來(lái)設(shè)定 icon 的名稱。有時(shí)侯,當(dāng)我們?cè)谖災(zāi)簧贤瑫r(shí) 開(kāi)太多個(gè)視窗時(shí),整個(gè)畫(huà)面可能會(huì)顯的很雜亂。因此,我們會(huì)借由把一 些暫時(shí)用不到的視窗縮小成一小圖示,也就是 icon,以減少所占的空 間,清理一下桌面。等到要用到該視窗時(shí),才將之放大回原來(lái)的大小。 而 XSetIconName 所設(shè)定的名稱,則會(huì)在視窗變成 icon 時(shí)顯示出來(lái)。 


            --------------------------------------------------------------------------------

            void XSetWMNormalHints(display, w, hints)
            Display *display;
            Window w;
            XSizeHints *hints;

            hints 指定視窗在一般狀況下的 size hints。


            --------------------------------------------------------------------------------

            #define USPosition (1L << 0)
            #define USSize (1L << 1)
            #define PPosition (1L << 2)
            #define PSize (1L << 3)
            #define PMinSize (1L << 4)
            #define PMaxSize (1L << 5)
            #define PResizeInc (1L << 6)
            #define PAspect (1L << 7)
            #define PBaseSize (1L << 8)
            #define PWinGravity (1L << 9)
            #define PAllHints

            typedef struct {
            long flags;
            int x, y;
            int width, height;
            int min_width, min_height;
            int max_width, max_height;
            int width_inc, height_inc;
            struct {
            int x;
            int y;
            } min_aspect, max_aspect;
            int base_width, base_height;
            int win_gravity;
            } XSizeHints;


            --------------------------------------------------------------------------------

            XSizeHints *XAllocSizeHints()


            --------------------------------------------------------------------------------

            XFree(data)
            void *data;

            data 要釋放掉的記憶。


            --------------------------------------------------------------------------------
            XSetWMNormalHints 用以設(shè)定有關(guān)視窗大小的和縮放的限制等等的。 由於 XSizeHints 的內(nèi)容以後可能會(huì)有所增長(zhǎng),所以必需透動(dòng)態(tài)記憶 的配,以避免以後因?yàn)楦陌嬷幔斐珊托掳娴?nbsp;Xlib 不和的 情形。Xlib 提供 XAllocSizeHints 配置一個(gè) XSizeHints 的 structure。所有將由 Xlib 所提供的函數(shù)所配的記憶,都要使用 XFree 釋放。

            5. 顯示視窗
            視窗建好之後, 仍然不會(huì)出現(xiàn)在螢?zāi)簧? 而是要經(jīng)過(guò)一道 mapping 的手序。 視窗都已經(jīng)設(shè)定好了,再來(lái)正式顯示在顯示器上就很容易了。這個(gè)步驟,mapping ,只要呼叫一個(gè)函數(shù)就 ok 了!! 
            --------------------------------------------------------------------------------

            XMapWindow(display, w)
            Display *display;
            Window w;

            w 要顯示的視窗。


            --------------------------------------------------------------------------------

            XFlush(display)
            Display *display;


            --------------------------------------------------------------------------------
            嗯!! 就這麼簡(jiǎn)單。但,當(dāng)你程式執(zhí)行到這一個(gè)步驟時(shí),也許你會(huì)發(fā)現(xiàn), 顯示器上跟本就沒(méi)有視窗出現(xiàn)。這是因?yàn)?nbsp;Xlib 設(shè)有 buffer,將所有 要傳送的訊息都先存在一個(gè) buffer 內(nèi),待 buffer 滿了之後才會(huì)將之 一起送出,以減少網(wǎng)路的流量,加過(guò)程式執(zhí)行的速度。然而,我們無(wú)法 知道什麼時(shí)侯才會(huì)滿,我們總不能一直等下去,等到程式結(jié)束了,也許 畫(huà)面都還沒(méi)出現(xiàn)。為了解決這個(gè)問(wèn)題,Xlib 提供 XFlush 這個(gè)函數(shù), 可以強(qiáng)迫 Xlib 立即將 buffer 內(nèi),現(xiàn)有的全部訊息都傳送出去,以讓 X Server 立即可以做處理。

            6. 關(guān)閉(destroy)視窗

            --------------------------------------------------------------------------------

            XDestroy(display, w)
            Display *display;
            Window w;

            w 要關(guān)閉的視窗。


            --------------------------------------------------------------------------------

            7. 關(guān)閉 display

            --------------------------------------------------------------------------------

            XCloseDisplay(display);
            Display display;


            --------------------------------------------------------------------------------

            8. 例

            --------------------------------------------------------------------------------

            /* --- Xtest.c --- */

            #include 
            #include 
            #include 
            #include 

            main() {
            Display *display;
            Window window;
            XSetWindowAttributes attr;
            XSizeHints *sz;

            /* 建立一個(gè) display 的 connection */
            display = XOpenDisplay("0:0");

            /* 建立和設(shè)定 window 的屬性 */
            window = XCreateWindow(display, XDefaultRootWindow(display),
            100, 100, 300, 300, 2, XDefaultDepth(display, 0),
            InputOutput, CopyFromParent, 0, &attr);

            /* 和 Window Manager 進(jìn)行溝通 */
            XStoreName(display, window, "hello!! world!!");
            sz = XAllocSizeHints();
            sz->x = 100;
            sz->y = 100;
            sz->width = 300;
            sz->height = 300;
            sz->flags = USPosition | USSize;
            XSetNormalHints(display, window, sz);

            /* Mapping Window  正式影射到顯示器畫(huà)面*/
            printf("Map window\n");
            XMapWindow(display, window);
            getchar(); /* 至此,視窗已執(zhí)行 Map 的動(dòng)作了,但
               顯示器上,卻可能看不到。*/

            printf("XFlush\n");
            XFlush(display);
            getchar(); /* 這,你應(yīng)該就看到顯示器上的變化了 */

            /*
               .................
               .... 程式處理部分 ..
               ....................
            */

            /* 關(guān)閉視窗 */
            printf("Destory Window\n");
            XDestroyWindow(display, window);
            getchar();

            printf("XFlush\n");
            XFlush(display);
            getchar();

            /* 關(guān)閉 display */
            printf("close display\n");
            XCloseDisplay(display);
            getchar();
            }


            --------------------------------------------------------------------------------

            gcc -o Xtest Xtest.c -L/usr/X11R6/lib -lX11


            --------------------------------------------------------------------------------
            上面是一個(gè)簡(jiǎn)單的例程式和 compile 的方法。

            X Window 程式設(shè)計(jì)入門(mén)--第三章 繪圖(Graphic)
            http://cnpa.yzu.edu.tw/~thinker 作者:李圭烽 (Thinker; Thinker.bbs@bbs.yzu.edu.tw) (2001-06-01 20:10:00)
            Index:
            顏色 
            Graphics Context 
            Graphics 
            Image 
            例 

            --------------------------------------------------------------------------------


            1. 顏色
              在 X Window 視窗系統(tǒng),程式使用顏色都是透過(guò)配置 color cell。 color cell 存放著顏色的 RGB 色值,即繪圖時(shí)顯示器上所顯示出來(lái) 的色值。在我們使用某種顏色之前,必需先配置一個(gè)正確的 cell, 使用該 cell 做為繪圖時(shí)的參數(shù)。當(dāng) server 將圖形輸出到顯示器時(shí) ,顯示器(顯示卡)會(huì)取出 cell 內(nèi)所設(shè)定之 RGB 值,輸出到畫(huà)面。 RGB 即光學(xué)三元色紅、綠、藍(lán),經(jīng)由三元色的比例不同,可以得到不 同的顏色。  


            color cells 分成兩種,read-only cell 和 read/write cell。 read-only cell 只能被使用,不能被應(yīng)用程式修改,但是由各個(gè)應(yīng)用 程式之間一起分享,共同使用。read/write cell 被配置(allocate) 之後可以修改其 RGB 值,但一般是不在各應(yīng)用程式之間分享,是私有 的。

            colormap 是 color cell 的集合。每個(gè) client 都可以有自己的 colormap,所以同時(shí)可能會(huì)有多個(gè) colormap 存在。而系統(tǒng)在同一 時(shí)間內(nèi),只安裝一個(gè) colormap 到顯示器上(有些硬容許同時(shí)安裝多 個(gè) colormap),所以當(dāng)一個(gè)視窗能顯示正確的顏色時(shí),其它視窗的顏色 可能會(huì)不正確。這是因?yàn)椴煌?nbsp;colormap,其 cell 和 RGB 值的對(duì) 應(yīng)可能不同,所以當(dāng) server 把某個(gè)視窗的 colormap 安裝到硬體上 時(shí),其它視窗內(nèi)的 cell 和 RGB 的對(duì)映,就變成新被安裝的 colormap 的對(duì)映方式,導(dǎo)至不正確的顏色顯示。也就是當(dāng) server 把某個(gè)視窗 的 colormap 安裝到顯示硬上時(shí),該視窗的顏色顯示就會(huì)正確。反 之,則會(huì)顯示目前被安裝的 colormap 的對(duì)映狀況,顯示不正確的顏 色。為了避免這個(gè)問(wèn)題,一般建議使用預(yù)定(default)共用的 colormap ,每個(gè)視窗都使用同一個(gè) colormap。default 的 colormap 可由 函數(shù) XDefaultColormap 取得。

            顏色是以 R、G、B 三種元色光的量值來(lái)表示,當(dāng)某元色的量值越大時(shí) ,則顯示出來(lái)的顏色就越偏向該元色。Xlib 使用 XColor 記錄 RGB 值。 
            --------------------------------------------------------------------------------

            typedef struct {
            unsigned long pixel; /* pixel value */
            unsigned short red, green, blue; /* rgb values */
            char flags; /* DoRed, DoGreen, DoBlue */
            char pad;
            } XColor;


            --------------------------------------------------------------------------------
            red、green、blue 的圍從 0 到 65535。Black 用 (0,0,0) 表示, White 用 (65535,65535,65535) 表示。

            每個(gè) color cell 在 colormap 上都占有一個(gè)位子,為了分別不同的 color cell,我們?yōu)槊總€(gè) color cell 指定一個(gè)編號(hào),稱之為 pixel。 所以當(dāng)我們需要指定一個(gè) cell 時(shí),我是指定其 pixel 值。pixel 是一個(gè) long 整數(shù),每一個(gè) bit 我們稱之為一個(gè) plane。因此,當(dāng)我 們?cè)?nbsp;colormap 上分配 x 個(gè) plane 時(shí),我們就是分配 2^x^ 個(gè) cell。

            cell 有分 read-only 和 read/write:read-only cell的 RGB 值是由 server 設(shè)定的,不能更改。但是可由各 client 并同使用。每當(dāng)有一 個(gè) client 配置(allocate)read-only cell,則 server 會(huì)紀(jì)錄下來(lái), 當(dāng)所有配置該 cell 的 client 都釋放該 cell 後,該 cell 才算真正 被釋放。否則該 cell 就只能維持其原來(lái)的值不能改變,也不能被當(dāng)成 read/write cell 配置。而同一個(gè) client 多次配置同一個(gè) cell 則視 為多次的配置,client 也必需釋放該 cell 相同次數(shù)。read/write cell 則不會(huì)有初值,但卻可以由 client 設(shè)定更改其 RGB 值。當(dāng) client 分 配到 read/write cell 後,雖然其它 client 也可以設(shè)定其內(nèi)容 (RGB 值),但一般我們還是認(rèn)為 read/write cell是屬私人的,不被分 享共用的。


            --------------------------------------------------------------------------------

            Status XAllocColor(display, colormap, screen_in_out)
            Display *display;
            Colormap colormap;
            XColor *screen_in_out;

            colormap 指定使用的 colormap。
            screen_in_out 指定和傳回 colormap 內(nèi),實(shí)際的值。


            --------------------------------------------------------------------------------
            可配置一個(gè) read-only cell。client 指定一個(gè) RGB 值,XAllocColor 分配一個(gè)對(duì)映到硬體所能提供最接近該 RGB 值的 cell。RGB 值設(shè)定在 screen_in_out 的 red、green、blue,而 cell 的 pixel 值會(huì)將由 pixel 傳回。硬體實(shí)際提供的 RGB 值,則經(jīng)由 red、green、blue 傳 回。


            --------------------------------------------------------------------------------

            Status XAllocColorCells(display, colormap, contig
            plane_masks_return, nplanes, pixels_return,
            npixels)
            Display *display;
            Colormap colormap;
            Bool contig;
            unsigned long plane_masks_return[];
            unsigned int nplanes;
            unsigned long pixels_return[];
            unsigned int npixels;

            colormap 指定使用的 colormap
            contig 一個(gè) Boolean 值,指示配置的 planes 是否必
            需是連續(xù)的。
            plane_mask_return
            傳回 plane masks 的 array。
            nplanes 指定在 plane_mask_return 要傳回多少個(gè) plane
            masks。
            pixels_return 傳回 pixel 陣列。
            npixels 指定在 pixels_return 傳回多少個(gè) pixel values。


            --------------------------------------------------------------------------------
            分配多個(gè) read/write cell。這些 cell 都未指定內(nèi)容,分配之後, client 程式可以更改其 RGB 值。在這你必需在 nplanes 指定你要分 配幾個(gè) plane,分配到的 plane,會(huì)經(jīng)由 plane_mask_return 傳回。 plane_mask_return 這個(gè)陣列內(nèi)的每個(gè)元素,指定了分配到的 plane 的 mask。npixels 則指定了要分配多少個(gè) pixel,pixel 則由 pixels_return 這個(gè)陣列傳回。所有分配到的 cell 的數(shù)目為 npixels * 2^nplanes^,而 cell 的 pixel 值則為 pixels_return 傳回之 pixel 值和 plane mask 做 OR 運(yùn)算所能產(chǎn)生 的所有值。如果 contig 設(shè)為 true,則所有分配到之 plane 會(huì)是相 鄰連續(xù)的,也就是所有傳回之 plane mask 做 OR 運(yùn)算,會(huì)得到一群 設(shè)為 1 的連續(xù) bits。


            --------------------------------------------------------------------------------

            XStoreColor(display, colormap, color)
            Display *display;
            Colormap colormap;
            XColor *color;

            colormap 指定 colormap。
            color 指定 pixel 和 RGB 值。


            --------------------------------------------------------------------------------
            使用 XStoreColor 設(shè)定指定之 cell 的 RGB 值,但只限於 read/write cell。


            --------------------------------------------------------------------------------

            XStoreColors(display, colormap, color, ncolors)
            Display *display;
            Colormap colormap;
            XColor color[];
            int ncolor;

            colormap 指定 colormap。
            color 指定要設(shè)定之顏色的結(jié)構(gòu)陣列。
            ncolor 指定 color 陣列中有多少個(gè)設(shè)定值。


            --------------------------------------------------------------------------------
            XStoreColors 可以同時(shí)設(shè)定多個(gè) color cells 的 RGB 值,但只 限於 read/write cell,read-only cell 不能更改。


            --------------------------------------------------------------------------------

            XFreeColors(display, colormap, pixels, npixels, planes)
            Display *display;
            Colormap colormap;
            unsigned long pixels[];
            int npixels;
            unsigned long planes;

            colormap 指定使用之 colormap。
            pixels 指定對(duì)映到 cells 的 pixels 值的陣列。
            npixels 指定 pixels 陣列中有多少個(gè) pixel 值。
            planes 指定你要釋放的 planes。


            --------------------------------------------------------------------------------
            當(dāng)你所配置到的 color cell 不再被需要時(shí),你可以使用 XFreeColors 釋放。XFreeColors 同一時(shí)間內(nèi)可以釋放多個(gè) cell ,pixels 是指定要釋放掉的 cell 的陣列,npixels 則指定 cell 的數(shù)目。planes 則是要釋放之 planes 的 plane mask,將要釋放 之所有 plane 的 mask OR 起來(lái)所得到的 mask。所釋放的 pixels 為,任一指定之 pixel 和 plane mask 之部分集合做 OR 運(yùn)算後,所 有可能產(chǎn)生的 pixel 集合。

            使用顏色名稱
            除了使用 RGB 值之外,你可以使用顏色的名稱,并取得適當(dāng)?shù)?nbsp;pixel 值。 
            --------------------------------------------------------------------------------

            status XAllocNamedColor(display, colormap, color_name,
            screen_def_return, exact_def_return)
            Display *display;
            Colormap colormap;
            char *color_name;
            XColor *screen_def_return, *exact_def_return;

            colormap 指定 colormap。
            color_name 顏色之名稱。
            screen_def_return
            傳回硬所能提供最接近之 RGB 值。
            screen_def_exact
            傳回精確的 RGB 值。


            --------------------------------------------------------------------------------
            screen_def_exact 傳回的是原本正確顏色所該有的 RGB 色值,而 screen_def_return 傳回的則是目前硬所能提供顏色最接近之 RGB 色值。

            操作 Colormaps
            除了使用預(yù)定公用的 colormap (從 parent 視窗拷貝而來(lái)的) 分配我 們需要的顏色之外,我們也可以為每個(gè)個(gè)別的視窗建立獨(dú)立的 colormap,讓每個(gè)視窗能獨(dú)力擁有 colormap,或者是由一群視窗來(lái) 分享(share)一個(gè) colormap。


            --------------------------------------------------------------------------------

            Colormap XCreateColormap(display, w, visual, alloc)
            Display *display;
            Window w;
            Visual *visual;
            int alloc;

            w 指定視窗。
            visual 指定一個(gè)該 screen 所提供之 visual。
            alloc 指定是否要分配在 colormap 的所有 entry。
            可以是 AllocNone 或 AllocAll。


            --------------------------------------------------------------------------------
            XCreateColormap 會(huì)傳回一個(gè)在指定視窗所在的 screen 上建立之新的 colormap。visual 指定該 colormap 所提供之 visual。

            我們可以隨時(shí)為視窗設(shè)定新的 colormap,但是 colormap 的 visual 必需和視窗的 visual 相同。指定視窗的 colormap,我們可以透過(guò) XSetWindowColormap: 
            --------------------------------------------------------------------------------

            XSetWindowColormap(display, w, colormap)
            Display *display;
            Window w;
            Colormap colormap;


            --------------------------------------------------------------------------------



            --------------------------------------------------------------------------------

            XFreeColormap(display, colormap)
            Display *display;
            Colormap colormap;

            colormap 要釋放之 colormap。


            --------------------------------------------------------------------------------
            釋放一個(gè) colormap,但對(duì)於預(yù)定之 colormap 沒(méi)有作用。如果要 釋放之 colormap 已被使用在某個(gè)視窗上時(shí),則 XFreeColormap 會(huì)將該視窗之 colormap 設(shè)成 None,并對(duì)該視窗產(chǎn)生 ColormapNotify event ( event 在後面的章節(jié)會(huì)談到 )。

            2. Graphics Context
            Graphics Context 簡(jiǎn)稱 GC,是存在 server 上的一種資源。GC 是用來(lái) 存放繪圖時(shí)所需要的各項(xiàng)資訊(例如: 線的寬度和長(zhǎng)度,前景和背景顏色 等等),在大部分的繪圖功能中,都需要使用 GC 做為參數(shù)。其實(shí),我們 可以把 GC 看做是我們?cè)谧霎?huà)時(shí)的畫(huà)筆,不同的畫(huà)筆會(huì)產(chǎn)生不同的效果 。同樣的,我們也可以使用不同的 GC 內(nèi)容的變化,來(lái)組合達(dá)成我們所 需要的畫(huà)面效果。同一個(gè) GC 可以在不同的視窗使用,也可以在不同的 client 間使用,但是一般來(lái)說(shuō) ,并不鼓勵(lì)由不同的 client 使用,因?yàn)?nbsp;Xlib 會(huì)對(duì) GC 暫存,可能會(huì)造 成同步上的問(wèn)題。GC 是和 screen 結(jié)合在一起的,同時(shí)也和 depth 有關(guān) ,只有 screen 和 depth 和 GC 和同的視窗,才可以使用該 GC。也就是 該視窗必需和 GC 是在同一個(gè) screen,并且要有相同的 depth。

            Xlib 提供 XGCValues 這個(gè)結(jié)構(gòu), 以存放 GC 的相關(guān)資訊。我們將要 設(shè)定的值,存於這個(gè)結(jié)構(gòu),同時(shí)也經(jīng)由這個(gè)結(jié)構(gòu)傳回 GC 的內(nèi)存值。 
            --------------------------------------------------------------------------------

            /* GC attribute value mask bits */

            #define GCFunction (1L<<0)
            #define GCPlaneMask (1L<<1)
            #define GCForeground (1L<<2)
            #define GCBackground (1L<<3)
            #define GCLineWidth (1L<<4)
            #define GCLineStyle (1L<<5)
            #define GCCapStyle (1L<<6)
            #define GCJoinStyle (1L<<7)
            #define GCFillStyle (1L<<8)
            #define GCFillRule (1L<<9)
            #define GCTile (1L<<10)
            #define GCStipple (1L<<11)
            #define GCTileStipXOrigin (1L<<12)
            #define GCTileStipYOrigin (1L<<13)
            #define GCFont (1L<<14)
            #define GCSubwindowMode (1L<<15)
            #define GraphicsExposures (1L<<16)
            #define GCClipXOrigin (1L<<17)
            #define GCClipYOrigin (1L<<18)
            #define GCClipMask (1L<<19)
            #define GCDashOffset (1L<<20)
            #define GCDashList (1L<<21)
            #define GCArcMode (1L<<22)

            /* Values */

            typedef struct {
            int function;
            unsigned long plane_mask;
            unsigned long foreground;
            unsigned long background;
            int line_width;
            int line_style;
            int cap_style;
            int join_style;
            int fill_style;
            int fill_rule;
            int arc_mode;
            Pixmap tile;
            Pixmap stipple;
            int ts_x_origin;
            int ts_y_origin;
            Font font;
            int subwindow_mode;
            Bool graphics_exposures;
            int clip_x_origin;
            int clip_y_origin;
            Pixmap clip_mask;
            int dash_offset;
            char dashes;
            } XGCValues;


            --------------------------------------------------------------------------------
            下面是 XGCValues 的欄位說(shuō)明。 欄位 預(yù)設(shè)值 說(shuō)明 
            function GXcopy Xlib 定義了 16 種 function, 用以定義各種 X 所提供的繪圖形式. Xlib 提供了一些繪圖函數(shù), 當(dāng)我們?cè)谝粋€(gè) drawable 上繪圖時(shí), 新繪上的 圖該如何和在原本位置上的圖形配合呢? function 定義了 X 所提供的 16 種可能中的一種. 當(dāng)我們?yōu)?nbsp;GC 設(shè)好新的 function 之後, 下一次我們使用 GC 進(jìn)行繪圖時(shí), 新的 function 就開(kāi)始發(fā)生了作用. 下面是 Xlib 定義的 16 種 function. GXclear 把輸出圖素清除為 0 
            GXand 把輸出之圖與原圖素做 and 運(yùn)算 
            GXandReverse 先把原圖素反相, 然後和輸出圖素做 and 運(yùn)算 
            GXcopy 直接用輸出圖素替代原圖素 
            GXandInverted 先將輸出圖素和原圖素做 and 運(yùn)算後, 再將結(jié)果反相 
            GXnoop 維持原圖素 
            GXxor 輸出圖素和原圖素做 xor 運(yùn)算 
            GXor 輸出圖素和原圖素做 or 運(yùn)算 
            GXnor 先分別把輸出圖素和原圖素做反相, 再將反相後的兩圖做 and 運(yùn)算 
            GXequiv 先反相輸出圖素,然後和原圖素做 xor 運(yùn)算  
            GXinvert 把原圖素反相 
            GXorReverse 反相原圖素, 然後和輸出圖素做 xor 運(yùn)算 
            GXcopyInverted 把輸出圖素反相當(dāng)為最後結(jié)果 
            GXorInverted 把輸出圖素反相後和原圖素做 or 運(yùn)算 
            GXnand 把輸出圖素和原圖素做反相, 然後兩圖做 or 運(yùn)算 
            GXset 把輸出部分全設(shè)為 1 
             
            plane_mask AllPlanes 指定會(huì)被影的 planes, 會(huì)被影的 planes 設(shè)為 1。Xlib 中定義 AllPlanes 常數(shù), 指定所有的 planes。繪圖的最後結(jié)果是: 
            ((輸出圖素 function 原圖素) AND plane_mask)

             
            foreground 1 指定圖形輸出時(shí)的前景所使用的圖素值(pixel)  
            background 0 指定圖形輸出時(shí)的背景所使用的圖素值(pixel)  
            line_width 0 如果輸出中有線條時(shí), 線條的寬度.  
            line_style LineSolid 線條的樣式, Xlib 定義三個(gè)常數(shù), 代表三種樣式. LineSolid 實(shí)線 
            LineOnOffDash 虛線 
            LineDoubleDash 另一種虛線 
             
            cap_style CapButt 指定線條端線點(diǎn)(起點(diǎn)和終點(diǎn))的樣式。 CapNotLast 和 CapButt 相似, 只是 line width 為 0 時(shí), 不畫(huà)出端點(diǎn).  
            CapButt 方形長(zhǎng)角的端點(diǎn) 
            CapRound 圓弧形的端點(diǎn) 
            CapProjecting 和 CapButt 相似, 但端點(diǎn)會(huì)再延伸 line width 的一半長(zhǎng)度 
             
            join_style JoinMiter 折線的折點(diǎn)形式。 JoinMiter 角狀的折點(diǎn) 
            JoinRound 圖弧狀的折點(diǎn) 
            JoinBevel 像是兩個(gè) CapButt 的端點(diǎn)重疊在一起 
             
            fill_style FillSolid 設(shè)定線段,文字,和填充畫(huà)面的來(lái)源。 FillSolid 前景填滿 foreground 顏色 
            FillTiled 以 tile 填滿 
            FillStippled 前景以填上 foreground 但以 stipple 遮罩起來(lái). 
            FillOpaqueStippled 和 FillStippled 相似, 但被遮罩的部分(stipple 內(nèi)為 0 的部分) 填上 background。  
             
            fill_rule EvenOddRule 設(shè)定呼叫 XFillPolygon 時(shí),如何定義出內(nèi)部和外部。 EvenOddRule 以通過(guò)指定點(diǎn)的線為基準(zhǔn), 通過(guò) path 奇數(shù)次的為 inside 
            WindingRule 通過(guò)順時(shí)鐘方向的 path 和逆時(shí)鐘方向的 path 的次數(shù)如果不同 即為 inside。  
             
            arc_mode ArcPieSlice 控制 XFillArcs 如何填滿圓弧。 ArcChord 以琴弦般的填滿弧 
            ArcPieSlice 像被切開(kāi)的 pie 一樣的填滿弧 
             
            tile 0 和 GC 有相同 root 和深度(depth)的 pixmap 
            stipple 0 深度(depth)為 1 的 pixmap 
            ts_x_origin 0 設(shè)定 tile/stipple 的原點(diǎn)的 x 座標(biāo) 
            ts_y_origin 0 設(shè)定 tile/stipple 的原點(diǎn)的 y 座標(biāo) 
            font Implementation dependent 字形,XLoadFont 的傳回值 
            subwindow_mode ClipByChildren ClipByChildren 
            IncludeInferiors  
             
            graphics_exposures True 控制 XCopyArea 和 XCopyPlane 的 GraphicsExpose 事件(event)的產(chǎn)生。  
            clip_x_origin 0 clip_mask 的原點(diǎn)相對(duì)於 drawable 的位置 
            clip_y_origin 0 clip_mask 的原點(diǎn)相對(duì)於 drawable 的位置 
            clip_mask None clip_mask 為深度(depth)為 1 并和 GC 相同 root 的 pixmap, 做為輸出的 mask  
            dash_offset 
            dashes 


            你可以透過(guò) XCreateGC 建立一新的 GC: 
            --------------------------------------------------------------------------------

            GC XCreateGC(display, d, valuemask, values)
            Display *display;
            Drawable d;
            unsigned long valuemask;
            XGCValues *values;

            d 指定 drawable。
            valuemask 指定使用了那些 GC 元件。這個(gè)參數(shù)是把各元件之
            mask OR 起來(lái)得到的 mask,用以指定設(shè)了那些元
            件。
            value 指定設(shè)定的 GC 內(nèi)容。


            --------------------------------------------------------------------------------
            呼叫 XCreateGC 後,建立一個(gè)新的 GC,并會(huì)傳回 GC。所謂的 drawable 指的是一個(gè)可以使用繪圖功能,在其上進(jìn)行繪圖的視窗或是其它 X 上的 物件。


            --------------------------------------------------------------------------------

            XFreeGC(display, gc)
            Display *display;
            GC gc;

            gc 指定要釋放之 GC。


            --------------------------------------------------------------------------------
            釋放一個(gè)己建立之 GC。

            下面我們介紹一些設(shè)定 GC 的方便函數(shù),以方便我們做 GC 設(shè)定。


            --------------------------------------------------------------------------------

            XSetForeground(display, gc, foreground)
            Display *display;
            GC gc;
            usigned long foreground;

            gc 指定作用對(duì)像之 GC。
            foreground 指定前景顏色。


            --------------------------------------------------------------------------------
            設(shè)定 GC 內(nèi)容的前景。當(dāng)你使用該 GC 繪圖時(shí),前景顏色即為 GC 內(nèi)所設(shè)的前景顏色。


            --------------------------------------------------------------------------------

            XSetBackground(display, gc, background)
            Display *display;
            GC gc;
            usigned long background;

            gc 指定作用對(duì)像之 GC。
            background 指定背景顏色。


            --------------------------------------------------------------------------------
            設(shè)定 GC 的背景顏色。當(dāng)你使用該 GC 繪圖時(shí),前景顏色即為 GC 內(nèi)所設(shè)的前景顏色。


            --------------------------------------------------------------------------------

            XSetLineAttributes(display, gc, line_width, line_style,
            cap_style, join_style)
            Display *display;
            GC gc;
            unsigned int line_width;
            int line_style;
            int cap_style;
            int join_style;

            gc 指定作用對(duì)像之 GC。
            line_width 線條之寬度。
            line_style 線條型式,有 LineSolid、LineOnOffDash、
            LineDoubleDash。
            cap_style 指定線條端點(diǎn)之型式,有 CapNotLast、
            CapButt、CapRound、CapProjecting。
            join_style 指定線條轉(zhuǎn)折點(diǎn)的型式,有 JoinMiter、
            JoinRound、JoinBevel。


            --------------------------------------------------------------------------------
            設(shè)定線的形式。


            --------------------------------------------------------------------------------

            XSetFont(display, gc, font)
            Display *display;
            GC gc;
            Font font;

            gc 指定作用對(duì)像之 GC。
            font 指定字型。


            --------------------------------------------------------------------------------
            設(shè)定字形。


            --------------------------------------------------------------------------------

            XSetArcMode(display, gc, arc_mode)
            Display *display;
            GC gc;
            int arc_mode;

            gc 指定作用對(duì)像之 GC。
            arc_mode 指定畫(huà)弧時(shí),封口的型式,有 ArcChord、
            ArcPieSlice。


            --------------------------------------------------------------------------------
            設(shè)定畫(huà)弧時(shí),封口的型式。 
            3. Graphics
            Xlib 提供大量的函數(shù),處理圖形的輸出。 
            --------------------------------------------------------------------------------

            XClearWindow(display, w)
            Display *display;
            Window w;


            --------------------------------------------------------------------------------
            清除視窗。


            --------------------------------------------------------------------------------

            XDrawPoint(display, d, gc, x, y)
            Display *display;
            Drawable d;
            GC gc;
            int x, y;

            d 指定 drawable。
            gc 指定要使用之 GC。
            x, y 指定畫(huà)點(diǎn)的座標(biāo)。


            --------------------------------------------------------------------------------
            在視窗上畫(huà)一點(diǎn)。


            --------------------------------------------------------------------------------

            XDrawLine(display, d, gc, x1, y1, x2, y2)
            Display *display;
            Drawable d;
            GC gc;
            int x1, y1, x2, y2;

            d 指定目的 drawable。
            gc 指定使用之 GC。
            x1, y1, x2, y2 指定線的兩端點(diǎn)座標(biāo)。


            --------------------------------------------------------------------------------
            在視窗上畫(huà)一條線。


            --------------------------------------------------------------------------------

            XDrawRectangle(display, d, gc, x, y, width, height)
            Display *display;
            Drawable d;
            GC gc;
            int x, y;
            unsigned int width, height;

            x, y 指定矩形的左上角座標(biāo)。
            width, height 指定矩形的大小。


            --------------------------------------------------------------------------------
            在視窗上畫(huà)一個(gè)矩形。


            --------------------------------------------------------------------------------

            XDrawArc(display, d, gc, x, y, width, height, angle1, 
            angle2)
            Display *display;
            Drawable d;
            GC gc;
            int x, y;
            unsigned int width, height;
            int angle1, angle2;

            x, y 指定弧的中心點(diǎn)(原點(diǎn))。
            width, height  指定弧的 x 軸和 y 軸的比例。
            angle1, angle2 弧的起始角度和結(jié)止角度。


            --------------------------------------------------------------------------------
            在視窗上畫(huà)一個(gè)弧形。


            --------------------------------------------------------------------------------

            XFillRectangle(display, d, gc, x, y, width, height)
            Display *display;
            Drawable d;
            GC gc;
            int x, y;
            unsigned int width, height;


            --------------------------------------------------------------------------------
            在視窗上畫(huà)一個(gè)填滿顏色的矩形。


            --------------------------------------------------------------------------------

            XFillArc(display, d, gc, x, y, width, height, angle1,
            angle2)
            Display *display;
            Drawable d;
            GC gc;
            int x, y;
            unsigned int width, height;
            int angle1, angle2;


            --------------------------------------------------------------------------------
            在視窗上畫(huà)一個(gè)填滿顏色的弧形。


            --------------------------------------------------------------------------------

            Font XLoadFont(display, name)
            Display *display;
            char *name;

            name 指定字形名稱。


            --------------------------------------------------------------------------------
            載入字形,當(dāng)我要在視窗上顯示某一字形時(shí),我們必需先載入字形, 然後才能使用。使用這個(gè)函數(shù)之後,會(huì)傳回一個(gè) Font 的 ID,這 就是我們?cè)谑褂?nbsp;XSetFont 函數(shù)設(shè)定 GC 所要傳入的參數(shù)之一。 當(dāng)我們使用傳回來(lái)的 Font 設(shè)定 GC 後,就可以使用該 GC 當(dāng)做 參數(shù)在螢?zāi)簧巷@示該字形的字串。


            --------------------------------------------------------------------------------

            XUnloadFont(display, font)
            Display *display;
            Font font;

            font 指定要 unload 的字形。


            --------------------------------------------------------------------------------
            移除字形。當(dāng)我們不再使用一字形時(shí),我們必需將之移除。


            --------------------------------------------------------------------------------

            XDrawString(display, d, gc, x, y, string, lengtth)
            Display *display;
            Drawable d;
            GC gc;
            int x, y;
            char *string;
            int length;

            gc 畫(huà)字時(shí)所要用的 GC。
            x, y 指定字串顯示的座標(biāo)。
            string 要顯示的字串。
            length 字串的長(zhǎng)度。


            --------------------------------------------------------------------------------
            在螢?zāi)簧巷@示一字串。


            --------------------------------------------------------------------------------

            XDrawString16(display, d, gc, x, y, string, length)
            Display *display;
            Drawable d;
            GC gc;
            int x, y;
            XChar2b *string;
            int length;

            gc 指定使用之 GC。
            x, y 指定字串顯示的座標(biāo)。
            string 指定顯示之字串。
            length 指定字串內(nèi)有多少個(gè)字。


            --------------------------------------------------------------------------------
            在螢?zāi)簧巷@示一雙位元組(或 16bits)的字串。X Window 有支援雙位元組 字集,用以顯示雙位元組的語(yǔ)言(如中文等)。雙位元組的字元是以 XChar2b 這個(gè) structure 來(lái)表示: 
            typedef struct {
            unsigned char byte1;
            unsigned char byte2;
            } XChar2b;

            byte1 存放的是雙位元組字元的高位元組(MSB:most significant byte) ,byte2 存放的則是低位元組(LSB:least significant byte)。一個(gè)雙 位元組的字串就是 XChar2b 的陣列。

            4. Image 
            在 GUI 介面下, 常會(huì)需要將一張圖片直接 show 在視窗上, 像是 show 照片. Xlib 提供一些可以直接在 client 和 server 間傳送影像(image)的函數(shù), 以直接處理一張張的影像, 例如, 圖形檔. 在這提到的 image 相關(guān)函數(shù), 都會(huì)使用 XImage 結(jié)構(gòu)做為函數(shù)的輸入?yún)?shù). Xlib 在 client 端使用 XImage 描述影像資料, 當(dāng)你要使用 Xlib 的函數(shù)處理影像資料時(shí), 必需透過(guò) XImage 進(jìn)行操作. XImage 提供一個(gè)物件化的介面, 透過(guò)物件提供的函數(shù), 我們可以相同的方式, 處理不同的影像資料. 
            --------------------------------------------------------------------------------

            /*
             * Data structure for "image" data, used by image manipulation routines.
             */
            typedef struct _XImage {
                int width, height;          /* size of image */
                int xoffset;                /* number of pixels offset in X direction */
                int format;                 /* XYBitmap, XYPixmap, ZPixmap */
                char *data;                 /* pointer to image data */
                int byte_order;             /* data byte order, LSBFirst, MSBFirst */
                int bitmap_unit;            /* quant. of scanline 8, 16, 32 */
                int bitmap_bit_order;       /* LSBFirst, MSBFirst */
                int bitmap_pad;             /* 8, 16, 32 either XY or ZPixmap */
                int depth;                  /* depth of image */
                int bytes_per_line;         /* accelarator to next line */
                int bits_per_pixel;         /* bits per pixel (ZPixmap) */
                unsigned long red_mask;     /* bits in z arrangment */
                unsigned long green_mask;
                unsigned long blue_mask;
                XPointer obdata;            /* hook for the object routines to hang on */
                struct funcs {              /* image manipulation routines */
                    struct _XImage *(*create_image)();
            #if NeedFunctionPrototypes
                    int (*destroy_image)        (struct _XImage *);
                    unsigned long (*get_pixel)  (struct _XImage *, int, int);
                    int (*put_pixel)            (struct _XImage *, int, int, unsigned long);
                    struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
                    int (*add_pixel)            (struct _XImage *, long);
            #else
                    int (*destroy_image)();
                    unsigned long (*get_pixel)();
                    int (*put_pixel)();
                    struct _XImage *(*sub_image)();
                    int (*add_pixel)();
            #endif
                    } f;
            } XImage;


            --------------------------------------------------------------------------------
            XImage 可以建過(guò) XInitImage 和 XCreateImage 建立. 建立之後的 object, 可以使用 XGetPixel, XPutPixel, XSubImage 和 XAddPixel 讀取和修改內(nèi)容. 使用 XPutImage 輸出到 drawable (視窗或 pixmap), 使用 XGetImage 從 drawable 讀取. object 最後必需使用 XDestroyImage 釋放.


            --------------------------------------------------------------------------------

                   Status XInitImage(image)
                         XImage *image;


            --------------------------------------------------------------------------------
            XImage 在使用之前, 必需先經(jīng)過(guò) XInitImage 進(jìn)行 initialize. 在呼叫 XInitImage 之前, 除了 manipulate functions 之外, 其它的欄位都必需 先設(shè)定好. 成功的話, 傳回非0值, 否則傳回 0.


            --------------------------------------------------------------------------------

                   XImage *XCreateImage(display, visual, depth, format, off-
                   set, data, width, height, bitmap_pad,
                                           bytes_per_line)
                         Display *display;
                         Visual *visual;
                         unsigned int depth;
                         int format;
                         int offset;
                         char *data;
                         unsigned int width;
                         unsigned int height;
                         int bitmap_pad;
                         int bytes_per_line;


            --------------------------------------------------------------------------------
            XCreateImage 會(huì)為輸入之影像資料產(chǎn)生一個(gè) XImage 結(jié)構(gòu), 并傳回結(jié)構(gòu). 是一個(gè)包裝 XInitImage 的函數(shù). 'format' 指定影像儲(chǔ)存的形式, 有 ZPixmap, XYPixmap 和 XYBitmap. ZPixmap 的儲(chǔ)存方式是一個(gè) pixel 接 著一個(gè) pixel 存放. XYPixmap 則是 plane 接著 plane, 將所有 pixel 特定 plane 的內(nèi)容集成 bitmap, 然後依 plane 的順序儲(chǔ)存各 plane 形式的 bitmap. XYBitmap 和 XYPixmap 一樣, 但是 XYBitmap只有一個(gè) plane. 而, 影像的內(nèi)容則存在 data 所指定的 memory block . 使用者必需指定一塊記憶(data)以儲(chǔ)存影像, XCreateImage 并不會(huì)主動(dòng)為您配置. data 的大小和 image 的大小和深度(depth)有關(guān), format 也會(huì)影響. 下面是 data 大小和 bytes_per_line 的計(jì)算公式. 
            format  size of data  bytes_per_line  
            ZPixmap width * height * ((depth + 7) / 8) width * ((depth + 7) / 8) 
            XYPixmap ((width + 7) / 8) * height * depth (width + 7) / 8 
            XYBitmap ((width + 7) / 8) * height * 1  (width + 7) / 8 



            --------------------------------------------------------------------------------

                   unsigned long XGetPixel(ximage, x, y)
                         XImage *ximage;
                         int x;
                         int y;


            --------------------------------------------------------------------------------
            取得影像內(nèi)的一個(gè)圖點(diǎn).


            --------------------------------------------------------------------------------

                   XPutPixel(ximage, x, y, pixel)
                         XImage *ximage;
                         int x;
                         int y;
                         unsigned long pixel;


            --------------------------------------------------------------------------------
            在影像上放上一個(gè)點(diǎn).


            --------------------------------------------------------------------------------

                   XImage *XSubImage(ximage, x, y, subimage_width,
                   subimage_height)
                         XImage *ximage;
                         int x;
                         int y;
                         unsigned int subimage_width;
                         unsigned int subimage_height; 


            --------------------------------------------------------------------------------
            讀取影像的一部分內(nèi)容, 并傳回 XImage. x, y, subimage_width, 和 subimage_height 指定 image 內(nèi)的一個(gè)方框的位置和大小, 讀 取方框內(nèi)的資料.


            --------------------------------------------------------------------------------

                   XAddPixel(ximage, value)
                         XImage *ximage;
                         long value;


            --------------------------------------------------------------------------------
            把 image 內(nèi)每個(gè)點(diǎn)的 pixel 值都加上指定的 valuex.


            --------------------------------------------------------------------------------

                   XDestroyImage(ximage)
                           XImage *ximage;


            --------------------------------------------------------------------------------
            由上面和下面各函數(shù)所產(chǎn)生的 XImage 物件, 最後不用時(shí), 都要使用 XDestroyImage 釋放掉。注意, XDestroyImage 會(huì)主動(dòng)將 data 釋放 


            --------------------------------------------------------------------------------

                   XPutImage(display, d, gc, image, src_x, src_y, dest_x,
                   dest_y, width, height)
                           Display *display;
                           Drawable d;
                           GC gc;
                           XImage *image;
                           int src_x, src_y;
                           int dest_x, dest_y;
                           unsigned int width, height;


            --------------------------------------------------------------------------------
            將 image 輸出 'd' 所指定的 drawable.


            --------------------------------------------------------------------------------

                   XImage *XGetImage(display, d, x, y, width, height,
                   plane_mask, format)
                           Display *display;
                           Drawable d;
                           int x, y;
                           unsigned int width, height;
                           unsigned long plane_mask;
                           int format;


            --------------------------------------------------------------------------------
            讀取 'd' 所指定之 drawable 的影像. 'plane_mask' 指定要讀取的 planes. 若指定的 planes, 為 drawable 所有 planes 的 subset, 那麼傳回的 image 的 depth 將和指定的 planes 數(shù)目相同.


            --------------------------------------------------------------------------------

                   XImage *XGetSubImage(display, d, x, y, width, height,
                   plane_mask, format, dest_image, dest_x,
                                        dest_y)
                         Display *display;
                         Drawable d;
                         int x, y;
                         unsigned int width, height;
                         unsigned long plane_mask;
                         int format;
                         XImage *dest_image;
                         int dest_x, dest_y;


            --------------------------------------------------------------------------------


            下面是處理影像的例. 
            --------------------------------------------------------------------------------

            /* -- Image-test.c -- */
            #include 
            #include 
            #include 
            #include 
            #include 
            #include 
            #include "gnu.xpm"
            #include "doomface.xpm"
            #include "Boss2.xpm"


            struct ColorElm {
            char *tag;
            unsigned long pixel;
            };


            unsigned long
            get_pixel(Display *display, Colormap colormap, char *str)
            {
            char *cp = str;
            XColor color, excolor;

            if(*cp == '#') {
            int j, k;
            int t;
            int rgbl;
            unsigned short rgb[3];

            cp++;
            if(strlen(cp) == 6)
            rgbl = 2;
            else
            rgbl = 4;

            for(k = 0; k < 3; k++) {
            t = 0;
            for(j = 0; j < rgbl; j++) {
            char c = *(cp++);

            t <<= 4;
            if(c >= 'A' && c <= 'F')
            t += c - 'A' + 10;
            else if(c >= 'a' && c <= 'f')
            t += c - 'a' + 10;
            else
            t += c - '0';
            }
            rgb[k] = t;
            }

            color.red = rgb[0];
            color.green = rgb[1];
            color.blue = rgb[2];
            color.flags = DoRed | DoGreen | DoBlue;
            XAllocColor(display, colormap, &color);
            } else {
            char *cp;

            if(strcasecmp(str, "None") == 0)
            cp = "black";
            else
            cp = str;
            XAllocNamedColor(display, colormap, cp, &color, &excolor);
            }

            return color.pixel;
            }


            /*
             * 從 *.xpm 轉(zhuǎn)換成 Xlib 能處理的 image 資料形式 (ZPixmap)
             */
            char *
            xpm_to_data(char **xpm, Display *display,
            Colormap colormap, int depth, int *width, int *height)
            {
            int nc, el; /* # of color, and element length */
            int i;
            int bpp; /* byte per pixel */
            struct ColorElm *ce, *cep;
            unsigned short rgb[3];
            XColor color;
            char *data, *dp;

            sscanf(*(xpm++), "%d %d %d %d", width, height, &nc, &el);
            bpp = (depth + 7) / 8;

            data = (char *)malloc(sizeof(char) * bpp *
            *width * *height);
            ce = (struct ColorElm *)malloc(sizeof(struct ColorElm) * nc);

            cep = ce;
            for(i = 0; i < nc; i++) {
            char *cp;

            cep->tag = (char *)malloc(sizeof(char) * el);
            memcpy(cep->tag, *xpm, el);

            cp = *xpm + el;
            /*
             * skip redundant character
             */
            while(isspace(*cp)) cp++;
            while(*(cp++) != 'c') {
            while(isspace(*cp)) cp++;
            while(!isspace(*cp)) cp++;
            while(isspace(*cp)) cp++;
            }
            /*
             * get pixel of color
             */
            while(isspace(*cp)) cp++;
            cep->pixel = get_pixel(display, colormap, cp);

            cep++;
            xpm++;
            }

            /*
             * generate image data
             */
            dp = data;
            for(i = 0; i < *height; i++) {
            int j;
            char *p;

            p = *(xpm++);
            for(j = 0; j < *width; j++) {
            int idx;
            unsigned long pixel;

            /*
             * find pixel of point
             */
            for(idx = 0; idx < nc; idx++)
            if(!memcmp(p, ce[idx].tag, el)) {
            memcpy(dp, &ce[idx].pixel, bpp);
            break;
            }
            dp += bpp;
            p += el;
            }
            }

            free(ce);
            return data;
            }


            main() 
            {
            Display *display;
            Window window;
            XSetWindowAttributes attr;
            Colormap colormap;
            XColor color1, color2;
            XGCValues gcvalue;
            GC gc;
            XSizeHints *sz;
            XImage *img1, *img2, *img3;
            int screen;
            char *data; /* image data */
            int w, h; /* width & height */
            int bpp; /* byte per pixel */

            display = XOpenDisplay("0:0");

            colormap = DefaultColormap(display, screen = DefaultScreen(display));
            color1.red = color1.blue = 0xffff;
            color1.green = 0;
            color2.red = color2.green = color2.blue = 0xff;
            color1.flags = color2.flags = DoRed | DoGreen | DoBlue; 
            XAllocColor(display, colormap, &color1);
            XAllocColor(display, colormap, &color2);

            attr.background_pixel = color2.pixel;
            window = XCreateWindow(display, XDefaultRootWindow(display),
            100, 100, 500, 300, 2, XDefaultDepth(display, 0),
            InputOutput, CopyFromParent, CWBackPixel, &attr);

            XStoreName(display, window, "hello!! world!!");
            sz = XAllocSizeHints();
            sz->x = 100;
            sz->y = 100;
            sz->width = 300;
            sz->height = 500;
            sz->flags = USPosition | USSize;
            XSetNormalHints(display, window, sz);
            XMapWindow(display, window);

            gc = XCreateGC(display, window, 0, &gcvalue);
            XSetForeground(display, gc, color1.pixel);
            XSetBackground(display, gc, color2.pixel);
            XFlush(display);

            printf("Show image!!\n");
            bpp = (DefaultDepth(display, screen) + 7) / 8;
            /*
             * Create gnu.xpm
             */
            data = xpm_to_data(image_name, display, colormap,
            DefaultDepth(display, screen), &w, &h);
            img1 = XCreateImage(display,
            DefaultVisual(display, screen),
            DefaultDepth(display, screen),
            ZPixmap, 0, data,
            w, h, 8, w * bpp);
            /* (w, h) 是影像的寬和高 */

            /*
             * Create doomface.xpm
             */
            data = xpm_to_data(xpm, display, colormap,
            DefaultDepth(display, screen), &w, &h);
            img2 = XCreateImage(display,
            DefaultVisual(display, screen),
            DefaultDepth(display, screen),
            ZPixmap, 0, data,
            w, h, 8, w * bpp);
            /* (w, h) 是影像的寬和高 */

            /*
             * Create Boss2.xpm
             */
            data = xpm_to_data(Boss2_xpm, display, colormap,
            DefaultDepth(display, screen), &w, &h);
            img3 = XCreateImage(display,
            DefaultVisual(display, screen),
            DefaultDepth(display, screen),
            ZPixmap, 0, data,
            w, h, 8, w * bpp);
            /* (w, h) 是影像的寬和高 */

            /*
             * Show images
             */
            XPutImage(display, window, gc, img1, 0, 0, 10, 10, w, h);
            XPutImage(display, window, gc, img2, 0, 0, 10, 100, w, h);
            XPutImage(display, window, gc, img3, 0, 0, 200, 50, w, h);
            XFlush(display);

            /*
             * Destroy images
             */
            XDestroyImage(img1);
            XDestroyImage(img2);
            XDestroyImage(img3);
            sleep(3);

            XDestroyWindow(display, window);
            XFlush(display);

            XCloseDisplay(display);
            }


            --------------------------------------------------------------------------------
            執(zhí)行結(jié)果

            顏色和原圖有些不同, 主要原因是使用 default 的 colormap. 上面的程式 在視窗顯示三張 .xpm 的圖形檔, 分別是 gnu.xpm, doomface.xpm 和 Boss2.xpm. 

            5. 例

            --------------------------------------------------------------------------------

            /* ---- XGraph.c ---- */

            #include 
            #include 
            #include 
            #include 

            main() {
            Display *display;
            Window window;
            XSetWindowAttributes attr;
            Colormap colormap;
            XColor color1, color2;
            XGCValues gcvalue;
            GC gc;
            XSizeHints *sz;

            display = XOpenDisplay("0:0");

            /* 取得預(yù)設(shè)之 colormap */
            colormap = DefaultColormap(display, 
            DefaultScreen(display));
            /* 取得 colorcell */
            color1.red = color1.blue = 0xffff;
            color1.green = 0;
            color2.red = color2.green = color2.blue = 0xff;
            color1.flags = color2.flags = DoRed | DoGreen | DoBlue; 
            XAllocColor(display, colormap, &color1);
            XAllocColor(display, colormap, &color2);

            /* 設(shè)定視窗的 attribute 和建設(shè) */
            attr.background_pixel = color2.pixel; /* 背景顏色 */
            window = XCreateWindow(display,
            XDefaultRootWindow(display), 100, 100, 300, 300,
            2, XDefaultDepth(display, 0), InputOutput, 
            CopyFromParent, CWBackPixel, &attr);

            /* 設(shè)定和 window manager 進(jìn)行溝通 */
            XStoreName(display, window, "hello!! world!!");
            sz = XAllocSizeHints();
            sz->x = 100;
            sz->y = 100;
            sz->width = 300;
            sz->height = 300;
            sz->flags = USPosition | USSize;
            XSetNormalHints(display, window, sz);

            /* 顯示視窗 */
            printf("Map window\n");
            XMapWindow(display, window);
            XFlush(display);
            getchar();

            /* 建立并設(shè)定 GC */
            gc = XCreateGC(display, window, 0, &gcvalue);
            XSetForeground(display, gc, color1.pixel);
            XSetBackground(display, gc, color2.pixel);

            /* 畫(huà)一個(gè)矩形 */
            printf("Draw rectangle\n");
            XDrawRectangle(display, window, gc, 10, 10, 100, 100);
            XFlush(display);
            getchar();

            /* 清除視窗 */
            XClearWindow(display, window);

            /* 設(shè)定 GC 內(nèi),線的形式 */
            XSetLineAttributes(display, gc, 5, LineOnOffDash,
            CapButt, JoinRound);
            /* 畫(huà)線 (200, 10) - (200, 290) */
            printf("Draw line\n");
            XDrawLine(display, window, gc, 200, 10, 200, 290);
            XFlush(display);
            getchar();

            /* 關(guān)閉視窗 */
            printf("Destory Window\n");
            XDestroyWindow(display, window);
            XFlush(display);
            getchar();

            printf("close display\n");
            XCloseDisplay(display);
            getchar();
            }


            --------------------------------------------------------------------------------

            gcc -o XGraph XGraph.c -L/usr/X11R6/lib -lX11


            --------------------------------------------------------------------------------
            上面是一個(gè)簡(jiǎn)單的例程式和 compile 的方法。
            X Window 程式設(shè)計(jì)入門(mén)--第四章 Event
            http://cnpa.yzu.edu.tw/~thinker 作者:李圭烽 (Thinker; Thinker.bbs@bbs.yzu.edu.tw) (2001-06-01 21:04:00)
            Index:
            Event Types and Event Masks 
            Events Propagation 
            Event Handling 
            Events 
            MapNotify 
            UnmapNotify 
            Expose 
            ButtonPress, ButtonRelease, KeyPress, KeyRelease, MotionNotify 
            CreateNotify 
            DestroyNotify 
            ResizeRequest 
            FocusIn, FocusOut 
            例 

            --------------------------------------------------------------------------------

            X Window 的 client 應(yīng)用程式,透過(guò)和 X Server 之間的 connection 和 Server 進(jìn)行通訊。client 應(yīng)用程式會(huì)通過(guò) Xlib,向 X Server 發(fā)出 request (要求)。而有時(shí)侯,X Server 也會(huì)產(chǎn)生 Event (事件), 需要經(jīng)由 connection 通知 client 程式。這些 Event 可能是因?yàn)槭褂?nbsp;者按下按鍵或是移動(dòng)滑鼠,也可能是因?yàn)?nbsp;client 發(fā)出的 request 而使 得 X Server 產(chǎn)生的。X Server 可以經(jīng)由產(chǎn)生 Event,通知 client 所 發(fā)生的所有事件。

            Event Types and Event Masks
            由 Server 傳給 client 的 Event,依不同的 Event,各使用不同的 structure 表示。而在不同 Event 之間,還是有其相同存在。不同 Event 使用的 structure 有一部分是相同的,每個(gè) sturcture 最前面 相同的部分可以使用 XAnyEvent 這個(gè) structure 表示。 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window window;
            } XAnyEvent;


            --------------------------------------------------------------------------------
            這個(gè) sturcture 收集各個(gè) Event 相同的部分,包括 type。透過(guò) type ,我可以辨識(shí)出各個(gè)不同的 Event,以做對(duì)應(yīng)的處理。

            Event 可以 _XEvent 這個(gè) union type 表示: 
            --------------------------------------------------------------------------------

            typedef union _XEvent {
            int type;
            XAnyEvent xany;
            XKeyEvent xkey;
            XButtonEvent xbutton;
            XMotionEvent xmotion;
            XCrossingEvent xcrossing;
            XFocusChangeEvent xfocus;
            XExposeEvent xexpose;
            XGraphicsExposeEvent xgraphicsexpose;
            XNoExposeEvent xnoexpose;
            XVisibilityEvent xvisibility;
            XCreateWindowEvent xcreatewindow;
            XDestroyWindowEvent xdestroywindow;
            XUnmapEvent xunmap;
            XMapEvent xmap;
            XMapRequestEvent xmaprequest;
            XReparentEvent xreparent;
            XConfigureEvent xconfigure;
            XGravityEvent xgravity;
            XResizeRequestEvent xresizerequest;
            XConfigureeRequestEvent xconfigurerequest;
            XCirculateEvent xcirculate;  
            XCirculateRequestEvent xcirculaterequest;
            XPropertyEvent xproperty;
            XSelectionClearEvent xselectionclear;
            XSelectionRequestEvent xselectionrequest;
            XSelectionEvent xselection;
            XColormapEvent xcolormap;
            XClientMessageEvent xclient;
            XMappingEvent xmapping;
            XErrorEvent xerror;
            XKeymapEvent xkeymap;
            long pad[24];
            } XEvent;


            --------------------------------------------------------------------------------
            根據(jù) type 這個(gè)欄位, 我們可以分辨出不同的 Event。依據(jù)不同的 Event, 我就可以透過(guò)對(duì)映該 Event 的欄位, 取得該 Event 的相關(guān) 訊息和資料。

            下面是用來(lái)標(biāo)示各種 Event type 的 mask: 
            --------------------------------------------------------------------------------

            NoEventMask
            KeyPressMask
            KeyReleaseMask
            ButtonPressMask
            ButtonReleaseMask
            EnterWindowMask
            LeaveWindowMask
            PointerMotionMask
            PointerMotionHintMask
            Button1MotionMask
            Button2MotionMask
            Button3MotionMask
            Button4MotionMask
            Button5MotionMask
            ButtonMotionMask
            KeymapStateMask
            ExposureMask
            VisibilityChangeMask
            StructureNotifyMask
            ResizeRedirectMask
            SubstructureNotifyMask
            SubstructureRedirectMask
            FocusChangeMask
            PropertyChangeMask
            ColormapChangeMask
            OwnerGrabButtonMask


            --------------------------------------------------------------------------------
            使用這些 mask 檢查 _XEvent 中表示 Event type 的 type 欄位, 可以得知處理之 Event 的 type。

            下表是不同的 Event type, 在 _XEvent 中所該對(duì)映的欄位。多個(gè) type 可能對(duì)映到同一個(gè)欄位。 
            Event Mask Event Type Structure Generic Structure 

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            ButtonMotionMask MotionNotify XPointerMoveEvent XMotionEvent 
            Button1MotionMask 
            Button2MotionMask 
            Button3MotionMask 
            Button4MotionMask 
            Button5MotionMask 
            ButtonPressMask ButtonPress XButtonPressedEvent XButtonEvent 
            ButtonReleaseMask ButtonRelease XButtonReleaseEvent XButtonEvent 
            ColormapChangeMask ColormapNotify XColormapEvent 
            EnterWindowMask EnterNotify XEnterWindowEvent XCrossingEvent 
            LeaveWindowMask LeaveNotify XLeaveWindowEvent XCrossingEvent 
            ExposureMask Expose XExposeEvent 
            GCGraphicsExposures in GC GraphicsExpose XGraphicsExposeEvent 
             NoExpose XNoExposeEvent 
            FocusChangeMask FocusIn XFocusInEvent XFocusChangeEvent 
             FocusOut XFocusOutEvent XFocusChangeEvent 
            KeymapStateMask KeymapNotify XKeymapEvent 
            KeyPressMask KeyPress XKeyPressEvent XKeyEvent 
            KeyReleaseMask KeyRelease XKeyReleaseEvent XKeyEvent 
            OwnerGrabButtonMask N.A. N.A. 
            PointerMotionMask MotionNotify XPointerMovedEvent XMotionEvent 
            PointerMotionHintMask N.A. N.A. 
            PropertyChangeMask PropertyNotify XPropertyEvent 
            ResizeRedirectMask ResizeRequest XResizeRequestEvent 
            StructureNotifyMask CirculateNotify XCirculateEvent 
             ConfigureNotify XConfigureEvent 
             DestroyNotify XDestroyWindowEvent 
             GravityNotify XGravityEvent 
             MapNotify XMapEvent 
             ReparentNotify XReparentEvent 
             UnmapNotify XUnmapEvent 
            SubstructureNotifyMask CirculateNotify XCirculateEvent 
             ConfigureNotify XConfigureNotify 
             CreateNotify XCreateWindowEvent 
             DestroyNotify XDestroyWindowEvent 
             GravityNotify  
             MapNotify XMapEvent 
             ReparentNotify XReparentEvent 
             UnmapNotify XUnmapEvent 
            SubstructureRedirectMask CirculateRequest XCirculateRequestEvent 
             ConfigureRequest XConfigureRequestEvent 
             MapRequest XMapRequestEvent 
            N.A. ClientMessage XClientMessageEvent 
            N.A. MappingNotify XMappingEvent 
            N.A. SelectionClear XSelectionClearEvent 
            N.A. SelectionNotify XSelectionEvent 
            N.A. SelectionRequest XSelectionRequestEvent 
            VisibilityChangeMask VisibilityNotify XVisibilityEvent 
             

            第一欄是代表的 Event Mask, 第二欄是 Event type, 第三欄是在 _XEvent 中所對(duì)映之 structure type。當(dāng)有兩個(gè)以上的 Event type 在 _XEvent 中共用一個(gè) structure type, 則該 structure type 會(huì)出現(xiàn)在第四欄。表中的 N.A. 表示該欄位在該列不具任何意義。

            Events Propagation 
            當(dāng)視窗有事件發(fā)生時(shí),對(duì)相對(duì)應(yīng)的 Event 卻可能不是由該視窗產(chǎn)生, 由其它的視窗產(chǎn)生。在我們?cè)O(shè)定視窗屬性時(shí),有一個(gè) do_not_propagate_mask 欄位。do_not_propagate_mask 用來(lái)選擇那 些 event 不能往先視窗(ancestor window)傳遞。一般來(lái)說(shuō) KeyPress KeyRelease ButtonPress ButtonRelease PointerMotion Button1Motion - Button2Motion 這些 event 發(fā)生之後,如果在 發(fā)生的視窗要求知道這些訊息,則這 evnet 會(huì)往父視窗(parent window)傳遞(propagation)。如果父視窗也不要,就會(huì)再往父視窗 的父視窗傳遞,一直到遇到其中的一個(gè)先視窗(ancester window) 有 client 向 其要求這項(xiàng) evnet 為止,這時(shí) Event 就會(huì)在這個(gè)祖先視窗產(chǎn)生。 我們稱這個(gè)祖先視窗為 Event Window,而發(fā)生 event 的視窗我們 稱之為 Source Window。如果在傳遞 event 的過(guò)程中,若有任何 一個(gè)傳遞經(jīng)過(guò)的視窗,在該視窗的 do_not_propagate_mask 設(shè)定 設(shè) evnet,則傳遞將會(huì)停止下來(lái),不再繼續(xù)往先視窗傳遞。

            Event Handling
            X Server 會(huì)針對(duì)各個(gè)視窗產(chǎn)生各種的 Event, 但是對(duì)於 client 程 式而言, 并不是所有的 Event 都是需要的。而大量的訊息傳送, 會(huì) 使的整個(gè)系統(tǒng)的效率降低, 所以我們并不希望 X Server 對(duì) client 送出所有的 Evnet。因此在 X 的設(shè)計(jì)上, X Server 讓 client 可 以選擇每個(gè)視窗所需要的 Event, 只傳送需要的 Event 給 client 。在 client 程式端, 由 X Server 送過(guò)來(lái)的 Event 都會(huì)存在 Event Queue 等待程式讀取和處理。程式可以透過(guò) XLib 所提供的 函數(shù), 讀取 Event Queue 內(nèi)的 Event 并取得關(guān)於 Event Queue 的 資訊。當(dāng) request 產(chǎn)生時(shí), XLib 并不會(huì)馬上將之傳到 X Server。 因?yàn)樾×慷啻蔚馁Y料傳送, 對(duì)於網(wǎng)路的效率是一個(gè)很大的傷害。 為了提高傳送的效率, XLib 會(huì)將產(chǎn)生的 Request 先暫存在 output buffer, 到達(dá)某一程度的量時(shí), 再一口氣將之傳送到 X Server。 然而這個(gè)使的 X Server 的反應(yīng)延遲, 我們可能希望 X Server 立 即做出反應(yīng)和處理。諸如此類(lèi), 我們可以要求 XLib 立即將 output buffer 的 request 全部傳送給 X Server,讓 X Server 可以即 時(shí)收到 request 并做出反應(yīng)。

            設(shè)定視窗需要產(chǎn)生那些 Event 的方法有很多種, 我們可以在呼叫 XCreateWindow 和 XChangeWindowAttributes 時(shí), 設(shè)定 XSetWindowAttributes 的 event_mask 欄位, 將之作為 XCreateWindow 和 XChangeWindowAttributes 的參數(shù)。另外就是透 過(guò) XSelectInput這個(gè)函數(shù)來(lái)選擇。 
            --------------------------------------------------------------------------------

            XSelectInput(display, w, event_mask)
            Display *display;
            Window w;
            long event_mask;

            w 指定選擇事件的視窗
            event_mask 指定 event mask


            --------------------------------------------------------------------------------
            XSelectInput 可以為你的 client 選取任何視窗上的 Event, 只要該視窗有你需要的 Event 發(fā)生, X Server 就會(huì)送 Event 給 client。而 X Server 會(huì)為任何向他登記需要該 Event 的 client 發(fā)送 Event。

            在選擇好所需要的 Event 之後, 我們就可以開(kāi)始接受 X Server 送來(lái)的 Event。一個(gè) client 程式, 可能同時(shí)會(huì)使用到多個(gè) 視窗, 但所有視窗的 Event 傳送到 client 後, 都會(huì)存在 Event Queue。雖然各個(gè)視窗的 Event 會(huì)因而混在一起, 但是我們可以 透過(guò) XEvent 這個(gè) union type 的 XAnyEvent 結(jié)構(gòu)的 window 欄位區(qū)分出該 Event 所屬的視窗。

            透過(guò) XNextEvent, 可以從 Event Queue 取出下一個(gè)從 X Server 送來(lái)的 Event, 并將之從 Event Queue 移除。 
            --------------------------------------------------------------------------------

            XNextEvent(display, event_return)
            Display *display;
            XEvent *event_return;

            event_return 傳回 event queue 的下一個(gè) event


            --------------------------------------------------------------------------------


            XPeekEvent 和 XNextEvent 的功能大致相同, 只差於 XPeekEvent 不會(huì)將傳回的 Event 從 Event Queue 移除。 
            --------------------------------------------------------------------------------

            XPeekEvent(display, event_return)
            Display *display;
            XEvent *event_return;

            event_return 傳回 event queue 的下一個(gè) event


            --------------------------------------------------------------------------------


            XFlush 會(huì)將暫存在 output buffer 的所有 request 立即傳送出 去。 
            --------------------------------------------------------------------------------

            XFlush(display)
            Display *display;


            --------------------------------------------------------------------------------
            一般程式中并不會(huì)使用到這個(gè)函數(shù), 因?yàn)?nbsp;XPending, XNextEvent 和 XWindowEvent 會(huì)自動(dòng) flush output buffer。

            XSync 會(huì)像 XFlush 一樣, 將 output buffer 所有的 request 傳送出去, 并且還會(huì)等待所有的 request 都被 X Server 處理。 
            --------------------------------------------------------------------------------

            XSync(display, discard)
            Display *display;
            Bool discard;

            discard 指示 XSync 是否要放棄現(xiàn)在 Event Queue
            的所有 Event。


            --------------------------------------------------------------------------------


            當(dāng) Event 源源不斷的從 X Server 傳來(lái)時(shí), Event Queue 可能 放滿了一些尚未被取出處理的 Event。XEventsQueued 會(huì)傳回 Event Queue , 目前所存放的 Event 數(shù)量。 
            --------------------------------------------------------------------------------

            int XEventsQueued(display, mode)
            Display *display;
            int mode;

            mode 指定設(shè)定模式。你可以指定 QueuedAlready,
            QueuedAfterFlush, 或 QueuedAfterReading。


            --------------------------------------------------------------------------------
            XEventsQueued 可以指定三種模式: 
            QueuedAlready: 
            傳回目前 Event Queue 的 evnet數(shù)量。 
            QueuedAfterFlush: 
            如果 Event Queue 不是空的, 則傳回 Event Queue 的 Event 數(shù)量。若是空的, 則先 flush output buffer, 并試著從 connection 讀出更 多的 Event, 然後傳回讀到的 Event 數(shù)量。 
            QueuedAfterReading: 
            如果 Event Queue 不是空的, 則傳 回 Event Queue 的 Event 數(shù)量。反之, 則試著從 connection 讀出所有的 Event, 但是并不 flush output buffer, 然後傳回所讀到的 Event 數(shù)量。 

            傳回 Event Queue , 第一個(gè)和指定視窗和 evnet mask 符 合之 Event。 
            --------------------------------------------------------------------------------

            XWindowEvent(display, w, event_mask, event_return)
            Display *display;
            Window w;
            long event_mask;
            XEvent *event_return;

            w 指定視窗
            event_mask 指定 event mask
            event_return 傳回符合的 event structure


            --------------------------------------------------------------------------------


            傳回 Event Queue , 第一個(gè)符合指定之 evnet mask 的 Event。 
            --------------------------------------------------------------------------------

            XMaskEvent(display, event_mask, event_return)
            Display *display;
            long event_mask;
            XEvent *event_return;

            event_mask 指定要求之 event mask
            event_return 傳回符合條件的 event structure


            --------------------------------------------------------------------------------


            Events
            MapNotify
            當(dāng)視窗從未映射(unmapped)的狀態(tài)變?yōu)橛成?mapped)狀態(tài)時(shí), 會(huì)發(fā)生 MapNotify Event,并傳送到需要該 Event 的 client。 而使視窗從未映射的狀態(tài)轉(zhuǎn)變成映射狀態(tài)進(jìn)而使 X Server 產(chǎn)生 MapNotify Event 的原因,可能是因?yàn)?nbsp;client 呼叫 XMapWindow XMapRaised XMapSubwindows 或 XReparentWindow 等 Xlib 函數(shù)。 而需要視窗 MapNotify Event 的 client,必需設(shè)定 event mask 的 StructureNotifyMask bit 或是 SubstructureNotifyMask, 如此 X Server 才會(huì)將產(chǎn)生的 MapNotify Event 傳送給 client。SubstructureNotifyMask 是設(shè)在父視窗(parent window) 的,一旦 client 在視窗的 event mask 設(shè)定 SubstructureNotifyMask bit,則只要有任何的子視窗(child window) 被映射(mapped),就會(huì)產(chǎn)生 MapNotify。下面是 MapNotify Event 的結(jié)構(gòu): 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event; /* true 如果是以 SendEvent 產(chǎn)生 */
            Display *display;
            Window event;
            Window window;
            Bool override_redirect;
            } XMapEvent;


            --------------------------------------------------------------------------------
            event 所存的 Window ID 要看 UnmapNotify Event 是因?yàn)樵O(shè)定 StructureNotifyMask 或是 SbustructureNotifyMask 而產(chǎn)生。 如果是因?yàn)?nbsp;StructureNotifyMask ,則 event 的內(nèi)容是變成 未映射(unmapped) 視窗的 Window ID,反之若是因?yàn)?nbsp;SubstructureNotifyMask 而產(chǎn)生的,則 event 欄位被設(shè)定為被 變成未映射之視窗的父視窗(parent window) 的 Window ID。 window 則是被映射的視窗的 Window ID。

            UnmapNotify
            這是和 MapNotify 相反的情況。當(dāng)視窗從映射(mapped)狀態(tài)轉(zhuǎn)變 為未映射(unmapped)狀態(tài)時(shí),X Server 會(huì)產(chǎn)生 UnmapNotify Evnet ,并傳送給需要該 Evnet 的 client。client 若需要接收 UnmapNotify Event,則必需在 event mask 設(shè)定 StructureNotifyMask bit 或 SubstructureNotifyMask bit。SubstructureNotifyMask 是 設(shè)在父視窗(parent window),當(dāng) client 在視窗的 event mask 設(shè)定 SubstructureNotifyMask bit 時(shí),任何的子視窗(child window)變成 未映射(unmapped)時(shí),就會(huì)產(chǎn)生 UnmapNotify。這個(gè) event type 的結(jié)構(gòu)(structure) 如下所示: 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event; /* true 如果是以 SendEvent 產(chǎn)生 */
            Display *display;
            Window event;
            Window window;
            Bool from_configure;
            } XUnmapEvent;


            --------------------------------------------------------------------------------
            event 所存的 Window ID 要看 UnmapNotify Event 是因?yàn)樵O(shè)定 StructureNotifyMask 或是 SbustructureNotifyMask 而產(chǎn)生。 如果是因?yàn)?nbsp;StructureNotifyMask ,則 event 的內(nèi)容是變成 未映射(unmapped) 視窗的 Window ID,反之若是因?yàn)?nbsp;SubstructureNotifyMask 而產(chǎn)生的,則 event 欄位被設(shè)定為被 變成未映射之視窗的父視窗(parent window) 的 Window ID。 window 則是被映射的視窗的 Window ID。

            Expose
            Expose 產(chǎn)生的時(shí)機(jī)是在,當(dāng)視窗的某一個(gè)區(qū)塊的資料己經(jīng) 遺失了,而且該區(qū)域也看的見(jiàn)時(shí),這時(shí) X Server 必需通知那 些想要得知這個(gè)訊息的 client,以便這些 client 補(bǔ)上這塊被 遺失的資料或做其它合適處置。當(dāng)我們?cè)谕粋€(gè)畫(huà)面上同時(shí)開(kāi) 上兩個(gè)以上的視窗時(shí),往往會(huì)覺(jué)的畫(huà)面不夠大而使的視窗相互 重疊。在重疊的部分,下面的視窗中,也許原本在該區(qū)有顯示 什麼資料,但現(xiàn)在被上面的視窗蓋掉了。經(jīng)過(guò)我們的操作,經(jīng) 過(guò)一段時(shí)間,原本被蓋住的部分又會(huì)重新被顯示出來(lái)。如我把 在上面的視窗關(guān)掉,其它視窗被該視窗蓋住的部分又會(huì)顯示出 來(lái)?;蚴俏覀儼涯硞€(gè)視窗顯小成小圖示(icon)那麼其它視窗被 其蓋住的部分也會(huì)再度顯示出來(lái)。當(dāng)這些被上層蓋住的區(qū)塊被 再度裸露出來(lái)時(shí),X Server 必需為這些區(qū)塊重新畫(huà)上在下層 視窗的資料,以使產(chǎn)生上層視窗被移掉,而下層視窗浮出來(lái) 的效果,但往往 X Server 并沒(méi)有記錄下這些被遮蓋區(qū)塊的 內(nèi)容。這時(shí) X Server 就需要 client 的協(xié)助,重新把這個(gè)失 落的環(huán)節(jié)補(bǔ)上。視窗被重新裸露出來(lái)時(shí),被裸露出來(lái)的區(qū)塊往往 并不是規(guī)則的四方形。被裸露出來(lái)的部分可能成梯狀或某種由 四方形方塊相疊而形成的圖形。每個(gè) Expose Event 都包含著 一個(gè)在視窗內(nèi)被裸露出來(lái)的方形區(qū)塊的位置和大小,X Server 會(huì)為每個(gè)該被重新補(bǔ)上的方形區(qū)塊產(chǎn)生一個(gè) Expose Event。 而 X Server 會(huì)把同一次裸露事件所產(chǎn)生的 Expose Evnet 一 起且連續(xù)的送出。要接收 Expose Event 的 client 必需在 event mask 設(shè)定 ExposureMask。Expose Event 的結(jié)構(gòu)如下: 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window window;
            int x, y;
            int width, height;
            int count;
            } XExposeEvent;


            --------------------------------------------------------------------------------
            window 是被裸露出來(lái)的視窗的 Window ID。x 和 y 則是該 被重繪的方形區(qū)塊的右上角座標(biāo),width 和 height 則是該 區(qū)塊的寬度和高度。而 count 若為 0,則表示這個(gè) Expose Event 是這次視窗被裸所產(chǎn)生的最後一個(gè) Expose Event。 若不為 0,則表示後面至還有這麼多個(gè) Expose Event 在等 著,而且還可能比 count 所指示的數(shù)量多。

            ButtonPress
            ButtonRelease
            KeyPress
            KeyRelease
            MotionNotify
            X Window 提供 KeyPress 和 KeyRelease Event。當(dāng)使用者 按下鍵盤(pán)上的按鍵時(shí),X Server 會(huì)產(chǎn)生 KeyPress Event 給登記需要按鍵按下去的訊息的 client。當(dāng)使用者放開(kāi)按 鍵時(shí),X Server 又會(huì)產(chǎn)生 KeyRelease Evnet 給登記需要 KeyRelease Event 這項(xiàng)訊息的 client。X Server 會(huì)對(duì)鍵盤(pán) 上所有的按鍵產(chǎn)生這兩種 Event。ButtonPress 和 ButtonRelease 則是在滑鼠(mouse) 被按下和放開(kāi)時(shí)產(chǎn)生。 client 要接收 KeyPress KeyRelease ButtonPress ButtonRelease 等 Event,需要在 event mask 設(shè)定 KeyPressMask KeyReleaseMask ButtonPressMask ButtonReleaseMask 對(duì)等的 bit。

            當(dāng)滑鼠在視窗內(nèi)移動(dòng)時(shí),會(huì)產(chǎn)生一連串的 MotionNotify Event?;蟛粩嗟囊苿?dòng)而 MotionNotify 也不斷的產(chǎn)生, 難道你的滑鼠每移動(dòng)一點(diǎn) X Server 就產(chǎn)生一個(gè) MotionNotify 嗎? 當(dāng)然不是這麼張。X Server 并不包證多遠(yuǎn)的距離 產(chǎn)生一個(gè) MotionNotify Event,但包證至少在移動(dòng)的起 始點(diǎn)和終點(diǎn)各會(huì)產(chǎn)生一次 MotionNotify Event。 在 event mask 設(shè)定 Button1MotionMask - Button5MotionMask,ButtonMotionMask PointerMotionMask 等,可以使 X Server 傳送 MotionNotify Event 給 client。 
            --------------------------------------------------------------------------------

            Button1MotionMask - Button5MotionMask 
            當(dāng)被指定的滑鼠按鈕(button)被按住且滑鼠一邊在移動(dòng)時(shí),X Server 會(huì)產(chǎn)生 MotionNotify。 
            ButtonMotionMask 
            當(dāng)任何一個(gè)滑鼠按鈕(button)按住且滑鼠一邊移動(dòng)時(shí),X Server 會(huì)產(chǎn)生 MotionNotify。 
            PointerMotionMask 
            不論滑鼠按鈕(button)是否被按下,只要滑鼠移動(dòng) X Server 就會(huì)產(chǎn)生 MotionNotify。 
            --------------------------------------------------------------------------------
            除了上面幾個(gè)之外,還有 PointerMotionHintMask。 PointerMotionMask 是和上面幾個(gè) Mask 合使用的, 當(dāng)指定任何上面所提的 Mask 後,再加上 PointerMotionHintMask ,X Server 可以只產(chǎn)生一次 MotionNotify 給 client。除此之外,滑鼠按鈕的狀態(tài)改變 (按下變放開(kāi)或反之),滑鼠的標(biāo)離開(kāi)視窗,或 client 呼叫 XQueryPointer 或 XGetMotionEvents,X Server 也會(huì)產(chǎn)生 MotionNotify Event。這些狀況產(chǎn)生的 MotionNotify 都會(huì)設(shè)定 Event Structure 的 is_hint 欄位(is_hint memeber)。除了上面的狀況外, X Server 可能依然產(chǎn)生沒(méi)有設(shè)定 is_hint 欄位的 MotionNotify Event (也就是沒(méi)在 event mask 設(shè)定 PointerMotionMask 情況下所產(chǎn)生的 MotionNotify)。 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window window;
            Window root;
            Window subwindow;
            Time time;
            int x, y;
            int x_root, y_root;
            unsigned int state;
            unsigned int botton;
            Bool same_screen;
            } XButtonEvent;
            typedef XButtonEvent XButtonPressedEvent;
            typedef XButtonEvent XButtonReleasedEvent;

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window window;
            Window root;
            Window subwindow;
            Time time;
            int x, y;
            int x_root, y_root;
            unsigned int state;
            unsigned int keycode;
            Bool same_screen;
            } XKeyEvent;
            typedef XKeyEvent XKeyPressedEvent;
            typedef XKeyEvent XKeyReleasedEvent;

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window window;
            Window root;
            Window subwindow;
            Time time;
            int x, y;
            int x_root, y_root;
            unsigned int state;
            unsigned int is_hint;
            Bool same_screen;
            } XMotionEvent;
            typedef XMotionEvent XPointerMoveEvent;


            --------------------------------------------------------------------------------
            window 是指 event window,也就是產(chǎn)生事件的 window。root 是指 source window 所在 screen 之 root window。前面有提及 事件會(huì)尋著視窗的階層架構(gòu),往祖先視窗(ancester window)傳遞 (propagate)。若 event window 和 source window 是不同個(gè)視 窗時(shí)(從視窗階層下層傳遞上來(lái)),則 subwindow 則是 event window 的 child window,這個(gè) child window 是事件傳遞過(guò)程經(jīng)過(guò)的視 窗。若 event window 和 source window 是同一個(gè)時(shí)(也就是產(chǎn)生 Event 和事件發(fā)生是同一個(gè)視窗),則 subwindow 設(shè)為 None。 x 和 y 則是事件發(fā)生時(shí),標(biāo)相對(duì)於 event window 左上角的 座標(biāo)。x_root 和 y_root 則是標(biāo)在 root window 上的座標(biāo)。 state 是事件發(fā)生時(shí)滑鼠按鈕和鍵盤(pán)上修飾鍵的狀態(tài),是由一個(gè) 或數(shù)個(gè)狀態(tài)做 OR 運(yùn)算的組合。這些狀態(tài)是 Button1Mask, Button2Mask,Button3Mask,Button4Mask,Button5Mask, ShiftMask,LockMask,ControlMask,Mod1Mask,Mod2Mask, Mod3Mask,Mod4Mask,Mod5Mask。same_screen 是指示 root window 和 event window 是否在同一個(gè) screen,內(nèi)容是 True or False。 button 是 XButtonPressedEvent 和 XButtonReleasedEvent 事件結(jié)構(gòu)內(nèi)的欄位,用以紀(jì)錄滑鼠按鈕狀態(tài)改變。XKeyPressedEvent 和 XKeyReleasedEvent 的 keycode 是任何按鍵的 keycode 即 鍵盤(pán)按鍵的代碼(在後面會(huì)述及)。XPointerMovedEvent 事件結(jié)構(gòu) 內(nèi)的 is_hint 在前面有說(shuō)明,內(nèi)容是 NotifyNormal 或 NotifyHint。 

            CreateNotify
            CreateNotify 是在視窗建立時(shí)產(chǎn)生的事件,client 在視窗的 evnet mask 設(shè)定 SubstructureNotifyMask,則任何子視窗(child window)的建立都會(huì)產(chǎn)生 CreateNotify。這個(gè)事件的結(jié)構(gòu)包含下面 幾個(gè)資訊: 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window parent;
            Window window;
            int x, y;
            int width, height;
            int border_width;
            Bool override_redirect;
            } XCreateWindowEvent;


            --------------------------------------------------------------------------------
            parent 是被建立之視窗的 parent window 的 Window ID,window 則是新建立的 window。x 和 y 則是新視窗相於 parent window 左上角的座標(biāo)。width 和 height 則是新視窗的寬度和高度。 override_redirect 則是視窗的 override_redirect 屬性,若 為 True 則 window manager 不會(huì)幫這個(gè)視窗做處理,乎略這個(gè) 視窗。

            DestroyNotify
            DestroyNotify 是在視窗被刪除 (destroy) 時(shí)產(chǎn)生的事件。當(dāng)視窗 被刪除時(shí),其所有的子視窗也會(huì)跟著被刪除,而子視窗 (child window) 的 DestroyNotify 會(huì)在父視窗 (parent window) 之前產(chǎn)生。client 在視窗的 event mask 設(shè)定 StructureNotifyMask,則視窗被刪 除時(shí)會(huì)收到 DestroyNotify,若設(shè)定 SubstructureNotifyMask 則是子視窗 (child window) 被刪除時(shí)會(huì)收到 DestroyNotify。 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window event;
            Window window;
            } XDestroyWindowEvent;


            --------------------------------------------------------------------------------
            若是設(shè)定 StructureNotifyMask 則 event 是被刪除(destroyed) 視窗的 Window ID,若是 SubstructureNotifyMask 則 event 是被刪除視窗的父視窗 (parent window) 的 window ID。

            ResizeRequest
            如果有任何的 client 試途要改變視窗的大小, 則 X Server 會(huì)向其它要求知道這項(xiàng)訊息的 client 傳送 ResizeRequest。 當(dāng) client 需要知道這個(gè)訊息時(shí),必需在視窗的 event mask 設(shè)定 ResizeRedirect,這樣子只要有任何的其它 client 試 圖改變?cè)撘暣按笮?,X Server 就會(huì)傳送 ResizeRequest 給 client。這個(gè)事件的結(jié)構(gòu)如下: 
            --------------------------------------------------------------------------------

            typedef struct {
            int type;
            unsigned long serial;
            Bool send_event;
            Display *display;
            Window window;
            int width, height;
            } XResizeRequestEvent;


            --------------------------------------------------------------------------------
            width 和 height 是另一個(gè) client 試圖要把視窗改成的大小。

            FocusIn
            FocusOut
            當(dāng)你在鍵盤(pán)上敲下 'A' 時(shí),X Server 會(huì)將「按下按鍵'A'」這個(gè) event 送到目前 focus 的視窗。也就是當(dāng)視窗為目前的 focus 時(shí) ,X Server 才會(huì)把鍵盤(pán)輸入的事件傳送給視窗。而 focus 會(huì)在不 同的視窗之間轉(zhuǎn)移,不同的 Window Manager 有不同的轉(zhuǎn)移方式。 可能是你把滑鼠指標(biāo)移到那某個(gè)視窗,focus 就會(huì)轉(zhuǎn)移到該視窗。 也可能是你要在該視窗的 title 上面按一下,focus 才會(huì)轉(zhuǎn)移過(guò) 去。當(dāng) focus 進(jìn)入某一視窗時(shí),代表 focus 從另一個(gè)視窗移走。 focus 進(jìn)入視窗時(shí),會(huì)在該視窗產(chǎn)生 FocusIn event。focus 從 視窗移除時(shí),X Server 會(huì)在該視窗產(chǎn)生 FocusOut event。如果你 希望 client 程式接收這兩個(gè) event,必需在視窗的 event-mask 設(shè)定 FocusChangeMask 這個(gè) bit。

            下面是 FocusIn 和 FocusOut 這兩個(gè) event 的結(jié)構(gòu): 
            --------------------------------------------------------------------------------

            typedef struct {
                   int type;
                   unsigned long serial;
                   Bool send_event;
                   Display *display;
                   Window window;
                   int mode;
                   int detail;
            } XFocusChangeEvent;

            typedef XFocusChangeEvent XFocusInEvent;
            typedef XFocusChangeEvent XFocusOutEvent;


            --------------------------------------------------------------------------------



            --------------------------------------------------------------------------------

            /* ------ XEvent.c ------ */
            #include 
            #include 
            #include 
            #include 


            GC gc;
            Display *display;
            Window window;


            void
            reshow(void)
            {
            /*
             * 畫(huà)方框
             */
            XDrawRectangle(display, window, gc, 10, 10, 100, 100);

            /*
             * 畫(huà)直線
             */
            XDrawLine(display, window, gc, 200, 10, 200, 290);
            }


            int
            main_loop(XEvent *xe)
            {
            if(xe->type == Expose)
            {
            printf("Expose! \n");
            reshow();
            }

            return False;
            }


            void
            init(void)
            {
            XSetWindowAttributes attr;
            Colormap colormap;
            XColor color1, color2;
            XGCValues gcvalue;
            XSizeHints *sz;

            display = XOpenDisplay("0:0");

            colormap = DefaultColormap(display, DefaultScreen(display));
            /*
             * 配置 colorcell
             */
            color1.red = color1.blue = 0xffff;
            color1.green = 0;
            color2.red = color2.green = color2.blue = 0xff;
            color1.flags = color2.flags = DoRed | DoGreen | DoBlue; 
            XAllocColor(display, colormap, &color1);
            XAllocColor(display, colormap, &color2);

            attr.background_pixel = color2.pixel; /* background color */
            attr.event_mask = ExposureMask; /* receive expose event */

            window = XCreateWindow(display,
                   XDefaultRootWindow(display),
                   100, 100, /* 左上角位置 */
                   300, 300, /* 視窗大小 */
                   2, /* border 的寬度 */
                   XDefaultDepth(display, 0),
                   InputOutput, /* window class */
                   CopyFromParent, /* visual */
                   CWBackPixel | CWEventMask,
                   &attr); /* attributes */

            XStoreName(display, window, "hello!! world!!");

            sz = XAllocSizeHints();
            sz->x = 100;
            sz->y = 100;
            sz->width = 300;
            sz->height = 300;
            sz->flags = USPosition | USSize;
            XSetNormalHints(display, window, sz);

            /*
             * Mapping
             */
            XMapWindow(display, window);

            gcvalue.foreground = color1.pixel;
            gcvalue.background = color2.pixel;
            gcvalue.line_width = 5;
            gcvalue.line_style = LineOnOffDash;
            gcvalue.cap_style = CapButt;
            gcvalue.join_style = JoinRound;
            gc = XCreateGC(display, window,
                   GCForeground | GCBackground | 
                   GCLineWidth | GCLineStyle |
                   GCCapStyle | GCJoinStyle,
                   &gcvalue);
            }


            main() 
            {
            XEvent xe;
            int i = 0;

            init();

            while(1)
            {
            printf("while %d\n", i++);
            XFlush(display);
            XNextEvent(display, &xe); /* 取得下一個(gè) event */
            if(main_loop(&xe)) /* 處理 event */
            return 0;
            }
            }


            --------------------------------------------------------------------------------
            這個(gè)程式和第三章的例程式相似, 但處理了 expose event. 執(zhí)行之後 會(huì)發(fā)現(xiàn)處理 expose event 之後, 圖形不會(huì)因?yàn)楸黄渌暣吧w掉而無(wú) 法恢復(fù)了. 

            X Window 程式設(shè)計(jì)入門(mén)--第五章 Window
            http://cnpa.yzu.edu.tw/~thinker 作者:李圭烽 (Thinker; Thinker.bbs@bbs.yzu.edu.tw) (2001-06-02 00:16:10)
            Window
            作 者 : Thinker
            E-Mail: Thinker.bbs@bbs.yzu.edu.tw 
            --------------------------------------------------------------------------------
                
            Index:
            Create windows/Destroy windows 
                Class 
                Visual Types 
                Depth 
                Create 
                Destroy 
            Map windows/Unmap windows 
                Events 
                SubstructureRedirectMask 
                Mapping/UnMapping Fuctions 
            Configure windows 
                XWindowChanges 
                Convenient functions 
            Change the stacking order 
            Change window attributes 
                background 
                border 
                bit-gravity 
                win-gravity 
                backing-store 
                save-under 
                event-mask 
                do-not-propagate-mask 
                override-redirect 
                colormap 
                cursor 

            --------------------------------------------------------------------------------


            Create windows/Destroy windows
            Class
            X Window 系統(tǒng)的視窗可分為兩類(lèi)(兩種 Class),InputOnly 和 InputOutput。 InputOnly 的視窗,
            顧名思意就是只能做為 Input 使用,也就是 client 程式只能透過(guò)這個(gè)視窗來(lái)收取 event,但是不
            能在這個(gè)視 窗做任何的輸出。而 InputOutput 視窗則不只可以接受輸入而己, 而且也可以使用該
            視窗做輸出。你可以在 InputOutput 視窗上輸出 文字圖形,卻不能在 InputOnly 視窗上這麼做。
            InputOnly 視窗 由於并沒(méi)有輸出的能力,所以并不會(huì)出現(xiàn)在畫(huà)面上。雖然如此,實(shí) 際上它還是存在
            的。其主要功能是用來(lái)做輸入的控制,例如讓 標(biāo)進(jìn)入其區(qū)域時(shí),立即變成另一種的形式。這樣的可
            以讓使用者感 覺(jué)到標(biāo)在 parent 視窗的某個(gè)區(qū)域采用不同的標(biāo)。既然 InputOnly 沒(méi)有輸出的能力,
            所以 InputOnly 視窗也不能做為 drawable 使用。

            Visual
            在有些硬體上可能提供多種顏色的對(duì)映方式。例如有些硬體可能提供 了 16bits 的模式,也就是顯示
            出來(lái)的每個(gè)點(diǎn)使用 16bits 長(zhǎng)度的 pixel 值表示。同時(shí)也可能提供 8bits 的模式,每個(gè)點(diǎn)的顏色使用
             8bits 長(zhǎng)度的 pixel 值表示。這種 pixel 值的大小稱 depth,例如 使用 8bits 來(lái)表示顏色,則其 
             depth 為 8。除了表示的位元數(shù)不同外 ,顏色和 pixel 值之間的對(duì)映方式也不同。像一般以 RGB 為
             基礎(chǔ)的 硬,如果采用 8bits 的模式可能 3bits 對(duì)映為 red,3bits 對(duì)映 為 green,2bits 對(duì)映為 
             blue。這種對(duì)映的方式稱為 visual。

            Xlib 使用 Visual 這個(gè)結(jié)構(gòu)存放對(duì)映的 visual 資料,而 Visual 實(shí)際內(nèi)容被包裝起來(lái),不讓使用者
            直接接觸。Xlib 提供一些應(yīng)用的 函數(shù)和巨集,讓 programmer 透過(guò)這些功能來(lái)操作 Visual 結(jié)構(gòu)。 
            下面是所有的 visual 種類(lèi)及其對(duì) colormap 和 RGB 的影。 
            PseudoColor 
            pixel 值對(duì)映到 colormap 而產(chǎn)生 RGB 值,RGB 值可以隨時(shí)更改而不 影到已輸出的點(diǎn)。 
            GrayScale 
            和 PseudoColor 差不多,主要的不同在 RGB 值不能更改,否則會(huì)影 到已輸出的點(diǎn)的顏色。 
            DirectColor 
            pixel 被分成 R,G,B 三個(gè)部分,這三個(gè)部分分別對(duì)映 colormap 得到 三個(gè)值。從 colormap 得到的
            三個(gè)值,可以組合成對(duì)映的顏色值。 colormap 的 RGB 值可以隨時(shí)更換,并且不會(huì)因而影項(xiàng)到已輸出 
            的點(diǎn)之顏色。 
            TrueColor 
            和 DirectColor 近似,但是 colormap 內(nèi)的 RGB 值是內(nèi)定的,而且不能更改。不同的硬所提供的 
            colormap 不盡相同,但在 RGB 各個(gè)原色的 colormap 中,大多會(huì)提供線性或接進(jìn)線性變化的 RGB 值。 
            StaticColor 
            和 PseudoColor 的不同在於其 colormap 的 RGB 值是預(yù)定的,無(wú)法修改的。 
            StaticGray 
            和 StaticColor 相似,但任何單一點(diǎn)的 RGB 值都一樣,其實(shí)就是單色的意思。 
            Depth
            depth 就如先前所說(shuō)的,用以表示對(duì)映顏色的資料長(zhǎng)度。以 8bits 的 pixel 值表示對(duì)映顏色,則 
            depth 為 8。 
            Create
            Xlib 提供 XCreateWindow 建立 unmapped 的視窗: 
            --------------------------------------------------------------------------------

                 Window XCreateWindow(display, parent, x, y, width, height,
            border_width, depth, class, visual, valuemask, attributes)
                       Display *display;
                       Window parent;
                       int x, y;
                       unsigned int width, height;
                       unsigned int border_width;
                       int depth;
                       unsigned int class;
                       Visual *visual
                       unsigned long valuemask;
                       XSetWindowAttributes *attributes;


            --------------------------------------------------------------------------------
            如果成功建立視窗的話,XCreateWindow 會(huì)傳回一 Window ID,用以 往後指定視窗,并且產(chǎn)生 
            CreateNotify event。新建立的視窗,會(huì)是 parent 參數(shù)所指定之視窗的子 視窗(subwindow)。x 和 y 
            則指定視窗左上角相對(duì)於 parent 視窗左 上角的座標(biāo)。width 和 hieght 指定視窗的寬和高。border_width 
            和 depth 分別是視窗邊框的寬度和視窗的 depth,depth 并不需要和 parent 一樣。視窗的 class 為 
            InputOnly ,border_width 和 depth 必需指定為零,否則會(huì)產(chǎn)生 BadMatch error。InputOutput 視窗的 
            parent 規(guī)定必需也是 InputOutput,否則會(huì)產(chǎn)生 BadMatch error,InputOnly 則無(wú)這種限 制。visual 
            必需設(shè)為硬體有提供的 visual。valuemask 和 attributes 則合力指定視窗的屬性,在後面會(huì)談到。

            XCreateSimpleWindow 則是簡(jiǎn)易版,用於建立 InputOutput 視窗: 
            --------------------------------------------------------------------------------

                 Window XCreateSimpleWindow(display, parent, x, y, width, height,
                  border_width, border, background)
                       Display *display;
                       Window parent;
                       int x, y;
                       unsigned int width, height;
                       unsigned int border_width;
                       unsigned long border;
                       unsigned long background;


            --------------------------------------------------------------------------------
            參數(shù)的指定和 XCreateWindow 都差不多,border 是指定邊框的 pixel 值,background 指定背景的 
            pixel 值。

            Destroy
            任何一個(gè)視窗被關(guān)掉(移除; destroy)都會(huì)產(chǎn)生 DestroyNotify event。 parent 視窗被關(guān)掉,子視窗也
            會(huì)因而被關(guān)掉,而且會(huì) parent 視窗關(guān) 掉之前先自動(dòng)關(guān)掉子視窗。這時(shí),任何被關(guān)掉的視窗,包括子視窗
            和 parent 視窗,都會(huì)產(chǎn)生 DestroyNotify event。

            XDestroyWindow 是用以關(guān)閉指定之視窗及其子視窗。 
            --------------------------------------------------------------------------------

              XDestroyWindow(display, w)
                    Display *display;
                    Window w;


            --------------------------------------------------------------------------------


            XDestroySubwindows 關(guān)閉指定視窗的所有子視窗,但不包括指定 之視窗。 
            --------------------------------------------------------------------------------

              XDestroySubwindows(display, w)
                    Display *display;
                    Window w;


            --------------------------------------------------------------------------------

            Map windows/Unmap windows
            Events
            視窗被建立之後,并不會(huì)立即出現(xiàn)在螢?zāi)簧希陲@示之前還要經(jīng)過(guò)一個(gè) 稱為 mapping 的動(dòng)作。map 一個(gè)
            子視窗後,如果其任何一個(gè) ancest 視窗(先視窗)是在 unmapped 狀態(tài)(未曾被 map, 或者曾被 map 但又
             被 unmap 了)則子視窗還是不會(huì)顯示出來(lái),我們稱之為 unviewable。 子視窗必需等到其所有 ancest 
             視窗都在 mapped 的狀態(tài)下時(shí),才會(huì)從 unviewable 的狀態(tài)進(jìn)入到 viewable 狀況。視窗只有在 viewable 
             的狀 態(tài)下才會(huì)被顯示。將視窗 unmap 會(huì)使的視窗和其子視窗都隱形起來(lái)。任 何一個(gè)視窗只要有任何一個(gè)
              ancest 視窗被 unmap,都會(huì)使該視窗從顯 示器上消失(隱形起來(lái)),也就是進(jìn)入 unviewable 的狀態(tài)。

            當(dāng)視窗被 map 時(shí),X Server 會(huì)產(chǎn)生 MapNotify evnet。而 unmap 時(shí),會(huì) 產(chǎn)件 UnmapNotify event。當(dāng)視
            窗由 unviewable 進(jìn)入 viewable 狀態(tài), 并且沒(méi)有全部被其它視窗遮住,則 X Server 會(huì)產(chǎn)生 Expose event。
             任何時(shí)候,只要視窗的任何一部分從在顯示上看不到 的狀態(tài)變成看的到的狀態(tài),就會(huì)產(chǎn)生 Expose evnet。

            SubstructureRedirectMask
            如果有 client 程式對(duì) parent 視窗設(shè)定 SubstructureRedirectMask,則其它的 client 對(duì)子視窗發(fā)出的
             Map request 都會(huì)被轉(zhuǎn)送給設(shè)定 SubstructureRedirectMask 的 client,而且該 Map request 并不會(huì)被
             進(jìn)行。Window Manager 就是采用這個(gè)方式,對(duì) root 視窗設(shè)定 SubstructureRedirectMask ,因而能攫取
             其它 client 對(duì) root 視窗的子視窗(top window)所送 出的 Map request,而收到 MapRequest Event。
             透過(guò)這樣的方式, Window Manager 能控制視窗的外觀和行為。但,事情并不完全這樣 的,如果子視窗
             (child window)的 override-redirect flag 被設(shè)為 True,會(huì)使這種轉(zhuǎn)送(redirect)機(jī)制失效,其它視窗
             所產(chǎn)生的 Map request 將不再被轉(zhuǎn)送給在父視窗設(shè)定 SubstructureRedirectMask 的 client。

            類(lèi)似於 SubstructureRedirectMask 的情形也發(fā)生在 ResizeRedirectMask。如果有 client 對(duì) parent window
             設(shè)定 ResizeRedirectMask,則其它 client 對(duì) child window 的 Resize request 同樣也會(huì)被轉(zhuǎn)送給對(duì) 
             parent window 設(shè)定 ResizeRedirectMask 的 client。如果 child window 的 override-redirect flag 被
             設(shè)為 True,同樣的,這種轉(zhuǎn)送機(jī)制 也會(huì)失效。

            Mapping/UnMapping Fuctions

            --------------------------------------------------------------------------------

              XMapWindow(display, w)
                    Display *display;
                    Window w;

              XMapRaised(display, w)
                    Display *display;
                    Window w;

              XMapSubwindows(display, w)
                    Display *display;
                    Window w;


            --------------------------------------------------------------------------------
            XMapRaised() 除了 map 指定的視窗之外,還會(huì)使的視窗上到 window stack 的最上面,使的視窗出現(xiàn)在畫(huà)面
            的最上面,不會(huì)被 其它的視窗擋住。而 XMapSubwindows() 則是 map 指定視窗的所 有子視窗。

            Configure windows
            XWindowChanges

            --------------------------------------------------------------------------------

                 /* Configure window value mask bits */
                 #define   CWX                         (1<<0)
                 #define   CWY                         (1<<1)
                 #define   CWWidth                     (1<<2)
                 #define   CWHeight                    (1<<3)
                 #define   CWBorderWidth               (1<<4)
                 #define   CWSibling                   (1<<5)
                 #define   CWStackMode                 (1<<6)
                 /* Values */

                 typedef struct {
                      int x, y;
                      int width, height;
                      int border_width;
                      Window sibling;
                      int stack_mode;
                 } XWindowChanges;


            --------------------------------------------------------------------------------

            x,y 
            顧名思意, x,y 欄位設(shè)定視窗的左上角位置. 
            width,height 
            視窗的寬(width)和高(height) 
            border_width 
            視窗邊框的寬度 
            sibling,stack_mode 
            sibling 和 stack_mode 是相關(guān)的, 在 sibling 設(shè)定一個(gè) window ID, 此視窗和 欲設(shè)定其屬性的視窗
            為兄弟(sibling;同一個(gè) parent window). stack_mode 指定 視窗重疊順序如何調(diào)整. 
            我們可以使用 XConfigureWindow 來(lái)對(duì)視窗設(shè)定一些屬性. 
            --------------------------------------------------------------------------------

                 XConfigureWindow(display, w, value_mask, values)
                       Display *display;
                       Window w;
                       unsigned int value_mask;
                       XWindowChanges *values;


            --------------------------------------------------------------------------------
            values 傳入一些視窗的屬性, 是一個(gè) (XWindowChanges *)的指標(biāo). XWindowChanges 請(qǐng)參考上表. 
            value_mask 用以表示被修改的 屬性部分. 若指定 values->sibling 和 values->stack_mode, 則 w 
            視窗的重疊次序會(huì)如下改變: 
            Above 
            w 視窗的重疊次序會(huì)重新排在 sibling 的上面. 
            Below 
            w 視窗的重疊次序會(huì)重新排在 sibling 的下面. 
            TopIf 
            若 sibling 視窗完全蓋住 w 視窗, 則 w 視窗的次序會(huì)重新排在最上面. 
            ButtomIf 
            若 w 視窗完全蓋住 sibling 視窗, 則 w 視窗的次序會(huì)重新排在最下面. 
            Opposite 
            若 sibling 視窗完全蓋住 w 視窗, 則 w 視窗的次序會(huì)重新排在最上面. 若 w 視窗完全蓋住 sibling
             視窗, 則 w 視窗的次序會(huì)重新排在最下面. 
            若只指定 values->stack_mode, 而未指定 values->sibling, 則 w 視窗的重疊次序會(huì)如下改變: 
            Above 
            w 視窗的重疊次序會(huì)重新排在任何其它兄弟視窗的上面(最上面;top). 
            Below 
            w 視窗的重疊次序會(huì)重新排在任何其它兄弟視窗的下面(最下面;buttom). 
            TopIf 
            若有任何其它兄弟視窗蓋住 w, 則 w 的重疊次序會(huì)重新排在最上面. 
            ButtomIf 
            若 w 蓋住任何其它兄弟視窗, 則 w 的重疊次序會(huì)重新排在最下面. 
            Opposite 
            若有任可其它兄弟視窗蓋住 w, 則 w 的重疊次序會(huì)重新排在最上面. 若 w 蓋住任何其它兄弟視窗, 
            則 w 的重疊次序會(huì)重新排在最下面. 

            --------------------------------------------------------------------------------

            #include 
            #include 
            #include 
            #include 
            #include 


            Display *display;
            Window window;
            GC gc;


            void
            draw()
            {
            XDrawRectangle(display, window, gc, 10, 10, 100, 100);

            XDrawLine(display, window, gc, 200, 10, 200, 290);
            }


            main()
            {
            XSetWindowAttributes attr;
            Colormap colormap;
            XColor color1, color2;
            XGCValues gcvalue;
            XSizeHints *sz;
            unsigned int vmask;
            XWindowChanges values;

            display = XOpenDisplay("0:0");

            colormap = DefaultColormap(display, DefaultScreen(display));
            color1.red = color1.blue = 0xffff;
            color1.green = 0;
            color2.red = color2.green = color2.blue = 0xff;
            color1.flags = color2.flags = DoRed | DoGreen | DoBlue; 
            XAllocColor(display, colormap, &color1);
            XAllocColor(display, colormap, &color2);

            attr.background_pixel = color2.pixel;
            window = XCreateWindow(display, XDefaultRootWindow(display),
            50, 100, 400, 300, 2, XDefaultDepth(display, 0),
            InputOutput, CopyFromParent, CWBackPixel, &attr);

            XStoreName(display, window, "hello!! world!!");
            sz = XAllocSizeHints();
            sz->x = 50;
            sz->y = 100;
            sz->width = 400;
            sz->height = 300;
            sz->flags = USPosition | USSize;
            XSetNormalHints(display, window, sz);
            XMapWindow(display, window);
            XFlush(display);

            gc = XCreateGC(display, window, 0, &gcvalue);
            XSetLineAttributes(display, gc, 5, LineOnOffDash,
            CapButt, JoinRound);
            XSetForeground(display, gc, color1.pixel);
            XSetBackground(display, gc, color2.pixel);
            XFlush(display);
            sleep(2);
            draw();
            XFlush(display);
            sleep(3);

            printf("XConfigureWindow()\n");
            values.x = 100;
            values.y = 50;
            values.width = 300;
            values.height = 200;
            vmask = CWX | CWY | CWWidth | CWHeight;
            XConfigureWindow(display, window, vmask, &values);
            XFlush(display);
            sleep(2);
            draw();
            XFlush(display);
            sleep(3);

            XDestroyWindow(display, window);
            XFlush(display);

            XCloseDisplay(display);
            }


            --------------------------------------------------------------------------------
            上例是改變視窗的位置和大小, 位置在螢?zāi)簧?nbsp;(100, 50) 的位置, 大小為寬高各為 300 和 200. 
            Convenient functions

            --------------------------------------------------------------------------------

                 XMoveWindow(display, w, x, y)
                       Display *display;
                       Window w;
                       int x, y;

                 XResizeWindow(display, w, width, height)
                       Display *display;
                       Window w;
                       unsigned int width, height;

                 XMoveResizeWindow(display, w, x, y, width, height)
                       Display *display;
                       Window w;
                       int x, y;
                       unsigned int width, height;

                 XSetWindowBorderWidth(display, w, width)
                       Display *display;
                       Window w;
                       unsigned int width;


            --------------------------------------------------------------------------------

            XMoveWindow, XResizeWindow, XMoveResizeWindow, XSetWindowBorderWidth, 分別為移動(dòng)視窗, 
            改變視窗大小, 移動(dòng)并改變視窗大小, 和設(shè)定視窗的外框的 寬度, 是一些簡(jiǎn)單方便的函數(shù), 可以簡(jiǎn)
            化 XConfigureWindow 的使用. 
            Change the stacking order
            在 X 的 window 常因?yàn)橄嗷ブ丿B, 而使的視窗部方的畫(huà)面被其它視窗擋 住. 這種視窗重疊的上下次
            序稱為 stack order. 
            --------------------------------------------------------------------------------

              XRaiseWindow(display, w)
                    Display *display;
                    Window w;

              XLowerWindow(display, w)
                    Display *display;
                    Window w;


            --------------------------------------------------------------------------------
            上面兩個(gè)函數(shù)正是把視窗在 stack 的順序移至最上面(raise)和 最下面(lower). 
            --------------------------------------------------------------------------------

              XCirculateSubwindows(display, w, direction)
                    Display *display;
                    Window w;
                    int direction;


            --------------------------------------------------------------------------------
            XCirculateSubwindows 改變有子視窗的 stack order, 'direction ' 為 移動(dòng)的方向, RaiseLowest 把
            所有視窗往上移動(dòng)一個(gè)位子, 最上面的視窗 則回到 stack 的最下面, LowerHighest 則反之. 
            --------------------------------------------------------------------------------

              XCirculateSubwindowsUp(display, w)
                    Display *display;
                    Window w;

              XCirculateSubwindowsDown(display, w)
                    Display *display;
                    Window w;


            --------------------------------------------------------------------------------
            和 XCirculateSubwindows 功能重, 但比較易於使用. 
            --------------------------------------------------------------------------------

              XRestackWindows(display, windows, nwindows);
                    Display *display;
                    Window windows[];
                    int nwindows;


            --------------------------------------------------------------------------------
            透過(guò) XRestackWindows 可以直接指定 stack order. windows 傳入 依次序存放的 Window 陣列, 
            nwindows 則是陣列的長(zhǎng)度. 
            Change window attributes
            視窗除了位置和大小之外, 還有其它不同的屬性, 控制視窗的外觀和行為. 
            --------------------------------------------------------------------------------

                 /* Window attribute value mask bits */
                 #define   CWBackPixmap                (1L<<0)
                 #define   CWBackPixel                 (1L<<1)
                 #define   CWBorderPixmap              (1L<<2)
                 #define   CWBorderPixel               (1L<<3)
                 #define   CWBitGravity                (1L<<4)
                 #define   CWWinGravity                (1L<<5)
                 #define   CWBackingStore              (1L<<6)
                 #define   CWBackingPlanes             (1L<<7)
                 #define   CWBackingPixel              (1L<<8)
                 #define   CWOverrideRedirect          (1L<<9)
                 #define   CWSaveUnder                 (1L<<10)
                 #define   CWEventMask                 (1L<<11)
                 #define   CWDontPropagate             (1L<<12)
                 #define   CWColormap                  (1L<<13)
                 #define   CWCursor                    (1L<<14)
                 /* Values */

              typedef struct {
                   Pixmap background_pixmap;/* background, None, or ParentRelative */
                   unsigned long background_pixel;/* background pixel */
                   Pixmap border_pixmap;    /* border of the window or CopyFromParent */
                   unsigned long border_pixel;/* border pixel value */
                   int bit_gravity;         /* one of bit gravity values */
                   int win_gravity;         /* one of the window gravity values */
                   int backing_store;       /* NotUseful, WhenMapped, Always */
                   unsigned long backing_planes;/* planes to be preserved if possible */
                   unsigned long backing_pixel;/* value to use in restoring planes */
                   Bool save_under;         /* should bits under be saved? (popups) */
                   long event_mask;         /* set of events that should be saved */
                   long do_not_propagate_mask;/* set of events that should not propagate */
                   Bool override_redirect;  /* boolean value for override_redirect */
                   Colormap colormap;       /* color map to be associated with window */
                   Cursor cursor;           /* cursor to be displayed (or None) */
              } XSetWindowAttributes;


              XChangeWindowAttributes(display, w, valuemask, attributes)
                    Display *display;
                    Window w;
                    unsigned long valuemask;
                    XSetWindowAttributes *attributes;


            --------------------------------------------------------------------------------
            XChangeWindowAttributes 設(shè)定視窗的各種屬性, 各種屬性的意義在後面 的小節(jié)會(huì)一一介紹. 'valuemask' 
            是根據(jù)設(shè)定的 attributes 欄位而 定, 把有設(shè)定的欄位的對(duì)應(yīng) mask 做 OR 運(yùn)算. 
            --------------------------------------------------------------------------------

            Display *d;
            Window w;
            XSetWindowAttributes attr;
            unsigned long vmask;

            ...............
            ........

            attr.save_under = True;
            attr.override_redirect = False;
            vmask = CWOverrideRedirect | CWSaveUnder;
            XChangeWindowAttributes(d, w, vmask, &attr);


            --------------------------------------------------------------------------------

            background
            視窗的背景可以涂上單一顏色, 或者是貼上不同的圖案. 
            --------------------------------------------------------------------------------

              XSetWindowBackground(display, w, background_pixel)
                    Display *display;
                    Window w;
                    unsigned long background_pixel;

              XSetWindowBackgroundPixmap(display, w, background_pixmap)
                    Display *display;
                    Window w;
                    Pixmap background_pixmap;


            --------------------------------------------------------------------------------
            XSetWindowBackground 用以設(shè)定背景顏色, 'background_pixel' 則為 背景的顏色. 功能和設(shè)定 
            XSetWindowAttributes 中的 background_pixel 欄位的功能相同. XSetWindowBackgroundPixmap 
            則是設(shè)定背景為一張圖 (pixmap), 相當(dāng)於設(shè)定 background_pixmap 欄位. 
            border
            設(shè)定視窗的外框顏色或圖形. 
            --------------------------------------------------------------------------------

              XSetWindowBorder(display, w, border_pixel)
                    Display *display;
                    Window w;
                    unsigned long border_pixel;

              XSetWindowBorderPixmap(display, w, border_pixmap)
                    Display *display;
                    Window w;
                    Pixmap border_pixmap;


            --------------------------------------------------------------------------------

            bit-gravity
            設(shè)定視窗的 bit-gravity, bit-gravity 控制 InputOutput 視窗 resize 時(shí), 視窗的內(nèi)容如何維持. 
            當(dāng)視窗的大小改變時(shí), 視窗的內(nèi)容不會(huì)改變, 但是會(huì)因?yàn)橐暣按笮〉母淖兌苿?dòng)其在視窗內(nèi)的相對(duì)位置
            (相對(duì)於左上角). 當(dāng)視窗的寬和高改變了 w 和 h, 則任何一點(diǎn)(x,y)的位置會(huì)如下改變: 
            NorthWestGravity (0,0) 
            NorthGravity (w/2,0) 
            NorthEastGravity (w,0) 
            WestGravity (0,h/2) 
            CenterGravity (w/2,h/2) 
            EastGravity (w,h/2) 
            SouthWestGravity (0,h) 
            SouthGravity (w/2,h) 
            SouthEastGravity (w,h) 

            win-gravity
            win-gravity 和 bit-gravity 類(lèi)似, 但控制的對(duì)像是視窗內(nèi)的子視窗的位置. 
            backing-store
            有些 X Server 會(huì)幫視窗儲(chǔ)存其內(nèi)容, 當(dāng)視窗的內(nèi)容 lost 而需要重繪時(shí), Server 會(huì)使用先前儲(chǔ)存的
            內(nèi)容自動(dòng)補(bǔ)回去, 這樣的動(dòng)作稱為 backing store. backing-store 控制這項(xiàng)功能是否作用, 其狀態(tài)可
            為 NotUseful (default), WhenMapped, Always.

            backing-store 為 NotUseful, 則議 X Server 不要進(jìn)行 backing store. 但這只是議, X Server 可能
            還是選擇進(jìn)行 backing store. WhenMapped 則議 X Server 在視窗映射時(shí)(mapped)進(jìn)行 backing store,
             同樣的, 這也只是議, 并不保 X Server 一定會(huì)進(jìn)行, 所以 client 還是得注 意 Expose evnet.Always
              則是議隨時(shí)都進(jìn)行 backing store, 不論是 映射(mapped)或未映射. 
            save-under
            save under 和 backing store 類(lèi)似, 但其處理的對(duì)象是被指定視窗蓋住 的其它視窗內(nèi)容. save-under 
            可為 True 或 False(default), 為 True, X Server 會(huì)自動(dòng)維護(hù)被該視窗蓋到的其它視窗內(nèi)容, 在該部分
            重新 Expose 時(shí), 自動(dòng)回補(bǔ). 
            event-mask
            do-not-propagate-mask
            do-not-propagate-mask 是一個(gè) KeyPress, KeyRelease, ButtonPress, ButtonRelease, PointerMotion, 
            Button1Motion, Button2Motion, Button3Motion, Button4Motion, Buttton5Motion, ButtonMotion 的 
            bitwise inclusive or. 當(dāng)視窗產(chǎn)生或從子視窗 propagate 一個(gè)被 mask 的 event, 該 event 將不會(huì)繼續(xù)
            往 parent propagate. 
            override-redirect
            將使的 parent 上設(shè)定 SubstructureRedirectMask 失效. 
            colormap

            --------------------------------------------------------------------------------

              XSetWindowColormap(display, w, colormap)
                    Display *display;
                    Window w;
                    Colormap colormap;


            --------------------------------------------------------------------------------

            cursor
            cursor 指定標(biāo)進(jìn)入視窗後所使用的指標(biāo), 指標(biāo)可用 XCreatePixmapCursor 建立. 
            --------------------------------------------------------------------------------

              Cursor XCreatePixmapCursor(display, source, mask,
              foreground_color, background_color, x, y)
            Display *display;
            Pixmap source;
            Pixmap mask;
            XColor *foreground_color;
            XColor *background_color;
            unsigned int x, y;


            --------------------------------------------------------------------------------
            XCreatePixmapCursor 可由 pixmap 建立一個(gè)新的標(biāo), source 是標(biāo)的 圖案, mask 則是圖形的 mask, 用以 
            mask 標(biāo)的圖形, 以定義圖形內(nèi)那 一部分屬於標(biāo)圖形(設(shè)為1), 那一部分不屬於(設(shè)為0), 建立不規(guī)則形狀的 
            標(biāo). 
            X Window 程式設(shè)計(jì)入門(mén)--第六章 Inter-Client Communication
            http://cnpa.yzu.edu.tw/~thinker 作者:李圭烽 (Thinker; Thinker.bbs@bbs.yzu.edu.tw) (2001-06-02 18:08:00)
            Index:
            Property & Atom 
               Atom 
               Property 
            Cut Buffer 
            Window Manager 
               WM_NAME 
               WM_ICON_NAME 
               WM_NORMAL_HINTS 
               WM_HINTS 
               WM_CALSS 
            Selection 
               Owner & Requestor 
               例 1 
               傳輸大量資料 - INCR 
               例 2 
               Selection Atom 
               Functions of Selection 
               Client Message 



            Property & Atom



            在 X 的世界中, 每一個(gè)視窗都隨附著一些資料, 稱為 property. 每個(gè) property 都有一個(gè)名稱, 和 type. 每個(gè) property 的 type 指定了資料的資料形態(tài)(type), 如 INTEGER, PIXMAP, CURSOR, ... etc. 而 名稱則為存取 property 的途徑, client 透過(guò)名稱以存取特定視窗 的某個(gè) property. property 可以是由 client 自定, 或由 system 內(nèi)建. X 內(nèi)建了許多 property , 用於視窗管理(window manager 管理). 如: WM_CLASS, WM_NAME, WM_ICON_NAME, ... etc.

            Atom
            因?yàn)樾室蛩氐目剂? 這些 property 的名稱和 type 以 atom 表示. 在 系統(tǒng), 每一個(gè) atom 以一個(gè)整數(shù)(atom ID)表示, 代表著一個(gè)字串. 而且 每一個(gè) atom 都是唯一的, 沒(méi)有任何兩個(gè) atom 擁有相同的 ID. 當(dāng)我對(duì) X Server 發(fā)出 request 而需要這些字串時(shí)為參數(shù)時(shí), 我們就以對(duì)應(yīng)的 atom ID 為參數(shù), 這樣可以降低字串在網(wǎng)路上傳輪的 overhead, 改進(jìn)系統(tǒng)效率. Xlib 提供 一些 function, 讓我們?cè)?nbsp;atom 和字串之間轉(zhuǎn)換. 當(dāng) client 導(dǎo)入一個(gè)新的 字串進(jìn)入系統(tǒng)時(shí), Xlib 也提供 function 以取得一個(gè)唯一,而且不重的 atom ID, 以對(duì)應(yīng)新加入的字串. 因此, 由 client 導(dǎo)入的字串, 在每一次 執(zhí)行時(shí), 不一定會(huì)得到同一個(gè) atom ID. 但, 由系統(tǒng)內(nèi)建的 atom 則有固定 的 ID, 這些 atom 定義在 (XA_prefix 形式, 如 XA_WM_CLASS).這些 atom 可以 hard code 在程式碥, 不需再經(jīng)過(guò) Xlib 所提供的 function 加以轉(zhuǎn)換.

            atom 除了用於 property 名稱和 property type 之外, 還用於 selection , Font property, type of client message 等等.

            下面是 Xlib 提供的 function, XInterAtom 可從 string 轉(zhuǎn)換成 atom ID, XInterAtoms 則一次可以轉(zhuǎn)換多個(gè)字串. XGetAtomNames 則是由 atom 取得字串. 
            --------------------------------------------------------------------------------

              Atom XInternAtom(display, atom_name, only_if_exists)
            Display *display;
            char *atom_name;
            Bool only_if_exists;


            --------------------------------------------------------------------------------
            由 atom_name 指定要轉(zhuǎn)換的字串, XInternAtom 傳回對(duì)應(yīng)的 atom ID. 當(dāng) only_if_exists 為 True, 若字串原本不存在系統(tǒng), 則會(huì)為其分配 一個(gè)不重的 ID. 若 only_if_exists 為 False 時(shí), 只有在 atom 早己 存在時(shí)才會(huì)傳回 atom ID, 否則會(huì)傳回 None.


            --------------------------------------------------------------------------------

              Status XInternAtoms(display, names, count, only_if_exists,
              atoms_return)
            Display *display;
            char **names;
            int count;
            Bool only_if_exists;
            Atom *atoms_return;


            --------------------------------------------------------------------------------
            XInternAtoms 和 XInternAtom 功能相同, 但一次轉(zhuǎn)換多個(gè) atom, 由 names 傳入每個(gè)字串, count 是字串的數(shù)目, 由 atoms_return 傳回 atom ID 陣列. only_if_exists 為 False, 只有己存在的 atom 會(huì) 傳回 atom ID, 不存在的 atom 會(huì)傳回 None. only_if_exists 為 True 時(shí), 則會(huì)為不存在的 atom 配置一個(gè) atom ID. 這個(gè)函數(shù)只有在所有的字串都 傳回 atom ID 時(shí), 才傳回不為 0 的數(shù)字, 否則傳為 0.


            --------------------------------------------------------------------------------

              char *XGetAtomName(display, atom)
            Display *display;
            Atom atom;


            --------------------------------------------------------------------------------
            XGetAtomName 可從 atom ID 取得對(duì)應(yīng)字串.


            --------------------------------------------------------------------------------

              Status XGetAtomNames(display, atoms, count, names_return)
            Display *display;
            Atom *atoms;
            int count;
            char **names_return;


            --------------------------------------------------------------------------------
            和 XGetAtomName 相同, 但可一次轉(zhuǎn)換多個(gè) atom.

            Property

            --------------------------------------------------------------------------------

              int XGetWindowProperty(display, w, property, long_offset,
              long_length, delete, req_type, actual_type_return,
              actual_format_return, nitems_return, bytes_after_return,
              prop_return)
            Display *display;
            Window w;
            Atom property;
            long long_offset, long_length;
            Bool delete;
            Atom req_type;
            Atom *actual_type_return;
            int *actual_format_return;
            unsigned long *nitems_return;
            unsigned long *bytes_after_return;
            unsigned char **prop_return;


            --------------------------------------------------------------------------------
            XGetWindowProperty 為我們傳回 property 的內(nèi)容, client 指定 display, 視窗(w), property, 從資料那個(gè)位置(long_offset)開(kāi)始讀取和 讀取長(zhǎng)度(long_length). delete 為 True or False, 指定是否在讀取之後, 將 property 刪除. long_length 是以 4 bytes 為單位, 也就是你實(shí)際指定 的長(zhǎng)度是 long_length * 4. 另外 req_type 指定 property 資料的 type, 若你不計(jì)較 property 資料的 type, 那麼你可以指定 AnyPropertyType. 而此 function 則傳回資料的實(shí)際 type(actual_type_return), 資料的 format(單位長(zhǎng)度 8, 16, 32;actual_format_return), 傳回多少個(gè)單位 的資料(實(shí)際長(zhǎng)度/format;nitems_return), 結(jié)尾還有多少資料 (bytes_after_return)和 property 內(nèi)容(prop_return).注意: 改變 property 或 delete property 會(huì)產(chǎn)生 PropertyNotify event.

            若我們所要讀取的 property 并不存在, 那麼 XGetWindowProperty 會(huì) 傳回 None 實(shí)際資料 type(actual_type_return). 
            --------------------------------------------------------------------------------

              int XGetWindowProperty(display, w, property, long_offset,
              long_length, delete, req_type, actual_type_return,
              actual_format_return, nitems_return, bytes_after_return,
              prop_return)
            Display *display;
            Window w;
            Atom property;
                    long long_offset, long_length;
                    Bool delete;
                    Atom req_type;
                    Atom *actual_type_return;
                    int *actual_format_return;
                    unsigned long *nitems_return;
                    unsigned long *bytes_after_return;
                    unsigned char **prop_return;


            --------------------------------------------------------------------------------
            XGetWindowProperty 為我們傳回 property 的內(nèi)容, client 指定 display, 視窗(w), property, 從資料那個(gè)位置(long_offset)開(kāi)始讀取和 讀取長(zhǎng)度(long_length). delete 為 True or False, 指定是否在讀取之後, 將 property 刪除. long_length 是以 4 bytes 為單位, 也就是你實(shí)際指定 的長(zhǎng)度是 long_length * 4. 另外 req_type 指定 property 資料的 type, 若你不計(jì)較 property 資料的 type, 那麼你可以指定 AnyPropertyType. 而此 function 則傳回資料的實(shí)際 type(actual_type_return), 資料的 format(單位長(zhǎng)度 8 bits, 16 bits, 32 bits;actual_format_return), 傳回多少個(gè)單位的資料(實(shí)際長(zhǎng)度/format;nitems_return), 結(jié)尾還有多 少資料(bytes_after_return)和 property 內(nèi)容(prop_return).

            因?yàn)?nbsp;X 的網(wǎng)路特性, 讓我們不得注意 byte order 的問(wèn)題. 資料在網(wǎng)路 上傳送, 我們無(wú)法知道在網(wǎng)對(duì)面的接收端電腦的資料表示形式是否和我們 相同. 如一個(gè) 32 bits - 4bytes 的整數(shù), 低位元和高位元的存放次序在 不同的電腦上就不太相同. 也許在 A 機(jī)器的儲(chǔ)放方式是先最低位的 byte 然後次低位,然後次高位,最後最高位. 然 B 機(jī)器卻可能相反. 因此, 每 個(gè) property 都必需指定 format, 以確定資料單位的單位長(zhǎng)度, 這樣 Xlib 才能自動(dòng)進(jìn)行 byte order 的轉(zhuǎn)換, 確保資料的 byte order 不會(huì) 錯(cuò)亂.

            若我們所要讀取的 property 并不存在, 那麼 XGetWindowProperty 會(huì) 傳回 None 實(shí)際資料 type(actual_type_return). actual_format_return 和 bytes_after_return 也皆為 0. nitem_return 則傳回 0(empty).

            若 property 存在, 但是 req_type(request type) 和 property 的實(shí)際 type 不合(不相同), 那麼 XGetWindowProperty 在 actual_type_return 傳回實(shí) 際的 type, 在 actual_format_return 傳回 property 資料的 format, bytes_after_return 則以 byte 為單位, 傳回 property 的實(shí)際長(zhǎng)度. 這時(shí), nitem_return 則為 0, 也就是不傳回任何資料(空的;empty).

            若 property 存在, 且指定 AnyPropertyType 或 property type 和指定 的 type 吻合, 則 XGetWindowProperty prop_return 傳回 property 的內(nèi)容. 
            --------------------------------------------------------------------------------

            N = property 的實(shí)際長(zhǎng)度(以 byte 為單位)
            I = 4 * long_offset
            T = N - T
            L = MINIMUM(T, 4 * long_length)
            A = N - (I + L)


            --------------------------------------------------------------------------------
            prop_return 傳回的資料長(zhǎng)度為 L, 但 XGetWindowProperty 總是會(huì)多配置 一個(gè) byte 的空間, 在這個(gè)多馀的 byte 填上 0, 這樣方便字串的使用, 不需進(jìn)行 null terminate, 增加 copy 的動(dòng)作. bytes_after_return 則 傳回 A, 告知 client 在傳回這些資料後, 還有多少資料在後面. prop_return 的內(nèi)容是從 property 的第 I 個(gè) byte 開(kāi)始, 一直到 (I + L - 1) byte, prop_return 的空間是於 Xlib 自動(dòng)配置, client 程式最後必需透過(guò) XFree() 將之釋放.


            --------------------------------------------------------------------------------

              Atom *XListProperties(display, w, num_prop_return)
            Display *display;
            Window w;
            int *num_prop_return;


            --------------------------------------------------------------------------------
            XListProperties 可傳回隨附在視窗(w)的所有 property 名稱 (名稱字串的 atom). num_prop_return 是實(shí)際 property 的個(gè)數(shù), 名稱 atom 直接從 return value 傳回 atom list. 若視窗(w)沒(méi)有任有 property, 則 function 傳回 null pointer. 傳回的 atom list 最後必需以 XFree() 釋放.


            --------------------------------------------------------------------------------

              XChangeProperty(display, w, property, type, format, mode,
              data, nelements)
            Display *display;
            Window w;
            Atom property, type;
            int format;
            int mode;
            unsigned char *data;
            int nelements;


            --------------------------------------------------------------------------------
            透過(guò) XChangeProperty 可以修改增加 property 的內(nèi)容. property 和 type 分別傳入 property 的名稱 atom 和 type atom, format 可以指定 8, 16, 32. nelements 則是傳入資料的單位個(gè)數(shù), data 則為資料內(nèi)容. mode 則指 定修改方式, PropModeReplace, PropModePrepend, 或 PropModeAppend. 
            PropModeReplace 
            以新的資料完全取代舊內(nèi)容. 
            PropModePrepend 
            新資料插入到舊資料之前 
            PropModeAppend 
            新資料插入到舊資料之後 
            PropModePrepend 和 PropModeAppend mode, 新資料的 type 和 format 必需和舊資料相同.


            --------------------------------------------------------------------------------

              XDeleteProperty(display, w, property)
            Display *display;
            Window w;
            Atom property;


            --------------------------------------------------------------------------------
            刪除 property.

            Cut Buffer
            Cut Buffer 是一種簡(jiǎn)單, 但是功能、效果較不好的 peer-to-peer 訊通架構(gòu). Cut Buffer 是屬於一種被動(dòng)的形式, 資料提供者直接將資料放在 cut buffer。 當(dāng)其它 client 有需要時(shí),直接從 cut buffer 將資取出,資料的要求者和資 料的提供者之間沒(méi)有直接的互動(dòng)。

            Cut buffer 機(jī)制包含 8 個(gè)在 screen 0 的 root window 的 property, 分別以 atoms CUT_BUFFER0 ... CUT_BUFFER7 命名。存在 cut buffer property 的資料,必需 是 STRING type 并且 format 8。資料提供者在儲(chǔ)存資料之前,必需先確定這些 property 是否存在。確定的方式是透過(guò) XChangeProperty() 函數(shù), append 長(zhǎng)度 為 0 的資料至 CUT_BUFFER0 ... CUT_BUFFER7。

            資料提供者在每次儲(chǔ)存資料至 CUT_BUFFER0 ... CUT_BUFFER7 之前,必需先 做 rotate property 的順序。透過(guò) XRotateWindowProperties 函數(shù),將 CUT_BUFFER0 改名為 CUT_BUFFER1, CUT_BUFFER1 改為 CUT_BUFFER2 ...... CUT_BUFFER7 改名為 CUT_BUFFER0。 寫(xiě)入 Cut buffer 的機(jī)制如下: 
            資料提供者確定 CUT_BUFFER0 ... CUT_BUFFER7 存在.(XChangeProperty) 
            Rotate Properties 
            將資料存入 CUT_BUFFER0 

            Client 在讀取資料時(shí),也會(huì)希望輸替讀取 CUT_BUFFER0 ... CUT_BUFFER7 的 內(nèi)容,那麼需要在讀取資料之後,透過(guò) XRotateWindowProperties 函數(shù),將 CUT_BUFFER0 ... CUT_BUFFER7 改名,CUT_BUFFER7 變成 CUT_BUFFER6 ,CUT_BUFFER6 變 CUT_BUFFER5, ......, CUT_BUFFER0 變成 CUT_BUFFER7。 讀取 cut buffer 的機(jī)制如下: 
            讀取 CUT_BUFFER0 
            Rotate Properties 

            Window Manager
            當(dāng) client 執(zhí)行時(shí), 除了要處理視窗的內(nèi)容外, 還需要和 Window Manager 配合, 提供 Window Manager 必要的資訊, 如視窗的名稱(WM_NAME),icon 等等, 讓 Window Manager 進(jìn)行裝飾工作(如顯示 title, 提供視窗的外框). 這 些由 client 提供給 Window Manager 的資訊稱為 hint, 是透過(guò) property 的機(jī)制附屬於 top window.我們可以直設(shè)定 property, 或經(jīng)由 Xlib 提供的 function, 提供 Window Manager Hint

            以 client 的觀點(diǎn)而言, top window 可分為三種狀態(tài) 
            Normal 
            Iconic 
            Withdrawn 
            視窗剛被建立時(shí), top window 初始在 Withdrawn, 此時(shí)視窗尚未 map. 一旦 map 之後, top window 即進(jìn)入 Normal 或 Iconic state. 之後, 因 map 和 unmap 而在 Normal 和 Iconic 之間轉(zhuǎn)換. Normal state 即一般的視窗模式, 相對(duì)於 Iconic state, 視窗只以一個(gè)小 icon 表示.

            WM_NAME
            通常 Window Manager 會(huì)在 Window 的上方放置一個(gè) title bar, 用以 顯示 Window 的名稱. Window Manager 透過(guò) Client 設(shè)定 WM_NAME property, 取得 Client 希望設(shè)定的訊息. WM_NAME 是一個(gè)經(jīng)過(guò)編碼的 字串, 而字串的 encoding 則由 property 的 type 決定. 例如以 STRING 為 property type, 則字串的內(nèi)容為 ISO Latin-1 character 再加上一些控制字元; COMPOUND_TEXT 則為 Compound Text interchange format 字串, 為一種可以包含 Multi-language 的字串格式(此格式內(nèi) 容煩長(zhǎng), 需另寫(xiě)文章介紹). 
            --------------------------------------------------------------------------------

                                                            
              void XSetWMName(display, w, text_prop)
            Display *display;
            Window w;
            XTextProperty *text_prop;

              typedef struct {
                  unsigned char *value;/* property data */
                   Atom encoding;      /* type of property */
                   int format;         /* 8, 16, or 32 */
                   unsigned long nitems;/* number of items in value */
              } XTextProperty;


            --------------------------------------------------------------------------------
            Xlib 提供 XSetWMName 做為方便函數(shù), 但使用起來(lái)似乎沒(méi)有比直接 使用 XChangeProperty 方便到那去. 使用 XChangeProperty 修改 WM_NAME property 時(shí), type 參數(shù)即和 XTextProperty::encoding 相當(dāng), 可以為 STRING, COMPOUND_TEXT 或 C_STRING 等 type.

            WM_ICON_NANE
            WM_ICON_NAME 指定 window 的 icon 名稱. Window Manager 將一個(gè) 視窗變成 icon 形式時(shí), 通常會(huì)在 icon 下方顯示字串, 以提醒使用 者該 icon 和代表的內(nèi)容. 當(dāng) window 進(jìn)入 icon 狀態(tài)時(shí), 由於 icon 的面積往往較小, title bar 上的訊息通常太長(zhǎng), 以致於不適合做為 icon 名稱. 所以 WM_ICON_NAME 需要由 Client 設(shè)定一較精簡(jiǎn)的訊息, 以反應(yīng)其內(nèi)容.

            WM_NORMAL_HINTS
            WM_NORMAL_HINTS property 的 type 為 WM_SIZE_HINTS, 設(shè)定和 window 大小相關(guān)的資料, 如視窗的最大寬度和高度. 當(dāng)使用者欲 改變視窗大小時(shí)(如將視窗拉大), Window Manager 會(huì)參考 WM_NORMAL_HINTS, 以控制 window 的行為.

            WM_NORMAL_HINTS 的內(nèi)容如下: 
            --------------------------------------------------------------------------------
             
            Field Type Comments 

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            flags CARD32 見(jiàn)下表 
            pad 4*CARD32 For backward compatibility 
            min_width INT32 寬度最小值 
            min_height INT32 高度最小值 
            max_width INT32 寬度最大值 
            max_height INT32 高度最大值 
            width_inc INT32 視窗寬度的變化值 
            height_inc INT32 視窗高度的變化值 
            min_aspect (INT32,INT32)  
            max_aspect (INT32,INT32)  
            base_width INT32 初始的寬 
            base_height INT32 初始的高 
            win_gravity INT32 default=NorthWest 

            --------------------------------------------------------------------------------
             
            下面定義 WM_SIZE_HINTS.flags bits: 
            --------------------------------------------------------------------------------
             
            Name Value Field 

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            USPosition 1 User-specified x, y 
            USSize 2 User-specified width, height 
            PPosition 4 Program-specified position 
            PSize 8 Program-specified size 
            PMinSize 16 Program-specified minimum size 
            PMaxSize 32 Program-specified maximum size 
            PResizeInc 64 Program-specified resize increments 
            PAspect 128 Program-specified min and max aspect ratios 
            PBaseSize 256 Program-specified base size 
            PWinGravity 512 Program-specified window gravity 

            --------------------------------------------------------------------------------
             
            WM_SIZE_HINTS.flags 用以告知 Window Manager, Client 設(shè)定 WM_SIZE_HINTS 那些欄位. 但 USPosition 和 USSize 則是例外, 告知 Window Manager 視窗第一次 map 時(shí), 可由使用者指定視窗 位置和大小. PPosition 和 PSize 則是另一個(gè)另外, 告知 Window Manager 視窗第一次 map 時(shí), 位置和大小全由 client 自行控制, 不需經(jīng)過(guò)使用者指定.

            PMinSize 和 PMaxSize 所指定的欄位 min_width, min_height, max_width, max_height 告知 Window Manager, 當(dāng)使用調(diào)整視窗 的大小時(shí), 希望視窗大小不超過(guò)這幾個(gè)極限值.

            PResizeInc 和 PBaseSize 的欄位 width_inc, height_inc, base_width 和 base_height 形成下面兩修公式: 
            width = base_width + (i * width_inc)
            height = base_height + (j * height_inc)

            i 和 j 是大於零的整數(shù). 當(dāng)使用者調(diào)整視窗大小時(shí), client 希望 Window Manager 只讓 user 將視窗調(diào)整為符合上列公式所得的寬和高, 成為 perferred window size. 若 base_width 和 base_height 沒(méi)有指定, 則 Window Manager 以 min_width 和 min_height 做為 base.

            PAspect 和 PBaseSize 的欄位形成下面公式: 
            min_aspect[0] / min_aspect[1] <
            (width - base_width) / (height - base_height) <
            max_aspect[0] / max_aspect[1]

            在每次改變視窗大小時(shí), Window Manager 會(huì)檢查上面的不等式是否成立, width 和 height 為視窗的寬和高. 若 client 沒(méi)有指定 base size, 那麼 width 和 height 就不 需減去 base size, 也就是使用下面的 式子: 
            min_aspect[0] / min_aspect[1] <
            width / height <
            max_aspect[0] / max_aspect[1]

            這些不等式, 更進(jìn)一步限制 preferred window size 的比例.

            PWinGravity 指定 client window 要如何移位(shift), 以維持 window manager frame 和 client window 的位置 關(guān). PWinGravity 可以是 Static, NorthWest, NorthEast, SouthWest, SouthEast, North, South, East, West 和 Center. 若指定 Static, 則 client window 保位置, window manager frame 臨接在 client window 的外緣; window manager frame 的內(nèi)緣和 client window 的 border 位在相同位置. 其它 win_gravity 指定的值, 指定了一個(gè)參考 點(diǎn)(referrence point). North, South, East, West 指定參考點(diǎn)於 於相對(duì)應(yīng)的外圍邊緣(outer border; 視窗的外框線)的中心點(diǎn). NorthWest, NorthEast, SouthWest 和 SouthEast 指定對(duì)應(yīng)的角落為 參考點(diǎn)(referrence point). Center 則指定視窗之中央為 referrence point. 若是指定 Static 以外的 PWinGravity 值, 則 window manager frame 的 referrence point 將會(huì)位於 client window 從 Withdrawn state 變成其它 state 時(shí), client window 的 referrence point 的 位置. 即 client window 的位置會(huì)適當(dāng)?shù)奈灰?shift), 以使的 frame 的 referrence point 能置於原本 client window referrence point 的位置.

            WM_HINTS
            WM_HINTS property 的 type 為 WM_HINTS, 提供 window manager 除了位置大小和名稱以外的資訊, 讓 client 能向 window manager 進(jìn)行一些視窗行為的建議. 
            --------------------------------------------------------------------------------
             
            Field Type Comment 

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            flags CARD32 請(qǐng)見(jiàn)下表 
            input CARD32 The client's input model 
            initial_state CARD32 第一次 map 時(shí)的狀態(tài) 
            icon_pixmap PIXMAP icon 的圖形 
            icon_window WINDOW 顯示 icon 圖形的視窗 
            icon_x INT32 icon 位置的 x 座標(biāo) 
            icon_y INT32 icon 位置的 y 座標(biāo) 
            icon_mask PIXMAP icon 形狀的 mask 
            window_group WINDOW group leader 的 window ID 

            --------------------------------------------------------------------------------
             
            下表定義 WM_HINTS.flags bits: 
            --------------------------------------------------------------------------------
             
            Name Value Field 

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            InputHint 1 input 
            StateHint 2 initial_state, 參考下表 
            IconPixmapHint 4 icon_pixmap 
            IconWindowHint 8 icon_window 
            IconPositionHint 16 icon_x & icon_y 
            IconMaskHint 32 icon_mask 
            WindowGroupHint 64 window_group 
            MessageHint 128 (obsolete) 
            UrgencyHint 256 urgency 

            --------------------------------------------------------------------------------
             
            initial_state: 
            --------------------------------------------------------------------------------
             
            State Value Comment 

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            NormalState 1 視窗內(nèi)容可見(jiàn) 
            IconicState 3 視窗在 icon 狀態(tài) 

            --------------------------------------------------------------------------------
             
            WM_HINTS.flags 指定 client 設(shè)定的 WM_HINTS property 欄 位. 上面第二表定義各欄位的對(duì)應(yīng) flag bit.

            input 欄位的值為 True or False. 當(dāng)使用者點(diǎn)選視窗時(shí), 通常 window manager 會(huì)將 Focus 轉(zhuǎn)移至 user 點(diǎn)選的視窗, 以供使 用者在該視窗進(jìn)行輸入資料的動(dòng)作. input 欄位若為 True, window manager 就會(huì)主動(dòng)將 focus 設(shè)定在 user 指定的 top window. 若 input 欄位為 False, 則 window manager 將不會(huì)設(shè)定 focus 至 該 top window. 因此, 一些 input only 的視窗, 例如小時(shí)鐘之類(lèi)的 程式, 就不需要 focus, 可以將 input 欄位設(shè)為 False. 雖然 window manager 不主動(dòng)轉(zhuǎn)移 focus 至 input 欄位為 False 的 top window, 但是 client 還是可以自行主動(dòng)進(jìn)行 focus 的轉(zhuǎn)移, 取得 focus.

            initial_state 可為 NormalState 或 IconicState. 為 NormalState 時(shí), top window 第一次 map 會(huì)進(jìn)入 normal state. 為 IconicState 時(shí), 則會(huì)進(jìn)入 iconic state.

            icon_pixmap 指定該視窗的 icon 圖形. 關(guān)於 icon pixmap 有幾個(gè)規(guī)定: 
            若有 WM_ICON_SIZE property 存在於 root 視窗, 則 pixmap 必需是 WM_ICON_SIZE 所指的其中一個(gè)大小. 
            pixmap 的 deep 必需為 1 bit. 
            icon_mask 用來(lái)指定 icon 的形狀, 去除不必要的陪份, 讓 icon 不只是 矩形, 也可以是不規(guī)則形.

            也許你希望使用自己指定的視窗做為 icon, 那麼你就必需將 window id 設(shè)定於 icon_window. 如此, client 可以自行控制 icon 行, 做一些不同 的變化.

            flags bit, UrgencyHint 告知 window manager 視窗的內(nèi)容是屬於緊急 性的, 如此 window manager 可以做特別的處理, 以提醒 user. UrgencyHint 狀態(tài)可以隨時(shí)改便, 隨時(shí) set or unset. 當(dāng)一 top window 離開(kāi) Withdrawn state 後, window manager 就必需隨時(shí)注意 UrgencyHint 的變化, 以及時(shí)做出反應(yīng).

            WM_CLASS
            WM_CLASS property 的 type 為 STRING, 包含兩個(gè)連續(xù), null-terminated 的字串, 分別為 application 的 instance name 和 class name. 這兩個(gè) name 用於 window manager 或 client 存取 application 的 resource 時(shí)使用, 做為識(shí)別名稱(identify). 關(guān)於 resource 在往後 的章節(jié)另有說(shuō)明.

            Selection
            在 X 環(huán)境, 兩個(gè) client 之間要如何交換訊息呢? client 之間不能 像一般的程式一樣, 開(kāi)個(gè)共同存取的檔案, 而且 client 可能各自使用 不同的協(xié)定和 X Server 通訊, 因此不能假定能透過(guò)一般的方式和其它 client 溝通. X client 之間主要的通訊方式是透過(guò) selection 機(jī)制. Atom 在這也扮演 selection 的名稱, 做為存取的媒介.

            selection 主要是用於 client 之間傳輸資料, 如: 常用於視窗之間的 copy & paste 動(dòng)作. 我們先在 A 視窗 mark 要 copy 的資料, 然於 再於 B 視窗 paste, 於是 A 視窗成了資料的擁有者, B 視窗成了資 料的要求者. 當(dāng)在 A 視窗完 mark 資料的動(dòng)作之後, A 視 窗取得一個(gè) selection S 的擁有權(quán), 成為 S 的擁有者, 等待資料要求者的要求. 然後我們?cè)?nbsp;B 視窗進(jìn)行 paste 動(dòng)作時(shí), B 視窗就向 S 進(jìn)行要求(SelectionRequest), 這個(gè)對(duì) selection S 的要會(huì)轉(zhuǎn)送到 S 的擁有者 A 視窗. A 視窗 收到要求後就將資料傳送給 B 視窗. 接我們又在 C 視窗進(jìn)行 paste 動(dòng)作, 同樣的 C 視窗也對(duì) S 進(jìn)行要求, 而 A 視窗則繼續(xù)服務(wù) 對(duì) S 提出的要求, 直到其它視窗奪走(取得) S 的擁有權(quán), 或著 A 視 窗自動(dòng)放棄 S 的擁有權(quán).

            Owner & Requestor
            系統(tǒng)內(nèi)可以有多個(gè) selection 存在, 每個(gè) selection 有自已的名稱. 這些 selection 是整個(gè) display 共用的, 除了系統(tǒng)預(yù)定的 selection , client 之也可以定義自己的 selection. 每個(gè) selection 可以有一 個(gè)擁有者(owner)視窗, 但 selection 不一有擁有者. 當(dāng)視窗準(zhǔn)備好 資料, 視窗的擁有者 client 透過(guò) XSetSelectionOwner() 函數(shù)宣告視窗 成為 selection 的新?lián)碛姓? 若 selection 原本就有一個(gè)擁有者, 在改變擁有者時(shí), 原擁有者會(huì)得 SelectionClear event, 得知不再擁有 該 selection.

            Selection 的要求者(requestor)則透過(guò) XConvertSelection() 函數(shù)對(duì) selection 進(jìn) 行要求, 這時(shí)擁有者會(huì)收到 SelectionRequest event. SelectionRequest 包含幾個(gè)參數(shù), selection, target, property, 和 requestor. target 指定要求的資料形態(tài), 例如 INTEGER, PIXMAP, AnyPropertyType. 擁有者 將資料轉(zhuǎn)換成 target 指定的 type, 然後才傳送給 requstor 指定的視窗. 傳送流程 中, 若擁有者有能力提供 target 指定的資料 type, 則擁有者將資料寫(xiě)入 SelectionRequest 指定的 property, 然後擁 有者傳送 SelectionNotify 給 requestor, 告知資料己經(jīng)備妥. 擁有者必需設(shè)定 SelectionNotify 的 selection, target, property 和 time 等參數(shù). 這些參數(shù)必需和 SelectionRequest 得到的對(duì)應(yīng)參 數(shù)相同. 若擁有者無(wú)法提供 target 指定的資料 type, 或者無(wú)法順利寫(xiě)入 property, 則 SelectionNotify 的 property 參數(shù)需設(shè)為 None, 以示無(wú)法提供資料.

            要求者在收到 SelectionNotify 之後, requestor 就從 SelectionNotify 指定的 property(!= None) 讀取資料, 最後將 property delete (透過(guò) XGetWindowProperty, delete=True). property 被 delete 之後, 擁有者會(huì)得到 PropertyNotify, 以得知 requestor 己傳完資料. 擁有者在得知資料 己傳送完畢前, 必需保持資料的完整性, 直到傳送完成之後, 才可以 對(duì)使用者做回饋反應(yīng). 擁有者(owner)為了要在最後能收到 PropertyNotify 必需在傳送 SelectionNotify 之前, 對(duì) requestor 視窗的 PropertyNotify 表示興趣(XSelectInput), 才能正確的收到 event.

            要求者若要求一個(gè)沒(méi)有擁有者(owner)的 selection 時(shí), 這明顯的得不到 任何資料, X Server 會(huì)自動(dòng)產(chǎn)生一個(gè) property=None 的 SelectionNotify. 

            Request selection 的流程: 
            要求者: XConvertSelection() 
            擁有者: 
            收到 SelectionRequest 
            將資料轉(zhuǎn)換成 target 指定的 type 
            然後將資料 replace property 的資料, 傳送 SelectionNotify 要求者. 
            要求者: 
            收到 SelectionNotify 
            讀取 property 并 delete property. 
            要求者完成所有步驟. 
            擁有者: 
            收到 PropertyNotify(state=Deleted). 
            擁有者完成 request 的 service. 
            下面是本章各 event 的結(jié)構(gòu): 
            --------------------------------------------------------------------------------

            typedef struct {
                int type;
                unsigned long serial;   /* # of last request processed by server */ 
                Bool send_event;    /* true if this came from a SendEvent request */
                Display *display;   /* Display the event was read from */
                Window owner;
                Window requestor;
                Atom selection;
                Atom target;  
                Atom property;
                Time time;
            } XSelectionRequestEvent;


            --------------------------------------------------------------------------------


            Structure of SelectionNotify: 
            --------------------------------------------------------------------------------

            typedef struct {
                int type;   
                unsigned long serial;   /* # of last request processed by server */
                Bool send_event;    /* true if this came from a SendEvent request */
                Display *display;   /* Display the event was read from */
                Window requestor;
                Atom selection;  
                Atom target;     
                Atom property;      /* ATOM or None */
                Time time;
            } XSelectionEvent;


            --------------------------------------------------------------------------------



            --------------------------------------------------------------------------------

            typedef struct {
                int type;
                unsigned long serial;   /* # of last request processed by server */
                Bool send_event;    /* true if this came from a SendEvent request */
                Display *display;   /* Display the event was read from */
                Window window;
                Atom selection;
                Time time;
            } XSelectionClearEvent;


            --------------------------------------------------------------------------------


            Structure of PropertyNotify: 
            --------------------------------------------------------------------------------

            typedef struct {
                int type;
                unsigned long serial;   /* # of last request processed by server */
                Bool send_event;    /* true if this came from a SendEvent request */
                Display *display;   /* Display the event was read from */
                Window window;
                Atom atom;
                Time time;
                int state;      /* NewValue, Deleted */
            } XPropertyEvent;


            --------------------------------------------------------------------------------


            例 1
            程式
            signature

            傳輸大量資料 - INCR
            利用 property 做為傳輸媒介時(shí), 由於 property 是屬於系統(tǒng)資源, 當(dāng) 資料量大時(shí), 耗用系統(tǒng)大量的資源, 因此實(shí)在不適合一次塞進(jìn)這麼多資 料, 造成系統(tǒng)資源的使用效率低落. 因此 selection 在 ICCCM 提供 了一個(gè)傳送大量資料時(shí)的成規(guī).

            當(dāng) selection 傳送大量資料的完整流程如下: 
            擁有者傳送 property type 為 INCR 的 SelectionNotify 給擁有 者, type INCR (incrementally) 是一種整數(shù), 記錄整個(gè) selection 的資料大小. 
            要求者收到 SelectionNotify, property 的 type 為 INCR, 這時(shí) 要求者可以從 property 取得整個(gè) selection 的資料量(integer) ; 以byte 為單位計(jì)算. 并 delete property. delete property 會(huì)造生 PropertyNotify(state=Deleted). 
            擁有者收到 PropertyNotify(state=Deleted), 將一小部分還未傳輸 的資料附加(append)到 property. 這個(gè) property 和前面的 SelectionNotify 的 property 相同. 由於 property 改變, 這導(dǎo)致 PropertyNotify(state=NewValue) event. 
            要求者收到 PropertyNotify(state=NewValue) event, 從 property 讀取資料, 并 delete property 產(chǎn)生 PropertyNotify(state= Deleted). 
            goto step 3 until 沒(méi)有未傳資料. 
            擁有者收到 PropertyNotify(state=Deleted)對(duì) property append 長(zhǎng)度 0 的資料. 
            要求者收到 PropertyNotif(state=NewValue), 從 property 讀取 資料長(zhǎng)度 0, 并 delete property 產(chǎn)生 PropertyNotify(state= Deleted). 要求者完成 selection request. 
            擁有者收到 PropertyNotify(state=Deleted), 完成對(duì) selection request 的 service. 
            Selection Atom
            前面說(shuō)過(guò), selection 可以由 client 自行定義, 每一個(gè) selection 都以 atom 命名. X 環(huán)境定義三個(gè) selection atom, 讓各種 client 可以遵循, 讓各種不特定的 client 能夠相互溝通. 
            PRIMARY 
            主要用於當(dāng)作 command 的第一個(gè) selection 參數(shù) 
            SECONDARY 
            當(dāng)作需要兩個(gè) selection 參數(shù)的 command 的第二個(gè)參數(shù), 或其它原因不愿使 用 PRIMARY 時(shí)使用. 
            CLIPBOARD 
            做為一般 copy & paste 動(dòng)作使用. 
            在 ICCCM 說(shuō)道, 習(xí)慣上, 一般的 client 只也支援上面三個(gè) selection, 反過(guò)來(lái)說(shuō), client 至少要能支援上面三個(gè) selection. 否則很難 和其它 client 做 inter-client 的通訊.

            例 2
            程式
            signature

            DELETE INSERT_SELECTION INSERT_PROPERTY 
            Functions of Selection

            --------------------------------------------------------------------------------

              XSetSelectionOwner(display, selection, owner, time)
            Display *display;
            Atom selection;
            Window owner;
            Time time;


            --------------------------------------------------------------------------------

            --------------------------------------------------------------------------------

              Window XGetSelectionOwner(display, selection)
            Display *display;
            Atom selection;


            --------------------------------------------------------------------------------

            --------------------------------------------------------------------------------

              XConvertSelection(display, selection, target, property,
              requestor, time)
            Display *display;
            Atom selection, target;
            Atom property;
            Window requestor;
            Time time;


            --------------------------------------------------------------------------------

            Client Message

            posted on 2007-05-18 15:37 zmj 閱讀(2757) 評(píng)論(0)  編輯 收藏 引用

            美女写真久久影院| 7777精品久久久大香线蕉| 国产精品久久婷婷六月丁香| 亚洲av伊人久久综合密臀性色| 无码AV中文字幕久久专区| 伊人久久免费视频| 久久精品国产乱子伦| 国产精品久久波多野结衣| 久久久久亚洲精品天堂久久久久久| 久久精品国产色蜜蜜麻豆| 久久香蕉一级毛片| 久久青青色综合| Xx性欧美肥妇精品久久久久久| 久久人妻少妇嫩草AV蜜桃| 91精品日韩人妻无码久久不卡| 精品久久亚洲中文无码| 91精品国产综合久久香蕉 | 国产精品亚洲综合久久| 国内精品久久久久伊人av| 日产久久强奸免费的看| 国产精品久久久久久福利漫画| 欧美日韩精品久久免费| 久久精品亚洲男人的天堂| 久久99国产乱子伦精品免费| 伊人久久精品影院| 91久久精品视频| 久久精品国产亚洲AV高清热 | 国产精品欧美久久久天天影视| 久久久久无码精品国产app| 国产精品九九九久久九九| 久久国语露脸国产精品电影| 狠狠色丁香婷婷综合久久来来去| 国内精品久久久久影院优| 久久久精品人妻一区二区三区蜜桃| 9999国产精品欧美久久久久久 | 伊人热热久久原色播放www| 亚洲一区二区三区日本久久九| 男女久久久国产一区二区三区| 久久精品一区二区三区AV| 亚洲午夜福利精品久久| 婷婷久久综合九色综合绿巨人|