Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crates/shell/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ fn main() {
if native_mobile {
println!("cargo:rustc-cfg=native_mobile");
}
if feature || target_os == "android" || target_env == "ohos" {
// Experiment: `OCTOSENSE_OHOS_DESKTOP=1` builds the desktop shell for an
// OpenHarmony 2-in-1 (every native app is an in-process module there).
println!("cargo:rerun-if-env-changed=OCTOSENSE_OHOS_DESKTOP");
let ohos_desktop = target_env == "ohos" && std::env::var_os("OCTOSENSE_OHOS_DESKTOP").is_some_and(|v| v == "1");
if feature || target_os == "android" || (target_env == "ohos" && !ohos_desktop) {
println!("cargo:rustc-cfg=mobile_only");
}
// `kernel`: this build hosts the octos kernel, exactly as
Expand Down
4 changes: 4 additions & 0 deletions crates/shell/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6415,6 +6415,10 @@ app_main!(
/// The person's home directory (`HOME`; `USERPROFILE` on Windows), where a
/// new terminal with no directory to inherit opens.
fn user_home() -> Option<std::path::PathBuf> {
// Android, iOS and OpenHarmony: `HOME` is not the app's to use.
if let Some(dir) = makepad_widgets::makepad_platform::home::platform_data_dir() {
return Some(dir);
}
let var = if cfg!(windows) { "USERPROFILE" } else { "HOME" };
std::env::var_os(var).filter(|home| !home.is_empty()).map(std::path::PathBuf::from).filter(|home| home.is_dir())
}
3 changes: 3 additions & 0 deletions phone/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,8 @@ app-hub = ["dep:octosense-app-hub-app", "octosense-shell/app-hub"]
# END native-apps: features
app-aichat = ["dep:makepad-aichat", "octosense-shell/app-aichat"]
dev-mode = ["octosense-shell/dev-mode"]
# Experiment: Terminal in the OpenHarmony desktop build (native-apps.json
# keeps it off the phone shell).
app-terminal = ["octosense-shell/app-terminal"]
# The system toolbox offered to app agents (off by default; ADR 0002 §6).
toolbox-peers = ["octosense-shell/toolbox-peers"]
6 changes: 5 additions & 1 deletion phone/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ fn main() {
if native_mobile {
println!("cargo:rustc-cfg=native_mobile");
}
if feature || target_os == "android" || target_env == "ohos" {
// Experiment: `OCTOSENSE_OHOS_DESKTOP=1` builds the desktop shell for an
// OpenHarmony 2-in-1 (every native app is an in-process module there).
println!("cargo:rerun-if-env-changed=OCTOSENSE_OHOS_DESKTOP");
let ohos_desktop = target_env == "ohos" && std::env::var_os("OCTOSENSE_OHOS_DESKTOP").is_some_and(|v| v == "1");
if feature || target_os == "android" || (target_env == "ohos" && !ohos_desktop) {
println!("cargo:rustc-cfg=mobile_only");
}
// The host's build id: the second this build was configured, as digits.
Expand Down
12 changes: 11 additions & 1 deletion phone/ohos/EntryAbility.ets
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { BusinessError, deviceInfo } from '@kit.BasicServicesKit';
import makepad from 'libmakepad.so'
import {ArkGlue} from '../makepad/makepad'

Expand Down Expand Up @@ -52,6 +52,16 @@ export default class EntryAbility extends UIAbility {
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
});

// A 2-in-1 starts the shell full size: its desktop build is the
// OctoSense desktop, which is its own window manager.
if (deviceInfo.deviceType === '2in1') {
windowStage.getMainWindow().then((mainWindow) => {
mainWindow.maximize().catch((e: BusinessError) => {
hilog.warn(0x0000, 'testTag', 'maximize failed: %{public}d', e.code);
});
});
}

// HarmonyOS lays the XComponent between its native system bars. Its
// surface dimensions and local touch coordinates already exclude them.
windowStage.getMainWindow().then((mainWindow) => {
Expand Down
17 changes: 14 additions & 3 deletions rom/docs/home-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,20 @@ draggable floating ball over hosted content. Tapping it opens a compact panel
with **返回首页** and **最近应用**. Dragging docks it inside the nearest side;
tapping outside dismisses the panel without activating the content underneath.
The ball stays in the app window and reserves no content height.
The generated ArkTS bridge also receives `phone/ohos/keyboard.patch` to coalesce
per-frame keyboard requests and serialize attach/show/hide while leaving the
pinned framework checkout intact. OpenHarmony uses only its native keyboard.
With a framework whose ArkTS bridge still drives the input method, the bridge
also receives `phone/ohos/keyboard.patch` to coalesce per-frame keyboard
requests and serialize attach/show/hide while leaving the pinned framework
checkout intact; a framework with the NDK input method (makepad's
`oh_ime.rs`) serializes them natively and gets no patch. OpenHarmony uses only
its native keyboard.
On a HarmonyOS 2-in-1, `--desktop` builds the OctoSense desktop instead of
the phone shell (`OCTOSENSE_OHOS_DESKTOP=1`, read by `crates/shell/build.rs`
and `phone/build.rs`; every native app is an in-process module there), declares
the module for `2in1` and `tablet`, and the window opens maximized. Terminal
is the opt-in `app-terminal` feature of `phone/Cargo.toml`, which this script
does not pass yet. The desktop build was run on a MateBook
Pro (HarmonyOS 7.0) from an equivalent Linux build; this script's `--desktop`
path itself is **unverified**.
OpenHarmony does not recognize shell edge swipes or draw a second navigation
pill; those gestures remain available to the host OS. Home paging and the
central pull for the app library still work inside the content area.
Expand Down
21 changes: 19 additions & 2 deletions rom/scripts/build-home-ohos.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def main():
p.add_argument('--compatible-sdk', default='6.0.1(21)')
p.add_argument('--remote-port', type=int, help='Validation only: app-owned loopback inspection')
p.add_argument('--offline', action='store_true')
p.add_argument('--desktop', action='store_true',
help='The OctoSense desktop for a 2-in-1 (OCTOSENSE_OHOS_DESKTOP=1), also declared for 2in1 and tablet')
args = p.parse_args()
for name in ('deveco_home', 'signing_config', 'packager'):
setattr(args, name, getattr(args, name).expanduser().resolve())
Expand Down Expand Up @@ -70,6 +72,8 @@ def main():
env.pop('MAKEPAD_REMOTE', None)
if args.remote_port:
env['MAKEPAD_REMOTE'] = str(args.remote_port)
if args.desktop:
env['OCTOSENSE_OHOS_DESKTOP'] = '1'
cargo_args = ['-p', 'octosense-home', '--release', '--locked']
if args.offline:
cargo_args.append('--offline')
Expand All @@ -84,8 +88,21 @@ def main():
# keep the floating controls inside its safe area.
shutil.copy2(home / 'ohos/EntryAbility.ets',
project / 'entry/src/main/ets/entryability/EntryAbility.ets')
subprocess.run(['patch', '--batch', '--forward', '-p1', '-i',
str(home / 'ohos/keyboard.patch')], cwd=project, check=True)
# A framework whose ArkTS bridge still drives the input method gets the
# patch that serializes it; one with the native (NDK) input method has
# no ArkTS keyboard code left to patch.
bridge = project / 'entry/src/main/ets/makepad/makepad.ets'
if 'inputMethod' in bridge.read_text():
subprocess.run(['patch', '--batch', '--forward', '-p1', '-i',
str(home / 'ohos/keyboard.patch')], cwd=project, check=True)
if args.desktop:
# A phone-only module runs in a phone-sized compatibility window on a
# 2-in-1; the desktop shell is declared for it (and tablets).
module_path = project / 'entry/src/main/module.json5'
module = read_json5(module_path)
types = module['module'].setdefault('deviceTypes', [])
types.extend(t for t in ('2in1', 'tablet') if t not in types)
module_path.write_text(json.dumps(module, ensure_ascii=False, indent=2) + '\n')
app_path = project / 'AppScope/app.json5'
app = read_json5(app_path)
app['app']['bundleName'] = args.bundle_id
Expand Down
Loading