
    lKj7                     F   U d Z ddlZddlZddlmZmZmZmZmZ ddl	m
Z
mZmZ ddlZddlmZmZmZmZmZmZ ddlmZmZmZmZmZ ddlmZ dd	lmZmZm Z m!Z!  ejD                  e#      Z$i Z%e&e'd
f   e(d<    ejR                  e      d        Z* G d d      Z+ G d d
      Z,y)z
macOS Accessibility event observation system.
Provides AXObserver wrapper for monitoring accessibility notifications
(focus changes, structure changes, property changes, etc.).

Equivalent to the Windows UIA events.py module, adapted for macOS.
    N)AnyCallableOptionalSequenceSet)ThreadEventLock)AXObserverCreateAXObserverAddNotificationAXObserverRemoveNotificationAXObserverGetRunLoopSourceAXUIElementCreateApplicationkAXErrorSuccess)CFRunLoopGetCurrentCFRunLoopAddSourceCFRunLoopRemoveSourceCFRunLoopRunInModekCFRunLoopDefaultMode)NSWorkspace   )NotificationFOCUS_NOTIFICATIONSSTRUCTURE_NOTIFICATIONSPROPERTY_NOTIFICATIONSEventObserver_observer_registryc                     	 t         j                         D ]1  }|j                  |       s|j                  |t	        |      |        y y# t
        $ r"}t        j                  d|        Y d}~yd}~ww xY w)z
    Global callback function for AXObserver notifications.
    Routes notifications to appropriate EventObserver instances.
    z#Error in global observer callback: N)r   values_has_observer	_dispatchstr	Exceptionloggerdebug)observerelementnotificationrefconevent_observeres         d/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/macos_mcp/ax/events.py_global_observer_callbackr-   2   sn    @0779N++H5((#l2CVL :  @:1#>??@s"   (A A 	A 	A6A11A6c                   N    e Zd ZdZdeddfdZdee   defdZ	dd
Z
dedefdZy	)AppObserverz
    Observer for a single application's accessibility events.
    Each application requires its own AXObserver instance.

    Equivalent to the per-process observer in Windows UIA.
    pidparentr   c                 h    || _         || _        d | _        d | _        d | _        t               | _        y N)r0   r1   r&   ax_apprun_loop_sourcesetregistered_notifications)selfr0   r1   s      r,   __init__zAppObserver.__init__N   s0    #25%%    notificationsreturnc                 x   	 t        | j                        | _        | j                  syt        | j                  t        d      \  }| _        |t        k7  s| j
                  sd| _        yt        | j
                        | _        | j                  sd| _        d| _        yt               }t        || j                  t               |D ]\  }	 t        | j
                  | j                  || j                        }|t        k(  r$| j                  j                  t        |             ^ | j                  s1t#        || j                  t               d| _        d| _        d| _        yy# t         $ r Y w xY w# t         $ r?}t$        j'                  d| j                   d|        | j)                          Y d}~yd}~ww xY w)z
        Create the observer and register for notifications.

        Args:
            notifications: List of notification name strings to watch.

        Returns:
            True if successfully started.
        FNTz!Failed to start observer for PID : )r   r0   r4   r   r-   r&   r   r   r5   r   r   r   r   r7   addr"   r#   r   r$   r%   stop)r8   r;   errorrun_loopr(   r+   s         r,   startzAppObserver.startV   sy   ,	6txx@DK;;#33T$ E4= 't}}"#=dmm#LD '' $"*,Hx)=)=?TU -5t{{L$((E /5599#l:KL !. 00%h0D0DF[\'+$ $" !   	LL<TXXJbLMIIK	sM   &E1 ?E1 )4E1 *E1 	AE"">E1 "	E.+E1 -E..E1 1	F9:5F44F9Nc                    	 | j                   rb| j                  rVt        | j                        D ]$  }	 t	        | j                   | j                  |       & | j                  j                          | j                  r+	 t        t               | j                  t               d| _        d| _         d| _        y# t
        $ r Y w xY w# t
        $ r Y 0w xY w# t
        $ r/}t        j                  d| j                   d|        Y d}~yd}~ww xY w)z)Stop the observer and clean up resources.Nz Error stopping observer for PID r>   )r&   r4   listr7   r   r#   clearr5   r   r   r   r$   r%   r0   )r8   	notif_strr+   s      r,   r@   zAppObserver.stop   s    	M}}!%d&C&C!DI4 MM4;;	 "E --335##)+-,,- (,$ DMDK! %  !   	MLL;DHH:RsKLL	Ms^   0C !B6(C =#C  C 6	C?C CC 	CC CC 	D%DDr&   c                     | j                   |u S )z4Check if this AppObserver owns the given AXObserver.)r&   )r8   r&   s     r,   matches_observerzAppObserver.matches_observer   s    }}((r:   r<   N)__name__
