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
use super::{CommandBuilder, Config, DisplayEvent, Manager, Mode};
use crate::display_action::DisplayAction;
use crate::display_servers::DisplayServer;
use crate::models::WindowHandle;
use crate::State;

impl<C: Config, SERVER: DisplayServer> Manager<C, SERVER> {
    /// Process a collection of events, and apply them changes to a manager.
    /// Returns true if changes need to be rendered.
    pub fn display_event_handler(&mut self, event: DisplayEvent) -> bool {
        match event {
            DisplayEvent::ScreenCreate(s) => self.screen_create_handler(s),
            DisplayEvent::WindowCreate(w, x, y) => self.window_created_handler(w, x, y),
            DisplayEvent::WindowChange(w) => self.window_changed_handler(w),
            DisplayEvent::WindowTakeFocus(handle) => {
                self.state.focus_window(&handle);
                false
            }
            DisplayEvent::HandleWindowFocus(handle) => {
                self.state.handle_window_focus(&handle);
                false
            }

            DisplayEvent::KeyGrabReload => {
                self.state
                    .actions
                    .push_back(DisplayAction::ReloadKeyGrabs(self.config.mapped_bindings()));
                false
            }

            DisplayEvent::MoveFocusTo(x, y) => {
                self.state.move_focus_to_point(x, y);
                false
            }

            // This is a request to validate focus. Double check that we are focused on the correct
            // window.
            DisplayEvent::VerifyFocusedAt(handle) => {
                if self.state.focus_manager.behaviour.is_sloppy() {
                    self.state.validate_focus_at(&handle);
                }
                false
            }

            DisplayEvent::WindowDestroy(handle) => self.window_destroyed_handler(&handle),

            DisplayEvent::KeyCombo(mod_mask, xkeysym) => {
                //look through the config and build a command if its defined in the config
                let build = CommandBuilder::<C>::new(&self.config);
                let command = build.xkeyevent(mod_mask, xkeysym);
                command.map_or(false, |cmd| self.command_handler(cmd))
            }

            DisplayEvent::SendCommand(command) => self.command_handler(&command),

            DisplayEvent::MouseCombo(mod_mask, button, handle, x, y) => self
                .state
                .mouse_combo_handler(mod_mask, button, handle, x, y),

            DisplayEvent::ChangeToNormalMode => {
                match self.state.mode {
                    Mode::MovingWindow(h) | Mode::ResizingWindow(h) => {
                        self.state.focus_window(&h);
                    }
                    _ => {}
                }
                self.state.mode = Mode::Normal;
                true
            }

            DisplayEvent::Movement(handle, x, y) => {
                if self.state.screens.iter().any(|s| s.root == handle) {
                    self.state.focus_workspace_under_cursor(x, y);
                }
                false
            }

            DisplayEvent::MoveWindow(handle, x, y) => {
                // Setup for when window first moves.
                if let Mode::ReadyToMove(h) = self.state.mode {
                    self.state.mode = Mode::MovingWindow(h);
                    prepare_window(&mut self.state, h);
                }
                self.window_move_handler(&handle, x, y)
            }
            DisplayEvent::ResizeWindow(handle, x, y) => {
                // Setup for when window first resizes.
                if let Mode::ReadyToResize(h) = self.state.mode {
                    self.state.mode = Mode::ResizingWindow(h);
                    prepare_window(&mut self.state, h);
                }
                self.window_resize_handler(&handle, x, y)
            }

            DisplayEvent::ConfigureXlibWindow(handle) => {
                if let Some(window) = self.state.windows.iter().find(|w| w.handle == handle) {
                    let act = DisplayAction::ConfigureXlibWindow(window.clone());
                    self.state.actions.push_back(act);
                }
                false
            }
        }
    }
}

// Save off the info about position of the window when we start to move/resize.
fn prepare_window(state: &mut State, handle: WindowHandle) {
    if let Some(w) = state.windows.iter_mut().find(|w| w.handle == handle) {
        if w.floating() {
            let offset = w.get_floating_offsets().unwrap_or_default();
            w.start_loc = Some(offset);
        } else {
            let container = w.container_size.unwrap_or_default();
            let normal = w.normal;
            let floating = normal - container;
            w.set_floating_offsets(Some(floating));
            w.start_loc = Some(floating);
            w.set_floating(true);
        }
    }
    state.move_to_top(&handle);
}