summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-11-24 22:12:31 +0100
committerMarkus Pettersson <markus.pettersson@mullvad.net>2024-11-27 07:19:19 +0100
commitc43ac26acb47e1dbf8231a065dd66b4befc0cce3 (patch)
treeb07dce0f8718a8f448a2d734d39002e810710930
parent906a393e7f1daf6c584d173b8b2309b9d8edb585 (diff)
downloadmullvadvpn-c43ac26acb47e1dbf8231a065dd66b4befc0cce3.tar.xz
mullvadvpn-c43ac26acb47e1dbf8231a065dd66b4befc0cce3.zip
Allow `start` to be called multiple time
Create one `NSEventContext` per call to `start`, effectively allowing multiple, independenct callback to be registered at once.
-rw-r--r--desktop/packages/nseventforwarder/nseventforwarder-rs/lib.rs77
-rw-r--r--desktop/packages/nseventforwarder/src/index.cts4
2 files changed, 36 insertions, 45 deletions
diff --git a/desktop/packages/nseventforwarder/nseventforwarder-rs/lib.rs b/desktop/packages/nseventforwarder/nseventforwarder-rs/lib.rs
index e3d8deb9a8..09c7271e5a 100644
--- a/desktop/packages/nseventforwarder/nseventforwarder-rs/lib.rs
+++ b/desktop/packages/nseventforwarder/nseventforwarder-rs/lib.rs
@@ -8,10 +8,8 @@ use std::thread::JoinHandle;
use block2::RcBlock;
use neon::prelude::{
- Context, FunctionContext, Handle, JsFunction, JsNull, JsResult, JsUndefined, ModuleContext,
- NeonResult, Object, Root,
+ Context, FunctionContext, JsFunction, JsNull, JsResult, ModuleContext, NeonResult, Object, Root,
};
-use neon::result::Throw;
use objc2_app_kit::{NSEvent, NSEventMask};
#[neon::main]
@@ -20,31 +18,11 @@ fn main(mut cx: ModuleContext<'_>) -> NeonResult<()> {
Ok(())
}
-/// NSEventForwarder instance. It must be initialized by `start` and cleaned up by the callback
-/// function returned from `start`.
-static NSEVENTFORWARDER: Mutex<Option<NSEventForwarder>> = Mutex::new(None);
-
-struct NSEventForwarder {
- /// The thread listening for incoming [NSEvent]s.
- thread: JoinHandle<()>,
- /// Signal for the current execution context to stop.
- stop: mpsc::Sender<()>,
-}
-
-impl NSEventForwarder {
- fn stop(self) {
- // Tell the thread to stop running
- let _ = self.stop.send(());
- // Wait for the thread to shutdown
- self.thread
- .join()
- .expect("Couldn't join the NSEventForwarder thread");
- }
-}
-
/// Register a callback to fire every time a [NSEventMask::LeftMouseDown] or [NSEventMask::RightMouseDown] event occur.
///
-/// Returns a stop function to call when the original callback shouldn't be called anymore.
+/// Returns a stop function to call when the original callback shouldn't be called anymore. This
+/// stop function returns a `true` value when called the first time and the callback is
+/// deregistered. If it were to be called yet again, it will keep returning `false`.
fn start(mut cx: FunctionContext<'_>) -> JsResult<'_, JsFunction> {
// Set up neon stuff.
// These will be moved into the spawned thread
@@ -88,29 +66,42 @@ fn start(mut cx: FunctionContext<'_>) -> JsResult<'_, JsFunction> {
// The thread's execution will stop when this function returns
});
- let new_context = NSEventForwarder {
+ // NSEventForwarder instance. It must be cleaned up by the callback
+ // function returned from `start` (aka `stop`). We use an Option here
+ // because we can not enforce the Nodejs caller to only call `stop` once.
+ let nseventforwarder = Mutex::new(Some(NSEventForwarder {
thread: join_handle,
stop: stop_tx,
- };
-
- // Update the global NSEventForwarder state
- let mut nseventmonitor_context = NSEVENTFORWARDER.lock().unwrap();
- // Stop any old NSEventForwarder
- if let Some(context) = nseventmonitor_context.take() {
- context.stop();
- }
- let _ = nseventmonitor_context.insert(new_context);
- drop(nseventmonitor_context);
+ }));
// Return a stop function to be invoked from the node runtime to deregister the NSEvent
// callback.
- JsFunction::new(&mut cx, stop)
+ JsFunction::new(&mut cx, move |mut cx: FunctionContext<'_>| {
+ // Stop this NSEventForwarder
+ // Returns whether NSEventForwarder was stopped on this invocation of the stop function
+ let mut stopped = false;
+ if let Some(context) = nseventforwarder.lock().unwrap().take() {
+ context.stop();
+ stopped = true;
+ }
+ Ok(cx.boolean(stopped))
+ })
}
-fn stop(mut cx: FunctionContext<'_>) -> Result<Handle<'_, JsUndefined>, Throw> {
- if let Some(context) = NSEVENTFORWARDER.lock().unwrap().take() {
- context.stop();
- }
+struct NSEventForwarder {
+ /// The thread listening for incoming [NSEvent]s.
+ thread: JoinHandle<()>,
+ /// Signal for the current execution context to stop.
+ stop: mpsc::Sender<()>,
+}
- Ok(JsUndefined::new(&mut cx))
+impl NSEventForwarder {
+ fn stop(self) {
+ // Tell the thread to stop running
+ let _ = self.stop.send(());
+ // Wait for the thread to shutdown
+ self.thread
+ .join()
+ .expect("Couldn't join the NSEventForwarder thread");
+ }
}
diff --git a/desktop/packages/nseventforwarder/src/index.cts b/desktop/packages/nseventforwarder/src/index.cts
index bee20624ae..0d480d15ad 100644
--- a/desktop/packages/nseventforwarder/src/index.cts
+++ b/desktop/packages/nseventforwarder/src/index.cts
@@ -6,9 +6,9 @@ import * as addon from './load.cjs';
// Use this declaration to assign types to the addon's exports,
// which otherwise by default are `any`.
declare module './load.cjs' {
- function start(cb: () => void): () => void;
+ function start(cb: () => void): () => boolean;
}
-export function start(cb: () => void): () => void {
+export function start(cb: () => void): () => boolean {
return addon.start(cb);
}