#pragma once

#include <AK/Optional.h>
#include <LibGfx/Point.h>
#include <LibGfx/Size.h>
#include <LibIPC/TransportHandle.h>
#include <LibWeb/Compositor/Types.h>
#include <LibWeb/Page/InputEvent.h>
#include <AK/Error.h>
#include <AK/MemoryStream.h>
#include <AK/OwnPtr.h>
#include <AK/Platform.h>
#include <AK/Result.h>
#include <AK/Utf8View.h>
#include <LibIPC/Attachment.h>
#include <LibIPC/Connection.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
#include <LibIPC/File.h>
#include <LibIPC/Message.h>
#include <LibIPC/Stub.h>

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdefaulted-function-deleted"
#endif

namespace Messages::CompositorControlServer {

enum class MessageID : i32 {
    InitTransport = 1,
    InitTransportResponse = 2,
    ConnectWebContent = 3,
    ConnectWebContentResponse = 4,
    CreateContext = 5,
    CreateContextResponse = 6,
    ViewportSizeUpdated = 7,
    SetDisplayMetadata = 8,
    HandleMouseEvent = 9,
    HandleMouseEventResponse = 10,
    DispatchMouseEventToWebContent = 11,
    DispatchMouseEventToWebContentResponse = 12,
    HandlePinchEvent = 13,
    HandlePinchEventResponse = 14,
    AsyncScrollBy = 15,
    AsyncScrollByResponse = 16,
    PresentedBitmapReadyToPaint = 17,
    Crash = 18,
};

class InitTransportResponse final : public IPC::Message {
public:
    InitTransportResponse(int peer_pid)
        : m_peer_pid(move(peer_pid))
    {
    }

    InitTransportResponse(InitTransportResponse const&) = default;
    InitTransportResponse(InitTransportResponse&&) = default;
    InitTransportResponse& operator=(InitTransportResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, int>)
    InitTransportResponse(WrappedReturnType&& value)
        : m_peer_pid(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::InitTransportResponse; }
    static i32 static_message_id() { return (int)MessageID::InitTransportResponse; }
    virtual StringView message_name() const override { return "CompositorControlServer::InitTransportResponse"sv; }

    static ErrorOr<NonnullOwnPtr<InitTransportResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto peer_pid = TRY((decoder.decode<int>()));
        return make<InitTransportResponse>(move(peer_pid));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(int peer_pid)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::InitTransportResponse));
        TRY(stream.encode(peer_pid));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_peer_pid);
    }

    int peer_pid() const { return m_peer_pid; }

private:
    int m_peer_pid;
};

class InitTransport final : public IPC::Message {
public:
    typedef class InitTransportResponse ResponseType;

    InitTransport(int peer_pid)
        : m_peer_pid(move(peer_pid))
    {
    }

    InitTransport(InitTransport const&) = default;
    InitTransport(InitTransport&&) = default;
    InitTransport& operator=(InitTransport const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, int>)
    InitTransport(WrappedReturnType&& value)
        : m_peer_pid(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::InitTransport; }
    static i32 static_message_id() { return (int)MessageID::InitTransport; }
    virtual StringView message_name() const override { return "CompositorControlServer::InitTransport"sv; }

    static ErrorOr<NonnullOwnPtr<InitTransport>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto peer_pid = TRY((decoder.decode<int>()));
        return make<InitTransport>(move(peer_pid));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(int peer_pid)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::InitTransport));
        TRY(stream.encode(peer_pid));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_peer_pid);
    }

    int peer_pid() const { return m_peer_pid; }

private:
    int m_peer_pid;
};

class ConnectWebContentResponse final : public IPC::Message {
public:
    ConnectWebContentResponse(IPC::TransportHandle handle, i32 web_content_connection_id)
        : m_handle(move(handle))
        , m_web_content_connection_id(move(web_content_connection_id))
    {
    }

    ConnectWebContentResponse(ConnectWebContentResponse const&) = default;
    ConnectWebContentResponse(ConnectWebContentResponse&&) = default;
    ConnectWebContentResponse& operator=(ConnectWebContentResponse const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectWebContentResponse; }
    static i32 static_message_id() { return (int)MessageID::ConnectWebContentResponse; }
    virtual StringView message_name() const override { return "CompositorControlServer::ConnectWebContentResponse"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectWebContentResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto handle = TRY((decoder.decode<IPC::TransportHandle>()));
        auto web_content_connection_id = TRY((decoder.decode<i32>()));
        return make<ConnectWebContentResponse>(move(handle), move(web_content_connection_id));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(IPC::TransportHandle const& handle, i32 web_content_connection_id)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectWebContentResponse));
        TRY(stream.encode(handle));
        TRY(stream.encode(web_content_connection_id));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_handle, m_web_content_connection_id);
    }

    IPC::TransportHandle const& handle() const { return m_handle; }
    IPC::TransportHandle take_handle() { return move(m_handle); }

    i32 web_content_connection_id() const { return m_web_content_connection_id; }

