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