MATLAB でモニターの座標を取得する

MATLABでプロットなどする時に、PC環境つまりモニター・ディスプレイの構成によってFigureの位置が異なってしまうことがある。

MATLABにはモニターの位置を取得することができるので、それを活用するとある程度はFigureの位置を制御できる。

最近、xrdp経由でLinuxのデスクトップ環境を使っているが、この場合素のWindowsで使う場合とモニター座標が異なるらしい。

例えばWindowsで

moniInfo = groot;

とすると以下のようになる。

この場合モニター・ディスプレイは物理的に二つあって、MoniterPositionがそれを反映している。

>> moniInfo

moniInfo = 

  Graphics Root のプロパティ:

          CurrentFigure: [1×1 Figure]
    ScreenPixelsPerInch: 96
             ScreenSize: [1 1 1920 1080]
       MonitorPositions: [2×4 double]
                  Units: 'pixels'

ところが、xrdp経由のLinux上のMATLABでは

>> moniInfo

moniInfo = 

  Graphics Root のプロパティ:

          CurrentFigure: [1×1 Figure]
    ScreenPixelsPerInch: 80
             ScreenSize: [1 1 3200 900]
       MonitorPositions: [1 1 3200 900]
                  Units: 'pixels'

となる。

素のWindowsと異なるのが、ScreenPixelPerInch、ScreenSize, MoniterPositons の三つある。

スクリーン・サイズが異なるのはScreenPixelPerInchが80になっているためだろう。 たとえばScreenSizeが3200×900になっているが、これをScreenPixelPerInchを96相当に変換するなら、3840×1080となる。 3840は1920の2倍なので、pixel数は正しい。

ただし、MonitorPositionsは横幅が大きい一枚のモニター・ディスプレイとして認識されているようだ。 これはxrdpの仕様上しかたのないと推測される (物理的なモニター・サイズを授受しない仕様なのだと思われる)。 (NativeなLinux上で動かす場合は、おそらく物理的なモニターサイズを取得できるので、素のWindows上と同様の結果を返すのではないか。←あくまで推測。)

以上のことから、xrdp経由でもそれっぽい位置にfigureを配置させる場合は以下のようなコードになる。

下の例ではx, y座標はfigure全体が一つのモニターの中央になるように計算している。 また、モニターが複数あっても grootで取得された1番目のモニターに配置する。

figh_101 = figure(101);

x = 0:1e-2:2*pi;
y = sin(x);

plot(x, y)

moniInfo = groot;

fig_W =  800 * moniInfo.ScreenPixelsPerInch / 96; % in pixels
fig_H =  600 * moniInfo.ScreenPixelsPerInch / 96;

if size(moniInfo.MonitorPositions, 1) < 2 % display 数が1つの場合(xrdp経由の場合など)
    if moniInfo.MonitorPositions(1,3) * 92 / moniInfo.ScreenPixelsPerInch > 2000
        % monitor 横幅が2000 pixelより大きい場合は半分にする
        moniterRight = moniInfo.MonitorPositions(1,3) / 2;
    end
else
    moniterRight = moniInfo.MonitorPositions(1,3) ;
end
moniterLeft    = moniInfo.MonitorPositions(1,1);
moniterTop     = moniInfo.MonitorPositions(1,4);
moniterBottom  = moniInfo.MonitorPositions(1,2);


fig_X = moniterLeft   + (moniterRight - fig_W) / 2;
fig_Y = moniterBottom + (moniterTop   - fig_H) / 2;
figh_101.Position = [fig_X, fig_Y, fig_W, fig_H];