__module____qualname____doc__intr9   r   r"   boolrC   r@   r   rI    r:   r,   r/   r/   F   sK    8C 8 868C= 6T 6pM<) ) )r:   r/   c                       e Zd ZdZdZddefdZd Zd Ze	de
fd       Zdd
ZddZdede
fdZdedededd	fdZdee   fdZdee   fdZddZddZy	)r   ac  
    High-level event observation service for macOS Accessibility.
    Manages multiple AppObserver instances to track changes across applications.

    Equivalent to the Windows UIA event handler system.

    Usage:
        observer = EventObserver()
        observer.on_focus_changed = my_focus_callback
        observer.on_structure_changed = my_structure_callback
        observer.start()
        # ... run your app ...
        observer.stop()

    Or as a context manager:
        with EventObserver() as observer:
            observer.on_focus_changed = my_callback
            # ... run your app ...
    r   debounce_intervalc                    t         xj                  dz  c_        t         j                  | _        t               | _        d| _        t               | _        d| _        d| _	        d| _
        i | _        t               | _        d| _        || _        y)z]
        Args:
            debounce_interval: Minimum time between events (seconds).
        r   Nr   )r   _instance_counter_instance_idr	   _running_threadr
   _lockon_focus_changedon_structure_changedon_property_changed_app_observersr6   _observed_pids_last_event_time_debounce_interval)r8   rS   s     r,   r9   zEventObserver.__init__   s|    
 	''1,');;)-V
 598<!7;  79(+ ()"3r:   c                 &    | j                          | S r3   )rC   r8   s    r,   	__enter__zEventObserver.__enter__   s    

r:   c                 $    | j                          y r3   )r@   )r8   exc_typeexc_valexc_tbs       r,   __exit__zEventObserver.__exit__   s    		r:   r<   c                 6    | j                   j                         S )z!Check if the observer is running.)rW   is_setrb   s    r,   
is_runningzEventObserver.is_running   s     }}##%%r:   Nc                 b   | j                   j                         ry| t        | j                  <   | j                   j	                          t        | j                  d| j                   d      | _        | j                  j                          t        j                  d| j                   d       y)z#Start the event observation thread.NzAXEventObserver-T)targetnamedaemonz EventObserver started (instance ))rW   rj   r   rV   r6   r   _runrX   rC   r$   r%   rb   s    r,   rC   zEventObserver.start   s    ==!044,,-99#D$5$5#67

 	78I8I7J!LMr:   c                 x   | j                   j                         sy| j                   j                          | j                  r6| j                  j	                         r| j                  j                  d       t        j                  | j                  d       t        j                  d| j                   d       y)z"Stop the event observation thread.Ng       @)timeoutz EventObserver stopped (instance rp   )rW   rj   rF   rX   is_alivejoinr   poprV   r$   r%   rb   s    r,   r@   zEventObserver.stop  s    }}##%<<DLL113LLc*t00$778I8I7J!LMr:   r&   c                     | j                   5  | j                  j                         D ]  }|j                  |      s ddd       y 	 ddd       y# 1 sw Y   yxY w)z6Check if this EventObserver owns the given AXObserver.NTF)rY   r]   r   rI   )r8   r&   app_observers      r,   r    zEventObserver._has_observer  sM    ZZ $ 3 3 : : <00: Z <  	  s   /AAAAr'   r(   r0   c                    t        j                          }|| j                  z
  | j                  k  ry|| _        	 |t        v r | j                  r| j	                  |||       y|t
        v r | j                  r| j                  |||       y|t        v r!| j                  r| j                  |||       yyy# t        $ r"}t        j                  d|        Y d}~yd}~ww xY w)z4Dispatch a notification to the appropriate callback.Nz Error in notification dispatch: )timer_   r`   r   rZ   r   r[   r   r\   r#   r$   r%   )r8   r'   r(   r0   current_timer+   s         r,   r!   zEventObserver._dispatch  s    yy{$///$2I2II ,	A22t7L7L%%g|SA!88T=V=V))'<E!77D<T<T((,D =U7 	ALL;A3?@@	As#   'B4 "'B4 
