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