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