1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright 2018 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.

use {
    crate::aura_shell::AuraOutput,
    crate::client::Client,
    crate::object::{ObjectRef, RequestReceiver},
    anyhow::Error,
    fidl_fuchsia_ui_gfx::DisplayInfo,
    fuchsia_wayland_core as wl,
    wayland_server_protocol::{wl_output, WlOutput, WlOutputEvent, WlOutputRequest},
};

/// An implementation of the wl_output global.
pub struct Output {
    aura_output: Option<ObjectRef<AuraOutput>>,
}

impl Output {
    /// Creates a new `Output`.
    pub fn new() -> Self {
        Output { aura_output: None }
    }

    pub fn set_aura_output(&mut self, aura_output: ObjectRef<AuraOutput>) {
        self.aura_output = Some(aura_output);
    }

    pub fn post_output_info(
        this: wl::ObjectId,
        client: &Client,
        display_info: &DisplayInfo,
    ) -> Result<(), Error> {
        // Just report the current display info as our only mode.
        client.event_queue().post(
            this,
            WlOutputEvent::Mode {
                flags: wl_output::Mode::Current | wl_output::Mode::Preferred,
                width: display_info.width_in_px as i32,
                height: display_info.height_in_px as i32,
                // Vertical refresh rate in mHz.
                refresh: 60 * 1000,
            },
        )?;
        client.event_queue().post(
            this,
            WlOutputEvent::Geometry {
                make: "unknown".to_string(),
                model: "unknown".to_string(),
                x: 0,
                y: 0,
                subpixel: wl_output::Subpixel::None,
                transform: wl_output::Transform::Normal,
                // TODO(tjdetwiler): at 96dpi pixels would be ~.264mm.
                // Approximate this as .25 as a placeholder until we can query
                // scenic for real resolution.
                physical_width: display_info.width_in_px as i32 / 4,
                physical_height: display_info.height_in_px as i32 / 4,
            },
        )?;
        client.event_queue().post(this, WlOutputEvent::Scale { factor: 1 })?;
        Ok(())
    }

    pub fn post_output_done(this: wl::ObjectId, client: &Client) -> Result<(), Error> {
        client.event_queue().post(this, WlOutputEvent::Done)
    }

    pub fn post_display_info(
        this: ObjectRef<Self>,
        client: &Client,
        display_info: &DisplayInfo,
    ) -> Result<(), Error> {
        let output = this.get(client)?;

        // Post basic output info.
        Self::post_output_info(this.id(), client, display_info)?;

        // Post additional Aura output info if requested.
        if let Some(aura_output) = output.aura_output {
            AuraOutput::post_display_info(aura_output, client, display_info)?;
        }

        // Any series of output events must be concluded with a 'done' event.
        Self::post_output_done(this.id(), client)?;
        Ok(())
    }
}

impl RequestReceiver<WlOutput> for Output {
    fn receive(
        this: ObjectRef<Self>,
        request: WlOutputRequest,
        client: &mut Client,
    ) -> Result<(), Error> {
        let WlOutputRequest::Release = request;
        client.delete_id(this.id())?;
        Ok(())
    }
}