
    f{                        d dl mZmZmZ d dlZd dlZd dlmZ d dlm	Z	 d dl
mZmZmZ d dlmZ d dlmZ  ej$                  e      Z e	       Z	  G d d	e      Z G d
 de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z  G d de      Z! G d de      Z"y)     )divisionprint_functionunicode_literalsN)
cmp_to_key)Config)XIDeviceManagerXIEventTypeXIEventMask)show_new_device_dialog)Timerc                   ~    e 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d Zd Zd Zd Zd Zd Zd Zd Zy)Chunkerz
    Abstract base class for all chunker objects.

    Organizes keys into groups and provides methods
    to travers and highlight them.

    Hierarchy:
      Chunker --> FlatChunker --> GroupChunker
                              --> GridChunker
    c                 ~    t         j                  d       	 d | _        	 d| _        	 d| _        	 g | _        	 d| _        y )NzChunker.__init__()r   )loggerdebug_chunks_index_length_pathcyclesselfs    1/usr/lib/python3/dist-packages/Onboard/Scanner.py__init__zChunker.__init__5   sA    )*).:/
C    c                 .    t         j                  d       y )NzChunker.__del__()r   r   r   s    r   __del__zChunker.__del__G       ()r   c                     t               )zB
        Abstract: Split the keys on a layer into chunks.
        NotImplementedErrorr   layoutlayers      r   chunkzChunker.chunkJ        "##r   c                 n    | j                   }| j                  D ]  }|d   }||   } || j                     S )z<
        Get the list or key the chunker points to.
        r   )r   r   r   )r   levelpindexs       r   get_current_objectzChunker.get_current_objectP   sC      	!AaDE%LE	! T[[!!r   c                     t        |t              r|D ]  }| j                  |||        y||j                  k7  r||_        |j	                  |       yy)zG
        Recursively sets the highlight on all keys below obj.
        N)
isinstancelist_highlight_recscannedappend)r   objhlkeysos        r   r0   zChunker._highlight_rec\   sU     c4  1##Ar401 S[[  C  !r   Nc                 T    g }|s| j                         }| j                  |||       |S )z7
        Highlight or clear the current chunk.
        )r,   r0   )r   r4   rootr5   s       r   	highlightzChunker.highlighth   s1     **,DD"d+r   c                 :    | j                  || j                        S )z0
        Highlight or clear all chunks.
        )r9   r   )r   r4   s     r   highlight_allzChunker.highlight_allu   s     ~~b$,,//r   c                     | j                   dz   | j                  z  }|| j                   k  r| xj                  dz  c_        || _         y)z>
        Move to the next chunk on the current level.
           Nr   r   r   )r   nexts     r   r?   zChunker.next{   ;     a4<</$++KK1Kr   c                     | j                   dz
  | j                  z  }|| j                   kD  r| xj                  dz  c_        || _         y)zB
        Move to the previous chunk on the current level.
        r=   Nr>   )r   prevs     r   previouszChunker.previous   r@   r   c                 2    t        | j                        dk7  S )zK
        Whether the chunker can move a level up in the hierarchy.
        r   )lenr   r   s    r   
can_ascendzChunker.can_ascend   s     4::!##r   c                     | j                         r/| j                  j                         \  | _        | _        d| _        yy)z5
        Move one level up in the hierarchy.
        r   TF)rF   r   popr   r   r   r   s    r   ascendzChunker.ascend   s4     ??(,

(8%DKDKr   c                 >    t        | j                         t              S )zM
        Whether the chunker can move a level down in the hierarchy.
        )r.   r,   r/   r   s    r   can_descendzChunker.can_descend   s     $113T::r   c                    | j                         }t        |t              re| j                  j	                  | j
                  | j                  f       d| _        t        |      | _        d| _        | j                  dk(  r|d   }tyy)zj
        Move one level down in the hierarchy.
        - Skips levels that have only one element.
        r   r=   TF)	r,   r.   r/   r   r2   r   r   rE   r   r   r3   s     r   descendzChunker.descend   sr    
 %%'d#JJt{{DLL9:DKs8DLDK||q !fr   c                     t               )z:
        Abstract: Move to key above the current.
        r!   r   s    r   upz
