summaryrefslogtreecommitdiff
path: root/src/client/config_reload.rs
blob: c20de760c67384c95905654509eea59e49d5e8f6 (plain)
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
123
124
125
126
127
128
129
use super::*;

pub(super) fn init_logging() {
    crate::logging::init_file_logging("herdr-client.log");
}

pub(super) fn apply_reload(
    state: &mut ClientState,
    endpoints: &mut endpoint::EndpointRegistry,
    pending_activation: &mut Option<endpoint::PendingEndpointActivation>,
    host_mouse_capture_active: &std::sync::atomic::AtomicBool,
    host_sgr_pixels_active: &std::sync::atomic::AtomicBool,
    prefix_input_source: &mut impl crate::platform::PrefixInputSource,
) -> Result<(), ClientError> {
    let previous_mouse_capture = state.shell_mouse_capture_preference;
    let mut mouse_capture = previous_mouse_capture;
    reload_local_client_config(
        &mut state.sound_config,
        &mut state.redraw_on_focus_gained,
        &mut state.draw_host_cursor,
        &mut state.remote_image_paste_key,
        &mut mouse_capture,
    );
    state.shell_mouse_capture_preference = mouse_capture;
    state.direct_mouse_capture_preference = state.attach_escape.is_some() && mouse_capture;
    if state.shell.is_some() && previous_mouse_capture != mouse_capture {
        write_to_server(
            endpoints,
            &ClientMessage::ClientShellMouseCapture {
                enabled: mouse_capture,
            },
        )
        .map_err(ClientError::ConnectionLost)?;
    }
    if state.attach_escape.is_some() {
        let enabled = effective_mouse_capture(
            state.endpoint_mouse_capture_requested,
            state.direct_mouse_capture_preference,
        );
        let sgr_pixels = effective_sgr_pixel_mouse(
            enabled,
            state.endpoint_sgr_pixels_requested,
            state.pixel_geometry_exact,
        );
        if enabled != state.mouse_capture_active
            || sgr_pixels != host_sgr_pixels_active.load(Ordering::Acquire)
        {
            set_mouse_capture(enabled, sgr_pixels).map_err(ClientError::ConnectionFailed)?;
        }
        state.mouse_capture_active = enabled;
        host_mouse_capture_active.store(enabled, Ordering::Release);
        host_sgr_pixels_active.store(sgr_pixels, Ordering::Release);
    }
    let (frame, resize) = if let Some(shell) = state.shell.as_mut() {
        let previous_size = shell.surface_size(state.reported_size.0, state.reported_size.1);
        shell.reload_client_config();
        let next_size = shell.surface_size(state.reported_size.0, state.reported_size.1);
        let resize = (previous_size != next_size).then(|| {
            shell.invalidate_pane_surface();
            client_shell_resize_message(
                shell,
                state.reported_size.0,
                state.reported_size.1,
                state.reported_cell_size.0,
                state.reported_cell_size.1,
                state.pixel_geometry_exact,
            )
        });
        (
            shell.compose(state.reported_size.0, state.reported_size.1),
            resize,
        )
    } else {
        (None, None)
    };
    apply_client_shell_input_source_changes(state, prefix_input_source);
    if let Some(resize) = resize {
        if let Some(activation) = pending_activation.as_mut() {
            if let Err(error) = activation.update_resize(resize, endpoints) {
                rollback_endpoint_activation(state, endpoints, pending_activation, error, false);
            }
        } else {
            write_to_server(endpoints, &resize).map_err(ClientError::ConnectionLost)?;
        }
    }
    if let Some(frame) = frame {
        state.present_frame(frame);
    }
    Ok(())
}

pub(super) fn reload_local_client_config(
    sound_config: &mut crate::config::SoundConfig,
    redraw_on_focus_gained: &mut bool,
    draw_host_cursor: &mut bool,
    remote_image_paste_key: &mut Option<(
        crossterm::event::KeyCode,
        crossterm::event::KeyModifiers,
    )>,
    mouse_capture: &mut bool,
) {
    match crate::config::load_live_config() {
        Ok(loaded) => {
            let invalid_section = |section: &str| {
                loaded
                    .invalid_sections
                    .iter()
                    .any(|invalid| invalid == section)
            };
            if !invalid_section("ui") && loaded.config.invalid_sidebar_bounds_diagnostic().is_none()
            {
                for diagnostic in loaded.config.ui.sound.diagnostics() {
                    warn!(diagnostic = %diagnostic, "local sound config diagnostic");
                }
                *sound_config = loaded.config.ui.sound.clone();
                *redraw_on_focus_gained = loaded.config.ui.redraw_on_focus_gained;
                *draw_host_cursor = should_draw_host_cursor(loaded.config.ui.host_cursor);
                *mouse_capture = loaded.config.ui.mouse_capture;
            }
            if !invalid_section("keys") {
                *remote_image_paste_key = client_remote_image_paste_key(&loaded.config);
            }
            debug!("reloaded local client config");
        }
        Err(diagnostics) => {
            warn!(diagnostics = ?diagnostics, "failed to reload local client config; keeping current client config");
        }
    }
}