mirror of
https://github.com/flectar/mail.git
synced 2026-11-13 18:44:12 +00:00
Merge pull request #162 from springmin/ohos-ime-window-offset
ohos: refresh the IME cursor offset with the window
This commit is contained in:
1 file changed
+48
-20
@@ -8,6 +8,8 @@ import { window } from '@kit.ArkUI';
|
||||
import { util } from '@kit.ArkTS';
|
||||
|
||||
const LOG_TAG = 'FlectarOhos';
|
||||
// The XComponent, as both its native id and its component id.
|
||||
const SURFACE_ID = 'flectar_mail_surface';
|
||||
// One document is copied for the Files pane, whose transfers stop here.
|
||||
// Several are bounded by the free space alone, which a copy never takes
|
||||
// below the reserve. The same limits apply on Android and iOS.
|
||||
@@ -63,8 +65,11 @@ struct Index {
|
||||
private imeAttachPending: boolean = false;
|
||||
private imePassword: boolean | undefined = undefined;
|
||||
private pendingImePassword: boolean | undefined = undefined;
|
||||
private windowOffsetX: number = 0;
|
||||
private windowOffsetY: number = 0;
|
||||
private observedWindow: window.Window | undefined = undefined;
|
||||
// Moving the window moves the surface on the screen without a layout pass.
|
||||
private windowRectHandler = (_options: window.RectChangeOptions): void => {
|
||||
this.applyImeCursor();
|
||||
};
|
||||
private appBackgroundHandler: () => void = (): void => {
|
||||
this.nativeModule?.suspendPreview?.();
|
||||
};
|
||||
@@ -95,7 +100,7 @@ struct Index {
|
||||
|
||||
onPageShow(): void {
|
||||
this.applySystemColorScheme(this.colorMode);
|
||||
this.updateWindowOffset();
|
||||
this.observeWindow();
|
||||
this.refreshClipboard();
|
||||
}
|
||||
|
||||
@@ -130,6 +135,7 @@ struct Index {
|
||||
(error as BusinessError).message);
|
||||
}
|
||||
this.systemPasteboard = undefined;
|
||||
this.releaseWindowObserver();
|
||||
this.imeAttached = false;
|
||||
this.imeAttachPending = false;
|
||||
this.imePassword = undefined;
|
||||
@@ -140,12 +146,17 @@ struct Index {
|
||||
build(): void {
|
||||
Column() {
|
||||
XComponent({
|
||||
id: 'flectar_mail_surface',
|
||||
id: SURFACE_ID,
|
||||
type: XComponentType.SURFACE,
|
||||
libraryname: 'flectar_mail_ohos',
|
||||
})
|
||||
.id(SURFACE_ID)
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
// Maximizing, restoring and split screen lay the surface out again.
|
||||
.onAreaChange((): void => {
|
||||
this.applyImeCursor();
|
||||
})
|
||||
.focusable(true)
|
||||
.defaultFocus(true)
|
||||
.onLoad((context?: object): void => {
|
||||
@@ -218,7 +229,7 @@ struct Index {
|
||||
},
|
||||
});
|
||||
this.applySystemColorScheme(this.colorMode);
|
||||
this.updateWindowOffset();
|
||||
this.observeWindow();
|
||||
this.installClipboardListener();
|
||||
}
|
||||
|
||||
@@ -529,15 +540,20 @@ struct Index {
|
||||
return;
|
||||
}
|
||||
const cursor = this.pendingImeCursor;
|
||||
const key = this.imeCursorKey(cursor);
|
||||
if (key === this.lastImeCursor) {
|
||||
return;
|
||||
}
|
||||
const rect = this.imeCursorKey(cursor);
|
||||
try {
|
||||
// CursorInfo is in px on the screen, while Slint reports the caret in vp
|
||||
// relative to the surface. Offset it by where the surface is on the
|
||||
// screen now, which follows window moves, maximizing and split screen.
|
||||
const ui = this.getUIContext();
|
||||
const origin = ui.getComponentUtils().getRectangleById(SURFACE_ID).screenOffset;
|
||||
const key = `${origin.x},${origin.y},${rect}`;
|
||||
if (key === this.lastImeCursor) {
|
||||
return;
|
||||
}
|
||||
const px: inputMethod.CursorInfo = {
|
||||
left: this.windowOffsetX + ui.vp2px(cursor.left),
|
||||
top: this.windowOffsetY + ui.vp2px(cursor.top),
|
||||
left: origin.x + ui.vp2px(cursor.left),
|
||||
top: origin.y + ui.vp2px(cursor.top),
|
||||
width: ui.vp2px(cursor.width),
|
||||
height: ui.vp2px(cursor.height),
|
||||
};
|
||||
@@ -545,7 +561,7 @@ struct Index {
|
||||
// Only remember a rectangle that is still the latest one. An older
|
||||
// request completing late must not overwrite a newer caret.
|
||||
const current = this.pendingImeCursor;
|
||||
if (current !== undefined && this.imeCursorKey(current) === key) {
|
||||
if (current !== undefined && this.imeCursorKey(current) === rect) {
|
||||
this.lastImeCursor = key;
|
||||
this.imeCursorRetries = 0;
|
||||
} else {
|
||||
@@ -558,7 +574,7 @@ struct Index {
|
||||
// as applied; retry the current one shortly, otherwise identical
|
||||
// updates would be deduplicated forever.
|
||||
const current = this.pendingImeCursor;
|
||||
if (current === undefined || this.imeCursorKey(current) !== key) {
|
||||
if (current === undefined || this.imeCursorKey(current) !== rect) {
|
||||
this.applyImeCursor();
|
||||
return;
|
||||
}
|
||||
@@ -594,21 +610,33 @@ struct Index {
|
||||
}
|
||||
}
|
||||
|
||||
// CursorInfo is in absolute physical screen coordinates. The Slint caret
|
||||
// rectangle is relative to the XComponent, so add the window origin.
|
||||
private async updateWindowOffset(): Promise<void> {
|
||||
// Follow the app window once, so moving it re-places the IME candidate.
|
||||
private async observeWindow(): Promise<void> {
|
||||
if (this.observedWindow !== undefined) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const context = this.getUIContext().getHostContext() as common.UIAbilityContext;
|
||||
const appWindow = await window.getLastWindow(context);
|
||||
const rect = appWindow.getWindowProperties().windowRect;
|
||||
this.windowOffsetX = rect.left;
|
||||
this.windowOffsetY = rect.top;
|
||||
if (this.observedWindow !== undefined) {
|
||||
return;
|
||||
}
|
||||
this.observedWindow = appWindow;
|
||||
appWindow.on('windowRectChange', this.windowRectHandler);
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, LOG_TAG, 'could not read the window origin: %{public}s',
|
||||
hilog.error(0x0000, LOG_TAG, 'could not observe the window: %{public}s',
|
||||
(error as BusinessError).message);
|
||||
}
|
||||
}
|
||||
|
||||
private releaseWindowObserver(): void {
|
||||
if (this.observedWindow === undefined) {
|
||||
return;
|
||||
}
|
||||
this.observedWindow.off('windowRectChange', this.windowRectHandler);
|
||||
this.observedWindow = undefined;
|
||||
}
|
||||
|
||||
private applySystemColorScheme(mode: number): void {
|
||||
try {
|
||||
let colorMode = mode;
|
||||
|
||||
Reference in new issue
Block a user