Chunker.up   r'   r   c                     t               )z:
        Abstract: Move to key below the current.
        r!   r   s    r   downzChunker.down   r'   r   c                 H    | j                         }t        |t              s|S y)zT
        Get the current key.
        Returns None if the object is a list.
        N)r,   r.   r/   rM   s     r   get_keyzChunker.get_key   s$    
 %%'#t$Jr   c                 b    d| _         d| _        t        | j                        | _        g | _        y)z7
        Set the chunker to its initial state.
        r   N)r   r   rE   r   r   r   r   s    r   resetzChunker.reset   s)     4<<(
r   c                 j    | j                    xr% | j                   xr t        | j                         S )z6
        Is the chunker in its initial state.
        )r   r   rE   r   r   s    r   is_resetzChunker.is_reset   s3     ;; #;;#tzz?"	#r   N)__name__
__module____qualname____doc__r   r   r&   r,   r0   r9   r;   r?   rC   rF   rI   rK   rN   rP   rR   rT   rV   rX    r   r   r   r   )   sa    	$*$
"
!0		$	;($$
#r   r   c                       e Zd ZdZd Zd Zy)FlatChunkerz/
    Chunks a layer based on key location.
    c                     |j                         j                         }|j                         j                         }|j                  |j                  z
  }|dk7  r|S |j                  |j                  z
  S )z4
        Sort keys by y and then x position
        r   )get_border_rectintyx)r   abrect_arect_brd   s         r   compare_keyszFlatChunker.compare_keys   sc     ""$((*""$((*HHvxx6Hxx&((""r   c                    |j                  |      D cg c]  }|j                         r| c}| _        | j                  j                  |j                  d      D cg c]  }|j                         r| c}       | j                  j	                  t        | j                               t        | j                        | _        yc c}w c c}w )z>
        Create a list of scannable keys and sort it.
        N)key)	iter_layer_keysis_path_scannabler   extendsortr   rj   rE   r   )r   r$   r%   ks       r   r&   zFlatChunker.chunk   s     $*#9#9%#@ 2a..0  2(>(>t(D 71 ! 3 3 5  7 	8j):):;<4<<(27s   CCN)rZ   r[   r\   r]   rj   r&   r^   r   r   r`   r`      s    #	)r   r`   c                   ,     e Zd ZdZ fdZ fdZ xZS )GroupChunkerz<
    Chunks a layer based on priority and key location.
    c                 |    |j                         |j                         z
  }|dk7  r|S t        t        |   ||      S )z5
        Sort keys by priority and location.
        r   )get_path_scan_prioritysuperrs   rj   )r   rf   rg   r*   	__class__s       r   rj   zGroupChunker.compare_keys  sA     $$&)A)A)CC6H\45a;;r   c                    d}d}g }t         t        |   ||       | j                  D ]  }|j	                         }||k7  r|}d}g }|j                  |       |j                         j                         }	|	j                  |k7  r|	j                  }g }
j                  |
       
j                  |        t        |      dk(  r|d   }|| _        t        | j                        | _
        y)/
        Create a nested list of keys.
        Nr=   r   )rv   rs   r&   r   ru   r2   rb   rc   rd   rE   r   )r   r$   r%   last_prioritylast_ychunksrl   scan_prioritygrouprectrowrw   s              r   r&   zGroupChunker.chunk  s      	lD'6
 << 	C668M- -e$&&(,,.DvvS!JJsO	" v;!AYF4<<(r   )rZ   r[   r\   r]   rj   r&   __classcell__rw   s   @r   rs   rs     s    <$) $)r   rs   c                   4     e Zd ZdZ fdZd Zd Zd Z xZS )GridChunkerz+
    Chunks a layer into rows of keys.
    c                 p   t         j                  }g }t        t        |   ||       | j
                  D ]_  }|j                         j                         }|j                  |k  rg }|j                  |       |j                  }j                  |       a || _        t        | j
                        | _        y)ry   N)sysmaxsizerv   r   r&   r   rb   rc   re   r2   rE   r   )	r   r$   r%   last_xr|   rl   r   r   rw   s	           r   r&   zGridChunker.chunk<  s      	k4&vu5<< 	C&&(,,.Dvvc"VVFJJsO	 4<<(r   c                    |y |j                         j                         }t        j                  j                  }| j                           |        t        | j                               D ]A  \  }}|j                         j                         }t        |d   |d   z
        }||k  s>|}|}	C | j                          	| _
        y )Nr   )rb   
