U
    Pe                     @   sX   d Z d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 G dd	 d	eZd
S )a  
Calibration
===========

.. versionadded:: 1.9.0

Recalibrate input device to a specific range / offset.

Let's say you have 3 1080p displays, the 2 firsts are multitouch. By default,
both will have mixed touch, the range will conflict with each others: the 0-1
range will goes to 0-5760 px (remember, 3 * 1920 = 5760.)

To fix it, you need to manually reference them. For example::

    [input]
    left = mtdev,/dev/input/event17
    middle = mtdev,/dev/input/event15
    # the right screen is just a display.

Then, you can use the calibration postproc module::

    [postproc:calibration]
    left = xratio=0.3333
    middle = xratio=0.3333,xoffset=0.3333

Now, the touches from the left screen will be within 0-0.3333 range, and the
touches from the middle screen will be within 0.3333-0.6666 range.

You can also match calibration rules to devices based on their provider type.
This is useful when probesysfs is used to match devices. For example::

    [input]
    mtdev_%(name)s = probesysfs,provider=mtdev

Then to apply calibration to any mtdev device, you can assign rules to the
provider name enclosed by parentheses::

    [postproc:calibration]
    (mtdev) = xratio=0.3333,xoffset=0.3333

Calibrating devices like this means the device's path doesn't need to be
configured ahead of time. Note that with this method, all mtdev inputs will
have the same calibration applied to them. For this reason, matching by
provider will typically be useful when expecting only one input device.
)InputPostprocCalibration    )Config)Logger)	providers)MotionEventFactory)MotionEventc                       s@   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Z  Z	S )r   a#  Recalibrate the inputs.

    The configuration must go within a section named `postproc:calibration`.
    Within the section, you must have a line like::

        devicename = param=value,param=value

    If you wish to match by provider, you must have a line like::

        (provider) = param=value,param=value

    :Parameters:
        `xratio`: float
            Value to multiply X
        `yratio`: float
            Value to multiply Y
        `xoffset`: float
            Value to add to X
        `yoffset`: float
            Value to add to Y
        `auto`: str
            If set, then the touch is transformed from screen-relative
            to window-relative The value is used as an indication of
            screen size, e.g for fullHD:

                auto=1920x1080

            If present, this setting overrides all the others.
            This assumes the input device exactly covers the display
            area, if they are different, the computations will be wrong.

    .. versionchanged:: 1.11.0
        Added `auto` parameter
    c           
         s   t t|   i | _d| _|  | _tds2d S ddddd}t	dD ]\}}|
 }|dD ]v}| }|svqd|dd\}}|dkrdd	 |d
D \}}	||	f|d<  q|dkrtd| t|||< qd|| j|< qJd S )Nr   zpostproc:calibration   )xoffsetyoffsetxratioyratio,=autoc                 S   s   g | ]}t |qS  )float).0xr   r   C/tmp/pip-unpacked-wheel-xzebddm3/kivy/input/postproc/calibration.py
<listcomp>l   s     z5InputPostprocCalibration.__init__.<locals>.<listcomp>r   z%Calibration: invalid key provided: {})superr   __init__devicesframe_get_provider_mapprovider_mapr   has_sectionitemscopysplitstripr   errorformatr   )
selfZdefault_paramsZ
device_keyZ
params_strparamsparamkeyvaluewidthheight	__class__r   r   r   \   s0    

z!InputPostprocCalibration.__init__c                 C   sT   i }t  D ]B}tt|sqtt|}|jD ] }t||}t|tr,|||< q,q|S )zIterates through all registered input provider names and finds the
        respective MotionEvent subclass for each. Returns a dict of MotionEvent
        subclasses mapped to their provider name.
        )r   listhasattrr   getattr__all__
issubclassr   )r#   r   Zinput_providerpmeventr   r   r   r   u   s    




z*InputPostprocCalibration._get_provider_mapc                 C   s.   | j |j}d|}|r*|| jkr*|S dS )zfReturns the provider key for the event if the provider is configured
        for calibration.
        z({})N)r   getr+   r"   r   )r#   r3   Z
input_typer&   r   r   r   _get_provider_key   s    
z*InputPostprocCalibration._get_provider_keyc                 C   sP  | j s
|S |  jd7  _| j}g }|D ]\}}|dkr:q&|j| j krN|j}n
| |}|s^q&d|jkrt||jd< n|jd |krq&||jd< | j | }d|kr| |j|j|d \|_|_d|j  krdkrn nd|j  krdks4n |||f q&|j|d  |d  |_|j|d  |d	  |_q&|D ]}|	| q:|S )
Nr   endzcalibration:framer   r   r   r	   r   r
   )
r   r   Zdevicer5   Zudauto_calibratesxsyappendremove)r#   eventsr   Z	to_removeetyper3   devr$   r   r   r   process   s@    




  4z InputPostprocCalibration.processc                 C   sn   ddl m} |\}}||j }||j }|j |j }	||j |j  |j }
|| |	 }|| |
 }||fS )Nr   )Window)Zkivy.core.windowr@   r(   r)   lefttop)r#   r8   r9   sizeWZWIDTHZHEIGHTr   r   r	   r
   r   r   r   r7      s    

z'InputPostprocCalibration.auto_calibrate)
__name__
__module____qualname____doc__r   r   r5   r?   r7   __classcell__r   r   r*   r   r   8   s   #	+r   N)rH   r/   Zkivy.configr   Zkivy.loggerr   Z
kivy.inputr   Zkivy.input.factoryr   Zkivy.input.motioneventr   objectr   r   r   r   r   <module>   s   .