hyprshell_windows_lib/switch/
create.rs1use crate::global::{WindowsSwitchConfig, WindowsSwitchData};
2use adw::gtk::gdk::Key;
3use adw::gtk::glib::Propagation;
4use adw::gtk::prelude::*;
5use adw::gtk::{
6 Application, ApplicationWindow, EventControllerKey, FlowBox, Orientation, Overlay,
7 SelectionMode,
8};
9use anyhow::Context;
10use async_channel::Sender;
11use config_lib::{FilterBy, Modifier, Switch, Windows};
12use core_lib::transfer::{Direction, SwitchSwitchConfig, TransferType};
13use core_lib::{HyprlandData, SWITCH_NAMESPACE, WarnWithDetails};
14use exec_lib::get_initial_active;
15use gtk4_layer_shell::{KeyboardMode, Layer, LayerShell};
16use std::collections::HashMap;
17use tracing::{debug, debug_span};
18
19pub fn create_windows_switch_window(
20 app: &Application,
21 switch: &Switch,
22 windows: &Windows,
23 event_sender: Sender<TransferType>,
24) -> anyhow::Result<WindowsSwitchData> {
25 let _span = debug_span!("create_windows_switch_window").entered();
26
27 let clients_flow = FlowBox::builder()
28 .selection_mode(SelectionMode::None)
29 .orientation(Orientation::Horizontal)
30 .max_children_per_line(u32::from(windows.items_per_row))
31 .min_children_per_line(u32::from(windows.items_per_row))
32 .build();
33
34 let clients_flow_overlay = Overlay::builder()
35 .child(&clients_flow)
36 .css_classes(["monitor", "no-hover"])
37 .build();
38
39 let window = ApplicationWindow::builder()
40 .css_classes(["window"])
41 .application(app)
42 .child(&clients_flow_overlay)
43 .default_height(10)
44 .default_width(10)
45 .build();
46
47 let key_controller = EventControllerKey::new();
48 let event_sender_2 = event_sender.clone();
49 key_controller.connect_key_pressed(move |_, key, _, _| handle_key(key, &event_sender_2));
50 let event_sender_3 = event_sender;
51 let r#mod = switch.modifier;
52 key_controller.connect_key_released(move |_, key, _, _| {
53 handle_release(key, r#mod, &event_sender_3);
54 });
55 window.add_controller(key_controller);
56
57 window.init_layer_shell();
58 window.set_namespace(Some(SWITCH_NAMESPACE));
59 window.set_layer(Layer::Top);
60 window.set_keyboard_mode(KeyboardMode::Exclusive);
63 window.present();
64 window.set_visible(false);
65
66 debug!("Created switch window ({})", window.id());
67
68 Ok(WindowsSwitchData {
69 config: WindowsSwitchConfig {
70 items_per_row: windows.items_per_row,
71 scale: windows.scale,
72 filter_current_workspace: switch.filter_by.contains(&FilterBy::CurrentWorkspace),
73 filter_current_monitor: switch.filter_by.contains(&FilterBy::CurrentMonitor),
74 filter_same_class: switch.filter_by.contains(&FilterBy::SameClass),
75 switch_workspaces: switch.switch_workspaces,
76 },
77 window,
78 main_flow: clients_flow,
79 workspaces: HashMap::default(),
80 clients: HashMap::default(),
81 active: get_initial_active().context("unable to get initial active data")?,
82 hypr_data: HyprlandData::default(),
83 })
84}
85
86fn handle_release(key: Key, modifier: Modifier, event_sender: &Sender<TransferType>) {
87 if ((key == Key::Alt_L || key == Key::Alt_R) && modifier == Modifier::Alt)
88 || ((key == Key::Control_L || key == Key::Control_R) && modifier == Modifier::Ctrl)
89 || ((key == Key::Super_L || key == Key::Super_R) && modifier == Modifier::Super)
90 {
91 event_sender
92 .send_blocking(TransferType::CloseSwitch)
93 .warn_details("unable to send");
94 }
95}
96
97fn handle_key(key: Key, event_sender: &Sender<TransferType>) -> Propagation {
98 match key {
99 Key::Tab | Key::l | Key::Right => {
100 event_sender
101 .send_blocking(TransferType::SwitchSwitch(SwitchSwitchConfig {
102 direction: Direction::Right,
103 }))
104 .warn_details("unable to send");
105 Propagation::Stop
106 }
107 Key::ISO_Left_Tab | Key::grave | Key::dead_grave | Key::h | Key::Left => {
108 event_sender
109 .send_blocking(TransferType::SwitchSwitch(SwitchSwitchConfig {
110 direction: Direction::Left,
111 }))
112 .warn_details("unable to send");
113 Propagation::Stop
114 }
115 Key::j | Key::Down => {
116 event_sender
117 .send_blocking(TransferType::SwitchSwitch(SwitchSwitchConfig {
118 direction: Direction::Down,
119 }))
120 .warn_details("unable to send");
121 Propagation::Stop
122 }
123 Key::k | Key::Up => {
124 event_sender
125 .send_blocking(TransferType::SwitchSwitch(SwitchSwitchConfig {
126 direction: Direction::Up,
127 }))
128 .warn_details("unable to send");
129 Propagation::Stop
130 }
131 _ => Propagation::Proceed,
132 }
133}