• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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 */
15import deviceInfo from '@ohos.deviceInfo';
16import window from '@ohos.window';
17import createOrGet from '../utils/SingleInstanceUtils';
18import { Log } from '../utils/Log';
19import { BroadcastConstants } from '../constants/BroadcastConstants';
20import { WindowConstants } from '../constants/WindowConstants';
21import { getResourceString } from '../utils/ResourceUtils';
22import { Broadcast } from '../utils/Broadcast';
23
24export enum ColumnSize {
25    COLUMN_TWO = 2,
26    COLUMN_FOUR = 4,
27    COLUMN_SIX = 6,
28    COLUMN_EIGHT = 8,
29    COLUMN_TWELVE = 12
30}
31
32enum ScreenWidth {
33    WIDTH_MEDIUM = 520,
34    WIDTH_LARGE = 840
35}
36
37enum WindowMode {
38    UNDEFINED = 1,
39    FULL_SCREEN,
40    PRIMARY,
41    SECONDARY,
42    FLOATING
43}
44
45const TAG = "ScreenManager"
46
47const APP_KEY_SCREEN_MANAGER = 'app_key_screen_manager';
48
49const SCREEN_ORIENTATION_HORIZONTAL: string = 'isHorizontal';
50const SCREEN_SIDEBAR: string = 'isSidebar';
51
52const COLUMN_MARGIN: number = 12;
53const COLUMN_GUTTER: number = 12;
54
55class ScreenManager {
56    readonly ON_WIN_SIZE_CHANGED = 'on_win_size_changed';
57    readonly ON_LEFT_BLANK_CHANGED = 'on_left_blank_changed';
58    readonly DEFAULT_WIDTH: number = 1920;
59    readonly DEFAULT_HEIGHT: number = 1080;
60    readonly SPLIT_THRESHOLD = 1.7;
61    private winWidth = 0.0;
62    private winHeight = 0.0;
63    private statusBarHeight = 0;
64    private naviBarHeight = 0;
65    private leftBlank: [number, number, number, number] = [0, 0, 0, 0];
66    private broadcast: Broadcast = new Broadcast();
67    private events = [];
68    private mainWindow: window.Window = undefined;
69
70    // Default orientation
71    private horizontal = deviceInfo.deviceType == 'phone' || deviceInfo.deviceType == 'default' ? false : true;
72
73    // Default sidebar
74    private sidebar = deviceInfo.deviceType == 'phone' || deviceInfo.deviceType == 'default' ? false : true;
75    private windowMode = WindowMode.UNDEFINED;
76
77    constructor() {
78        Log.info(TAG, 'constructor');
79    }
80
81    async initializationSize(win): Promise<void> {
82        this.mainWindow = win;
83        this.setMainWindow(win)
84        await this.checkWindowMode();
85        this.getWindowProperties(win);
86    }
87
88    /**
89     * Add Listeners
90     *
91     * @param event
92     * @param fn
93     */
94    on(event, fn) {
95        this.broadcast.on(event, fn);
96    }
97
98    /**
99     * Delete Listeners
100     *
101     * @param event
102     * @param fn
103     */
104    off(event, fn) {
105        this.broadcast.off(event, fn);
106    }
107
108    private emit(event, argument: any[]) {
109        this.broadcast.emit(event, argument);
110    }
111
112    private isLeftBlankInitialized(): boolean {
113        return this.leftBlank[0] != 0 || this.leftBlank[1] != 0 || this.leftBlank[2] != 0 || this.leftBlank[3] != 0;
114    }
115
116    // Unit:vp
117    getWinWidth(): number {
118        return px2vp(this.winWidth);
119    }
120
121    // Unit:vp
122    getWinHeight(): number {
123        return px2vp(this.winHeight);
124    }
125
126    getStatusBarHeight(): number {
127        return px2vp(this.statusBarHeight);
128    }
129
130    getNaviBarHeight(): number {
131        return px2vp(this.naviBarHeight);
132    }
133
134    async initWindowMode() {
135        Log.debug(TAG, `start to initialize photos application window mode: ${this.windowMode}`);
136    }
137
138    isSplitMode(): boolean {
139        return (WindowMode.PRIMARY == this.windowMode || WindowMode.SECONDARY == this.windowMode)
140    }
141
142    async checkWindowMode() {
143        let before = this.windowMode;
144        let mode = await globalThis.photosWindowStage.getWindowMode();
145        Log.info(TAG, `photos application before/current window mode: ${before}/${mode}`);
146
147        if (before == mode) {
148            return;
149        }
150        this.windowMode = mode;
151        if (WindowMode.FULL_SCREEN == this.windowMode) {
152            await this.setFullScreen();
153        } else {
154            this.setSplitScreen();
155        }
156    }
157
158    private setMainWindow(win: window.Window) {
159        Log.debug(TAG, 'setMainWindow');
160        win.on('windowSizeChange', (data) => {
161            Log.debug(TAG, `windowSizeChange ${JSON.stringify(data)}`);
162            this.checkWindowMode()
163            this.onWinSizeChanged(data);
164        })
165    }
166
167    private getWindowProperties(win: window.Window) {
168        Log.debug(TAG, 'getWindowProperties');
169        try {
170            let properties = win.getWindowProperties();
171            if(properties.windowRect.width !== 0 && properties.windowRect.height !== 0){
172                this.winWidth = properties.windowRect.width;
173                this.winHeight = properties.windowRect.height;
174            }
175            Log.debug(TAG, `this.winWidth = ${this.winWidth} this.winHeight = ${this.winHeight}`);
176        } catch (exception) {
177            console.error('Failed to obtain the window properties. Cause: ' + JSON.stringify(exception));
178        }
179    }
180
181    private async setFullScreen() {
182        let topWindow: any = AppStorage.Get(WindowConstants.MAIN_WINDOW);
183        Log.debug(TAG, 'getTopWindow start');
184        try {
185            await topWindow.setLayoutFullScreen(true)
186            Log.debug(TAG, 'setFullScreen true Succeeded');
187            await this.hideStatusBar(topWindow);
188        } catch (err) {
189            Log.error(TAG, `setFullScreen err: ${err}`);
190        }
191    }
192
193    setSplitScreen() {
194        try {
195            this.statusBarHeight = 0;
196            this.naviBarHeight = 0;
197            this.leftBlank = [0, 0, 0, 0];
198            AppStorage.SetOrCreate(BroadcastConstants.LEFT_BLANK, this.leftBlank);
199        } catch (err) {
200            Log.error(TAG, `setSplitScreen err: ${err}`);
201        }
202    }
203
204    private async hideStatusBar(topWindow: any) {
205        Log.debug(TAG, 'hideStatusBar start');
206        let names = ['navigation'];
207        Log.debug(TAG, `getTopWindow names: ${names} end`);
208        try {
209            await topWindow.setSystemBarEnable(names)
210            Log.debug(TAG, 'hideStatusBar Succeeded');
211            let data = await topWindow.getAvoidArea(0)
212            Log.debug(TAG, `Succeeded in obtaining the area. Data: ${JSON.stringify(data)}`);
213            this.onLeftBlankChanged(data);
214            let barColor = await getResourceString($r('app.color.default_background_color'));
215            let barContentColor = await getResourceString($r('app.color.default_bar_content_color'));
216            if (!barColor) {
217                barColor = '#00FFFFFF';
218            }
219            if (!barContentColor) {
220                barContentColor = '#FF000000';
221            }
222            await topWindow.setSystemBarProperties({
223                navigationBarColor: barColor,
224                navigationBarContentColor: barContentColor
225            });
226            Log.info(TAG, 'setStatusBarColor done');
227        } catch (err) {
228            Log.error(TAG, `hideStatusBar err: ${err}`);
229        }
230    }
231
232    async setNavigationBarColor(barColor: string, barContentColor: string) {
233        Log.debug(TAG, 'setNavigationBarColor start');
234        let topWindow: any = AppStorage.Get(WindowConstants.MAIN_WINDOW);
235        try {
236            topWindow.setSystemBarProperties(
237                {
238                    navigationBarColor: barColor,
239                    navigationBarContentColor: barContentColor
240                },
241                () => Log.info(TAG, 'setStatusBarColor done')
242            );
243        } catch (err) {
244            Log.error(TAG, `setNavigationBarColor err: ${err}`);
245        }
246    }
247
248    setSystemUi(isShowBar: boolean): void {
249        Log.debug(TAG, 'setSystemUi start');
250        let topWindow: any = AppStorage.Get(WindowConstants.MAIN_WINDOW);
251        Log.debug(TAG, 'getTopWindow start');
252        let names = ["navigation"];
253        if (!isShowBar) {
254            names = [];
255        }
256        Log.debug(TAG, `getTopWindow names: ${names} end`);
257        try {
258            topWindow.setSystemBarEnable(names, () => {
259                Log.debug(TAG, 'setFullScreen Succeeded');
260                if (isShowBar) {
261                    topWindow.getAvoidArea(0, (err, data) => {
262                        Log.info(TAG, 'Succeeded in obtaining the area. Data:' + JSON.stringify(data));
263                        this.onLeftBlankChanged(data);
264                    });
265                }
266            })
267        } catch (err) {
268            Log.error(TAG, `setSystemUi err: ${err}`);
269        }
270    }
271
272    private onLeftBlankChanged(area) {
273        if (area == null || area == undefined || area.bottomRect.height == 0) {
274            return;
275        }
276        let leftBlankBefore = {
277            status: this.statusBarHeight,
278            navi: this.naviBarHeight
279        };
280        this.statusBarHeight = 0;
281        this.naviBarHeight = area.bottomRect.height;
282        this.leftBlank = [this.leftBlank[0], this.leftBlank[1], this.leftBlank[2], area.bottomRect.height];
283        if (leftBlankBefore.status != this.statusBarHeight || leftBlankBefore.navi != this.naviBarHeight) {
284            Log.info(TAG, `leftBlank changed: ${JSON.stringify(leftBlankBefore)}-${JSON.stringify(this.leftBlank)}`)
285            AppStorage.SetOrCreate(BroadcastConstants.LEFT_BLANK, this.leftBlank);
286        }
287    }
288
289    private onWinSizeChanged(size) {
290        Log.info(TAG, `onWinSizeChanged ${JSON.stringify(size)}`);
291        if (size == null || size == undefined) {
292            return;
293        }
294        let sizeBefore = {
295            width: this.winWidth,
296            height: this.winHeight
297        };
298        this.winWidth = size.width;
299        this.winHeight = size.height;
300
301
302        if (sizeBefore.width != this.winWidth || sizeBefore.height != this.winHeight) {
303            Log.info(TAG, `winSize changed: ${JSON.stringify(sizeBefore)} -> ${JSON.stringify(size)}`);
304            this.emit(screenManager.ON_WIN_SIZE_CHANGED, [size]);
305        }
306    }
307
308    private onRotationAngleChanged(angle) {
309        if (angle == null || angle == undefined) {
310            return;
311        }
312
313        if (angle == 0) {
314            this.horizontal = false;
315        } else {
316            this.horizontal = true;
317        }
318        AppStorage.SetOrCreate(SCREEN_ORIENTATION_HORIZONTAL, this.horizontal);
319    }
320
321    isHorizontal(): boolean {
322        if (AppStorage.Get(SCREEN_ORIENTATION_HORIZONTAL) == null) {
323            AppStorage.SetOrCreate(SCREEN_ORIENTATION_HORIZONTAL, this.horizontal);
324        }
325        return AppStorage.Get(SCREEN_ORIENTATION_HORIZONTAL);
326    }
327
328    isSidebar(): boolean {
329        if (AppStorage.Get(SCREEN_SIDEBAR) == null) {
330            AppStorage.SetOrCreate(SCREEN_SIDEBAR, this.sidebar);
331        }
332        return AppStorage.Get(SCREEN_SIDEBAR);
333    }
334
335    getColumnsWidth(count: number): number {
336        let columns = this.getScreenColumns()
337        Log.info(TAG, `getColumnsWidth count is ${count} colunms is ${columns}`);
338        let columnWidth = (px2vp(this.winWidth) - COLUMN_MARGIN) / columns;
339        return columnWidth * count - COLUMN_GUTTER;
340    }
341
342    getScreenColumns(): number {
343        let width = px2vp(this.winWidth)
344        if (width < ScreenWidth.WIDTH_MEDIUM) {
345            return ColumnSize.COLUMN_FOUR;
346        } else if (width >= ScreenWidth.WIDTH_MEDIUM && width < ScreenWidth.WIDTH_LARGE) {
347            return ColumnSize.COLUMN_EIGHT;
348        } else {
349            return ColumnSize.COLUMN_TWELVE;
350        }
351    }
352
353    setKeepScreenOn() {
354        Log.info(TAG, 'setKeepScreenOn start');
355        let topWindow: any = AppStorage.Get('mainWindow');
356        try {
357            topWindow.setKeepScreenOn(true, () => Log.info(TAG, 'setKeepScreenOn Succeeded'))
358        } catch (err) {
359            Log.error(TAG, `setKeepScreenOn err: ${err}`);
360        }
361    }
362
363    setKeepScreenOff() {
364        Log.info(TAG, 'setKeepScreenOff start');
365        let topWindow: any = AppStorage.Get('mainWindow');
366        try {
367            topWindow.setKeepScreenOn(false, () => Log.info(TAG, 'setKeepScreenOff Succeeded'))
368        } catch (err) {
369            Log.error(TAG, `setKeepScreenOff err: ${err}`);
370        }
371    }
372}
373
374let screenManager = createOrGet(ScreenManager, TAG);
375
376export default screenManager as ScreenManager;
377