# This file has been autogenerated by the pywayland scanner

# Copyright © 2008-2013 Kristian Høgsberg
# Copyright © 2013      Rafael Antognolli
# Copyright © 2013      Jasper St. Pierre
# Copyright © 2010-2013 Intel Corporation
# Copyright © 2015-2017 Samsung Electronics Co., Ltd
# Copyright © 2015-2017 Red Hat Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

from __future__ import annotations

import enum

from pywayland.protocol_core import (
    Argument,
    ArgumentType,
    Global,
    Interface,
    Proxy,
    Resource,
)
from .xdg_popup import XdgPopup
from .xdg_positioner import XdgPositioner
from .xdg_toplevel import XdgToplevel


class XdgSurface(Interface):
    """Desktop user interface surface base interface

    An interface that may be implemented by a
    :class:`~pywayland.protocol.wayland.WlSurface`, for implementations that
    provide a desktop-style user interface.

    It provides a base set of functionality required to construct user
    interface elements requiring management by the compositor, such as toplevel
    windows, menus, etc. The types of functionality are split into
    :class:`XdgSurface` roles.

    Creating an :class:`XdgSurface` does not set the role for a
    :class:`~pywayland.protocol.wayland.WlSurface`. In order to map an
    :class:`XdgSurface`, the client must create a role-specific object using,
    e.g., get_toplevel, get_popup. The
    :class:`~pywayland.protocol.wayland.WlSurface` for any given
    :class:`XdgSurface` can have at most one role, and may not be assigned any
    role not based on :class:`XdgSurface`.

    A role must be assigned before any other requests are made to the
    :class:`XdgSurface` object.

    The client must call :func:`WlSurface.commit()
    <pywayland.protocol.wayland.WlSurface.commit>` on the corresponding
    :class:`~pywayland.protocol.wayland.WlSurface` for the :class:`XdgSurface`
    state to take effect.

    Creating an :class:`XdgSurface` from a
    :class:`~pywayland.protocol.wayland.WlSurface` which has a buffer attached
    or committed is a client error, and any attempts by a client to attach or
    manipulate a buffer prior to the first :func:`XdgSurface.configure()` call
    must also be treated as errors.

    After creating a role-specific object and setting it up, the client must
    perform an initial commit without any buffer attached. The compositor will
    reply with initial :class:`~pywayland.protocol.wayland.WlSurface` state
    such as :func:`WlSurface.preferred_buffer_scale()
    <pywayland.protocol.wayland.WlSurface.preferred_buffer_scale>` followed by
    an :func:`XdgSurface.configure()` event. The client must acknowledge it and
    is then allowed to attach a buffer to map the surface.

    Mapping an :class:`XdgSurface`-based role surface is defined as making it
    possible for the surface to be shown by the compositor. Note that a mapped
    surface is not guaranteed to be visible once it is mapped.

    For an :class:`XdgSurface` to be mapped by the compositor, the following
    conditions must be met: (1) the client has assigned an
    :class:`XdgSurface`-based role to the surface (2) the client has set and
    committed the :class:`XdgSurface` state and the     role-dependent state to
    the surface (3) the client has committed a buffer to the surface

    A newly-unmapped surface is considered to have met condition (1) out of the
    3 required conditions for mapping a surface if its role surface has not
    been destroyed, i.e. the client must perform the initial commit again
    before attaching a buffer.
    """

    name = "xdg_surface"
    version = 6

    class error(enum.IntEnum):
        not_constructed = 1
        already_constructed = 2
        unconfigured_buffer = 3
        invalid_serial = 4
        invalid_size = 5
        defunct_role_object = 6


