Skip to content

Commit

Permalink
feat: allow resizing undecorated window using touch
Browse files Browse the repository at this point in the history
closes #399
closes #398
  • Loading branch information
amrbashir committed Aug 28, 2021
1 parent cff38ec commit d369d74
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 11 deletions.
6 changes: 6 additions & 0 deletions .changes/resizing-undecorated-window-touch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"wry": patch
---

* Fix hovering over an edge of undecorated window on Linux won't change cursor.
* Undecorated window can be resized using touch on Linux and Windows.
92 changes: 84 additions & 8 deletions src/webview/webkitgtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use std::rc::Rc;

use gdk::{WindowEdge, RGBA};
use gdk::{Cursor, EventMask, WindowEdge, RGBA};
use gio::Cancellable;
use glib::signal::Inhibit;
use gtk::prelude::*;
Expand Down Expand Up @@ -108,6 +108,47 @@ impl InnerWebView {
close_window.gtk_window().close();
});

webview.add_events(
EventMask::POINTER_MOTION_MASK
| EventMask::BUTTON1_MOTION_MASK
| EventMask::BUTTON_PRESS_MASK
| EventMask::TOUCH_MASK,
);
webview.connect_motion_notify_event(|webview, event| {
// This one should be GtkWindow
if let Some(widget) = webview.parent() {
// This one should be GtkWindow
if let Some(window) = widget.parent() {
// Safe to unwrap unless this is not from tao
let window: gtk::Window = window.downcast().unwrap();
if !window.is_decorated() && window.is_resizable() {
if let Some(window) = window.window() {
let (cx, cy) = event.root();
let edge = hit_test(&window, cx, cy);
// FIXME: calling `window.begin_resize_drag` seems to revert the cursor back to normal style
window.set_cursor(
Cursor::from_name(
&window.display(),
match edge {
WindowEdge::North => "n-resize",
WindowEdge::South => "s-resize",
WindowEdge::East => "e-resize",
WindowEdge::West => "w-resize",
WindowEdge::NorthWest => "nw-resize",
WindowEdge::NorthEast => "ne-resize",
WindowEdge::SouthEast => "se-resize",
WindowEdge::SouthWest => "sw-resize",
_ => "default",
},
)
.as_ref(),
);
}
}
}
}
Inhibit(false)
});
webview.connect_button_press_event(|webview, event| {
if event.button() == 1 {
let (cx, cy) = event.root();
Expand All @@ -118,13 +159,48 @@ impl InnerWebView {
// Safe to unwrap unless this is not from tao
let window: gtk::Window = window.downcast().unwrap();
if !window.is_decorated() && window.is_resizable() {
// Safe to unwrap since it's a valide GtkWindow
let result = hit_test(&window.window().unwrap(), cx, cy);

// we ignore the `__Unknown` variant so the webview receives the click correctly if it is not on the edges.
match result {
WindowEdge::__Unknown(_) => (),
_ => window.begin_resize_drag(result, 1, cx as i32, cy as i32, event.time()),
if let Some(window) = window.window() {
// Safe to unwrap since it's a valide GtkWindow
let result = hit_test(&window, cx, cy);

// we ignore the `__Unknown` variant so the webview receives the click correctly if it is not on the edges.
match result {
WindowEdge::__Unknown(_) => (),
_ => window.begin_resize_drag(result, 1, cx as i32, cy as i32, event.time()),
}
}
}
}
}
}
Inhibit(false)
});
webview.connect_touch_event(|webview, event| {
// This one should be GtkBox
if let Some(widget) = webview.parent() {
// This one should be GtkWindow
if let Some(window) = widget.parent() {
// Safe to unwrap unless this is not from tao
let window: gtk::Window = window.downcast().unwrap();
if !window.is_decorated() && window.is_resizable() {
if let Some(window) = window.window() {
if let Some((cx, cy)) = event.root_coords() {
if let Some(device) = event.device() {
let result = hit_test(&window, cx, cy);

// we ignore the `__Unknown` variant so the window receives the click correctly if it is not on the edges.
match result {
WindowEdge::__Unknown(_) => (),
_ => window.begin_resize_drag_for_device(
result,
&device,
0,
cx as i32,
cy as i32,
event.time(),
),
}
}
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/webview/webview2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ impl InnerWebView {
window.addEventListener('mousedown', (e) => {
if (e.buttons === 1) window.chrome.webview.postMessage('__WEBVIEW_LEFT_MOUSE_DOWN__')
});
window.addEventListener('mousemove', () => window.chrome.webview.postMessage('__WEBVIEW_MOUSE_MOVE__'));
window.addEventListener('touchstart', (e) => window.chrome.webview.postMessage('__WEBVIEW_TOUCH_START__'));
window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('__WEBVIEW_MOUSE_MOVE__'));
"#,
|_| (Ok(())),
)?;
Expand All @@ -126,7 +127,7 @@ impl InnerWebView {
let rpc_handler = attributes.rpc_handler.take();
w.add_web_message_received(move |webview, args| {
let js = args.try_get_web_message_as_string()?;
if js == "__WEBVIEW_LEFT_MOUSE_DOWN__" || js == "__WEBVIEW_MOUSE_MOVE__" {
if js == "__WEBVIEW_LEFT_MOUSE_DOWN__" || js == "__WEBVIEW_TOUCH_START__" || js == "__WEBVIEW_MOUSE_MOVE__" {
if !window_.is_decorated() && window_.is_resizable() {
use winapi::um::winuser::{
HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTLEFT, HTRIGHT,
Expand Down Expand Up @@ -158,7 +159,7 @@ impl InnerWebView {
window_.set_cursor_icon(cursor);
}

if js == "__WEBVIEW_LEFT_MOUSE_DOWN__" {
if js == "__WEBVIEW_LEFT_MOUSE_DOWN__" || js == "__WEBVIEW_TOUCH_START__" {
// we ignore `HTCLIENT` variant so the webview receives the click correctly if it is not on the edges
// and prevent conflict with `tao::window::drag_window`.
if result != HTCLIENT {
Expand Down

0 comments on commit d369d74

Please sign in to comment.