• <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 程式設計

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

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



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

            相關 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/)

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

            版權宣告 LICENSE.txt 

            本文為文章著作權宣告

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

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

            Event 和 Request
              當 Client 需 要 在 顯 示 幕 上 開 一 個 window 或 是 顯 示 一 段 文 字 或圖 形 時 , 則 Client ( 即 X 下 的 應 用 程 式 ) 向 Server 提 出 一 個 Request ; Server 收 到 Request 之 後 , 則 依 據 Request 的 內 容 , 提 供 相 對 應 的 服 務 。當 使 用 者 在 屬 於 某 一 Client 的 window 內 , 按 了 一 下 滑 鼠 的 右 鍵 , 或 是 敲 了 鍵 盤 上 的 一 個 Key , 則 Server 會 發 送 一 個 Event 給 該 Client 。 而 Client 只 要 依 據 Server 送 回 來 的 Event, 即可 判 斷 有 何 事 件 發 生 , 然 後 依 據 所 發 生 的 Event 發 生 相 對 應的 動 作 。  

            X Window 的 網 路 特 性 
              Client 和 Server 不 一 定 要 在 同 一 部 電 腦 上 執 行 ; Client 和 Server 可 以 是 接 在 網 路 上 的 兩 臺 電 腦 。 當 Client 要 向 Server 發 出 Request 時 , 可 以 透 過 網 路 向 執 行 Server 的 機 器 發 出 Request , 然 後 送 達 給 Server 處 理 。 同 樣 的 , 當 Server 要 向 Client 通 知 Event 的 發 生 時 , 也 可 以 透 過 網 路 向 Client 傳 送 。 因 此 你 可 以在 A 地 的 電 腦 上 執 行 某 一 X Window 應 用 程 式 , 而 在 B 地 透 過 X Server 觀 察 程 式 執 行 的 結 果 。  

            一 個 X Window 的 程 式 , 也 就 是 Client , 在 同 一 時 間 可 以 和 一 個 以 上 的 Server 溝 通 。 也 可 以 同 時 和 多 個 Server 建 立 連 接 , 在 多個 Server 上 顯 示 , 并 接 受 多 個 Server 的 訊 息 。 而 X Server 也 可 以在 同 時 間 內 , 接 受 多 個 Client 送 來 的 訊 息 , 并 做 對 應 的 處 理。 

            Window 的 階 層 性 
            X Window 內 的 window 是 有 階 層 關  的 , 這 階 層 關  可 以 畫 成 一樹 狀 圖 。 在 樹 狀 的 最 上 層 是 root window , 這 個 window 是 Server 所特 有 的 。 除 了 root window 之 外 , 每 個 window 都 有 一 個 parent window , 即 是 在 樹 狀 圖 上 的 上 一 層 window 。 在 樹 狀 圖 的 下 一 層 window 稱 為 child window 。 每 個 window 可 以有 多 個 child , 但 不 一 定 每 個 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 永 遠 在 parent 上 面 ( 即 parent 被 child 蓋 住 ) 。 而 child window 可 以 比 parent window 大 , 但 超 過 parent 的 部 份 , 會 被 截 掉 而 不 顯 示 在 顯 示 幕 上 。 
             藍 色 部 分 為 parent window , 而 草 綠 色 部 分 則 為 child window 和 parent window 重 疊 的 部 分 。 在 parent window 外 面 灰 色 部 分 也 為 child window 的 一 部 分 , 但 其 為 超 過 parent window 視 窗  圍 之 外 的 部 分 , 所 以 不 會 被 顯 示 出 來 。 草 綠 色 部 分 則 是 顯 示 child window 的 內 容 。  


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

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

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

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

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

            1. 建立一個 display 至 X Server
            在程式開始向 X Server 進行任何的動作之前,程式必需先和 X Server 之間建立一個連線(connection),我們稱之為 display。 XOpenDisplay 即為 Xlib 提供給我建立 display 的函數。 
            --------------------------------------------------------------------------------

            Display *XOpenDisplay(display_name)
            char *display_name;

            display_name 指定要連接之 server。如果 display_name 設定為
            NULL,則內定使用環境變數(environment variable)
            DISPLAY 的內容為連接對像。


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


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

            hostname:number.screen_number

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


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

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

            建立與 cnpa.yzu.edu.tw 上第零個 server 的 display。 
            2. 取得 display 的相關資料
            在我們建立視窗之前,我們必需對目標 display 和螢幕(screen)的屬 性狀況有所了解。 我們可以透過 Xlib 所提供的巨集(macro)和函數 (function)取得指定 display 和螢幕(screen)的資料,利用這些資料 以設定視窗參數,以應不同的螢幕建構合適的視窗。

            建立視窗,我們必需設定多種和目標螢幕(screen)相關的參數。我們就 這些參數設定的需要,介紹如何利用 Xlib 來取得關於 display 的資 料。


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

            DefaultRootWindow(display)

            Window XDefaultRootWindow(display)
            Display *display;

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


            --------------------------------------------------------------------------------
            傳回預定螢幕(default screen)的根(root)視窗。每一個視窗都有父視 窗(parent window),當你要在程式開啟一個最上層的視窗(top window);不是程式其它視窗的子視窗。那麼,由於己沒有其它更上層 的視窗可以當父視窗,所以必需設根視窗(root window)為該視窗的父視窗 (parent window)。我們使用 DefaultRootWindow 取得預定螢幕的根視 窗(root window),可以在建立新視窗時,以任一根視窗(root window) 做為新視窗的父視窗(parent window)。透過指定父視窗(root window) ,我們也指定了負責顯示新視窗的螢幕(screen)。


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

            DefaultDepth(display, screen_number)

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

            display 指定連至 X Server 的連接(connection)。
            screen_number 指定螢幕的編號。


            --------------------------------------------------------------------------------
            傳回指定螢幕根視窗(root window)的預定深度(depth)。每個視窗都有 自己的深度(depth),深度影著該視窗所能顯示的顏色數。當一個視窗 的的深度大,則其同時能顯示的顏色總數也會隨之增加。但,深度( depth)并非無限量的增加,會受限於硬的限制。一般我們會參考根視 窗(root window)的設定。


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

            DefaultScreenOfDisplay(display)

            Screen *XDefaultScreenOfDisplay(display)
            Display *display;

            display 指定一個 X Server 的連結(connection)


            --------------------------------------------------------------------------------
            傳回指向預定螢幕(default screen)的指標。預定螢幕(default screen)即建立 display 時,在 display name 指定的 screen number。


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

            DefaultVisualOfScreen(screen)

            Visual *XDefaultVisualOfScreen(screen)
            Screen *screen;

            screen 指定適當的 Screen 結構。


            --------------------------------------------------------------------------------
            傳回預定螢幕(default screen)的預定視覺(default visual)。在某些 顯示設備上,允許同時以多種不同的方式理顏色的顯示。我們可以任意 的方式,將深度(depth)為 8-bits 的圖素(pixel)對映到顯示的顏色。 也可以將深度(depth)為 24-bits 的圖素(pixel),以紅、黃、藍各為 8-bits 的方式對映到實際的顏色。圖素(pixel)指的是畫面上的一個點 ,這指的是代表該點顏色的一個編號。例如,我們可能以 7 做為RGB 值為 0x9f7071 的顏色的編碼,則任何圖素(pixel)為 7 的點,其顏色 則為 RGB 0x7f7071。

            3. 建立視窗
            我現在開始建立新視窗(window)。視窗(window)建立之後,并不會馬上 在我們指定的顯示器(screen)上顯示出來。我們要經過一道 map 的手 序後,視窗(window)才會正式在顯示器上顯示出來。在我們建立視窗( window)之後,在 map 之前,我們可以對新視窗(window)做一些設定的 動作,以設定視窗(window)的行為特性。

            建立新視窗(window)要透過 Xlib 所提供的 XCreateWindow 函數或者 XCreateSimpleWindow 函數,XCreateSimpleWindow 是 XCreateWindow 的簡化版。這兩個函數可用來建立新的子視窗。 
            --------------------------------------------------------------------------------

            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 的連結。
            parent 指定父視窗(parent window)。
            x, y 指定視窗邊框(border)的左上角相對於父視窗(parent
            window的座標。也就是以父視窗(parent window)內部
            的左上角做為原點所求得的相對座標。此座標用來指
            定視窗的顯示位子。
            width, height 視窗內部尺寸的寬度和高度,高度和寬度并不包括邊框
            (border)的部分。這些尺寸不能為度,否則會造成
            BadValue 的錯誤結果。
            border_width 設定視窗邊框(border)的寬度,其單位為圖素(pixels)
            ,也就是指定其邊框的寬度是幾個圖素(pixels)。
            depth 設定新視窗的顏色深度(depth),若指定 depth 的值為
            CopyFromParent,則深度(depth)將會從父視窗(parent
            window)取得。
            class 指定視窗的類別(class)。你可以指定為 InputOutput
            ,InputOnly 或 CopyFromParent 其中一種。若指定為
            CopyFromParent 則表示將由父視窗(parent window)取
            得。
            visual 設定視覺(visual)的種類。設為 CopyFromParent 則會
            取自父視窗。
            valuemask 用以設定在 attributes 參數設定了那些視窗屬性
            (attribut)的遮罩(mask)。在這個遮罩(mask),每一
            bit 代表著一項屬性(attribut),我們以 OR 位元運算
            ,將代表各項屬性的遮罩(mask)組合起來。若為零,則
            會乎略 attributes 參數。
            attributes 這是一個存放視窗屬性(attribut)的結構(structure)
            ,配合設定正確的遮罩(mask),用以設定視窗的屬性。


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

            /* 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)。但在 程式一開始時,還沒有建立任何的視窗,因此也就無法建立任何視窗的 子視窗。我們使用根視窗(root window)做為父視窗(parent window)建 立其子視窗(child window),以根視窗(root window)的子視窗(child window)做為我們程式最上階層的視窗。

            每個都有各種的屬性,我們設定其屬性即會改變視窗表現出來的行為。 例如,深度(depth),邊框(border)的寬度等等的。Xlib 提供 XChangeWindowAttributes 這個函數,設定任一 window 大部分的 Attributes(屬性)。 
            --------------------------------------------------------------------------------

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

            w 指定設定的 window。
            valuemask 指定在 attributes 這個參數,設定了那些 window
            attributes。這個 mask 也是用 OR 運算,將所有的屬性的 mask
            (遮罩)值組合起來。
            attributes 指定儲存屬性設定值的 XSetWindowAttributes 結構。


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

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



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

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

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


            --------------------------------------------------------------------------------
            此函數用來設定視窗的名稱,這個名稱將會被顯示在該視窗的 title 處。title 就像文章的標題一樣,用來指明此一視窗,讓使用者可以 依據 title 辨別不同的視窗。


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

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

            icon_name 指定 icon 的名稱,此名稱在視窗縮成 icon 時顯示
            出來。


            --------------------------------------------------------------------------------
            XSetIconName 用來設定 icon 的名稱。有時侯,當我們在螢幕上同時 開太多個視窗時,整個畫面可能會顯的很雜亂。因此,我們會借由把一 些暫時用不到的視窗縮小成一小圖示,也就是 icon,以減少所占的空 間,清理一下桌面。等到要用到該視窗時,才將之放大回原來的大小。 而 XSetIconName 所設定的名稱,則會在視窗變成 icon 時顯示出來。 


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

            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 用以設定有關視窗大小的和縮放的限制等等的。 由於 XSizeHints 的內容以後可能會有所增長,所以必需透動態記憶 的配,以避免以後因為改版之後,而造成和新版的 Xlib 不和的 情形。Xlib 提供 XAllocSizeHints 配置一個 XSizeHints 的 structure。所有將由 Xlib 所提供的函數所配的記憶,都要使用 XFree 釋放。

            5. 顯示視窗
            視窗建好之後, 仍然不會出現在螢幕上, 而是要經過一道 mapping 的手序。 視窗都已經設定好了,再來正式顯示在顯示器上就很容易了。這個步驟,mapping ,只要呼叫一個函數就 ok 了!! 
            --------------------------------------------------------------------------------

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

            w 要顯示的視窗。


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

            XFlush(display)
            Display *display;


            --------------------------------------------------------------------------------
            嗯!! 就這麼簡單。但,當你程式執行到這一個步驟時,也許你會發現, 顯示器上跟本就沒有視窗出現。這是因為 Xlib 設有 buffer,將所有 要傳送的訊息都先存在一個 buffer 內,待 buffer 滿了之後才會將之 一起送出,以減少網路的流量,加過程式執行的速度。然而,我們無法 知道什麼時侯才會滿,我們總不能一直等下去,等到程式結束了,也許 畫面都還沒出現。為了解決這個問題,Xlib 提供 XFlush 這個函數, 可以強迫 Xlib 立即將 buffer 內,現有的全部訊息都傳送出去,以讓 X Server 立即可以做處理。

            6. 關閉(destroy)視窗

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

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

            w 要關閉的視窗。


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

            7. 關閉 display

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

            XCloseDisplay(display);
            Display display;


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

            8. 例

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

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

            #include 
            #include 
            #include 
            #include 

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

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

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

            /* 和 Window Manager 進行溝通 */
            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  正式影射到顯示器畫面*/
            printf("Map window\n");
            XMapWindow(display, window);
            getchar(); /* 至此,視窗已執行 Map 的動作了,但
               顯示器上,卻可能看不到。*/

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

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

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

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

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


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

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


            --------------------------------------------------------------------------------
            上面是一個簡單的例程式和 compile 的方法。

            X Window 程式設計入門--第三章 繪圖(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 視窗系統,程式使用顏色都是透過配置 color cell。 color cell 存放著顏色的 RGB 色值,即繪圖時顯示器上所顯示出來 的色值。在我們使用某種顏色之前,必需先配置一個正確的 cell, 使用該 cell 做為繪圖時的參數。當 server 將圖形輸出到顯示器時 ,顯示器(顯示卡)會取出 cell 內所設定之 RGB 值,輸出到畫面。 RGB 即光學三元色紅、綠、藍,經由三元色的比例不同,可以得到不 同的顏色。  


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

            colormap 是 color cell 的集合。每個 client 都可以有自己的 colormap,所以同時可能會有多個 colormap 存在。而系統在同一 時間內,只安裝一個 colormap 到顯示器上(有些硬容許同時安裝多 個 colormap),所以當一個視窗能顯示正確的顏色時,其它視窗的顏色 可能會不正確。這是因為不同的 colormap,其 cell 和 RGB 值的對 應可能不同,所以當 server 把某個視窗的 colormap 安裝到硬體上 時,其它視窗內的 cell 和 RGB 的對映,就變成新被安裝的 colormap 的對映方式,導至不正確的顏色顯示。也就是當 server 把某個視窗 的 colormap 安裝到顯示硬上時,該視窗的顏色顯示就會正確。反 之,則會顯示目前被安裝的 colormap 的對映狀況,顯示不正確的顏 色。為了避免這個問題,一般建議使用預定(default)共用的 colormap ,每個視窗都使用同一個 colormap。default 的 colormap 可由 函數 XDefaultColormap 取得。

            顏色是以 R、G、B 三種元色光的量值來表示,當某元色的量值越大時 ,則顯示出來的顏色就越偏向該元色。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) 表示。

            每個 color cell 在 colormap 上都占有一個位子,為了分別不同的 color cell,我們為每個 color cell 指定一個編號,稱之為 pixel。 所以當我們需要指定一個 cell 時,我是指定其 pixel 值。pixel 是一個 long 整數,每一個 bit 我們稱之為一個 plane。因此,當我 們在 colormap 上分配 x 個 plane 時,我們就是分配 2^x^ 個 cell。

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


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

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

            colormap 指定使用的 colormap。
            screen_in_out 指定和傳回 colormap 內,實際的值。


            --------------------------------------------------------------------------------
            可配置一個 read-only cell。client 指定一個 RGB 值,XAllocColor 分配一個對映到硬體所能提供最接近該 RGB 值的 cell。RGB 值設定在 screen_in_out 的 red、green、blue,而 cell 的 pixel 值會將由 pixel 傳回。硬體實際提供的 RGB 值,則經由 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 一個 Boolean 值,指示配置的 planes 是否必
            需是連續的。
            plane_mask_return
            傳回 plane masks 的 array。
            nplanes 指定在 plane_mask_return 要傳回多少個 plane
            masks。
            pixels_return 傳回 pixel 陣列。
            npixels 指定在 pixels_return 傳回多少個 pixel values。


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


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

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

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


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


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

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

            colormap 指定 colormap。
            color 指定要設定之顏色的結構陣列。
            ncolor 指定 color 陣列中有多少個設定值。


            --------------------------------------------------------------------------------
            XStoreColors 可以同時設定多個 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 指定對映到 cells 的 pixels 值的陣列。
            npixels 指定 pixels 陣列中有多少個 pixel 值。
            planes 指定你要釋放的 planes。


            --------------------------------------------------------------------------------
            當你所配置到的 color cell 不再被需要時,你可以使用 XFreeColors 釋放。XFreeColors 同一時間內可以釋放多個 cell ,pixels 是指定要釋放掉的 cell 的陣列,npixels 則指定 cell 的數目。planes 則是要釋放之 planes 的 plane mask,將要釋放 之所有 plane 的 mask OR 起來所得到的 mask。所釋放的 pixels 為,任一指定之 pixel 和 plane mask 之部分集合做 OR 運算後,所 有可能產生的 pixel 集合。

            使用顏色名稱
            除了使用 RGB 值之外,你可以使用顏色的名稱,并取得適當的 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
            除了使用預定公用的 colormap (從 parent 視窗拷貝而來的) 分配我 們需要的顏色之外,我們也可以為每個個別的視窗建立獨立的 colormap,讓每個視窗能獨力擁有 colormap,或者是由一群視窗來 分享(share)一個 colormap。


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

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

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


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

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

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


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



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

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

            colormap 要釋放之 colormap。


            --------------------------------------------------------------------------------
            釋放一個 colormap,但對於預定之 colormap 沒有作用。如果要 釋放之 colormap 已被使用在某個視窗上時,則 XFreeColormap 會將該視窗之 colormap 設成 None,并對該視窗產生 ColormapNotify event ( event 在後面的章節會談到 )。

            2. Graphics Context
            Graphics Context 簡稱 GC,是存在 server 上的一種資源。GC 是用來 存放繪圖時所需要的各項資訊(例如: 線的寬度和長度,前景和背景顏色 等等),在大部分的繪圖功能中,都需要使用 GC 做為參數。其實,我們 可以把 GC 看做是我們在做畫時的畫筆,不同的畫筆會產生不同的效果 。同樣的,我們也可以使用不同的 GC 內容的變化,來組合達成我們所 需要的畫面效果。同一個 GC 可以在不同的視窗使用,也可以在不同的 client 間使用,但是一般來說 ,并不鼓勵由不同的 client 使用,因為 Xlib 會對 GC 暫存,可能會造 成同步上的問題。GC 是和 screen 結合在一起的,同時也和 depth 有關 ,只有 screen 和 depth 和 GC 和同的視窗,才可以使用該 GC。也就是 該視窗必需和 GC 是在同一個 screen,并且要有相同的 depth。

            Xlib 提供 XGCValues 這個結構, 以存放 GC 的相關資訊。我們將要 設定的值,存於這個結構,同時也經由這個結構傳回 GC 的內存值。 
            --------------------------------------------------------------------------------

            /* 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 的欄位說明。 欄位 預設值 說明 
            function GXcopy Xlib 定義了 16 種 function, 用以定義各種 X 所提供的繪圖形式. Xlib 提供了一些繪圖函數, 當我們在一個 drawable 上繪圖時, 新繪上的 圖該如何和在原本位置上的圖形配合呢? function 定義了 X 所提供的 16 種可能中的一種. 當我們為 GC 設好新的 function 之後, 下一次我們使用 GC 進行繪圖時, 新的 function 就開始發生了作用. 下面是 Xlib 定義的 16 種 function. GXclear 把輸出圖素清除為 0 
            GXand 把輸出之圖與原圖素做 and 運算 
            GXandReverse 先把原圖素反相, 然後和輸出圖素做 and 運算 
            GXcopy 直接用輸出圖素替代原圖素 
            GXandInverted 先將輸出圖素和原圖素做 and 運算後, 再將結果反相 
            GXnoop 維持原圖素 
            GXxor 輸出圖素和原圖素做 xor 運算 
            GXor 輸出圖素和原圖素做 or 運算 
            GXnor 先分別把輸出圖素和原圖素做反相, 再將反相後的兩圖做 and 運算 
            GXequiv 先反相輸出圖素,然後和原圖素做 xor 運算  
            GXinvert 把原圖素反相 
            GXorReverse 反相原圖素, 然後和輸出圖素做 xor 運算 
            GXcopyInverted 把輸出圖素反相當為最後結果 
            GXorInverted 把輸出圖素反相後和原圖素做 or 運算 
            GXnand 把輸出圖素和原圖素做反相, 然後兩圖做 or 運算 
            GXset 把輸出部分全設為 1 
             
            plane_mask AllPlanes 指定會被影的 planes, 會被影的 planes 設為 1。Xlib 中定義 AllPlanes 常數, 指定所有的 planes。繪圖的最後結果是: 
            ((輸出圖素 function 原圖素) AND plane_mask)

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


            你可以透過 XCreateGC 建立一新的 GC: 
            --------------------------------------------------------------------------------

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

            d 指定 drawable。
            valuemask 指定使用了那些 GC 元件。這個參數是把各元件之
            mask OR 起來得到的 mask,用以指定設了那些元
            件。
            value 指定設定的 GC 內容。


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


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

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

            gc 指定要釋放之 GC。


            --------------------------------------------------------------------------------
            釋放一個己建立之 GC。

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


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

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

            gc 指定作用對像之 GC。
            foreground 指定前景顏色。


            --------------------------------------------------------------------------------
            設定 GC 內容的前景。當你使用該 GC 繪圖時,前景顏色即為 GC 內所設的前景顏色。


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

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

            gc 指定作用對像之 GC。
            background 指定背景顏色。


            --------------------------------------------------------------------------------
            設定 GC 的背景顏色。當你使用該 GC 繪圖時,前景顏色即為 GC 內所設的前景顏色。


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

            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 指定作用對像之 GC。
            line_width 線條之寬度。
            line_style 線條型式,有 LineSolid、LineOnOffDash、
            LineDoubleDash。
            cap_style 指定線條端點之型式,有 CapNotLast、
            CapButt、CapRound、CapProjecting。
            join_style 指定線條轉折點的型式,有 JoinMiter、
            JoinRound、JoinBevel。


            --------------------------------------------------------------------------------
            設定線的形式。


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

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

            gc 指定作用對像之 GC。
            font 指定字型。


            --------------------------------------------------------------------------------
            設定字形。


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

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

            gc 指定作用對像之 GC。
            arc_mode 指定畫弧時,封口的型式,有 ArcChord、
            ArcPieSlice。


            --------------------------------------------------------------------------------
            設定畫弧時,封口的型式。 
            3. Graphics
            Xlib 提供大量的函數,處理圖形的輸出。 
            --------------------------------------------------------------------------------

            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 指定畫點的座標。


            --------------------------------------------------------------------------------
            在視窗上畫一點。


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

            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 指定線的兩端點座標。


            --------------------------------------------------------------------------------
            在視窗上畫一條線。


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

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

            x, y 指定矩形的左上角座標。
            width, height 指定矩形的大小。


            --------------------------------------------------------------------------------
            在視窗上畫一個矩形。


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

            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 指定弧的中心點(原點)。
            width, height  指定弧的 x 軸和 y 軸的比例。
            angle1, angle2 弧的起始角度和結止角度。


            --------------------------------------------------------------------------------
            在視窗上畫一個弧形。


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

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


            --------------------------------------------------------------------------------
            在視窗上畫一個填滿顏色的矩形。


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

            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;


            --------------------------------------------------------------------------------
            在視窗上畫一個填滿顏色的弧形。


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

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

            name 指定字形名稱。


            --------------------------------------------------------------------------------
            載入字形,當我要在視窗上顯示某一字形時,我們必需先載入字形, 然後才能使用。使用這個函數之後,會傳回一個 Font 的 ID,這 就是我們在使用 XSetFont 函數設定 GC 所要傳入的參數之一。 當我們使用傳回來的 Font 設定 GC 後,就可以使用該 GC 當做 參數在螢幕上顯示該字形的字串。


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

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

            font 指定要 unload 的字形。


            --------------------------------------------------------------------------------
            移除字形。當我們不再使用一字形時,我們必需將之移除。


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

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

            gc 畫字時所要用的 GC。
            x, y 指定字串顯示的座標。
            string 要顯示的字串。
            length 字串的長度。


            --------------------------------------------------------------------------------
            在螢幕上顯示一字串。


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

            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 指定字串顯示的座標。
            string 指定顯示之字串。
            length 指定字串內有多少個字。


            --------------------------------------------------------------------------------
            在螢幕上顯示一雙位元組(或 16bits)的字串。X Window 有支援雙位元組 字集,用以顯示雙位元組的語言(如中文等)。雙位元組的字元是以 XChar2b 這個 structure 來表示: 
            typedef struct {
            unsigned char byte1;
            unsigned char byte2;
            } XChar2b;

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

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

            /*
             * 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 可以建過 XInitImage 和 XCreateImage 建立. 建立之後的 object, 可以使用 XGetPixel, XPutPixel, XSubImage 和 XAddPixel 讀取和修改內容. 使用 XPutImage 輸出到 drawable (視窗或 pixmap), 使用 XGetImage 從 drawable 讀取. object 最後必需使用 XDestroyImage 釋放.


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

                   Status XInitImage(image)
                         XImage *image;


            --------------------------------------------------------------------------------
            XImage 在使用之前, 必需先經過 XInitImage 進行 initialize. 在呼叫 XInitImage 之前, 除了 manipulate functions 之外, 其它的欄位都必需 先設定好. 成功的話, 傳回非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 會為輸入之影像資料產生一個 XImage 結構, 并傳回結構. 是一個包裝 XInitImage 的函數. 'format' 指定影像儲存的形式, 有 ZPixmap, XYPixmap 和 XYBitmap. ZPixmap 的儲存方式是一個 pixel 接 著一個 pixel 存放. XYPixmap 則是 plane 接著 plane, 將所有 pixel 特定 plane 的內容集成 bitmap, 然後依 plane 的順序儲存各 plane 形式的 bitmap. XYBitmap 和 XYPixmap 一樣, 但是 XYBitmap只有一個 plane. 而, 影像的內容則存在 data 所指定的 memory block . 使用者必需指定一塊記憶(data)以儲存影像, XCreateImage 并不會主動為您配置. data 的大小和 image 的大小和深度(depth)有關, format 也會影響. 下面是 data 大小和 bytes_per_line 的計算公式. 
            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;


            --------------------------------------------------------------------------------
            取得影像內的一個圖點.


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

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


            --------------------------------------------------------------------------------
            在影像上放上一個點.


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

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


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


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

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


            --------------------------------------------------------------------------------
            把 image 內每個點的 pixel 值都加上指定的 valuex.


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

                   XDestroyImage(ximage)
                           XImage *ximage;


            --------------------------------------------------------------------------------
            由上面和下面各函數所產生的 XImage 物件, 最後不用時, 都要使用 XDestroyImage 釋放掉。注意, XDestroyImage 會主動將 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 數目相同.


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

                   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 轉換成 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);
            }


            --------------------------------------------------------------------------------
            執行結果

            顏色和原圖有些不同, 主要原因是使用 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");

            /* 取得預設之 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);

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

            /* 設定和 window manager 進行溝通 */
            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();

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

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

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

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

            /* 關閉視窗 */
            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


            --------------------------------------------------------------------------------
            上面是一個簡單的例程式和 compile 的方法。
            X Window 程式設計入門--第四章 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 應用程式,透過和 X Server 之間的 connection 和 Server 進行通訊。client 應用程式會通過 Xlib,向 X Server 發出 request (要求)。而有時侯,X Server 也會產生 Event (事件), 需要經由 connection 通知 client 程式。這些 Event 可能是因為使用 者按下按鍵或是移動滑鼠,也可能是因為 client 發出的 request 而使 得 X Server 產生的。X Server 可以經由產生 Event,通知 client 所 發生的所有事件。

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

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


            --------------------------------------------------------------------------------
            這個 sturcture 收集各個 Event 相同的部分,包括 type。透過 type ,我可以辨識出各個不同的 Event,以做對應的處理。

            Event 可以 _XEvent 這個 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;


            --------------------------------------------------------------------------------
            根據 type 這個欄位, 我們可以分辨出不同的 Event。依據不同的 Event, 我就可以透過對映該 Event 的欄位, 取得該 Event 的相關 訊息和資料。

            下面是用來標示各種 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 中所該對映的欄位。多個 type 可能對映到同一個欄位。 
            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 中所對映之 structure type。當有兩個以上的 Event type 在 _XEvent 中共用一個 structure type, 則該 structure type 會出現在第四欄。表中的 N.A. 表示該欄位在該列不具任何意義。

            Events Propagation 
            當視窗有事件發生時,對相對應的 Event 卻可能不是由該視窗產生, 由其它的視窗產生。在我們設定視窗屬性時,有一個 do_not_propagate_mask 欄位。do_not_propagate_mask 用來選擇那 些 event 不能往先視窗(ancestor window)傳遞。一般來說 KeyPress KeyRelease ButtonPress ButtonRelease PointerMotion Button1Motion - Button2Motion 這些 event 發生之後,如果在 發生的視窗要求知道這些訊息,則這 evnet 會往父視窗(parent window)傳遞(propagation)。如果父視窗也不要,就會再往父視窗 的父視窗傳遞,一直到遇到其中的一個先視窗(ancester window) 有 client 向 其要求這項 evnet 為止,這時 Event 就會在這個祖先視窗產生。 我們稱這個祖先視窗為 Event Window,而發生 event 的視窗我們 稱之為 Source Window。如果在傳遞 event 的過程中,若有任何 一個傳遞經過的視窗,在該視窗的 do_not_propagate_mask 設定 設 evnet,則傳遞將會停止下來,不再繼續往先視窗傳遞。

            Event Handling
            X Server 會針對各個視窗產生各種的 Event, 但是對於 client 程 式而言, 并不是所有的 Event 都是需要的。而大量的訊息傳送, 會 使的整個系統的效率降低, 所以我們并不希望 X Server 對 client 送出所有的 Evnet。因此在 X 的設計上, X Server 讓 client 可 以選擇每個視窗所需要的 Event, 只傳送需要的 Event 給 client 。在 client 程式端, 由 X Server 送過來的 Event 都會存在 Event Queue 等待程式讀取和處理。程式可以透過 XLib 所提供的 函數, 讀取 Event Queue 內的 Event 并取得關於 Event Queue 的 資訊。當 request 產生時, XLib 并不會馬上將之傳到 X Server。 因為小量而多次的資料傳送, 對於網路的效率是一個很大的傷害。 為了提高傳送的效率, XLib 會將產生的 Request 先暫存在 output buffer, 到達某一程度的量時, 再一口氣將之傳送到 X Server。 然而這個使的 X Server 的反應延遲, 我們可能希望 X Server 立 即做出反應和處理。諸如此類, 我們可以要求 XLib 立即將 output buffer 的 request 全部傳送給 X Server,讓 X Server 可以即 時收到 request 并做出反應。

            設定視窗需要產生那些 Event 的方法有很多種, 我們可以在呼叫 XCreateWindow 和 XChangeWindowAttributes 時, 設定 XSetWindowAttributes 的 event_mask 欄位, 將之作為 XCreateWindow 和 XChangeWindowAttributes 的參數。另外就是透 過 XSelectInput這個函數來選擇。 
            --------------------------------------------------------------------------------

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

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


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

            在選擇好所需要的 Event 之後, 我們就可以開始接受 X Server 送來的 Event。一個 client 程式, 可能同時會使用到多個 視窗, 但所有視窗的 Event 傳送到 client 後, 都會存在 Event Queue。雖然各個視窗的 Event 會因而混在一起, 但是我們可以 透過 XEvent 這個 union type 的 XAnyEvent 結構的 window 欄位區分出該 Event 所屬的視窗。

            透過 XNextEvent, 可以從 Event Queue 取出下一個從 X Server 送來的 Event, 并將之從 Event Queue 移除。 
            --------------------------------------------------------------------------------

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

            event_return 傳回 event queue 的下一個 event


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


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

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

            event_return 傳回 event queue 的下一個 event


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


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

            XFlush(display)
            Display *display;


            --------------------------------------------------------------------------------
            一般程式中并不會使用到這個函數, 因為 XPending, XNextEvent 和 XWindowEvent 會自動 flush output buffer。

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

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

            discard 指示 XSync 是否要放棄現在 Event Queue
            的所有 Event。


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


            當 Event 源源不斷的從 X Server 傳來時, Event Queue 可能 放滿了一些尚未被取出處理的 Event。XEventsQueued 會傳回 Event Queue , 目前所存放的 Event 數量。 
            --------------------------------------------------------------------------------

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

            mode 指定設定模式。你可以指定 QueuedAlready,
            QueuedAfterFlush, 或 QueuedAfterReading。


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

            傳回 Event Queue , 第一個和指定視窗和 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 , 第一個符合指定之 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
            當視窗從未映射(unmapped)的狀態變為映射(mapped)狀態時, 會發生 MapNotify Event,并傳送到需要該 Event 的 client。 而使視窗從未映射的狀態轉變成映射狀態進而使 X Server 產生 MapNotify Event 的原因,可能是因為 client 呼叫 XMapWindow XMapRaised XMapSubwindows 或 XReparentWindow 等 Xlib 函數。 而需要視窗 MapNotify Event 的 client,必需設定 event mask 的 StructureNotifyMask bit 或是 SubstructureNotifyMask, 如此 X Server 才會將產生的 MapNotify Event 傳送給 client。SubstructureNotifyMask 是設在父視窗(parent window) 的,一旦 client 在視窗的 event mask 設定 SubstructureNotifyMask bit,則只要有任何的子視窗(child window) 被映射(mapped),就會產生 MapNotify。下面是 MapNotify Event 的結構: 
            --------------------------------------------------------------------------------

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


            --------------------------------------------------------------------------------
            event 所存的 Window ID 要看 UnmapNotify Event 是因為設定 StructureNotifyMask 或是 SbustructureNotifyMask 而產生。 如果是因為 StructureNotifyMask ,則 event 的內容是變成 未映射(unmapped) 視窗的 Window ID,反之若是因為 SubstructureNotifyMask 而產生的,則 event 欄位被設定為被 變成未映射之視窗的父視窗(parent window) 的 Window ID。 window 則是被映射的視窗的 Window ID。

            UnmapNotify
            這是和 MapNotify 相反的情況。當視窗從映射(mapped)狀態轉變 為未映射(unmapped)狀態時,X Server 會產生 UnmapNotify Evnet ,并傳送給需要該 Evnet 的 client。client 若需要接收 UnmapNotify Event,則必需在 event mask 設定 StructureNotifyMask bit 或 SubstructureNotifyMask bit。SubstructureNotifyMask 是 設在父視窗(parent window),當 client 在視窗的 event mask 設定 SubstructureNotifyMask bit 時,任何的子視窗(child window)變成 未映射(unmapped)時,就會產生 UnmapNotify。這個 event type 的結構(structure) 如下所示: 
            --------------------------------------------------------------------------------

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


            --------------------------------------------------------------------------------
            event 所存的 Window ID 要看 UnmapNotify Event 是因為設定 StructureNotifyMask 或是 SbustructureNotifyMask 而產生。 如果是因為 StructureNotifyMask ,則 event 的內容是變成 未映射(unmapped) 視窗的 Window ID,反之若是因為 SubstructureNotifyMask 而產生的,則 event 欄位被設定為被 變成未映射之視窗的父視窗(parent window) 的 Window ID。 window 則是被映射的視窗的 Window ID。

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

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


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

            ButtonPress
            ButtonRelease
            KeyPress
            KeyRelease
            MotionNotify
            X Window 提供 KeyPress 和 KeyRelease Event。當使用者 按下鍵盤上的按鍵時,X Server 會產生 KeyPress Event 給登記需要按鍵按下去的訊息的 client。當使用者放開按 鍵時,X Server 又會產生 KeyRelease Evnet 給登記需要 KeyRelease Event 這項訊息的 client。X Server 會對鍵盤 上所有的按鍵產生這兩種 Event。ButtonPress 和 ButtonRelease 則是在滑鼠(mouse) 被按下和放開時產生。 client 要接收 KeyPress KeyRelease ButtonPress ButtonRelease 等 Event,需要在 event mask 設定 KeyPressMask KeyReleaseMask ButtonPressMask ButtonReleaseMask 對等的 bit。

            當滑鼠在視窗內移動時,會產生一連串的 MotionNotify Event?;蟛粩嗟囊苿佣?nbsp;MotionNotify 也不斷的產生, 難道你的滑鼠每移動一點 X Server 就產生一個 MotionNotify 嗎? 當然不是這麼張。X Server 并不包證多遠的距離 產生一個 MotionNotify Event,但包證至少在移動的起 始點和終點各會產生一次 MotionNotify Event。 在 event mask 設定 Button1MotionMask - Button5MotionMask,ButtonMotionMask PointerMotionMask 等,可以使 X Server 傳送 MotionNotify Event 給 client。 
            --------------------------------------------------------------------------------

            Button1MotionMask - Button5MotionMask 
            當被指定的滑鼠按鈕(button)被按住且滑鼠一邊在移動時,X Server 會產生 MotionNotify。 
            ButtonMotionMask 
            當任何一個滑鼠按鈕(button)按住且滑鼠一邊移動時,X Server 會產生 MotionNotify。 
            PointerMotionMask 
            不論滑鼠按鈕(button)是否被按下,只要滑鼠移動 X Server 就會產生 MotionNotify。 
            --------------------------------------------------------------------------------
            除了上面幾個之外,還有 PointerMotionHintMask。 PointerMotionMask 是和上面幾個 Mask 合使用的, 當指定任何上面所提的 Mask 後,再加上 PointerMotionHintMask ,X Server 可以只產生一次 MotionNotify 給 client。除此之外,滑鼠按鈕的狀態改變 (按下變放開或反之),滑鼠的標離開視窗,或 client 呼叫 XQueryPointer 或 XGetMotionEvents,X Server 也會產生 MotionNotify Event。這些狀況產生的 MotionNotify 都會設定 Event Structure 的 is_hint 欄位(is_hint memeber)。除了上面的狀況外, X Server 可能依然產生沒有設定 is_hint 欄位的 MotionNotify Event (也就是沒在 event mask 設定 PointerMotionMask 情況下所產生的 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,也就是產生事件的 window。root 是指 source window 所在 screen 之 root window。前面有提及 事件會尋著視窗的階層架構,往祖先視窗(ancester window)傳遞 (propagate)。若 event window 和 source window 是不同個視 窗時(從視窗階層下層傳遞上來),則 subwindow 則是 event window 的 child window,這個 child window 是事件傳遞過程經過的視 窗。若 event window 和 source window 是同一個時(也就是產生 Event 和事件發生是同一個視窗),則 subwindow 設為 None。 x 和 y 則是事件發生時,標相對於 event window 左上角的 座標。x_root 和 y_root 則是標在 root window 上的座標。 state 是事件發生時滑鼠按鈕和鍵盤上修飾鍵的狀態,是由一個 或數個狀態做 OR 運算的組合。這些狀態是 Button1Mask, Button2Mask,Button3Mask,Button4Mask,Button5Mask, ShiftMask,LockMask,ControlMask,Mod1Mask,Mod2Mask, Mod3Mask,Mod4Mask,Mod5Mask。same_screen 是指示 root window 和 event window 是否在同一個 screen,內容是 True or False。 button 是 XButtonPressedEvent 和 XButtonReleasedEvent 事件結構內的欄位,用以紀錄滑鼠按鈕狀態改變。XKeyPressedEvent 和 XKeyReleasedEvent 的 keycode 是任何按鍵的 keycode 即 鍵盤按鍵的代碼(在後面會述及)。XPointerMovedEvent 事件結構 內的 is_hint 在前面有說明,內容是 NotifyNormal 或 NotifyHint。 

            CreateNotify
            CreateNotify 是在視窗建立時產生的事件,client 在視窗的 evnet mask 設定 SubstructureNotifyMask,則任何子視窗(child window)的建立都會產生 CreateNotify。這個事件的結構包含下面 幾個資訊: 
            --------------------------------------------------------------------------------

            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 左上角的座標。width 和 height 則是新視窗的寬度和高度。 override_redirect 則是視窗的 override_redirect 屬性,若 為 True 則 window manager 不會幫這個視窗做處理,乎略這個 視窗。

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

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


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

            ResizeRequest
            如果有任何的 client 試途要改變視窗的大小, 則 X Server 會向其它要求知道這項訊息的 client 傳送 ResizeRequest。 當 client 需要知道這個訊息時,必需在視窗的 event mask 設定 ResizeRedirect,這樣子只要有任何的其它 client 試 圖改變該視窗大小,X Server 就會傳送 ResizeRequest 給 client。這個事件的結構如下: 
            --------------------------------------------------------------------------------

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


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

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

            下面是 FocusIn 和 FocusOut 這兩個 event 的結構: 
            --------------------------------------------------------------------------------

            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)
            {
            /*
             * 畫方框
             */
            XDrawRectangle(display, window, gc, 10, 10, 100, 100);

            /*
             * 畫直線
             */
            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); /* 取得下一個 event */
            if(main_loop(&xe)) /* 處理 event */
            return 0;
            }
            }


            --------------------------------------------------------------------------------
            這個程式和第三章的例程式相似, 但處理了 expose event. 執行之後 會發現處理 expose event 之後, 圖形不會因為被其它視窗蓋掉而無 法恢復了. 

            X Window 程式設計入門--第五章 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 系統的視窗可分為兩類(兩種 Class),InputOnly 和 InputOutput。 InputOnly 的視窗,
            顧名思意就是只能做為 Input 使用,也就是 client 程式只能透過這個視窗來收取 event,但是不
            能在這個視 窗做任何的輸出。而 InputOutput 視窗則不只可以接受輸入而己, 而且也可以使用該
            視窗做輸出。你可以在 InputOutput 視窗上輸出 文字圖形,卻不能在 InputOnly 視窗上這麼做。
            InputOnly 視窗 由於并沒有輸出的能力,所以并不會出現在畫面上。雖然如此,實 際上它還是存在
            的。其主要功能是用來做輸入的控制,例如讓 標進入其區域時,立即變成另一種的形式。這樣的可
            以讓使用者感 覺到標在 parent 視窗的某個區域采用不同的標。既然 InputOnly 沒有輸出的能力,
            所以 InputOnly 視窗也不能做為 drawable 使用。

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

            Xlib 使用 Visual 這個結構存放對映的 visual 資料,而 Visual 實際內容被包裝起來,不讓使用者
            直接接觸。Xlib 提供一些應用的 函數和巨集,讓 programmer 透過這些功能來操作 Visual 結構。 
            下面是所有的 visual 種類及其對 colormap 和 RGB 的影。 
            PseudoColor 
            pixel 值對映到 colormap 而產生 RGB 值,RGB 值可以隨時更改而不 影到已輸出的點。 
            GrayScale 
            和 PseudoColor 差不多,主要的不同在 RGB 值不能更改,否則會影 到已輸出的點的顏色。 
            DirectColor 
            pixel 被分成 R,G,B 三個部分,這三個部分分別對映 colormap 得到 三個值。從 colormap 得到的
            三個值,可以組合成對映的顏色值。 colormap 的 RGB 值可以隨時更換,并且不會因而影項到已輸出 
            的點之顏色。 
            TrueColor 
            和 DirectColor 近似,但是 colormap 內的 RGB 值是內定的,而且不能更改。不同的硬所提供的 
            colormap 不盡相同,但在 RGB 各個原色的 colormap 中,大多會提供線性或接進線性變化的 RGB 值。 
            StaticColor 
            和 PseudoColor 的不同在於其 colormap 的 RGB 值是預定的,無法修改的。 
            StaticGray 
            和 StaticColor 相似,但任何單一點的 RGB 值都一樣,其實就是單色的意思。 
            Depth
            depth 就如先前所說的,用以表示對映顏色的資料長度。以 8bits 的 pixel 值表示對映顏色,則 
            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 會傳回一 Window ID,用以 往後指定視窗,并且產生 
            CreateNotify event。新建立的視窗,會是 parent 參數所指定之視窗的子 視窗(subwindow)。x 和 y 
            則指定視窗左上角相對於 parent 視窗左 上角的座標。width 和 hieght 指定視窗的寬和高。border_width 
            和 depth 分別是視窗邊框的寬度和視窗的 depth,depth 并不需要和 parent 一樣。視窗的 class 為 
            InputOnly ,border_width 和 depth 必需指定為零,否則會產生 BadMatch error。InputOutput 視窗的 
            parent 規定必需也是 InputOutput,否則會產生 BadMatch error,InputOnly 則無這種限 制。visual 
            必需設為硬體有提供的 visual。valuemask 和 attributes 則合力指定視窗的屬性,在後面會談到。

            XCreateSimpleWindow 則是簡易版,用於建立 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;


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

            Destroy
            任何一個視窗被關掉(移除; destroy)都會產生 DestroyNotify event。 parent 視窗被關掉,子視窗也
            會因而被關掉,而且會 parent 視窗關 掉之前先自動關掉子視窗。這時,任何被關掉的視窗,包括子視窗
            和 parent 視窗,都會產生 DestroyNotify event。

            XDestroyWindow 是用以關閉指定之視窗及其子視窗。 
            --------------------------------------------------------------------------------

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


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


            XDestroySubwindows 關閉指定視窗的所有子視窗,但不包括指定 之視窗。 
            --------------------------------------------------------------------------------

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


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

            Map windows/Unmap windows
            Events
            視窗被建立之後,并不會立即出現在螢幕上,在顯示之前還要經過一個 稱為 mapping 的動作。map 一個
            子視窗後,如果其任何一個 ancest 視窗(先視窗)是在 unmapped 狀態(未曾被 map, 或者曾被 map 但又
             被 unmap 了)則子視窗還是不會顯示出來,我們稱之為 unviewable。 子視窗必需等到其所有 ancest 
             視窗都在 mapped 的狀態下時,才會從 unviewable 的狀態進入到 viewable 狀況。視窗只有在 viewable 
             的狀 態下才會被顯示。將視窗 unmap 會使的視窗和其子視窗都隱形起來。任 何一個視窗只要有任何一個
              ancest 視窗被 unmap,都會使該視窗從顯 示器上消失(隱形起來),也就是進入 unviewable 的狀態。

            當視窗被 map 時,X Server 會產生 MapNotify evnet。而 unmap 時,會 產件 UnmapNotify event。當視
            窗由 unviewable 進入 viewable 狀態, 并且沒有全部被其它視窗遮住,則 X Server 會產生 Expose event。
             任何時候,只要視窗的任何一部分從在顯示上看不到 的狀態變成看的到的狀態,就會產生 Expose evnet。

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

            類似於 SubstructureRedirectMask 的情形也發生在 ResizeRedirectMask。如果有 client 對 parent window
             設定 ResizeRedirectMask,則其它 client 對 child window 的 Resize request 同樣也會被轉送給對 
             parent window 設定 ResizeRedirectMask 的 client。如果 child window 的 override-redirect flag 被
             設為 True,同樣的,這種轉送機制 也會失效。

            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 指定的視窗之外,還會使的視窗上到 window stack 的最上面,使的視窗出現在畫面
            的最上面,不會被 其它的視窗擋住。而 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 欄位設定視窗的左上角位置. 
            width,height 
            視窗的寬(width)和高(height) 
            border_width 
            視窗邊框的寬度 
            sibling,stack_mode 
            sibling 和 stack_mode 是相關的, 在 sibling 設定一個 window ID, 此視窗和 欲設定其屬性的視窗
            為兄弟(sibling;同一個 parent window). stack_mode 指定 視窗重疊順序如何調整. 
            我們可以使用 XConfigureWindow 來對視窗設定一些屬性. 
            --------------------------------------------------------------------------------

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


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

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

            #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);
            }


            --------------------------------------------------------------------------------
            上例是改變視窗的位置和大小, 位置在螢幕上 (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, 分別為移動視窗, 
            改變視窗大小, 移動并改變視窗大小, 和設定視窗的外框的 寬度, 是一些簡單方便的函數, 可以簡
            化 XConfigureWindow 的使用. 
            Change the stacking order
            在 X 的 window 常因為相互重疊, 而使的視窗部方的畫面被其它視窗擋 住. 這種視窗重疊的上下次
            序稱為 stack order. 
            --------------------------------------------------------------------------------

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

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


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

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


            --------------------------------------------------------------------------------
            XCirculateSubwindows 改變有子視窗的 stack order, 'direction ' 為 移動的方向, RaiseLowest 把
            所有視窗往上移動一個位子, 最上面的視窗 則回到 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;


            --------------------------------------------------------------------------------
            透過 XRestackWindows 可以直接指定 stack order. windows 傳入 依次序存放的 Window 陣列, 
            nwindows 則是陣列的長度. 
            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 設定視窗的各種屬性, 各種屬性的意義在後面 的小節會一一介紹. 'valuemask' 
            是根據設定的 attributes 欄位而 定, 把有設定的欄位的對應 mask 做 OR 運算. 
            --------------------------------------------------------------------------------

            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 用以設定背景顏色, 'background_pixel' 則為 背景的顏色. 功能和設定 
            XSetWindowAttributes 中的 background_pixel 欄位的功能相同. XSetWindowBackgroundPixmap 
            則是設定背景為一張圖 (pixmap), 相當於設定 background_pixmap 欄位. 
            border
            設定視窗的外框顏色或圖形. 
            --------------------------------------------------------------------------------

              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
            設定視窗的 bit-gravity, bit-gravity 控制 InputOutput 視窗 resize 時, 視窗的內容如何維持. 
            當視窗的大小改變時, 視窗的內容不會改變, 但是會因為視窗大小的改變而移動其在視窗內的相對位置
            (相對於左上角). 當視窗的寬和高改變了 w 和 h, 則任何一點(x,y)的位置會如下改變: 
            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 類似, 但控制的對像是視窗內的子視窗的位置. 
            backing-store
            有些 X Server 會幫視窗儲存其內容, 當視窗的內容 lost 而需要重繪時, Server 會使用先前儲存的
            內容自動補回去, 這樣的動作稱為 backing store. backing-store 控制這項功能是否作用, 其狀態可
            為 NotUseful (default), WhenMapped, Always.

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

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

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


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

            cursor
            cursor 指定標進入視窗後所使用的指標, 指標可用 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 建立一個新的標, source 是標的 圖案, mask 則是圖形的 mask, 用以 
            mask 標的圖形, 以定義圖形內那 一部分屬於標圖形(設為1), 那一部分不屬於(設為0), 建立不規則形狀的 
            標. 
            X Window 程式設計入門--第六章 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 的世界中, 每一個視窗都隨附著一些資料, 稱為 property. 每個 property 都有一個名稱, 和 type. 每個 property 的 type 指定了資料的資料形態(type), 如 INTEGER, PIXMAP, CURSOR, ... etc. 而 名稱則為存取 property 的途徑, client 透過名稱以存取特定視窗 的某個 property. property 可以是由 client 自定, 或由 system 內建. X 內建了許多 property , 用於視窗管理(window manager 管理). 如: WM_CLASS, WM_NAME, WM_ICON_NAME, ... etc.

            Atom
            因為效率因素的考量, 這些 property 的名稱和 type 以 atom 表示. 在 系統, 每一個 atom 以一個整數(atom ID)表示, 代表著一個字串. 而且 每一個 atom 都是唯一的, 沒有任何兩個 atom 擁有相同的 ID. 當我對 X Server 發出 request 而需要這些字串時為參數時, 我們就以對應的 atom ID 為參數, 這樣可以降低字串在網路上傳輪的 overhead, 改進系統效率. Xlib 提供 一些 function, 讓我們在 atom 和字串之間轉換. 當 client 導入一個新的 字串進入系統時, Xlib 也提供 function 以取得一個唯一,而且不重的 atom ID, 以對應新加入的字串. 因此, 由 client 導入的字串, 在每一次 執行時, 不一定會得到同一個 atom ID. 但, 由系統內建的 atom 則有固定 的 ID, 這些 atom 定義在 (XA_prefix 形式, 如 XA_WM_CLASS).這些 atom 可以 hard code 在程式碥, 不需再經過 Xlib 所提供的 function 加以轉換.

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

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

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


            --------------------------------------------------------------------------------
            由 atom_name 指定要轉換的字串, XInternAtom 傳回對應的 atom ID. 當 only_if_exists 為 True, 若字串原本不存在系統, 則會為其分配 一個不重的 ID. 若 only_if_exists 為 False 時, 只有在 atom 早己 存在時才會傳回 atom ID, 否則會傳回 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 功能相同, 但一次轉換多個 atom, 由 names 傳入每個字串, count 是字串的數目, 由 atoms_return 傳回 atom ID 陣列. only_if_exists 為 False, 只有己存在的 atom 會 傳回 atom ID, 不存在的 atom 會傳回 None. only_if_exists 為 True 時, 則會為不存在的 atom 配置一個 atom ID. 這個函數只有在所有的字串都 傳回 atom ID 時, 才傳回不為 0 的數字, 否則傳為 0.


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

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


            --------------------------------------------------------------------------------
            XGetAtomName 可從 atom ID 取得對應字串.


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

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


            --------------------------------------------------------------------------------
            和 XGetAtomName 相同, 但可一次轉換多個 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 的內容, client 指定 display, 視窗(w), property, 從資料那個位置(long_offset)開始讀取和 讀取長度(long_length). delete 為 True or False, 指定是否在讀取之後, 將 property 刪除. long_length 是以 4 bytes 為單位, 也就是你實際指定 的長度是 long_length * 4. 另外 req_type 指定 property 資料的 type, 若你不計較 property 資料的 type, 那麼你可以指定 AnyPropertyType. 而此 function 則傳回資料的實際 type(actual_type_return), 資料的 format(單位長度 8, 16, 32;actual_format_return), 傳回多少個單位 的資料(實際長度/format;nitems_return), 結尾還有多少資料 (bytes_after_return)和 property 內容(prop_return).注意: 改變 property 或 delete property 會產生 PropertyNotify event.

            若我們所要讀取的 property 并不存在, 那麼 XGetWindowProperty 會 傳回 None 實際資料 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 的內容, client 指定 display, 視窗(w), property, 從資料那個位置(long_offset)開始讀取和 讀取長度(long_length). delete 為 True or False, 指定是否在讀取之後, 將 property 刪除. long_length 是以 4 bytes 為單位, 也就是你實際指定 的長度是 long_length * 4. 另外 req_type 指定 property 資料的 type, 若你不計較 property 資料的 type, 那麼你可以指定 AnyPropertyType. 而此 function 則傳回資料的實際 type(actual_type_return), 資料的 format(單位長度 8 bits, 16 bits, 32 bits;actual_format_return), 傳回多少個單位的資料(實際長度/format;nitems_return), 結尾還有多 少資料(bytes_after_return)和 property 內容(prop_return).

            因為 X 的網路特性, 讓我們不得注意 byte order 的問題. 資料在網路 上傳送, 我們無法知道在網對面的接收端電腦的資料表示形式是否和我們 相同. 如一個 32 bits - 4bytes 的整數, 低位元和高位元的存放次序在 不同的電腦上就不太相同. 也許在 A 機器的儲放方式是先最低位的 byte 然後次低位,然後次高位,最後最高位. 然 B 機器卻可能相反. 因此, 每 個 property 都必需指定 format, 以確定資料單位的單位長度, 這樣 Xlib 才能自動進行 byte order 的轉換, 確保資料的 byte order 不會 錯亂.

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

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

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

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


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


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

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


            --------------------------------------------------------------------------------
            XListProperties 可傳回隨附在視窗(w)的所有 property 名稱 (名稱字串的 atom). num_prop_return 是實際 property 的個數, 名稱 atom 直接從 return value 傳回 atom list. 若視窗(w)沒有任有 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;


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


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

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


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

            Cut Buffer
            Cut Buffer 是一種簡單, 但是功能、效果較不好的 peer-to-peer 訊通架構. Cut Buffer 是屬於一種被動的形式, 資料提供者直接將資料放在 cut buffer。 當其它 client 有需要時,直接從 cut buffer 將資取出,資料的要求者和資 料的提供者之間沒有直接的互動。

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

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

            Client 在讀取資料時,也會希望輸替讀取 CUT_BUFFER0 ... CUT_BUFFER7 的 內容,那麼需要在讀取資料之後,透過 XRotateWindowProperties 函數,將 CUT_BUFFER0 ... CUT_BUFFER7 改名,CUT_BUFFER7 變成 CUT_BUFFER6 ,CUT_BUFFER6 變 CUT_BUFFER5, ......, CUT_BUFFER0 變成 CUT_BUFFER7。 讀取 cut buffer 的機制如下: 
            讀取 CUT_BUFFER0 
            Rotate Properties 

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

            以 client 的觀點而言, top window 可分為三種狀態 
            Normal 
            Iconic 
            Withdrawn 
            視窗剛被建立時, top window 初始在 Withdrawn, 此時視窗尚未 map. 一旦 map 之後, top window 即進入 Normal 或 Iconic state. 之後, 因 map 和 unmap 而在 Normal 和 Iconic 之間轉換. Normal state 即一般的視窗模式, 相對於 Iconic state, 視窗只以一個小 icon 表示.

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

                                                            
              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 做為方便函數, 但使用起來似乎沒有比直接 使用 XChangeProperty 方便到那去. 使用 XChangeProperty 修改 WM_NAME property 時, type 參數即和 XTextProperty::encoding 相當, 可以為 STRING, COMPOUND_TEXT 或 C_STRING 等 type.

            WM_ICON_NANE
            WM_ICON_NAME 指定 window 的 icon 名稱. Window Manager 將一個 視窗變成 icon 形式時, 通常會在 icon 下方顯示字串, 以提醒使用 者該 icon 和代表的內容. 當 window 進入 icon 狀態時, 由於 icon 的面積往往較小, title bar 上的訊息通常太長, 以致於不適合做為 icon 名稱. 所以 WM_ICON_NAME 需要由 Client 設定一較精簡的訊息, 以反應其內容.

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

            WM_NORMAL_HINTS 的內容如下: 
            --------------------------------------------------------------------------------
             
            Field Type Comments 

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            flags CARD32 見下表 
            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 設定 WM_SIZE_HINTS 那些欄位. 但 USPosition 和 USSize 則是例外, 告知 Window Manager 視窗第一次 map 時, 可由使用者指定視窗 位置和大小. PPosition 和 PSize 則是另一個另外, 告知 Window Manager 視窗第一次 map 時, 位置和大小全由 client 自行控制, 不需經過使用者指定.

            PMinSize 和 PMaxSize 所指定的欄位 min_width, min_height, max_width, max_height 告知 Window Manager, 當使用調整視窗 的大小時, 希望視窗大小不超過這幾個極限值.

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

            i 和 j 是大於零的整數. 當使用者調整視窗大小時, client 希望 Window Manager 只讓 user 將視窗調整為符合上列公式所得的寬和高, 成為 perferred window size. 若 base_width 和 base_height 沒有指定, 則 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]

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

            這些不等式, 更進一步限制 preferred window size 的比例.

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

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

            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            --------------------------------------------------------------------------------
             
            flags CARD32 請見下表 
            input CARD32 The client's input model 
            initial_state CARD32 第一次 map 時的狀態 
            icon_pixmap PIXMAP icon 的圖形 
            icon_window WINDOW 顯示 icon 圖形的視窗 
            icon_x INT32 icon 位置的 x 座標 
            icon_y INT32 icon 位置的 y 座標 
            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 視窗內容可見 
            IconicState 3 視窗在 icon 狀態 

            --------------------------------------------------------------------------------
             
            WM_HINTS.flags 指定 client 設定的 WM_HINTS property 欄 位. 上面第二表定義各欄位的對應 flag bit.

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

            initial_state 可為 NormalState 或 IconicState. 為 NormalState 時, top window 第一次 map 會進入 normal state. 為 IconicState 時, 則會進入 iconic state.

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

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

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

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

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

            selection 主要是用於 client 之間傳輸資料, 如: 常用於視窗之間的 copy & paste 動作. 我們先在 A 視窗 mark 要 copy 的資料, 然於 再於 B 視窗 paste, 於是 A 視窗成了資料的擁有者, B 視窗成了資 料的要求者. 當在 A 視窗完 mark 資料的動作之後, A 視 窗取得一個 selection S 的擁有權, 成為 S 的擁有者, 等待資料要求者的要求. 然後我們在 B 視窗進行 paste 動作時, B 視窗就向 S 進行要求(SelectionRequest), 這個對 selection S 的要會轉送到 S 的擁有者 A 視窗. A 視窗 收到要求後就將資料傳送給 B 視窗. 接我們又在 C 視窗進行 paste 動作, 同樣的 C 視窗也對 S 進行要求, 而 A 視窗則繼續服務 對 S 提出的要求, 直到其它視窗奪走(取得) S 的擁有權, 或著 A 視 窗自動放棄 S 的擁有權.

            Owner & Requestor
            系統內可以有多個 selection 存在, 每個 selection 有自已的名稱. 這些 selection 是整個 display 共用的, 除了系統預定的 selection , client 之也可以定義自己的 selection. 每個 selection 可以有一 個擁有者(owner)視窗, 但 selection 不一有擁有者. 當視窗準備好 資料, 視窗的擁有者 client 透過 XSetSelectionOwner() 函數宣告視窗 成為 selection 的新擁有者. 若 selection 原本就有一個擁有者, 在改變擁有者時, 原擁有者會得 SelectionClear event, 得知不再擁有 該 selection.

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

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

            要求者若要求一個沒有擁有者(owner)的 selection 時, 這明顯的得不到 任何資料, X Server 會自動產生一個 property=None 的 SelectionNotify. 

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

            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 做為傳輸媒介時, 由於 property 是屬於系統資源, 當 資料量大時, 耗用系統大量的資源, 因此實在不適合一次塞進這麼多資 料, 造成系統資源的使用效率低落. 因此 selection 在 ICCCM 提供 了一個傳送大量資料時的成規.

            當 selection 傳送大量資料的完整流程如下: 
            擁有者傳送 property type 為 INCR 的 SelectionNotify 給擁有 者, type INCR (incrementally) 是一種整數, 記錄整個 selection 的資料大小. 
            要求者收到 SelectionNotify, property 的 type 為 INCR, 這時 要求者可以從 property 取得整個 selection 的資料量(integer) ; 以byte 為單位計算. 并 delete property. delete property 會造生 PropertyNotify(state=Deleted). 
            擁有者收到 PropertyNotify(state=Deleted), 將一小部分還未傳輸 的資料附加(append)到 property. 這個 property 和前面的 SelectionNotify 的 property 相同. 由於 property 改變, 這導致 PropertyNotify(state=NewValue) event. 
            要求者收到 PropertyNotify(state=NewValue) event, 從 property 讀取資料, 并 delete property 產生 PropertyNotify(state= Deleted). 
            goto step 3 until 沒有未傳資料. 
            擁有者收到 PropertyNotify(state=Deleted)對 property append 長度 0 的資料. 
            要求者收到 PropertyNotif(state=NewValue), 從 property 讀取 資料長度 0, 并 delete property 產生 PropertyNotify(state= Deleted). 要求者完成 selection request. 
            擁有者收到 PropertyNotify(state=Deleted), 完成對 selection request 的 service. 
            Selection Atom
            前面說過, selection 可以由 client 自行定義, 每一個 selection 都以 atom 命名. X 環境定義三個 selection atom, 讓各種 client 可以遵循, 讓各種不特定的 client 能夠相互溝通. 
            PRIMARY 
            主要用於當作 command 的第一個 selection 參數 
            SECONDARY 
            當作需要兩個 selection 參數的 command 的第二個參數, 或其它原因不愿使 用 PRIMARY 時使用. 
            CLIPBOARD 
            做為一般 copy & paste 動作使用. 
            在 ICCCM 說道, 習慣上, 一般的 client 只也支援上面三個 selection, 反過來說, client 至少要能支援上面三個 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 閱讀(2764) 評論(0)  編輯 收藏 引用

            亚洲国产成人久久精品动漫| 一本久道久久综合狠狠躁AV| 精品综合久久久久久888蜜芽| 一本色综合网久久| 国产精品久久久久久久久| 久久99精品国产麻豆不卡| 91久久精品无码一区二区毛片| 一级做a爰片久久毛片看看| 少妇久久久久久被弄高潮| 精品久久久久久99人妻| 久久人人青草97香蕉| 日韩精品久久久久久久电影| 久久久久久久女国产乱让韩| 狠狠狠色丁香婷婷综合久久俺| 青草久久久国产线免观| 久久棈精品久久久久久噜噜| 欧美一级久久久久久久大片| 91精品国产乱码久久久久久| 亚洲欧美国产精品专区久久| 国内精品久久久久久久coent| 亚洲va久久久噜噜噜久久狠狠| 久久亚洲国产精品123区| 亚洲国产精品久久久久婷婷软件 | 日韩精品久久久久久久电影蜜臀| 夜夜亚洲天天久久| 久久国产色AV免费观看| 一级做a爰片久久毛片看看| 久久久免费观成人影院| 亚洲综合久久综合激情久久| 久久精品成人免费看| 97精品依人久久久大香线蕉97| 亚洲日韩欧美一区久久久久我| 久久久久久久久久久免费精品| 久久99精品久久久久久齐齐| 亚洲午夜精品久久久久久人妖| 久久精品人人做人人爽97| 狠狠色丁香久久婷婷综合五月 | 婷婷久久综合九色综合98| 久久久国产精品亚洲一区| 性做久久久久久久| 久久久久国产精品熟女影院|