private:
    IPC::TransportHandle m_handle;
    i32 m_web_content_connection_id;
};

class ConnectWebContent final : public IPC::Message {
public:
    typedef class ConnectWebContentResponse ResponseType;

    ConnectWebContent() = default;

    ConnectWebContent(ConnectWebContent const&) = default;
    ConnectWebContent(ConnectWebContent&&) = default;
    ConnectWebContent& operator=(ConnectWebContent const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectWebContent; }
    static i32 static_message_id() { return (int)MessageID::ConnectWebContent; }
    virtual StringView message_name() const override { return "CompositorControlServer::ConnectWebContent"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectWebContent>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        return make<ConnectWebContent>();
    }

    static ErrorOr<IPC::MessageBuffer> static_encode()
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectWebContent));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode();
    }

private:
};

class CreateContextResponse final : public IPC::Message {
public:
    CreateContextResponse() = default;

    CreateContextResponse(CreateContextResponse const&) = default;
    CreateContextResponse(CreateContextResponse&&) = default;
    CreateContextResponse& operator=(CreateContextResponse const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::CreateContextResponse; }
    static i32 static_message_id() { return (int)MessageID::CreateContextResponse; }
    virtual StringView message_name() const override { return "CompositorControlServer::CreateContextResponse"sv; }

    static ErrorOr<NonnullOwnPtr<CreateContextResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        return make<CreateContextResponse>();
    }

    static ErrorOr<IPC::MessageBuffer> static_encode()
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::CreateContextResponse));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode();
    }

private:
};

class CreateContext final : public IPC::Message {
public:
    typedef class CreateContextResponse ResponseType;

    CreateContext(Web::Compositor::CompositorContextId context_id, Optional<u64> page_id, i32 web_content_connection_id)
        : m_context_id(move(context_id))
        , m_page_id(move(page_id))
        , m_web_content_connection_id(move(web_content_connection_id))
    {
    }

    CreateContext(CreateContext const&) = default;
    CreateContext(CreateContext&&) = default;
    CreateContext& operator=(CreateContext const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::CreateContext; }
    static i32 static_message_id() { return (int)MessageID::CreateContext; }
    virtual StringView message_name() const override { return "CompositorControlServer::CreateContext"sv; }

    static ErrorOr<NonnullOwnPtr<CreateContext>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto page_id = TRY((decoder.decode<Optional<u64>>()));
        auto web_content_connection_id = TRY((decoder.decode<i32>()));
        return make<CreateContext>(move(context_id), move(page_id), move(web_content_connection_id));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, Optional<u64> const& page_id, i32 web_content_connection_id)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::CreateContext));
        TRY(stream.encode(context_id));
        TRY(stream.encode(page_id));
        TRY(stream.encode(web_content_connection_id));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_page_id, m_web_content_connection_id);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    Optional<u64> const& page_id() const { return m_page_id; }
    Optional<u64> take_page_id() { return move(m_page_id); }

    i32 web_content_connection_id() const { return m_web_content_connection_id; }

private:
    Web::Compositor::CompositorContextId m_context_id;
    Optional<u64> m_page_id;
    i32 m_web_content_connection_id;
};

class ViewportSizeUpdated final : public IPC::Message {
public:
    ViewportSizeUpdated(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress window_resize_in_progress)
        : m_context_id(move(context_id))
        , m_viewport_size(move(viewport_size))
        , m_window_resize_in_progress(move(window_resize_in_progress))
    {
    }

    ViewportSizeUpdated(ViewportSizeUpdated const&) = default;
    ViewportSizeUpdated(ViewportSizeUpdated&&) = default;
    ViewportSizeUpdated& operator=(ViewportSizeUpdated const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ViewportSizeUpdated; }
    static i32 static_message_id() { return (int)MessageID::ViewportSizeUpdated; }
    virtual StringView message_name() const override { return "CompositorControlServer::ViewportSizeUpdated"sv; }

    static ErrorOr<NonnullOwnPtr<ViewportSizeUpdated>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto viewport_size = TRY((decoder.decode<Gfx::IntSize>()));
        auto window_resize_in_progress = TRY((decoder.decode<Web::Compositor::WindowResizingInProgress>()));
        return make<ViewportSizeUpdated>(move(context_id), move(viewport_size), move(window_resize_in_progress));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress const& window_resize_in_progress)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ViewportSizeUpdated));
        TRY(stream.encode(context_id));
        TRY(stream.encode(viewport_size));
        TRY(stream.encode(window_resize_in_progress));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_viewport_size, m_window_resize_in_progress);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    Gfx::IntSize viewport_size() const { return m_viewport_size; }

    Web::Compositor::WindowResizingInProgress const& window_resize_in_progress() const { return m_window_resize_in_progress; }
    Web::Compositor::WindowResizingInProgress take_window_resize_in_progress() { return move(m_window_resize_in_progress); }

