Skip to content

Commit

Permalink
#1381 Fix "This app does not have Accessibility Permissions enabled a…
Browse files Browse the repository at this point in the history
…nd will not work" error
  • Loading branch information
helgoboss committed Dec 27, 2024
1 parent 3e4b34b commit 26cfea6
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ stylua = "0.19.1"
resvg = "0.44.0"
enigo = "0.0.14"
device_query = "1.1.1"
macos-accessibility-client = "0.0.1"
base64 = "0.21.2"
rtrb = "0.3.0"
envcrypt = "0.5.0"
Expand Down
7 changes: 6 additions & 1 deletion base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ tracing.workspace = true
metrics.workspace = true
ascii.workspace = true
enigo.workspace = true
# For getting current mouse state
device_query.workspace = true
derive_more.workspace = true
either.workspace = true
logos.workspace = true
anyhow.workspace = true
thiserror.workspace = true
camino.workspace = true
indexmap.workspace = true
indexmap.workspace = true

[target.'cfg(target_os = "macos")'.dependencies]
# For not letting device_query panic when macOS accessibility permissions not granted
macos-accessibility-client.workspace = true
46 changes: 41 additions & 5 deletions base/src/mouse/enigo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,47 @@ use crate::{Mouse, MouseCursorPosition};
use device_query::DeviceState;
use enigo::{Enigo, MouseControllable};
use helgobox_api::persistence::{Axis, MouseButton};
use reaper_high::Reaper;

Check failure on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Check

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Check

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Test

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Test

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Build

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Build

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Build

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Build

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Build

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Test

unused import: `reaper_high::Reaper`

Check warning on line 5 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Test

unused import: `reaper_high::Reaper`
use std::fmt::Debug;

#[derive(Debug, Default)]
#[derive(Debug)]
pub struct EnigoMouse {
enigo: Enigo,
device_state: DeviceState,
device_state: Option<DeviceState>,
}

impl EnigoMouse {
pub fn new() -> Self {

Check failure on line 15 in base/src/mouse/enigo.rs

View workflow job for this annotation

GitHub Actions / Clippy

you should consider adding a `Default` implementation for `EnigoMouse`
Self {
enigo: Default::default(),
device_state: create_device_state(),
}
}
}

fn create_device_state() -> Option<DeviceState> {
#[cfg(target_os = "macos")]
{
let trusted =
macos_accessibility_client::accessibility::application_is_trusted_with_prompt();
if trusted {
Some(DeviceState::new())
} else {
Reaper::get().show_console_msg("This Helgobox feature only works if Helgobox can access the state of your mouse. For this, it needs macOS accessibility permissions. Please grant REAPER the accessibility permission in the macOS system settings and restart it!\n\n");
None
}
}
#[cfg(not(target_os = "macos"))]
{
Some(DeviceState::new())
}
}

unsafe impl Send for EnigoMouse {}

impl Clone for EnigoMouse {
fn clone(&self) -> Self {
Default::default()
Self::new()
}
}

Expand Down Expand Up @@ -52,7 +80,11 @@ impl Mouse for EnigoMouse {
let (x, y) = Enigo::mouse_location();
#[cfg(target_os = "linux")]
let (x, y) = {
let device_state = self.device_state.query_pointer();
let device_state = self
.device_state
.as_ref()
.expect("DeviceState should always work on Linux")
.query_pointer();
(device_state.coords.0, device_state.coords.1)
};
Ok(MouseCursorPosition::new(x.max(0) as u32, y.max(0) as u32))
Expand Down Expand Up @@ -91,7 +123,11 @@ impl Mouse for EnigoMouse {
}

fn is_pressed(&self, button: MouseButton) -> Result<bool, &'static str> {
let mouse_state = self.device_state.query_pointer();
let mouse_state = self
.device_state
.as_ref()
.ok_or("macOS accessibility permissions not granted")?
.query_pointer();
let button_index = convert_button_to_device_query(button);
let pressed = mouse_state
.button_pressed
Expand Down
4 changes: 3 additions & 1 deletion main/src/domain/targets/mouse_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl UnresolvedReaperTargetDef for UnresolvedMouseTarget {
_: CompartmentKind,
) -> Result<Vec<ReaperTarget>, &'static str> {
Ok(vec![ReaperTarget::Mouse(EnigoMouseTarget {
mouse: Default::default(),
mouse: EnigoMouse::new(),
action_type: self.action_type,
axis: self.axis,
button: self.button,
Expand Down Expand Up @@ -235,6 +235,8 @@ pub const MOUSE_TARGET: TargetTypeDef = TargetTypeDef {
section: TargetSection::Global,
name: "Mouse",
short_name: "Mouse",
#[cfg(target_os = "macos")]
hint: "Needs macOS accessibility permissions",
supports_axis: true,
supports_mouse_button: true,
..DEFAULT_TARGET
Expand Down
2 changes: 1 addition & 1 deletion pot-browser/src/pot_browser_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2588,7 +2588,7 @@ impl MainState {
bank_index: 0,
preset_cache: PresetCache::new(),
dialog: Default::default(),
mouse: Default::default(),
mouse: EnigoMouse::new(),
has_shown_legacy_vst3_scan_warning: false,
}
}
Expand Down
2 changes: 1 addition & 1 deletion pot/src/preset_crawler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ where
let reaper_resource_dir = Reaper::get().resource_path();
let fx_info = args.fx.info()?;
let plugin_id = get_plugin_id_from_fx_info(&fx_info);
let mut mouse = EnigoMouse::default();
let mut mouse = EnigoMouse::new();
let escape_catcher = EscapeCatcher::new();
let mut chunks_file = tempfile::tempfile()?;
let mut current_file_offset = 0u64;
Expand Down

0 comments on commit 26cfea6

Please sign in to comment.