1/* 2 * Copyright (c) 2022-2023 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 emitter from '@ohos.events.emitter'; 18import display from '@ohos.display'; 19import Logger from '../util/Logger'; 20import { WindowColor, WindowEventId } from '../util/WindowConst'; 21 22const windowPoint = { 23 x: 50, // 窗口移动的起始坐标X 24 y: 250, // 窗口移动的起始坐标Y 25}; 26const WIDTH = 320; 27const HEIGHT = 240; 28const MOVE_X = 10; 29let MOVE_Y = 500; 30let MOVE_Y2 = 300; 31 32class WindowType { 33 moveToWidth: number; 34 moveToHeight: number; 35 setTouchable: boolean; 36 resetSizeWidth: number; 37 resetSizeHeight: number; 38 setPrivacyMode: boolean; 39 setBrightness: number; 40}; 41 42class WindowManger { 43 private tag: string = 'WindowManger'; 44 private startX: number = 0; // 窗口移动的起始坐标X 45 private startY: number = 0; // 窗口移动的起始坐标Y 46 private endX: number = MOVE_X; // 窗口移动的结束坐标X 47 private endY: number = MOVE_Y; // 窗口移动的结束坐标Y 48 private distanceX: number = 0; // 窗口在X轴上移动距离 49 private distanceY: number = 0; // 窗口在Y轴上移动距离 50 private windowWidth: number = 0; // 当前窗口宽度 51 private windowHeight: number = 0; // 当前窗口高度 52 53 initMainWindow(windowStage: window.WindowStage) { 54 windowStage.getMainWindow((err, data) => { 55 if (err.code) { 56 Logger.error(this.tag, 'Failed to obtain the main window. Cause: ' + JSON.stringify(err)); 57 return; 58 } 59 ; 60 let mainWindow = data; 61 // 窗口规避区域 62 mainWindow.on('avoidAreaChange', ({type, area}) => { 63 if (type === window.AvoidAreaType.TYPE_SYSTEM) { 64 AppStorage.setOrCreate<number>('topHeight', area.topRect.height); 65 AppStorage.setOrCreate<number>('topWidth', area.topRect.width); 66 } 67 }); 68 mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM); 69 // 设置主窗口沉浸式 70 mainWindow.setWindowLayoutFullScreen(true); 71 // 设置主窗口导航栏、状态栏、文字颜色等属性 72 const sysBarProps: window.SystemBarProperties = { 73 statusBarColor: WindowColor.statusBarColor, 74 navigationBarColor: WindowColor.navigationBarColor, 75 statusBarContentColor: WindowColor.statusBarContentColor, 76 navigationBarContentColor: WindowColor.navigationBarContentColor 77 }; 78 // 加载状态变量 79 mainWindow.setWindowSystemBarProperties(sysBarProps); 80 }); 81 } 82 83 updateDisplay() { 84 try { 85 const displayClass = display.getDefaultDisplaySync(); 86 this.windowWidth = displayClass.width; 87 this.windowHeight = displayClass.height; 88 MOVE_Y = this.windowHeight / 2; 89 this.endY = MOVE_Y; 90 } catch (err) { 91 Logger.error('Failed to obtain the default display object. Code: ' + JSON.stringify(err)); 92 } 93 } 94 95 async initSubWindow(windowStage, windowAttribute, isPortrait) { 96 // 创建应用子窗口 97 let subWindow = await windowStage.createSubWindow('mySubWindow'); 98 subWindow.on('avoidAreaChange', ({type, area}) => { 99 if (type === window.AvoidAreaType.TYPE_SYSTEM) { 100 AppStorage.setOrCreate<number>('topHeight', area.topRect.height); 101 AppStorage.setOrCreate<number>('bottomHeight', area.bottomRect.height); 102 } 103 }); 104 try { 105 subWindow.setWindowFocusable(true, (err) => { 106 if (err.code) { 107 console.error('Failed to set the window to be focusable. Cause:' + JSON.stringify(err)); 108 return; 109 } 110 console.info('Succeeded in setting the window to be focusable.'); 111 }); 112 subWindow.on('windowEvent', (data) => { 113 console.info('Sub Window event happened. Event:' + JSON.stringify(data)); 114 let message = null; 115 switch (JSON.stringify(data)) { 116 case '1': 117 message = $r('app.string.foreground'); 118 break; 119 case '2': 120 message = $r('app.string.get_focus'); 121 break; 122 case '3': 123 message = $r('app.string.lose_focus'); 124 break; 125 case '4': 126 message = $r('app.string.background'); 127 break; 128 default: 129 message = $r('app.string.unknown'); 130 break; 131 } 132 AppStorage.SetOrCreate('focusText', message); 133 }); 134 } catch (exception) { 135 console.error('Failed to register callback. Cause: ' + JSON.stringify(exception)); 136 } 137 ; 138 139 try { 140 windowStage.on('windowStageEvent', (data) => { 141 console.info('Succeeded in enabling the listener for window stage event changes. Data: ' + 142 JSON.stringify(data)); 143 }); 144 } catch (exception) { 145 console.error('Failed to enable the listener for window stage event changes. Cause:' + 146 JSON.stringify(exception)); 147 } 148 ; 149 150 Logger.info('show'); 151 subWindow.resize(vp2px(WIDTH), vp2px(HEIGHT)); 152 if (isPortrait) { 153 subWindow.moveWindowTo(MOVE_X, MOVE_Y); 154 } else { 155 this.updateDisplay(); 156 subWindow.moveWindowTo(MOVE_X, MOVE_Y2); 157 } 158 subWindow.setUIContent('pages/SubWindowPage'); 159 subWindow.setWindowTouchable(true); 160 subWindow.showWindow(); 161 162 // onTouch的坐标绑定 163 let innerEvent = { 164 eventId: WindowEventId.SUB_WINDOW_INNER_EVENT_ID 165 }; 166 let callback = (eventData) => { 167 Logger.info(this.tag, 'onTouchEventData' + eventData.data.x); 168 if (!this.startX || !this.startY || eventData.data.type === 0) { 169 this.startX = eventData.data.x; 170 this.startY = eventData.data.y; 171 return; 172 } 173 ; 174 this.distanceX = eventData.data.x - this.startX; 175 this.distanceY = eventData.data.y - this.startY; 176 this.endX += vp2px(this.distanceX); 177 this.endY += vp2px(this.distanceY); 178 this.startX = eventData.data.x; 179 this.startY = eventData.data.y; 180 if (this.endX > 0 && this.endX < this.windowWidth - vp2px(WIDTH) && this.endY > AppStorage.get('topHeight') 181 && this.endY < this.windowHeight - vp2px(HEIGHT)) { 182 subWindow.moveWindowTo(this.endX, this.endY); 183 } 184 ; 185 }; 186 emitter.on(innerEvent, callback); 187 } 188 189 async setSubWindowAttribute(windowStage: window.WindowStage, windowAttribute: WindowType) { 190 let subWindow: window.Window = await windowStage.getMainWindow(); 191 await subWindow.moveWindowTo(windowAttribute.moveToWidth, windowAttribute.moveToHeight); 192 // 设置子窗口为可触状态 193 await subWindow.setWindowTouchable(windowAttribute.setTouchable); 194 // 设置子窗口的大小 195 await subWindow.resize(windowAttribute.resetSizeWidth, windowAttribute.resetSizeHeight); 196 // 设置子窗口亮度 197 await subWindow.setWindowBrightness(windowAttribute.setBrightness); 198 // 设置子窗口为隐私模式 199 await subWindow.setWindowPrivacyMode(windowAttribute.setPrivacyMode); 200 } 201 202 changeWindowDirection(windowStage: window.WindowStage, orientation: window.Orientation) { 203 windowStage.getMainWindow((err, data) => { 204 if (err.code) { 205 Logger.error(this.tag, 'Failed to change the window: ' + JSON.stringify(err)); 206 return; 207 } 208 data.setPreferredOrientation(orientation); 209 }); 210 } 211 212 destorySubWindowCallback() { 213 this.startX = 0; 214 this.startY = 0; 215 this.endX = MOVE_X; 216 this.endY = MOVE_Y; 217 this.distanceX = 0; 218 this.distanceY = 0; 219 } 220} 221 222export default new WindowManger();