private:
    Web::Compositor::CompositorContextId m_context_id;
    Gfx::IntSize m_viewport_size;
    Web::Compositor::WindowResizingInProgress m_window_resize_in_progress;
};

class SetDisplayMetadata final : public IPC::Message {
public:
    SetDisplayMetadata(Web::Compositor::CompositorContextId context_id, Optional<u64> display_id, double refresh_rate)
        : m_context_id(move(context_id))
        , m_display_id(move(display_id))
        , m_refresh_rate(move(refresh_rate))
    {
    }

    SetDisplayMetadata(SetDisplayMetadata const&) = default;
    SetDisplayMetadata(SetDisplayMetadata&&) = default;
    SetDisplayMetadata& operator=(SetDisplayMetadata const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::SetDisplayMetadata; }
    static i32 static_message_id() { return (int)MessageID::SetDisplayMetadata; }
    virtual StringView message_name() const override { return "CompositorControlServer::SetDisplayMetadata"sv; }

    static ErrorOr<NonnullOwnPtr<SetDisplayMetadata>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto display_id = TRY((decoder.decode<Optional<u64>>()));
        auto refresh_rate = TRY((decoder.decode<double>()));
        return make<SetDisplayMetadata>(move(context_id), move(display_id), move(refresh_rate));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, Optional<u64> const& display_id, double refresh_rate)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::SetDisplayMetadata));
        TRY(stream.encode(context_id));
        TRY(stream.encode(display_id));
        TRY(stream.encode(refresh_rate));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_display_id, m_refresh_rate);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    Optional<u64> const& display_id() const { return m_display_id; }
    Optional<u64> take_display_id() { return move(m_display_id); }

    double refresh_rate() const { return m_refresh_rate; }

private:
    Web::Compositor::CompositorContextId m_context_id;
    Optional<u64> m_display_id;
    double m_refresh_rate;
};

class HandleMouseEventResponse final : public IPC::Message {
public:
    HandleMouseEventResponse(bool handled)
        : m_handled(move(handled))
    {
    }

    HandleMouseEventResponse(HandleMouseEventResponse const&) = default;
    HandleMouseEventResponse(HandleMouseEventResponse&&) = default;
    HandleMouseEventResponse& operator=(HandleMouseEventResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    HandleMouseEventResponse(WrappedReturnType&& value)
        : m_handled(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::HandleMouseEventResponse; }
    static i32 static_message_id() { return (int)MessageID::HandleMouseEventResponse; }
    virtual StringView message_name() const override { return "CompositorControlServer::HandleMouseEventResponse"sv; }

    static ErrorOr<NonnullOwnPtr<HandleMouseEventResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto handled = TRY((decoder.decode<bool>()));
        return make<HandleMouseEventResponse>(move(handled));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool handled)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::HandleMouseEventResponse));
        TRY(stream.encode(handled));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_handled);
    }

    bool handled() const { return m_handled; }

private:
    bool m_handled;
};

class HandleMouseEvent final : public IPC::Message {
public:
    typedef class HandleMouseEventResponse ResponseType;

    HandleMouseEvent(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event)
        : m_context_id(move(context_id))
        , m_event(move(event))
    {
    }

    HandleMouseEvent(HandleMouseEvent const&) = default;
    HandleMouseEvent(HandleMouseEvent&&) = default;
    HandleMouseEvent& operator=(HandleMouseEvent const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::HandleMouseEvent; }
    static i32 static_message_id() { return (int)MessageID::HandleMouseEvent; }
    virtual StringView message_name() const override { return "CompositorControlServer::HandleMouseEvent"sv; }

    static ErrorOr<NonnullOwnPtr<HandleMouseEvent>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto event = TRY((decoder.decode<Web::MouseEvent>()));
        return make<HandleMouseEvent>(move(context_id), move(event));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, Web::MouseEvent const& event)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::HandleMouseEvent));
        TRY(stream.encode(context_id));
        TRY(stream.encode(event));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_event);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    Web::MouseEvent const& event() const { return m_event; }
    Web::MouseEvent take_event() { return move(m_event); }

private:
    Web::Compositor::CompositorContextId m_context_id;
    Web::MouseEvent m_event;
};

class DispatchMouseEventToWebContentResponse final : public IPC::Message {
public:
    DispatchMouseEventToWebContentResponse(bool dispatched)
        : m_dispatched(move(dispatched))
    {
    }

