
    g
fc                        d dl Z  e j                  dd       d dlmZ d dlZd dlZd dlZd dlmZ ddlm	Z	 ddlm
Z
 dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dZd ZdZdZdZdZdZ G d d      Z G d d      Zy)    NAtspiz2.0)r   )GLib   )cmdnames)debug)focus_manager)keybindings)messages)input_event)settings_manager)AXCollection)AXObject)AXText      -   	   c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
PriorityQueuez This class represents a thread **UNSAFE** priority queue where priority
    is determined by the given integer priority.  The entries are also
    maintained in chronological order.

    TODO: experiment with Queue.Queue to make thread safe
    c                     g | _         y Nqueueselfs    2/usr/lib/python3/dist-packages/orca/liveregions.py__init__zPriorityQueue.__init__*   s	    
    c                 p    t        j                  | j                  |t        j                         ||f       y)zS Add a new element to the queue according to 1) priority and
        2) timestamp. N)bisectinsort_leftr   time)r   datapriorityobjs       r   enqueuezPriorityQueue.enqueue-   s'     	4::$))+tS'IJr   c                 8    | j                   j                  d      S )z2get the highest priority element from the queue.  r   )r   popr   s    r   dequeuezPriorityQueue.dequeue2   s    zz~~a  r   c                     g | _         y)z Clear the queue Nr   r   s    r   clearzPriorityQueue.clear6   s	    
