Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bunch of improvements: MacOS Stylus, Virtual Key, Reconnect, etc. #276

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e5779ad
feat: make remote stylus pressure works on MacOS
lyonbot Jul 7, 2024
8632858
fix: right-click
lyonbot Jul 7, 2024
0ff46e4
feat: virtual key
lyonbot Jul 11, 2024
9764d3f
chore: build script use npm not tsc
lyonbot Jul 11, 2024
de3e6fd
feat: use official autopilot cargo
lyonbot Jul 12, 2024
dc640d0
feat: virtual key striking
lyonbot Jul 12, 2024
d460039
fix: always treat pen as primary input
lyonbot Jul 12, 2024
867bc83
feat: reconnect without refreshing page
lyonbot Jul 12, 2024
c2463e8
fix: abort building if npm fails
lyonbot Jul 12, 2024
d626e36
fix: ffmpeg building fails for linux/windows
lyonbot Jul 12, 2024
aa839e9
fix: missing branches
lyonbot Jul 12, 2024
b908efc
feat: multiple virtual key profiles, and sync between clients
lyonbot Jul 20, 2024
e368905
fix: when editing, shall not send keys
lyonbot Jul 20, 2024
3e5324b
chore: add contributor
lyonbot Jul 20, 2024
b440b4a
fix: macos build for intel & arm
lyonbot Jul 20, 2024
f8bacaa
fix: macos mouse dragging error
lyonbot Jul 20, 2024
7cd4613
fix: macos mouse dragging error
lyonbot Jul 20, 2024
8a168f1
Fix building on Windows
electronstudio Jul 30, 2024
a012263
package lock file for npm, not just pnmp
electronstudio Jul 31, 2024
b3808b8
chore: make stylus smooth
lyonbot Aug 4, 2024
c204987
chore: refactor code about event and canvas
lyonbot Aug 4, 2024
ff71078
fix: comment
lyonbot Aug 4, 2024
17dec71
feat: improve pointer sampling rate (smooth lines!)
lyonbot Aug 10, 2024
17118a2
fix: remove wrong mousemove event in MacOS, fix Krita glitches
lyonbot Aug 10, 2024
b876f62
Merge branch 'lyonbot:pr' into pr
electronstudio Aug 10, 2024
2f6d1b0
Merge pull request #1 from electronstudio2/pr
lyonbot Aug 11, 2024
71cabcd
fix: ios doesn't support getCoalescedEvents
lyonbot Sep 8, 2024
26dfe45
Merge remote-tracking branch 'origin/pr' into pr
lyonbot Sep 8, 2024
ed28e61
feat: smooth pointer coordination
lyonbot Sep 29, 2024
45f9be8
Merge remote-tracking branch 'hmh/master' into pr
lyonbot Sep 29, 2024
e7f9415
chore: [skip-ci] use h-m-h newest headers file (not tested)
lyonbot Sep 29, 2024
9d37df7
fix: merge request problem
lyonbot Sep 29, 2024
37d6ca9
chore: revert lock to HMH master version
lyonbot Sep 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build-macos:
runs-on: macOS-latest
strategy:
matrix:
os: [macos-latest, macos-13] # -latest if for Apple Silicon, -13 is for Intel
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
Expand All @@ -114,13 +117,15 @@ jobs:
# run: MACOSX_DEPLOYMENT_TARGET=10.13 cargo bundle --release
run: cargo bundle --release
- name: Package
run: cd target/release/bundle/osx/ && zip -r macOS.zip Weylus.app
run: |
MACOS_BUILD_NAME=macos-$([ "${{ matrix.os }}" == "macos-latest" ] && echo "arm" || echo "intel")
echo "MACOS_BUILD_NAME=$MACOS_BUILD_NAME" >> $GITHUB_ENV
cd target/release/bundle/osx/ && zip -r ${MACOS_BUILD_NAME}.zip Weylus.app
- name: Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }}
path: |
target/release/bundle/osx/macOS.zip
name: ${{ env.MACOS_BUILD_NAME }}
path: target/release/bundle/osx/${{ env.MACOS_BUILD_NAME }}.zip
- name: ArtifactsDebug
if: failure()
uses: actions/upload-artifact@v4
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
/deps/libva
c_helper/target
c_helper/Cargo.lock
.DS_Store
node_modules
/www/static/lib.js
/www/static/style.css
/www/static/*.map
*.js
*.js.map
*.tar.gz
42 changes: 42 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'weylus'",
"cargo": {
"args": [
"build",
"--bin=weylus",
"--package=weylus"
],
"filter": {
"name": "weylus",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'weylus'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=weylus",
"--package=weylus"
],
"filter": {
"name": "weylus",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ List of Contributors:
**************************
Robert Schroll
Daniel Rutz
lyonbot
Philipp Urlbauer
OmegaRogue
**************************
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2021"
description = "Use your iPad or Android tablet as graphic tablet."

[dependencies]
autopilot = { git = "https://github.com/H-M-H/autopilot-rs.git", rev = "63eed09c715bfb665bb23172a3930a528e11691c" }
autopilot = { git = "https://github.com/lyonbot/autopilot-rs.git", rev = "a92b41edb4818d0d4b4289d49e65420dbe9ab081", version = "0.4.0" }
bitflags = { version = "^2.6", features = ["serde"] }
bytes = "1.7.1"
clap = { version = "4.5.18", features = ["derive"] }
Expand Down
93 changes: 60 additions & 33 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,64 @@ fn build_ffmpeg(dist_dir: &Path) {
}
}

fn build_www() {
let www_dir = Path::new("www");

#[cfg(not(target_os = "windows"))]
let shell = "bash";

#[cfg(not(target_os = "windows"))]
let shell_flag = "-c";

#[cfg(target_os = "windows")]
let shell = "cmd";

#[cfg(target_os = "windows")]
let shell_flag = "/c";


// try `pnpm` first, then `npm`
if !www_dir.join("node_modules").exists() {
let pnpm_install_success = match Command::new(shell)
.args([shell_flag, "pnpm install"])
.current_dir(www_dir)
.status()
{
Ok(e) => e.success(),
Err(_) => false,
};

if !pnpm_install_success {
let npm_install_result = Command::new(shell)
.args([shell_flag, "npm install"])
.current_dir(www_dir)
.status()
.expect("Failed to run npm or pnpm!");

if !npm_install_result.success() {
panic!(
"Failed to install npm dependencies! npm exited with code {}",
npm_install_result.code().unwrap_or(-1)
);
}
}
}

let build_result = Command::new(shell)
.args([shell_flag, "npm run build"])
.current_dir(www_dir)
.status()
.expect("Failed to build www!");

if !build_result.success() {
panic!(
"Failed to build www! npm exited with code {}",
build_result.code().unwrap_or(-1)
);
}
}


fn main() {
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();

Expand All @@ -38,39 +96,8 @@ fn main() {
build_ffmpeg(&dist_dir);
}

println!("cargo:rerun-if-changed=ts/lib.ts");

#[cfg(not(target_os = "windows"))]
let mut tsc_command = Command::new("tsc");

#[cfg(target_os = "windows")]
let mut tsc_command = Command::new("bash");
#[cfg(target_os = "windows")]
tsc_command.args(&["-c", "tsc"]);

let js_needs_update = || -> Result<bool, Box<dyn std::error::Error>> {
Ok(Path::new("ts/lib.ts").metadata()?.modified()?
> Path::new("www/static/lib.js").metadata()?.modified()?)
}()
.unwrap_or(true);

if js_needs_update {
match tsc_command.status() {
Err(err) => {
println!("cargo:warning=Failed to call tsc: {}", err);
std::process::exit(1);
}
Ok(status) => {
if !status.success() {
match status.code() {
Some(code) => println!("cargo:warning=tsc failed with exitcode: {}", code),
None => println!("cargo:warning=tsc terminated by signal."),
};
std::process::exit(2);
}
}
}
}
println!("cargo:rerun-if-changed=www/src/");
build_www();

println!("cargo:rerun-if-changed=lib/encode_video.c");
let mut cc_video = cc::Build::new();
Expand Down
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ pub struct Config {
#[serde(skip)]
pub print_lib_js: bool,

pub virtual_keys_profiles: Option<String>,

#[arg(
long,
help = "Use custom template of index.html to be served by Weylus."
Expand Down
72 changes: 66 additions & 6 deletions src/input/autopilot_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,30 @@ use autopilot::mouse;
use autopilot::mouse::ScrollDirection;
use autopilot::screen::size as screen_size;

use tracing::warn;
use tracing::{debug, warn};

use crate::input::device::{InputDevice, InputDeviceType};
use crate::protocol::{Button, KeyboardEvent, KeyboardEventType, PointerEvent, WheelEvent};
use crate::protocol::{
Button, KeyboardEvent, KeyboardEventType, PointerEvent, PointerEventType, PointerType,
WheelEvent,
};

use crate::capturable::{Capturable, Geometry};

#[cfg(target_os = "macos")]
use super::macos_tablet::{MacosPenEventType, macos_send_tablet_event};

pub struct AutoPilotDevice {
tablet_down: bool,
capturable: Box<dyn Capturable>,
}

impl AutoPilotDevice {
pub fn new(capturable: Box<dyn Capturable>) -> Self {
Self { capturable }
Self {
tablet_down: false,
capturable,
}
}
}

Expand All @@ -30,7 +40,7 @@ impl InputDevice for AutoPilotDevice {
}

fn send_pointer_event(&mut self, event: &PointerEvent) {
if !event.is_primary {
if !event.is_primary && event.pointer_type != PointerType::Pen {
return;
}
if let Err(err) = self.capturable.before_input() {
Expand All @@ -54,12 +64,62 @@ impl InputDevice for AutoPilotDevice {
return;
}
};
if let Err(err) = mouse::move_to(autopilot::geometry::Point::new(

let point = autopilot::geometry::Point::new(
(event.x * width_rel + x_rel) * width,
(event.y * height_rel + y_rel) * height,
)) {
);

// MacOS only: send tablet (stylus) events
#[cfg(target_os = "macos")]
if event.pointer_type == PointerType::Pen {
let pe_type = match event.event_type {
PointerEventType::DOWN => MacosPenEventType::Down,
PointerEventType::UP => MacosPenEventType::Up,
PointerEventType::CANCEL => MacosPenEventType::Up,
PointerEventType::ENTER => MacosPenEventType::Enter,
PointerEventType::LEAVE => MacosPenEventType::Leave,
_ => MacosPenEventType::Move,
};

match event.event_type {
PointerEventType::DOWN => {
self.tablet_down = true;
}
PointerEventType::CANCEL | PointerEventType::UP | PointerEventType::LEAVE => {
self.tablet_down = false;
}
_ => (),
}

match event.event_type {
PointerEventType::ENTER => {
debug!("Entering tablet");
}
PointerEventType::LEAVE => {
debug!("Leaving tablet");
}
_ => (),
}

let buttons = if self.tablet_down { 1 } else { 0 };
if let Err(err) = macos_send_tablet_event(
point,
pe_type,
event.button.bits().into(),
buttons,
event.pressure,
) {
warn!("Could not send pressure: {}", err);
}

return;
}

if let Err(err) = mouse::move_to(point) {
warn!("Could not move mouse: {}", err);
}

match event.button {
Button::PRIMARY => {
mouse::toggle(mouse::Button::Left, event.buttons.contains(event.button))
Expand Down
Loading