GNOME Shellの拡匵機胜を䜜成する方法サむレントモヌド

それはすべお、1぀のLinuxディストリビュヌションの新しいバヌゞョンに移行するこずから始たりたした。そこには、Javascriptの悪名高い GNOME Shell略しおGHがありたす。 JSでは、JSで機胜したす-そしお倧䞈倫です。


同時に、ブラりザヌのoutlook.office.comタブの数メガバむトのブレヌキングずガチャガチャではなく、私の仕事のペヌスは長い間、通垞のメヌラヌを芋぀けるこずを芁求しおきたした。 そしお今、私は、私たちの時代には、いく぀かのほが優秀な候補者がいるこずを発芋したした、1぀の問題-メヌラヌは新しい手玙の通知で私を取埗し始めたした-そしお音ずポップアップ碑文。


どうする Do Not Disturb拡匵機胜を䜜成するずいう決定はすぐには埗られたせんでした。自転車を䜜成したり、開発で動揺したり、コヌドや゚ラヌが倧量に発生したりするこずは本圓に望みたせんでしたが、今ではHabrず経隓を共有したいず考えおいたす。 1



技術的芁件


欲しいです 倧きい 遞択した時間に通知ず音をオフにするボタン20分、40分、1時間、2時間、4、8、24時間。 2ええ、スラックのようなタむミング。


extensions.gnome.orgの拡匵郚分には、「Do Not Disturb Button」ずいう拡匵機胜があり、拡匵機胜「 Do Not Disturb Time」を蚘述するためのモデルずしお機胜したした 。


最終結果 時間を邪魔しないでください


時間を邪魔しないでください


extensions.gnome.orgからむンストヌルしたす。
githubの゜ヌス星、フォヌクを入れお、改善を提䟛したす。


GH拡匵機胜のむンストヌル方法手順


  1. Ubuntuを䟋ずしお䜿甚しお、ブラりザヌコネクタであるchrome-gnome-shellパッケヌゞをむンストヌルしたす。
    sudo apt install chrome-gnome-shell
  2. リンクをクリックしお、ブラりザヌ拡匵機胜をむンストヌルしたす。
    • リンクをクリックしおブラりザ拡匵機胜をむンストヌルしおください
    • Ubuntu 18.04では、Chrome / Chromiumブラりザ、Fedora 28/29-FirefoxずChromiumの䞡方で動䜜したした
  3. リストhttps://extensions.gnome.orgで目的の拡匵機胜を探しおいたす。拡匵機胜の蚭定を有効化、無効化、倉曎したす。
  4. 利益

開始する


拡匵機胜をれロから䜜成したす。


 $ gnome-shell-extension-tool --create-extension Name: Do Not Disturb Time Description: Disables notifications and sound for a period Uuid: dnd@catbo.net Created extension in '~/.local/share/gnome-shell/extensions/dnd@catbo.net' #  gnome-shell Alt+F2, r, Enter #    https://extensions.gnome.org/local/      #   Gnome Shell - , gnome-shell   systemd,   journalctl -f /usr/bin/gnome-shell #    ,       gnome-shell journalctl -f /usr/bin/gnome-shell | grep -E 'dnd|$' 

察応するディレクトリのextension.jsファむルは、アプリケヌションの゚ントリポむントです。最小バヌゞョンでは、次のようになりたす。


 function enable() {} //   ;    function disable() {} // --||-- ;     enable() 

最初のコヌド


最初Status Menu䞊のスクリヌンショットのようStatus Menu右䞊のStatus Menuボタンを远加したす。


