現在どのモニタに焦点を当てているかを問い合わせる簡単な方法

現在どのモニタに焦点を当てているかを問い合わせる簡単な方法

現在フォーカスされているモニターを照会するツールがあるかどうか疑問に思います。

現在使用しているモニターの壁紙を変更するスクリプトが必要です(xwallpaperを使用)。私が理解したのは、モニター番号やモニター名(HDMI1、eDP1など)が私の目標を達成するのに役立ちます。

最後に、現在のモニターで選択されている壁紙は、次の構造の名前を使用してコピーされますwall-HDMI1.pngwall-eDP1.png

部分的な解決策があります。許容される答えは、マウスの位置を使用して現在のモニターを推測することを示唆しています。使用xdotool。これはせいぜいトリッキーなようです。特に、さまざまなレイアウトを使用して複数のモニターに接続できるノートブックの場合は、さらにそうです。

ベストアンサー1

現在の基本モニターが何であるか疑問に思うなら簡単です。

$ xrandr | grep primary
DP-2 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 597mm x 336mm

または

$ xrandr | awk '/ primary / {print $1}'
DP-2

現在、マウスポインタがどのモニタに入っているかを知りたい場合は、もう少し難しいです。まず、マウスポインタの位置を把握してから(たとえばを使用してxdotool)、マウスのX、Y座標を各画面の開始と終了のX、Y座標と比較する必要があります(たとえばを使用xrandr)。 。

次のPerlスクリプトはこれを実行するためにxrandrおよびを使用しますxdotool

#!/usr/bin/perl

use strict;

my %M;    # hash to hold keys from 'xdotool getmouselocation --shell'
my $pipe; # file handle for the pipes we're going to open

# get the current cursor location into $M{X} and $M{Y}
open($pipe, "-|", qw(xdotool getmouselocation --shell)) ||
    die "couldn't open pipe from xdotool: $!\n";

while(<$pipe>) {
  chomp;
  my($key, $val) = split /=/;
  $M{$key} = $val;
};
close($pipe);

# compare mouse location to monitor co-ordinates
open($pipe, "-|", "xrandr") ||
    die "couldn't open pipe from xrandr: $!\n";

while(<$pipe>) {
  my ($display, $width, $height, $x_offset, $y_offset);

  next unless m/ connected /;
  my @F = split;
  $display = $F[0];

  # co-ordinates are on fourth field (F[3]) on the primary display
  # or on third field (F[2]) on non-primary displays. Perl arrays
  # start from zero, not one (same as in bash). 
  if ($F[2] eq "primary") {
    ($width, $height, $x_offset, $y_offset) = split /[x+]/, $F[3];
  } else {
    ($width, $height, $x_offset, $y_offset) = split /[x+]/, $F[2];
  };

  if ($M{X} >= $x_offset && $M{X} <= $width + $x_offset && 
      $M{Y} >= $y_offset && $M{Y} <= $height + $y_offset) {
    print "$display\n";
    last;
  };
};
close($pipe);

たとえば、 として保存し、 を使用して./get-focused-monitor.pl実行可能にしてからchmod +x get-focused-monitor.pl実行します。現在マウスポインタがどのモニタの上にあるかを知らせます。

$ ./get-focused-monitor.pl 
DP-2

これを実行すると、watch -n 0.1 ./get-focused-monitor.plあるモニターから別のモニターにマウスを移動したときにモニター名が変更されることを確認できます。何十秒もこのことをしましたが、私のときめきは変わりませんでした。ほぼ多すぎます。


ところで、現在2つの1440pモニターが接続されています。横モードの27インチモニター(「DP-2」、基本モニター)と縦モードに切り替えられた24インチモニター(「DP-0」)。私のシステムで解析されたこのスクリプトの出力はxrandr次のとおりです。

$ xrandr | grep \\bconnected
DP-0 connected 1440x2560+2560+0 left (normal left inverted right x axis y axis) 527mm x 296mm
DP-2 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 597mm x 336mm