get_centerr   
float_infomaxrI   	enumerater,   absrN   r   )
r   rl   	directionkcmin_xidxr3   ocdx	neighbours
             r   _select_neighbourzGridChunker._select_neighbourQ  s    ;  "--/""!$"9"9";< 	 HC$$&113BRURU]#BEz		  	r   c                 X    | j                  | j                         | j                         y rY   )r   rT   rC   r   s    r   rP   zGridChunker.upe  s    t||~t}}=r   c                 X    | j                  | j                         | j                         y rY   )r   rT   r?   r   s    r   rR   zGridChunker.downh  s    t||~tyy9r   )	rZ   r[   r\   r]   r&   r   rP   rR   r   r   s   @r   r   r   8  s    )* (>:r   r   c                        e 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 f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 xZS )ScanModea  
    Abstract base class for all scanning modes.

    Specifies how the scanner moves between chunks of keys
    and when to activate them. Scan mode subclasses define
    a set of actions they support and the base class translates
    input device events into scan actions.

    Hierarchy:
        ScanMode --> AutoScan --> UserScan
                              --> OverScan
                 --> StepScan
                 --> DirectScan
    r   r=                        g?c                     t         t        |           t        j	                  d       	 t               | _        	 d| _        	 || _        	 || _	        	 d | _
        y )NzScanMode.__init__()r   )rv   r   r   r   r   r   _activation_timer_flash_redraw_callback_activate_callbackchunkerr   redraw_callbackactivate_callbackrw   s      r   r   zScanMode.__init__  sT    h&(*+)!&/( /+"3"r   c                 .    t         j                  d       y )NzScanMode.__del__()r   r   s    r   r   zScanMode.__del__  s    )*r   c                     t               )zC
        Abstract: Convert input events into scan actions.
        r!   )r   detailpresseds      r   map_actionszScanMode.map_actions  r'   r   c                     t               )z0
        Abstract: Handle scan actions.
        r!   r   actions     r   	do_actionzScanMode.do_action  r'   r   c                     t               )z0
        Abstract: Move between chunks.
        r!   r   s    r   scanzScanMode.scan  r'   r   c                     t               )z6
        Abstract: Create a chunker instance.
        r!   r   s    r   create_chunkerzScanMode.create_chunker  r'   r   c                      y)zL
        Virtual: Called if a new layer was set or a key activated.
        Nr^   r   s    r   init_positionzScanMode.init_position  s     	r   c                    | j                   j                         ry|j                  }|t        j                  k(  r8t
        j                  j                  }| j                  ||j                  d      }n|t        j                  k(  r8t
        j                  j                  }| j                  ||j                  d      }n|t        j                  k(  r8t
        j                  j                  }| j                  ||j                  d      }nW|t        j                  k(  r8t
        j                  j                  }| j                  ||j                  d      }n| j                  }|| j                  k7  r| j!                  |       yy)z<
        Translate device events into scan actions.
        NTF)r   
is_runningxi_typer	   ButtonPressconfigscannerdevice_button_mapr   buttonButtonReleaseKeyPressdevice_key_mapkeyval
KeyReleaseACTION_UNHANDLEDr   )r   event
event_type
button_mapr   key_maps         r   handle_eventzScanMode.handle_event  s"   
 !!,,.]]
