hyprshell_windows_lib/overview/
create.rs

1use crate::global::{WindowsOverviewConfig, WindowsOverviewData, WindowsOverviewMonitorData};
2use adw::gtk::gdk::{Display, Monitor};
3use adw::gtk::prelude::*;
4use adw::gtk::{Application, ApplicationWindow, FlowBox, Orientation, Overlay, SelectionMode};
5use anyhow::Context;
6use config_lib::{FilterBy, Overview, Windows};
7use core_lib::{HyprlandData, OVERVIEW_NAMESPACE};
8use exec_lib::{get_initial_active, get_monitors};
9use gtk4_layer_shell::{Edge, KeyboardMode, Layer, LayerShell};
10use std::collections::HashMap;
11use tracing::{debug, debug_span};
12
13pub fn create_windows_overview_window(
14    app: &Application,
15    overview: &Overview,
16    windows: &Windows,
17) -> anyhow::Result<WindowsOverviewData> {
18    let _span = debug_span!("create_windows_overview_window").entered();
19    let mut window_list = HashMap::new();
20
21    let monitors = get_monitors();
22    if let Ok(display) = Display::default().context("Could not connect to a display") {
23        let gtk_monitors = display
24            .monitors()
25            .iter()
26            .filter_map(Result::ok)
27            .collect::<Vec<Monitor>>();
28
29        for gtk_monitor in gtk_monitors {
30            let monitor_name = gtk_monitor.connector().unwrap_or_default();
31            if let Some(monitor) = monitors.iter().find(|m| m.name == monitor_name) {
32                let workspaces_flow = FlowBox::builder()
33                    .selection_mode(SelectionMode::None)
34                    .orientation(Orientation::Horizontal)
35                    .max_children_per_line(u32::from(windows.items_per_row))
36                    .min_children_per_line(u32::from(windows.items_per_row))
37                    .build();
38
39                let workspaces_flow_overlay = Overlay::builder()
40                    .child(&workspaces_flow)
41                    .css_classes(["monitor"])
42                    .build();
43
44                let window = ApplicationWindow::builder()
45                    .css_classes(["window"])
46                    .application(app)
47                    .child(&workspaces_flow_overlay)
48                    .default_height(10)
49                    .default_width(10)
50                    .build();
51
52                window.init_layer_shell();
53                window.set_namespace(Some(OVERVIEW_NAMESPACE));
54                window.set_layer(Layer::Top);
55                window.set_anchor(Edge::Top, true);
56                window.set_margin(Edge::Top, 435i32);
57                window.set_keyboard_mode(KeyboardMode::None);
58                window.set_monitor(Some(&gtk_monitor));
59                window.present();
60                window.set_visible(false);
61
62                debug!(
63                    "Created overview window ({}) for monitor {monitor_name:?}",
64                    window.id()
65                );
66                window_list.insert(
67                    window,
68                    WindowsOverviewMonitorData::new(monitor.id, workspaces_flow),
69                );
70            }
71        }
72    }
73
74    let active = get_initial_active().context("unable to get initial active data")?;
75    Ok(WindowsOverviewData {
76        config: WindowsOverviewConfig {
77            items_per_row: windows.items_per_row,
78            scale: windows.scale,
79            filter_current_workspace: overview.filter_by.contains(&FilterBy::CurrentWorkspace),
80            filter_current_monitor: overview.filter_by.contains(&FilterBy::CurrentMonitor),
81            filter_same_class: overview.filter_by.contains(&FilterBy::SameClass),
82        },
83        window_list,
84        active,
85        initial_active: active,
86        hypr_data: HyprlandData::default(),
87    })
88}