@@ -88,7 +88,7 @@ impl MacOSEmulation {
8888 button_state,
8989 previous_button : None ,
9090 previous_button_click : None ,
91- button_click_state : 1 ,
91+ button_click_state : 0 ,
9292 repeat_task : None ,
9393 notify_repeat_task : Arc :: new ( Notify :: new ( ) ) ,
9494 modifier_state : Rc :: new ( Cell :: new ( XMods :: empty ( ) ) ) ,
@@ -244,158 +244,165 @@ impl Emulation for MacOSEmulation {
244244 ) -> Result < ( ) , EmulationError > {
245245 log:: trace!( "{event:?}" ) ;
246246 match event {
247- Event :: Pointer ( pointer_event) => match pointer_event {
248- PointerEvent :: Motion { time : _, dx, dy } => {
249- let mut mouse_location = match self . get_mouse_location ( ) {
250- Some ( l) => l,
251- None => {
252- log:: warn!( "could not get mouse location!" ) ;
253- return Ok ( ( ) ) ;
247+ Event :: Pointer ( pointer_event) => {
248+ match pointer_event {
249+ PointerEvent :: Motion { time : _, dx, dy } => {
250+ let mut mouse_location = match self . get_mouse_location ( ) {
251+ Some ( l) => l,
252+ None => {
253+ log:: warn!( "could not get mouse location!" ) ;
254+ return Ok ( ( ) ) ;
255+ }
256+ } ;
257+
258+ let ( new_mouse_x, new_mouse_y) =
259+ clamp_to_screen_space ( mouse_location. x , mouse_location. y , dx, dy) ;
260+
261+ mouse_location. x = new_mouse_x;
262+ mouse_location. y = new_mouse_y;
263+
264+ let mut event_type = CGEventType :: MouseMoved ;
265+ if self . button_state . left {
266+ event_type = CGEventType :: LeftMouseDragged
267+ } else if self . button_state . right {
268+ event_type = CGEventType :: RightMouseDragged
269+ } else if self . button_state . center {
270+ event_type = CGEventType :: OtherMouseDragged
271+ } ;
272+ let event = match CGEvent :: new_mouse_event (
273+ self . event_source . clone ( ) ,
274+ event_type,
275+ mouse_location,
276+ CGMouseButton :: Left ,
277+ ) {
278+ Ok ( e) => e,
279+ Err ( _) => {
280+ log:: warn!( "mouse event creation failed!" ) ;
281+ return Ok ( ( ) ) ;
282+ }
283+ } ;
284+ event. set_integer_value_field ( EventField :: MOUSE_EVENT_DELTA_X , dx as i64 ) ;
285+ event. set_integer_value_field ( EventField :: MOUSE_EVENT_DELTA_Y , dy as i64 ) ;
286+ event. post ( CGEventTapLocation :: HID ) ;
287+ }
288+ PointerEvent :: Button {
289+ time : _,
290+ button,
291+ state,
292+ } => {
293+ let ( event_type, mouse_button) = match ( button, state) {
294+ ( BTN_LEFT , 1 ) => ( CGEventType :: LeftMouseDown , CGMouseButton :: Left ) ,
295+ ( BTN_LEFT , 0 ) => ( CGEventType :: LeftMouseUp , CGMouseButton :: Left ) ,
296+ ( BTN_RIGHT , 1 ) => ( CGEventType :: RightMouseDown , CGMouseButton :: Right ) ,
297+ ( BTN_RIGHT , 0 ) => ( CGEventType :: RightMouseUp , CGMouseButton :: Right ) ,
298+ ( BTN_MIDDLE , 1 ) => ( CGEventType :: OtherMouseDown , CGMouseButton :: Center ) ,
299+ ( BTN_MIDDLE , 0 ) => ( CGEventType :: OtherMouseUp , CGMouseButton :: Center ) ,
300+ _ => {
301+ log:: warn!( "invalid button event: {button},{state}" ) ;
302+ return Ok ( ( ) ) ;
303+ }
304+ } ;
305+ // store button state
306+ self . button_state [ mouse_button] = state == 1 ;
307+
308+ // update previous button state
309+ if state == 1 {
310+ if self . previous_button . is_some_and ( |b| b. eq ( & mouse_button) )
311+ && self
312+ . previous_button_click
313+ . is_some_and ( |i| i. elapsed ( ) < DOUBLE_CLICK_INTERVAL )
314+ {
315+ self . button_click_state += 1 ;
316+ } else {
317+ self . button_click_state = 1 ;
318+ }
319+ self . previous_button = Some ( mouse_button) ;
320+ self . previous_button_click = Some ( Instant :: now ( ) ) ;
254321 }
255- } ;
256322
257- let ( new_mouse_x, new_mouse_y) =
258- clamp_to_screen_space ( mouse_location. x , mouse_location. y , dx, dy) ;
259-
260- mouse_location. x = new_mouse_x;
261- mouse_location. y = new_mouse_y;
262-
263- let mut event_type = CGEventType :: MouseMoved ;
264- if self . button_state . left {
265- event_type = CGEventType :: LeftMouseDragged
266- } else if self . button_state . right {
267- event_type = CGEventType :: RightMouseDragged
268- } else if self . button_state . center {
269- event_type = CGEventType :: OtherMouseDragged
270- } ;
271- let event = match CGEvent :: new_mouse_event (
272- self . event_source . clone ( ) ,
273- event_type,
274- mouse_location,
275- CGMouseButton :: Left ,
276- ) {
277- Ok ( e) => e,
278- Err ( _) => {
279- log:: warn!( "mouse event creation failed!" ) ;
280- return Ok ( ( ) ) ;
281- }
282- } ;
283- event. set_integer_value_field ( EventField :: MOUSE_EVENT_DELTA_X , dx as i64 ) ;
284- event. set_integer_value_field ( EventField :: MOUSE_EVENT_DELTA_Y , dy as i64 ) ;
285- event. post ( CGEventTapLocation :: HID ) ;
286- }
287- PointerEvent :: Button {
288- time : _,
289- button,
290- state,
291- } => {
292- let ( event_type, mouse_button) = match ( button, state) {
293- ( BTN_LEFT , 1 ) => ( CGEventType :: LeftMouseDown , CGMouseButton :: Left ) ,
294- ( BTN_LEFT , 0 ) => ( CGEventType :: LeftMouseUp , CGMouseButton :: Left ) ,
295- ( BTN_RIGHT , 1 ) => ( CGEventType :: RightMouseDown , CGMouseButton :: Right ) ,
296- ( BTN_RIGHT , 0 ) => ( CGEventType :: RightMouseUp , CGMouseButton :: Right ) ,
297- ( BTN_MIDDLE , 1 ) => ( CGEventType :: OtherMouseDown , CGMouseButton :: Center ) ,
298- ( BTN_MIDDLE , 0 ) => ( CGEventType :: OtherMouseUp , CGMouseButton :: Center ) ,
299- _ => {
300- log:: warn!( "invalid button event: {button},{state}" ) ;
301- return Ok ( ( ) ) ;
302- }
303- } ;
304- // store button state
305- self . button_state [ mouse_button] = state == 1 ;
306-
307- // update previous button state
308- if state == 1 {
309- if self . previous_button . is_some_and ( |b| b. eq ( & mouse_button) )
310- && self
311- . previous_button_click
312- . is_some_and ( |i| i. elapsed ( ) < DOUBLE_CLICK_INTERVAL )
313- {
314- self . button_click_state += 1 ;
315- } else {
316- self . button_click_state = 1 ;
317- }
318- self . previous_button = Some ( mouse_button) ;
319- self . previous_button_click = Some ( Instant :: now ( ) ) ;
323+ log:: debug!( "click_state: {}" , self . button_click_state) ;
324+ let location = self . get_mouse_location ( ) . unwrap ( ) ;
325+ let event = match CGEvent :: new_mouse_event (
326+ self . event_source . clone ( ) ,
327+ event_type,
328+ location,
329+ mouse_button,
330+ ) {
331+ Ok ( e) => e,
332+ Err ( ( ) ) => {
333+ log:: warn!( "mouse event creation failed!" ) ;
334+ return Ok ( ( ) ) ;
335+ }
336+ } ;
337+ event. set_integer_value_field (
338+ EventField :: MOUSE_EVENT_CLICK_STATE ,
339+ self . button_click_state ,
340+ ) ;
341+ event. post ( CGEventTapLocation :: HID ) ;
342+ }
343+ PointerEvent :: Axis {
344+ time : _,
345+ axis,
346+ value,
347+ } => {
348+ let value = value as i32 ;
349+ let ( count, wheel1, wheel2, wheel3) = match axis {
350+ 0 => ( 1 , value, 0 , 0 ) , // 0 = vertical => 1 scroll wheel device (y axis)
351+ 1 => ( 2 , 0 , value, 0 ) , // 1 = horizontal => 2 scroll wheel devices (y, x) -> (0, x)
352+ _ => {
353+ log:: warn!( "invalid scroll event: {axis}, {value}" ) ;
354+ return Ok ( ( ) ) ;
355+ }
356+ } ;
357+ let event = match CGEvent :: new_scroll_event (
358+ self . event_source . clone ( ) ,
359+ ScrollEventUnit :: PIXEL ,
360+ count,
361+ wheel1,
362+ wheel2,
363+ wheel3,
364+ ) {
365+ Ok ( e) => e,
366+ Err ( ( ) ) => {
367+ log:: warn!( "scroll event creation failed!" ) ;
368+ return Ok ( ( ) ) ;
369+ }
370+ } ;
371+ event. post ( CGEventTapLocation :: HID ) ;
372+ }
373+ PointerEvent :: AxisDiscrete120 { axis, value } => {
374+ const LINES_PER_STEP : i32 = 3 ;
375+ let ( count, wheel1, wheel2, wheel3) = match axis {
376+ 0 => ( 1 , value / ( 120 / LINES_PER_STEP ) , 0 , 0 ) , // 0 = vertical => 1 scroll wheel device (y axis)
377+ 1 => ( 2 , 0 , value / ( 120 / LINES_PER_STEP ) , 0 ) , // 1 = horizontal => 2 scroll wheel devices (y, x) -> (0, x)
378+ _ => {
379+ log:: warn!( "invalid scroll event: {axis}, {value}" ) ;
380+ return Ok ( ( ) ) ;
381+ }
382+ } ;
383+ let event = match CGEvent :: new_scroll_event (
384+ self . event_source . clone ( ) ,
385+ ScrollEventUnit :: LINE ,
386+ count,
387+ wheel1,
388+ wheel2,
389+ wheel3,
390+ ) {
391+ Ok ( e) => e,
392+ Err ( ( ) ) => {
393+ log:: warn!( "scroll event creation failed!" ) ;
394+ return Ok ( ( ) ) ;
395+ }
396+ } ;
397+ event. post ( CGEventTapLocation :: HID ) ;
320398 }
321-
322- log:: debug!( "click_state: {}" , self . button_click_state) ;
323- let location = self . get_mouse_location ( ) . unwrap ( ) ;
324- let event = match CGEvent :: new_mouse_event (
325- self . event_source . clone ( ) ,
326- event_type,
327- location,
328- mouse_button,
329- ) {
330- Ok ( e) => e,
331- Err ( ( ) ) => {
332- log:: warn!( "mouse event creation failed!" ) ;
333- return Ok ( ( ) ) ;
334- }
335- } ;
336- event. set_integer_value_field (
337- EventField :: MOUSE_EVENT_CLICK_STATE ,
338- self . button_click_state ,
339- ) ;
340- event. post ( CGEventTapLocation :: HID ) ;
341- }
342- PointerEvent :: Axis {
343- time : _,
344- axis,
345- value,
346- } => {
347- let value = value as i32 ;
348- let ( count, wheel1, wheel2, wheel3) = match axis {
349- 0 => ( 1 , value, 0 , 0 ) , // 0 = vertical => 1 scroll wheel device (y axis)
350- 1 => ( 2 , 0 , value, 0 ) , // 1 = horizontal => 2 scroll wheel devices (y, x) -> (0, x)
351- _ => {
352- log:: warn!( "invalid scroll event: {axis}, {value}" ) ;
353- return Ok ( ( ) ) ;
354- }
355- } ;
356- let event = match CGEvent :: new_scroll_event (
357- self . event_source . clone ( ) ,
358- ScrollEventUnit :: PIXEL ,
359- count,
360- wheel1,
361- wheel2,
362- wheel3,
363- ) {
364- Ok ( e) => e,
365- Err ( ( ) ) => {
366- log:: warn!( "scroll event creation failed!" ) ;
367- return Ok ( ( ) ) ;
368- }
369- } ;
370- event. post ( CGEventTapLocation :: HID ) ;
371399 }
372- PointerEvent :: AxisDiscrete120 { axis, value } => {
373- const LINES_PER_STEP : i32 = 3 ;
374- let ( count, wheel1, wheel2, wheel3) = match axis {
375- 0 => ( 1 , value / ( 120 / LINES_PER_STEP ) , 0 , 0 ) , // 0 = vertical => 1 scroll wheel device (y axis)
376- 1 => ( 2 , 0 , value / ( 120 / LINES_PER_STEP ) , 0 ) , // 1 = horizontal => 2 scroll wheel devices (y, x) -> (0, x)
377- _ => {
378- log:: warn!( "invalid scroll event: {axis}, {value}" ) ;
379- return Ok ( ( ) ) ;
380- }
381- } ;
382- let event = match CGEvent :: new_scroll_event (
383- self . event_source . clone ( ) ,
384- ScrollEventUnit :: LINE ,
385- count,
386- wheel1,
387- wheel2,
388- wheel3,
389- ) {
390- Ok ( e) => e,
391- Err ( ( ) ) => {
392- log:: warn!( "scroll event creation failed!" ) ;
393- return Ok ( ( ) ) ;
394- }
395- } ;
396- event. post ( CGEventTapLocation :: HID ) ;
400+
401+ // reset button click state in case it's not a button event
402+ if !matches ! ( pointer_event, PointerEvent :: Button { .. } ) {
403+ self . button_click_state = 0 ;
397404 }
398- } ,
405+ }
399406 Event :: Keyboard ( keyboard_event) => match keyboard_event {
400407 KeyboardEvent :: Key {
401408 time : _,
0 commit comments