    DispatchMouseEventToWebContentResponse(DispatchMouseEventToWebContentResponse const&) = default;
    DispatchMouseEventToWebContentResponse(DispatchMouseEventToWebContentResponse&&) = default;
    DispatchMouseEventToWebContentResponse& operator=(DispatchMouseEventToWebContentResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    DispatchMouseEventToWebContentResponse(WrappedReturnType&& value)
        : m_dispatched(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::DispatchMouseEventToWebContentResponse; }
    static i32 static_message_id() { return (int)MessageID::DispatchMouseEventToWebContentResponse; }
    virtual StringView message_name() const override { return "CompositorControlServer::DispatchMouseEventToWebContentResponse"sv; }

    static ErrorOr<NonnullOwnPtr<DispatchMouseEventToWebContentResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto dispatched = TRY((decoder.decode<bool>()));
        return make<DispatchMouseEventToWebContentResponse>(move(dispatched));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool dispatched)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::DispatchMouseEventToWebContentResponse));
        TRY(stream.encode(dispatched));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_dispatched);
    }

    bool dispatched() const { return m_dispatched; }

private:
    bool m_dispatched;
};

class DispatchMouseEventToWebContent final : public IPC::Message {
public:
    typedef class DispatchMouseEventToWebContentResponse ResponseType;

    DispatchMouseEventToWebContent(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event)
        : m_context_id(move(context_id))
        , m_event(move(event))
    {
    }

    DispatchMouseEventToWebContent(DispatchMouseEventToWebContent const&) = default;
    DispatchMouseEventToWebContent(DispatchMouseEventToWebContent&&) = default;
    DispatchMouseEventToWebContent& operator=(DispatchMouseEventToWebContent const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::DispatchMouseEventToWebContent; }
    static i32 static_message_id() { return (int)MessageID::DispatchMouseEventToWebContent; }
    virtual StringView message_name() const override { return "CompositorControlServer::DispatchMouseEventToWebContent"sv; }

    static ErrorOr<NonnullOwnPtr<DispatchMouseEventToWebContent>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto event = TRY((decoder.decode<Web::MouseEvent>()));
        return make<DispatchMouseEventToWebContent>(move(context_id), move(event));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, Web::MouseEvent const& event)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::DispatchMouseEventToWebContent));
        TRY(stream.encode(context_id));
        TRY(stream.encode(event));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_event);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    Web::MouseEvent const& event() const { return m_event; }
    Web::MouseEvent take_event() { return move(m_event); }

private:
    Web::Compositor::CompositorContextId m_context_id;
    Web::MouseEvent m_event;
};

class HandlePinchEventResponse final : public IPC::Message {
public:
    HandlePinchEventResponse(bool handled)
        : m_handled(move(handled))
    {
    }

    HandlePinchEventResponse(HandlePinchEventResponse const&) = default;
    HandlePinchEventResponse(HandlePinchEventResponse&&) = default;
    HandlePinchEventResponse& operator=(HandlePinchEventResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    HandlePinchEventResponse(WrappedReturnType&& value)
        : m_handled(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::HandlePinchEventResponse; }
    static i32 static_message_id() { return (int)MessageID::HandlePinchEventResponse; }
    virtual StringView message_name() const override { return "CompositorControlServer::HandlePinchEventResponse"sv; }

    static ErrorOr<NonnullOwnPtr<HandlePinchEventResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto handled = TRY((decoder.decode<bool>()));
        return make<HandlePinchEventResponse>(move(handled));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool handled)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::HandlePinchEventResponse));
        TRY(stream.encode(handled));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_handled);
    }

    bool handled() const { return m_handled; }

private:
    bool m_handled;
};

class HandlePinchEvent final : public IPC::Message {
public:
    typedef class HandlePinchEventResponse ResponseType;

    HandlePinchEvent(Web::Compositor::CompositorContextId context_id, Web::PinchEvent event)
        : m_context_id(move(context_id))
        , m_event(move(event))
    {
    }

    HandlePinchEvent(HandlePinchEvent const&) = default;
    HandlePinchEvent(HandlePinchEvent&&) = default;
    HandlePinchEvent& operator=(HandlePinchEvent const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::HandlePinchEvent; }
    static i32 static_message_id() { return (int)MessageID::HandlePinchEvent; }
    virtual StringView message_name() const override { return "CompositorControlServer::HandlePinchEvent"sv; }

    static ErrorOr<NonnullOwnPtr<HandlePinchEvent>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto event = TRY((decoder.decode<Web::PinchEvent>()));
        return make<HandlePinchEvent>(move(context_id), move(event));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, Web::PinchEvent const& event)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::HandlePinchEvent));
        TRY(stream.encode(context_id));
        TRY(stream.encode(event));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_event);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    Web::PinchEvent const& event() const { return m_event; }
    Web::PinchEvent take_event() { return move(m_event); }

