在 Xlib 中,看 document 都會跟你說這個 function 有錯誤發生時候丟出如 BadAlloc 這樣的 error。但看 function prototype 又不一定有直接的 return value(因為動作的發生是 async 的,所以在 function return 時 error 可能還未發生),那,到底 error 是怎麼去接的?不接又會如何?

原來,在 Xlib 中提供了 XSetErrorHandler() function 可供設定 error callback。如果沒有設定這個 error callback,那 default 的行為是 dump error information 後 exit。
在 X programming 時,常會用到一個技巧,就是做做看,錯誤發生時就要走其他的路子。例如:Window manager 要能正常動作,就要對部份 root window 的 event 進行 redirect 的動作。但這個 redirect 動作同時間只能有一個人做,如果第二個人做了就會發生 BadAccess error。
這時候,如果直接被 exit 可能使用用者經驗就不會那麼好,至少,要有些不那麼技術導向的 information 讓使用者瞭解問題所在。
這時候,就可以設定你的 error callback,來接取收錯誤回報#include
static int x_error_type = Success;
static int on_x_error(Display * display, XErrorEvent * error){ x_error_type = error->type; return 0;}
void trap_x_error(){ XSetErrorHandler(display);}
int untrap_x_error(){ XSetErrorHandler(NULL); int retval = x_error_type; x_error_type = Success; return retval;}
使用方式如下#include #include
Display * display = XOpenDisplay(NULL);Window root = XDefaultRootWindow(display);trap_x_error(display);XSelectInput(display, root, XDK_EVENT_MASK_SUBSTRUCTURE_REDIRECT);if(untrap_x_error()) { fprintf(stderr, "WM already installed"); exit(1);}
這種 pattern 在 gdk, clutter 中很常見。細節請參考:http://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.htmlhttp://developer.gnome.org/gdk/stable/gdk-General.htmlhttp://docs.clutter-project.org/docs/clutter/1.9/clutter-X11-Specific-Support.html