調べたら普通にドキュメントが出るけどメモ。
まず WebSettings というのを変更して enable-developer-extras というのを有効にしてやって、
WebKitSettings *settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW(web_view)); g_object_set(G_OBJECT(settings), "enable-developer-extras", TRUE, NULL); それから inspector を開くという感じ。
WebKitWebInspector *inspector = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(web_view)); webkit_web_inspector_show(WEBKIT_WEB_INSPECTOR(inspector)); 実行してやるといつも F12 で開いてる感じの画面が別窓で出てくる。
全体像
#include <gtk/gtk.h> #include <webkit2/webkit2.h> static void on_destroy(GtkWidget *widget, GtkWidget *window) { gtk_main_quit(); } static gboolean on_close_web_view(WebKitWebView *web_view, GtkWidget *window) { gtk_widget_destroy(window); return TRUE; } int main(int argc, char **argv) { gtk_init(&argc, &argv); GtkWidget *main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(main_window), 800, 600); gtk_window_set_title(GTK_WINDOW(main_window), "Browse"); WebKitWebView *web_view = WEBKIT_WEB_VIEW(webkit_web_view_new()); gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(web_view)); g_signal_connect(main_window, "destroy", G_CALLBACK(&on_destroy), NULL); g_signal_connect(web_view, "close", G_CALLBACK(&on_close_web_view), main_window); WebKitSettings *settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW(web_view)); g_object_set(G_OBJECT(settings), "enable-developer-extras", TRUE, NULL); webkit_web_view_load_uri(web_view, "https://www.chronoscoper.com/"); WebKitWebInspector *inspector = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(web_view)); webkit_web_inspector_show(WEBKIT_WEB_INSPECTOR(inspector)); gtk_widget_grab_focus(GTK_WIDGET(web_view)); gtk_widget_show_all(main_window); gtk_main(); } このキャプチャはインスペクタを表示して、ソースコード眺めてたら目についた console.screenshot() というのを 呼んでみたところ。
どうでもいいけど WebKit のソースいじったりしていろいろやろうと思っている(思いつき)。
最初の設定は最初しかしない(当たり前)のですぐ忘れる。
これをせずに未署名のアドオンをインストールしようとすると壊れているとか文句を言われる。壊れてねーよ。
Firefox Developer Edition を入れる。Stable とかだと署名していないアドオンをインストールできるようにできない。まあこれは常識。 about:config で xpinstall.signatures.required を false にする。 おしまい。
これで壊れていると言われたら多分本当に壊れている(欠けているファイルがあるとか)。
今日ハマったのとしては,zip にするときに zip extension.zip * ってやったことでサブディレクトリが zip に入ってなかった。 zip extension.zip ** ってやれば解決。
あと applications.gecko が必要なのかよく分かってないけど前うまくいかなかった気がするので追加。
"applications": { "gecko": { "id": "{9e13ea3f-fe6d-4246-88f9-00a9836d9816}" } }, id のところはメールアドレススタイルの id 考えるのがだるいので適当に uuidgen で生成した UUID で埋めればいいっぽい (知らんけど)。
Linux カーネルには Kernel address space layout randomization という仕組みがある(別に Linux カーネルじゃなくてもあると思うが)。 これはカーネルのコードが置かれる仮想アドレスを起動するたびにランダムにするというもので, 悪意のあるソフトウェアのカーネルへの攻撃を難しくしている。ってのはまあどうでもいい話。
で,これ,セキュアになるのはいいんだけどあんなことやこんなことをする時(つまり自分が悪意のある側, とまではいかないが何かの手段としてそれに近いことをしようとした場合)に 面倒臭いことがあって,かといって自分で無効化してコンパイルし直すのもなということでメモ。
nokaslr をカーネルパラメータに追加する1だけ。終了。
一応これをデフォルトにするのは良くない気がするので,起動時に GRUB で変えてやるのがいいと思う。 ↩︎
ふと FizzBuzz を LISP 的に書くとどうなるんだろうと思って調べてみた。 ループで書くのは LISP 的にはダサいはず(適当)なので末尾再帰とかだろうかと 思っていたら,1 から 100 までのリストを作って map していくという感じらしい。 ほんまか?
(letrec ((print-all (lambda (l) (when (pair? l) (print (car l)) (print-all (cdr l)))))) (print-all (map (lambda (n) (cond ((= (remainder n 15) 0) "FizzBuzz") ((= (remainder n 3) 0) "Fizz") ((= (remainder n 5) 0) "Buzz") (else (number->string n)))) (iota 100 1)))) てことで Scheme で書いてみた。一応手元の環境の Gauche 0.9.9 では動いた。
出力する部分のせいでかなりごちゃごちゃになったが,FizzBuzz のリストを作ること自体は 簡単にできる(僕は LISP はまともに書けないのでこのコードは LISP の人から見ると一笑に付す ようなものだろうが)。
しかしなんというかメモリが潤沢な前提の贅沢な考え方だなぁ……。
面倒臭い失敗をしてしまった(戻せるのでセーフ) pic.twitter.com/GSo48SZ9Vw
— kofuk (@man_2_fork) August 17, 2020 覚えていたのでパッと対処できたけど忘れないとも限らないのでメモ。grub じゃない環境での方法は分からない。
再起動する。 GRUB のメニューが表示されたら eを押すと起動のコマンドを編集できる。 linux から始まる行での後ろに init=/bin/bash と書き加える。 Ctrl-x で起動する。 Bash が起動しているので何でもアリの無法地帯。 終わったら exec /sbin/init して起動する。 init を起動せずに Bash から exit すると kernel panic するので注意。
開発者ではなく一ユーザーとして。メジャーリリースでいろいろ変更があるようだ。 NEWS.27 のファイルに変更の長いリストがある(visible changes って書いてあるので 内部的にはもっといろいろ変わっているということだが)。
JSON のパースがネイティブになる LSP が広がったことで JSON をパースすることが多くなり,高速化を図ったのだろう。
設定ファイルをホームディレクトリに直接置く必要がなくなった 今までは設定ファイルは .emacs.d の中に設定ファイルを置いていたが, $XDG_CONFIG_HOME/emacs に置けるようになる。 多分デフォルトの XDG_CONFIG_HOME であれば ~/.config/emacs になると思う。 ホームディレクトリが散らからないので良い(ドットファイルだったのでさほど問題ではなかったが)。
package-initialize する必要がなくなった init.el を読む前にインストールしているパッケージが読まれるようになったらしい。
Qt は全く使ったことがなかったが,ここまでできれば簡単なことはリファレンスだけで できそう。
.ui ファイルでレイアウトを作る方法や QtCreator を使う方法(まあこれも間接的に .ui を使う 方法だといえると思うが)ではなく,とりあえずコードでレイアウト組む方法でやってみた。 ちょっとした GUI を作るのに別ファイルが必要だったりテキストファイルを埋め込んだり (バッファから読ませることができるのかは調べてないので分からない)というのは 面倒臭いと思ったので。
というわけで Hello world。
#include <QApplication> #include <QLabel> int main(int argc, char **argv) { /* Widget を作る前に QApplication を作っておく必要あり */ QApplication app(argc, argv); QLabel l("Hello"); l.setWindowTitle("Hello world!"); l.show(); return app.exec(); } コンパイルは:
$ g++ -fPIC $(pkg-config --cflags --libs Qt5Widgets) foo.cc これで Hello と書かれた Hello world というタイトルのウィンドウが出てくる。 まともにレイアウトを作るならばなんとか Layout とかに addWidget したりしていき, 最後にルートの Widget に setLayout していくことになる。
UNIX のコマンドで(本来の)機能が誤解されがちなコマンドとして cat や touch が有名な 気がするが,env もそのひとつだと思う。env の使われ方としては,単独で実行して設定されている 環境変数を見たり,shebang で bash (やその他 executable)のパスをハードコードするのを避けるために
#!/usr/bin/env bash といった感じで使われるのが多分ほとんどのような気がする。
env の本来(?)の機能は環境変数をいじってからコマンドを実行するといったところだ。 なので Bash から実行するときは env なしで
FOO=bar command といった感じで実行しているのをこういった書き方が使えない環境で実現したいと思ったときに
env FOO=bar command というコマンドで実行すると等価なことができるということだ。
NMake は並列でビルドできないという問題があるので,JOM という NMake のクローンを使う。 これは Qt の開発元が作っているらしい。
ビルドするのは面倒なので適当に公式からバイナリ配布を拾ってくる(ソースコードかと思ってダウンロードしてみたらバイナリだった)。 で,面倒なので PATH を通す。こういう具合でどんどん PATH を通していくと膨大な PATH になってしまう訳ですね。
で,CMake で JOM 用の Makefile を生成する。
$ cmake -G"NMake Makefiles JOM" .. これで
$ jom /J 8 とかすると 8 並列でビルドされる。おしまい。
ちょっと前に .bashrc に追加したやつの紹介。
既に(別の terminal で)動いているプロセスの stdin, stdout, stderr を乗っ取って自分の terminal に 無理矢理つなぐ。
(適当に dotfiles から抜粋)
if [ "$#" -ne 1 ]; then echo 'usage: hijack PID' >&2 return 1 fi local tty="$(readlink /proc/self/fd/0)" echo "Info: Connect to $tty" local run_as_root= if command -v sudo &>/dev/null && [ "_$(whoami)" != '_root' ]; then run_as_root=sudo fi local pid="$1" $run_as_root gdb -p "$pid" <<EOF compile code \ unsigned char attrs[3][1024]; \ for (int fd = 0; fd < 3; ++fd) { \ tcgetattr(fd, (struct termios *)attrs[fd]); \ } \ dup2(open("$tty", 0 /* O_RDONLY */), 0); \ dup2(open("$tty", 1 /* O_WRONLY */), 1); \ dup2(open("$tty", 1 /* O_WRONLY */), 2); \ for (int fd = 0; fd < 3; ++fd) { \ tcsetattr(fd, 0 /* TCSADRAIN */, (struct termios *)attrs[fd]); \ } EOF # If this is TUI app, let it redraw. kill -WINCH "$pid" tail -f /dev/null --pid "$pid" やっていることは基本的に単純で,gdb でプロセスを attach して file descriptor の 0 から 2 までを書き換えています。compile ってのは gdb のコマンドで,渡したコード をコンパイルして,そのプロセスで実行してくれる。このときに #include すると いろいろ問題が起きたりしたので O_RDONLY とか O_RWONLY とかは数字をそのまま書いてある。 あといろんなヘッダファイルに書いてある情報が使えないがために struct termios の 大きさが 1024 byte 以下という仮定をしていたりする。1 KiB 超えの構造体ってなんやねん なので大丈夫やろ。