在 Chrome 中创建 windows 应用程序在启动时忽略边界?

Creating windows in Chrome App ignores bounds when launching?

我使用 background.js 脚本创建新的 windows,但是当我使用 chrome.app.window.create 方法设置边界并为 CreateWindowOptions 对象传递参数时它们是第一次使用,但每次我重新启动应用程序时都会被忽略。

在 OSX 上,似乎在 window 的 outerBounds 对象上创建回调后调用方法 setPositionsetSize 应用程序将响应到我试图设定的界限。但是,这似乎根本不适用于 Windows 10。

似乎我创建的 windows 在应用程序关闭时仍然存在。我不确定如何清除它们,尤其是当用户关闭应用程序时使用菜单或 OS 退出。有什么方法可以确保销毁或清除这些 windows,或强制 Chrome 应用程序设置我设置的边界而不恢复到以前的某个状态?

我创建的 windows 是 运行 PixiJS 如果这有什么区别的话。当关闭事件被触发时,我确实在 windows 上调用了一个 destroy 方法,但这没有影响。

这是我的背景脚本:

(function( global ) {

    "use strict";


    /* ----- VARS ----- */
    var displayInfo;
    var isMultiDisplay;

    var controlDisplayIndex;
    var controlBounds;
    var controlLoaded;
    var controlWindow;

    var gameDisplayIndex;
    var gameBounds;
    var gameLoaded;
    var gameWindow;


    /* ----- CONSTANTS ----- */
    var CONTROL_WIDTH = 1920;
    var CONTROL_HEIGHT = 1080;

    var GAME_WIDTH = 2160;
    var GAME_HEIGHT = 3840;

    var FRAME_OPTIONS = {
        type: "none"
    };


    /* ----- FUNCTIONS ----- */
    function init() {
        console.log( "background.js: init" );
        console.info( "background.js: ", chrome.app.window.getAll() );

        isMultiDisplay = false;

        controlLoaded = false;
        gameLoaded = false;

        loadDisplayInfo();

    };

    function loadDisplayInfo() {
        console.log( "background.js: loadDisplayInfo" );

        chrome.system.display.getInfo( onDisplayInfo );

    };

    function createWindows() {
        console.log( "background.js: createWindows" );

        isMultiDisplay = ( displayInfo.length > 0 );

        if ( isMultiDisplay ) {

            var i = 0;
            var length = 2;

            for ( i; i < length; i++ ) {

                if ( displayInfo[i].isPrimary )
                    controlDisplayIndex = i;
                else 
                    gameDisplayIndex = i;

            }

            gameBounds = {
                height: displayInfo[ gameDisplayIndex ].workArea.height,
                left: displayInfo[ gameDisplayIndex ].workArea.left,
                top: displayInfo[ gameDisplayIndex ].workArea.top,
                width: displayInfo[ gameDisplayIndex ].workArea.width
            };

            controlBounds = {
                height: displayInfo[ controlDisplayIndex ].workArea.height,
                left: displayInfo[ controlDisplayIndex ].workArea.left,
                top: displayInfo[ controlDisplayIndex ].workArea.top,
                width: displayInfo[ controlDisplayIndex ].workArea.width
            };

        } else {

            // This assumes single monitor is in landscape.
            gameBounds = {
                top: displayInfo[0].workArea.top,
                left: displayInfo[0].workArea.left,
                height: displayInfo[0].workArea.height,
                width: Math.floor( displayInfo[0].workArea.height * GAME_WIDTH / GAME_HEIGHT )
            };

            controlBounds = {
                top: displayInfo[0].workArea.top,
                left: displayInfo[0].workArea.left + gameBounds.width,
                width: gameBounds.width,
                height: Math.floor( gameBounds.width * CONTROL_HEIGHT / CONTROL_WIDTH )
            };

        }

        console.info( "Game Bounds:", gameDisplayIndex, gameBounds.left, gameBounds.top, gameBounds.width, gameBounds.height );
        console.info( "Control Bounds:", controlDisplayIndex, controlBounds.left, controlBounds.top, controlBounds.width, controlBounds.height );

        var state = ( isMultiDisplay ) ? "fullscreen" : "normal";

        // Game
        chrome.app.window.create( "window-game.html", {
            id: "gameWindow",
            bounds: gameBounds,
            frame: FRAME_OPTIONS,
            resizable: true,
            state: state
        }, onGameWindowCreated );

        // Control
        chrome.app.window.create( "window-control.html", {
            id: "controlWindow",
            bounds: controlBounds,
            frame: FRAME_OPTIONS,
            resizable: true,
            state: state
        }, onControlWindowCreated );

    };


    /* ----- EVENT LISTENERS ----- */
    function onLaunched() {
        console.log( "background.js: onLaunched" );

        init();

    };

    function onDisplayInfo( info ) {
        console.log( "background.js: onDisplayInfo" );

        displayInfo = info;
        createWindows();

    };

    function onControlWindowCreated( obj ) {
        console.log( "background.js: onControlWindowCreated", obj.id );

        controlLoaded = true;
        controlWindow = obj;

        controlWindow.outerBounds.setPosition( controlBounds.left, controlBounds.top );
        controlWindow.outerBounds.setSize( controlBounds.width, controlBounds.height );

        if ( isMultiDisplay ) controlWindow.fullscreen();

        //console.info( controlWindow.innerBounds.width, controlWindow.innerBounds.height );
        //console.info( controlWindow.outerBounds.width, controlWindow.outerBounds.height );

        controlWindow.onClosed.addListener( onControlWindowClosed );

    };

    function onControlWindowClosed() {
        console.log( "background.js: onControlWindowClosed" );

        controlWindow.onClosed.removeListener( onControlWindowClosed );
        controlWindow.destroy();
        controlWindow = undefined;

    };

    function onGameWindowCreated( obj ) {
        console.log( "background.js: onGameWindowCreated", obj.id );

        gameLoaded = true;
        gameWindow = obj;

        gameWindow.outerBounds.setPosition( gameBounds.left, gameBounds.top );
        gameWindow.outerBounds.setSize( gameBounds.width, gameBounds.height );

        if ( isMultiDisplay ) gameWindow.fullscreen();

        //console.info( gameWindow.innerBounds.width, gameWindow.innerBounds.height );
        //console.info( gameWindow.outerBounds.width, gameWindow.outerBounds.height );

        gameWindow.onClosed.addListener( onGameWindowClosed );

    };

    function onGameWindowClosed() {
        console.log( "background.js: onGameWindowClosed" );

        gameWindow.onClosed.removeListener( onGameWindowClosed );
        gameWindow.destroy();
        gameWindow = undefined;

    };


    /* ----- CALL ----- */
    chrome.app.runtime.onLaunched.addListener( onLaunched );

}( this ));

