1 #ifndef PLUGIN_H 2 #define PLUGIN_H 3 4 #include <functional> 5 #include <memory> 6 #include "wayfire/util.hpp" 7 #include "wayfire/bindings.hpp" 8 9 #include <wayfire/nonstd/wlroots.hpp> 10 11 class wayfire_config; 12 namespace wf 13 { 14 class output_t; 15 16 /** 17 * Plugins can set their capabilities to indicate what kind of plugin they are. 18 * At any point, only one plugin with a given capability can be active on its 19 * output (although multiple plugins with the same capability can be loaded). 20 */ 21 enum plugin_capabilities_t 22 { 23 /** The plugin provides view decorations */ 24 CAPABILITY_VIEW_DECORATOR = 1 << 0, 25 /** The plugin grabs input. 26 * Required in order to use plugin_grab_interface_t::grab() */ 27 CAPABILITY_GRAB_INPUT = 1 << 1, 28 /** The plugin uses custom renderer */ 29 CAPABILITY_CUSTOM_RENDERER = 1 << 2, 30 /** The plugin manages the whole desktop, for ex. switches workspaces. */ 31 CAPABILITY_MANAGE_DESKTOP = 1 << 3, 32 /* Compound capabilities */ 33 34 /** The plugin manages the whole compositor state */ 35 CAPABILITY_MANAGE_COMPOSITOR = CAPABILITY_GRAB_INPUT | 36 CAPABILITY_MANAGE_DESKTOP | CAPABILITY_CUSTOM_RENDERER, 37 }; 38 39 /** 40 * The plugin grab interface is what the plugins use to announce themselves to 41 * the core and other plugins as active, and to request to grab input. 42 */ 43 struct plugin_grab_interface_t 44 { 45 private: 46 bool grabbed = false; 47 48 public: 49 /** The name of the plugin. Not important */ 50 std::string name; 51 /** The plugin capabilities. A bitmask of the values specified above */ 52 uint32_t capabilities; 53 /** The output the grab interface is on */ 54 wf::output_t*const output; 55 56 plugin_grab_interface_t(wf::output_t *_output); 57 58 /** 59 * Grab the input on the output. Requires CAPABILITY_GRAB_INPUT. 60 * On successful grab, core will reset keyboard/pointer/touch focus. 61 * 62 * @return True if input was successfully grabbed. 63 */ 64 bool grab(); 65 /** @return If the grab interface is grabbed */ 66 bool is_grabbed(); 67 /** Ungrab input, if it is grabbed. */ 68 void ungrab(); 69 70 /** 71 * When grabbed, core will redirect all input events to the grabbing plugin. 72 * The grabbing plugin can subscribe to different input events by setting 73 * the callbacks below. 74 */ 75 struct 76 { 77 struct 78 { 79 std::function<void(wlr_event_pointer_axis*)> axis; 80 std::function<void(uint32_t, uint32_t)> button; // button, state 81 std::function<void(int32_t, int32_t)> motion; // x, y 82 std::function<void(wlr_event_pointer_motion*)> relative_motion; 83 } pointer; 84 85 struct 86 { 87 std::function<void(uint32_t, uint32_t)> key; // button, state 88 std::function<void(uint32_t, uint32_t)> mod; // modifier, state 89 } keyboard; 90 91 struct 92 { 93 std::function<void(int32_t, int32_t, int32_t)> down; // id, x, y 94 std::function<void(int32_t)> up; // id 95 std::function<void(int32_t, int32_t, int32_t)> motion; // id, x, y 96 } touch; 97 98 /** 99 * Each plugin might be deactivated forcefully, for example when the 100 * desktop is locked. Plugins MUST honor this signal and exit their 101 * grabs/renderers immediately. 102 * 103 * Note that cancel() is emitted even when the plugin is just activated 104 * without grabbing input. 105 */ 106 std::function<void()> cancel; 107 } callbacks; 108 }; 109 110 using plugin_grab_interface_uptr = std::unique_ptr<plugin_grab_interface_t>; 111 112 class plugin_interface_t 113 { 114 public: 115 /** 116 * The output this plugin is running on. Initialized by core. 117 * Each output has its own set of plugin instances. This way, a plugin 118 * rarely if ever needs to care about multi-monitor setups. 119 */ 120 wf::output_t *output; 121 122 /** 123 * The grab interface of the plugin, initialized by core. 124 */ 125 std::unique_ptr<plugin_grab_interface_t> grab_interface; 126 127 /** 128 * The init method is the entry of the plugin. In the init() method, the 129 * plugin should register all bindings it provides, connect to signals, etc. 130 */ 131 virtual void init() = 0; 132 133 /** 134 * The fini method is called when a plugin is unloaded. It should clean up 135 * all global state it has set (for ex. signal callbacks, bindings, ...), 136 * because the plugin will be freed after this. 137 */ 138 virtual void fini(); 139 140 /** 141 * A plugin can request that it is never unloaded, even if it is removed 142 * from the config's plugin list. 143 * 144 * Note that unloading a plugin is sometimes unavoidable, for ex. when the 145 * output the plugin is running on is destroyed. So non-unloadable plugins 146 * should still provide proper fini() methods. 147 */ is_unloadable()148 virtual bool is_unloadable() 149 { 150 return true; 151 } 152 153 virtual ~plugin_interface_t(); 154 155 /** Handle to the plugin's .so file, used by the plugin loader */ 156 void *handle = NULL; 157 }; 158 } 159 160 /** 161 * Each plugin must provide a function which instantiates the plugin's class 162 * and returns the instance. 163 * 164 * This function must have the name newInstance() and should be declared with 165 * extern "C" so that the loader can find it. 166 */ 167 using wayfire_plugin_load_func = wf::plugin_interface_t * (*)(); 168 169 /** The version of Wayfire's API/ABI */ 170 constexpr uint32_t WAYFIRE_API_ABI_VERSION = 2020'01'24; 171 172 /** 173 * Each plugin must also provide a function which returns the Wayfire API/ABI 174 * that it was compiled with. 175 * 176 * This function must have the name getWayfireVersion() and should be declared 177 * with extern "C" so that the loader can find it. 178 */ 179 using wayfire_plugin_version_func = uint32_t (*)(); 180 181 /** 182 * A macro to declare the necessary functions, given the plugin class name 183 */ 184 #define DECLARE_WAYFIRE_PLUGIN(PluginClass) \ 185 extern "C" \ 186 { \ 187 wf::plugin_interface_t*newInstance() { return new PluginClass; } \ 188 uint32_t getWayfireVersion() { return WAYFIRE_API_ABI_VERSION; } \ 189 } 190 191 #endif 192