float-clock-wayland 0.2.1

Always-on-top floating desktop clock widget for Wayland compositors.
use gtk::prelude::*;
use gtk::ApplicationWindow;
use gtk_layer_shell::{Edge, Layer, LayerShell};
use std::cell::Cell;
use std::rc::Rc;

pub struct LayerShellWindow {
    window: ApplicationWindow,
    margin_left: Rc<Cell<i32>>,
    margin_top: Rc<Cell<i32>>,
}

impl LayerShellWindow {
    pub fn new(app: &gtk::Application, initial_pos: (i32, i32), layer_setting: &str) -> Self {
        let window = ApplicationWindow::builder()
            .application(app)
            .app_paintable(true)
            .build();

        window.init_layer_shell();

        let target_layer = match layer_setting.to_lowercase().as_str() {
            "overlay" => Layer::Overlay,
            "bottom" => Layer::Bottom,
            "background" => Layer::Background,
            _ => Layer::Top,
        };

        window.set_layer(target_layer);
        window.set_anchor(Edge::Top, true);
        window.set_anchor(Edge::Left, true);

        window.set_layer_shell_margin(Edge::Left, initial_pos.0);
        window.set_layer_shell_margin(Edge::Top, initial_pos.1);

        if let Some(visual) = WidgetExt::screen(&window).and_then(|s| s.rgba_visual()) {
            window.set_visual(Some(&visual));
        }

        Self {
            window,
            margin_left: Rc::new(Cell::new(initial_pos.0)),
            margin_top: Rc::new(Cell::new(initial_pos.1)),
        }
    }

    pub fn window(&self) -> &ApplicationWindow {
        &self.window
    }

    pub fn set_margin(&self, margin: (i32, i32)) {
        self.margin_left.set(margin.0);
        self.margin_top.set(margin.1);
        self.window.set_layer_shell_margin(Edge::Left, margin.0);
        self.window.set_layer_shell_margin(Edge::Top, margin.1);
    }

    #[allow(dead_code)]
    pub fn current_margin(&self) -> (i32, i32) {
        (self.margin_left.get(), self.margin_top.get())
    }

    pub fn close(&self) {
        self.window.close();
    }
}