/*
 * Copyright (C) 2024 Zhiyi Zhang for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifdef __WIDL__
#pragma winrt ns_prefix
#endif

#ifndef DO_NO_IMPORTS
import "inspectable.idl";
import "asyncinfo.idl";
import "eventtoken.idl";
import "windowscontracts.idl";
import "windows.foundation.idl";
import "windows.devices.input.idl";
import "windows.system.idl";
import "windows.ui.core.idl";
#endif

namespace Windows.UI.Input {
    typedef enum PointerUpdateKind PointerUpdateKind;

    interface IPointerPoint;
    interface IPointerPointProperties;
    interface IPointerPointProperties2;
    interface IPointerPointStatics;
    interface IPointerPointTransform;

    runtimeclass PointerPoint;
    runtimeclass PointerPointProperties;

    declare {
        interface Windows.Foundation.Collections.IVectorView<Windows.UI.Input.PointerPoint *>;
        interface Windows.Foundation.Collections.IVector<Windows.UI.Input.PointerPoint *>;
    }

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0)
    ]
    enum PointerUpdateKind
    {
        Other                = 0,
        LeftButtonPressed    = 1,
        LeftButtonReleased   = 2,
        RightButtonPressed   = 3,
        RightButtonReleased  = 4,
        MiddleButtonPressed  = 5,
        MiddleButtonReleased = 6,
        XButton1Pressed      = 7,
        XButton1Released     = 8,
        XButton2Pressed      = 9,
        XButton2Released     = 10
    };

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0),
        exclusiveto(Windows.UI.Input.PointerPoint),
        uuid(e995317d-7296-42d9-8233-c5be73b74a4a)
    ]
    interface IPointerPoint : IInspectable
    {
        [propget] HRESULT PointerDevice([out, retval] Windows.Devices.Input.PointerDevice **value);
        [propget] HRESULT Position([out, retval] Windows.Foundation.Point *value);
        [propget] HRESULT RawPosition([out, retval] Windows.Foundation.Point *value);
        [propget] HRESULT pointer_id([out, retval] UINT32 *value);
        [propget] HRESULT FrameId([out, retval] UINT32 *value);
        [propget] HRESULT Timestamp([out, retval] UINT64 *value);
        [propget] HRESULT IsInContact([out, retval] boolean *value);
        [propget] HRESULT Properties([out, retval] Windows.UI.Input.PointerPointProperties **value);
    }

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0),
        exclusiveto(Windows.UI.Input.PointerPointProperties),
        uuid(c79d8a4b-c163-4ee7-803f-67ce79f9972d)
    ]
    interface IPointerPointProperties : IInspectable
    {
        [propget] HRESULT Pressure([out, retval] FLOAT *value);
        [propget] HRESULT IsInverted([out, retval] boolean *value);
        [propget] HRESULT IsEraser([out, retval] boolean *value);
        [propget] HRESULT Orientation([out, retval] FLOAT *value);
        [propget] HRESULT XTilt([out, retval] FLOAT *value);
        [propget] HRESULT YTilt([out, retval] FLOAT *value);
        [propget] HRESULT Twist([out, retval] FLOAT *value);
        [propget] HRESULT ContactRect([out, retval] Windows.Foundation.Rect *value);
        [propget] HRESULT ContactRectRaw([out, retval] Windows.Foundation.Rect *value);
        [propget] HRESULT TouchConfidence([out, retval] boolean *value);
        [propget] HRESULT IsLeftButtonPressed([out, retval] boolean *value);
        [propget] HRESULT IsRightButtonPressed([out, retval] boolean *value);
        [propget] HRESULT IsMiddleButtonPressed([out, retval] boolean *value);
        [propget] HRESULT MouseWheelDelta([out, retval] INT32 *value);
        [propget] HRESULT IsHorizontalMouseWheel([out, retval] boolean *value);
        [propget] HRESULT IsPrimary([out, retval] boolean *value);
        [propget] HRESULT IsInRange([out, retval] boolean *value);
        [propget] HRESULT IsCanceled([out, retval] boolean *value);
        [propget] HRESULT IsBarrelButtonPressed([out, retval] boolean *value);
        [propget] HRESULT IsXButton1Pressed([out, retval] boolean *value);
        [propget] HRESULT IsXButton2Pressed([out, retval] boolean *value);
        [propget] HRESULT PointerUpdateKind([out, retval] Windows.UI.Input.PointerUpdateKind *value);
        HRESULT HasUsage([in] UINT32 usage_page, [in] UINT32 usage_id, [out, retval] boolean *value);
        HRESULT GetUsageValue([in] UINT32 usage_page, [in] UINT32 usage_id, [out, retval] INT32 *value);
    }

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0),
        exclusiveto(Windows.UI.Input.PointerPointProperties),
        uuid(22c3433a-c83b-41c0-a296-5e232d64d6af)
    ]
    interface IPointerPointProperties2 : IInspectable
    {
        [propget] HRESULT ZDistance([out, retval] Windows.Foundation.IReference<FLOAT> **value);
    }

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0),
        exclusiveto(Windows.UI.Input.PointerPoint),
        uuid(a506638d-2a1a-413e-bc75-9f38381cc069)
    ]
    interface IPointerPointStatics : IInspectable
    {
        [overload("GetCurrentPoint")] HRESULT GetCurrentPoint([in] UINT32 pointer_id, [out, retval] Windows.UI.Input.PointerPoint **point);
        [overload("GetIntermediatePoints")] HRESULT GetIntermediatePoints([in] UINT32 pointer_id, [out, retval] Windows.Foundation.Collections.IVector<Windows.UI.Input.PointerPoint *> **points);
        [overload("GetCurrentPoint")] HRESULT GetCurrentPointTransformed([in] UINT32 pointer_id, [in] Windows.UI.Input.IPointerPointTransform *transform, [out, retval] Windows.UI.Input.PointerPoint **point);
        [overload("GetIntermediatePoints")] HRESULT GetIntermediatePointsTransformed([in] UINT32 pointer_id, [in] Windows.UI.Input.IPointerPointTransform *transform, [out, retval] Windows.Foundation.Collections.IVector<Windows.UI.Input.PointerPoint *> **points);
    }

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0),
        uuid(4d5fe14f-b87c-4028-bc9c-59e9947fb056)
    ]
    interface IPointerPointTransform : IInspectable
    {
        [propget] HRESULT Inverse([out, retval] Windows.UI.Input.IPointerPointTransform **value);
        HRESULT TryTransform([in] Windows.Foundation.Point in_point, [out] Windows.Foundation.Point *out_point, [out, retval] boolean *value);
        HRESULT TransformBounds([in] Windows.Foundation.Rect rect, [out, retval] Windows.Foundation.Rect *value);
    }

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0),
        marshaling_behavior(none),
        static(Windows.UI.Input.IPointerPointStatics, Windows.Foundation.UniversalApiContract, 1.0)
    ]
    runtimeclass PointerPoint
    {
        [default] interface Windows.UI.Input.IPointerPoint;
    }

    [
        contract(Windows.Foundation.UniversalApiContract, 1.0),
        marshaling_behavior(none)
    ]
    runtimeclass PointerPointProperties
    {
        [default] interface Windows.UI.Input.IPointerPointProperties;
        [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.UI.Input.IPointerPointProperties2;
    }
}
