window最大化の制御(Electron)

Electron

長いので結論から。
個人的にはレンダラープロセスで完結できるFullScreen APIがおススメ。
パーツ単位でも最大化できるので便利です。
ただし、最小化に関してはレンダラープロセスでは手が出せないのでIPC使うことになります。

前提として標準のFrameは消してあります。

mainWindow = new BrowserWindow({ 
   frame: false
});

htmlのFullScreen APIを使う

html5で仕様が定まっているので非常にシンプルです。
Full Screenにする対象も全体ではなく、個別の要素単位で最大化できるので汎用性が高いです。

//最大化
maximizeButton.onclick = function(){
    // let contents = document.getElementById('contents');
    let contents = document.body;
    contents.requestFullscreen();
};

//最大化解除
exitFullScreenButton.onclick = function(){
    document.exitFullscreen();
};

後述するwindow.setFullScreen(false)でメインプロセスからFull Screenを解除することもできるが基本的にNG。おそらくrequestFullscreen用の内部パラメータが変化しないため、2度目以降のrequestFullscreen()が実行されなくなる。

windowにはenter-full-screenイベントが呼ばれる。
文字通りFull Screenになるが、windowをドラッグをしてもwindowサイズは戻らない。

メインプロセスからwindowをコントロールする

主に2通りあります。

  • window.setFullScreen(true)
  • window.maximize()

同じように使って問題ありませんが、少し違いがあります。
1つはsetFullScreenは文字通りフルスクリーン。
対して、maximizeはタスクバーを含まない領域に対して最大化されます。

また呼ばれるイベントもsetFullScreen()はenter-full-screenイベントが呼ばれますが、maximize()はフルスクリーンではないのでこのイベントは呼ばれません。なのにsetFullScreen(false)で元に戻る不思議。

実装

rendererプロセスから直接呼び出せないため、IPCでメインプロセスから呼び出します。

//renderer process

const {ipcRenderer} = require("electron");

maximizeButton.onclick = function(){
    ipcRenderer.invoke('setFullScreen');
};

exitFullScreenButton.onclick = function(){
    ipcRenderer.invoke('exitFullScreen');
};
const ipcMain = require('electron').ipcMain;
let mainWindow = new BrowserWindow({ frame: false });

ipcMain.handle("setFullScreen", () => {
   mainWindow.setFullScreen(true);
   // or
   // mainWindow.maximize();
});

ipcMain.handle("exitFullScreen", () => {
   mainWindow.setFullScreen(false);

   // restoreは機能しない
   // mainWindow.restore();
});

どちらも最大化後にwindowをドラッグしても最大化は解除されません。(windowサイズはそのままです)
なのでドラッグで解除したい場合は明示的にsetFullScreen(false)を呼び出してください。

cssで-webkit-app-regionを使う

アプリケーションのデフォルトフレームを消すと、windowの移動やリサイズができなくなるためよく使われます。

//.css

.header{
    -webkit-app-region: drag;
}
.headerButton{
    -webkit-app-region: no-drag;
}

簡単で便利なのですが、安易に行うと対象オブジェクトの制御を全てSystemに持っていかれますので注意が必要です。
具体的にはクリックイベントがアプリケーションまで降りてこず、途中でOS側の制御に取り込まれてしまいます。処理される内容もOS側でコントロールされているため、アプリケーション側からは手出しができなくなります。(windowsならDesktop Window Manager辺り?)

私が困ったのはドラッグ可能の領域をダブルクリックで最大化される事です。
アプリの外側の事象なので止められません。

しかも最大化の挙動が前述の方法とは異なります。
具体的には
・最大化なのでタスクバーは隠さない。
 つまりフルスクリーンではない。
・最大化解除にはwindow.restore()を使う。
 ※setFullScreen(false)では解除できない。
・ドラッグするとwindowサイズは元に戻る。
・maximizeイベントが呼ばれる。
 ※window.maximize()ではこのイベントは呼ばれない。

ネックなのは最大化解除の方法ですね。
前述のやり方と異なるため、混ぜて使うと管理する状態が複雑になります。
なのでwindowのドラッグ制御が必要なだけであれば、自力でメソッドを定義した方が管理しやすいと思います。

コメント