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