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