それではどこから始めたすか ああ、ドキュメントから始めたしょう。 公匏のドキュメント、すべおのものがありたす。 しかし、公匏ドキュメントは非垞に小さく断片化されおいたすが、 julio641742ずその非公匏ドキュメントのおかげで、必芁なものが埗られたす。


  // 1 -    (1 - , 0 - , 0.5 -  ) // true,     let dndButton = new PanelMenu.Button(1, "DoNotDisturb", false); // `right` -      (left/center/right) Main.panel.addToStatusArea("DoNotDisturbRole", dndButton, 0, "right"); let box = new St.BoxLayout(); dndButton.actor.add_child(box); let icon = new St.Icon({ style_class: "system-status-icon" }); icon.set_gicon(Gio.icon_new_for_string("/tmp/bell_normal.svg")); box.add(icon); 

このコヌドは、 dndButtonクラスのdndButtonキヌオブゞェクトを䜜成したす。これは、ステヌタスメニュヌパネル甚に特別に蚭蚈されたボタンです。 そしお、Main.panel.addToStatusArea関数を䜿甚しおこのパネルに挿入したす。 3


ハンドラヌがボルトで固定されたメニュヌ項目を挿入したす。䟋


  let menuItem = new PopupMenu.PopupMenuItem("hello, world!"); menuItem.connect("activate", (menuItem, event) => { log("hello, world!"); }); dndButton.menu.addMenuItem(menuItem); 

julio641742、ドキュメントをありがずう リンク
https://github.com/julio641742/gnome-shell-extension-reference


最終的な䜜業コヌドはこちらです。


GNOMEシェルおよびJavaScript機胜


倖郚は2018幎末であり、Node.js / V8はJavascriptコヌドを実行するためのメむンツヌルです。 最新のWeb開発はすべお「ノヌド」に基づいおいたす。


ただし、GNOMEシェルずその呚蟺のむンフラストラクチャは、異なるJavaScript゚ンゞンであるMozillaのSpiderMonkeyを䜿甚しおいるため、パフォヌマンスに倚くの重芁な違いが生じたす。


モゞュヌルのむンポヌト


Node.jsずは異なり、requireはなく、掟手なES6-importもありたせん。 代わりに、特別なimportsオブゞェクトがあり、その属性にアクセスしおモゞュヌルをロヌドしたす


  //const PanelMenu = require("ui/panelMenu"); const PanelMenu = imports.ui.panelMenu; 

この堎合、ポップアップメニュヌを備えたボタンの機胜を実装するGNOME Shellパッケヌゞラむブラリからjs / ui / panelMenu.jsモゞュヌルをダりンロヌドしたした。


はい、GNOMEを䜿甚した最新のLinuxデスクトップのパネルにあるすべおのボタンは、panelMenu.jsに基づいおいたす。 含むバッテリヌむンゞケヌタヌ、Wi-fi、音量の同じ右ボタン。 入力蚀語スむッチen-ru。


次に、特別な属性imports.searchPathがありたす-これは、JSモゞュヌルが怜玢されるパス行のリストです。 たずえば、タむマヌ関数を別のtimeUtils.jsモゞュヌルに割り圓お、拡匵機胜の入力ポむントextension.jsの近くに配眮したした。 次のようにtimeUtils.jsをむンポヌトしたす。


 //     , -  ~/.local/share/gnome-shell/extensions/<your-extension>/ const Me = imports.misc.extensionUtils.getCurrentExtension(); //       imports.searchPath.unshift(Me.path); //   const timeUtils = imports.timeUtils; 

ロギング、Javascriptのデバッグ


Node.jsがないため、独自のロギングがありたす。 console.logの代わりに、コヌドでいく぀かのロギング関数を䜿甚できたす。gjs/../ global.cpp、static_funcsを参照しおください。



 $ cat helloWorld.js log("hello, world"); $ gjs helloWorld.js Gjs-Message: 17:20:21.048: JS LOG: hello, world 


 try { throw new Error('bum!'); } catch(e) { logError(e, "what a fuck"); } 

そしお、これはスタむルでstderrに描画したす


 (gjs:28674): Gjs-WARNING **: 13:39:46.951: JS ERROR: what a fuck: Error: bum! ggg@./gtk.js:5:15 ddd@./gtk.js:12:5 @./gtk.js:15:1 


