www.mtkn.jp

Manuscripts for my personal webpage.
git clone https://git.mtkn.jp/www.mtkn.jp
Log | Files | Refs | LICENSE

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 &lt;stdio.h&gt;
     29 #include &lt;stdlib.h&gt;
     30 #include &lt;X11/Xlib.h&gt;
     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 &lt;time.h&gt;
     88 #include &lt;math.h&gt;
     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) &gt; 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>