diff --git a/src/stremio_app/stremio_app.rs b/src/stremio_app/stremio_app.rs index 0c12136..16f8441 100644 --- a/src/stremio_app/stremio_app.rs +++ b/src/stremio_app/stremio_app.rs @@ -1,10 +1,16 @@ use native_windows_derive::NwgUi; use native_windows_gui as nwg; use serde::{Deserialize, Serialize}; -use serde_json; +use serde_json::{self, json}; +use std::cell::RefCell; use std::cmp; use std::sync::Arc; use std::thread; +use winapi::um::winuser::{ + GetSystemMetrics, GetWindowLongA, SetWindowLongA, GWL_EXSTYLE, GWL_STYLE, SM_CXSCREEN, + SM_CYSCREEN, WS_CAPTION, WS_EX_CLIENTEDGE, WS_EX_DLGMODALFRAME, WS_EX_STATICEDGE, + WS_EX_WINDOWEDGE, WS_THICKFRAME, +}; use crate::stremio_app::stremio_player::Player; use crate::stremio_app::stremio_wevbiew::WebView; @@ -39,11 +45,36 @@ struct RPCResponse { #[serde(skip_serializing_if = "Option::is_none")] args: Option, } -////////////////////////////////////////// +impl RPCResponse { + fn visibility_change(visible: bool, visibility: u32, is_full_screen: bool) -> String { + let resp = RPCResponse { + id: 1, + object: "transport".to_string(), + response_type: 1, + args: Some(json!(["win-visibility-changed" ,{ + "visible": visible, + "visibility": visibility, + "isFullscreen": is_full_screen + }])), + ..Default::default() + }; + serde_json::to_string(&resp).expect("Cannot build response") + } +} +////////////////////////////////////////// +#[derive(Default)] +pub struct WindowStyle { + pub full_screen: bool, + pub pos: (i32, i32), + pub size: (u32, u32), + pub style: i32, + pub ex_style: i32, +} #[derive(Default, NwgUi)] pub struct MainWindow { pub webui_url: String, + pub saved_window_style: RefCell, #[nwg_resource] pub embed: nwg::EmbedResource, #[nwg_resource(source_embed: Some(&data.embed), source_embed_str: Some("MAINICON"))] @@ -163,7 +194,7 @@ impl MainWindow { player_tx.send(resp_json).ok(); } else { match method { - "toggle-fullscreen" => { + "win-set-visibility" => { toggle_fullscreen_sender.notice(); } "quit" => { @@ -171,6 +202,9 @@ impl MainWindow { } "app-ready" => { hide_splash_sender.notice(); + web_tx_web + .send(RPCResponse::visibility_change(true, 1, false)) + .ok(); } "app-error" => { hide_splash_sender.notice(); @@ -225,7 +259,58 @@ impl MainWindow { } } fn on_toggle_fullscreen_notice(&self) { - println!("full screen toggle requested"); + if let Some(hwnd) = self.window.handle.hwnd() { + let mut saved_style = self.saved_window_style.borrow_mut(); + if saved_style.full_screen { + unsafe { + SetWindowLongA(hwnd, GWL_STYLE, saved_style.style); + SetWindowLongA(hwnd, GWL_EXSTYLE, saved_style.ex_style); + } + self.window + .set_position(saved_style.pos.0, saved_style.pos.1); + self.window.set_size(saved_style.size.0, saved_style.size.1); + saved_style.full_screen = false; + } else { + saved_style.pos = self.window.position(); + saved_style.size = self.window.size(); + unsafe { + saved_style.style = GetWindowLongA(hwnd, GWL_STYLE); + saved_style.ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); + SetWindowLongA( + hwnd, + GWL_STYLE, + saved_style.style & !(WS_CAPTION as i32 | WS_THICKFRAME as i32), + ); + SetWindowLongA( + hwnd, + GWL_EXSTYLE, + saved_style.ex_style + & !(WS_EX_DLGMODALFRAME as i32 + | WS_EX_WINDOWEDGE as i32 + | WS_EX_CLIENTEDGE as i32 + | WS_EX_STATICEDGE as i32), + ); + } + self.window.set_position(0, 0); + self.window + .set_size(unsafe { GetSystemMetrics(SM_CXSCREEN) as u32 }, unsafe { + GetSystemMetrics(SM_CYSCREEN) as u32 + }); + saved_style.full_screen = true; + } + let web_channel = self.webview.channel.borrow(); + let (web_tx, _) = web_channel + .as_ref() + .expect("Cannont obtain communication channel for the Web UI"); + let web_tx_app = web_tx.clone(); + web_tx_app + .send(RPCResponse::visibility_change( + true, + 1, + saved_style.full_screen, + )) + .ok(); + } } fn on_quit_notice(&self) { self.on_quit(); diff --git a/src/stremio_app/stremio_wevbiew/stremio_wevbiew.rs b/src/stremio_app/stremio_wevbiew/stremio_wevbiew.rs index 5d21eb7..dc3d4e3 100644 --- a/src/stremio_app/stremio_wevbiew/stremio_wevbiew.rs +++ b/src/stremio_app/stremio_wevbiew/stremio_wevbiew.rs @@ -98,7 +98,6 @@ impl PartialUi for WebView { |_| Ok(()), ) .ok(); - let tx_fs = tx_web.clone(); webview.add_web_message_received(move |_w, msg| { let msg = msg.try_get_web_message_as_string()?; tx_web.send(msg).ok(); @@ -114,10 +113,6 @@ impl PartialUi for WebView { msg.put_handled(true).ok(); Ok(()) }).ok(); - webview.add_contains_full_screen_element_changed(move |_w| { - tx_fs.send(r#"{"id":1, "args": ["toggle-fullscreen"]}"#.to_string()).ok(); - Ok(()) - }).ok(); WebView::resize_to_window_bounds_and_show(Some(&controller), Some(hwnd)); controller_clone .set(controller) @@ -153,6 +148,16 @@ impl PartialUi for WebView { ) { use nwg::Event as E; match evt { + // FIXME: Hack to focus the webview when pressing alt-tab. + // This doesn't work if you click the window's title with + // the mouse. A better solution is needed + E::OnKeyPress | E::OnKeyRelease => { + if let Some(controller) = self.controller.get() { + controller + .move_focus(webview2::MoveFocusReason::Programmatic) + .ok(); + } + } E::OnResize | E::OnWindowMaximize => { WebView::resize_to_window_bounds_and_show(self.controller.get(), handle.hwnd()); }