private:
    Web::Compositor::CompositorContextId m_context_id;
    Web::PinchEvent m_event;
};

class AsyncScrollByResponse final : public IPC::Message {
public:
    AsyncScrollByResponse(bool handled)
        : m_handled(move(handled))
    {
    }

    AsyncScrollByResponse(AsyncScrollByResponse const&) = default;
    AsyncScrollByResponse(AsyncScrollByResponse&&) = default;
    AsyncScrollByResponse& operator=(AsyncScrollByResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    AsyncScrollByResponse(WrappedReturnType&& value)
        : m_handled(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::AsyncScrollByResponse; }
    static i32 static_message_id() { return (int)MessageID::AsyncScrollByResponse; }
    virtual StringView message_name() const override { return "CompositorControlServer::AsyncScrollByResponse"sv; }

    static ErrorOr<NonnullOwnPtr<AsyncScrollByResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto handled = TRY((decoder.decode<bool>()));
        return make<AsyncScrollByResponse>(move(handled));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool handled)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::AsyncScrollByResponse));
        TRY(stream.encode(handled));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_handled);
    }

    bool handled() const { return m_handled; }

private:
    bool m_handled;
};

class AsyncScrollBy final : public IPC::Message {
public:
    typedef class AsyncScrollByResponse ResponseType;

    AsyncScrollBy(Web::Compositor::CompositorContextId context_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels)
        : m_context_id(move(context_id))
        , m_position(move(position))
        , m_delta_in_device_pixels(move(delta_in_device_pixels))
    {
    }

    AsyncScrollBy(AsyncScrollBy const&) = default;
    AsyncScrollBy(AsyncScrollBy&&) = default;
    AsyncScrollBy& operator=(AsyncScrollBy const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::AsyncScrollBy; }
    static i32 static_message_id() { return (int)MessageID::AsyncScrollBy; }
    virtual StringView message_name() const override { return "CompositorControlServer::AsyncScrollBy"sv; }

    static ErrorOr<NonnullOwnPtr<AsyncScrollBy>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto position = TRY((decoder.decode<Gfx::FloatPoint>()));
        auto delta_in_device_pixels = TRY((decoder.decode<Gfx::FloatPoint>()));
        return make<AsyncScrollBy>(move(context_id), move(position), move(delta_in_device_pixels));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::AsyncScrollBy));
        TRY(stream.encode(context_id));
        TRY(stream.encode(position));
        TRY(stream.encode(delta_in_device_pixels));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_position, m_delta_in_device_pixels);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    Gfx::FloatPoint position() const { return m_position; }

    Gfx::FloatPoint delta_in_device_pixels() const { return m_delta_in_device_pixels; }

private:
    Web::Compositor::CompositorContextId m_context_id;
    Gfx::FloatPoint m_position;
    Gfx::FloatPoint m_delta_in_device_pixels;
};

class PresentedBitmapReadyToPaint final : public IPC::Message {
public:
    PresentedBitmapReadyToPaint(Web::Compositor::CompositorContextId context_id, i32 bitmap_id)
        : m_context_id(move(context_id))
        , m_bitmap_id(move(bitmap_id))
    {
    }

    PresentedBitmapReadyToPaint(PresentedBitmapReadyToPaint const&) = default;
    PresentedBitmapReadyToPaint(PresentedBitmapReadyToPaint&&) = default;
    PresentedBitmapReadyToPaint& operator=(PresentedBitmapReadyToPaint const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::PresentedBitmapReadyToPaint; }
    static i32 static_message_id() { return (int)MessageID::PresentedBitmapReadyToPaint; }
    virtual StringView message_name() const override { return "CompositorControlServer::PresentedBitmapReadyToPaint"sv; }

    static ErrorOr<NonnullOwnPtr<PresentedBitmapReadyToPaint>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto context_id = TRY((decoder.decode<Web::Compositor::CompositorContextId>()));
        auto bitmap_id = TRY((decoder.decode<i32>()));
        return make<PresentedBitmapReadyToPaint>(move(context_id), move(bitmap_id));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Web::Compositor::CompositorContextId const& context_id, i32 bitmap_id)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::PresentedBitmapReadyToPaint));
        TRY(stream.encode(context_id));
        TRY(stream.encode(bitmap_id));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_context_id, m_bitmap_id);
    }

    Web::Compositor::CompositorContextId const& context_id() const { return m_context_id; }
    Web::Compositor::CompositorContextId take_context_id() { return move(m_context_id); }

    i32 bitmap_id() const { return m_bitmap_id; }

private:
    Web::Compositor::CompositorContextId m_context_id;
    i32 m_bitmap_id;
};

