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
130
131
132
133
134
135
136
//! Common code between all native desktop platforms. The counterpart is `cx_wasm32`.

use crate::*;
use std::fs::File;
use std::io::prelude::*;
use std::net::TcpStream;

#[derive(Clone, Default)]
pub(crate) struct CxDesktop {
    pub(crate) repaint_via_scroll_event: bool,
}

impl CxDesktopVsWasmCommon for Cx {
    /// See [`CxDesktopVsWasmCommon::get_default_window_size`] for documentation.
    fn get_default_window_size(&self) -> Vec2 {
        Vec2 { x: 800., y: 600. }
    }

    /// See [`CxDesktopVsWasmCommon::file_write`] for documentation.
    fn file_write(&mut self, path: &str, data: &[u8]) {
        // just write it right now
        if let Ok(mut file) = File::create(path) {
            if file.write_all(data).is_ok() {
            } else {
                println!("ERROR WRITING FILE {}", path);
            }
        } else {
            println!("ERROR WRITING FILE {}", path);
        }
    }

    /// See [`CxDesktopVsWasmCommon::websocket_send`] for documentation.
    fn websocket_send(&mut self, _url: &str, _data: &[u8]) {}

    /// See [`CxDesktopVsWasmCommon::http_send`] for documentation.
    fn http_send(
        &mut self,
        verb: &str,
        path: &str,
        _proto: &str,
        domain: &str,
        port: u16,
        content_type: &str,
        body: &[u8],
        signal: Signal,
    ) {
        fn write_bytes_to_tcp_stream(tcp_stream: &mut TcpStream, bytes: &[u8]) -> bool {
            let bytes_total = bytes.len();
            let mut bytes_left = bytes_total;
            while bytes_left > 0 {
                let buf = &bytes[(bytes_total - bytes_left)..bytes_total];
                if let Ok(bytes_written) = tcp_stream.write(buf) {
                    if bytes_written == 0 {
                        return false;
                    }
                    bytes_left -= bytes_written;
                } else {
                    return true;
                }
            }
            false
        }

        // start a thread, connect, and report back.
        let data = body.to_vec();
        let byte_len = data.len();
        let header = format!(
            "{} {} HTTP/1.1\r\nHost: {}\r\nConnect: close\r\nContent-Type:{}\r\nContent-Length:{}\r\n\r\n",
            verb, path, domain, content_type, byte_len
        );
        let host = format!("{}:{}", domain, port);
        let _connect_thread = {
            std::thread::spawn(move || {
                let stream = TcpStream::connect(&host);
                if let Ok(mut stream) = stream {
                    if !write_bytes_to_tcp_stream(&mut stream, header.as_bytes())
                        && !write_bytes_to_tcp_stream(&mut stream, &data)
                    {
                        Cx::post_signal(signal, Cx::STATUS_HTTP_SEND_OK);
                        return;
                    }
                }
                Cx::post_signal(signal, Cx::STATUS_HTTP_SEND_FAIL);
            })
        };
    }

    /// See [`CxDesktopVsWasmCommon::call_js`] for documentation.
    #[allow(unused_variables)]
    #[cfg(feature = "cef")]
    fn call_js(&mut self, name: &str, params: Vec<ZapParam>) {
        self.cef_browser.call_js(name, params);
    }

    /// See [`CxDesktopVsWasmCommon::return_to_js`] for documentation.
    #[cfg(feature = "cef")]
    fn return_to_js(&mut self, callback_id: u32, params: Vec<ZapParam>) {
        self.cef_browser.return_to_js(callback_id, params);
    }
    /// This never gets called if cef is not enabled, but we need it to pass compilation.
    #[cfg(not(feature = "cef"))]
    fn return_to_js(&mut self, _callback_id: u32, _params: Vec<ZapParam>) {}
}

impl Cx {
    pub(crate) fn process_desktop_paint_callbacks(&mut self) -> bool {
        let mut vsync = false; //self.platform.desktop.repaint_via_scroll_event;
        self.platform.desktop.repaint_via_scroll_event = false;
        if self.requested_next_frame {
            self.call_next_frame_event();
            if self.requested_next_frame {
                vsync = true;
            }
        }

        self.call_signals();

        // call redraw event
        if self.requested_draw {
            self.call_draw_event();
        }
        if self.requested_draw {
            vsync = true;
        }

        self.call_signals();

        vsync
    }

    /// See [`Cx::on_call_rust_sync`] for documentation.
    #[cfg(feature = "cef")]
    pub(crate) fn on_call_rust_sync_internal(&mut self, func: CallRustSyncFn) {
        self.cef_browser.on_call_rust_sync(func);
    }
}