'B4 4	C=CCc                     t               }	 t        j                         j                         }|D ]5  }|j	                         dk(  s|j                  |j                                7 	 |S # t        $ r Y |S w xY w)z1Get PIDs of all running user-facing applications.r   )r6   r   sharedWorkspacerunningApplicationsactivationPolicyr?   processIdentifierr#   )r8   pidsappsapps       r,   _get_running_app_pidsz#EventObserver._get_running_app_pids'  su    u	..0DDFD'')Q.HHS2245 
   		s   :A+ !A+ +	A87A8c                    g }| j                   r>|j                  t        j                  t        j                  t        j
                  g       | j                  rk|j                  t        j                  t        j                  t        j                  t        j                  t        j                  t        j                  g       | j                  r|j                  t        j                  t        j                  t        j                   t        j"                  t        j$                  t        j&                  t        j(                  t        j*                  t        j,                  t        j.                  t        j0                  g       |S )zADetermine which notifications to register based on set callbacks.)rZ   extendr   FocusedUIElementChangedFocusedWindowChangedMainWindowChangedr[   CreatedUIElementDestroyedWindowCreated
MenuOpened
MenuClosedRowCountChangedr\   ValueChangedTitleChangedSelectedTextChangedSelectedChildrenChangedSelectedChildrenMovedSelectedRowsChangedSelectedColumnsChangedSelectedCellsChangedUnitsChangedMovedResized)r8   r;   s     r,   _get_notifications_to_registerz,EventObserver._get_notifications_to_register3  s        88 55 22 $$   (( 33 .. ++ ++ 00	 ##   -- -- 44 88 66 44 77 55 -- && ((  r:   c                    | j                   5  | j                         }| j                         }|sm| j                  j	                         D ]  }|j                           | j                  j                          | j                  j                          	 ddd       y| j                  |z
  }|D ]U  }|| j                  v r*| j                  |   j                          | j                  |= | j                  j                  |       W || j                  z
  }|D ]Z  }t        ||       }|j                  |      r|| j                  |<   n|j                          | j                  j                  |       \ 	 ddd       y# 1 sw Y   yxY w)z9Update observers to match currently running applications.N)rY   r   r   r]   r   r@   rF   r^   discardr/   rC   r?   )r8   current_pidsr;   r&   
terminatedr0   new_pidss          r,   _update_observerszEventObserver._update_observers_  sH   ZZ557L ??AM  $ 3 3 : : <HMMO !=##))+##))+ Z ,,|;J!$---'',113++C0##++C0	 " $d&9&99H&sD1>>-0/7D'', MMO##'',  + ZZs   BE>CE>>Fc                    	 | j                   j                         rYt        j                         5  | j	                          t        t        dd       ddd       | j                   j                         rY| j                  5  | j                  j                         D ]  }	 |j                           | j                  j                          | j                  j                          ddd       y# 1 sw Y   xY w# t        $ r"}t        j                  d|        Y d}~d}~ww xY w# t        $ r Y w xY w# 1 sw Y   yxY w# | j                  5  | j                  j                         D ]"  }	 |j                          # t        $ r Y  w xY w | j                  j                          | j                  j                          ddd       w # 1 sw Y   w xY wxY w)z.Main event loop running in a dedicated thread.g?FNzEventObserver died: )rW   rj   objcautorelease_poolr   r   r   r#   r$   rA   rY   r]   r   r@   rF   r^   )r8   r+   r&   s      r,   rq   zEventObserver._run  sm   	,--&&( **,**,&'<c5I - --&&(  $ 3 3 : : <H  !=
 ##))+##))+  -,  	5LL/s344	5 % 	  $ 3 3 : : <H $  !=
 ##))+##))+ s   .C; "C/"C; D8 D)06D8/C84C; ;	D&D!E !D&&E )	D52D84D55D88EGG0F G	F
GF8G	GGG)g?rJ   )rK   rL   rM   rN   rU   floatr9   rc   rh   propertyrP   rk   rC   r@   r   r    r"   rO   r!   r   r   rE   r   r   rq   rQ   r:   r,   r   r      s    ( 4% 42 &D & &NNc d A AC Ac Ad A"
s3x 
*S	 *X-@,r:   )-rN   loggingrz   typingr   r   r   r   r   	threadingr   r	   r
   r   ApplicationServicesr   r   r   r   r   r   CoreFoundationr   r   r   r   r   Cocoar   enumsr   r   r   r   	getLoggerrK   r$   r   dictrO   __annotations__callbackForr-   r/   r   rQ   r:   r,   <module>r      s      9 9 ) )      
		8	$ 24 Do-. 3 "#@ $@&h) h)``, `,r:   