class Crash final : public IPC::Message {
public:
    Crash() = default;

    Crash(Crash const&) = default;
    Crash(Crash&&) = default;
    Crash& operator=(Crash const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 490619793;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::Crash; }
    static i32 static_message_id() { return (int)MessageID::Crash; }
    virtual StringView message_name() const override { return "CompositorControlServer::Crash"sv; }

    static ErrorOr<NonnullOwnPtr<Crash>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        return make<Crash>();
    }

    static ErrorOr<IPC::MessageBuffer> static_encode()
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::Crash));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode();
    }

private:
};

} // namespace Messages::CompositorControlServer

template<typename LocalEndpoint, typename PeerEndpoint>
class CompositorControlServerProxy {
public:
    // Used to disambiguate the constructor call.
    struct Tag { };

    CompositorControlServerProxy(IPC::Connection<LocalEndpoint, PeerEndpoint>& connection, Tag)
        : m_connection(connection)
    {
    }

    int init_transport(int peer_pid)
    {
        return m_connection.template send_sync<Messages::CompositorControlServer::InitTransport>(peer_pid)->peer_pid();
    }

    void async_init_transport(int peer_pid)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::InitTransport::static_encode(peer_pid));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<int> try_init_transport(int peer_pid)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::CompositorControlServer::InitTransport>(peer_pid))
            return result->peer_pid();
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    Messages::CompositorControlServer::ConnectWebContentResponse connect_web_content()
    {
        return move(*m_connection.template send_sync<Messages::CompositorControlServer::ConnectWebContent>());
    }

    void async_connect_web_content()
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::ConnectWebContent::static_encode());
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<Messages::CompositorControlServer::ConnectWebContentResponse> try_connect_web_content()
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::CompositorControlServer::ConnectWebContent>())
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void create_context(Web::Compositor::CompositorContextId context_id, Optional<u64> page_id, i32 web_content_connection_id)
    {
        (void)m_connection.template send_sync<Messages::CompositorControlServer::CreateContext>(move(context_id), move(page_id), web_content_connection_id);
    }

    void async_create_context(Web::Compositor::CompositorContextId const& context_id, Optional<u64> const& page_id, i32 web_content_connection_id)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::CreateContext::static_encode(move(context_id), move(page_id), web_content_connection_id));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<void> try_create_context(Web::Compositor::CompositorContextId context_id, Optional<u64> page_id, i32 web_content_connection_id)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::CompositorControlServer::CreateContext>(move(context_id), move(page_id), web_content_connection_id))
            return {};
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void async_viewport_size_updated(Web::Compositor::CompositorContextId const& context_id, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress const& window_resize_in_progress)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::ViewportSizeUpdated::static_encode(move(context_id), viewport_size, move(window_resize_in_progress)));
        (void)m_connection.post_message(message_buffer);
    }

    void async_set_display_metadata(Web::Compositor::CompositorContextId const& context_id, Optional<u64> const& display_id, double refresh_rate)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::SetDisplayMetadata::static_encode(move(context_id), move(display_id), refresh_rate));
        (void)m_connection.post_message(message_buffer);
    }

    bool handle_mouse_event(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event)
    {
        return m_connection.template send_sync<Messages::CompositorControlServer::HandleMouseEvent>(move(context_id), move(event))->handled();
    }

    void async_handle_mouse_event(Web::Compositor::CompositorContextId const& context_id, Web::MouseEvent const& event)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::HandleMouseEvent::static_encode(move(context_id), move(event)));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_handle_mouse_event(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::CompositorControlServer::HandleMouseEvent>(move(context_id), move(event)))
            return result->handled();
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    bool dispatch_mouse_event_to_web_content(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event)
    {
        return m_connection.template send_sync<Messages::CompositorControlServer::DispatchMouseEventToWebContent>(move(context_id), move(event))->dispatched();
    }

    void async_dispatch_mouse_event_to_web_content(Web::Compositor::CompositorContextId const& context_id, Web::MouseEvent const& event)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::DispatchMouseEventToWebContent::static_encode(move(context_id), move(event)));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_dispatch_mouse_event_to_web_content(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::CompositorControlServer::DispatchMouseEventToWebContent>(move(context_id), move(event)))
            return result->dispatched();
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    bool handle_pinch_event(Web::Compositor::CompositorContextId context_id, Web::PinchEvent event)
    {
        return m_connection.template send_sync<Messages::CompositorControlServer::HandlePinchEvent>(move(context_id), move(event))->handled();
    }

    void async_handle_pinch_event(Web::Compositor::CompositorContextId const& context_id, Web::PinchEvent const& event)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::HandlePinchEvent::static_encode(move(context_id), move(event)));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_handle_pinch_event(Web::Compositor::CompositorContextId context_id, Web::PinchEvent event)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::CompositorControlServer::HandlePinchEvent>(move(context_id), move(event)))
            return result->handled();
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    bool async_scroll_by(Web::Compositor::CompositorContextId context_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels)
    {
        return m_connection.template send_sync<Messages::CompositorControlServer::AsyncScrollBy>(move(context_id), position, delta_in_device_pixels)->handled();
    }

    void async_async_scroll_by(Web::Compositor::CompositorContextId const& context_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::AsyncScrollBy::static_encode(move(context_id), position, delta_in_device_pixels));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_async_scroll_by(Web::Compositor::CompositorContextId context_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::CompositorControlServer::AsyncScrollBy>(move(context_id), position, delta_in_device_pixels))
            return result->handled();
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void async_presented_bitmap_ready_to_paint(Web::Compositor::CompositorContextId const& context_id, i32 bitmap_id)
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::PresentedBitmapReadyToPaint::static_encode(move(context_id), bitmap_id));
        (void)m_connection.post_message(message_buffer);
    }

    void async_crash()
    {
        auto message_buffer = MUST(Messages::CompositorControlServer::Crash::static_encode());
        (void)m_connection.post_message(message_buffer);
    }