r   c                     t        j                          fd}t        t        || j                              | _        y)zC Purge items from the queue that are older than the keepalive time c                 *    | xr | d   t         z   kD  S )Nr   )MSG_KEEPALIVE_TIME)itemcurrenttimes    r   myfilterz0PriorityQueue.purgeByKeepAlive.<locals>.myfilter>   s    FDG&88;FFr   N)r#   listfilterr   )r   r2   r1   s     @r   purgeByKeepAlivezPriorityQueue.purgeByKeepAlive:   s-    iik	G &4::67
r   c                 X    fd}t        t        || j                              | _        y)ze Purge items from the queue that have a lower than or equal priority
        than the given argument c                     | xr | d   kD  S Nr    )r0   r%   s    r   r2   z/PriorityQueue.purgeByPriority.<locals>.myfilterG   s    .DGh..r   N)r3   r4   r   )r   r%   r2   s    ` r   purgeByPriorityzPriorityQueue.purgeByPriorityC   s!    	/ &4::67
r   c                 ,    t        | j                        S )z  Return the length of the queue )lenr   r   s    r   __len__zPriorityQueue.__len__L   s    4::r   N)__name__
__module____qualname____doc__r   r'   r*   r,   r5   r:   r=   r9   r   r   r   r   #   s+    K
!88r   r   c                       e Zd Zd Zd dZd!dZd Zd Zd"dZd"dZ	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd#dZd Zd Zd Zd Z y)$LiveRegionManagerc                    || _         t               | _        d| _        | j	                  d      | _        t        j                         | _        | j                  | j                  | j                  | j                  g| _        g | _        d | _        d | _        d | _        d| _        | j'                          |j(                  j+                  | j,                         |j(                  j/                  | j&                         y )NFT)_scriptr   	msg_queue
_suspendedget_handlers	_handlersr	   KeyBindings	_bindingsadvancePolitenesssetLivePolitenessOfftoggleMonitoringreviewLiveAnnouncement	functions	msg_cache_politenessOverrides_restoreOverrideslastliveobj
monitoringbookmarkLoadHandler	bookmarksaddSaveObserverbookmarkSaveHandleraddLoadObserver)r   scripts     r   r   zLiveRegionManager.__init__R   s    &  **40$002 0033//557  %)!!%    	  "(()A)AB(()A)ABr   c                     |rCd}t        j                  t         j                  |d       | j                          | j                  S | j                  j                         r| j                          | j                  S )z,Returns the live-region-manager keybindings.z)LIVE REGION MANAGER: Refreshing bindings.T)r   printMessage
LEVEL_INFO_setup_bindingsrK   isEmpty)r   refresh
is_desktopmsgs       r   get_bindingszLiveRegionManager.get_bindings   sd     =Cu//d;  " ~~ ^^##%  "~~r   c                     |r7d}t        j                  t         j                  |d       | j                          | j                  S )z)Returns the live-region-manager handlers.z)LIVE REGION MANAGER: Refreshing handlers.T)r   r]   r^   _setup_handlersrI   )r   ra   rc   s      r   rH   zLiveRegionManager.get_handlers   s:     =Cu//d;  "~~r   c                    i | _         t        j                  | j                  t        j
                  | j                         | j                   d<   t        j                  | j                  t        j                  | j                         | j                   d<   t        j                  | j                  t        j                  | j                         | j                   d<   t        j                  | j                  t        j                  | j                         | j                   d<   d| j                   }t        j                  t        j                  |d       y)	z5Sets up the live-region-manager input event handlers.)enabledadvanceLivePolitenessrM   monitorLiveRegionsrO   z1LIVE REGION MANAGER: Handlers set up. Suspended: TN)rI   r   InputEventHandlerrL   r   LIVE_REGIONS_ADVANCE_POLITENESSrG   rM   LIVE_REGIONS_SET_POLITENESS_OFFrN   LIVE_REGIONS_MONITORrO   LIVE_REGIONS_REVIEWr   r]   r^   )r   rc   s     r   rf   z!LiveRegionManager._setup_handlers   s#     ))&&88"oo-/ 	./ ))))88"oo-/ 	-. ))%%--"oo-/ 	+, ))++,,"oo-/ 	/0 B$//ARS5++S$7r   c                 $   t        j                         | _        | j                  j                  t        j                  dt         j
                  t         j                  | j                  j                  d      d| j                                | j                  j                  t        j                  dt         j
                  t         j                  | j                  j                  d      d| j                                | j                  j                  t        j                  dt         j
                  t         j                  | j                  j                  d      d| j                                dD ]u  }| j                  j                  t        j                  |t         j
                  t         j                  | j                  j                  d      d| j                                w t        j                         j                  | j                  | j                  d      | _        d	| j                   }t!        j"                  t         j$                  |d
       | j                  g}t!        j&                  t         j$                  |d
       y)z-Sets up the live-region-manager key bindings.	backslashri   r   rM   rj   )	F1F2F3F4F5F6F7F8F9rO   Fz1LIVE REGION MANAGER: Bindings set up. Suspended: TN)r	   rJ   rK   add
KeyBindingdefaultModifierMaskNO_MODIFIER_MASKrI   getrG   SHIFT_MODIFIER_MASKORCA_SHIFT_MODIFIER_MASKORCA_MODIFIER_MASKr   
getManageroverrideKeyBindingsr   r]   r^   printTokens)r   keyrc   tokenss       r   r_   z!LiveRegionManager._setup_bindings   s    %002""//,,""#:;OO#%	& 	""////""#9:OO#%	& 	""//44""#78OO#%	& J 	*CNN&&3322NN&&'?@')*	* *446JJNNDNNE3 B$//ARS5++S$7..!%**FD9r   c                    d}|r|d| z  }t        j                  t         j                  |d       | j                  j                  D ]  }|j                  j                  |d       ! | j                  d      | _        | j                  d      | _        | j                  j                  D ]*  }|j                  j                  || j                          , y)z4Refreshes live region bindings and grabs for script.z2LIVE REGION MANAGER: Refreshing bindings and grabs: T)includeGrabsN)r   r]   r^   rK   keyBindingsremoverH   rI   rd   r{   rG   )r   r[   reasonrc   bindings        r   refresh_bindings_and_grabsz,LiveRegionManager.refresh_bindings_and_grabs   s     CRx= C5++S$7~~11 	BG%%gD%A	B **40**40~~11 	NG""7T__9L"M	Nr   c                     || j                   k(  ryd| }|r|d| z  }t        j                  t        j                  |d       || _         | j	                  |d|        y)zASuspends live region commands independent of the enabled setting.Nz)LIVE REGION MANAGER: Commands suspended: r   TzSuspended changed to )rG   r   r]   r^   r   )r   r[   	suspendedr   rc   s        r   suspend_commandsz"LiveRegionManager.suspend_commands   si     '9)ERx= C5++S$7#''2G	{0STr   c                     i }| j                   j                  j                         }| j                  j	                         D ]  \  }}|d   |k(  s
|t
        k7  s|||<    || _        y r8   )rE   rW   	getURIKeyrR   items	LIVE_NONE)r   newpoliteness
currenturir   values        r   resetzLiveRegionManager.reset  sj     \\++557
3399; 	+JC1v#u	'9%*c"	+ %2!r   c                 f    | j                   j                  j                  | j                  d       y)zBookmark save callback
politenessfilenameN)rE   rW   saveBookmarksToDiskrR   r   s    r   rY   z%LiveRegionManager.bookmarkSaveHandler  s+    2243L3L=I 	3 	Kr   c                 b    | j                   j                  j                  d      xs i | _        y)zBookmark load callbackr   r   N)rE   rW   readBookmarksFromDiskrR   r   s    r   rV   z%LiveRegionManager.bookmarkLoadHandler  s/    
 	44l4K 	 	!r   c                    | j                  |j                        }|t        k(  ry|t        k(  r| j                  s\y|t
        k(  rnQ|t        k(  r | j                  j                  t
               n(|t        k(  r| j                  j                  t               | j                  |      }|r`t        | j                        dk(  r t        j                  d| j                         | j                  j                  |||j                         yy)zMain live region event handlerNr   d   )_getLiveTypesourceLIVE_OFFr   rU   LIVE_POLITELIVE_ASSERTIVErF   r:   	LIVE_RUDE_getMessager<   r   timeout_addpumpMessagesr'   )r   eventr   messages       r   handleEventzLiveRegionManager.handleEvent  s    &&u||4
