clap

CLAP Audio Plugin API
Log | Files | Refs | README | LICENSE

gui.h (9873B)


      1 #pragma once
      2 
      3 #include "../plugin.h"
      4 
      5 /// @page GUI
      6 ///
      7 /// This extension defines how the plugin will present its GUI.
      8 ///
      9 /// There are two approaches:
     10 /// 1. the plugin creates a window and embeds it into the host's window
     11 /// 2. the plugin creates a floating window
     12 ///
     13 /// Embedding the window gives more control to the host, and feels more integrated.
     14 /// Floating window are sometimes the only option due to technical limitations.
     15 ///
     16 /// The Embedding protocol is by far the most common, supported by all hosts to date,
     17 /// and a plugin author should support at least that case.
     18 ///
     19 /// Showing the GUI works as follow:
     20 ///  1. clap_plugin_gui->is_api_supported(), check what can work
     21 ///  2. clap_plugin_gui->create(), allocates gui resources
     22 ///  3. if the plugin window is floating
     23 ///  4.    -> clap_plugin_gui->set_transient()
     24 ///  5.    -> clap_plugin_gui->suggest_title()
     25 ///  6. else
     26 ///  7.    -> clap_plugin_gui->set_scale()
     27 ///  8.    -> clap_plugin_gui->can_resize()
     28 ///  9.    -> if resizable and has known size from previous session, clap_plugin_gui->set_size()
     29 /// 10.    -> else clap_plugin_gui->get_size(), gets initial size
     30 /// 11.    -> clap_plugin_gui->set_parent()
     31 /// 12. clap_plugin_gui->show()
     32 /// 13. clap_plugin_gui->hide()/show() ...
     33 /// 14. clap_plugin_gui->destroy() when done with the gui
     34 ///
     35 /// Resizing the window (initiated by the plugin, if embedded):
     36 /// 1. Plugins calls clap_host_gui->request_resize()
     37 /// 2. If the host returns true the new size is accepted,
     38 ///    the host doesn't have to call clap_plugin_gui->set_size().
     39 ///    If the host returns false, the new size is rejected.
     40 ///
     41 /// Resizing the window (drag, if embedded)):
     42 /// 1. Only possible if clap_plugin_gui->can_resize() returns true
     43 /// 2. Mouse drag -> new_size
     44 /// 3. clap_plugin_gui->adjust_size(new_size) -> working_size
     45 /// 4. clap_plugin_gui->set_size(working_size)
     46 
     47 static CLAP_CONSTEXPR const char CLAP_EXT_GUI[] = "clap.gui";
     48 
     49 // If your windowing API is not listed here, please open an issue and we'll figure it out.
     50 // https://github.com/free-audio/clap/issues/new
     51 
     52 // uses physical size
     53 // embed using https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent
     54 static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WIN32[] = "win32";
     55 
     56 // uses logical size, don't call clap_plugin_gui->set_scale()
     57 static const CLAP_CONSTEXPR char CLAP_WINDOW_API_COCOA[] = "cocoa";
     58 
     59 // uses physical size
     60 // embed using https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
     61 static const CLAP_CONSTEXPR char CLAP_WINDOW_API_X11[] = "x11";
     62 
     63 // uses physical size
     64 // embed is currently not supported, use floating windows
     65 static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WAYLAND[] = "wayland";
     66 
     67 #ifdef __cplusplus
     68 extern "C" {
     69 #endif
     70 
     71 typedef void         *clap_hwnd;
     72 typedef void         *clap_nsview;
     73 typedef unsigned long clap_xwnd;
     74 
     75 // Represent a window reference.
     76 typedef struct clap_window {
     77    const char *api; // one of CLAP_WINDOW_API_XXX
     78    union {
     79       clap_nsview cocoa;
     80       clap_xwnd   x11;
     81       clap_hwnd   win32;
     82       void       *ptr; // for anything defined outside of clap
     83    };
     84 } clap_window_t;
     85 
     86 // Information to improve window resizing when initiated by the host or window manager.
     87 typedef struct clap_gui_resize_hints {
     88    bool can_resize_horizontally;
     89    bool can_resize_vertically;
     90 
     91    // if both horizontal and vertical resize are available, do we preserve the
     92    // aspect ratio, and if so, what is the width x height aspect ratio to preserve.
     93    // These flags are unused if can_resize_horizontally or vertically are false,
     94    // and ratios are unused if preserve is false.
     95    bool     preserve_aspect_ratio;
     96    uint32_t aspect_ratio_width;
     97    uint32_t aspect_ratio_height;
     98 } clap_gui_resize_hints_t;
     99 
    100 // Size (width, height) is in pixels; the corresponding windowing system extension is
    101 // responsible for defining if it is physical pixels or logical pixels.
    102 typedef struct clap_plugin_gui {
    103    // Returns true if the requested gui api is supported, either in floating (plugin-created)
    104    // or non-floating (embedded) mode.
    105    // [main-thread]
    106    bool(CLAP_ABI *is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating);
    107 
    108    // Returns true if the plugin has a preferred api.
    109    // The host has no obligation to honor the plugin preference, this is just a hint.
    110    // The const char **api variable should be explicitly assigned as a pointer to
    111    // one of the CLAP_WINDOW_API_ constants defined above, not strcopied.
    112    // [main-thread]
    113    bool(CLAP_ABI *get_preferred_api)(const clap_plugin_t *plugin,
    114                                      const char         **api,
    115                                      bool                *is_floating);
    116 
    117    // Create and allocate all resources necessary for the gui.
    118    //
    119    // If is_floating is true, then the window will not be managed by the host. The plugin
    120    // can set its window to stays above the parent window, see set_transient().
    121    // api may be null or blank for floating window.
    122    //
    123    // If is_floating is false, then the plugin has to embed its window into the parent window, see
    124    // set_parent().
    125    //
    126    // After this call, the GUI may not be visible yet; don't forget to call show().
    127    //
    128    // Returns true if the GUI is successfully created.
    129    // [main-thread]
    130    bool(CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating);
    131 
    132    // Free all resources associated with the gui.
    133    // [main-thread]
    134    void(CLAP_ABI *destroy)(const clap_plugin_t *plugin);
    135 
    136    // Set the absolute GUI scaling factor, and override any OS info.
    137    // Should not be used if the windowing api relies upon logical pixels.
    138    //
    139    // If the plugin prefers to work out the scaling factor itself by querying the OS directly,
    140    // then ignore the call.
    141    //
    142    // scale = 2 means 200% scaling.
    143    //
    144    // Returns true if the scaling could be applied
    145    // Returns false if the call was ignored, or the scaling could not be applied.
    146    // [main-thread]
    147    bool(CLAP_ABI *set_scale)(const clap_plugin_t *plugin, double scale);
    148 
    149    // Get the current size of the plugin UI.
    150    // clap_plugin_gui->create() must have been called prior to asking the size.
    151    //
    152    // Returns true if the plugin could get the size.
    153    // [main-thread]
    154    bool(CLAP_ABI *get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
    155 
    156    // Returns true if the window is resizeable (mouse drag).
    157    // [main-thread & !floating]
    158    bool(CLAP_ABI *can_resize)(const clap_plugin_t *plugin);
    159 
    160    // Returns true if the plugin can provide hints on how to resize the window.
    161    // [main-thread & !floating]
    162    bool(CLAP_ABI *get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints);
    163 
    164    // If the plugin gui is resizable, then the plugin will calculate the closest
    165    // usable size which fits in the given size.
    166    // This method does not change the size.
    167    //
    168    // Returns true if the plugin could adjust the given size.
    169    // [main-thread & !floating]
    170    bool(CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
    171 
    172    // Sets the window size.
    173    //
    174    // Returns true if the plugin could resize its window to the given size.
    175    // [main-thread & !floating]
    176    bool(CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height);
    177 
    178    // Embeds the plugin window into the given window.
    179    //
    180    // Returns true on success.
    181    // [main-thread & !floating]
    182    bool(CLAP_ABI *set_parent)(const clap_plugin_t *plugin, const clap_window_t *window);
    183 
    184    // Set the plugin floating window to stay above the given window.
    185    //
    186    // Returns true on success.
    187    // [main-thread & floating]
    188    bool(CLAP_ABI *set_transient)(const clap_plugin_t *plugin, const clap_window_t *window);
    189 
    190    // Suggests a window title. Only for floating windows.
    191    //
    192    // [main-thread & floating]
    193    void(CLAP_ABI *suggest_title)(const clap_plugin_t *plugin, const char *title);
    194 
    195    // Show the window.
    196    //
    197    // Returns true on success.
    198    // [main-thread]
    199    bool(CLAP_ABI *show)(const clap_plugin_t *plugin);
    200 
    201    // Hide the window, this method does not free the resources, it just hides
    202    // the window content. Yet it may be a good idea to stop painting timers.
    203    //
    204    // Returns true on success.
    205    // [main-thread]
    206    bool(CLAP_ABI *hide)(const clap_plugin_t *plugin);
    207 } clap_plugin_gui_t;
    208 
    209 typedef struct clap_host_gui {
    210    // The host should call get_resize_hints() again.
    211    // [thread-safe & !floating]
    212    void(CLAP_ABI *resize_hints_changed)(const clap_host_t *host);
    213 
    214    // Request the host to resize the client area to width, height.
    215    // Return true if the new size is accepted, false otherwise.
    216    // The host doesn't have to call set_size().
    217    //
    218    // Note: if not called from the main thread, then a return value simply means that the host
    219    // acknowledged the request and will process it asynchronously. If the request then can't be
    220    // satisfied then the host will call set_size() to revert the operation.
    221    // [thread-safe & !floating]
    222    bool(CLAP_ABI *request_resize)(const clap_host_t *host, uint32_t width, uint32_t height);
    223 
    224    // Request the host to show the plugin gui.
    225    // Return true on success, false otherwise.
    226    // [thread-safe]
    227    bool(CLAP_ABI *request_show)(const clap_host_t *host);
    228 
    229    // Request the host to hide the plugin gui.
    230    // Return true on success, false otherwise.
    231    // [thread-safe]
    232    bool(CLAP_ABI *request_hide)(const clap_host_t *host);
    233 
    234    // The floating window has been closed, or the connection to the gui has been lost.
    235    //
    236    // If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge
    237    // the gui destruction.
    238    // [thread-safe]
    239    void(CLAP_ABI *closed)(const clap_host_t *host, bool was_destroyed);
    240 } clap_host_gui_t;
    241 
    242 #ifdef __cplusplus
    243 }
    244 #endif