X Window

addon of firefox

firefoxの画面サイズを変更するアドオン。中身を取り出して調べてみる。拡張って所に変なファイル名で入っていた。

sakae@deb:/tmp/extensions$ file \{52c2fc44-27f2-40a0-a8fb-fd01690f81fe\}.xpi
{52c2fc44-27f2-40a0-a8fb-fd01690f81fe}.xpi: Zip archive data, at least v2.0 to extract

変な(オイラーの知らない)拡張子だけど、どうって事なかった。unzipで展開。

sakae@deb:/tmp/extensions$ ls
data/  lib/  manifest.json  META-INF/

manifest.jsonって言うのをまずは見る。

{
  "version": "0.1.3",
  "manifest_version": 2,
  "offline_enabled": true,
  "name": "Window Resizer",
  "short_name": "window-resizer",
  "permissions": ["storage", "system.display"],
  "homepage_url": "https://mybrowseraddon.com/window-resizer.html",
  "description": "Easily set the layout (size & position) of your browser window",
    :

こいつが動くには、保存と、表示の権限が必要とな。設定値をどこかに保存。それを何かのタイミングで反映するんだな。

"layouts": [
  {"id": 1, "width": 800, "height": 1200, "left":0, "top": 0},
  {"id": 2, "width": 800, "height": 1200, "left": 300, "top": 0},
  {"id": 3, "width": 800, "height": 1200, "left": 600, "top": 0},
   :

保存の形式は、あれ(geometory)と同一じゃん。

sakae@deb:/tmp/extensions$ grep system -rIl .
./data/popup/popup.js
./manifest.json

微妙な使われ方をしてる所。

"monitor": function (callback) {
  config.active.window(function (win) {
    var flag = chrome.system && chrome.system.display && chrome.system.display.getInfo;
    if (flag) {
      chrome.system.display.getInfo(function (displays) {
        for (var i = 0; i < displays.length; i++) {
          var monitor = {}, current = {};
          var area = displays[i].workArea;
          /*  */
          current.left = win.left;
          monitor.left = area.left;
          current.right = win.left + win.width;
          monitor.right = area.left + area.width;

ざっと見だけど、このあたりだろうね。

libxcb

前回の続きで、xbacklightする。するってのは、コンパイルの事ね。普通にconfigureしてからmakeすれば良い。X関係者だからと言って特段と違った事をする訳でもない。

vbox$ make
make  all-recursive
Making all in man
  GEN      xbacklight.1
  CC       xbacklight.o
xbacklight.c:48:1: warning: function 'usage' could be declared with attribute
      'noreturn' [-Wmissing-noreturn]
{
^
1 warning generated.
  CCLD     xbacklight

誰だ、こういう風に大事な事を隠す奴は。オイラーは、どんなライブラリィーをリンクしてるか、知りたいぞ。そんなのレシピであるMakefileを見れ。

XRANDR_CFLAGS = -I/usr/X11R6/include
XRANDR_LIBS = -L/usr/X11R6/lib -lxcb-randr -lxcb-util -lxcb

この設定が

vbox$ ldd xbacklight
xbacklight:
        Start    End      Type  Open Ref GrpRef Name
        14b57000 34b59000 exe   1    0   0      xbacklight
        0d91f000 2d921000 rlib  0    1   0      /usr/X11R6/lib/libxcb-randr.so.2.3
        00d75000 20d77000 rlib  0    1   0      /usr/X11R6/lib/libxcb-util.so.0.0
        085c2000 285c4000 rlib  0    3   0      /usr/X11R6/lib/libxcb.so.4.1
        09a8e000 29a9f000 rlib  0    1   0      /usr/lib/libc.so.96.0
        04f16000 24f18000 rlib  0    1   0      /usr/X11R6/lib/libXau.so.10.0
        01d10000 21d12000 rlib  0    1   0      /usr/X11R6/lib/libXdmcp.so.11.0
        0b14e000 0b14e000 ld.so 0    1   0      /usr/libexec/ld.so

こんな風に適用された。指定してない奴もリンクされてるけど、そんなものなのか。

内部で使われている関数のmanが無い。あ、うんの呼吸で使えってか。だから、GUI系は好きになれないのよ。嘆いていてもしょうがないので、関数の仕様書であるヘッダーファイルを閲覧する。

conn = xcb_connect (dpy_name, NULL);

文中に出て来た一番簡単そうな関数。この第二引数は何? xcb.hにあった。

xcb_connection_t *xcb_connect(const char *displayname, int *screenp);

/**
 * @brief Connects to the X server, using an authorization information.
 * @param display The name of the display.
 * @param auth The authorization information.
 * @param screen A pointer to a preferred screen number.
 * @return A newly allocated xcb_connection_t structure.
 *
 * Connects to the X server specified by @p displayname, using the
 * authorization @p auth. If a particular screen on that server is
 * preferred, the int pointed to by @p screenp (if not @c NULL) will
 * be set to that screen; otherwise @p screenp will be set to 0.
 *
 * Always returns a non-NULL pointer to a xcb_connection_t, even on failure.
 * Callers need to use xcb_connection_has_error() to check for failure.
 * When finished, use xcb_disconnect() to close the connection and free
 * the structure.
 */

こうやって、調べて行くの面倒だな。

Basic Graphics Programming With The XCB Library

世の中には、こういう便利な説明書が公開されてた。

xeyes

JR東日本、先月から顔認証で犯罪者や仮釈放者を照合していた なんて話が話題になってた。ギョロ目で挙動不審者を撮影。AIでヤバイ事をやりそうな人を炙り出し。乗客の皆様の安全の為ですとか、言うんだろうね。これが正しいのか否かは、判断に迷う所。

Xな環境でもマウスの位置をギョロ目で追うアプリがある。これもmakeしてみた。

vbox$ make
make  all-recursive
Making all in man
  GEN      xeyes.1
  CC       Eyes.o
  CC       transform.o
  CC       xeyes.o
  CCLD     xeyes

やっぱり大事な所は隠しているね。

XEYES_CFLAGS = -I/usr/X11R6/include
XEYES_LIBS = -L/usr/X11R6/lib -lXext -lXmu -lXt -lX11

リンクしてる物が違っているね。一筋縄ではいきそうに無いですな。まあ、そんなものと諦めるしかないんだろうね。

こいつもmanを見ると

-geometry geometry
        define the initial window geometry; see X(7).

たらい回しだな。

One of the advantages of using window systems instead of hardwired
terminals is that applications don't have to be restricted to a
particular size or location on the screen.  Although the layout of
windows on a display is controlled by the window manager that the user
is running (described below), most X programs accept a command line
argument of the form -geometry WIDTHxHEIGHT+XOFF+YOFF (where WIDTH,
HEIGHT, XOFF, and YOFF are numbers) for specifying a preferred size and
location for this application's main window.

firefoxなんかは、この習慣を無視してる新種のアプリです。アプリの初期配置を指定するんだな。LCD画面が1024x768のサイズなら、左上を原点として、どの位置にどれだけのサイズのアプリ用窓を出すか。これを実際にやるのは、twmとかLXDE等のウィンドウ・マネージャーの仕事か。

と考えると、昔やったお絵描きソフトpostscriptと一緒じゃん。あちらは最終ターゲットが、A4サイズとかの用紙って違いしかない。Xは画面制御の他にマウスやらキーボードなんてのも扱えるとな(フォントを無視するなんてフォントに悲しいと、親父ギャク炸裂)。

あれ、そんなののコンソール版があるぞ。OpenBSD wscons(4)

wscons is made of a number of cooperating modules, in particular

•   Hardware support for display adapters, keyboards and mice; see
    wsdisplay(4), wskbd(4), and wsmouse(4).

•   Input event multiplexor; see wsmux(4).

•   Terminal emulation modules (see below).

話が剃れた。ジオメトリィーに戻ると、

vbox$ grep geometry *.c
Eyes.c:    /* query_geometry            */      XtInheritQueryGeometry,
xeyes.c:            "       [-geometry [{width}][x{height}][{+-}{xoff}[{+-}{yoff}]]]\n"

当たり前の機能なので、X側でサポートするようになってるっぽいな。個別に深入りしても良い事なさそうなので、もっと大局的に調べてみるかな。

X Window

Xプログラミング入門

素晴しい資料に出会えた。これで、何たるかが判るな。

Xlib - C Language X Interface

後はman代わりに参照すれば良いのか。manはもう時代遅れだな。

Xlib sample

そして、サンプルは何時もハロワです。

X Window System編 - ツールキットごとに異なるプログラム

続・X Window System編 - あえてメジャーではないツールキットを使う

色々なツールキットが有るんだな。

下記は、勉強の為の叩き台。

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// Compile:     cc gui.c -lX11
// Window:      ウィンドウへのハンドル(識別子)
// Display:     ディスプレイへのハンドル(識別子)
// GC:  グラッフィクコンテキスト[描画属性]へのハンドル(識別子)
// Xevent:      イベント

void main() {
        Window window;
        Display *display;
        int screen;
        GC gc;
        XEvent event;

        // ディスプレイの指定
        display = XOpenDisplay("");
        screen = DefaultScreen(display);

        // ウィンドウの生成・表示・GC作成、イベント指定
        window = XCreateSimpleWindow (display,
                                RootWindow(display, screen),
                                100, 100,
                                256, 256,
                                4,
                                BlackPixel(display, screen),
                                WhitePixel(display, screen) );
        XMapWindow(display, window);
        gc = XCreateGC(display, window, 0, 0);
        XSelectInput(display, window, ExposureMask | ButtonPressMask);

        // イベント待ち無限ループ
        while(1) {
                XNextEvent(display, &event);
                switch( event.type ) {
                case ButtonPress:
                        printf("button pressed\n");
                        XDrawString(display, window, gc, 100, 100, "Hello World", 11);
                break;
                }
        }
        return;
}

ruby/Tk

ちょいとXlibを扱かうには、ruby/Tkが最適らしい。みんな、あんな古いものを使うなんてと馬鹿にするけど、昭和の香が漂っていて、若い人にも新鮮に映るだろう。

何でも有ると自慢のdebianでも、apt一発でruby/Tkは入らない。パッケージが無いんだ。 そこで、gemの出番になる。

sudo gem install tk で行けるはずなんだけど、自前でインストールしたrubyには、opensslが入っていなくて、gemが起動しなかった。インストール時に警告が出てきてたのは知ってたけど、よもやgemが足を引っ張るなんて、想像もつかなかったよ。

んな訳で、libssl-devを入れてからrubyを作り直した。そして再トライしたら、今度はtcltkのライブラリィーが見付からないとな。ちゃんと、tk-devは入れてるのにね。全く困ったものだとググレですよ。32Bitマシン用に変更して、やっとインストール出来た。

sudo gem install tk -- --with-tcltkversion=8.6 \
  --with-tcl-lib=/usr/lib/i386-linux-gnu \
  --with-tk-lib=/usr/lib/i386-linux-gnu \
  --with-tcl-include=/usr/include/tcl8.6 \
  --with-tk-include=/usr/include/tcl8.6 \
  --enable-pthread

ついでに、FreeBSDにも入れた。こちらは面倒無いように、pkg install rubygem-tk で、一発導入出来た。どうやら、FreeBSDのそれは、何から何まで、rubygem-xxx になってるみたい。irbなんて標準添付かと思ったら、rubygem-irb みたいにする必要があった。パッケージを作る人のポリシーが、色濃く出ているね。

お気楽 Ruby/Tk 超入門

こちらが網羅的に一番詳しく解説されてた。ちょっといじるには最適な取合せと思うぞ。どれぐらい楽かと言うと、

[sakae@fb ~]$ wc tk-clock.rb
     112     392    2241 tk-clock.rb

これ、超入門に載ってた、素敵なアナログ時計です。一方、Xに備付のoclockは

vbox$ wc *.c
     570    1941   16177 Clock.c
     168     563    5207 oclock.c
     104     464    2828 transform.c
     842    2968   24212 total

でした。もう圧倒的に楽ですよ。

xlib in scm

xlibなんて言うGUI系の権家のような本は、残念ながら持っていない。まて、昔のscheme本にxscmの紹介が載っていたような。調べてみたらxscmは既にディスコン。DLしようにも、探し出せなかった。悔しいので、 The SCM Implementation of Schemeな本家へ行ってみた。何とXlibScmをサポートしてるじゃないですか。これはもう試してみるしか。

debianのaptから入れた。一見動きそうだったけどダメだった。 しょうがないので自前でコンパイルして入れたよ。

下記は、サーバーと通信出来るかの試験スクリプト。

(require 'Xlib)
(define d (x:open-display #f))
d
(x:server-vendor d)
(x:protocol-version d)
(x:vendor-release d)
(x:screen-count d)
(x:default-screen d)
(x:close d)

それぞれのS式をC-x C-e で、一つづつ評価してみた。

> ;linking /usr/local/lib/scm/x.so
;done linking /usr/local/lib/scm/x.so
#<unspecified>
> #<unspecified>
> #<X display ":0">
> "The X.Org Foundation"
> (11 . 0)
> 12011000
> 1
> 0
> #<unspecified>

何となく動いてるっぽい。

ports of FreeBSD

気をよくしたオイラーは、FreeBSDではどうよとportsを調べてみた。portsにはなってるけど、残念ながら、X11は無しでコンパイルされてた。

.if ${PORT_OPTIONS:MX11}
SCM_MODULES+=   ${SCM_MODULES_X11}
SCM_DATA+=      ${SCM_DATA_X11}
.endif

scmの作成仕様書Makefileを見ると上記のようになってた。はて、このオプションをどう指定するんだったかな? 昔、こういうのを散々やったんだけど、すっかり忘却の彼方になってる。最近は、努力のうちに入らないググレが幅を効かせているので、

FreeBSD portsの使い方

ああ、思い出したよ。情無い。情無いと言えば、自分用のカーネルを作るのもさぼっているな。ええ、カーネルのアップデートをお任せにするには、標準品が(ほぼ)要求されますからね。

ports of OpenBSD

portslistを入れておくと、portsに対してキーワード検索が出来るようになる。FreeBSDでは入れなくても検索出来るんだけどね。リナで言う、apt-cache search xxx相当かな。

vbox$ cd /usr/ports/
vbox$ make search key=scm | less
 :
Port:   scm-5f1p2
Path:   lang/scm
Info:   scheme r5 interpreter
Maint:  Marc Espie <espie@openbsd.org>
Index:  lang
L-deps:
B-deps: archivers/unzip devel/slib
R-deps: devel/slib
Archs:  any

Port:   scm-5f1p2-no_x11
Path:   lang/scm,no_x11
Info:   scheme r5 interpreter
Maint:  Marc Espie <espie@openbsd.org>
Index:  lang
L-deps:
B-deps: archivers/unzip devel/slib
R-deps: devel/slib
Archs:  any

余計な文字列に対してもヒットするので、lessの検索を使って絞り込のがお得だ。scmはデフォでXサポート済ってのが、メンテナの気持を表しているな。同じ調子で、ruby-tkを検索。2.6, 2.7, 3.0系のruby用が有ったぞ。選び放題だな。

scmを入れたので、上で出て来たチェック・スクリプトを走らせてみた。

> #t
> #<unspecified>
> #<X display "aa.bb.cc.5:0">
> "HC-Consult"
> (11 . 0)
> 12000000
> 1
> 0
> #<unspecified>

Xサーバーは、Windows10に入れているvcXsrvを環境変数DISPLAYで指定した。ベンダー名が、見慣れないものになっている。WSL上にXサーバをインストールしてGUIを実現する(VcXsrv編)

mobaTermは自前のXを持っているので、それでも試してみた。既に設定されてる環境変数は、unset DISPLAYして、削除しておき、movaTermを起動する事。設定されてると、そちらを優先してしまうようだ。

> #t
> #<unspecified>
> #<X display "localhost:10.0">
> "Moba/X"
> (11 . 0)
> 11603000
> 1
> 0
> #<unspecified>

ちゃんと自前のサーバー名を名乗っているね。

最後にX関係のリンク情報をあげておく。

vbox$ ldd /usr/local/bin/scm
/usr/local/bin/scm:
        Start    End      Type  Open Ref GrpRef Name
        15760000 35769000 exe   1    0   0      /usr/local/bin/scm
        02edd000 22ee1000 rlib  0    1   0      /usr/X11R6/lib/libX11.so.17.1
        0422a000 2422f000 rlib  0    1   0      /usr/lib/libreadline.so.4.0
        07b56000 27b5a000 rlib  0    2   0      /usr/lib/libcurses.so.14.0
        06eef000 26ef1000 rlib  0    1   0      /usr/lib/libm.so.10.1
        04d98000 24da9000 rlib  0    1   0      /usr/lib/libc.so.96.0
        0fd22000 2fd24000 rlib  0    1   0      /usr/X11R6/lib/libxcb.so.4.1
        00569000 2056b000 rlib  0    1   0      /usr/X11R6/lib/libXau.so.10.0
        05fe8000 25fea000 rlib  0    1   0      /usr/X11R6/lib/libXdmcp.so.11.0
        07406000 07406000 ld.so 0    1   0      /usr/libexec/ld.so

This year's Index

Home