xmonadでスクラッチパッドをお洒落にポップアップ
スクラッチパッドは、キー1発で、一時的なターミナルを呼び出す機能!! フローティングで配置されるので、現状のタイリング配置に影響を与えません。
タイリング配置された通常のウィンドウとは別に、右上に現れているターミナルがスクラッチパッドです。 そして、もう一度、キーを押せば、画面から消えてしまいます。 まさに、「一時的」ターミナル。
スクラッチパッドを利用するための概要
スクラッチパッドは、xmonadのモジュールである 「XMonad.Util.NamedScratchpad」 を利用します。
まずは、以下にスクラッチパッドを利用するための簡単なxmonad.hsの例を見てみましょう。
-------------------------------------------------------------------------------- | |
-- shunsk's base xmonad.hs file for NamedScratchPad | |
-- https://ok-xmonad.blogspot.com | |
-- | |
-- 必要な外部アプリ | |
-- kittyターミナル | |
-- dmenu | |
-------------------------------------------------------------------------------- | |
import System.Exit | |
import XMonad | |
import XMonad.Util.Run | |
import XMonad.Util.EZConfig | |
import XMonad.Util.NamedScratchpad | |
import XMonad.ManageHook | |
import qualified XMonad.StackSet as W | |
--------------------------------------------------------------- | |
-- MAIN | |
--------------------------------------------------------------- | |
main = xmonad | |
def { terminal = "kitty" | |
, modMask = mod4Mask | |
-- スクラッチパッドを操作出来るように | |
-- manageHookを修正する | |
, manageHook = manageHook def | |
<+> namedScratchpadManageHook mySPconf | |
, keys = \c -> mkKeymap c (keyMapDataList c) | |
} | |
--------------------------------------------- | |
-- スクラッチパッド設定データの作成 | |
--------------------------------------------- | |
mySPconf = [ | |
NS "ScrathcPad01" | |
"kitty -T ScratchPad01" | |
(title =? "ScratchPad01") | |
(customFloating $ W.RationalRect 0.51 0.05 0.48 0.5), | |
NS "ScrathcPad02" | |
"kitty --class ScratchPad02" | |
(className =? "ScratchPad02") | |
defaultFloating, | |
NS "ScrathcPad03" | |
"kitty -T ScratchPad03 htop" | |
(title =? "ScratchPad03") | |
nonFloating | |
] | |
--------------------------------------------- | |
-- キーバインド関連 | |
--------------------------------------------- | |
keyMapDataList :: XConfig Layout -> [(String, X ())] | |
keyMapDataList conf = | |
[("M-S-<Return>", spawn $ XMonad.terminal conf) | |
,("M-p", spawn "dmenu_run") | |
,("M-S-c", kill) | |
,("M-<Space>", sendMessage NextLayout) | |
,("M-S-<Space>", setLayout $ XMonad.layoutHook conf) | |
,("M-n", refresh) | |
,("M-j", windows W.focusDown) | |
,("M-k", windows W.focusUp) | |
,("M-m", windows W.focusMaster) | |
,("M-S-j", windows W.swapDown) | |
,("M-S-k", windows W.swapUp) | |
,("M-<Return>", windows W.swapMaster) | |
,("M-t", withFocused $ windows . W.sink) | |
,("M-S-q", io (exitWith ExitSuccess)) | |
,("M-q", spawn myRecompileCmd) | |
] | |
++ | |
[("M-" ++ m ++ show k , windows $ f i) | |
| (i,k) <- zip (XMonad.workspaces conf) ([1..5] :: [Int]) | |
, (f,m) <- [(W.view, ""),(W.shift, "S-")] | |
] | |
-- スクラッチパッドの呼び出しキー | |
++ | |
[("M-o", namedScratchpadAction mySPconf "ScrathcPad01") | |
,("M-i", namedScratchpadAction mySPconf "ScrathcPad02") | |
,("M-S-i", namedScratchpadAction mySPconf "ScrathcPad03") | |
] | |
where | |
myRecompileCmd = | |
"xmonad --recompile && (killall xmobar; xmonad --restart)" |
スクラッチパッドを利用するために必要となる事をまとめると次のようになります。
- 必要なモジュールのインポート
- スクラッチパッド設定データNSの定義
- スクラッチパッド呼び出しアクションをキーにバインド
- スクラッチパッドの挙動を制御するためにスクラッチパッド用のmanageHookを設定
スクラッチパッドは、NS型というデータ型で、どの様なスクラッチパッドを作るかを定義しておき、 その定義に基づいたスクラッチパッドを作るnamedScratchpadAction関数をキーにバインドしておきます。 また、スクラッチパッドの挙動は他のウィンドウと異なるため、 そのようなスクラッチパッド的な挙動を行うようにmanageHookを再定義します。
では、一つづゝ詳しく見ていきましょう。
必要パッケージのインポート
まずは、必要となるモジュールです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XMonad.Util.NamedScratchpad
import XMonad.ManageHook
import qualified XMonad.StackSet as W
中心になるのは、「XMonad.Util.NamedScratchpad」です。 そして、それ以外にスクラッチパッドの設定を行うNS型の定義をする時に、 ウィンドウの位置を指定するために「XMonad.StackSet」モジュールが、 また、ウィンドウを特定するための条件を指定するために「XMonad.ManageHook」が必要となります。 それぞれのページのリファレンスも設定の際に役に立つので以下に纏めておきます。
NS型データの定義
どの様なスクラッチパッドにするかを定義します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
---------------------------------------------
-- スクラッチパッド設定データの作成
---------------------------------------------
mySPconf = [
NS "ScrathcPad01"
"kitty -T ScratchPad01"
(title =? "ScratchPad01")
(customFloating $ W.RationalRect 0.51 0.05 0.48 0.5),
NS "ScrathcPad02"
"kitty --class ScratchPad02"
(className =? "ScratchPad02")
defaultFloating,
NS "ScrathcPad03"
"kitty -T ScratchPad03 htop"
(title =? "ScratchPad03")
nonFloating
]
実際の定義では、mySPconfという名前のリストの中に3つのNS型のデータを定義しています。 スクラッチパッドを呼び出す関数がNS型のリストを引数として取るため、 スクラッチパッドを1つしか定義しない場合であっても、必ずリストとして定義する必要が有ります。
この「NS」はNS型のデータをつくるための「値コンストラクタ」(よくわからない場合は「haskellのお洒落なレコード構文について」も参考にしてみましょう)です。 この値コンストラクタの引数は次の4つを取ります。
位置 | 引数名と型 | 内容 |
---|---|---|
1 | name :: String | スクラッチパッドの名前 |
2 | cmd :: String | アプリケーションを実行するためのコマンド |
3 | query :: Query Bool | アプリケーションを特定するための条件 |
4 | hook :: ManageHook | ウィンドウ表示の仕方 |
では、具体的な設定と見比べながらもう少し詳しく見ていきましょう。
スクラッチパッドの名前「name」
スクラッチパッドを呼び出すためには、 namedScratchpadAction関数にNS型のリストを第1引数として渡し、 その中のどれを呼び出すかを「name」の文字列で指定して第2引数に渡すことになります。 つまり、「name」は、複数登録されたスクラッチパッドのどれなのかを特定するための名前になります。 複数のスクラッチパッドを定義する場合には、重ならないように注意しましょう。 また、この文字列自体は、namedScratchpadAction関数を呼び出す時に必要となるだけなので、 ウィンドウのタイトル等とは無関係です。
1つ目のNS設定では、"ScratchPad01"と名付けています。 そして、これに対応しているのが、85行目のnamedScratchpadAction関数の第2引数です。
実行されるコマンド「cmd」
スクラッチパッドとして呼び出すプログラムのコマンドです。 シェルに渡すための文字列として定義しましょう。 1つめのNS定義では、kittyターミナルを呼び出しています。 呼び出すコマンドには必要なオプションも渡します。
"kitty -T ScratchPad01"
kittyの「-T」オプションは、タイトルを設定するためものもです。 ですから、このコマンドでは、タイトルが「ScratchPad01」となるkittyターミナルを呼び出すというコマンドになっています。
この「タイトル」は、なんとなく付けているわけではなく、 実は、NS値コンストラクタの3つめの引数である「アプリケーションを特定するための条件」と密接に関連していることに留意して置いて下さい。 そして、次の項目を読んで把握した後、再度、アプリケーションを特定するために必要となる引数について調整して下さい。
アプリケーションを特定するための条件「query」
xmonadは通常、ウィンドウが開かれるとタイル状に順番に配置されていきます。 一方、スクラッチパッドは、これとは別に、ウィンドウをフローティング状態で開く事ができます。 そして、ある特定のボタンを押すことで、今のワークスペースに表示したり、消したりすることが出来ます。 このように、スクラッチパッドで呼び出されるウィンドウは他のウィンドウとは別の異なった特別な挙動をするのですが、 これは単純に、「ある条件に合致するウィンドウ」にスクラッチパッド的な挙動をさせるという仕組みで行っています。
具体的なものを見てみましょう。 1つ目のNS定義では、3つめの引数として以下のようになっています。
(title =? "ScratchPad01")
この式の意味を大雑把にいえば、「タイトルが"ScratchPad01"と等しいですか?」という意味の式であり、 その結果として、等しければ「True」を「Faluse」を返します。 そして、スクラッチパッドは、この条件でTrueが帰るウィンドウをスクラッチパッドとして扱うことになります。
実は、ウィンドウを特定するための機能は、スクラッチパッド特有の機能ではなく、 xmonad自体が用意している機能で、「XMonad.MangeHook」モジュールでその機能が定義されています。 そして、特定するための条件として使えるものは「タイトル」だけでなく、次のようなものが用意されています。 尚、式にある"=?"は、右と左が同じであるかどうかを比較する比較演算子です。
関数 | 内容 |
---|---|
title | ウィンドウのタイトルを返す |
appName | アプリの名前を返す |
resource | アプリの名前を返す |
className | クラス名を返す |
ここで、そもそも「タイトル」や、「アプリの名前」とは何でしょうか? 実は、これらは、Xサーバーで管理されるウィンドウのプロパティ項目なのです。 ターミナルから以下のコマンドを実行すると、カーソルが十字キーになります。 そのカーソルで、何処かのウインドウをクリックしてみて下さい。 ウィンドウのプロパティーが表示されます。 ここで、「タイトル」に対応するものは、「_NET_WM_NAME」になります。
$ xprop
これらのウィンドウのプロパティは、プログラムを立ち上げる時の引数で変更することができます。 ここでの例では、先に述べたとおりkittyの「-T」オプションで「タイトル」を設定し、 これに呼応して「タイトル」が「"ScratchPad01"」であるものという条件でウィンドウを特定しています。
ここで、NS定義の2つ目を参照してみましょう。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NS "ScrathcPad02"
"kitty --class ScratchPad02"
(className =? "ScratchPad02")
defaultFloating,
プログラムの立ち上げ時に「クラス名」を特定するオプションを使って指定(45行目)すれば、 ウィンドウの特定にも、「クラス名」の特定で条件づけする(46行目)ことになります。
ここで、「タイトル」を条件とする場合、注意が必要です。 多くのターミナルでは、「タイトル」は動的に変化することが多いです。 一般的に、ターミナルではbashやzsh等のシェルが動いていますが、 これらのシェルは、カレントディレクトリや起動するコマンド名で、 そのウィンドウのタイトルを動的に上書きしてしまうことがあります。 これらの挙動は、kitty、xterm、rxvt等、 それぞれのターミナルプログラムによって、それぞれ独自の挙動をするので、 それぞれのターミナルのオプションと、 実際のxpropコマンドの出力を確認しながら、 どのプロパティでウィンドウを特定できるのかを調べる必要があるかもしれません。 例で利用しているkittyターミナルは、そのあたりの挙動が素直です。
ウィンドウ表示の仕方「hook」
スクラッチパッドは、フローティングの状態でウィンドウを表示すると説明してきましたが、 実はタイル状の一部として呼び出すことも出来ます。 この「hook」として設定できる選択肢は大まかに以下の3つになっています。
関数 | 内容 |
---|---|
nonFloating | 普通のタイル状のウインドウの一部として表示 |
defaultFloating | デフォルトの位置でフローティングして表示 |
customFloating | 自分の好きな位置にフローティングして表示 |
「nonFloating」と「defaultFloating」は、「hook」の内容として、これだけを定義すればOKです。 一方、「customFloating」は、位置を指定するためのデータ「RationalRect」が引数として必要になります。
「RationalRect」データとは、画面の中で任意の長方形を、画面の高さと幅に対する割合で指定するデータで、 XMonad.StackSetモジュールで定義されています。 RationalRect型データは、RationalRect値コンストラクタに4つの引数を与える事で作成します。 それぞれの引数は以下のとおりです。
引数の位置 | 内容 |
---|---|
第1引数 | 長方形左上のx座標の位置を画面幅に対する割合で指示 |
第2引数 | 長方形左上のy座標の位置を画面高さに対する割合で指示 |
第3引数 | 長方形の幅をを画面幅に対する割合で指示 |
第4引数 | 長方形の高さを画面高さに対する割合で指示 |
この具体例である、ひとつめのNS定義の第4引数を見てみましょう。
W.RationalRect 0.51 0.05 0.48 0.5
初めの2つ0.51と0.05が長方形の左上座標を表し、0.48と0.5が幅と高さをそれぞれ表しています。 そして、これら数値は、それぞれ画面の幅、若しくは、高さに対する割合(ピクセル等の具体的で絶対的な数値ではない)を表しています。
スクラッチパッドを起動するキーバインド
スクラッチパッドは、 namedScratchpadAction
関数で作られるアクションを自分の好きなキーにバインドします。
キー設定のカスタマイズがよくわからない場合は「xmonadでお洒落にキーのカスタマイズ」も参考にしてみて下さい。
例示のxmonad.hsの該当部分は以下のとおりです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- スクラッチパッドの呼び出しキー
++
[("M-o", namedScratchpadAction mySPconf "ScrathcPad01")
,("M-i", namedScratchpadAction mySPconf "ScrathcPad02")
,("M-S-i", namedScratchpadAction mySPconf "ScrathcPad03")
]
namedScratchpadAction
関数は、2つの引数を取ります。
1つ目は、NSデータのリストです。
そして、2つ目は、そのNSデータリストの中で、呼び出したいデータの「name」です。
manageHookの修正
最後に、設定したスクラッチパッドがスクラッチパッドとして動くように、xmonadに渡すXConfilg l型データのmanageHookを修正します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- スクラッチパッドを操作出来るように
-- manageHookを修正する
, manageHook = manageHook def
<+> namedScratchpadManageHook mySPconf
スクラッチパッド用のmanageHookは、namedScratchpadManageHook関数にNSデータのリストを渡して作成します。 そして、出来上がったスクラッチパッド用のmanageHookは、他のmanageHookデータに"<+>"演算子を使って、結合しておけばOKです。
スクラッチパッドとワークスペース「NSP」
最後に、もう少しだけスクラッチパッドの正確な挙動を説明しておきます。 スクラッチパッドは、設定してあるキーを押すことで、設定されているアプリケーションが起動します。 若しくは、既にそのアプリケーションが起動されている場合、現在のワークスペースにそのアプリケーションウィンドウを移動させます。 そして、もう一度、設定してあるキーを押すと「NSP」という名前のワークスペースにアプリケーションウィンドウを移動させます。 この「NSP」という名前のワークスペースは、自動的に作成される、若しくは、自分で同名のワークスペースを作っている場合は、そのワークスペースが使用されます。
さて、ここでスクラッチパッドを利用しだすと、このNSPという名前のワークスペースに不満が出てくるようになります。 スクラッチパッドの隠れ先であるNSPワークスペースは、ステータスバーのワークスペース名表示や、 ワークスペース移動の際に隠れた状態にしたくなります。
これらの問題は、解決可能ですが、ステータスバーでのワークスペース表示のさせ方や、 ワークスペース移動をどの様に設定しているかによって、NSPをスキップさせる方法がいくつも考えられます。 そこで、NSPのスキップのさせ方については、ステータスバーでのワークスペース表示の仕方と併せて別の機会にノートしたいと思っています。 しかし、もし、手っ取り早くNSPをスキップさせたいという場合には、「NSP skip」等でググるとヒントが色々と得られると思います。
0 件のコメント:
コメントを投稿