💎

Ruby で DBus サーバーを作る

に公開

Linux デスクトップ上で自作のキーリマッパー Rkremap を使ってるんだけど、アプリごとに異なるキーマップにするために X11 の機能を使ってるので、Wayland だと動かない。

前の記事でアクティブウィンドウが切り替わったときに KWin Script で何かする方法はわかった。

けど、情報を外部アプリに渡すために、ファイルに書いたりソケット通信したりコマンドを実行したりする方法はなさそうだった。唯一使えそうなのが callDBus で、DBus を使ったプロセス間通信だった。

DBus については何もわかってなかったんだけど、ruby-dbus というのを使えば Ruby からでも使えそう。

https://github.com/mvidner/ruby-dbus

チュートリアルに書かれてるままなんだけどサーバーはこんな感じ:

require 'dbus'

# DBus にサービス登録
bus = DBus.session_bus
service = bus.request_service("org.ruby.service")

class Test < DBus::Object
  dbus_interface "org.ruby.SampleInterface" do
    dbus_method :hello, "in name:s, in name2:s" do |name, name2|
      puts "hello(#{name}, #{name2})"
    end
  end
end

# オブジェクト作成
exported_obj = Test.new("/org/ruby/MyInstance")
service.export(exported_obj)

# イベントループ
loop = DBus::Main.new
loop << bus
loop.run

実行:

% ruby hoge.rb

別の端末から qdbus を使ってクライアントを実行:

% qdbus org.ruby.service /org/ruby/MyInstance org.ruby.SampleInterface.hello hoge fuga

出力:

hello(hoge, fuga)
...

ちゃんと動いてそう。

アクティブウィンドウが切り替わる度にこの DBus にウィンドウ名とクラスを通知する KWin Script を作る:

workspace.windowActivated.connect(function(win) {
    if (win) {
        callDBus('org.ruby.service', '/org/ruby/MyInstance', 'org.ruby.SampleInterface', 'hello', win.caption, win.resourceClass)
    }
})

KWin Script の有効化:

% qdbus org.kde.KWin /Scripting loadScript /tmp/hoge.js hoge
% qdbus org.kde.KWin /Scripting start

アクティブウィンドウを切り替えてみたときの hoge.rb の出力にちゃんとウィンドウ名が表示された。

hello(hoge.rb - GNU Emacs at t14, Emacs)
hello(端末 - tommy@t14:/tmp, Xfce4-terminal)
hello(Ruby で DBus を使う - tmtms のメモ — Mozilla Firefox, firefox)
...

なんとかなりそう。

Discussion