+
     iL  c                   sl   R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	H
t
Ht ^ RIt^ RIHt ^ RIHt ]P"                  ! RR4       ^ RIHt ^ R	IHt ^ R
IHtHt ^ RIHt ^ RIHt ^ RIHt ^ RIH t  ^ RI!H"t" ^ RI#H$t$ ^ RI%H&t& ^ RI'H(t( Rt)^
t* ! R R4      t+R t, ! R R]	4      t- ! R R4      t.R# )zStarts injecting keycodes based on the configuration.

https://github.com/LEW21/pydbus/tree/cc407c8b1d25b7e28a6d661a29f9e661b1c9b964/examples/clientserver  # noqa pylint: disable=line-too-long
N)PurePath)ProtocolDictOptional)	SystemBus)MappingParserGLibz2.0)r   )logger)InjectorInjectorState)Preset)GlobalConfig)keyboard_layout)groups)	PathUtils)	UserUtils)macro_variables)GlobalUInputszinputremapper.Controlc                   s`   a  ] tR t^=t o RtR tV 3R lR ltV 3R lR ltV 3R lR ltR	t	V t
R
# )AutoloadHistoryz1Contains the autoloading history and constraints.c                s    / V n         R# )z%Construct this with an empty history.N_autoload_historyself   &9/usr/lib/python3.14/site-packages/inputremapper/daemon.py__init__ZAutoloadHistory.__init__@   s     "$    c                &   < V ^8  d   QhRS[ RS[ /#    	group_keypresetstrZformat__classdict__   "r   __annotate__AutoloadHistory.__annotate__E   s     B B# Bs Br   c                sN    \         P                   ! 4       V3V P                  V&   R# )z8Remember when this preset was autoloaded for the device.N)timer   r   r   r      &&&r   rememberZAutoloadHistory.rememberE   s    -1YY[&,Ay)r   c                    < V ^8  d   QhRS[ /# r   r   r    r"   r$   r   r%   r&   I   s     2 2 2r   c                sD    WP                   9   d   V P                   V R# R# )z-The injection was stopped or started by hand.Nr   r   r      &&r   forgetZAutoloadHistory.forgetI   s!    ...&&y1 /r   c                r   r   r    r"   r$   r   r%   r&   N   s      c 3 r   c                s    WP                   9  d   R# V P                   V,          ^,          V8w  d   R# \        P                  ! 4       p^pV P                   V,          ^ ,          W4,
          8  d   R# R# )a  Check if this autoload would be redundant.

This is needed because udev triggers multiple times per hardware
device, and because it should be possible to stop the injection
by unplugging the device if the preset goes wrong or if input-remapper
has some bug that prevents the computer from being controlled.

For that unplug and reconnect the device twice within a 15 seconds
timeframe which will then not ask for autoloading again. Wait 3
seconds between replugging.
TF)r   r'   )r   r   r   nowZ	thresholds   &&&  r   may_autoloadZAutoloadHistory.may_autoloadN   s`     222!!),Q/69 iik	!!),Q/#/Ar   r   N)__name__
__module____qualname____firstlineno____doc__r   r*   r/   r1   __static_attributes____classdictcell__r#      @r   r   r   =   s-     ;$
B B2 2
 r   r   c                s   a  V 3R lpV# )zERemove timeout to ensure the call works if the daemon is not a proxy.c                  s(   < R V9   d   VR  S! V / VB # Ztimeout )ZargsZkwargsfuncs   *,r   wrappedZremove_timeout.<locals>.wrappeds   s#    y!T$V$$r   r<   )r=   r>   s   f r   remove_timeoutr?   n   s    
% Nr   c                   s   a  ] tR t^|t o RtV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR	 ltV 3R
 lR lt	V 3R lR lt
