xlib_playground1.html (5181B)
1 +++ 2 date = '2022-12-21T00:00:00+09:00' 3 draft = false 4 title = 'Xlibで遊んでみる1' 5 +++ 6 <time>2022-12-21</time> 7 8 <h2>はじめに</h2> 9 <p>X11でGUIのプログラミングをしてみようと思い、してみた。X11用の低レベルのライブラリはXlibとxcbの二つがあるようだ。x.orgのウェブページを見てみると、Xlibは古く、xcbに置きかわりつつあるという。そのため、新しくなにかを作る場合はxcbを使うようにとのことである。ところがこのxcbはドキュメンテーションに乏しく、X11を触るのが初めての人間にはなにをどうすればいいのかほとんど分からなかった。知らない関数や構造体やらがでてきても(殆ど全部知らないものだが)、その関数なり構造体なりの説明がどこにも見当たらない。manページもない。あるのはdoxygenなるものでソースコードのコメントから自動生成したいい加減なものだけで、使いものにならない。</p> 10 <p>とりあえずX11のことを少しは理解してからでないと初められそうもないと思い、もう少しましな情報があるXlibから始めることにした。</p> 11 <p>言語はC言語である。ソースコードは<a href="https://git.mtkn.jp/xlib_playground">ここ</a>にある。 12 </p> 13 14 <h2>初期設定</h2> 15 <p>ディスプレイを開き、ウィンドウを作成する。変数はとりあえずグローバルに宣言することにした。<code>main</code>関数はできるだけ小さくして実際の処理はそれぞれの関数にさせてみる:</p> 16 <pre><code> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <X11/Xlib.h> 20 21 /* macros */ 22 #define INIT_WIDTH 800 23 #define INIT_HEIGHT 600 24 25 /* variables */ 26 Display *display; 27 Window window; 28 unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT; 29 GC gc; 30 Atom wm_delete_window; 31 32 void 33 setup(void) 34 { 35 // Open a display. 36 if ((display = XOpenDisplay(NULL)) == NULL){ 37 fprintf(stderr, "ERROR: could not open display\n"); 38 exit(1); 39 } 40 // Create a window. 41 window = XCreateSimpleWindow( 42 display, 43 XDefaultRootWindow(display), 44 0, 0, 45 win_width, win_height, 46 0, 0, // border properties 47 0); // background color: black 48 XStoreName(display, window, "UNKO"); 49 50 // Setup a graphical context. 51 gc = XCreateGC(display, window, 0, NULL); 52 XSetForeground(display, gc, 0x0000FF); 53 54 // Kill the application when the window is destroyed. 55 wm_delete_window = XInternAtom(display, 56 "WM_DELETE_WINDOW", False); 57 XSetWMProtocols(display, window, &wm_delete_window, 1); 58 59 // Setup which input to process. 60 XSelectInput(display, window, 61 ExposureMask|KeyPressMask|KeyReleaseMask); 62 63 // Actually draw the window. 64 XMapWindow(display, window); 65 } 66 67 void 68 clean_up(void) 69 { 70 XCloseDisplay(display); 71 } 72 </code></pre> 73 74 <p>適当な四角形のものを表示し、その位置を時間の関数として動かしてみる。</p> 75 <pre><code>#include <time.h> 76 #include <math.h> 77 78 int 79 main(void) 80 { 81 int px, py; 82 int quit; 83 struct timespec ts; 84 XEvent event; 85 86 setup(); 87 quit = 0; 88 89 while (!quit){ 90 while(XPending(display) > 0){ 91 XNextEvent(display, &event); 92 switch (event.type){ 93 case KeyPress: { 94 switch (XLookupKeysym(&event.xkey, 0)){ 95 case 'q': 96 quit = 1; 97 break; 98 default: 99 break; 100 } 101 } break; 102 case ClientMessage: { 103 if ((Atom) event.xclient.data.l[0] == wm_delete_window) { 104 quit = 1; 105 } 106 } break; 107 default: 108 break; 109 } 110 } 111 clock_gettime(CLOCK_MONOTONIC, &ts); 112 px = 200 + (int) (100 * sinf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000)); 113 py = 200 + (int) (100 * cosf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000)); 114 XClearArea(display, window, 115 0, 0, // position 116 win_width, win_height, // width and height 117 False); 118 XFillRectangle(display, window, gc, 119 px, py, // position 120 100, 100); // width and height 121 122 ts.tv_sec = 0; 123 ts.tv_nsec = 10 * 1000 * 1000; 124 nanosleep(&ts, NULL); 125 } 126 127 cleanup(); 128 return 0; 129 } 130 </code></pre> 131 132 <p>ここまでのコードはgitリポジトリの<a href="https://git.mtkn.jp/xlib_playground/file/ex1/ex1.c.html">ex1/ex1.c</a>にある。</p> 133 <h2>完成品:</h2> 134 <video controls> 135 <source src="videos/ex1.webm" type="video/webm"> 136 </video> 137 138 <h2>参考</h2> 139 <ul> 140 <li><a href="https://tronche.com/gui/x/xlib/">The Xlib Manual(html conversion)</a></li> 141 <li><a href="https://www.youtube.com/watch?v=764fnfEb1_c">X11 App in C with Xlib(youtube video by tsoding)</a></li> 142 </ul> 143 144 <a href="xlib_playground2.html">次の記事</a> 145