00099J%%j%,,EF;44499J%%j%,,FF;///nn33G%%gu||TBF;111nn33G%%gu||UCF **FT***NN6" +r   c                 "    | j                         S )z-
        Override: Timer() callback.
        )r   r   s    r   on_timerzScanMode.on_timer  s     yy{r   c                 d    | j                   j                  t        j                  j                  k\  S )zH
        Check if the maximum number of scan cycles is reached.
        )r   r   r   r   r   s    r   max_cycles_reachedzScanMode.max_cycles_reached  s#     ||""fnn&;&;;;r   c                     | j                          | j                         | _        | j                  j                  ||       | j	                          y)z7
        Set the layer that should be scanned.
        N)rV   r   r   r&   r   r#   s      r   	set_layerzScanMode.set_layer  s=     	

**,65)r   c                     | j                   dkD  r:|j                   |_        | xj                   dz  c_         | j                  |g       y| j                  |       | j	                          y)zK
        Timer callback: Flashes the key and finally activates it.
        r   r=   TF)r   r1   redrawr   r   r   rl   s     r   _on_activation_timerzScanMode._on_activation_timer  sX     ;;?!kk/CKKK1KKK##C( r   c                 :   | j                   j                         }|syt        j                  j                  rC| j
                  | _        | j                  j                  | j                  | j                  |       y| j                  |       | j                          y)z8
        Activates a key and triggers feedback.
        N)r   rT   r   r   feedback_flashACTIVATION_FLASH_COUNTr   r   startACTIVATION_FLASH_INTERVALr   r   r   r   s     r   activatezScanMode.activate  sz     ll""$>>((55DK""(()G)G)-)B)B),. ##C( r   c                     | j                         r| j                          | j                  r+| j                  | j                  j	                  d             yy)z9
        Stop scanning and clear all highlights.
        FN)r   stopr   r   r;   r   s    r   rV   zScanMode.reset  s>     ??IIK<<KK2259: r   c                 &    | j                  |       y)z@
        Update individual keys or the entire keyboard.
        N)r   )r   r5   s     r   r   zScanMode.redraw  s     	d#r   c                 2    | j                          d| _        y)z1
        Clean up the ScanMode instance.
        N)rV   r   r   s    r   finalizezScanMode.finalize%  s     	

!%r   rY   ) rZ   r[   r\   r]   ACTION_STEPACTION_LEFTACTION_RIGHT	ACTION_UPACTION_DOWNACTION_ACTIVATEACTION_STEP_STARTACTION_STEP_STOPr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rV   r   r   r   r   s   @r   r   r   l  s     KKLIKO8 #,(+$$$$#><!";$&r   r   c                   (    e Zd ZdZd Zd Zd Zd Zy)AutoScanzx
    Automatic scan mode for 1 switch. Starts scanning on
    switch press and moves through a hierarchy of chunks.
    c                     t               S rY   rs   r   s    r   r   zAutoScan.create_chunker2  
    ~r   c                 >    |r||v r| j                   S | j                  S rY   )r   r   r   dev_mapr   is_presss       r   r   zAutoScan.map_actions5  s$    ')###$$$r   c                 6   | j                  | j                  j                  d             | j                  j                          | j	                         r| j                  j                          y| j                  | j                  j                  d             yNFT)r   r   r9   r?   r   rV   r   s    r   r   zAutoScan.scan;  sj    DLL**512""$LL KK..t45r   c                 p   | j                         sT| j                  | j                  j                  d             | j	                  t
        j                  j                         y | j                          | j                  | j                  j                  d             | j                  j                         rT| j                  | j                  j                  d             | j	                  t
        j                  j                         y | j                          | j                  j                          y )NTF)r   r   r   r9   r   r   r   intervalr   rN   r   rV   r   s     r   r   zAutoScan.do_actionF  s     KK..t45JJv~~../ IIKKK..u56||##%DLL22489

