1/** 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import window from '@ohos.window'; 17import display from '@ohos.display'; 18import { Log } from '../utils/Log'; 19 20const TAG = 'DisplayManager: '; 21 22export class DisplayManager { 23 private readonly MAIN_WINDOW_PREFIX = 'customMainWindow_'; 24 private readonly DEFAULT_MAIN_WINDOW_PAGE = 'pages/SubDisplayWallpaperPage'; 25 26 public defaultDisplay: display.Display = undefined; 27 private displayDevices: Array<display.Display> = []; 28 29 private constructor() { 30 Log.showInfo(TAG, 'constructor called.'); 31 this.loadDefaultDisplay(); 32 this.loadAllDisplays(); 33 34 this.initDisplayChangeListener(); 35 } 36 37 public static getInstance(): DisplayManager { 38 return globalThis.DisplayManager ??= new DisplayManager(); 39 } 40 41 private loadDefaultDisplay() { 42 try { 43 this.defaultDisplay = display.getDefaultDisplaySync(); 44 Log.showInfo(TAG, 'loadDefaultDisplay. defaultDisplay id: ' + this.defaultDisplay?.id); 45 } catch (err) { 46 Log.showError(TAG, 'loadDefaultDisplay occur error. errInfo: ' + JSON.stringify(err)); 47 } 48 } 49 50 private async loadAllDisplays() { 51 let displays: Array<display.Display> = await display.getAllDisplays(); 52 for (let display of displays) { 53 if (this.displayDevices.findIndex(item => item.id === display.id) < 0) { 54 Log.showInfo(TAG, 'new display added. detail: ' + JSON.stringify(display)); 55 this.displayDevices.push(display); 56 this.createMainWindow(display); 57 } 58 } 59 } 60 61 private initDisplayChangeListener() { 62 display.on('add', displayId => { 63 Log.showInfo(TAG, 'add new display. id: ' + JSON.stringify(displayId)); 64 this.loadAllDisplays(); 65 }) 66 67 display.on('remove', displayId => { 68 Log.showInfo(TAG, 'remove display. id: ' + JSON.stringify(displayId)); 69 let delIndex: number = this.displayDevices.findIndex(item => item.id === displayId); 70 if (delIndex > 0) { 71 this.destroyMainWindow(displayId); 72 this.displayDevices.splice(delIndex, 1); 73 } 74 }) 75 } 76 77 /** 78 * 在指定屏幕上创建主window(新屏幕插入时,默认桌面窗口,不支持隐藏;屏幕拔出时,隐藏销毁本窗口) 79 * @param display 80 */ 81 private createMainWindow(display: display.Display) { 82 if (display.id === this.defaultDisplay?.id) { 83 //主屏不需要创建主窗口 84 return; 85 } 86 window.createWindow({ 87 ctx: globalThis.desktopContext, 88 name: this.MAIN_WINDOW_PREFIX + display.id, 89 windowType: window.WindowType.TYPE_DESKTOP, 90 displayId: display.id 91 }).then((resultWindow: window.Window) => { 92 resultWindow.resize(display.width, display.height); 93 resultWindow.setWindowMode(window.WindowMode.FULLSCREEN); 94 resultWindow.setUIContent(this.DEFAULT_MAIN_WINDOW_PAGE); 95 Log.showInfo(TAG, `create main window ${display.id} success.`); 96 97 resultWindow.showWithAnimation(); 98 }).catch(err => { 99 Log.showError(TAG, 'create main window failed. reason: ' + JSON.stringify(err)); 100 }) 101 } 102 103 private findWindow(displayId: number): window.Window { 104 let resultWindow = undefined; 105 try { 106 resultWindow = window.findWindow(this.MAIN_WINDOW_PREFIX + displayId); 107 } catch (err) { 108 Log.showError(TAG, 'findWindow occur err. errInfo: ' + JSON.stringify(err)); 109 } 110 return resultWindow; 111 } 112 113 114 private destroyMainWindow(displayId: number) { 115 if (displayId === this.defaultDisplay?.id) { 116 return; 117 } 118 let resultWindow = this.findWindow(displayId); 119 if (resultWindow?.isWindowShowing()) { 120 resultWindow.hideWithAnimation(); 121 } 122 resultWindow?.destroyWindow(); 123 Log.showInfo(TAG, `destroy main window ${displayId} success.`); 124 } 125 126 public destroySubDisplayWindow() { 127 for (let display of this.displayDevices) { 128 this.destroyMainWindow(display.id); 129 } 130 display.off('add'); 131 display.off('remove'); 132 } 133}