# inset-services/src
Flutter home: packages/flutter/lib/src/services
Ported against: ed2132410ee94b5a590cb7f67cee7a6ea9101a60
Only the app life cycle and the application exit of `ServicesBinding`, the hardware keyboard, haptic feedback, mouse cursors, the mouse tracking annotation, state restoration, the application switcher description, the system overlay style, `TextInput` / `TextInputConnection` / `TextInputClient` / `TextSelectionDelegate`, text layout metric statics, the text boundaries, the clipboard, text input formatters, `SelectionChangedCause`, autofill (`AutofillHints` / `AutofillClient` / `AutofillScope`), keyboard-inserted content, spell check, live text, process text, `UndoManager` / `UndoManagerClient`, and re-exports of the text-input value types are here; the rest of the package waits.
## Identical
- text_editing.rs → text_editing.dart (re-export of embedder `TextSelection`)
- text_layout_metrics.rs → text_layout_metrics.dart (`isWhitespace` / `isLineTerminator`)
- text_boundary.rs → text_boundary.dart (`LineBoundary` needs layout, so it sits in rendering)
## binding.rs → binding.dart
- Change: `ServicesBinding` reaches the widgets binding's exit handler through a registered `ServicesBindingOverrides`, where Dart's `WidgetsBinding` overrides it.
Reason: language — a crate above cannot override a method below it.
Affect: without the widgets binding, every exit request is answered `Exit`.
- Change: `ServicesBinding::handle_lifecycle_message` is public and takes an `AppLifecycleState`, where Dart's private handler parses a state's name from a channel.
Reason: platform — there are no method channels; the host trait is the channel.
Affect: a test reports a lifecycle state by calling the binding.
- Change: `ServicesBinding::clipboard` is a listenable the host notifies each time it says the clipboard changed.
Reason: platform — Flutter's engines never say the clipboard changed; a host that can tell, says so.
Affect: what shows whether the clipboard can be pasted follows a copy made elsewhere.
- Change: `ServicesBinding::exit_application` answers `Cancel` at once on a host with no `AppExit` capability, where Dart's call fails.
Reason: platform — the host trait is the channel, and a host without the capability answers `None`.
Affect: on a phone or in a browser the app keeps running and the caller sees `Cancel`, not an error.
## clipboard.rs → clipboard.dart
- Change: `Clipboard::has_strings` answers from the types on the clipboard, never reading the text.
Reason: platform — the host's clipboard lists its items' types without their content, as a host whose own reads are guarded must.
Affect: an empty text on the clipboard counts as strings, as it does on iOS and Android.
- Change: while the host's copy, cut or paste event is handled (`Clipboard::handle_event`), `set_data` writes through the event and `get_data` and `has_strings` read what was pasted.
Reason: platform — where only the user's own paste may read the clipboard, as in a browser, the host hands what was pasted with the event.
Affect: a text field pastes what the user pasted even where the app may not read the clipboard itself.
## text_input.rs → text_input.dart
- Change: text input reaches the host through `View` — start and stop, editing state, composing and caret rects, client geometry.
Reason: platform — there are no method channels; the host trait is the channel.
Affect: on a host that does not implement those methods, `TextInputConnection::show` and the rest do nothing and no IME appears.
- Change: the host delivers `updateEditingValue` / `performAction` / `connectionClosed` by calling `EmbedderClient`, and `Shell` forwards them to the `TextInput` singleton without a client id.
Reason: platform — the host trait is the channel, and one connection is attached at a time.
Affect: an inbound edit always lands on the currently attached client; a message meant for a connection that has just been replaced cannot be told apart and is applied to the new one.
- Change: `performPrivateCommand` carries only the action string, and `insertContent`, `currentAutofillScope`, `didChangeInputControl` and `onFocusReceived` are absent from `TextInputClient`.
Reason: platform — those payloads were method-channel maps, and no host sends them.
Affect: a private command's `data` is dropped, and a client is never handed inserted content nor asked for its autofill scope.
- Change: text input finds the view a field is in only by its configuration's `view_id`, where Flutter's engine falls back to the implicit view when there is none.
Reason: platform — there is no implicit view; `EditableText` names its view, as Flutter's does.
Affect: a configuration that names no view reaches no host text input.
- Change: `TextInput::request_autofill` and `TextInput::finish_autofill_context` exist but do nothing.
Reason: platform — there is no host autofill API.
Affect: `AutofillGroup` disposal still calls them, but the platform is never asked to fill a group or to commit a saved autofill context.
## system_context_menu.rs → `SystemContextMenuController` / `IOSSystemContextMenuItemData*` in text_input.dart
- Change: the last-shown controller is registered per `App` rather than in a Dart static, menu items cross to the host as `SystemContextMenuItem` values instead of JSON maps, and a custom item's callback id is assigned on the item rather than derived from `hashCode`.
Reason: language — there is no isolate-wide static; platform — the host trait is the channel and carries no JSON.
Affect: two `App`s can each show a system menu at once, and two custom items with equal contents keep separate callbacks.
## spell_check.rs → spell_check.dart
- Change: `fetch_spell_check_suggestions` answers within the call, and answers `None` unless a host implements [`SpellCheckService`].
Reason: platform — there are no method channels, so there is no default OS spell checker to reach.
Affect: text is never marked misspelled unless the embedder supplies a service.
## live_text.rs → live_text.dart
- Change: `LiveText::is_live_text_input_available` answers `false` and `start_live_text_input` does nothing.
Reason: platform — there are no method channels and no host API for it.
Affect: the "insert from camera" entry never appears in a text toolbar.
## process_text.rs → process_text.dart
- Change: `query_text_actions` answers an empty list and `process_text_action` answers `None`, both within the call.
Reason: platform — there are no method channels; a host that has OS text actions implements [`ProcessTextService`].
Affect: no OS text actions appear in the selection toolbar, and a test supplies a service instead of a fake channel.
## autofill.rs → autofill.dart
- Change: `AutofillScope::attach` hands `TextInput::attach` the trigger's own configuration and does not wrap it to carry the group's other fields.
Reason: platform — Dart's wrapper exists only to add `fields` to the channel JSON, and `TextInputHost::start` takes one configuration.
Affect: the host never learns the sibling fields of a group, so OS autofill fills the focused field alone.
## text_formatter.rs → text_formatter.dart
- Change: `FilteringTextInputFormatter` matches a [`FilterPattern`], either a literal or the digit class, where Dart takes any `Pattern`.
Reason: language — there is no regular expression type in the port.
Affect: a filter Dart writes as a regex cannot be expressed; only a literal and `digits_only` filter.
- Change: `LengthLimitingTextInputFormatter` counts Unicode scalar values, and `get_default_max_length_enforcement` has no web branch.
Reason: language — Dart counts grapheme clusters through its `characters` package; platform — there is no web target.
Affect: a family emoji spends several characters of the limit, and truncating at the limit can cut one apart.
## undo_manager.rs → undo_manager.dart
- Change: `set_undo_state` does nothing, and the host drives undo by calling `UndoManager::handle_platform_undo`.
Reason: platform — the host trait is the channel and has no message carrying undo state.
Affect: the OS undo affordance is never told whether undo or redo is available, so it cannot disable itself.
## keyboard_key.rs → keyboard_key.g.dart
The key constants and the four tables are machine-written from the Dart, as Flutter machine-writes that file from `dev/tools/gen_keycodes`.
## hardware_keyboard.rs → hardware_keyboard.dart
- Change: `sync_keyboard_state` takes the pressed-key map from its caller instead of asking the host for it.
Reason: platform — `Platform` has no keyboard-state query.
Affect: keys already held when the app starts or regains focus stay unknown unless an embedder passes them in.
- Change: `KeyEventManager::handle_key_data` dispatches to `HardwareKeyboard` within the call and answers whether a handler took the event, where Dart infers a transit mode and queues events until the next raw key message.
Reason: platform — the raw key channel is not ported, so nothing would ever flush that queue.
Affect: handlers see each key event as it arrives and the host reads the answer from `key_data`; there is no `KeyMessage` stage after them.
- Change: key dispatch does not catch a panicking handler.
Reason: language — no `FlutterError.reportError` hook to catch and continue.
Affect: one failing handler unwinds the dispatch and the remaining handlers do not run.
- Change: `KeyEvent::to_key_data` gives back the `KeyData` an event was made from, which Dart does not offer.
Reason: platform — an app that claims a key and leaves it later hands it back to the host's menu bar (`MenuBar::perform_key_equivalent`), which knows its own event by the key it reported.
Affect: a key kept back can still reach the menu bar's item with its shortcut.
## mouse_cursor.rs → mouse_cursor.dart
- Change: a session's `activate` asks the host of the view the pointer is over (`ViewHost::activate_system_cursor`) for a `SystemMouseCursorKind`, and returns nothing.
Reason: platform — the host trait is the channel; there is no channel reply to await and nothing needs the string encoding.
Affect: the cursor changes without waiting a frame, and a view with no host leaves the cursor as it was.
- Change: `MouseCursorSession::activate` and `MouseCursorManager::handle_device_cursor_update` also take the view the pointer is over.
Reason: platform — where each window has its own cursor, the host must know which window to change.
Affect: a custom session must keep the view it was activated with for any later cursor change.
## restoration.rs → restoration.dart
- Change: restoration data is `RestorationData`, an enum over the kinds the codec can carry, and a bucket's `read` / `write` / `remove` lose Dart's type parameter.
Reason: language — Rust has no `Object?`, so the enum is the only thing a bucket can hold.
Affect: a value Dart would reject at run time cannot be written at all, and `read` answers data the caller narrows with `as_int` and friends.
- Change: restoration reaches the host through its `Restoration` capability, passing a `RestorationMap` rather than an encoded byte buffer.
Reason: platform — the host trait is the channel and nothing on it needs an encoding.
Affect: a host stores the map as it stands, and pushes data that arrives later by calling `RestorationManager::handle_restoration_update_from_engine` itself.
- Change: `root_bucket` asks the host and builds the bucket within the call, where Dart's getter is a `Future`.
Reason: platform — the host answers a `Platform` call in place; there is no channel reply to await.
Affect: the root bucket is there for the first frame that asks for it, and listeners still fire from `handle_restoration_update_from_engine` as in Dart.
- Change: `dispose` destroys the bucket's arena slot.
Reason: language — the arena owns the object, and no collector keeps a disposed bucket alive.
Affect: using a bucket after `dispose` panics in a release build too, where Dart only asserts in debug.
- Change: `RestorationBucket::root` takes the raw map by value and the hierarchy owns it from then on.
Reason: language — a Rust value has one owner, so the caller cannot keep watching the map it handed over.
Affect: a child bucket's writes are no longer visible through the caller's map; read the data back through the buckets or from what `Restoration::put` receives.
## system_chrome.rs → system_chrome.dart
- Change: the switcher description and the overlay style are calls on the host's `SystemChrome` capability that complete in place and cannot fail.
Reason: platform — the host trait is the channel; there is no `Future` and no channel error.
Affect: `Title` and `CupertinoApp` apply them mid-build, and the failure Dart's `onError` handler reports cannot happen.
## haptic_feedback.rs → haptic_feedback.dart
- Change: each `HapticFeedback` member calls the host's `Haptics` capability with a `HapticFeedbackType`, and the argument-less `vibrate` passes the `Vibrate` kind.
Reason: platform — the host trait is the channel, so Dart's `'HapticFeedbackType.xxx'` strings are the enum's variants.
Affect: a host without a vibrator, which is every desktop one, drops the call.
## Deferred
- Platform channels, `SystemChannels`, `BinaryMessenger`. Trigger: the first service that needs a named channel rather than a `Platform` method.
- `MouseCursor` diagnostics (`debugFillProperties`, `toString(minLevel)`). Trigger: diagnostics.
- An `EmbedderClient` hook for restoration data that arrives while the app runs. Trigger: an embedder whose OS hands it new data after start; until then the host calls `RestorationManager::handle_restoration_update_from_engine`.
- The rest of text input: `ScribbleClient`, `DeltaTextInputClient`, `TextInputControl` / `setInputControl`, `setSelectionRects` and `updateStyle` reaching the host, asset bundles. Trigger: scribble, a custom input control, or a host that implements autofill.
- The rest of `SystemChrome`: `setPreferredOrientations`, `setEnabledSystemUIMode`, `restoreSystemUIOverlays`, `setSystemUIChangeCallback`, `DeviceOrientation`, `SystemUiMode`. Trigger: an orientation-aware or fullscreen-capable host.
- The raw key path (`RawKeyboard`, `RawKeyEvent`, `KeyMessage`, `KeyDataTransitMode`, `KeyEventManager.handleRawKeyMessage`), which Flutter has deprecated. Trigger: an embedder that can only send raw key data.
- `debugPrintKeyboardEvents` and `HardwareKeyboard._logEventIfIrregular`. Trigger: `services/debug.dart`.
- The host side of `sync_keyboard_state`. Trigger: a `Platform` that can report the keys held at start or on regaining focus.
- `KeyEvent` / `KeyboardKey` diagnostics. Trigger: diagnostics.