private:
    IPC::Connection<LocalEndpoint, PeerEndpoint>& m_connection;
};

template<typename LocalEndpoint, typename PeerEndpoint>
class CompositorControlServerProxy;
class CompositorControlServerStub;

class CompositorControlServerEndpoint {
public:
    template<typename LocalEndpoint>
    using Proxy = CompositorControlServerProxy<LocalEndpoint, CompositorControlServerEndpoint>;
    using Stub = CompositorControlServerStub;

    static u32 static_magic() { return 490619793; }

    static ErrorOr<NonnullOwnPtr<IPC::Message>> decode_message(ReadonlyBytes buffer, [[maybe_unused]] Queue<IPC::Attachment>& attachments)
    {
        FixedMemoryStream stream { buffer };
        auto message_endpoint_magic = TRY(stream.read_value<u32>());

        if (message_endpoint_magic != static_magic())
            return Error::from_string_literal("Endpoint magic number mismatch, not my message!");

        auto message_id = TRY(stream.read_value<i32>());

        switch (message_id) {
        case (int)Messages::CompositorControlServer::MessageID::InitTransport:
            return Messages::CompositorControlServer::InitTransport::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::InitTransportResponse:
            return Messages::CompositorControlServer::InitTransportResponse::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::ConnectWebContent:
            return Messages::CompositorControlServer::ConnectWebContent::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::ConnectWebContentResponse:
            return Messages::CompositorControlServer::ConnectWebContentResponse::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::CreateContext:
            return Messages::CompositorControlServer::CreateContext::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::CreateContextResponse:
            return Messages::CompositorControlServer::CreateContextResponse::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::ViewportSizeUpdated:
            return Messages::CompositorControlServer::ViewportSizeUpdated::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::SetDisplayMetadata:
            return Messages::CompositorControlServer::SetDisplayMetadata::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::HandleMouseEvent:
            return Messages::CompositorControlServer::HandleMouseEvent::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::HandleMouseEventResponse:
            return Messages::CompositorControlServer::HandleMouseEventResponse::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::DispatchMouseEventToWebContent:
            return Messages::CompositorControlServer::DispatchMouseEventToWebContent::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::DispatchMouseEventToWebContentResponse:
            return Messages::CompositorControlServer::DispatchMouseEventToWebContentResponse::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::HandlePinchEvent:
            return Messages::CompositorControlServer::HandlePinchEvent::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::HandlePinchEventResponse:
            return Messages::CompositorControlServer::HandlePinchEventResponse::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::AsyncScrollBy:
            return Messages::CompositorControlServer::AsyncScrollBy::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::AsyncScrollByResponse:
            return Messages::CompositorControlServer::AsyncScrollByResponse::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::PresentedBitmapReadyToPaint:
            return Messages::CompositorControlServer::PresentedBitmapReadyToPaint::decode(stream, attachments);
        case (int)Messages::CompositorControlServer::MessageID::Crash:
            return Messages::CompositorControlServer::Crash::decode(stream, attachments);
        default:
            return Error::from_string_literal("Failed to decode CompositorControlServer message");
        }

        VERIFY_NOT_REACHED();
    }
};

class CompositorControlServerStub : public IPC::Stub {
public:
    CompositorControlServerStub() { }
    virtual ~CompositorControlServerStub() override { }

    virtual u32 magic() const override { return 490619793; }
    virtual ByteString name() const override { return "CompositorControlServer"; }

