diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index b247103..975c808 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -67,6 +67,7 @@ "LEFT_HANDED_MOUSE": "Left-handed mouse", "LEFT_HANDED_MOUSE_HELP": "Use this if mouse buttons are swapped", "LONG_PRESS_DURATION": "Long press duration", + "LONG_PRESS_TO_RIGHT_CLICK": "Long press to right click", "LOOK_AND_FEEL": "Look & Feel", "MISC": "Miscellaneous", "NOTIFICATIONS_ENABLED": "Enable notifications", diff --git a/dash-frontend/src/tab/settings.rs b/dash-frontend/src/tab/settings.rs index cdb8e97..762935e 100644 --- a/dash-frontend/src/tab/settings.rs +++ b/dash-frontend/src/tab/settings.rs @@ -231,6 +231,7 @@ enum SettingType { Language, LeftHandedMouse, LongPressDuration, + LongPressToRightClick, NotificationsEnabled, NotificationsSoundEnabled, OpaqueBackground, @@ -267,6 +268,7 @@ impl SettingType { Self::AllowSliding => &mut config.allow_sliding, Self::FocusFollowsMouseMode => &mut config.focus_follows_mouse_mode, Self::LeftHandedMouse => &mut config.left_handed_mouse, + Self::LongPressToRightClick => &mut config.long_press_to_right_click, Self::BlockGameInput => &mut config.block_game_input, Self::BlockGameInputIgnoreWatch => &mut config.block_game_input_ignore_watch, Self::BlockPosesOnKbdInteraction => &mut config.block_poses_on_kbd_interaction, @@ -378,6 +380,7 @@ impl SettingType { Self::Language => Ok("APP_SETTINGS.LANGUAGE"), Self::LeftHandedMouse => Ok("APP_SETTINGS.LEFT_HANDED_MOUSE"), Self::LongPressDuration => Ok("APP_SETTINGS.LONG_PRESS_DURATION"), + Self::LongPressToRightClick => Ok("APP_SETTINGS.LONG_PRESS_TO_RIGHT_CLICK"), Self::NotificationsEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_ENABLED"), Self::NotificationsSoundEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED"), Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"), @@ -831,6 +834,7 @@ impl TabSettings { checkbox!(mp, c, SettingType::InvertScrollDirectionY); slider_f32!(mp, c, SettingType::ScrollSpeed, 0.1, 5.0, 0.1); slider_f32!(mp, c, SettingType::LongPressDuration, 0.1, 2.0, 0.1); + checkbox!(mp, c, SettingType::LongPressToRightClick); slider_f32!(mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1); slider_f32!(mp, c, SettingType::XrClickSensitivity, 0.1, 1.0, 0.1); slider_f32!(mp, c, SettingType::XrClickSensitivityRelease, 0.1, 1.0, 0.1); diff --git a/wayvr/src/backend/input.rs b/wayvr/src/backend/input.rs index 3d92e6b..a15714f 100644 --- a/wayvr/src/backend/input.rs +++ b/wayvr/src/backend/input.rs @@ -101,16 +101,11 @@ impl InputState { hand.interaction.long_press_click_sent = false; } - let long_press_threshold = Duration::from_secs_f32(session.config.long_press_duration); - let is_long_press = hand - .click_press_start - .is_some_and(|start| start.elapsed() >= long_press_threshold); - // Prevent the mode from changing during a click (except for long press) - if !hand.before.click || is_long_press { + if !hand.before.click || (session.config.long_press_to_right_click && hand.click_press_start.is_some_and(|start| start.elapsed() >= Duration::from_secs_f32(session.config.long_press_duration))) { if hand.now.click_modifier_right { hand.interaction.mode = PointerMode::Right; - } else if is_long_press { + } else if session.config.long_press_to_right_click && hand.click_press_start.is_some_and(|start| start.elapsed() >= Duration::from_secs_f32(session.config.long_press_duration)) { hand.interaction.mode = PointerMode::Right; } else if hand.now.click_modifier_middle { hand.interaction.mode = PointerMode::Middle; @@ -545,18 +540,38 @@ where let pointer = &mut app.input_state.pointers[hit.pointer]; // Check if we should send a long-press click immediately - let long_press_threshold = Duration::from_secs_f32(app.session.config.long_press_duration); - let is_long_press = pointer - .click_press_start - .is_some_and(|start| start.elapsed() >= long_press_threshold); + if app.session.config.long_press_to_right_click { + let long_press_threshold = Duration::from_secs_f32(app.session.config.long_press_duration); + let is_long_press = pointer + .click_press_start + .is_some_and(|start| start.elapsed() >= long_press_threshold); - if is_long_press && pointer.now.click && !pointer.interaction.long_press_click_sent { - // Immediately send right-click (press + release) - pointer.interaction.long_press_click_sent = true; - let mut hit_right = hit; - hit_right.mode = PointerMode::Right; - hovered.config.backend.on_pointer(app, &hit_right, true); - hovered.config.backend.on_pointer(app, &hit_right, false); + if is_long_press && pointer.now.click && !pointer.interaction.long_press_click_sent { + // Immediately send right-click (press + release) + pointer.interaction.long_press_click_sent = true; + let mut hit_right = hit; + hit_right.mode = PointerMode::Right; + hovered.config.backend.on_pointer(app, &hit_right, true); + hovered.config.backend.on_pointer(app, &hit_right, false); + } else if pointer.now.click && !pointer.before.click { + pointer.interaction.clicked_id = Some(hit.overlay); + update_focus( + &mut app.hid_provider.keyboard_focus, + hovered.config.keyboard_focus, + ); + hovered.config.backend.on_pointer(app, &hit, true); + } else if !pointer.now.click && pointer.before.click { + // Only send release if we haven't already sent a long press click + if !pointer.interaction.long_press_click_sent { + if let Some(clicked_id) = pointer.interaction.clicked_id.take() { + if let Some(clicked) = overlays.mut_by_id(clicked_id) { + clicked.config.backend.on_pointer(app, &hit, false); + } + } else { + hovered.config.backend.on_pointer(app, &hit, false); + } + } + } } else if pointer.now.click && !pointer.before.click { pointer.interaction.clicked_id = Some(hit.overlay); update_focus( diff --git a/wayvr/src/config.rs b/wayvr/src/config.rs index 2a797e1..5678f57 100644 --- a/wayvr/src/config.rs +++ b/wayvr/src/config.rs @@ -113,6 +113,7 @@ pub struct AutoSettings { pub invert_scroll_direction_y: bool, pub scroll_speed: f32, pub long_press_duration: f32, + pub long_press_to_right_click: bool, pub notifications_enabled: bool, pub notifications_sound_enabled: bool, pub keyboard_sound_enabled: bool, @@ -163,6 +164,7 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> { invert_scroll_direction_y: config.invert_scroll_direction_y, scroll_speed: config.scroll_speed, long_press_duration: config.long_press_duration, + long_press_to_right_click: config.long_press_to_right_click, notifications_enabled: config.notifications_enabled, notifications_sound_enabled: config.notifications_sound_enabled, keyboard_sound_enabled: config.keyboard_sound_enabled, diff --git a/wayvr/src/res/config.yaml b/wayvr/src/res/config.yaml index 76064af..88afd56 100644 --- a/wayvr/src/res/config.yaml +++ b/wayvr/src/res/config.yaml @@ -182,6 +182,9 @@ ## before it's considered a long press #long_press_duration: 1.0 +## When enabled, a long press will be interpreted as a right click. +#long_press_to_right_click: true + ## Change speed of scrolling # 0.5 → half the speed # 2.0 → twice the speed diff --git a/wlx-common/src/config.rs b/wlx-common/src/config.rs index 6086477..ff9c82a 100644 --- a/wlx-common/src/config.rs +++ b/wlx-common/src/config.rs @@ -184,6 +184,9 @@ pub struct GeneralConfig { #[serde(default = "def_one")] pub long_press_duration: f32, + #[serde(default = "def_true")] + pub long_press_to_right_click: bool, + #[serde(default = "def_mouse_move_interval_ms")] pub mouse_move_interval_ms: i32,