Skip to main content

fidl_fuchsia_ui_input_internal/
fidl_fuchsia_ui_input_internal.rs

1// WARNING: This file is machine generated by fidlgen.
2
3#![warn(clippy::all)]
4#![allow(unused_parens, unused_mut, unused_imports, nonstandard_style)]
5
6use bitflags::bitflags;
7use fidl::client::QueryResponseFut;
8use fidl::encoding::{MessageBufFor, ProxyChannelBox, ResourceDialect};
9use fidl::endpoints::{ControlHandle as _, Responder as _};
10pub use fidl_fuchsia_ui_input_internal_common::*;
11use futures::future::{self, MaybeDone, TryFutureExt};
12use zx_status;
13
14#[derive(Debug, PartialEq)]
15pub struct InputOwnershipGetEventRequest {
16    pub target: InputOwnershipTarget,
17}
18
19impl fidl::Standalone<fidl::encoding::DefaultFuchsiaResourceDialect>
20    for InputOwnershipGetEventRequest
21{
22}
23
24#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
25pub struct InputOwnershipGetEventResponse {
26    pub ownership_event: fidl::Event,
27}
28
29impl fidl::Standalone<fidl::encoding::DefaultFuchsiaResourceDialect>
30    for InputOwnershipGetEventResponse
31{
32}
33
34/// Target identity when requesting direct input ownership.
35#[derive(Debug)]
36pub enum InputOwnershipTarget {
37    ViewRef(fidl_fuchsia_ui_views::ViewRef),
38    Virtcon(Virtcon),
39    Platform(Platform),
40    #[doc(hidden)]
41    __SourceBreaking {
42        unknown_ordinal: u64,
43    },
44}
45
46/// Pattern that matches an unknown `InputOwnershipTarget` member.
47#[macro_export]
48macro_rules! InputOwnershipTargetUnknown {
49    () => {
50        _
51    };
52}
53
54// Custom PartialEq so that unknown variants are not equal to themselves.
55impl PartialEq for InputOwnershipTarget {
56    fn eq(&self, other: &Self) -> bool {
57        match (self, other) {
58            (Self::ViewRef(x), Self::ViewRef(y)) => *x == *y,
59            (Self::Virtcon(x), Self::Virtcon(y)) => *x == *y,
60            (Self::Platform(x), Self::Platform(y)) => *x == *y,
61            _ => false,
62        }
63    }
64}
65
66impl InputOwnershipTarget {
67    #[inline]
68    pub fn ordinal(&self) -> u64 {
69        match *self {
70            Self::ViewRef(_) => 1,
71            Self::Virtcon(_) => 2,
72            Self::Platform(_) => 3,
73            Self::__SourceBreaking { unknown_ordinal } => unknown_ordinal,
74        }
75    }
76
77    #[inline]
78    pub fn unknown_variant_for_testing() -> Self {
79        Self::__SourceBreaking { unknown_ordinal: 0 }
80    }
81
82    #[inline]
83    pub fn is_unknown(&self) -> bool {
84        match self {
85            Self::__SourceBreaking { .. } => true,
86            _ => false,
87        }
88    }
89}
90
91impl fidl::Standalone<fidl::encoding::DefaultFuchsiaResourceDialect> for InputOwnershipTarget {}
92
93#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
94pub struct InputOwnershipMarker;
95
96impl fidl::endpoints::ProtocolMarker for InputOwnershipMarker {
97    type Proxy = InputOwnershipProxy;
98    type RequestStream = InputOwnershipRequestStream;
99    #[cfg(target_os = "fuchsia")]
100    type SynchronousProxy = InputOwnershipSynchronousProxy;
101
102    const DEBUG_NAME: &'static str = "fuchsia.ui.input.internal.InputOwnership";
103}
104impl fidl::endpoints::DiscoverableProtocolMarker for InputOwnershipMarker {}
105pub type InputOwnershipGetEventResult = Result<fidl::Event, InputOwnershipError>;
106
107pub trait InputOwnershipProxyInterface: Send + Sync {
108    type GetEventResponseFut: std::future::Future<Output = Result<InputOwnershipGetEventResult, fidl::Error>>
109        + Send;
110    fn r#get_event(&self, target: InputOwnershipTarget) -> Self::GetEventResponseFut;
111}
112#[derive(Debug)]
113#[cfg(target_os = "fuchsia")]
114pub struct InputOwnershipSynchronousProxy {
115    client: fidl::client::sync::Client,
116}
117
118#[cfg(target_os = "fuchsia")]
119impl fidl::endpoints::SynchronousProxy for InputOwnershipSynchronousProxy {
120    type Proxy = InputOwnershipProxy;
121    type Protocol = InputOwnershipMarker;
122
123    fn from_channel(inner: fidl::Channel) -> Self {
124        Self::new(inner)
125    }
126
127    fn into_channel(self) -> fidl::Channel {
128        self.client.into_channel()
129    }
130
131    fn as_channel(&self) -> &fidl::Channel {
132        self.client.as_channel()
133    }
134}
135
136#[cfg(target_os = "fuchsia")]
137impl InputOwnershipSynchronousProxy {
138    pub fn new(channel: fidl::Channel) -> Self {
139        Self { client: fidl::client::sync::Client::new(channel) }
140    }
141
142    pub fn into_channel(self) -> fidl::Channel {
143        self.client.into_channel()
144    }
145
146    /// Waits until an event arrives and returns it. It is safe for other
147    /// threads to make concurrent requests while waiting for an event.
148    pub fn wait_for_event(
149        &self,
150        deadline: zx::MonotonicInstant,
151    ) -> Result<InputOwnershipEvent, fidl::Error> {
152        InputOwnershipEvent::decode(self.client.wait_for_event::<InputOwnershipMarker>(deadline)?)
153    }
154
155    /// Gets a duplicate handle to the shared kernel `ownership_event` whose
156    /// orthogonal signals inform clients and the system pipeline when direct
157    /// driver input access (`fuchsia.input.report.Service`) is granted or revoked:
158    ///
159    /// - `Virtcon` (`target` = `virtcon: {}`): owns input iff
160    ///   `InputOwnershipSignal.DISPLAY_UNOWNED` is asserted.
161    /// - `Starnix` (`target` = `view_ref`): owns direct input iff both
162    ///   `InputOwnershipSignal.DISPLAY_PLATFORM_OWNED` and
163    ///   `InputOwnershipSignal.INPUT_CLIENT_OWNED` are asserted.
164    /// - `SceneManager` (`target` = `platform: {}`): owns platform pipeline
165    ///   input iff both `InputOwnershipSignal.DISPLAY_PLATFORM_OWNED` and
166    ///   `InputOwnershipSignal.INPUT_PLATFORM_OWNED` are asserted (pauses whenever
167    ///   `DISPLAY_UNOWNED` or `INPUT_CLIENT_OWNED` is asserted).
168    ///
169    /// Requesting direct input ownership:
170    ///
171    /// Calling `GetEvent` with `target` = `view_ref` is also how a view requests
172    /// direct input ownership; there is no separate request method. `GetEvent`
173    /// supports pre-registering a valid `ViewRef` before the view is created or
174    /// attached to the `ViewTree`. On success, the server registers the `ViewRef`
175    /// as the system-wide direct input client, immediately evaluates it against
176    /// the latest `ViewTree` snapshot if one exists, and continues evaluating it
177    /// against the single-view + full-screen criteria on every subsequent `ViewTree`
178    /// update. `INPUT_CLIENT_OWNED` is asserted only while the registered view
179    /// meets those criteria; otherwise `INPUT_PLATFORM_OWNED` is asserted.
180    ///
181    /// - Registration is singleton and last-writer-wins: a successful call with
182    ///   a different `ViewRef` replaces any previously registered view. This
183    ///   mechanism is intended for a single trusted client replacing its own view
184    ///   rather than independent concurrent components: because every `GetEvent`
185    ///   call returns a handle to the same shared kernel `ownership_event`, replacing
186    ///   the registered `ViewRef` does not silence earlier callers' handles when
187    ///   their view is unlinked or destroyed and the new view goes fullscreen.
188    /// - If the `ViewTree` contains more than one view or overlay competing
189    ///   with the registered view, the criteria are not met and ownership
190    ///   falls back to the platform. Thus, when multiple views request direct
191    ///   input while coexisting in the `ViewTree`, none of them is granted
192    ///   direct input, regardless of which one registered last.
193    /// - Registration is tied to the lifetime of the view, not to this
194    ///   channel or the returned event. Unlinking the view from the `ViewTree`
195    ///   (placing it in `unconnected_views`) reverts ownership to
196    ///   `INPUT_PLATFORM_OWNED` while retaining the registration, so re-linking
197    ///   fullscreen restores `INPUT_CLIENT_OWNED`. Destroying the view permanently
198    ///   drops the registration, at which point ownership reverts to the platform.
199    /// - Calls with `virtcon: {}` or `platform: {}` only observe ownership and
200    ///   do not modify the registered direct client.
201    ///
202    /// If `target` is set to an unsupported or unknown variant, the call
203    /// returns `InputOwnershipError.INVALID_TARGET`.
204    pub fn r#get_event(
205        &self,
206        mut target: InputOwnershipTarget,
207        ___deadline: zx::MonotonicInstant,
208    ) -> Result<InputOwnershipGetEventResult, fidl::Error> {
209        let _response =
210            self.client.send_query::<InputOwnershipGetEventRequest, fidl::encoding::ResultType<
211                InputOwnershipGetEventResponse,
212                InputOwnershipError,
213            >, InputOwnershipMarker>(
214                (&mut target,),
215                0x486e6eebf1f00657,
216                fidl::encoding::DynamicFlags::empty(),
217                ___deadline,
218            )?;
219        Ok(_response.map(|x| x.ownership_event))
220    }
221}
222
223#[cfg(target_os = "fuchsia")]
224impl From<InputOwnershipSynchronousProxy> for zx::NullableHandle {
225    fn from(value: InputOwnershipSynchronousProxy) -> Self {
226        value.into_channel().into()
227    }
228}
229
230#[cfg(target_os = "fuchsia")]
231impl From<fidl::Channel> for InputOwnershipSynchronousProxy {
232    fn from(value: fidl::Channel) -> Self {
233        Self::new(value)
234    }
235}
236
237#[cfg(target_os = "fuchsia")]
238impl fidl::endpoints::FromClient for InputOwnershipSynchronousProxy {
239    type Protocol = InputOwnershipMarker;
240
241    fn from_client(value: fidl::endpoints::ClientEnd<InputOwnershipMarker>) -> Self {
242        Self::new(value.into_channel())
243    }
244}
245
246#[derive(Debug, Clone)]
247pub struct InputOwnershipProxy {
248    client: fidl::client::Client<fidl::encoding::DefaultFuchsiaResourceDialect>,
249}
250
251impl fidl::endpoints::Proxy for InputOwnershipProxy {
252    type Protocol = InputOwnershipMarker;
253
254    fn from_channel(inner: ::fidl::AsyncChannel) -> Self {
255        Self::new(inner)
256    }
257
258    fn into_channel(self) -> Result<::fidl::AsyncChannel, Self> {
259        self.client.into_channel().map_err(|client| Self { client })
260    }
261
262    fn as_channel(&self) -> &::fidl::AsyncChannel {
263        self.client.as_channel()
264    }
265}
266
267impl InputOwnershipProxy {
268    /// Create a new Proxy for fuchsia.ui.input.internal/InputOwnership.
269    pub fn new(channel: ::fidl::AsyncChannel) -> Self {
270        let protocol_name = <InputOwnershipMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME;
271        Self { client: fidl::client::Client::new(channel, protocol_name) }
272    }
273
274    /// Get a Stream of events from the remote end of the protocol.
275    ///
276    /// # Panics
277    ///
278    /// Panics if the event stream was already taken.
279    pub fn take_event_stream(&self) -> InputOwnershipEventStream {
280        InputOwnershipEventStream { event_receiver: self.client.take_event_receiver() }
281    }
282
283    /// Gets a duplicate handle to the shared kernel `ownership_event` whose
284    /// orthogonal signals inform clients and the system pipeline when direct
285    /// driver input access (`fuchsia.input.report.Service`) is granted or revoked:
286    ///
287    /// - `Virtcon` (`target` = `virtcon: {}`): owns input iff
288    ///   `InputOwnershipSignal.DISPLAY_UNOWNED` is asserted.
289    /// - `Starnix` (`target` = `view_ref`): owns direct input iff both
290    ///   `InputOwnershipSignal.DISPLAY_PLATFORM_OWNED` and
291    ///   `InputOwnershipSignal.INPUT_CLIENT_OWNED` are asserted.
292    /// - `SceneManager` (`target` = `platform: {}`): owns platform pipeline
293    ///   input iff both `InputOwnershipSignal.DISPLAY_PLATFORM_OWNED` and
294    ///   `InputOwnershipSignal.INPUT_PLATFORM_OWNED` are asserted (pauses whenever
295    ///   `DISPLAY_UNOWNED` or `INPUT_CLIENT_OWNED` is asserted).
296    ///
297    /// Requesting direct input ownership:
298    ///
299    /// Calling `GetEvent` with `target` = `view_ref` is also how a view requests
300    /// direct input ownership; there is no separate request method. `GetEvent`
301    /// supports pre-registering a valid `ViewRef` before the view is created or
302    /// attached to the `ViewTree`. On success, the server registers the `ViewRef`
303    /// as the system-wide direct input client, immediately evaluates it against
304    /// the latest `ViewTree` snapshot if one exists, and continues evaluating it
305    /// against the single-view + full-screen criteria on every subsequent `ViewTree`
306    /// update. `INPUT_CLIENT_OWNED` is asserted only while the registered view
307    /// meets those criteria; otherwise `INPUT_PLATFORM_OWNED` is asserted.
308    ///
309    /// - Registration is singleton and last-writer-wins: a successful call with
310    ///   a different `ViewRef` replaces any previously registered view. This
311    ///   mechanism is intended for a single trusted client replacing its own view
312    ///   rather than independent concurrent components: because every `GetEvent`
313    ///   call returns a handle to the same shared kernel `ownership_event`, replacing
314    ///   the registered `ViewRef` does not silence earlier callers' handles when
315    ///   their view is unlinked or destroyed and the new view goes fullscreen.
316    /// - If the `ViewTree` contains more than one view or overlay competing
317    ///   with the registered view, the criteria are not met and ownership
318    ///   falls back to the platform. Thus, when multiple views request direct
319    ///   input while coexisting in the `ViewTree`, none of them is granted
320    ///   direct input, regardless of which one registered last.
321    /// - Registration is tied to the lifetime of the view, not to this
322    ///   channel or the returned event. Unlinking the view from the `ViewTree`
323    ///   (placing it in `unconnected_views`) reverts ownership to
324    ///   `INPUT_PLATFORM_OWNED` while retaining the registration, so re-linking
325    ///   fullscreen restores `INPUT_CLIENT_OWNED`. Destroying the view permanently
326    ///   drops the registration, at which point ownership reverts to the platform.
327    /// - Calls with `virtcon: {}` or `platform: {}` only observe ownership and
328    ///   do not modify the registered direct client.
329    ///
330    /// If `target` is set to an unsupported or unknown variant, the call
331    /// returns `InputOwnershipError.INVALID_TARGET`.
332    pub fn r#get_event(
333        &self,
334        mut target: InputOwnershipTarget,
335    ) -> fidl::client::QueryResponseFut<
336        InputOwnershipGetEventResult,
337        fidl::encoding::DefaultFuchsiaResourceDialect,
338    > {
339        InputOwnershipProxyInterface::r#get_event(self, target)
340    }
341}
342
343impl InputOwnershipProxyInterface for InputOwnershipProxy {
344    type GetEventResponseFut = fidl::client::QueryResponseFut<
345        InputOwnershipGetEventResult,
346        fidl::encoding::DefaultFuchsiaResourceDialect,
347    >;
348    fn r#get_event(&self, mut target: InputOwnershipTarget) -> Self::GetEventResponseFut {
349        fn _decode(
350            mut _buf: Result<<fidl::encoding::DefaultFuchsiaResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc, fidl::Error>,
351        ) -> Result<InputOwnershipGetEventResult, fidl::Error> {
352            let _response = fidl::client::decode_transaction_body::<
353                fidl::encoding::ResultType<InputOwnershipGetEventResponse, InputOwnershipError>,
354                fidl::encoding::DefaultFuchsiaResourceDialect,
355                0x486e6eebf1f00657,
356            >(_buf?)?;
357            Ok(_response.map(|x| x.ownership_event))
358        }
359        self.client
360            .send_query_and_decode::<InputOwnershipGetEventRequest, InputOwnershipGetEventResult>(
361                (&mut target,),
362                0x486e6eebf1f00657,
363                fidl::encoding::DynamicFlags::empty(),
364                _decode,
365            )
366    }
367}
368
369pub struct InputOwnershipEventStream {
370    event_receiver: fidl::client::EventReceiver<fidl::encoding::DefaultFuchsiaResourceDialect>,
371}
372
373impl std::marker::Unpin for InputOwnershipEventStream {}
374
375impl futures::stream::FusedStream for InputOwnershipEventStream {
376    fn is_terminated(&self) -> bool {
377        self.event_receiver.is_terminated()
378    }
379}
380
381impl futures::Stream for InputOwnershipEventStream {
382    type Item = Result<InputOwnershipEvent, fidl::Error>;
383
384    fn poll_next(
385        mut self: std::pin::Pin<&mut Self>,
386        cx: &mut std::task::Context<'_>,
387    ) -> std::task::Poll<Option<Self::Item>> {
388        match futures::ready!(futures::stream::StreamExt::poll_next_unpin(
389            &mut self.event_receiver,
390            cx
391        )?) {
392            Some(buf) => std::task::Poll::Ready(Some(InputOwnershipEvent::decode(buf))),
393            None => std::task::Poll::Ready(None),
394        }
395    }
396}
397
398#[derive(Debug)]
399pub enum InputOwnershipEvent {}
400
401impl InputOwnershipEvent {
402    /// Decodes a message buffer as a [`InputOwnershipEvent`].
403    fn decode(
404        mut buf: <fidl::encoding::DefaultFuchsiaResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc,
405    ) -> Result<InputOwnershipEvent, fidl::Error> {
406        let (bytes, _handles) = buf.split_mut();
407        let (tx_header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
408        debug_assert_eq!(tx_header.tx_id, 0);
409        match tx_header.ordinal {
410            _ => Err(fidl::Error::UnknownOrdinal {
411                ordinal: tx_header.ordinal,
412                protocol_name:
413                    <InputOwnershipMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME,
414            }),
415        }
416    }
417}
418
419/// A Stream of incoming requests for fuchsia.ui.input.internal/InputOwnership.
420pub struct InputOwnershipRequestStream {
421    inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
422    is_terminated: bool,
423}
424
425impl std::marker::Unpin for InputOwnershipRequestStream {}
426
427impl futures::stream::FusedStream for InputOwnershipRequestStream {
428    fn is_terminated(&self) -> bool {
429        self.is_terminated
430    }
431}
432
433impl fidl::endpoints::RequestStream for InputOwnershipRequestStream {
434    type Protocol = InputOwnershipMarker;
435    type ControlHandle = InputOwnershipControlHandle;
436
437    fn from_channel(channel: ::fidl::AsyncChannel) -> Self {
438        Self { inner: std::sync::Arc::new(fidl::ServeInner::new(channel)), is_terminated: false }
439    }
440
441    fn control_handle(&self) -> Self::ControlHandle {
442        InputOwnershipControlHandle { inner: self.inner.clone() }
443    }
444
445    fn into_inner(
446        self,
447    ) -> (::std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>, bool)
448    {
449        (self.inner, self.is_terminated)
450    }
451
452    fn from_inner(
453        inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
454        is_terminated: bool,
455    ) -> Self {
456        Self { inner, is_terminated }
457    }
458}
459
460impl futures::Stream for InputOwnershipRequestStream {
461    type Item = Result<InputOwnershipRequest, fidl::Error>;
462
463    fn poll_next(
464        mut self: std::pin::Pin<&mut Self>,
465        cx: &mut std::task::Context<'_>,
466    ) -> std::task::Poll<Option<Self::Item>> {
467        let this = &mut *self;
468        if this.inner.check_shutdown(cx) {
469            this.is_terminated = true;
470            return std::task::Poll::Ready(None);
471        }
472        if this.is_terminated {
473            panic!("polled InputOwnershipRequestStream after completion");
474        }
475        fidl::encoding::with_tls_decode_buf::<_, fidl::encoding::DefaultFuchsiaResourceDialect>(
476            |bytes, handles| {
477                match this.inner.channel().read_etc(cx, bytes, handles) {
478                    std::task::Poll::Ready(Ok(())) => {}
479                    std::task::Poll::Pending => return std::task::Poll::Pending,
480                    std::task::Poll::Ready(Err(zx_status::Status::PEER_CLOSED)) => {
481                        this.is_terminated = true;
482                        return std::task::Poll::Ready(None);
483                    }
484                    std::task::Poll::Ready(Err(e)) => {
485                        return std::task::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(
486                            e.into(),
487                        ))));
488                    }
489                }
490
491                // A message has been received from the channel
492                let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
493
494                std::task::Poll::Ready(Some(match header.ordinal {
495                    0x486e6eebf1f00657 => {
496                        header.validate_request_tx_id(fidl::MethodType::TwoWay)?;
497                        let mut req = fidl::new_empty!(
498                            InputOwnershipGetEventRequest,
499                            fidl::encoding::DefaultFuchsiaResourceDialect
500                        );
501                        fidl::encoding::Decoder::<fidl::encoding::DefaultFuchsiaResourceDialect>::decode_into::<InputOwnershipGetEventRequest>(&header, _body_bytes, handles, &mut req)?;
502                        let control_handle =
503                            InputOwnershipControlHandle { inner: this.inner.clone() };
504                        Ok(InputOwnershipRequest::GetEvent {
505                            target: req.target,
506
507                            responder: InputOwnershipGetEventResponder {
508                                control_handle: std::mem::ManuallyDrop::new(control_handle),
509                                tx_id: header.tx_id,
510                            },
511                        })
512                    }
513                    _ => Err(fidl::Error::UnknownOrdinal {
514                        ordinal: header.ordinal,
515                        protocol_name:
516                            <InputOwnershipMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME,
517                    }),
518                }))
519            },
520        )
521    }
522}
523
524/// Get information about ownership of input (replaces `DisplayOwnership`).
525///
526/// By default, user input is handled by the platform input pipeline
527/// (`SceneManager`) and delivered to applications via standard UI protocols
528/// (e.g. `fuchsia.ui.pointer.TouchSource`).
529///
530/// Low-level components (such as Starnix or Virtcon) that require direct access
531/// to hardware input devices via `fuchsia.input.report.Service` must observe this
532/// event to pause or resume reading from direct driver streams, preventing
533/// duplicate processing or input leakage.
534///
535/// This protocol intentionally assumes a system-wide singleton direct-client
536/// model where only one direct client or the platform pipeline consumes input
537/// at any given time.
538///
539/// During ownership transitions (e.g. switching display ownership or view
540/// focus), an intermediate state may occur where neither the direct client nor
541/// the platform pipeline owns input. During any unowned or transition state, all
542/// consumers (both direct clients and the platform pipeline) must pause reading
543/// and processing hardware input reports until their respective ownership signal
544/// is asserted.
545///
546/// Security note:
547/// A `ViewRef` is a duplicable identity token rather than proof of view ownership,
548/// and any caller with access to this protocol can replace the registered `ViewRef`.
549/// Therefore, `InputOwnership` must only be routed to trusted system components.
550#[derive(Debug)]
551pub enum InputOwnershipRequest {
552    /// Gets a duplicate handle to the shared kernel `ownership_event` whose
553    /// orthogonal signals inform clients and the system pipeline when direct
554    /// driver input access (`fuchsia.input.report.Service`) is granted or revoked:
555    ///
556    /// - `Virtcon` (`target` = `virtcon: {}`): owns input iff
557    ///   `InputOwnershipSignal.DISPLAY_UNOWNED` is asserted.
558    /// - `Starnix` (`target` = `view_ref`): owns direct input iff both
559    ///   `InputOwnershipSignal.DISPLAY_PLATFORM_OWNED` and
560    ///   `InputOwnershipSignal.INPUT_CLIENT_OWNED` are asserted.
561    /// - `SceneManager` (`target` = `platform: {}`): owns platform pipeline
562    ///   input iff both `InputOwnershipSignal.DISPLAY_PLATFORM_OWNED` and
563    ///   `InputOwnershipSignal.INPUT_PLATFORM_OWNED` are asserted (pauses whenever
564    ///   `DISPLAY_UNOWNED` or `INPUT_CLIENT_OWNED` is asserted).
565    ///
566    /// Requesting direct input ownership:
567    ///
568    /// Calling `GetEvent` with `target` = `view_ref` is also how a view requests
569    /// direct input ownership; there is no separate request method. `GetEvent`
570    /// supports pre-registering a valid `ViewRef` before the view is created or
571    /// attached to the `ViewTree`. On success, the server registers the `ViewRef`
572    /// as the system-wide direct input client, immediately evaluates it against
573    /// the latest `ViewTree` snapshot if one exists, and continues evaluating it
574    /// against the single-view + full-screen criteria on every subsequent `ViewTree`
575    /// update. `INPUT_CLIENT_OWNED` is asserted only while the registered view
576    /// meets those criteria; otherwise `INPUT_PLATFORM_OWNED` is asserted.
577    ///
578    /// - Registration is singleton and last-writer-wins: a successful call with
579    ///   a different `ViewRef` replaces any previously registered view. This
580    ///   mechanism is intended for a single trusted client replacing its own view
581    ///   rather than independent concurrent components: because every `GetEvent`
582    ///   call returns a handle to the same shared kernel `ownership_event`, replacing
583    ///   the registered `ViewRef` does not silence earlier callers' handles when
584    ///   their view is unlinked or destroyed and the new view goes fullscreen.
585    /// - If the `ViewTree` contains more than one view or overlay competing
586    ///   with the registered view, the criteria are not met and ownership
587    ///   falls back to the platform. Thus, when multiple views request direct
588    ///   input while coexisting in the `ViewTree`, none of them is granted
589    ///   direct input, regardless of which one registered last.
590    /// - Registration is tied to the lifetime of the view, not to this
591    ///   channel or the returned event. Unlinking the view from the `ViewTree`
592    ///   (placing it in `unconnected_views`) reverts ownership to
593    ///   `INPUT_PLATFORM_OWNED` while retaining the registration, so re-linking
594    ///   fullscreen restores `INPUT_CLIENT_OWNED`. Destroying the view permanently
595    ///   drops the registration, at which point ownership reverts to the platform.
596    /// - Calls with `virtcon: {}` or `platform: {}` only observe ownership and
597    ///   do not modify the registered direct client.
598    ///
599    /// If `target` is set to an unsupported or unknown variant, the call
600    /// returns `InputOwnershipError.INVALID_TARGET`.
601    GetEvent { target: InputOwnershipTarget, responder: InputOwnershipGetEventResponder },
602}
603
604impl InputOwnershipRequest {
605    #[allow(irrefutable_let_patterns)]
606    pub fn into_get_event(self) -> Option<(InputOwnershipTarget, InputOwnershipGetEventResponder)> {
607        if let InputOwnershipRequest::GetEvent { target, responder } = self {
608            Some((target, responder))
609        } else {
610            None
611        }
612    }
613
614    /// Name of the method defined in FIDL
615    pub fn method_name(&self) -> &'static str {
616        match *self {
617            InputOwnershipRequest::GetEvent { .. } => "get_event",
618        }
619    }
620}
621
622#[derive(Debug, Clone)]
623pub struct InputOwnershipControlHandle {
624    inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
625}
626
627impl InputOwnershipControlHandle {
628    pub fn shutdown_with_epitaph(&self, status: impl Into<fidl::Epitaph>) {
629        self.inner.shutdown_with_epitaph(status.into())
630    }
631}
632
633impl fidl::endpoints::ControlHandle for InputOwnershipControlHandle {
634    fn shutdown(&self) {
635        self.inner.shutdown()
636    }
637
638    fn shutdown_with_epitaph(&self, status: fidl::Epitaph) {
639        self.inner.shutdown_with_epitaph(status)
640    }
641
642    fn is_closed(&self) -> bool {
643        self.inner.channel().is_closed()
644    }
645    fn on_closed(&self) -> fidl::OnSignalsRef<'_> {
646        self.inner.channel().on_closed()
647    }
648
649    #[cfg(target_os = "fuchsia")]
650    fn signal_peer(
651        &self,
652        clear_mask: zx::Signals,
653        set_mask: zx::Signals,
654    ) -> Result<(), zx_status::Status> {
655        use fidl::Peered;
656        self.inner.channel().signal_peer(clear_mask, set_mask)
657    }
658}
659
660impl InputOwnershipControlHandle {}
661
662#[must_use = "FIDL methods require a response to be sent"]
663#[derive(Debug)]
664pub struct InputOwnershipGetEventResponder {
665    control_handle: std::mem::ManuallyDrop<InputOwnershipControlHandle>,
666    tx_id: u32,
667}
668
669/// Set the the channel to be shutdown (see [`InputOwnershipControlHandle::shutdown`])
670/// if the responder is dropped without sending a response, so that the client
671/// doesn't hang. To prevent this behavior, call `drop_without_shutdown`.
672impl std::ops::Drop for InputOwnershipGetEventResponder {
673    fn drop(&mut self) {
674        self.control_handle.shutdown();
675        // Safety: drops once, never accessed again
676        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
677    }
678}
679
680impl fidl::endpoints::Responder for InputOwnershipGetEventResponder {
681    type ControlHandle = InputOwnershipControlHandle;
682
683    fn control_handle(&self) -> &InputOwnershipControlHandle {
684        &self.control_handle
685    }
686
687    fn drop_without_shutdown(mut self) {
688        // Safety: drops once, never accessed again due to mem::forget
689        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
690        // Prevent Drop from running (which would shut down the channel)
691        std::mem::forget(self);
692    }
693}
694
695impl InputOwnershipGetEventResponder {
696    /// Sends a response to the FIDL transaction.
697    ///
698    /// Sets the channel to shutdown if an error occurs.
699    pub fn send(
700        self,
701        mut result: Result<fidl::Event, InputOwnershipError>,
702    ) -> Result<(), fidl::Error> {
703        let _result = self.send_raw(result);
704        if _result.is_err() {
705            self.control_handle.shutdown();
706        }
707        self.drop_without_shutdown();
708        _result
709    }
710
711    /// Similar to "send" but does not shutdown the channel if an error occurs.
712    pub fn send_no_shutdown_on_err(
713        self,
714        mut result: Result<fidl::Event, InputOwnershipError>,
715    ) -> Result<(), fidl::Error> {
716        let _result = self.send_raw(result);
717        self.drop_without_shutdown();
718        _result
719    }
720
721    fn send_raw(
722        &self,
723        mut result: Result<fidl::Event, InputOwnershipError>,
724    ) -> Result<(), fidl::Error> {
725        self.control_handle.inner.send::<fidl::encoding::ResultType<
726            InputOwnershipGetEventResponse,
727            InputOwnershipError,
728        >>(
729            result.map(|ownership_event| (ownership_event,)),
730            self.tx_id,
731            0x486e6eebf1f00657,
732            fidl::encoding::DynamicFlags::empty(),
733        )
734    }
735}
736
737mod internal {
738    use super::*;
739
740    impl fidl::encoding::ResourceTypeMarker for InputOwnershipGetEventRequest {
741        type Borrowed<'a> = &'a mut Self;
742        fn take_or_borrow<'a>(
743            value: &'a mut <Self as fidl::encoding::TypeMarker>::Owned,
744        ) -> Self::Borrowed<'a> {
745            value
746        }
747    }
748
749    unsafe impl fidl::encoding::TypeMarker for InputOwnershipGetEventRequest {
750        type Owned = Self;
751
752        #[inline(always)]
753        fn inline_align(_context: fidl::encoding::Context) -> usize {
754            8
755        }
756
757        #[inline(always)]
758        fn inline_size(_context: fidl::encoding::Context) -> usize {
759            16
760        }
761    }
762
763    unsafe impl
764        fidl::encoding::Encode<
765            InputOwnershipGetEventRequest,
766            fidl::encoding::DefaultFuchsiaResourceDialect,
767        > for &mut InputOwnershipGetEventRequest
768    {
769        #[inline]
770        unsafe fn encode(
771            self,
772            encoder: &mut fidl::encoding::Encoder<
773                '_,
774                fidl::encoding::DefaultFuchsiaResourceDialect,
775            >,
776            offset: usize,
777            _depth: fidl::encoding::Depth,
778        ) -> fidl::Result<()> {
779            encoder.debug_check_bounds::<InputOwnershipGetEventRequest>(offset);
780            // Delegate to tuple encoding.
781            fidl::encoding::Encode::<
782                InputOwnershipGetEventRequest,
783                fidl::encoding::DefaultFuchsiaResourceDialect,
784            >::encode(
785                (<InputOwnershipTarget as fidl::encoding::ResourceTypeMarker>::take_or_borrow(
786                    &mut self.target,
787                ),),
788                encoder,
789                offset,
790                _depth,
791            )
792        }
793    }
794    unsafe impl<
795        T0: fidl::encoding::Encode<InputOwnershipTarget, fidl::encoding::DefaultFuchsiaResourceDialect>,
796    >
797        fidl::encoding::Encode<
798            InputOwnershipGetEventRequest,
799            fidl::encoding::DefaultFuchsiaResourceDialect,
800        > for (T0,)
801    {
802        #[inline]
803        unsafe fn encode(
804            self,
805            encoder: &mut fidl::encoding::Encoder<
806                '_,
807                fidl::encoding::DefaultFuchsiaResourceDialect,
808            >,
809            offset: usize,
810            depth: fidl::encoding::Depth,
811        ) -> fidl::Result<()> {
812            encoder.debug_check_bounds::<InputOwnershipGetEventRequest>(offset);
813            // Zero out padding regions. There's no need to apply masks
814            // because the unmasked parts will be overwritten by fields.
815            // Write the fields.
816            self.0.encode(encoder, offset + 0, depth)?;
817            Ok(())
818        }
819    }
820
821    impl fidl::encoding::Decode<Self, fidl::encoding::DefaultFuchsiaResourceDialect>
822        for InputOwnershipGetEventRequest
823    {
824        #[inline(always)]
825        fn new_empty() -> Self {
826            Self {
827                target: fidl::new_empty!(
828                    InputOwnershipTarget,
829                    fidl::encoding::DefaultFuchsiaResourceDialect
830                ),
831            }
832        }
833
834        #[inline]
835        unsafe fn decode(
836            &mut self,
837            decoder: &mut fidl::encoding::Decoder<
838                '_,
839                fidl::encoding::DefaultFuchsiaResourceDialect,
840            >,
841            offset: usize,
842            _depth: fidl::encoding::Depth,
843        ) -> fidl::Result<()> {
844            decoder.debug_check_bounds::<Self>(offset);
845            // Verify that padding bytes are zero.
846            fidl::decode!(
847                InputOwnershipTarget,
848                fidl::encoding::DefaultFuchsiaResourceDialect,
849                &mut self.target,
850                decoder,
851                offset + 0,
852                _depth
853            )?;
854            Ok(())
855        }
856    }
857
858    impl fidl::encoding::ResourceTypeMarker for InputOwnershipGetEventResponse {
859        type Borrowed<'a> = &'a mut Self;
860        fn take_or_borrow<'a>(
861            value: &'a mut <Self as fidl::encoding::TypeMarker>::Owned,
862        ) -> Self::Borrowed<'a> {
863            value
864        }
865    }
866
867    unsafe impl fidl::encoding::TypeMarker for InputOwnershipGetEventResponse {
868        type Owned = Self;
869
870        #[inline(always)]
871        fn inline_align(_context: fidl::encoding::Context) -> usize {
872            4
873        }
874
875        #[inline(always)]
876        fn inline_size(_context: fidl::encoding::Context) -> usize {
877            4
878        }
879    }
880
881    unsafe impl
882        fidl::encoding::Encode<
883            InputOwnershipGetEventResponse,
884            fidl::encoding::DefaultFuchsiaResourceDialect,
885        > for &mut InputOwnershipGetEventResponse
886    {
887        #[inline]
888        unsafe fn encode(
889            self,
890            encoder: &mut fidl::encoding::Encoder<
891                '_,
892                fidl::encoding::DefaultFuchsiaResourceDialect,
893            >,
894            offset: usize,
895            _depth: fidl::encoding::Depth,
896        ) -> fidl::Result<()> {
897            encoder.debug_check_bounds::<InputOwnershipGetEventResponse>(offset);
898            // Delegate to tuple encoding.
899            fidl::encoding::Encode::<
900                InputOwnershipGetEventResponse,
901                fidl::encoding::DefaultFuchsiaResourceDialect,
902            >::encode(
903                (<fidl::encoding::HandleType<
904                    fidl::Event,
905                    { fidl::ObjectType::EVENT.into_raw() },
906                    49155,
907                > as fidl::encoding::ResourceTypeMarker>::take_or_borrow(
908                    &mut self.ownership_event,
909                ),),
910                encoder,
911                offset,
912                _depth,
913            )
914        }
915    }
916    unsafe impl<
917        T0: fidl::encoding::Encode<
918                fidl::encoding::HandleType<
919                    fidl::Event,
920                    { fidl::ObjectType::EVENT.into_raw() },
921                    49155,
922                >,
923                fidl::encoding::DefaultFuchsiaResourceDialect,
924            >,
925    >
926        fidl::encoding::Encode<
927            InputOwnershipGetEventResponse,
928            fidl::encoding::DefaultFuchsiaResourceDialect,
929        > for (T0,)
930    {
931        #[inline]
932        unsafe fn encode(
933            self,
934            encoder: &mut fidl::encoding::Encoder<
935                '_,
936                fidl::encoding::DefaultFuchsiaResourceDialect,
937            >,
938            offset: usize,
939            depth: fidl::encoding::Depth,
940        ) -> fidl::Result<()> {
941            encoder.debug_check_bounds::<InputOwnershipGetEventResponse>(offset);
942            // Zero out padding regions. There's no need to apply masks
943            // because the unmasked parts will be overwritten by fields.
944            // Write the fields.
945            self.0.encode(encoder, offset + 0, depth)?;
946            Ok(())
947        }
948    }
949
950    impl fidl::encoding::Decode<Self, fidl::encoding::DefaultFuchsiaResourceDialect>
951        for InputOwnershipGetEventResponse
952    {
953        #[inline(always)]
954        fn new_empty() -> Self {
955            Self {
956                ownership_event: fidl::new_empty!(fidl::encoding::HandleType<fidl::Event, { fidl::ObjectType::EVENT.into_raw() }, 49155>, fidl::encoding::DefaultFuchsiaResourceDialect),
957            }
958        }
959
960        #[inline]
961        unsafe fn decode(
962            &mut self,
963            decoder: &mut fidl::encoding::Decoder<
964                '_,
965                fidl::encoding::DefaultFuchsiaResourceDialect,
966            >,
967            offset: usize,
968            _depth: fidl::encoding::Depth,
969        ) -> fidl::Result<()> {
970            decoder.debug_check_bounds::<Self>(offset);
971            // Verify that padding bytes are zero.
972            fidl::decode!(fidl::encoding::HandleType<fidl::Event, { fidl::ObjectType::EVENT.into_raw() }, 49155>, fidl::encoding::DefaultFuchsiaResourceDialect, &mut self.ownership_event, decoder, offset + 0, _depth)?;
973            Ok(())
974        }
975    }
976
977    impl fidl::encoding::ResourceTypeMarker for InputOwnershipTarget {
978        type Borrowed<'a> = &'a mut Self;
979        fn take_or_borrow<'a>(
980            value: &'a mut <Self as fidl::encoding::TypeMarker>::Owned,
981        ) -> Self::Borrowed<'a> {
982            value
983        }
984    }
985
986    unsafe impl fidl::encoding::TypeMarker for InputOwnershipTarget {
987        type Owned = Self;
988
989        #[inline(always)]
990        fn inline_align(_context: fidl::encoding::Context) -> usize {
991            8
992        }
993
994        #[inline(always)]
995        fn inline_size(_context: fidl::encoding::Context) -> usize {
996            16
997        }
998    }
999
1000    unsafe impl
1001        fidl::encoding::Encode<InputOwnershipTarget, fidl::encoding::DefaultFuchsiaResourceDialect>
1002        for &mut InputOwnershipTarget
1003    {
1004        #[inline]
1005        unsafe fn encode(
1006            self,
1007            encoder: &mut fidl::encoding::Encoder<
1008                '_,
1009                fidl::encoding::DefaultFuchsiaResourceDialect,
1010            >,
1011            offset: usize,
1012            _depth: fidl::encoding::Depth,
1013        ) -> fidl::Result<()> {
1014            encoder.debug_check_bounds::<InputOwnershipTarget>(offset);
1015            encoder.write_num::<u64>(self.ordinal(), offset);
1016            match self {
1017            InputOwnershipTarget::ViewRef(ref mut val) => {
1018                fidl::encoding::encode_in_envelope::<fidl_fuchsia_ui_views::ViewRef, fidl::encoding::DefaultFuchsiaResourceDialect>(
1019                    <fidl_fuchsia_ui_views::ViewRef as fidl::encoding::ResourceTypeMarker>::take_or_borrow(val),
1020                    encoder, offset + 8, _depth
1021                )
1022            }
1023            InputOwnershipTarget::Virtcon(ref val) => {
1024                fidl::encoding::encode_in_envelope::<Virtcon, fidl::encoding::DefaultFuchsiaResourceDialect>(
1025                    <Virtcon as fidl::encoding::ValueTypeMarker>::borrow(val),
1026                    encoder, offset + 8, _depth
1027                )
1028            }
1029            InputOwnershipTarget::Platform(ref val) => {
1030                fidl::encoding::encode_in_envelope::<Platform, fidl::encoding::DefaultFuchsiaResourceDialect>(
1031                    <Platform as fidl::encoding::ValueTypeMarker>::borrow(val),
1032                    encoder, offset + 8, _depth
1033                )
1034            }
1035            InputOwnershipTarget::__SourceBreaking { .. } => Err(fidl::Error::UnknownUnionTag),
1036        }
1037        }
1038    }
1039
1040    impl fidl::encoding::Decode<Self, fidl::encoding::DefaultFuchsiaResourceDialect>
1041        for InputOwnershipTarget
1042    {
1043        #[inline(always)]
1044        fn new_empty() -> Self {
1045            Self::__SourceBreaking { unknown_ordinal: 0 }
1046        }
1047
1048        #[inline]
1049        unsafe fn decode(
1050            &mut self,
1051            decoder: &mut fidl::encoding::Decoder<
1052                '_,
1053                fidl::encoding::DefaultFuchsiaResourceDialect,
1054            >,
1055            offset: usize,
1056            mut depth: fidl::encoding::Depth,
1057        ) -> fidl::Result<()> {
1058            decoder.debug_check_bounds::<Self>(offset);
1059            #[allow(unused_variables)]
1060            let next_out_of_line = decoder.next_out_of_line();
1061            let handles_before = decoder.remaining_handles();
1062            let (ordinal, inlined, num_bytes, num_handles) =
1063                fidl::encoding::decode_union_inline_portion(decoder, offset)?;
1064
1065            let member_inline_size = match ordinal {
1066                1 => <fidl_fuchsia_ui_views::ViewRef as fidl::encoding::TypeMarker>::inline_size(
1067                    decoder.context,
1068                ),
1069                2 => <Virtcon as fidl::encoding::TypeMarker>::inline_size(decoder.context),
1070                3 => <Platform as fidl::encoding::TypeMarker>::inline_size(decoder.context),
1071                0 => return Err(fidl::Error::UnknownUnionTag),
1072                _ => num_bytes as usize,
1073            };
1074
1075            if inlined != (member_inline_size <= 4) {
1076                return Err(fidl::Error::InvalidInlineBitInEnvelope);
1077            }
1078            let _inner_offset;
1079            if inlined {
1080                decoder.check_inline_envelope_padding(offset + 8, member_inline_size)?;
1081                _inner_offset = offset + 8;
1082            } else {
1083                depth.increment()?;
1084                _inner_offset = decoder.out_of_line_offset(member_inline_size)?;
1085            }
1086            match ordinal {
1087                1 => {
1088                    #[allow(irrefutable_let_patterns)]
1089                    if let InputOwnershipTarget::ViewRef(_) = self {
1090                        // Do nothing, read the value into the object
1091                    } else {
1092                        // Initialize `self` to the right variant
1093                        *self = InputOwnershipTarget::ViewRef(fidl::new_empty!(
1094                            fidl_fuchsia_ui_views::ViewRef,
1095                            fidl::encoding::DefaultFuchsiaResourceDialect
1096                        ));
1097                    }
1098                    #[allow(irrefutable_let_patterns)]
1099                    if let InputOwnershipTarget::ViewRef(ref mut val) = self {
1100                        fidl::decode!(
1101                            fidl_fuchsia_ui_views::ViewRef,
1102                            fidl::encoding::DefaultFuchsiaResourceDialect,
1103                            val,
1104                            decoder,
1105                            _inner_offset,
1106                            depth
1107                        )?;
1108                    } else {
1109                        unreachable!()
1110                    }
1111                }
1112                2 => {
1113                    #[allow(irrefutable_let_patterns)]
1114                    if let InputOwnershipTarget::Virtcon(_) = self {
1115                        // Do nothing, read the value into the object
1116                    } else {
1117                        // Initialize `self` to the right variant
1118                        *self = InputOwnershipTarget::Virtcon(fidl::new_empty!(
1119                            Virtcon,
1120                            fidl::encoding::DefaultFuchsiaResourceDialect
1121                        ));
1122                    }
1123                    #[allow(irrefutable_let_patterns)]
1124                    if let InputOwnershipTarget::Virtcon(ref mut val) = self {
1125                        fidl::decode!(
1126                            Virtcon,
1127                            fidl::encoding::DefaultFuchsiaResourceDialect,
1128                            val,
1129                            decoder,
1130                            _inner_offset,
1131                            depth
1132                        )?;
1133                    } else {
1134                        unreachable!()
1135                    }
1136                }
1137                3 => {
1138                    #[allow(irrefutable_let_patterns)]
1139                    if let InputOwnershipTarget::Platform(_) = self {
1140                        // Do nothing, read the value into the object
1141                    } else {
1142                        // Initialize `self` to the right variant
1143                        *self = InputOwnershipTarget::Platform(fidl::new_empty!(
1144                            Platform,
1145                            fidl::encoding::DefaultFuchsiaResourceDialect
1146                        ));
1147                    }
1148                    #[allow(irrefutable_let_patterns)]
1149                    if let InputOwnershipTarget::Platform(ref mut val) = self {
1150                        fidl::decode!(
1151                            Platform,
1152                            fidl::encoding::DefaultFuchsiaResourceDialect,
1153                            val,
1154                            decoder,
1155                            _inner_offset,
1156                            depth
1157                        )?;
1158                    } else {
1159                        unreachable!()
1160                    }
1161                }
1162                #[allow(deprecated)]
1163                ordinal => {
1164                    for _ in 0..num_handles {
1165                        decoder.drop_next_handle()?;
1166                    }
1167                    *self = InputOwnershipTarget::__SourceBreaking { unknown_ordinal: ordinal };
1168                }
1169            }
1170            if !inlined && decoder.next_out_of_line() != next_out_of_line + (num_bytes as usize) {
1171                return Err(fidl::Error::InvalidNumBytesInEnvelope);
1172            }
1173            if handles_before != decoder.remaining_handles() + (num_handles as usize) {
1174                return Err(fidl::Error::InvalidNumHandlesInEnvelope);
1175            }
1176            Ok(())
1177        }
1178    }
1179}