!" ??;&N*NN**;79$NN**>:""5)4>>"a'  d&7&78NN""7JE r   c                 0   t        | j                        dkD  rt        j                  t        j                  d       | j                  j                          | j                  j                         \  }}}}|d   |d   k(  r|d   }n|d   |d   z   }| j                  r| j                  j                  |       n'd}t        j                  t        j                  |d       || _        | j                  |       | j                  s| j                  j                          dt        | j                         }t        j                  t        j                  |d       t        j                  t        j                  d       t        | j                        dkD  S )	z Main gobject callback for live region support.  Handles both
        purging the message queue and outputting any queued messages that
        were queued up in the handleEvent() method.
        r   z(
vvvvv PRESENT LIVE REGION MESSAGE vvvvvlabelscontentz6INFO: Not presenting message because monitoring is offTz!LIVE REGIONS: messages in queue: z(^^^^^ PRESENT LIVE REGION MESSAGE ^^^^^
)r<   rF   r   r]   eventDebugLevelr5   r*   rU   rE   presentMessager^   rT   _cacheMessage)r   r   	timestampr   r&   uttsrc   s          r   r   zLiveRegionManager.pumpMessages7  sM    t~~"u446abNN++-26..2H2H2J/J	7C x GI$66y)x(79+==++D1N""5#3#3S$?  #D t$ NN++-1#dnn2E1FG5++S$75002]^ 4>>"Q&&r   c                    g }| j                   j                  j                         }| j                  D ]P  \  }}||k(  st	        |t
              s|j                  | j                   j                  j                  |             R |S )zXReturn the live objects that are registered and have a politeness
        of LIVE_NONE. )rE   rW   r   rR   
