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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//! Traits and types for the shell.
//!
//! A shell is the user facing component of the compositor. It manages a set of
//! surfaces, and is responsible of presenting them to the user, as well as
//! accepting user interactions. It is in control of all the visual aspects of
//! a compositor.

pub mod buffers;
pub mod output;
pub mod surface;
pub mod xdg;
use std::cell::RefCell;

use runa_core::events::EventSource;
use runa_wayland_protocols::wayland::{wl_keyboard::v9 as wl_keyboard, wl_seat::v9 as wl_seat};

/// Events emitted by a shell
#[derive(Clone, Debug, Copy)]
pub enum ShellEvent {
    /// The current set of surfaces have been rendered to screen.
    ///
    /// TODO: in future, we wants to be finer grained. as one render doesn't
    /// necessarily render all of the surfaces, e.g. some surfaces might not
    /// be visible.
    Render,
}

/// Shell
///
/// This is the fundamental interface to the compositor's shell. A shell needs
/// to support management of surface states, i.e. allocation, deallocation, and
/// access. The allocated states are reference via a token, in order to avoid
/// lifetime and ownership difficulties.
///
/// The shell interface also defines a number of callbacks, which `runa-orbiter`
/// will call in response to various operations done to surfaces.
///
/// The shell is also an event source, it must emit the event defined in
/// [`ShellEvent`] for various interfaces implemented here to function properly.
pub trait Shell: Sized + EventSource<ShellEvent> + 'static {
    /// A token to surfaces.
    ///
    /// Eq and PartialEq should compare if the keys point to the same surface
    /// state.
    ///
    /// Tokens to surface states should be reference counted, if a token to
    /// a surface state exists, the surface state should not be freed.
    ///
    /// A token must be released, impls of Shell can choose to panic
    /// if it was dropped it without being released.
    type Token: std::fmt::Debug + Copy + PartialEq + Eq + std::hash::Hash;

    /// A buffer type. We allow a user supplied buffer type instead of `dyn
    /// Buffer` to avoid virutal call overhead, and allow for a more
    /// flexible Buffer trait.
    type Buffer: buffers::BufferLike;

    /// Allocate a SurfaceState and returns a handle to it.
    fn allocate(&mut self, state: surface::SurfaceState<Self>) -> Self::Token;

    /// Release a token.
    fn destroy(&mut self, key: Self::Token);

    /// Get a reference to a SurfaceState by key.
    ///
    /// Returns None if the key is invalid.
    fn get(&self, key: Self::Token) -> &surface::SurfaceState<Self>;

    /// Get a mutable reference to a SurfaceState.
    fn get_mut(&mut self, key: Self::Token) -> &mut surface::SurfaceState<Self>;

    /// Get mutable references to multiple SurfaceStates.
    ///
    /// # Panic
    ///
    /// May panic if any of the keys are invalid, or if any two of the keys are
    /// equal.
    fn get_disjoint_mut<const N: usize>(
        &mut self,
        keys: [Self::Token; N],
    ) -> [&mut surface::SurfaceState<Self>; N];

    /// Callback which is called when a role is added to a surface corresponds
    /// to the given surface state. A role can be attached using a committed
    /// state or a pending state, and they should have the same effects.
    ///
    /// # Panic
    ///
    /// May panic if the handle is invalid.
    #[allow(unused_variables)]
    fn role_added(&mut self, key: Self::Token, role: &'static str) {}

    /// Callback that is called when a surface has its assigned role
    /// deactivated.
    ///
    /// # Panic
    ///
    /// May panic if the handle is invalid.
    #[allow(unused_variables)]
    fn role_deactivated(&mut self, key: Self::Token, role: &'static str) {}

    /// A commit happened on the surface which used to have surface state `old`.
    /// The new state is `new`. If `old` is None, this is the first commit
    /// on the surface. After this call returns, `new` is considered currently
    /// committed.
    ///
    /// old can be equal to new, if no changes has been made to double buffered
    /// surface states since the last commit.
    ///
    /// Note, for synced subsurface, this is called when `new` became cached
    /// state.
    ///
    /// # Panic
    ///
    /// This function may panic if either handle is invalid. Or if
    /// `old` has never been committed before.
    #[allow(unused_variables)]
    fn post_commit(&mut self, old: Option<Self::Token>, new: Self::Token) {}
}

/// Shell access
///
/// Implemented by the server context (see
/// [`ServerContext`](runa_core::client::traits::Client::ServerContext)) to
/// indicate that it has a shell.
pub trait HasShell: buffers::HasBuffer {
    /// Type of the shell
    type Shell: Shell<Buffer = <Self as buffers::HasBuffer>::Buffer>;

    /// Get a reference to the shell
    fn shell(&self) -> &RefCell<Self::Shell>;
}

/// Keyboard repeat repeat_info
///
/// See `wl_keyboard.repeat_info` for more details.
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RepeatInfo {
    pub rate:  i32,
    pub delay: i32,
}

/// Keymap
#[derive(Debug)]
pub struct Keymap {
    /// Format of the keymap
    pub format: wl_keyboard::enums::KeymapFormat,
    /// File descriptor of the keymap
    pub fd:     std::os::unix::io::OwnedFd,
    /// Size of the keymap in bytes
    pub size:   u32,
}

/// Events emitted by a seat
///
/// TODO: change to a bitflag struct, and use the aggregate event source.
#[derive(Clone, Debug, Copy)]
pub enum SeatEvent {
    /// The keymap has changed
    KeymapChanged,
    /// The repeat info has changed
    RepeatInfoChanged,
    /// The capabilities of the seat has changed
    CapabilitiesChanged,
    /// The name of the seat has changed
    NameChanged,
}

/// Seat
///
/// A seat is a set of input output devices attached to a computer. This trait
/// is mainly used by interface implementations to get information about mouse
/// and keyboard devices attached.
///
/// This is also an event source, it must emit events when information about the
/// seat changes.
///
/// This needs to be implemented by the
/// [`ServerContext`](runa_core::client::traits::Client::ServerContext).
pub trait Seat: EventSource<SeatEvent> {
    /// Get the capabilities of the seat.
    ///
    /// Whether the seat has a pointer, keyboard, or touch device attached.
    fn capabilities(&self) -> wl_seat::enums::Capability;

    /// Get the repeat info of the keyboard.
    fn repeat_info(&self) -> RepeatInfo;

    /// Get the current keymap.
    fn keymap(&self) -> &Keymap;

    /// Get the name of the seat.
    fn name(&self) -> &str;
}