しかし、すぐに䜿えるSpiderMonkey甚のデバッガはありたせんロギングに䜿甚できるすべおのツヌルよりも苊劎しお曞いたのは無駄ではありたせんでした。 必芁に応じお、JSRDbg one 、 twoを詊すこずができたす。


GNOME Shellの倖郚にJSコヌドの寿呜はありたすか


ありたす。 グラフィカルナヌザヌむンタヌフェむスGUIを含むフル機胜のアプリケヌションは、Javascriptで蚘述できたす。 GUIりィンドりの䜜成䟋である、js-GTKコヌドランチャヌであるgjs binarを䜿甚しお実行する必芁がありたす。


 $ which gjs /usr/bin/gjs $ dpkg --search /usr/bin/gjs gjs: /usr/bin/gjs $ cat gtk.js const Gtk = imports.gi.Gtk; Gtk.init(null); let win = new Gtk.Window(); win.connect("delete-event", () => { Gtk.main_quit(); }); win.show_all(); Gtk.main(); $ gjs gtk.js 

䞊蚘で、コヌドをモゞュヌルに分割し、Javascriptからロヌドするこずに蚀及したした。 問題が発生したすが、モゞュヌル自䜓で「メむン」モゞュヌルずしお起動されるか、別のモゞュヌルからロヌドされるかを刀断するにはどうすればよいですか


Pythonには本物の構造がありたす。


 if __name__ == "__main__": main() 

Node.jsで-同様に


 if (require.main === module) { main(); } 

Gjs / GHに察するこの質問に察する公匏の回答は芋぀かりたせんでしたが、読者ず共有するのを急ぐようなテクニックを思い぀きたしたなぜ誰かが「dosyudova」を読んだのですか


したがっお、トリッキヌなトリックは、珟圚のコヌルスタックの分析に基づいおいたす。2行以䞊で構成されおいる堎合、mainモゞュヌルには含たれたせん。


 if ( new Error().stack.split(/\r\n|\r|\n/g).filter(line => line.length > 0) .length == 1 ) { main(); } 

ハりスキヌピング


各GNOMEシェル拡匵機胜は、GNOMEシェル党䜓のすべおのオブゞェクトにアクセスできたす。 たずえば、ただ未読の通知の数を衚瀺するには、䞊の䞭倮にあるNotification Areaにあるコンテナヌにアクセスしたす。写真の4番です珟圚の時刻の碑文をクリックしたす。実際には、ここではなくクリックできたす。


時間を邪魔しないでください


  let unseenlist = Main.panel.statusArea.dateMenu._messageList._notificationSection._list; 

未読の通知の数を確認し、通知の远加ず削陀のむベントにサブスクラむブできたす。


 let number = unseenlist.get_n_children(); unseenlist.connect("actor-added", () => { log("added!"); }); unseenlist.connect("actor-removed", () => { log("removed!"); }); 

これは問題ありたせんが、ナヌザヌはX拡匵機胜が䞍芁になったず刀断し、ボタンをクリックしお拡匵機胜を無効にするこずができたす。 拡匵機胜の堎合、これはdisable関数を呌び出すこずず同等であり、無効にした拡匵機胜が動䜜䞭のGHを砎壊しないようにあらゆる努力を払う必芁がありたす。


 function disable() { dndButton.destroy(); } 

この堎合、ボタン自䜓を削陀するこずに加えお、むベント「actor-added」/「actor-removed」の登録を解陀する必芁がありたす。䟋


 var signal = unseenlist.connect("actor-added", () => { log("added!"); }); function disable() { dndButton.destroy(); unseenlist.disconnect(signal); } 

これが行われない堎合、ハンドラヌのコヌドは察応するむベントで呌び出され続け、もう存圚しないメニュヌボタンの状態を曎新しようずしたす... GNOME Shellは倱敗し始めたす。 ええ、はい、私たちはそれをしたす、ナヌザヌは誓いたす、石はGNOMEシェル開発者ずGNOME党般に飛ぶでしょう。 実際の画像、Th。


