AwesomeWM上でZoomを使っているときにポップアップウィンドウに邪魔されないようにする

2021/08/21 追記

まる一日運用してみたところ色々とバグがあったので全体的に更新した。

Motivation

AwesomeWMのタイルレイアウト上でZoomを使っていると、 "You are co-host now" や "hoge has started screen sharing" のようなポップアップメッセージが出たときにウィンドウレイアウトが大きく変わってしまい、かつそのポップアップウィンドウがフォーカスを持っていってしまうため、作業が中断される。 Zoomのポップアップウィンドウ これは大変に鬱陶しい。 幸い、AwesomeWMはウィンドウ(AwesomeWM用語としてはclient)が生成されるたびにコールバックを通してウィンドウのプロパティをいじれるので、その機能を使ってできるだけ邪魔をされないようにする。

Methods

$HOME/.config/awesome/rc.lua に以下の通り設定することで、Zoomのポップアップウィンドウが生成されたときに

  • floatingになる(既存のウィンドウレイアウトが崩れない)
  • focusされない(作業の邪魔にならない)

ようになる。

awful.rules.rules = {
  -- ... 既存の設定 ...

  {
    rule = { class = "zoom", type = "normal", name = "zoom" },
    properties = { focus = false, focusable = false, floating = true },
    -- 08/21 以下追記
    callback = function(c)
      f = function(_c)
        _c:disconnect_signal("property::name", f)
        if _c.name ~= "zoom" then
          _c.focus = false
          _c.focusable = true
          _c.floating = false
        end
      end
      c:connect_signal("property::name", f)
    end
  },
}

解説 & Tips

基本的にはawful.rulesのAPI docを読めば必要なことは書いてある。 新しいclientが生成されたとき(manage シグナルが発行されたとき)、rule = {...} にマッチするものについて、指定された properties を適用したり callback を実行したりできる。

したがって、新しいruleを追加するためには、操作したいclientのclass/type/name等の属性を知る必要がある。 このとき、簡便にこれらの情報を表示させるには以下のようにdesktop notificationを発行してしまうのが便利だと思う。

client.connect_signal("manage", function (c)
  naughty.notify({ preset = naughty.config.presets.critical,
                   title = "New client",
                   text = c.class .. ":" .. c.type .. ":" .. c.name })
end)

当然AwesomeWMのログに出力しても良いのだが、notificationだとその場でパッと確認できるのでやはり便利である。 ちなみに、notificationのレベルには critical normal low の3段階が(デフォルトで)用意されているが、 low または normal を設定すると発行後数秒で消えてしまい確認が困難になるため critical を使うのが良い。

このnotificationにより、対応すべきclientは class = "zoom", type = "normal", name = "zoom" であるとわかる。 ここで、 name = "zoom" とするのは対象が広くなりすぎるリスクがあるように感じるのだが、どうやら他のZoom関連のウィンドウはすべて "Zoom hogefuga" というように、頭のZが大文字で、かつ何らかの文字列が後ろに続くため、問題にならないようである。 このあたりは環境依存だったりZoomのバージョン依存であったりする可能性は否定されないので、なにか不具合が起こる可能性は残っている。

08/21 追記

やはり name = "zoom" で一網打尽にしてしまうのは問題があった。 というのも、Zoomのクライアントソフトウェアを立ち上げると "Zoom - Free Account" という name を持つメインウィンドウが表示されるのだが、これは一瞬 "zoom" という name のウィンドウが生成された直後にrenameされるものであるようだ。 awful.rules で設定した規則はウィンドウの生成時に解釈・適用されるため、この時点での name に依存して floating = true とか focusable = false が適用されてしまい、Zoomのメインウィンドウを操作できなくなってしまう。 そこで、 property::name イベントに対するコールバック関数として、名前が "zoom" でなくなったら属性を再度変更するという処理を行うことにした。

おまけ(08/21 更新)

以下のように設定すると、そもそもポップアップウィンドウが生成されようとした瞬間にcloseする(i.e., 現れなくする)こともできると考えたが、上記と同様の理由により、この設定を行うとZoomのメインウィンドウ自体が閉じられてしまうのでボツとなった。

awful.rules.rules = {
  -- ... 既存の設定 ...

  {
    rule = { class = "zoom", type = "normal", name = "zoom" },
    callback = function(c)
      c:kill()
    end
  }
}