isinstancetupleappend	pathToObj)r   retvalr   uriobjectids        r   getLiveNoneObjectsz$LiveRegionManager.getLiveNoneObjects`  su     \\++557
!66 	JMCj Z%%@dll44>>xHI	J r   c                    t        j                         j                  d      s*| j                  j	                  t
        j                         yt        j                         j                         }| j                  |      }| j                  j                  j                         }	 | j                  ||f   }|t        k(  s	|t         k(  r?t"        | j                  ||f<   | j                  j	                  t
        j$                         y|t"        k(  r?t&        | j                  ||f<   | j                  j	                  t
        j(                         y|t&        k(  r?t*        | j                  ||f<   | j                  j	                  t
        j,                         y|t*        k(  r?t        | j                  ||f<   | j                  j	                  t
        j.                         yy# t        $ r | j                  |      }Y Gw xY w)z0Advance the politeness level of the given objectinferLiveRegionsN)r   r   
getSettingrE   r   r
   LIVE_REGIONS_OFFr   get_locus_of_focus_getObjectIdrW   r   rR   KeyError_liveStringToTyper   r   r   LIVE_REGIONS_LEVEL_POLITEr   LIVE_REGIONS_LEVEL_ASSERTIVEr   LIVE_REGIONS_LEVEL_RUDELIVE_REGIONS_LEVEL_OFF)r   r[   
inputEventr&   r   r   cur_prioritys          r   rL   z#LiveRegionManager.advancePolitenessj  s     **,778JKLL''(A(AB&&(;;=$$S)ll$$..0	7
  44c8_EL 8#|y'@9DD%%sHo6LL''(J(JK[(9GD%%sHo6LL''(M(MN^+9BD%%sHo6LL''(H(HIY&9AD%%sHo6LL''(G(GH '  	711#6L	7s   &G! !G?>G?c                    | j                   rz| j                  j                  j                  | j                   d       | j                  j	                  | j                  j                  j                  | j                   d             yy)z^Move the caret to the last announced live region and speak the
        contents of that objectr   N)rT   rE   	utilitiessetCaretPositionspeakContentsgetObjectContentsAtOffsetr   s    r   goLastLiveRegionz"LiveRegionManager.goLastLiveRegion  sf     LL""33D4D4DaHLL&&t||'='='W'W'+'7'7(< = r   c                    t        |j                  dd       }t        j                         j	                  d      s*| j
                  j                  t        j                         y|t        | j                        kD  r*| j
                  j                  t        j                         y| j
                  j                  | j                  |           y)z%Speak the given number cached messager   Nr   )intevent_stringr   r   r   rE   r   r
   r   r<   rQ   LIVE_REGIONS_NO_MESSAGE)r   r[   r   msgnums       r   rO   z(LiveRegionManager.reviewLiveAnnouncement  s     Z,,QR01**,778JKLL''(A(ABC''LL''(H(HILL''w(?@r   c                    t        j                         j                  d      s*| j                  j	                  t
        j                         y| j                  j                  j                         }| j                  j                  j                         }| j                  r| j                  j	                  t
        j                         | j                  j                          t        j                  | j                         | _        | j                   j%                         D ]  }t&        | j                   |<    | j)                  |      }|D ](  }| j+                  |      }t&        | j                   ||f<   * d| _        y| j"                  j-                         D ]  \  }	}
|
| j                   |	<    | j                  j	                  t
        j.                         d| _        y)z]User toggle to set all live regions to LIVE_OFF or back to their
        original politeness.r   NFT)r   r   r   rE   r   r
   r   r   documentFramerW   r   rU   LIVE_REGIONS_ALL_OFFrF   r,   copyrR   rS   keysr   getAllLiveRegionsr   r   LIVE_REGIONS_ALL_RESTORED)r   r[   r   docframer   overridematchesmatchr   r   r   s              r   rM   z&LiveRegionManager.setLivePolitenessOff  s     **,778JKLL''(A(AB <<))779ll$$..0 ??LL''(E(EFNN  " &*YYt/H/H%ID" !55::< ?6>))(3? ,,X6G  F,,U3=E))3/:F
 $DO #44::< 7
U16))#.7LL''(J(JK"DOr   c                    g }g d}|D ]  }|j                  d|z           t        j                  |      }t        j                  ||      }dt	        |       d}t        j                  t
        j                  |d       |S )N)offpolite	assertivezcontainer-live:)
attributeszLIVE REGIONS: z regions foundT)r   r   create_match_ruleget_all_matchesr<   r   r]   r^   )r   documentattrslevelslevelruleresultrc   s           r   r   z#LiveRegionManager.getAllLiveRegions  s    / 	4ELL*U23	4 --?--h=s6{m>:5++S$7r   c                 d   | j                  |      }| j                  j                  j                         }g }t	        j
                  |t        j                  j                        }|rk|j                  d      }t        j                  |      }|j                         t	        j                  |      j                         k7  r|j                  |       	 | j                  ||f   }	| j!                  |	      }
|s|
dk7  r"|j                  t$        j&                  |
z         |S # t"        $ r d}
Y 8w xY w)znUsed in conjunction with whereAmI to output description and
        politeness of the given live region objectr   none)r   rE   rW   r   r   get_relationr   RelationTypeDESCRIBED_BY
get_targetr   get_all_textstripget_descriptionr   rR   _liveTypeToStringr   r
   LIVE_REGIONS_LEVEL)r   r&   argsr   r   resultsrelation	targetobjdescriptionlivepriorityliveprioritystrs              r   generateLiveRegionDescriptionz/LiveRegionManager.generateLiveRegionDescription  s    $$S)ll$$..0 ((e.@.@.M.MN ++A.I
 !--i8K  "h&>&>s&C&I&I&KK{+	%44c8_EL"44\BO o/NN866HI  	%$O	%s   "D! !D/.D/c                 N      fd} ||      r|S t        j                  ||      S )Nc                 D    j                  |       j                  d      S )Natomic)_getAttrDictionaryr   )xr   s    r   isContainerz5LiveRegionManager._findContainer.<locals>.isContainer  s    **1-11(;;r   )r   find_ancestor)r   r&   r
  s   `  r   _findContainerz LiveRegionManager._findContainer  s*    	< sJ%%c;77r   c                    | j                  |j                        }d}d}|j                  j                  d      ru|j	                  d      dk(  r1| j
                  j                  j                  |j                        }n| j
                  j                  j                  |j                        }n|j                  j                  d      r|j	                  d      dk7  rnd|j                  vr|j                  }n| j
                  j                  j                  |j                  |j                  |j                  |j                  z         }n@| j                  |j                        }| j
                  j                  j                  |      }|sy|j                         }t        j                  |j                        xs t        j                  |j                        j                         }|r||k7  r|}|j	                  d      d	k(  r;||z   }| j
                  j!                          | j
                  j#                  |       y|g|gd
