Gedit を F11 でフルスクリーンにする。
その状態でマウスカーソルを上部に持って行くとフルスクリーンコントローラがスルスルと降りてくる。
これをどうやって実現しているのか今まで謎だった。
Clutter や非推奨の GtkFixed を使えば実は簡単なんだけど。
実際 0.1 や拙作 Clutter 動画プレイヤーのシークバーでやっているし。
Cocoa は GtkFixed みたいな古臭い API という事実は置いておいて。
GTK+ は基本的に Widget を配置すると引き伸ばしされる。
加えて GtkBin のサブクラスには Widget を一つしか配置できない。
つまり Widget 同士を重ねて配置することは不可能。
しかし Gedit 等は実現している、手段を調べてみよう。
実は Widget の引き伸ばしは単なるデフォルト動作だった。
知らなかったよマジで。
valign, halign プロパティのデフォルトが GTK_ALIGN_FILL なのだ。
つまり。
#!/usr/bin/gjs
const System = imports.system;
const GObject = imports.gi.GObject;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
var FlWindow = GObject.registerClass({
GTypeName: "FlWindow"
}, class FlWindow extends Gtk.ApplicationWindow {
_init(app) {
super._init({application: app});
//
let entry = new Gtk.Entry({
text: "this is a Entry",
valign: Gtk.Align.END
});
this.add(entry);
//
this.show_all();
}
});
var FlApplication = GObject.registerClass({
GTypeName: "FlApplication"
}, class FlApplication extends Gtk.Application {
_init(v) {
GLib.set_prgname("MyProgram");
super._init({
application_id: "palepoli.skr.jp",
flags: Gio.ApplicationFlags.HANDLES_OPEN
});
}
vfunc_startup() {
super.vfunc_startup();
new FlWindow(this);
}
vfunc_open(files, hint) {
this.active_window.present();
}
vfunc_activate() {
this.active_window.present();
}
});
new FlApplication().run([System.programInvocationName].concat(ARGV));
で。
と valign, halign プロパティで Widget を上下左右に貼り付けることができる。
ウインドウをリサイズすると追従することが確認できる。
次は Widget 同士を重ねる方法。
なんてことはない、GtkOverlay というズバリな Widget があった。
#!/usr/bin/gjs
const System = imports.system;
const GObject = imports.gi.GObject;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
var FlWindow = GObject.registerClass({
GTypeName: "FlWindow"
}, class FlWindow extends Gtk.ApplicationWindow {
_init(app) {
super._init({application: app});
// Widgets
this.entry = new Gtk.Entry({
no_show_all: true,
text: "this is a Entry",
valign: Gtk.Align.START
});
let view = new Gtk.TextView();
view.buffer.set_text("1\n2\n3\n4\n5", -1);
// Overlay
let ol = new Gtk.Overlay();
ol.add(view);
ol.add_overlay(this.entry);
this.add(ol);
// Signal
this.connect("motion-notify-event", (widget, event)=> {
let [b, x, y] = event.get_coords();
this.entry.visible = y < 50;
});
this.show_all();
}
});
var FlApplication = GObject.registerClass({
GTypeName: "FlApplication"
}, class FlApplication extends Gtk.Application {
_init(v) {
GLib.set_prgname("MyProgram");
super._init({
application_id: "palepoli.skr.jp",
flags: Gio.ApplicationFlags.HANDLES_OPEN
});
}
vfunc_startup() {
super.vfunc_startup();
new FlWindow(this);
}
vfunc_open(files, hint) {
this.active_window.present();
}
vfunc_activate() {
this.active_window.present();
}
});
new FlApplication().run([System.programInvocationName].concat(ARGV));
結果。
クライアント領域上部にマウスカーソルを持って行くと Widget が重なって出て来る。
こんな感じでフルスクリーン時のみ Widget を重ねて上部に出してやればオケ。
後は Gedit のようにアニメーションで出す方法だけど。
ソースを見ると GtkRevealer を使っているので同じ配置をしてみたんだけど。
GTK_REVEALER_TRANSITION_TYPE_CROSSFADE 以外動かない、何故だ?
おまけに motion-notify-event で得る値がおかしくなる、ワカンネェ!
これについては気が向いたら後日。