免责声明:我知道 Chrome 应用程序正在停产,但由于项目时间安排,我必须完成此应用程序,然后再考虑移植到 Electron 或替代方案。

当您创建 window 并在 CreateWindowOptions 对象中设置 id 属性 时,将保存该 window 的最后已知边界通过 Chrome Apps 平台并使用下一个 window 创建了相同的 ID。

这是 id 属性 上文档的描述:

Id to identify the window. This will be used to remember the size and position of the window and restore that geometry when a window with the same id is later opened. If a window with a given id is created while another window with the same id already exists, the currently opened window will be focused instead of creating a new window.

并根据outerBounds的描述属性:

Used to specify the initial position, initial size and constraints of the window (including window decorations such as the title bar and frame). If an id is also specified and a window with a matching id has been shown before, the remembered bounds will be used instead.

所以,解决方案是省略id 属性。如果你像我一样,需要在你的脚本中对 window 做进一步的事情,那么使用 create window 回调来为那个函数 return 参数分配一个变量。

例如:

var myWindow;

chrome.app.window.create( "window.html", options, function( obj ) {

    myWindow = obj;

    // Do Stuff with myWindow

} );

我想即使在回调之后尝试设置 window 的大小和位置也不是完全可靠的,正如我在 Windows 10 下尝试做一些事情时所证明的那样。

我唯一不知道的是,当您给 windows 一个 ID 时,Google Chrome 存储所有这些 window 数据的应用在哪里?有没有办法清除它(除了卸载应用程序)?