split /[x+]/3番目または4番目のフィールドを幅、高さ、xオフセット、yオフセットなど4つの整数配列に分割するには、スクリプトまたはx区切り文字として使用します。 Perl関数の仕組みについては、参考資料を+参照してください。perldoc -f splitsplit()


PS:なぜPerlですか? Perl が簡単なので、シェルの while-read ループでテキストを解析するのは恐ろしく、シェルで計算を実行するのは少なくともそれほど悪いです。したがって、一般的なシェルの空白、引用、トークン化の問題に対処したくありません。あるいは、アレイのための非常に醜いシェル構文。シェルは外部プログラムとデータをリンクする唯一の言語ではありません。 UNIXとLinuxで一般的に使用されているほとんどの言語はこれを行うことができます。

シェルでこれを行うのは特に難しくありません。必要に応じて、bashでアルゴリズムを再実装することもできます。重要なのは言語ではなく方法です。

ところで、シェルでこれを行う最も簡単な方法は、このようなことを実行し、awkに両方のプログラム(xdotool getmouselocation --shell; xrandr) | awk '...'のさまざまな入力タイプを解析させることです。または、awkの代わりにperlを使用してください。 ShellやPerlと同様に、awkも外部プログラムを実行してその出力を処理できることにも注目する価値があります。

Perlには設定操作が少しありますが(明示的にパイプを開く)、これは定型句エントリです。残りのコードはシェルよりはるかに簡単です。

バックティックを使用して実行できます。またはqx()(参照perldoc -f qxコマンドの置き換えシェルと同じように使用する代わりにopen()(参考資料を参照perldoc -f open)。

#!/usr/bin/perl

foreach (qx(xdotool getmouselocation --shell)) {
  m/^([^=]+)=(.*)$/;
  $M{$1} = $2;
};

foreach (qx(xrandr)) {
  next unless m/connected/;
  ($d, $w, $h, $xo, $yo) = m/^([^\s]+) .* (\d+)x(\d+)\+(\d+)\+(\d+)/;

  if ($M{X} >= $xo && $M{X} <= $w + $xo &&
      $M{Y} >= $yo && $M{Y} <= $h + $yo) {
    print "$d\n";
    last;
  }
}

open()これは最初のスクリプトとまったく同じ出力を生成しますが、明示的な-ingパイプの代わりにPerlスタイルのコマンド置換を使用します。また、正規表現キャプチャグループを使用してsplit()

しかし、Perlには非常に便利な機能がありますmapperfoc -f map詳細については、参考資料を参照してください(perldoc -f grep同様の便利な組み込み機能も参照してください)。これは非常に便利で汎用性の高いツールです。このツールで実行できる最も簡単な作業の1つは、最初のforeachループを次に置き換えるなどのことです。

foreach (qx(xdotool getmouselocation --shell)) {
  map { $M{$1} = $2 } m/^([^=]+)=(.*)$/;
};

でも:

map { $M{$1} = $2 } m/^([^=]+)=(.*)$/ foreach (qx(xdotool getmouselocation --shell));

どちらのバージョンもデフォルトで同じです。map { CODE BLOCK } ARRAY- 配列はすでに存在する変数でも匿名配列でもよく、ユーザーに適した方法で即座に生成されます。

リスト(1つ以上の一致)コンテキストで呼び出されると、正規表現は配列を返します。上記の例では、正規表現一致演算子(m/PATTERN/)はループ内の各要素に適用され、配列foreachの要素を順番に繰り返します(この例の配列は、xdotool getmouselocation --shell配列要素ごとに行が1つずつある出力です)。

他の方法もmap使用できる。呼び出し方法に応じて、スカラー値、配列、またはハッシュ値を返すことができます。これは変数に割り当てるか、他の関数で使用できます。

ところで、foreachandはforPerlの同義語でもあります。私が書いたすべての場所で/を使用して上記で使用したように配列(リスト)を繰り返すことができ、C foreachスタイルループのように使用することもできます。forforforeachfor ($i = 1; $i < 10; $i++)

xdotoolxrandr直接クエリ用のPerlモジュールがあります。

おすすめ記事