Compare commits

...

6 Commits

Author SHA1 Message Date
Jon Stelly
0d96948c26 fix: remote key-up on triggered release (#371)
Fixes #369
2026-02-06 16:06:19 +01:00
Ferdinand Schober
7863e8b110 CI: update macos runners 2026-02-06 15:32:56 +01:00
Ferdinand Schober
708a40d0da macos: fix memory leak
probably should use an AutoreleasePool as well
2026-02-06 15:29:24 +01:00
skifli
3922b45bd9 feat: add binary cache to instructions (#353) 2025-12-04 12:09:10 +01:00
Ferdinand Schober
640fa995a4 improve reliability of connections (#349) 2025-11-03 18:04:18 +01:00
Ferdinand Schober
bdafaa07e5 macos: fix scroll capture (#350) 2025-11-03 18:04:09 +01:00
8 changed files with 86 additions and 35 deletions

View File

@@ -7,7 +7,7 @@ jobs:
matrix: matrix:
os: os:
- ubuntu-latest - ubuntu-latest
- macos-13 - macos-15-intel
- macos-14 - macos-14
name: "Build" name: "Build"
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -31,7 +31,7 @@ jobs:
run: nix build --print-build-logs --show-trace .#packages.x86_64-linux.lan-mouse run: nix build --print-build-logs --show-trace .#packages.x86_64-linux.lan-mouse
- name: Build lan-mouse (x86_64-darwin) - name: Build lan-mouse (x86_64-darwin)
if: matrix.os == 'macos-13' if: matrix.os == 'macos-15-intel'
run: nix build --print-build-logs --show-trace .#packages.x86_64-darwin.lan-mouse run: nix build --print-build-logs --show-trace .#packages.x86_64-darwin.lan-mouse
- name: Build lan-mouse (aarch64-darwin) - name: Build lan-mouse (aarch64-darwin)

View File

@@ -80,7 +80,7 @@ jobs:
path: lan-mouse-windows.zip path: lan-mouse-windows.zip
macos-release-build: macos-release-build:
runs-on: macos-13 runs-on: macos-15-intel
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: install dependencies - name: install dependencies

View File

@@ -94,7 +94,7 @@ jobs:
target/debug/*.dll target/debug/*.dll
build-macos: build-macos:
runs-on: macos-13 runs-on: macos-15-intel
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: install dependencies - name: install dependencies

View File

@@ -76,7 +76,7 @@ jobs:
path: lan-mouse-windows.zip path: lan-mouse-windows.zip
macos-release-build: macos-release-build:
runs-on: macos-13 runs-on: macos-15-intel
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: install dependencies - name: install dependencies

View File

@@ -318,21 +318,47 @@ fn get_events(
}))) })))
} }
CGEventType::ScrollWheel => { CGEventType::ScrollWheel => {
let v = ev.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_1); if ev.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_IS_CONTINUOUS) != 0 {
let h = ev.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2); let v =
if v != 0 { ev.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_1);
result.push(CaptureEvent::Input(Event::Pointer(PointerEvent::Axis { let h =
time: 0, ev.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2);
axis: 0, // Vertical if v != 0 {
value: v as f64, result.push(CaptureEvent::Input(Event::Pointer(PointerEvent::Axis {
}))); time: 0,
} axis: 0, // Vertical
if h != 0 { value: v as f64,
result.push(CaptureEvent::Input(Event::Pointer(PointerEvent::Axis { })));
time: 0, }
axis: 1, // Horizontal if h != 0 {
value: h as f64, result.push(CaptureEvent::Input(Event::Pointer(PointerEvent::Axis {
}))); time: 0,
axis: 1, // Horizontal
value: h as f64,
})));
}
} else {
// line based scrolling
const LINES_PER_STEP: i32 = 3;
const V120_STEPS_PER_LINE: i32 = 120 / LINES_PER_STEP;
let v = ev.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_DELTA_AXIS_1);
let h = ev.get_integer_value_field(EventField::SCROLL_WHEEL_EVENT_DELTA_AXIS_2);
if v != 0 {
result.push(CaptureEvent::Input(Event::Pointer(
PointerEvent::AxisDiscrete120 {
axis: 0, // Vertical
value: V120_STEPS_PER_LINE * v as i32,
},
)));
}
if h != 0 {
result.push(CaptureEvent::Input(Event::Pointer(
PointerEvent::AxisDiscrete120 {
axis: 1, // Horizontal
value: V120_STEPS_PER_LINE * h as i32,
},
)));
}
} }
} }
_ => (), _ => (),
@@ -427,8 +453,10 @@ fn create_event_tap<'a>(
// Returning Drop should stop the event from being processed // Returning Drop should stop the event from being processed
// but core fundation still returns the event // but core fundation still returns the event
cg_ev.set_type(CGEventType::Null); cg_ev.set_type(CGEventType::Null);
CallbackResult::Drop
} else {
CallbackResult::Keep
} }
CallbackResult::Replace(cg_ev.to_owned())
}; };
let tap = CGEventTap::new( let tap = CGEventTap::new(

View File

@@ -1,18 +1,18 @@
# Nix Flake Usage # Nix Flake Usage
## run ## Run
```bash ```bash
nix run github:feschber/lan-mouse nix run github:feschber/lan-mouse
# with params # With params
nix run github:feschber/lan-mouse -- --help nix run github:feschber/lan-mouse -- --help
``` ```
## home-manager module ## Home-manager module
add input Add input:
```nix ```nix
inputs = { inputs = {
@@ -20,14 +20,27 @@ inputs = {
} }
``` ```
enable lan-mouse Optional: add [our binary cache](https://app.cachix.org/cache/lan-mouse) to allow a faster package install.
```nix
nixConfig = {
extra-substituters = [
"https://lan-mouse.cachix.org/"
];
extra-trusted-public-keys = [
"lan-mouse.cachix.org-1:KlE2AEZUgkzNKM7BIzMQo8w9yJYqUpor1CAUNRY6OyM="
];
};
```
Enable lan-mouse:
``` nix ``` nix
{ {
inputs, inputs,
... ...
}: { }: {
# add the home manager module # Add the Home Manager module
imports = [inputs.lan-mouse.homeManagerModules.default]; imports = [inputs.lan-mouse.homeManagerModules.default];
programs.lan-mouse = { programs.lan-mouse = {

View File

@@ -362,7 +362,13 @@ impl CaptureTask {
} }
async fn release_capture(&mut self, capture: &mut InputCapture) -> Result<(), CaptureError> { async fn release_capture(&mut self, capture: &mut InputCapture) -> Result<(), CaptureError> {
self.active_client.take(); // If we have an active client, notify them we're leaving
if let Some(handle) = self.active_client.take() {
log::info!("sending Leave event to client {handle}");
if let Err(e) = self.conn.send(ProtoEvent::Leave(0), handle).await {
log::warn!("failed to send Leave to client {handle}: {e}");
}
}
capture.release().await capture.release().await
} }
} }

View File

@@ -223,14 +223,18 @@ async fn ping_pong(
) { ) {
loop { loop {
let (buf, len) = ProtoEvent::Ping.into(); let (buf, len) = ProtoEvent::Ping.into();
if let Err(e) = conn.send(&buf[..len]).await {
log::warn!("{addr}: send error `{e}`, closing connection");
let _ = conn.close().await;
break;
}
log::trace!("PING >->->->->- {addr}");
tokio::time::sleep(Duration::from_millis(500)).await; // send 4 pings, at least one must be answered
for _ in 0..4 {
if let Err(e) = conn.send(&buf[..len]).await {
log::warn!("{addr}: send error `{e}`, closing connection");
let _ = conn.close().await;
break;
}
log::trace!("PING >->->->->- {addr}");
tokio::time::sleep(Duration::from_millis(500)).await;
}
if !ping_response.borrow_mut().remove(&addr) { if !ping_response.borrow_mut().remove(&addr) {
log::warn!("{addr} did not respond, closing connection"); log::warn!("{addr} did not respond, closing connection");