S )z4Gets the message associated with a given live event. zobject:children-changed:addzcontainer-atomictruezobject:text-changed:insertu   ￼Nchannelnotify)r   r   )r  r   type
startswithr   rE   r   
expandEOCsany_datadetail1detail2r  r   r   get_namer   presentationInterruptr   )r   r   r   r   r   	containernamer   s           r   r   zLiveRegionManager._getMessage  s   ''5
 ::  !>?yy+,6,,00;;ELLI,,00;;ENNKZZ""#?@yy+,65>>1#nnG"ll44??emmU]]U]]5RTG !//=	,,00;;IF--/
 !!%,,/Y83K3KELL3Y``bDGOF 99Y8+G#DLL..0LL''-")vh77r   c                 8    | j                   j                          y r   )rF   r,   r   s    r   flushMessageszLiveRegionManager.flushMessages5  s    r   c                     | j                   j                  |       t        | j                         t        kD  r| j                   j	                  d       yy)z6Cache a message in our cache list of length CACHE_SIZEr   N)rQ   r   r<   
CACHE_SIZEr)   )r   r   s     r   r   zLiveRegionManager._cacheMessage8  s<    d#t~~+NNq! ,r   c                     | j                  |      }| j                  j                  j                         }||f| j                  v r| j                  ||f   S | j                  |      }|t        k(  r| j                  r|| j                  ||f<   |S )zReturns the live politeness setting for a given object. Also,
        registers LIVE_NONE objects in politeness overrides when monitoring.)r   rE   rW   r   rR   r   r   rU   )r   r&   r   r   livetypes        r   r   zLiveRegionManager._getLiveType>  s     $$S)ll$$..0?d777,,c8_==--c2H 9$=E))3/:Or   c                     | j                  |      }|| j                  |      S 	 |d   S # t        $ r | j                  |      cY S w xY w)zRReturns the HTML 'id' or a path to the object is an HTML id is
        unavailableid)r  _getPathr   )r   r&   r   s      r   r   zLiveRegionManager._getObjectIdO  sU     '',===%%	&; 	&==%%	&s   + AANc                     |xs | j                  |      }	 |d   dk(  rt        S |d   dk(  rt        S |d   dk(  rt        S |d   dk(  rt        S t
        S # t        $ r	 t
        cY S w xY w)z.Returns the politeness enum for a given objectzcontainer-liver   r   r   rude)r  r   r   r   r   r   r   )r   r&   r   r   s       r   r   z#LiveRegionManager._liveStringToTypeZ  s    :d55c:	%&%/'(H4""'(K7%%'(F2     		s'   A A A A A A'&A'c                 h    |t         k(  ry|t        k(  ry|t        k(  ry|t        k(  ry|t        k(  ryy)z@Returns the politeness level as a string given a politeness enumr   r   r   r&  r   unknown)r   r   r   r   r   )r   r   s     r   r   z#LiveRegionManager._liveTypeToStringk  s<    !;&>)9$9$r   c                 ,    t        j                  |      S r   )r   get_attributes_dict)r   r&   s     r   r  z$LiveRegionManager._getAttrDictionaryz  s    ++C00r   c                 .   | j                   j                  j                         }g }	 ||k(  st        j                  |      |j                          t        |      S |j                  t        j                  |             t        j                  |      }o)z_ Returns, as a tuple of integers, the path from the given object
        to the document frame.)	rE   r   r   r   
