1- use scap_targets:: { Display , DisplayId , bounds:: LogicalBounds } ;
1+ use cap_recording:: sources:: screen_capture:: ScreenCaptureTarget ;
2+ use scap_targets:: { Display , DisplayId , Window as ScapWindow , bounds:: LogicalBounds } ;
23use std:: { collections:: HashMap , sync:: Arc , time:: Duration } ;
34use tauri:: { AppHandle , Manager , WebviewWindow } ;
45use tokio:: { sync:: RwLock , time:: sleep} ;
56use tracing:: instrument;
67
8+ use crate :: { App , ArcLock , RecordingState } ;
9+
710const RECORDING_CONTROLS_LABEL : & str = "in-progress-recording" ;
811const RECORDING_CONTROLS_WIDTH : f64 = 320.0 ;
912const RECORDING_CONTROLS_HEIGHT : f64 = 150.0 ;
@@ -70,6 +73,37 @@ fn calculate_bottom_center_position(display: &Display) -> Option<(f64, f64)> {
7073 Some ( ( pos_x, pos_y) )
7174}
7275
76+ const TARGET_CONTROLS_OFFSET_Y : f64 = 48.0 ;
77+
78+ pub fn calculate_recording_controls_position_for_target (
79+ capture_target : & ScreenCaptureTarget ,
80+ ) -> Option < ( f64 , f64 ) > {
81+ match capture_target {
82+ ScreenCaptureTarget :: Window { id } => {
83+ let window = ScapWindow :: from_id ( id) ?;
84+ let bounds = window. raw_handle ( ) . logical_bounds ( ) ?;
85+ let pos_x =
86+ bounds. position ( ) . x ( ) + ( bounds. size ( ) . width ( ) - RECORDING_CONTROLS_WIDTH ) / 2.0 ;
87+ let pos_y = bounds. position ( ) . y ( ) + bounds. size ( ) . height ( )
88+ - RECORDING_CONTROLS_HEIGHT
89+ - TARGET_CONTROLS_OFFSET_Y ;
90+ Some ( ( pos_x, pos_y) )
91+ }
92+ ScreenCaptureTarget :: Area { screen, bounds } => {
93+ let display = Display :: from_id ( screen) ?;
94+ let display_bounds = display. raw_handle ( ) . logical_bounds ( ) ?;
95+ let abs_x = display_bounds. position ( ) . x ( ) + bounds. position ( ) . x ( ) ;
96+ let abs_y = display_bounds. position ( ) . y ( ) + bounds. position ( ) . y ( ) ;
97+ let pos_x = abs_x + ( bounds. size ( ) . width ( ) - RECORDING_CONTROLS_WIDTH ) / 2.0 ;
98+ let pos_y = abs_y + bounds. size ( ) . height ( )
99+ - RECORDING_CONTROLS_HEIGHT
100+ - TARGET_CONTROLS_OFFSET_Y ;
101+ Some ( ( pos_x, pos_y) )
102+ }
103+ _ => None ,
104+ }
105+ }
106+
73107pub fn spawn_fake_window_listener ( app : AppHandle , window : WebviewWindow ) {
74108 window. set_ignore_cursor_events ( true ) . ok ( ) ;
75109
@@ -78,19 +112,59 @@ pub fn spawn_fake_window_listener(app: AppHandle, window: WebviewWindow) {
78112 tokio:: spawn ( async move {
79113 let state = app. state :: < FakeWindowBounds > ( ) ;
80114 let mut current_display_id: Option < DisplayId > = get_display_id_for_cursor ( ) ;
115+ let mut last_target_pos: Option < ( f64 , f64 ) > = None ;
81116
82117 loop {
83118 sleep ( Duration :: from_millis ( 1000 / 20 ) ) . await ;
84119
85- if is_recording_controls && let Some ( cursor_display_id) = get_display_id_for_cursor ( ) {
86- let display_changed = current_display_id. as_ref ( ) != Some ( & cursor_display_id) ;
120+ if is_recording_controls {
121+ let capture_target = app. state :: < ArcLock < App > > ( ) . try_read ( ) . ok ( ) . and_then ( |s| {
122+ match & s. recording_state {
123+ RecordingState :: Pending { target, .. } => Some ( target. clone ( ) ) ,
124+ RecordingState :: Active ( inner) => Some ( inner. capture_target ( ) . clone ( ) ) ,
125+ RecordingState :: None => None ,
126+ }
127+ } ) ;
128+
129+ let mut handled = false ;
130+
131+ if let Some ( ref target) = capture_target {
132+ match target {
133+ ScreenCaptureTarget :: Window { .. } => {
134+ if let Some ( ( px, py) ) =
135+ calculate_recording_controls_position_for_target ( target)
136+ {
137+ let changed = match last_target_pos {
138+ Some ( ( lx, ly) ) => {
139+ ( px - lx) . abs ( ) > 0.5 || ( py - ly) . abs ( ) > 0.5
140+ }
141+ None => true ,
142+ } ;
143+ if changed {
144+ let _ =
145+ window. set_position ( tauri:: LogicalPosition :: new ( px, py) ) ;
146+ last_target_pos = Some ( ( px, py) ) ;
147+ }
148+ handled = true ;
149+ }
150+ }
151+ ScreenCaptureTarget :: Area { .. } => {
152+ handled = true ;
153+ }
154+ _ => { }
155+ }
156+ }
157+
158+ if !handled && let Some ( cursor_display_id) = get_display_id_for_cursor ( ) {
159+ let display_changed = current_display_id. as_ref ( ) != Some ( & cursor_display_id) ;
87160
88- if display_changed
89- && let Some ( display) = get_display_by_id ( & cursor_display_id)
90- && let Some ( ( pos_x, pos_y) ) = calculate_bottom_center_position ( & display)
91- {
92- let _ = window. set_position ( tauri:: LogicalPosition :: new ( pos_x, pos_y) ) ;
93- current_display_id = Some ( cursor_display_id) ;
161+ if display_changed
162+ && let Some ( display) = get_display_by_id ( & cursor_display_id)
163+ && let Some ( ( pos_x, pos_y) ) = calculate_bottom_center_position ( & display)
164+ {
165+ let _ = window. set_position ( tauri:: LogicalPosition :: new ( pos_x, pos_y) ) ;
166+ current_display_id = Some ( cursor_display_id) ;
167+ }
94168 }
95169 }
96170
0 commit comments