V 3R lR ltV 3R lR ltV 3R lR ltRtV tR# )DaemonProxyz%The interface provided over the dbus.c                $   < V ^8  d   QhRS[ RR/# r   r   returnNr    r"   r$   r   r%   DaemonProxy.__annotate__   s    9999r   c                    R # Nr<   r-   r.   r   stop_injectingZDaemonProxy.stop_injecting   s    cr   c                &   < V ^8  d   QhRS[ RS[/# r   r   rC   r!   r	   r"   r$   r   r%   rD      s    ==3===r   c                rE   rF   r<   r-   r.   r   	get_stateZDaemonProxy.get_state   s    #r   c                ,   < V ^8  d   QhRS[ RS[ RS[/# )r   r   r   rC   r!   boolr"   r$   r   r%   rD      s    GGGcGdGr   c                rE   rF   r<   r(   r)   r   start_injectingZDaemonProxy.start_injecting   s    Cr   c                   < V ^8  d   QhRR/# r   rC   Nr<   r"   r$   r   r%   rD          ##$#r   c                rE   rF   r<   r   r   r   stop_allZDaemonProxy.stop_all       r   c                rA   )r   
config_dirrC   Nr    r"   r$   r   r%   rD          ::::r   c                rE   rF   r<   )r   rU   r.   r   set_config_dirZDaemonProxy.set_config_dir       sr   c                rP   rQ   r<   r"   r$   r   r%   rD      rR   r   c                rE   rF   r<   r   r   r   autoloadZDaemonProxy.autoload   rT   r   c                rA   rB   r    r"   r$   r   r%   rD      rV   r   c                rE   rF   r<   r-   r.   r   autoload_singleZDaemonProxy.autoload_single   rX   r   c                r   )r   outrC   r    r"   r$   r   r%   rD      s    ))))r   c                rE   rF   r<   r   r[   r.   r   helloZDaemonProxy.hello   s    cr   c                rP   rQ   r<   r"   r$   r   r%   rD      s    dr   c                rE   rF   r<   r   r   r   quitZDaemonProxy.quit   s    Cr   r<   N)r2   r3   r4   r5   r6   rG   rK   rO   rS   rW   rY   rZ   r]   r^   r7   r8   r9   r:   r   r@   r@   |   s>     /99==GG##::##::))r   r@   c                   s2  a  ] tR t^t o RtR] R2tV 3R lR lt]RV 3R lR ll4       t	R t
R	 tR V 3R lR lltV 3R lR ltV 3R lR lt]V 3R lR l4       tV 3R lR lt]V 3R lR l4       t]R 4       tV 3R lR ltR tV 3R lR ltR tRtV tR
# )!DaemonaL  Starts injecting keycodes based on the configuration.

Can be talked to either over dbus or by instantiating it.