get_parentreverser   r   get_index_in_parent)r   r&   r   paths       r   r$  zLiveRegionManager._getPath}  sz     <<))779h("5"5c":"BT{"KK44S9:%%c*C r   c                    t        j                         j                  d      sNt        j                         j                  dd       | j                  j                  t        j                         y t        j                         j                  dd       | j                          | j                  j                  t        j                         y )Nr   TF)
r   r   r   
setSettingrE   r   r
   LIVE_REGIONS_MONITORING_ONr  LIVE_REGIONS_MONITORING_OFF)r   r[   r   s      r   rN   z"LiveRegionManager.toggleMonitoring  s    **,778JK'')445GNLL''(K(KL'')445GO LL''(L(LMr   )FT)F)r  r   )!r>   r?   r@   r   rd   rH   rf   r_   r   r   r   rY   rV   r   r   r   rL   r   rO   rM   r   r  r  r   r  r   r   r   r   r   r  r$  rN   r9   r   r   rC   rC   Q   s    +CZ
8@2:hN"U2K
F2''RID=A+#Z D8-8^""	&"1
+Nr   rC   )girequire_versiongi.repositoryr   r!   r   r#   r   r  r   r   r   r	   r
   r   r   ax_collectionr   	ax_objectr   ax_textr   r   r   r   r   r   r/   r  r   rC   r9   r   r   <module>r:     s    	   7E "             '   		   
+ +\N Nr   