blob: 43a05ec92f72a1cc6850d1bc1b395858512ea057 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:fidl_fuchsia_component/fidl_async.dart';
import 'package:fidl_fuchsia_component_decl/fidl_async.dart';
import 'package:fidl_fuchsia_io/fidl_async.dart';
import 'package:fidl_fuchsia_session_scene/fidl_async.dart';
import 'package:fidl_fuchsia_ui_app/fidl_async.dart';
import 'package:fidl_fuchsia_ui_focus/fidl_async.dart';
import 'package:fidl_fuchsia_ui_keyboard_focus/fidl_async.dart';
import 'package:fidl_fuchsia_ui_shortcut/fidl_async.dart' as shortcut;
import 'package:fidl_fuchsia_ui_views/fidl_async.dart';
import 'package:fuchsia_logger/logger.dart';
import 'package:fuchsia_services/services.dart';
import 'package:zircon/zircon.dart';
const kLoginShellName = 'login_shell';
const kAccountName = 'created_by_session';
const kAccountPassword = '';
const kAccountDirectory = 'account_data';
void main(List args) async {
setupLogger(name: 'workstation_session');
log.info('Setting up workstation session');
try {
// Connect to the Realm.
final realm = RealmProxy();
Incoming.fromSvcPath().connectToService(realm);
// Get the login shell's exposed /svc directory.
final exposedDir = DirectoryProxy();
await realm.openExposedDir(
ChildRef(name: kLoginShellName), exposedDir.ctrl.request());
// Get the login shell's view provider.
final viewProvider = ViewProviderProxy();
Incoming.withDirectory(exposedDir).connectToService(viewProvider);
// Set the login shell's view as the root view.
final sceneManager = ManagerProxy();
Incoming.fromSvcPath().connectToService(sceneManager);
final viewRef = await sceneManager.setRootView(viewProvider.ctrl.unbind());
// Wait for the view to be attached to the scene.
final viewRefInstalled = ViewRefInstalledProxy();
Incoming.fromSvcPath().connectToService(viewRefInstalled);
await viewRefInstalled.watch(viewRef.duplicate());
// Set focus on the root view.
await sceneManager.requestFocus(viewRef.duplicate());
// Hook up focus chain to IME and shortcut manager.
final focusChainRegistry = FocusChainListenerRegistryProxy();
Incoming.fromSvcPath().connectToService(focusChainRegistry);
await focusChainRegistry
.register(FocusChainListenerBinding().wrap(_FocusChainListener()));
// ignore: avoid_catches_without_on_clauses
} catch (e) {
log.severe('Caught exception during workstation session setup: $e');
}
}
/// Listens to focus chain updates and forwards them to [shortcut.Manager] and
/// IME [Controller].
class _FocusChainListener extends FocusChainListener {
final _ime = ControllerProxy();
final _shortcutManager = shortcut.ManagerProxy();
_FocusChainListener() {
Incoming.fromSvcPath().connectToService(_ime);
Incoming.fromSvcPath().connectToService(_shortcutManager);
}
@override
Future<void> onFocusChange(FocusChain focusChain) async {
final chain = focusChain.focusChain;
if (chain == null || chain.isEmpty) {
return;
}
try {
final viewRef = chain.last.duplicate();
await _ime.notify(viewRef);
await _shortcutManager.handleFocusChange(focusChain);
// ignore: avoid_catches_without_on_clauses
} catch (e) {
log.severe('Caught exception updating focus chain: $e');
}
}
}
extension _ViewRefDuplicator on ViewRef {
ViewRef duplicate() =>
ViewRef(reference: reference.duplicate(ZX.RIGHT_SAME_RIGHTS));
}