The Daemon may not have any knowledge about the logged in user, so it
can't read any config files. It has to be told what to do and will
continue to do so afterwards, but it can't decide to start injecting
on its own.
z-
        <node>
            <interface name='a?  '>
                <method name='stop_injecting'>
                    <arg type='s' name='group_key' direction='in'/>
                </method>
                <method name='get_state'>
                    <arg type='s' name='group_key' direction='in'/>
                    <arg type='s' name='response' direction='out'/>
                </method>
                <method name='start_injecting'>
                    <arg type='s' name='group_key' direction='in'/>
                    <arg type='s' name='preset' direction='in'/>
                    <arg type='b' name='response' direction='out'/>
                </method>
                <method name='stop_all'>
                </method>
                <method name='set_config_dir'>
                    <arg type='s' name='config_dir' direction='in'/>
                </method>
                <method name='autoload'>
                </method>
                <method name='autoload_single'>
                    <arg type='s' name='group_key' direction='in'/>
                </method>
                <method name='hello'>
                    <arg type='s' name='out' direction='in'/>
                    <arg type='s' name='response' direction='out'/>
                </method>
                <method name='quit'>
                </method>
            </interface>
        </node>
    c                s,   < V ^8  d   QhRS[ RS[RS[/# )r   global_configglobal_uinputsmapping_parser)r   r   r   r"   r$   r   r%   Daemon.__annotate__   s)     !  ! #!  &!  &	! r   c                s   \         P                  ! R4       Wn        W n        W0n        / V n        RV n        \        P                  R8w  d%   V P                  \        P                  ! 4       4       \        P                  ! 4       ^ 8w  d   \         P                  ! R4       \        4       V n        ^ V n        \$        P&                  ! V P(                  4       \*        P,                  ! 4        R# )zConstructs the daemon.zCreating daemonNrootz-The service usually needs elevated privileges)r   debugr`   ra   rb   	injectorsrU   r   userrW   r   get_config_pathosZgetuidZwarningr   autoload_historyrefreshed_devices_atatexitZregisterrS   r   start)r   r`   ra   rb   s   &&&&r   r   ZDaemon.__init__   s     	&'*,,.0>>V# 	 9 9 ;< 99;!NNJK / 1$%!& 	r   c                rH   )r   fallbackrC   )rN   r@   r"   r$   r   r%   rc      s     2 2t 2{ 2r   c                sv   \        4       p VP                  \        \        R7      p\        P
                  ! R4       \$        P&                  R8w  dS   \(        P*                  ! 4       p\        P                  ! RT4       XP-                  \(        P*                  ! 4       ^R7       X#   \        P                   Ed}   pT'       g   \        P                  ! RT4        Rp?R# \        P
                  ! R4       \        P                  ! 4       '       d   RMRpRT 2p\        P                  ! R	T4       \        P                  ! T4       \        P                  ! R
4       \        ^4       F  p TP                  \        \        R7      p  Rp?EKS    \        P                   d@   p\        P                  ! RT^,           4       \        P                  ! RT4        Rp?MRp?ii ; i\        P                  ! R
4       K  	  \        P                  ! R4       \         P"                  ! ^4        Rp?ELRp?ii ; i)zGet an interface to start and stop injecting keystrokes.

Parameters
----------
fallback
    If true, starts the daemon via pkexec if it cannot connect.
r;   zConnected to the servicezService not running? %sNzStarting the servicez -dZ z5pkexec input-remapper-control --command start-daemon zRunning `%s`g?z'Attempt %d to reach the service failed:z"%s"z Failed to connect to the servicerd   zTelling service about "%s")r   getBUS_NAMEBUS_TIMEOUTr   infor   ZGErrorerrorZis_debugre   ri   Zsystemr'   sleepZrangesysexitr   rg   r   rh   rW   )	Zclsrn   busZ	interfacers   re   ZcmdZattemptconfig_paths	   &&       r   connectZDaemon.connect   s    k"	+>IKK23D >>V##335KLL5{C$$Y%>%>%@!$LM {{ 	6>KK./ $__..EBEI%QC LL-IIcNJJsO !80 #+ FI{{ 0LL!JGVWKXLL//0 

3 $ ?@?	sO   1B& &H8<H3!0H3AH3-FH3G$%5GH3G$$A	H33H8c                s    \        4       p VP                  \        V 4       R#   \         dB   p\        P
                  ! R\        T4      4       \        P                  ! ^	4        Rp?R# Rp?ii ; i)z"Make the dbus interface available.z$Is the service already running? (%s)N)	r   publishrp   ZRuntimeErrorr   rs   r!   ru   rv   )r   rw   rs   s   &  r   rz   ZDaemon.publish  sL    k	KK$' 	LL?ULHHQKK	s   $ A06A++A0c                s|    \         P                  ! 4       p\        P                  ! R4       VP	                  4        R# )z6Start the daemons loop. Blocks until the daemon stops.zRunning daemonN)r   ZMainLoopr   re   run)r   Zloop   & r   r{   Z
Daemon.run"  s#    }}%&
r   Nc                s0   < V ^8  d   QhRS[ S[,          /# r,   )r   r!   r"   r$   r   r%   rc   (  s     , ,# ,r   c                s   \         P                   ! 4       pV^
,
          V P                  8  dJ   \        P                  ! R4       \         P                  ! R4       \
        P                  ! 4        W n        R# \
        P                  ! VR7      '       gK   \        P                  ! RV4       \         P                  ! R4       \
        P                  ! 4        W n        R# R# )zRefresh groups if the specified group is unknown.

Parameters
----------
group_key
    unique identifier used by the groups object
z'Refreshing because last info is too oldg?Nkeyz"Refreshing because "%s" is unknown)r'   rk   r   re   rt   r   refreshfind)r   r   r0      && r   r   ZDaemon.refresh(  s     iik8d///LLBCJJsONN(+%{{y))LL=yIJJsONN(+%	 *r   c                r+   r,   r    r"   r$   r   r%   rc   ?  s     
0 
0 
0r   c                s    V P                   P                  V4      f   \        P                  ! RV4       R# V P                   V,          P	                  4        V P
                  P                  V4       R# )z7Stop injecting the preset mappings for a single device.Nz:Tried to stop injector, but none is running for group "%s")rf   ro   r   re   rG   rj   r/   r-   r.   r   rG   ZDaemon.stop_injecting?  sW    >>i(0LLL y!002$$Y/r   c                rH   rI   rJ   r"   r$   r   r%   rc   K  s     K K3 K= Kr   c                s    V P                   P                  V4      pV'       d   VP                  4       # \        P                  # )zGet the injectors state.)rf   ro   rK   r	   ZUNKNOWN)r   r   injectorr   r   rK   ZDaemon.get_stateK  s2    >>%%i0'/x!!#J]5J5JJr   c                r+   )r   rU   r    r"   r$   r   r%   rc   Q  s     9 9 9r   c                s    \        VR4      p\        P                  P                  V4      '       g   \        P
                  ! RV4       R# Wn        V P                  P                  \        V4      4       R# )a  All future operations will use this config dir.

Existing injections (possibly of the previous user) will be kept
alive, call stop_all to stop them.

Parameters
----------
config_dir
    This path contains config.json, xmodmap.json and the
    presets directory
zconfig.jsonz"%s" does not existN)
r    ri   pathZexistsr   rs   rU   r`   Zload_configr!   )r   rU   rx   r   r   rW   ZDaemon.set_config_dirP  sS     z=9ww~~k**LL.<$&&s;'78r   c                r+   r,   r    r"   r$   r   r%   rc   e  s     &: &:3 &:r   c                s|   V P                  V4       \        P                  ! VR7      pVf   R# V P                  P	                  VP
                  4      pVf   R# \        V\        4      '       g   \        P                  ! RV4       R# \        P                  ! RVP
                  4       V P                  P                  VP
                  V4      '       g%   \        P                  ! RVVP
                  4       R# V P                  VP
                  V4       V P                  P                  VP
                  V4       R# )zCheck if autoloading is a good idea, and if so do it.

Parameters
----------
group_key
    unique identifier used by the groups object
r}   Nz*Expected a string for autoload, but got %szAutoloading for "%s"z9Not autoloading the same preset "%s" again for group "%s")r   r   r   r`   Zget_autoload_presetr~   Z
isinstancer!   r   rs   rr   rj   r1   rO   r*   )r   r   groupr   s   &&  r   	_autoloadZDaemon._autoloade  s     	Y	*= ##77		B>&#&&LLEvN*EII6$$11%))VDDKKK		
 UYY/&&uyy&9r   c                r+   r,   r    r"   r$   r   r%   rc     s     " " "r   c                s    VP                  R4      '       d   R# \        P                  ! RV4       V P                  f   \        P                  ! RV4       R# V P                  V4       R# )zInject the configured autoload preset for the device.

If the preset is already being injected, it won't autoload it again.

Parameters
----------
group_key
    unique identifier used by the groups object
zinput-remapperNzRequest to autoload for "%s"z`Request to autoload "%s" before a user told the service about their session using set_config_dir)Z
startswithr   rr   rU   rs   r   r-   r.   r   rZ   ZDaemon.autoload_single  sW      0112I>??"LL/
 y!r   c                sL   V P                   f   \        P                  ! R4       R# \        V P                  P                  4       4      p\        P                  ! R4       \        V4      ^ 8X  d   \        P                  ! R4       R# V F  w  r#V P                  V4       K  	  R# )z~Load all autoloaded presets for the current config_dir.

If the preset is already being injected, it won't autoload it again.
Nz_Request to autoload all before a user told the service about their session using set_config_dirzAutoloading for all devicesz!No presets configured to autoload)	rU   r   rs   listr`   Ziterate_autoload_presetsrr   Zlenr   )r   Zautoload_presetsr   Z_s   &   r   rY   ZDaemon.autoload  s     ??"LL/  2 2 K K MN12 A%LL<=,LINN9% -r   c                rL   )r   r   preset_namerC   rM   r"   r$   r   r%   rc     s'     \ \ \3 \4 \r   c                s8   \         P                  ! RV4       V P                  V4       V P                  f   \         P                  ! R4       R# \
        P                  ! VR7      pVf   \         P                  ! RV4       R# \        V P                  R\        P                  ! VP                  4      V R24      p\        P                  P                  V P                  R	4      p \        VR
4      ;_uu_ 4       p\        P                   ! V4      p\         P"                  ! RV4       \$        P&                  ! ^ 4       \$        P(                  ! V4       RRR4       \-        T4      p TP!                  4        T F(  p
T P0                  P3                  T
P4                  4       K*  	  T P6                  P9                  T4      e   T P;                  T4        \=        TTT P>                  4      pTPA                  4        YP6                  TPB                  &   R#   + '       g   i     L; i  \*         d    \         P                  ! RT4        Li ; i  \*         d+   p	\         P                  ! \/        T	4      4        Rp	?	R# Rp	?	ii ; i  \D         d     R# i ; i)a  Start injecting the preset for the device.

Returns True on success. If an injection is already ongoing for
the specified device it will stop it automatically first.

Parameters
----------
group_key
    The unique key of the group
preset_name
    The name of the preset
z#Request to start injecting for "%s"NzeRequest to start an injectoin before a user told the service about their session using set_config_dirFr}   zCould not find group "%s"Zpresetsz.jsonzxmodmap.jsonZrzUsing keycodes from "%s"zCould not find "%s"T)#r   rr   r   rU   rs   r   r   r    r   Zsanitize_path_componentZnameri   r   ZjoinZopenjsonZloadre   r   Zget_nameZupdateZFileNotFoundErrorr
   r!   ra   Zprepare_singleZtarget_uinputrf   ro   rG   r   rb   rm   r~   ZOSError)r   r   r   r   Zpreset_pathZxmodmap_pathZfileZxmodmapr   rs   Zmappingr   s   &&&         r   rO   ZDaemon.start_injecting  s    	99EY??"LL5 	*=LL4i@OO--ejj9m5!	
 ww||DOO^D	>lC((D ))D/7F  ((+&&w/ )$ $	KKM
 G
 ..w/D/DE  >>i(4	*	##H
 NN(0NN599% c )( ! 	>LL.=	> ! 	LLU$	,  	 	s[   'H* ;AHH* )I ?J
 H'	"H* 'H* *"IIJJJ
JJc                s    \         P                  ! R4       \        V P                  P	                  4       4       F  pV P                  V4       K  	  R# )zStop all injections.zStopping all injectionsN)r   rr   r   rf   ZkeysrG   r-   r|   r   rS   ZDaemon.stop_all  s9    -.dnn1134I	* 5r   c                r+   )r   r[   r    r"   r$   r   r%   rc   $  s       r   c                s4    \         P                  ! RV4       V# )zUsed for tests.zReceived "%s" from client)r   rr   r\   r.   r   r]   ZDaemon.hello$  s    /5
r   c                s^    \         P                  ! R4       \        P                  ! ^ 4       R# )zStop the process.z&Got command to stop the daemon processN)r   rr   ru   rv   r   r   r   r^   ZDaemon.quit)  s     	<=r   )rj   rU   r`   ra   rf   rb   rk   )TrF   )r2   r3   r4   r5   r6   rp   Zdbusr   Zclassmethodry   rz   r{   r   rG   rK   r?   rW   r   rZ   rY   rO   rS   r]   r^   r7   r8   r9   r:   r   r_   r_      s     &Z (!DF!  ! F 2 2 2h, ,.
0 
0K K
 9 9(&: &:P " "4 & &.\ \|+ 
 r   r_   )/r6   rl   r   ri   ru   r'   Zpathlibr    Ztypingr   r   r   ZgiZpydbusr   Z7inputremapper.injection.mapping_handlers.mapping_parserr   Zrequire_versionZgi.repositoryr   Zinputremapper.logging.loggerr   Z inputremapper.injection.injectorr   r	   Zinputremapper.configs.presetr
   Z#inputremapper.configs.global_configr   Z%inputremapper.configs.keyboard_layoutr   Zinputremapper.groupsr   Zinputremapper.configs.pathsr   Zinputremapper.userr   Z$inputremapper.injection.macros.macror   Z&inputremapper.injection.global_uinputsr   rp   rq   r   r?   r@   r_   r<   r   r   <module>r      s   *   	 
   + + 	  Q   65 !  / D / < A ' 1 ( @ @ # . .b (  ,[ [r   