GNOME Shell / Gjsは、Glib / GTKずJavascriptの2぀のシステムの共生であり、リ゜ヌス管理ぞのアプロヌチが異なりたす。 Glib / GTKでは、リ゜ヌスボタン、タむマヌなどを明瀺的に解攟する必芁がありたす。 オブゞェクトがJavascript゚ンゞンによっお䜜成された堎合、通垞どおり動䜜したす䜕もリリヌスしたせん。


その結果、拡匵機胜の準備が敎い、「フロヌ」しなくなるずすぐに、 https://extensions.gnome.orgで安党に公開できたす 。


GnomeSession.PresenceStatus.BUSYおよびDBusモヌド。


忘れおいない堎合は、ナヌザヌぞの通知の衚瀺をオフにする拡匵機胜「サむレント」を実行しおいたす。


GNOMEにはすでにこの状態を担圓するフラグがありたす。 ナヌザヌがログむンするず、gnome-sessionプロセスが䜜成され、このフラグが配眮されたす。これはGsmPresencePrivate.status属性です。gnome-sessionの゜ヌス、gnome-session / gsm-presence.cを参照しおください。 DBusむンタヌフェむスこのようなプロセス間通信を介しおこのフラグにアクセスできたす。


私たちだけでなく、GH自䜓も通知を衚瀺しないためにこのフラグに関する情報が必芁です。 これはGH゜ヌスで芋぀けるのに十分簡単です


 this._presence = new GnomeSession.Presence((proxy, error) => { this._onStatusChanged(proxy.status); }); ... this._presence.connectSignal('StatusChanged', (proxy, senderName, [status]) => { this._onStatusChanged(status); }); 

この堎合、_onStatusChangedメ゜ッドは状態の倉化に応答するハンドラヌです。 このコヌドを自分自身にコピヌしお適甚したす。4぀の通知を芋぀け、音がしたした。


ミュヌト/ミュヌト解陀


最新のLinuxデスクトップは、PulseAudioによっお制埡されたす。 悪名高い仕事 悪名高いレナヌト・ポ゚タリングのプログラム制䜜者。 これたで、PulseAudioのコヌドを手に入れたこずはありたせんでしたが、PulseAudioをある皋床理解する機䌚を埗られたこずを嬉しく思いたした。


その結果、ミュヌト/ミュヌト解陀には、1぀のpactlナヌティリティ、たたはそれに基づく3぀のコマンドで十分であるこずが刀明したした。



したがっお、私たちのタスクは、コマンド/プロセスを実行し、それらの出力stdoutを読み取り、定期的に目的の倀を怜玢するこずです。 芁するに、暙準タスク。


GNOMEでは、glibコアラむブラリがプロセスの䜜成を担圓し、それに優れたドキュメントがいく぀かありたす。 そしおもちろん圌女はCにいたす。JSがいたす。 Gjsパッケヌゞは、C-APIずJavascriptの間にスマヌトで「盎感的な」レむダヌを䜜成したこずが知られおいたす。 しかし、䟋が必芁であり、グヌグルなしではできないこずを理解しおいたす。


その結果、優れた芁点のおかげで、動䜜するコヌドが埗られたす。


 let resList = GLib.spawn_command_line_sync(cmd); // res = true/false, /   // status = int,    // out/err = ,  stdout/stderr  let [res, out, err, status] = resList; if (res != true || status != 0) { print("not ok!"); } else { // do something useful } 

蚭定を保存する レゞストリ内


もちろん、Linuxにはレゞストリはありたせん。 ここでは、Windowsではありたせん。 GSettingsこれはAPIず呌ばれるより優れたものがあり、いく぀かの実装オプションが背埌に隠されおいたす。デフォルトでは、GNOMEはDconfを䜿甚したす。 これは、GUIフレヌムワヌクの倖芳です。


dconf-editor


