Gedit を F11 でフルスクリーンにする。
その状態でマウスカーソルを上部に持って行くとフルスクリーンコントローラがスルスルと降りてくる。
これをどうやって実現しているのか今まで謎だった。
Clutter や非推奨の GtkFixed を使えば実は簡単なんだけど。
実際 0.1 や拙作 Clutter 動画プレイヤーのシークバーでやっているし。
Cocoa は GtkFixed みたいな古臭い API という事実は置いておいて。
GTK+ は基本的に Widget を配置すると引き伸ばしされる。
加えて GtkBin のサブクラスには Widget を一つしか配置できない。
つまり Widget 同士を重ねて配置することは不可能。
しかし Gedit 等は実現している、手段を調べてみよう。
実は Widget の引き伸ばしは単なるデフォルト動作だった。
知らなかったよマジで。
valign, halign プロパティのデフォルトが GTK_ALIGN_FILL なのだ。
つまり。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #!/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 があった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #!/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 で得る値がおかしくなる、ワカンネェ!
これについては気が向いたら後日。