16e80583aSopenharmony_ci/**
26e80583aSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
36e80583aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
46e80583aSopenharmony_ci * you may not use this file except in compliance with the License.
56e80583aSopenharmony_ci * You may obtain a copy of the License at
66e80583aSopenharmony_ci *
76e80583aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
86e80583aSopenharmony_ci *
96e80583aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
106e80583aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
116e80583aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126e80583aSopenharmony_ci * See the License for the specific language governing permissions and
136e80583aSopenharmony_ci * limitations under the License.
146e80583aSopenharmony_ci */
156e80583aSopenharmony_ci
166e80583aSopenharmony_ciimport window from '@ohos.window';
176e80583aSopenharmony_ciimport display from '@ohos.display';
186e80583aSopenharmony_ciimport { Log } from '../utils/Log';
196e80583aSopenharmony_ci
206e80583aSopenharmony_ciconst TAG = 'DisplayManager: ';
216e80583aSopenharmony_ci
226e80583aSopenharmony_ciexport class DisplayManager {
236e80583aSopenharmony_ci  private readonly MAIN_WINDOW_PREFIX = 'customMainWindow_';
246e80583aSopenharmony_ci  private readonly DEFAULT_MAIN_WINDOW_PAGE = 'pages/SubDisplayWallpaperPage';
256e80583aSopenharmony_ci
266e80583aSopenharmony_ci  public defaultDisplay: display.Display = undefined;
276e80583aSopenharmony_ci  private displayDevices: Array<display.Display> = [];
286e80583aSopenharmony_ci
296e80583aSopenharmony_ci  private constructor() {
306e80583aSopenharmony_ci    Log.showInfo(TAG, 'constructor called.');
316e80583aSopenharmony_ci    this.loadDefaultDisplay();
326e80583aSopenharmony_ci    this.loadAllDisplays();
336e80583aSopenharmony_ci
346e80583aSopenharmony_ci    this.initDisplayChangeListener();
356e80583aSopenharmony_ci  }
366e80583aSopenharmony_ci
376e80583aSopenharmony_ci  public static getInstance(): DisplayManager {
386e80583aSopenharmony_ci    return globalThis.DisplayManager ??= new DisplayManager();
396e80583aSopenharmony_ci  }
406e80583aSopenharmony_ci
416e80583aSopenharmony_ci  private loadDefaultDisplay() {
426e80583aSopenharmony_ci    try {
436e80583aSopenharmony_ci      this.defaultDisplay = display.getDefaultDisplaySync();
446e80583aSopenharmony_ci      Log.showInfo(TAG, 'loadDefaultDisplay. defaultDisplay id: ' + this.defaultDisplay?.id);
456e80583aSopenharmony_ci    } catch (err) {
466e80583aSopenharmony_ci      Log.showError(TAG, 'loadDefaultDisplay occur error. errInfo: ' + JSON.stringify(err));
476e80583aSopenharmony_ci    }
486e80583aSopenharmony_ci  }
496e80583aSopenharmony_ci
506e80583aSopenharmony_ci  private async loadAllDisplays() {
516e80583aSopenharmony_ci    let displays: Array<display.Display> = await display.getAllDisplays();
526e80583aSopenharmony_ci    for (let display of displays) {
536e80583aSopenharmony_ci      if (this.displayDevices.findIndex(item => item.id === display.id) < 0) {
546e80583aSopenharmony_ci        Log.showInfo(TAG, 'new display added. detail: ' + JSON.stringify(display));
556e80583aSopenharmony_ci        this.displayDevices.push(display);
566e80583aSopenharmony_ci        this.createMainWindow(display);
576e80583aSopenharmony_ci      }
586e80583aSopenharmony_ci    }
596e80583aSopenharmony_ci  }
606e80583aSopenharmony_ci
616e80583aSopenharmony_ci  private initDisplayChangeListener() {
626e80583aSopenharmony_ci    display.on('add', displayId => {
636e80583aSopenharmony_ci      Log.showInfo(TAG, 'add new display. id: ' + JSON.stringify(displayId));
646e80583aSopenharmony_ci      this.loadAllDisplays();
656e80583aSopenharmony_ci    })
666e80583aSopenharmony_ci
676e80583aSopenharmony_ci    display.on('remove', displayId => {
686e80583aSopenharmony_ci      Log.showInfo(TAG, 'remove display. id: ' + JSON.stringify(displayId));
696e80583aSopenharmony_ci      let delIndex: number = this.displayDevices.findIndex(item => item.id === displayId);
706e80583aSopenharmony_ci      if (delIndex > 0) {
716e80583aSopenharmony_ci        this.destroyMainWindow(displayId);
726e80583aSopenharmony_ci        this.displayDevices.splice(delIndex, 1);
736e80583aSopenharmony_ci      }
746e80583aSopenharmony_ci    })
756e80583aSopenharmony_ci  }
766e80583aSopenharmony_ci
776e80583aSopenharmony_ci  /**
786e80583aSopenharmony_ci   * 在指定屏幕上创建主window(新屏幕插入时,默认桌面窗口,不支持隐藏;屏幕拔出时,隐藏销毁本窗口)
796e80583aSopenharmony_ci   * @param display
806e80583aSopenharmony_ci   */
816e80583aSopenharmony_ci  private createMainWindow(display: display.Display) {
826e80583aSopenharmony_ci    if (display.id === this.defaultDisplay?.id) {
836e80583aSopenharmony_ci      //主屏不需要创建主窗口
846e80583aSopenharmony_ci      return;
856e80583aSopenharmony_ci    }
866e80583aSopenharmony_ci    window.createWindow({
876e80583aSopenharmony_ci      ctx: globalThis.desktopContext,
886e80583aSopenharmony_ci      name: this.MAIN_WINDOW_PREFIX + display.id,
896e80583aSopenharmony_ci      windowType: window.WindowType.TYPE_DESKTOP,
906e80583aSopenharmony_ci      displayId: display.id
916e80583aSopenharmony_ci    }).then((resultWindow: window.Window) => {
926e80583aSopenharmony_ci      resultWindow.resize(display.width, display.height);
936e80583aSopenharmony_ci      resultWindow.setWindowMode(window.WindowMode.FULLSCREEN);
946e80583aSopenharmony_ci      resultWindow.setUIContent(this.DEFAULT_MAIN_WINDOW_PAGE);
956e80583aSopenharmony_ci      Log.showInfo(TAG, `create main window ${display.id} success.`);
966e80583aSopenharmony_ci
976e80583aSopenharmony_ci      resultWindow.showWithAnimation();
986e80583aSopenharmony_ci    }).catch(err => {
996e80583aSopenharmony_ci      Log.showError(TAG, 'create main window failed. reason: ' + JSON.stringify(err));
1006e80583aSopenharmony_ci    })
1016e80583aSopenharmony_ci  }
1026e80583aSopenharmony_ci
1036e80583aSopenharmony_ci  private findWindow(displayId: number): window.Window {
1046e80583aSopenharmony_ci    let resultWindow = undefined;
1056e80583aSopenharmony_ci    try {
1066e80583aSopenharmony_ci      resultWindow = window.findWindow(this.MAIN_WINDOW_PREFIX + displayId);
1076e80583aSopenharmony_ci    } catch (err) {
1086e80583aSopenharmony_ci      Log.showError(TAG, 'findWindow occur err. errInfo: ' + JSON.stringify(err));
1096e80583aSopenharmony_ci    }
1106e80583aSopenharmony_ci    return resultWindow;
1116e80583aSopenharmony_ci  }
1126e80583aSopenharmony_ci
1136e80583aSopenharmony_ci
1146e80583aSopenharmony_ci  private destroyMainWindow(displayId: number) {
1156e80583aSopenharmony_ci    if (displayId === this.defaultDisplay?.id) {
1166e80583aSopenharmony_ci      return;
1176e80583aSopenharmony_ci    }
1186e80583aSopenharmony_ci    let resultWindow = this.findWindow(displayId);
1196e80583aSopenharmony_ci    if (resultWindow?.isWindowShowing()) {
1206e80583aSopenharmony_ci      resultWindow.hideWithAnimation();
1216e80583aSopenharmony_ci    }
1226e80583aSopenharmony_ci    resultWindow?.destroyWindow();
1236e80583aSopenharmony_ci    Log.showInfo(TAG, `destroy main window ${displayId} success.`);
1246e80583aSopenharmony_ci  }
1256e80583aSopenharmony_ci
1266e80583aSopenharmony_ci  public destroySubDisplayWindow() {
1276e80583aSopenharmony_ci    for (let display of this.displayDevices) {
1286e80583aSopenharmony_ci      this.destroyMainWindow(display.id);
1296e80583aSopenharmony_ci    }
1306e80583aSopenharmony_ci    display.off('add');
1316e80583aSopenharmony_ci    display.off('remove');
1326e80583aSopenharmony_ci  }
1336e80583aSopenharmony_ci}