6>>223 ""$r   N)rZ   r[   r\   r]   r   r   r   r   r^   r   r   r   r   -  s    %	%r   r   c                       e Zd ZdZd Zd Zy)UserScanzr
    Automatic scan mode for 1 switch. Like AutoScan but
    the scanner progresses only during switch press.
    c                 V    ||v r|r| j                   S | j                  S | j                  S rY   )r   r   r   r   s       r   r   zUserScan.map_actions_  s1    W---,,,$$$r   c                    || j                   k(  r| j                  j                         sD| j                  | j                  j	                  d             | j                  j                          | j                  | j                  j	                  d             | j                  t        j                  j                         y || j                  k(  r| j                          | j                  j                         sU| j                  | j                  j	                  d             | j                          | j                  j                          y y y r   )r   r   rX   r   r9   rN   r   r   r   r   r   r   rK   r   rV   r   s     r   r   zUserScan.do_actionh  s    T+++<<((*DLL2259:$$&KK..t45JJv~~../t,,,IIK<<++-DLL2259:""$	 . -r   N)rZ   r[   r\   r]   r   r   r^   r   r   r   r   Z  s    %%r   r   c                   4     e Zd ZdZ fdZd Zd Zd Z xZS )OverScanzv
    Automatic scan mode for 1 switch. Does fast forward
    scanning in a flat hierarchy with slow backtracking.
    c                 J    t         t        |   ||       d| _        d| _        y )NT)rv   r   r   _step_fastr   s      r   r   zOverScan.__init__  s#    h&8IJ

