diff --git a/.changes/resizing-undecorated-window-touch.md b/.changes/resizing-undecorated-window-touch.md new file mode 100644 index 0000000000..9db10d45b5 --- /dev/null +++ b/.changes/resizing-undecorated-window-touch.md @@ -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. \ No newline at end of file diff --git a/src/webview/webkitgtk/mod.rs b/src/webview/webkitgtk/mod.rs index abc2c3556c..c8bb9c817a 100644 --- a/src/webview/webkitgtk/mod.rs +++ b/src/webview/webkitgtk/mod.rs @@ -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::*; @@ -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(); @@ -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(), + ), + } + } } } } diff --git a/src/webview/webview2/mod.rs b/src/webview/webview2/mod.rs index 3441a4fc09..19fe91d5bb 100644 --- a/src/webview/webview2/mod.rs +++ b/src/webview/webview2/mod.rs @@ -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(())), )?; @@ -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, @@ -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 {