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 で得る値がおかしくなる、ワカンネェ!
これについては気が向いたら後日。