From b2a0bfc289786d0a23dac0c8d9543771e70e3427 Mon Sep 17 00:00:00 2001 From: Amr Bashir <48618675+amrbashir@users.noreply.github.com> Date: Thu, 25 Mar 2021 19:30:56 +0200 Subject: [PATCH] feat/ draggable-region (#92) * feat: add draggable-regions (gtk-rs) * fix: fix clippy_fmt_check ci * feat: add draggable-regions (winit) * chore: add change file * pull winit from github * Update draggable-regions.md --- .changes/draggable-regions.md | 5 ++ Cargo.toml | 4 +- examples/customtitlebar.rs | 104 ++++++++++++++++++++++++++++++++++ src/application/general.rs | 36 ++++++++---- src/application/gtkrs.rs | 36 ++++++++---- src/application/mod.rs | 7 +++ src/webview/mod.rs | 9 ++- 7 files changed, 176 insertions(+), 25 deletions(-) create mode 100644 .changes/draggable-regions.md create mode 100644 examples/customtitlebar.rs diff --git a/.changes/draggable-regions.md b/.changes/draggable-regions.md new file mode 100644 index 000000000..6d886bbb7 --- /dev/null +++ b/.changes/draggable-regions.md @@ -0,0 +1,5 @@ +--- +"wry": patch +--- + +Add draggable regions, just add `drag-region` class to the html element. diff --git a/Cargo.toml b/Cargo.toml index 2448c5f6f..5446b8ae4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,11 +46,11 @@ gdk-pixbuf = "0.9" [target."cfg(target_os = \"windows\")".dependencies] webview2 = "0.1.0-beta.1" winapi = { version = "0.3", features = [ "libloaderapi", "oleidl" ] } -winit = "0.24" +winit = { git = "https:/github.com/rust-windowing/winit", rev = "98470393d11b3b670c1e122c26a15c563dcf68a4"} [target."cfg(target_os = \"macos\")".dependencies] cocoa = "0.24" core-graphics = "0.22" objc = "0.2" objc_id = "0.1" -winit = "0.24" +winit = { git = "https:/github.com/rust-windowing/winit", rev = "98470393d11b3b670c1e122c26a15c563dcf68a4"} diff --git a/examples/customtitlebar.rs b/examples/customtitlebar.rs new file mode 100644 index 000000000..ee62d1d6e --- /dev/null +++ b/examples/customtitlebar.rs @@ -0,0 +1,104 @@ +use wry::{Application, Attributes, Result, RpcRequest, WindowProxy, WindowRpcHandler}; + +fn main() -> Result<()> { + let mut app = Application::new()?; + + let attributes = Attributes { + url: Some( + r#"data:text/html, + +
+
Awesome WRY Window
+
+
+ +
+
+ +
+
+ +
+
+
+
+ WRYYYYYYYYYYYYYYYYYYYYYY! +
+ + + "#.into(), + ), + // inject the css after 500ms, otherwise it won't work as the `head` element isn't created yet. + initialization_scripts:vec![ + r#" + setTimeout(() => { + const style = document.createElement('style'); + style.textContent = ` + * { + padding: 0; + margin: 0; + box-sizing: border-box; + } + .titlebar { + height: 30px; + background: #1F1F1F; + color: white; + user-select: none; + display: flex; + justify-content: space-between; + align-items: center; + } + .titlebar-button { + display: inline-flex; + justify-content: center; + align-items: center; + width: 30px; + height: 30px; + } + .titlebar-button:hover { + background: #3b3b3b; + } + .titlebar-button:nth-child(3):hover { + background: #da3d3d; + } + .titlebar-button img { + filter: invert(100%); + } + `; + document.head.append(style); + }, 500); + "#.into()], + decorations: false, + ..Default::default() + }; + + let handler: WindowRpcHandler = Box::new(|proxy: WindowProxy, req: RpcRequest| { + if req.method == "minimize" { + proxy.minimize().unwrap(); + } + if req.method == "maximize" { + if req.params.unwrap().as_array().unwrap()[0] == true { + proxy.maximize().unwrap(); + } else { + proxy.unmaximize().unwrap(); + } + } + if req.method == "close" { + proxy.close().unwrap(); + } + None + }); + + let _window1 = app.add_window_with_configs(attributes, Some(handler), None, None)?; + + app.run(); + Ok(()) +} diff --git a/src/application/general.rs b/src/application/general.rs index a7181eb09..523e961b7 100644 --- a/src/application/general.rs +++ b/src/application/general.rs @@ -296,6 +296,9 @@ impl App for InnerApplication { WindowMessage::EvaluationScript(script) => { let _ = webview.dispatch_script(&script); } + WindowMessage::BeginDrag { x: _, y: _ } => { + window.drag_window().unwrap(); + } } } } @@ -383,17 +386,28 @@ fn _create_webview( webview = webview.register_protocol(protocol.name, protocol.handler) } - if let Some(rpc_handler) = rpc_handler { - webview = webview.set_rpc_handler(Box::new(move |requests| { - let proxy = WindowProxy::new( - ApplicationProxy { - inner: proxy.clone(), - }, - window_id, - ); - rpc_handler(proxy, requests) - })); - } + webview = webview.set_rpc_handler(Box::new(move |mut request| { + let proxy = WindowProxy::new( + ApplicationProxy { + inner: proxy.clone(), + }, + window_id, + ); + + if &request.method == "__WRY_BEGIN_WINDOW_DRAG__" { + if let Some(params) = request.params.take() { + let x = params[0].as_f64()?; + let y = params[1].as_f64()?; + proxy.begin_drag(x, y).unwrap(); + } + } + + if let Some(rpc_handler) = &rpc_handler { + rpc_handler(proxy, request) + } else { + None + } + })); webview = webview.set_file_drop_handler(file_drop_handler); diff --git a/src/application/gtkrs.rs b/src/application/gtkrs.rs index ed0d5bb83..f0cb19e6d 100644 --- a/src/application/gtkrs.rs +++ b/src/application/gtkrs.rs @@ -307,6 +307,9 @@ impl App for InnerApplication { WindowMessage::EvaluationScript(script) => { let _ = webview.dispatch_script(&script); } + WindowMessage::BeginDrag { x, y } => { + window.begin_move_drag(1, x as i32, y as i32, 0); + } } } } @@ -432,17 +435,28 @@ fn _create_webview( webview = webview.register_protocol(protocol.name, protocol.handler); } - if let Some(rpc_handler) = rpc_handler { - webview = webview.set_rpc_handler(Box::new(move |requests| { - let proxy = WindowProxy::new( - ApplicationProxy { - inner: proxy.clone(), - }, - window_id, - ); - rpc_handler(proxy, requests) - })); - } + webview = webview.set_rpc_handler(Box::new(move |mut request| { + let proxy = WindowProxy::new( + ApplicationProxy { + inner: proxy.clone(), + }, + window_id, + ); + + if &request.method == "__WRY_BEGIN_WINDOW_DRAG__" { + if let Some(params) = request.params.take() { + let x = params[0].as_f64()?; + let y = params[1].as_f64()?; + proxy.begin_drag(x, y).unwrap(); + } + } + + if let Some(rpc_handler) = &rpc_handler { + rpc_handler(proxy, request) + } else { + None + } + })); webview = webview.set_file_drop_handler(file_drop_handler); diff --git a/src/application/mod.rs b/src/application/mod.rs index 0ee6e3dca..1845db073 100644 --- a/src/application/mod.rs +++ b/src/application/mod.rs @@ -44,6 +44,7 @@ pub enum WindowMessage { SetFullscreen(bool), SetIcon(Icon), EvaluationScript(String), + BeginDrag { x: f64, y: f64 }, } /// Describes a general message. @@ -276,6 +277,12 @@ impl WindowProxy { WindowMessage::EvaluationScript(script.into()), )) } + + pub fn begin_drag(&self, x: f64, y: f64) -> Result<()> { + self + .proxy + .send_message(Message::Window(self.id, WindowMessage::BeginDrag { x, y })) + } } /// Provides a way to create and manage WebView windows. diff --git a/src/webview/mod.rs b/src/webview/mod.rs index 008123fb9..605ede9f7 100644 --- a/src/webview/mod.rs +++ b/src/webview/mod.rs @@ -99,7 +99,14 @@ impl WebViewBuilder { Ok(Self { tx, rx, - initialization_scripts: vec![], + initialization_scripts: vec![r#" + document.addEventListener('mousedown', (e) => { + if (e.target.classList.contains('drag-region') && e.buttons === 1) { + window.rpc.notify('__WRY_BEGIN_WINDOW_DRAG__', e.screenX, e.screenY); + } + }) + "# + .into()], window, url: None, transparent: false,