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,
+
+
+
+ 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,