// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
 * \title Custom Extension
 * \example custom-extension
 * \examplecategory {Embedded}
 * \brief Custom Extension shows how to implement a custom Wayland extension.
 * \ingroup qtwaylandcompositor-examples
 *
 * It's easy to write new extensions for Wayland. They are defined using a XML-based format and
 * the \c wayland-scanner tool converts this to glue code in C. Qt expands on this with the
 * \c qtwaylandscanner, which generates additional glue code in Qt and C++.
 *
 * \image custom-extension.png
 *
 * The Custom Extension example shows how to use these tools to extend the Wayland protocol and
 * send custom requests and events between a Wayland client and a server.
 *
 * The example consists of four items:
 * \list
 *   \li The definition of the protocol itself.
 *   \li A compositor that supports the extension.
 *   \li A C++-based client that supports the extension.
 *   \li A QML-based client that supports the extension.
 * \endlist
 *
 * \section1 The Protocol Definition
 *
 * The XML file \c custom.xml defines the protocol. It contains an interface called
 * "qt_example_extension". This is the name which will be broadcast from the server and which the
 * client will attach to in order to send requests and receive events. This name should be unique,
 * so it is good to use a prefix that sets it apart from official interfaces.
 *
 * An interface typically consists of two types of remote procedure calls:
 * \e requests and \e events. "Requests" are calls the client makes on the server-side, and
 * "events" are calls the server makes on the client-side.
 *
 * The example extension contains a set of \e requests which instructs the server to apply certain
 * transforms to the client window. For instance, if the client sends a "bounce" request, then the
 * server should respond to this by making the window bounce on the screen.
 *
 * Similarly, it has a set of \e events which the server can use to provide instructions for the
 * client. For instance, the "set_font_size" event is an instruction for the client to set its
 * default font size to a specific size.
 *
 * The protocol defines the existence of requests and events, as well as the arguments they
 * take. When \c qtwaylandscanner is run on it, it will generate the code needed to marshall the
 * procedure call and its arguments and to transmit this over the connection. On the other end, this
 * becomes a call to a virtual function which can be implemented to provide the actual response.
 *
 * In order to have \c qtwaylandscanner run automatically as part of the build, we use the
 * CMake functions \c qt6_generate_wayland_protocol_server_sources() and
 * \c qt6_generate_wayland_protocol_client_sources() for generating the server-side and
 * client-side glue code, respectively. (When using \c qmake, the \c WAYLANDSERVERSOURCES and
 * \c WAYLANDCLIENTSOURCES variables achieve the same.)
 *
 * \section1 The Compositor Implementation
 *
 * The Compositor application itself is implemented using QML and Qt Quick, but the extension is
 * implemented in C++.
 *
 * The first step is to create a subclass of the glue code generated by \c qtwaylandscanner so
 * that we can access its functionality. We add the \l QML_ELEMENT macro to the class in order to
 * make it accessible from QML.
 *
 * \snippet custom-extension/compositor/customextension.h CustomExtension
 *
 * In addition to inheriting from the generated class, we also inherit the class
 * \l QWaylandCompositorExtensionTemplate which provides some additional convenience when dealing
 * with extensions, using the
 * l{https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern}{Curiously Recurring Template Pattern}.
 *
 * Note that the \l QWaylandCompositorExtensionTemplate must be first in the inheritance list, since
 * it is a \l{QObject}-based class.
 *
 * The subclass has re-implementations of virtual functions in the generated base class, where
 * we can handle requests issued by a client.
 *
 * \snippet custom-extension/compositor/customextension.h example_extension_bounce
 *
 * In these re-implementations, we simply translate the request to a \e signal emission, so that we
 * can handle it in the actual QML code of the compositor.
 *
 * \snippet custom-extension/compositor/customextension.cpp example_extension_bounce
 *
 * In addition, the subclass defines \e slots for each of the events, so that these can be either
 * called from QML or be connected to signals. The slots simply call the generated functions which
 * send the events to the client.
 *
 * \snippet custom-extension/compositor/customextension.cpp setFontSize
 *
 * Since we added the \l QML_ELEMENT macro to the class definition (and added the corresponding
 * build steps to the build system files), it can be instantiated in QML.
 *
 * We make it a direct child of the \l WaylandCompositor object in order for the compositor to
 * register it as an extension.
 *
 * \snippet custom-extension/compositor/qml/main.qml CustomExtension
 *
 * The object has signal handlers for the requests it may get from the client and reacts to them
 * accordingly. In addition, we can call its slots to send events.
 *
 * \snippet custom-extension/compositor/qml/main.qml setFontSize
 *
 * \section1 The C++ Client Implementation
 *
 * Both clients share the C++ implementation of the interface. Like in the compositor, we make
 * a subclass of the generated code which also inherits from a template class. In this case,
 * we inherit QWaylandClientExtensionTemplate.
 *
 * \snippet custom-extension/client-common/customextension.h CustomExtension
 *
 * The approach is very similar to that of the compositor, except inverted: Requests are implemented
 * as slots which call the generated functions, and events virtual functions which we re-implement
 * to emit signals.
 *
 * \snippet custom-extension/client-common/customextension.cpp sendBounce
 *
 * The client code itself is very simple and only intended to show how to trigger the behavior. In
 * a custom paint event, it draws a set of rectangles and labels. When any of these are clicked, it
 * issues requests to the server.
 *
 * \snippet custom-extension/cpp-client/main.cpp mousePressEvent
 *
 * To update the font size when the \c set_font_size event is received, the signal in our extension
 * class is connected to a slot.
 *
 * \snippet custom-extension/cpp-client/main.cpp connection
 *
 * The slot will update the font size and repaint the window.
 *
 * \section1 The QML Client Implementation
 *
 * The QML client is similar to the C++ client. It relies on the same implementation of the custom
 * extension as the C++ client, and instantiates this in QML to enable it.
 *
 * \snippet custom-extension/qml-client/main.qml CustomExtension
 *
 * The UI consists of some clickable rectangles, and uses \l TapHandler to send the corresponding
 * requests when a rectangle is clicked.
 *
 * \snippet custom-extension/qml-client/main.qml sendBounce
 *
 * For simplicity, the example has been limited to only demonstrate the \c bounce and \c spin
 * requests as well as the \c set_font_size event. Adding support for the additional features is
 * left as an exercise for the reader.
 */
