pinnacle_api/
pinnacle.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Compositor management.
6//!
7//! This module provides general compositor actions like quitting and reloading the config.
8
9use pinnacle_api_defs::pinnacle::{
10    self,
11    v1::{
12        BackendRequest, KeepaliveRequest, KeepaliveResponse, QuitRequest, ReloadConfigRequest,
13        SetLastErrorRequest, SetXwaylandClientSelfScaleRequest, TakeLastErrorRequest,
14    },
15};
16use tonic::Streaming;
17
18use crate::{client::Client, BlockOnTokio};
19
20/// A backend that Pinnacle runs with.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum Backend {
23    /// Pinnacle is running in a tty, possibly started through a display manager.
24    Tty,
25    /// Pinnacle is running in a window inside another compositor, window manager,
26    /// or desktop environment.
27    Window,
28}
29
30/// Quits Pinnacle.
31pub fn quit() {
32    // Ignore errors here, the config is meant to be killed
33    let _ = Client::pinnacle().quit(QuitRequest {}).block_on_tokio();
34}
35
36/// Reloads the currently active config.
37pub fn reload_config() {
38    // Ignore errors here, the config is meant to be killed
39    let _ = Client::pinnacle()
40        .reload_config(ReloadConfigRequest {})
41        .block_on_tokio();
42}
43
44/// Gets the currently running [`Backend`].
45pub fn backend() -> Backend {
46    let backend = Client::pinnacle()
47        .backend(BackendRequest {})
48        .block_on_tokio()
49        .unwrap()
50        .into_inner()
51        .backend();
52
53    match backend {
54        pinnacle::v1::Backend::Unspecified => panic!("received unspecified backend"),
55        pinnacle::v1::Backend::Window => Backend::Window,
56        pinnacle::v1::Backend::Tty => Backend::Tty,
57    }
58}
59
60/// Sets whether or not xwayland clients should scale themselves.
61///
62/// If `true`, xwayland clients will be told they are on an output with a larger or smaller size than
63/// normal then rescaled to replicate being on an output with a scale of 1.
64///
65/// Xwayland clients that support DPI scaling will scale properly, leading to crisp and correct scaling
66/// with fractional output scales. Those that don't, like `xterm`, will render as if they are on outputs
67/// with scale 1, and their scale will be slightly incorrect on outputs with fractional scale.
68///
69/// Results may vary if you have multiple outputs with different scales.
70pub fn set_xwayland_self_scaling(should_self_scale: bool) {
71    Client::pinnacle()
72        .set_xwayland_client_self_scale(SetXwaylandClientSelfScaleRequest {
73            self_scale: should_self_scale,
74        })
75        .block_on_tokio()
76        .unwrap();
77}
78
79/// Sets an error message that is held by the compositor until it is retrieved.
80pub fn set_last_error(error: impl std::fmt::Display) {
81    Client::pinnacle()
82        .set_last_error(SetLastErrorRequest {
83            error: error.to_string(),
84        })
85        .block_on_tokio()
86        .unwrap();
87}
88
89/// Gets and consumes the last error message set, possibly by a previously
90/// running config.
91pub fn take_last_error() -> Option<String> {
92    Client::pinnacle()
93        .take_last_error(TakeLastErrorRequest {})
94        .block_on_tokio()
95        .unwrap()
96        .into_inner()
97        .error
98}
99
100pub(crate) async fn keepalive() -> (
101    tokio::sync::mpsc::Sender<KeepaliveRequest>,
102    Streaming<KeepaliveResponse>,
103) {
104    let (send, recv) = tokio::sync::mpsc::channel::<KeepaliveRequest>(5);
105    let recv = tokio_stream::wrappers::ReceiverStream::new(recv);
106    let streaming = Client::pinnacle()
107        .keepalive(recv)
108        .await
109        .unwrap()
110        .into_inner();
111    (send, streaming)
112}