r   c                     t               S rY   )r`   r   s    r   r   zOverScan.create_chunker  
    }r   c                 b   | j                  | j                  j                  d             | j                  dkD  rZ| j                  j	                          | xj                  dz  c_        | j                  | j                  j                  d             y| j                  j                          | j                         r| j                  j                          y| j                  | j                  j                  d             | j                  s!| j                          | j                  d        y)NFr   r=   T)r   r   r9   r   rC   r?   r   rV   r   r   r   r   s    r   r   zOverScan.scan  s    DLL**512::>LL!!#JJ!OJKK..t45   LL&&(""$KK..t45::		t$r   c                    | j                         sbd| _        d| _        | j                  | j                  j                  d             | j                  t        j                  j                         y | j                  dk\  re| j                          | j                  | j                  j                  d             | j                          | j                  j                          y t        j                  j                  | _        d| _        d| j                  _        | j                  t        j                  j                         y )NTr   r   F)r   r   r   r   r   r9   r   r   r   interval_fastr   r   rV   	backtrackr   r   r   s     r   r   zOverScan.do_action  s     DJDJKK..t45JJv~~334 zzQ		DLL2259:""$ $^^55
"
&'#

6>>223r   )	rZ   r[   r\   r]   r   r   r   r   r   r   s   @r   r   r   |  s    04r   r   c                   @     e Zd ZdZ fdZd Zd Zd Zd Zd Z	 xZ
S )StepScanz,
    Directed scan mode for 2 switches.
    c                 <    t         t        |   ||       d| _        y )NF)rv   r  r   swappedr   s      r   r   zStepScan.__init__  s    h&8IJr   c                     t               S rY   r   r   s    r   r   zStepScan.create_chunker  r   r   c                     | j                   j                          | j                  | j                   j                  d             y NT)r   rV   r   r9   r   s    r   r   zStepScan.init_position  s-    DLL**401r   c                 0    |r	||v r||   S | j                   S rY   r   r   s       r   r   zStepScan.map_actions  "    ')6?"$$$r   c                     t         j                  j                  r3| j                  r'|| j                  k(  r| j
                  S | j                  S |S rY   )r   r   	alternater
  r   r   r   s     r   get_alternatezStepScan.get_alternate  s@    >>##)))+++'''r   c                    || j                  | j                        k(  r| j                  | j                  j	                  d             | j                  j                          | j                         r| j                          y | j                  | j                  j	                  d             y | j                  | j                  j	                  d             | j                   | _        | j                  j                         r+| j                  | j                  j	                  d             y | j                          y r   )r  r   r   r   r9   r?   r   r   r
  rN   r   r   s     r   r   zStepScan.do_action  s    T''(8(899KK..u56LL&&(""$DLL22489KK..u56#||+DL||##%DLL22489r   )rZ   r[   r\   r]   r   r   r   r   r  r   r   r   s   @r   r  r    s&    
2% r   r  c                   (    e Zd ZdZd Zd Zd Zd Zy)
DirectScanz1
    Directed scan mode for 3 or 5 switches.
    c                     t               S rY   )r   r   s    r   r   zDirectScan.create_chunker  r  r   c                     | j                   j                          | j                  | j                   j                  d             y r  )r   rN   r   r9   r   s    r   r   zDirectScan.init_position  s-    DLL**401r   c                 0    |r	||v r||   S | j                   S rY   r  r   s       r   r   zDirectScan.map_actions  r  r   c                     | j                   j                  d      }|| j                  k(  r| j                   j                          n|| j                  k(  r| j                   j                          nd|| j                  k(  r| j                   j                          n:|| j                  k(  r| j                   j                          n| j                          |j                  | j                   j                  d             | j                  |       y r   )r   r9   r   rC   r   r?   r   rP   r   rR   r   ro   r   )r   r   r5   s      r   r   zDirectScan.do_action  s    ||%%e,T%%%LL!!#t(((LLt~~%LLOOt'''LLMMODLL**401Dr   N)rZ   r[   r\   r]   r   r   r   r   r^   r   r   r  r    s    2%r   r  c                   R    e 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y)Scannerz
    Main controller class for keyboard scanning. Manages
    ScanMode and ScanDevices objects and provides the
    public interface for the scanner.
    r   r=   r   r   r   c                    t         j                  d       	 | j                  t        j                  j
                  ||      | _        	 t        | j
                  j                        | _        	 d | _	        	 d | _
        t        j                  j                  | j                         t        j                  j                  | j                         y )NzScanner.__init__())r   r   _get_scan_moder   r   mode
ScanDevicer   devicer$   r%   mode_notify_add_mode_notifyuser_scan_notify_add_user_scan_notify)r   r   r   s      r   r   zScanner.__init__  s    )*$''(;(;(7(9;	 	' !7!78!.
&&t'8'89++D,B,BCr   c                 .    t         j                  d       y )NzScanner.__del__()r   r   s    r   r   zScanner.__del__.  r   r   c                 j   | j                   j                  }| j                   j                  }| j                   j                          | j	                  |||      | _         | j                   j                  | j                  | j                         | j                   j                  | j                  _
        y)zB
        Callback for scanner.mode configuration changes.
        N)r  r   r   r   r  r   r$   r%   r   r!  _event_handler)r   r  rcbacbs       r   r#  zScanner._mode_notify1  sz     ii((ii**		''c37			DKK4%)YY%;%;"r   c                     t         j                  j                  | j                  k(  r*| j	                  t         j                  j                         yy)zG
        Callback for scanner.user_scan configuration changes.
        N)r   r   r  MODE_AUTOSCANr#  )r   	user_scans     r   r%  zScanner._user_scan_notify>  s9     >>$"4"44fnn112 5r   c                     t         t        t        t        g}|| j                  k(  r&t
        j                  j                  rt        ||      S  ||   ||      S )zD
        Get the ScanMode instance for the current profile.
        )	r   r   r  r  r,  r   r   r-  r   )r   r  r   r   profiless        r   r  zScanner._get_scan_modeE  sN     x:?4%%%&..*B*BO->??x~o/@AAr   c                     d}| j                   |k7  r	|| _         d}| j                  |k7  r	|| _        d}|s|r1| j                  j                  | j                   | j                         yy)zC
        Notify the scanner about layer or layout changes.
        FTN)r$   r%   r  r   )r   r$   r%   force_updatechangeds        r   update_layerzScanner.update_layerP  s_     ;;&  DKG::DJGlIITZZ8 #r   c                    t         j                  j                  | j                         t         j                  j	                  | j
                         | j                  j                          | j                  j                          y)z;
        Clean up all objects related to scanning.
        N)	r   r   mode_notify_remover#  user_scan_notify_remover%  r!  r   r  r   s    r   r   zScanner.finalizea  sT     	))$*;*;<..t/E/EF		r   N)F)rZ   r[   r\   r]   r,  MODE_OVERSCANMODE_STEPSCANMODE_DIRECTED3MODE_DIRECTED5r   r   r#  r%  r  r3  r   r^   r   r   r  r    sJ     MMMNND(*<3	B9"r   r  c                   |    e Zd ZdZ	 dZ	 dZdZ	 g dZd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zed        Zy)r   z
    Input device manager class.

    Manages input devices on the system and deals with
    PnP related event. The actual press/release events
    are forwarded to a ScanMode instance.
    Defaultr   r   )zVirtual core pointerzVirtual core keyboardzVirtual core XTEST pointerzVirtual core XTEST keyboardzPower Buttonc                    t         j                  d       	 d | _        	 d| _        	 || _        	 t               | _        | j                  j                  d| j                         t        j                  j                  | j                         t        j                  j                  | j                         | j                  t        j                  j                         y )NzScanDevice.__init__()Fdevice-event)r   r   _active_device_ids	_floatingr(  r   _device_managerconnect_device_event_handlerr   r   device_name_notify_add_device_name_notifydevice_detach_notify_add_device_detach_notifydevice_name)r   event_handlers     r   r   zScanDevice.__init__  s    ,-<"&5/+2.0$$^T5O5OP--d.F.FG//0J0JK  !;!;<r   c                 .    t         j                  d       y )NzScanDevice.__del__()r   r   s    r   r   zScanDevice.__del__  s    +,r   c                    |j                   }|j                  }|t        j                  k(  rZ| j                  j                  |      }t        |j                  |j                         |j                         | j                         y|t        j                  k(  rc| j                  rV| j                  d   |k(  rCd| _        d| _        dt        j                  _        | j"                  t        j                  _        yyy|| j&                  k7  rh|| j(                  k(  r't        j                  j$                  | j"                  k(  s| j                  r%|| j                  d   k(  r| j+                  |       yyyy)z)
        Handler for XI2 events.
        r   NF)r   	device_idr	   DeviceAddedrA  lookup_device_idr   nameget_config_string
is_pointer_on_new_device_acceptedDeviceRemovedr?  r@  r   r   device_detachDEFAULT_NAMErH  DEFAULT_VCK_IDDEFAULT_VCP_IDr(  )r   r   r   rL  r!  s        r   rC  z ScanDevice._device_event_handler  s@    ]]
__	000))::9EF"6;;#)#;#;#=#)#4#4#6#'#?#?A
 ;444 &&&&q)Y6*.'!&/4,-1->->*	 7 ' D/// !4!44NN..$2C2CC++!8!8!;;''. < , 0r   c                 X    |t         j                  _        dt         j                  _        y)zg
        Callback for the 'New device' dialog.
        Called only if 'Use device' was chosen.
        TN)r   r   rH  rT  )r   config_strings     r   rR  z"ScanDevice._on_new_device_accepted  s    
 &3"'+$r   c                     | j                   y|r,| j                  s| j                  | j                   d          yy| j                  r | j                  | j                     yy)zO
        Callback for the scanner.device_detach configuration changes.
        Nr   )r?  r@  detachattach)r   r[  s     r   rG  z ScanDevice._device_detach_notify  s[     ""*>>D33A67 " ~~T445 r   c                    | j                          || j                  k(  ry| j                  j                         D ]:  }| j	                  |      s||j                         k(  s)| j                  |        n | j                  Jt        j                  d       dt        j                  _        | j                  t        j                  _        yy)zM
        Callback for the scanner.device_name configuration changes.
        Nz%Unknown device-name in configuration.F)closerU  rA  get_devices
is_useablerP  openr?  r   r   r   r   rT  rH  )r   rO  r!  s      r   rE  zScanDevice._device_name_notify  s     	

4$$$**668 	Fv&v//11		&!		 ""*LL@A+0FNN()-):):FNN& +r   c                 :   |j                         r"t        j                  t        j                  z  }n!t        j                  t        j
                  z  }	 | j                  j                  d||       |j                  |j                  f| _
        t        j                   j"                  r-|j%                         s| j'                  |j                         yyy# t        $ r:}t        j                  dj                  |j                  |             Y d}~d}~ww xY w)zE
        Select for events and optionally detach the device.
        Nz Failed to open device {id}: {ex}idex)rQ  r
   ButtonPressMaskButtonReleaseMaskKeyPressMaskKeyReleaseMaskrA  select_eventsrd  
attachmentr?  	Exceptionr   warningformatr   r   rT  	is_masterr[  )r   r!  
event_maskre  s       r   ra  zScanDevice.open  s     $44$667J %11$334J	=  ..tVZH'-yy&2C2C&DD#
 >>''0@0@0BKK		" 1C'	  	=NN="F		F;= =	=s   :C 	D 0DDc                    | j                   r | j                  | j                    | j                  rM| j                  j	                  | j                  d         }	 | j                  j                  d|       d| _        yy# t        $ r=}t        j                  dj                  | j                  d   |             Y d}~yd}~ww xY w)z0
        Stop using the current device.
        r   Nz!Failed to close device {id}: {ex}rc  )
r@  r\  r?  rA  rN  unselect_eventsrl  r   rm  rn  )r   r!  re  s      r   r^  zScanDevice.close  s     >>DKK001""))::,0,C,CA,FHF1$$44T6B*.' #  1B &D,C,CA,F,. !' !01 11s   #B   	C	3CCc                     	 | j                   j                  ||       d| _        y#  t        j	                  dj                  ||             Y yxY w)z0
        Attach the device to a master.
        Fz(Failed to attach device {id} to {master})rd  masterN)rA  attach_device_idr@  r   rm  rn  )r   dev_idrt  s      r   r\  zScanDevice.attach  sK    	B  11&&A"DN	BNNE"FF@Bs	   #& (Ac                     	 | j                   j                  |       d| _        y#  t        j	                  dj                  |             Y yxY w)z4
        Detach the device from its master.
        TzFailed to detach device {id})rd  N)rA  detach_device_idr@  r   rm  rn  )r   rv  s     r   r[  zScanDevice.detach  sF    	O  11&9!DN	ONN9@@f@MNs	   "% 'Ac                 0   | j                   j                  d| j                         t        j                  j                  | j                         t        j                  j                  | j                         | j                          d| _
        d| _        y)z3
        Clean up the ScanDevice instance.
        r>  N)rA  
disconnectrC  r   r   device_name_notify_removerE  device_detach_notify_removerG  r^  r(  devicesr   s    r   r   zScanDevice.finalize#  sl     	''(,(B(B	D001I1IJ2243M3MN

"r   c                 |    | j                   t        j                  vxr | j                  xr | j	                          S )zD
        Check whether this device is useable for scanning.
        )rO  r   	blacklistenabledis_floating)r!  s    r   r`  zScanDevice.is_useable/  s;    
 {{*"6"66 ,>>,))++	,r   N)rZ   r[   r\   r]   rU  rW  rV  r  r   r   rC  rR  rG  rE  ra  r^  r\  r[  r   staticmethodr`  r^   r   r   r   r   k  sv     7L.NN!!I=*-"/H,6;(#(1$	BO
 , ,r   r   )#
__future__r   r   r   r   logging	functoolsr   Onboard.Configr   Onboard.XInputr   r	   r
   Onboard.WindowUtilsr   Onboard.Timerr   	getLoggerrZ   r   r   objectr   r`   rs   r   r   r   r   r   r  r  r  r   r^   r   r   <module>r     s   * B A 
    & I I 6 %			8	$	z#f z#z)' ):2); 2)j1:+ 1:h~&u ~&B*%x *%Z%x %D:4x :4z- x - `   F\f \~K, K,r   