• 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 ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
16import common from '@ohos.app.ability.common';
17import window from '@ohos.window';
18import inputMethod from '@ohos.inputMethod';
19import commonEvent from '@ohos.commonEventManager';
20import Want from '@ohos.app.ability.Want';
21import display from '@ohos.display';
22import { BusinessError } from '@ohos.base';
23
24let TAG: string = '[InputMethodChooseDialog]';
25let PACKAGE_ADDED: string = 'usual.event.PACKAGE_ADDED';
26let PACKAGE_REMOVED: string = 'usual.event.PACKAGE_REMOVED';
27let subscribeInfo: commonEvent.CommonEventSubscribeInfo = {
28  events: [PACKAGE_ADDED, PACKAGE_REMOVED]
29};
30
31interface DialogRect {
32  left: number;
33  top: number;
34  width: number;
35  height: number;
36}
37
38const DISPLAY_SCALE: number = 0.35;
39const MIN_SIZE: number = 350;
40const MAX_SZIE: number = 550;
41const DIALOG_POSITION_X: number = 50;
42const DIALOG_POSITION_Y_SCALE: number = 0.3;
43const DEFAULT_DIALOG_RECT: DialogRect = {
44  left: DIALOG_POSITION_X,
45  top: DIALOG_POSITION_X,
46  width: MIN_SIZE,
47  height: MIN_SIZE
48};
49
50export default class ServiceExtAbility extends ServiceExtensionAbility {
51  private extensionWin: window.Window | undefined = undefined;
52  private mContext: common.ServiceExtensionContext | undefined = undefined;
53  private windowNum: number = 0;
54
55  onCreate(want: Want): void {
56    console.log(TAG, 'onCreate');
57    this.windowNum = 0;
58    this.mContext = this.context;
59  }
60
61  onRequest(want: Want, startId: number): void {
62    console.log(TAG, 'onRequest execute');
63    let dialogRect: DialogRect = DEFAULT_DIALOG_RECT;
64    try {
65      let defaultDisplay = display.getDefaultDisplaySync();
66      let size = defaultDisplay.width * DISPLAY_SCALE > MIN_SIZE ? defaultDisplay.width * DISPLAY_SCALE : MIN_SIZE;
67      size = size < MAX_SZIE ? size : MAX_SZIE;
68      let dialogTop = defaultDisplay.height * DIALOG_POSITION_Y_SCALE;
69      dialogRect = {
70        left: DIALOG_POSITION_X,
71        top: dialogTop,
72        width: size,
73        height: size
74      };
75    } catch (error) {
76      console.error(TAG + 'getDefaultDisplaySync error use default dialogRect:' + JSON.stringify(error));
77    }
78    let windowConfig: window.Configuration = {
79      name: 'inputmethod Dialog',
80      windowType: window.WindowType.TYPE_GLOBAL_SEARCH,
81      ctx: this.mContext
82    };
83    this.getInputMethods().then(() => {
84      this.createWindow(windowConfig, dialogRect);
85    });
86
87    commonEvent.createSubscriber(subscribeInfo, (error: BusinessError, subcriber: commonEvent.CommonEventSubscriber) => {
88      commonEvent.subscribe(subcriber, (error: BusinessError, commonEventData: commonEvent.CommonEventData) => {
89        if (error) {
90          console.log(TAG + `commonEvent subscribe error, errorCode: ${error}`);
91          return;
92        }
93        if (commonEventData?.event === PACKAGE_ADDED || commonEventData?.event === PACKAGE_REMOVED) {
94          this.updateImeList();
95        }
96      });
97    });
98  }
99
100  onDestroy(): void {
101    console.log(TAG + 'ServiceExtAbility destroyed');
102    this.releaseContext();
103  }
104
105  private async createWindow(config: window.Configuration, rect: DialogRect): Promise<void> {
106    console.log(TAG + 'createWindow execute');
107    try {
108      if (this.windowNum > 0) {
109        this.updateImeList();
110        return;
111      }
112      try {
113        this.extensionWin = await window.createWindow(config);
114        console.info(TAG + 'Succeeded in creating the window. Data: ' + JSON.stringify(this.extensionWin));
115        this.extensionWin.on('windowEvent', async (data: window.WindowEventType) => {
116          console.log(TAG + 'windowEvent:' + JSON.stringify(data));
117          if (data === window.WindowEventType.WINDOW_INACTIVE) {
118            await this.releaseContext();
119          }
120        });
121        await this.extensionWin.moveWindowTo(rect.left, rect.top);
122        await this.extensionWin.resize(rect.width, rect.height);
123        await this.extensionWin.setUIContent('pages/index');
124        await this.extensionWin.showWindow();
125        this.windowNum++;
126        console.log(TAG + 'window create successfully');
127      } catch (exception) {
128        console.error('Failed to create the window. Cause: ' + JSON.stringify(exception));
129      }
130    } catch {
131      console.info(TAG + 'window create failed');
132    }
133  }
134
135  private async getInputMethods(): Promise<void> {
136    let inputMethodList: Array<inputMethod.InputMethodProperty> = [];
137    try {
138      let enableList = await inputMethod.getSetting().getInputMethods(true);
139      let disableList = await inputMethod.getSetting().getInputMethods(false);
140      inputMethodList = enableList.concat(disableList);
141      AppStorage.setOrCreate('inputMethodList', inputMethodList);
142    } catch {
143      console.log(TAG + 'getInputMethods failed');
144    }
145  }
146
147  private async updateImeList(): Promise<void> {
148    await this.getInputMethods().then(async () => {
149      if (this.extensionWin) {
150        await this.extensionWin.setUIContent('pages/index');
151        if (!this.extensionWin.isWindowShowing()) {
152          await this.extensionWin.showWindow();
153        }
154      }
155    });
156  }
157
158  public async releaseContext(): Promise<void> {
159    await this.extensionWin?.destroyWindow();
160    await this.mContext?.terminateSelf();
161  }
162};