class XdgSurfaceProxy(Proxy[XdgSurface]):
    interface = XdgSurface

    @XdgSurface.request()
    def destroy(self) -> None:
        """Destroy the :class:`XdgSurface`

        Destroy the :class:`XdgSurface` object. An :class:`XdgSurface` must
        only be destroyed after its role object has been destroyed, otherwise a
        defunct_role_object error is raised.
        """
        self._marshal(0)
        self._destroy()

    @XdgSurface.request(
        Argument(ArgumentType.NewId, interface=XdgToplevel),
    )
    def get_toplevel(self) -> Proxy[XdgToplevel]:
        """Assign the :class:`~pywayland.protocol.xdg_shell.XdgToplevel` surface role

        This creates an :class:`~pywayland.protocol.xdg_shell.XdgToplevel`
        object for the given :class:`XdgSurface` and gives the associated
        :class:`~pywayland.protocol.wayland.WlSurface` the
        :class:`~pywayland.protocol.xdg_shell.XdgToplevel` role.

        See the documentation of
        :class:`~pywayland.protocol.xdg_shell.XdgToplevel` for more details
        about what an :class:`~pywayland.protocol.xdg_shell.XdgToplevel` is and
        how it is used.

        :returns:
            :class:`~pywayland.protocol.xdg_shell.XdgToplevel`
        """
        id = self._marshal_constructor(1, XdgToplevel)
        return id

    @XdgSurface.request(
        Argument(ArgumentType.NewId, interface=XdgPopup),
        Argument(ArgumentType.Object, interface=XdgSurface, nullable=True),
        Argument(ArgumentType.Object, interface=XdgPositioner),
    )
    def get_popup(self, parent: XdgSurface | None, positioner: XdgPositioner) -> Proxy[XdgPopup]:
        """Assign the :class:`~pywayland.protocol.xdg_shell.XdgPopup` surface role

        This creates an :class:`~pywayland.protocol.xdg_shell.XdgPopup` object
        for the given :class:`XdgSurface` and gives the associated
        :class:`~pywayland.protocol.wayland.WlSurface` the
        :class:`~pywayland.protocol.xdg_shell.XdgPopup` role.

        If null is passed as a parent, a parent surface must be specified using
        some other protocol, before committing the initial state.

        See the documentation of
        :class:`~pywayland.protocol.xdg_shell.XdgPopup` for more details about
        what an :class:`~pywayland.protocol.xdg_shell.XdgPopup` is and how it
        is used.

        :param parent:
        :type parent:
            :class:`XdgSurface` or `None`
        :param positioner:
        :type positioner:
            :class:`~pywayland.protocol.xdg_shell.XdgPositioner`
        :returns:
            :class:`~pywayland.protocol.xdg_shell.XdgPopup`
        """
        id = self._marshal_constructor(2, XdgPopup, parent, positioner)
        return id

    @XdgSurface.request(
        Argument(ArgumentType.Int),
        Argument(ArgumentType.Int),
        Argument(ArgumentType.Int),
        Argument(ArgumentType.Int),
    )
    def set_window_geometry(self, x: int, y: int, width: int, height: int) -> None:
        """Set the new window geometry

        The window geometry of a surface is its "visible bounds" from the
        user's perspective. Client-side decorations often have invisible
        portions like drop-shadows which should be ignored for the purposes of
        aligning, placing and constraining windows.

        The window geometry is double buffered, and will be applied at the time
        :func:`WlSurface.commit()
        <pywayland.protocol.wayland.WlSurface.commit>` of the corresponding
        :class:`~pywayland.protocol.wayland.WlSurface` is called.

        When maintaining a position, the compositor should treat the (x, y)
        coordinate of the window geometry as the top left corner of the window.
        A client changing the (x, y) window geometry coordinate should in
        general not alter the position of the window.

        Once the window geometry of the surface is set, it is not possible to
        unset it, and it will remain the same until set_window_geometry is
        called again, even if a new subsurface or buffer is attached.

        If never set, the value is the full bounds of the surface, including
        any subsurfaces. This updates dynamically on every commit. This unset
        is meant for extremely simple clients.

        The arguments are given in the surface-local coordinate space of the
        :class:`~pywayland.protocol.wayland.WlSurface` associated with this
        :class:`XdgSurface`, and may extend outside of the
        :class:`~pywayland.protocol.wayland.WlSurface` itself to mark parts of
        the subsurface tree as part of the window geometry.

        When applied, the effective window geometry will be the set window
        geometry clamped to the bounding rectangle of the combined geometry of
        the surface of the :class:`XdgSurface` and the associated subsurfaces.

        The effective geometry will not be recalculated unless a new call to
        set_window_geometry is done and the new pending surface state is
        subsequently applied.

        The width and height of the effective window geometry must be greater
        than zero. Setting an invalid size will raise an invalid_size error.

        :param x:
        :type x:
            `ArgumentType.Int`
        :param y:
        :type y:
            `ArgumentType.Int`
        :param width:
        :type width:
            `ArgumentType.Int`
        :param height:
        :type height:
            `ArgumentType.Int`
        """
        self._marshal(3, x, y, width, height)

    @XdgSurface.request(
        Argument(ArgumentType.Uint),
    )
    def ack_configure(self, serial: int) -> None:
        """Ack a configure event

        When a configure event is received, if a client commits the surface in
        response to the configure event, then the client must make an
        ack_configure request sometime before the commit request, passing along
        the serial of the configure event.

        For instance, for toplevel surfaces the compositor might use this
        information to move a surface to the top left only when the client has
        drawn itself for the maximized or fullscreen state.

        If the client receives multiple configure events before it can respond
        to one, it only has to ack the last configure event. Acking a configure
        event that was never sent raises an invalid_serial error.

        A client is not required to commit immediately after sending an
        ack_configure request - it may even ack_configure several times before
        its next surface commit.

        A client may send multiple ack_configure requests before committing,
        but only the last request sent before a commit indicates which
        configure event the client really is responding to.

        Sending an ack_configure request consumes the serial number sent with
        the request, as well as serial numbers sent by all configure events
        sent on this :class:`XdgSurface` prior to the configure event
        referenced by the committed serial.

        It is an error to issue multiple ack_configure requests referencing a
        serial from the same configure event, or to issue an ack_configure
        request referencing a serial from a configure event issued before the
        event identified by the last ack_configure request for the same
        :class:`XdgSurface`. Doing so will raise an invalid_serial error.

        :param serial:
            the serial from the configure event
        :type serial:
            `ArgumentType.Uint`
        """
        self._marshal(4, serial)


class XdgSurfaceResource(Resource):
    interface = XdgSurface

    @XdgSurface.event(
        Argument(ArgumentType.Uint),
    )
    def configure(self, serial: int) -> None:
        """Suggest a surface change

        The configure event marks the end of a configure sequence. A configure
        sequence is a set of one or more events configuring the state of the
        :class:`XdgSurface`, including the final :func:`XdgSurface.configure()`
        event.

        Where applicable, :class:`XdgSurface` surface roles will during a
        configure sequence extend this event as a latched state sent as events
        before the :func:`XdgSurface.configure()` event. Such events should be
        considered to make up a set of atomically applied configuration states,
        where the :func:`XdgSurface.configure()` commits the accumulated state.

        Clients should arrange their surface for the new states, and then send
        an ack_configure request with the serial sent in this configure event
        at some point before committing the new surface.

        If the client receives multiple configure events before it can respond
        to one, it is free to discard all but the last event it received.

        :param serial:
            serial of the configure event
        :type serial:
            `ArgumentType.Uint`
        """
        self._post_event(0, serial)


class XdgSurfaceGlobal(Global):
    interface = XdgSurface


XdgSurface._gen_c()
XdgSurface.proxy_class = XdgSurfaceProxy
XdgSurface.resource_class = XdgSurfaceResource
XdgSurface.global_class = XdgSurfaceGlobal