    virtual ErrorOr<OwnPtr<IPC::MessageBuffer>> handle(NonnullOwnPtr<IPC::Message> message) override
    {
        switch (message->message_id()) {
        case (int)Messages::CompositorControlServer::MessageID::InitTransport:
            return handle_init_transport(*message);
        case (int)Messages::CompositorControlServer::MessageID::ConnectWebContent:
            return handle_connect_web_content();
        case (int)Messages::CompositorControlServer::MessageID::CreateContext:
            return handle_create_context(*message);
        case (int)Messages::CompositorControlServer::MessageID::ViewportSizeUpdated:
            return handle_viewport_size_updated(*message);
        case (int)Messages::CompositorControlServer::MessageID::SetDisplayMetadata:
            return handle_set_display_metadata(*message);
        case (int)Messages::CompositorControlServer::MessageID::HandleMouseEvent:
            return handle_handle_mouse_event(*message);
        case (int)Messages::CompositorControlServer::MessageID::DispatchMouseEventToWebContent:
            return handle_dispatch_mouse_event_to_web_content(*message);
        case (int)Messages::CompositorControlServer::MessageID::HandlePinchEvent:
            return handle_handle_pinch_event(*message);
        case (int)Messages::CompositorControlServer::MessageID::AsyncScrollBy:
            return handle_async_scroll_by(*message);
        case (int)Messages::CompositorControlServer::MessageID::PresentedBitmapReadyToPaint:
            return handle_presented_bitmap_ready_to_paint(*message);
        case (int)Messages::CompositorControlServer::MessageID::Crash:
            return handle_crash();
        default:
            return Error::from_string_literal("Unknown message ID for CompositorControlServer endpoint");
        }
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_init_transport(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::InitTransport&>(message);
        auto response = init_transport(request.peer_pid());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_connect_web_content()
    {
        auto response = connect_web_content();
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_create_context(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::CreateContext&>(message);
        create_context(request.take_context_id(), request.take_page_id(), request.web_content_connection_id());
        auto response = Messages::CompositorControlServer::CreateContextResponse {};
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_viewport_size_updated(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::ViewportSizeUpdated&>(message);
        viewport_size_updated(request.take_context_id(), request.viewport_size(), request.take_window_resize_in_progress());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_set_display_metadata(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::SetDisplayMetadata&>(message);
        set_display_metadata(request.take_context_id(), request.take_display_id(), request.refresh_rate());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_handle_mouse_event(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::HandleMouseEvent&>(message);
        auto response = handle_mouse_event(request.take_context_id(), request.take_event());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_dispatch_mouse_event_to_web_content(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::DispatchMouseEventToWebContent&>(message);
        auto response = dispatch_mouse_event_to_web_content(request.take_context_id(), request.take_event());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_handle_pinch_event(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::HandlePinchEvent&>(message);
        auto response = handle_pinch_event(request.take_context_id(), request.take_event());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_async_scroll_by(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::AsyncScrollBy&>(message);
        auto response = async_scroll_by(request.take_context_id(), request.position(), request.delta_in_device_pixels());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_presented_bitmap_ready_to_paint(IPC::Message& message)
    {
        auto& request = static_cast<Messages::CompositorControlServer::PresentedBitmapReadyToPaint&>(message);
        presented_bitmap_ready_to_paint(request.take_context_id(), request.bitmap_id());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_crash()
    {
        crash();
        return nullptr;
    }

    virtual Messages::CompositorControlServer::InitTransportResponse init_transport(int peer_pid) = 0;
    virtual Messages::CompositorControlServer::ConnectWebContentResponse connect_web_content() = 0;
    virtual void create_context(Web::Compositor::CompositorContextId context_id, Optional<u64> page_id, i32 web_content_connection_id) = 0;
    virtual void viewport_size_updated(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress window_resize_in_progress) = 0;
    virtual void set_display_metadata(Web::Compositor::CompositorContextId context_id, Optional<u64> display_id, double refresh_rate) = 0;
    virtual Messages::CompositorControlServer::HandleMouseEventResponse handle_mouse_event(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event) = 0;
    virtual Messages::CompositorControlServer::DispatchMouseEventToWebContentResponse dispatch_mouse_event_to_web_content(Web::Compositor::CompositorContextId context_id, Web::MouseEvent event) = 0;
    virtual Messages::CompositorControlServer::HandlePinchEventResponse handle_pinch_event(Web::Compositor::CompositorContextId context_id, Web::PinchEvent event) = 0;
    virtual Messages::CompositorControlServer::AsyncScrollByResponse async_scroll_by(Web::Compositor::CompositorContextId context_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels) = 0;
    virtual void presented_bitmap_ready_to_paint(Web::Compositor::CompositorContextId context_id, i32 bitmap_id) = 0;
    virtual void crash() = 0;
};

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic pop
#endif