-蚭定をプレヌンテキストファむルに保存するよりも優れおいるものは䜕ですか -叀いひげを生やしたLinuxナヌザヌが尋ねたす。 GSettingsの䞻な機胜は、次のような蚭定の倉曎を簡単にサブスクラむブできるこずです。


 const Gio = imports.gi.Gio; settings = new Gio.Settings({ settings_schema: schemaObj }); settings.connect("changed::mute-audio", function() { log("I see, you changed it!"); }); 

これたでの「サむレント」の唯䞀の蚭定は「ミュヌトオヌディオ」オプションで、ナヌザヌは「静かな時間」たたはナヌザヌの芁求なしにサりンドをオフにできたす。


少しクラシックなGTK GUI


拡匵機胜の蚭定をナヌザヌに矎しく衚瀺するためにたた、汚れた足でレゞストリに入らないように、GHはGUIコヌドを蚘述し、それをprefs.jsファむルのbuildPrefsWidget関数に入れるこずを提案したす。 この堎合、「むンストヌルされおいる拡匵機胜」のリストの拡匵機胜の反察偎に、 ここに远加のボタン「この拡匵機胜を構成する」が衚瀺されたす。


Eboutな​​しでは、申し蚳ありたせんが、プログラムは完党ではないこずがわかっおいるため、[About]タブを別に䜜成したしょう。


䞀般的に、叀兞的なグラフィカルむンタヌフェむスを構築するために、GTKにはさたざたなビルディングブロック、 があり、 ここで数量ず品質を確認できたす 。


そのうちのいく぀かを䜿甚したす。



 function buildPrefsWidget() { //    Gtk.Notebook    GUI let notebook = new Gtk.Notebook(); ... //  About,    VBox c   10 , //   margin/padding   let aboutBox = new Gtk.VBox({ border_width: 10 }); //     About notebook.append_page( aboutBox, new Gtk.Label({label: "About"}), ); //        , //      ,    (expand) aboutBox.pack_start( new Gtk.Label({ label: "<b>Do Not Disturb Time</b>", use_markup: true, }), true, // expand true, // fill 0, ); ... notebook.show_all(); return notebook; } 

最終的なスクリヌンショット



オプショナル


1.動䜜モヌドサポヌトず䜜業

私の堎合、プログラマヌの仕事には2぀のモヌドが関係しおいたす。
1サポヌトモヌドで、メヌル、Slack、Skypeなどのむベントにすばやく応答する必芁がある堎合
2動䜜モヌドでは、少なくずも20分間通知を削枛するこずが重芁です。そうしないず、フォヌカスが倱われ、最終的な劎働生産性が無芖できたす。 これには、サむレントモヌドが䟿利です。


2.サりンドをオフにする方法

完党なミュヌト、ミュヌトは倚すぎるように思えるかもしれたせん。 実際、理想的には、Slack / Skypeをサむレントモヌドで聞くこずをお勧めしたすが、その他のサりンド実際の通知は聞こえたせん。 しかし、このためには、䜕らかの圢で区別する必芁がありたす。 もちろん、通知専甚のサりンドAPIを䜜成するこずもできたすこれは既に存圚したす。そのような機胜を䜿甚しないプログラム/プログラマヌのみが垞に存圚したす。 䟋ずしおは、Mailspringメヌラヌがありたす。これは単にaudioタグを介しおサりンドを再生するだけであり、Slackコヌルのスピヌチず区別するこずはできたせん。


3. PanelMenu.Button

PanelMenu.Button-これはパネル+ポップアップメニュヌの実際のボタンであり、自分で把握しおれロから䜜成するこずができたす。䞡方ずも傷のある人に感謝されたす 迅速な結果を目指しおいたため、非公匏のドキュメントからコヌドをコピヌしたした。


4. SetStatusRemote

SetStatusRemoteを䜿甚しお、実際にモヌド倉曎を開始したす。



Source: https://habr.com/ru/post/J428187/


All Articles