最近在研究 X window 下怎麼寫個 composite manager,慢慢的記錄下過程。

雖然用習慣了 vala,但 xlib 的 binding 還很破,所以以下主要還是以 C 配合 xlib + glib (glib 非 X window programming 必要的) 完成。

首先,當然是 include xlib 的 header

include

接著,開啟 display
Display * display = XOpenDisplay(NULL);

參數傳入 NULL 時 XOpenDisplay() 會從環境變數 DISPLAY 取得 display string,例如 ":0" 這樣的玩意。

用完 display 後,關了它
XCloseDisplay(display);

完整程式如下

include

include

int main()
{

Display * display = XOpenDisplay(NULL);

if(! display) {

g_error("No display available");

}

XCloseDisplay(display);

return 0;
}

Buile & run 看看
$ gcc -o ywm-1 ywm-1.c $(pkg-config --cflags --libs x11 glib-2.0)
$ DISPLAY=:1234 ./ywm-1
Failed to open display
$ DISPLAY=:0 ./ymw-1

接下來簡單的介紹一下 X window 下的一些術語

  • X server: 提供顯示功能的程式,也就是會佔用你 video adapter 的程式
  • X client: 使用 X server 進行內容顯示及跟回應使用者操作的程式,例如: firefox
  • Display: 簡單的想做一個 display 就是跟 X server 間的 connection。當然,一個 client 是可以同時間對多個 X server 進行連線的
  • Screen: 一個 X server 可以有 1 到多個 screen。當 xinerama extension 打開時,一個 screen 還有可能由多個 monitor (實際的顯示器) 組成 (mouse cursor 可以在同一個 screen 所屬的 monitor 間自由來去,window 也一樣)
  • Window: 在 X window 下,window 的 parent/child 關係是非常自由的。用過 gtk+ 的朋友可能會想說 child window 是不能成為 top-level window 的。這個限制在 X window 中其實並不存在,也就是說,原本放在 parent window 中的 button,經過 reparent 到 root window 後,其實就變成了 top-level window
  • Window manager: X window 下的 window 其實是没有像 title 及大家常看慣的最小/最大/關閉鈕,如果没有 window manager,那想用 mouse 移動或是改變 window 的大小及位置的功能實現就落在了 application 身上。要 create 一個 window 可用 XCreateWindow()/XCreateSimpleWindow() 完成。不用時,XDestroyWindow()
  • Root window: 一個 screen 有一個 root window,是最上層的 window。Window manager 所管的 window 基本上就是 root window 的 direct child window。
  • Map/unmap: 在 X window 下,window create 後,還不會 show 在畫面上。要經過 XMapWindow() 後才會出現。要讓 window 從畫面上隱藏,可用 XUnmapWindow()
  • Flush: X window 為 client/server 架構,application (client) 要進行顯示動作就要發 command 給 X server。這些 command 通常會先 queue 住,直到 queue 滿了/執行 XFlush, XSync/XNextEvent 等情況,才會一口氣發出去,所以,如果覺得奇怪為什麼 function call 執行了以後没效果,可以 XFlush() 看看

接下來,開個 window 玩玩#include

include

int main()
{

Display * display = XOpenDisplay(NULL);

if(! display) {

g_error("No display available");

}

Window root = XDefaultRootWindow(display);

Window window = XCreateSimpleWindow(display, root, 0, 0, 320, 240, 0, 0, 0xffffff);

XMapWindow(display, window);

XFlush(display);

g_usleep(3 * G_USEC_PER_SEC);

XDestroyWindow(display, window);

XCloseDisplay(display);

return 0;
}
想瞭解細節,請參考http://tronche.com/gui/x/xlib/display/http://tronche.com/gui/x/xlib/window/