summaryrefslogtreecommitdiff
path: root/pages
diff options
context:
space:
mode:
authorXavi Artigas <xavierartigas@yahoo.es>2018-09-04 00:48:04 -0700
committerapache <apache@e5-web1.enlightenment.org>2018-09-04 00:48:04 -0700
commitf155c85bdde11597686ebdd0db4867037e82beb3 (patch)
tree6d44c592d6cbeb0f59548769dd50a2377ea06c3a /pages
parent062e87acbe12265271fac65526d67ce45c86e2c3 (diff)
Wiki page sandbox_gadgets.md changed with summary [Moved to proper place in Legacy Programming Guides] by Xavi Artigas
Diffstat (limited to 'pages')
-rw-r--r--pages/develop/legacy/program_guide/sandbox_gadgets.md.txt651
1 files changed, 651 insertions, 0 deletions
diff --git a/pages/develop/legacy/program_guide/sandbox_gadgets.md.txt b/pages/develop/legacy/program_guide/sandbox_gadgets.md.txt
new file mode 100644
index 000000000..2c58f4908
--- /dev/null
+++ b/pages/develop/legacy/program_guide/sandbox_gadgets.md.txt
@@ -0,0 +1,651 @@
1---
2~~Title: Creating Enlightenment Gadgets~~
3---
4
5# Creating Enlightenment Gadgets #
6**The code blocks in this guide are not intended to be compiled separately or work individually. They are meant to be used as a visual reference of the changes that need to be made to make an EFL application a gadget. The final code block, along with the accompanying .desktop file and meson.build at the end of this page are the intended files to use if you would like to compile and install this example as a gadget.**
7
8*Gadgets* are standalone applications that Enlightenment can use as extensions to its desktop. They are similar to modules in that they can be placed in containers, called *gadget sites*; they differ in that they are not internal to Enlightenment and do not run in the same process.
9
10This process separation occurs through Enlightenment placing gadgets into a sandbox. This sandbox is a gadget visual that manages the necessary gadget requirements, in place of the application handling this. Sandboxing is beneficial to the user desktop experience as it encourages the creation of gadgets through a much easier development path while also protecting the user desktop experience from being interrupted by faulty extensions.
11
12This guide demonstrates how to develop these gadgets.
13
14## Prerequisites ##
15
16* Install and configure Enlightenment and the EFL with Wayland support: [Get Enlightenment](http://www.enlightenment.org/docs/distros/start).
17* Create the Hello World program: [Get started with EFL](http://www.enlightenment.org/develop/efl/start)
18
19## Gadget Advantages and Limitations ##
20
21Creating gadgets directly, rather than as modules, reduces the need to call upon additional application programming interfaces (APIs). Gadgets are also more robust: as gadgets run in a separate process from Enlightenment they will not crash the desktop when encountering an error, instead gracefully recovering from their own crashes.
22
23There are, however, a few limitations for gadgets. It is not recommended to use forced sizes or size hints in the gadget application. The sandbox will manage sizing for the application; setting minimum or maximum sizes, resizing or moving objects will clash with how the sandbox is managing sizes. Simply setting the desired aspect for the application will tell the sandbox how it needs to prioritize the size of the application.
24
25Running additional applications from within the gadget application will also bring unintended results. The gadget lives in a sandbox and is bound by the size and space that the sandbox provides. If the gadget tries to open further windows or applications on its own these windows and applications will be restricted to the gadget visual. Fortunately, the sandbox provides smart callbacks than can be called to run external applications and also provides a method for opening further windows or popups within the gadget application.
26
27## Gadget Basics ##
28
29Enlightenment populates its list of gadgets by looking for ``.desktop`` files installed to the directory ``enlightenment/gadgets`` under Enlightenment's library directory, which can be found using ``pkg-config --variable=libdir enlightenment``. This gadget list is then made available for use through each gadget site's "Add Gadgets" popup. These popups display either a live view of the gadget or a still image.
30
31When Enlightenment executes the gadget application it sets the environment variable ``E_GADGET_ID``. This environmental variable is how the gadget application will determine if it is being run as a gadget, if it is being displayed in the "Add Gadget" popup or if it has been added to a gadget site and has a unique gadget ID. The environment variable ``E_GADGET_ORIENTATION`` is also set. It will be equal to one of three values. ``Horizontal`` ``Vertical`` or ``None`` and will indicate whether the gadget is being placed in a container that will layout its children horizontally, vertically, or neither. For the purpose of this example, this environment variable is not used.
32
33To demonstrate this, a modified version of the Hello World app referenced in the Prerequisites section of this guide is used. Note the following important change: in the original version the window is created using ``elm_win_util_standard_add()``, but in order to achieve transparency on the window for use as a gadget this is changed to ``elm_win_add()`` in this guide.
34
35In the ``elm_main()`` function the application can check for the ``E_GADGET_ID`` with the following code:
36
37```c
38EAPI_MAIN int
39elm_main(int argc, char **argv)
40{
41 Evas_Object *win, *btn, *icon;
42 int gadget =0, id_num = 0;
43 char buf[16];
44
45 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
46
47 if (getenv("E_GADGET_ID"))
48 {
49 gadget = 1;
50 snprintf(buf, sizeof(buf), "%s", getenv("E_GADGET_ID"));
51 id_num = atoi(buf);
52 }
53
54 win = elm_win_add(NULL, "Main", ELM_WIN_BASIC);
55 elm_win_title_set(win, "Hello, World!");
56 elm_win_autodel_set(win, EINA_TRUE);
57
58 if (gadget) elm_win_alpha_set(win, EINA_TRUE);
59
60 if (gadget && id_num == -1)
61 {
62 icon = elm_icon_add(win);
63 elm_icon_standard_set(icon, "start-here");
64 evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
65 evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
66 elm_win_resize_object_add(win, icon);
67 evas_object_show(icon);
68 }
69 else
70 {
71 btn = elm_button_add(win);
72 elm_object_text_set(btn, "Goodbye Cruel World");
73 elm_win_resize_object_add(win, btn);
74 evas_object_smart_callback_add(btn, "clicked", on_click, win);
75 evas_object_show(btn);
76 }
77 evas_object_show(win);
78
79 elm_run();
80
81 return 0;
82}
83```
84
85The variable ``gadget`` is used to determine if the application is running as a gadget or as a standalone application. The variable ``id_num`` is used to identify the ID of the gadget, if the application is indeed running as a gadget. If the application is running as a gadget, the window is set to alpha so that the background of the window does not show up. This is for aesthetics purposes so that gadgets on gadget sites don't all have a background.
86
87If the id of the gadget is ``-1`` the application is being run in the "Add Gadget" popup. In this case the application displays an icon. If the ID of the gadget is not ``-1`` the application is being run as a gadget in a gadget site and the ID will be unique to this gadget. This is important for complex gadgets where the application would like to save settings or configurations and have them loaded after restarts. This unique ID is how the application will identify which settings to load.
88
89## Gadget Events and Smart Callbacks ##
90
91Gadget applications will receive the following smart callbacks on their main window using ``evas_object_smart_callback_add(application_window, smart_callback_type, function, data)``:
92
93* ``gadget_action`` - There was an error with the gadget action.
94* ``gadget_action_deleted`` - The gadget action has been deleted.
95* ``gadget_action_end`` - The gadget action has ended.
96* ``gadget_configure`` - The configure menu item of the gadget has been clicked.
97* ``gadget_site_anchor`` - The position of the gadget has changed.
98* ``gadget_site_gravity`` - The gravity of the gadget has changed.
99* ``gadget_site_orient`` - The orientation of the gadget has changed.
100
101Gadget applications can call the following smart callbacks on their main window using ``evas_object_smart_callback_call(application_window, smart_callback_type, data)``:
102
103* ``gadget_action_request`` - This requests that the gadget sets up an action. The data on this call should be the action name.
104* ``gadget_open_uri`` - This requests the gadget to open an application that handles a uri. The data on this call should be the uri.
105
106You can call actions you set up via the ``evas_object_smart_callback_call(application_window, action, action_data)`` function.
107
108For more advanced purposes beyond the scope of this gadget introduction, it is worth noting that you can set an ecore event handler for ``ECORE_EVENT_SIGNAL_USER`` and the handler will be called when the user requests the gadget be removed. Inside of the handler, the user number will be equal to 2 if the user requested the gadget be removed.
109
110For the purpose of the Hello World gadget, a label detailing the anchor position and orientation of the gadget can be displayed using the following code:
111
112```c
113#include <Elementary.h>
114#include <e_gadget_types.h>
115
116static E_Gadget_Site_Orient gorient;
117static E_Gadget_Site_Anchor ganchor;
118
119static void
120update_anchor_orient(void *data, E_Gadget_Site_Orient orient, E_Gadget_Site_Anchor anchor)
121{
122 char buf[4096];
123 const char *s = "float";
124 Evas_Object *lbl = data;
125
126 if (anchor & E_GADGET_SITE_ANCHOR_LEFT)
127 {
128 if (anchor & E_GADGET_SITE_ANCHOR_TOP)
129 {
130 switch (orient)
131 {
132 case E_GADGET_SITE_ORIENT_HORIZONTAL:
133 s = "top_left";
134 break;
135 case E_GADGET_SITE_ORIENT_VERTICAL:
136 s = "left_top";
137 break;
138 case E_GADGET_SITE_ORIENT_NONE:
139 s = "left_top";
140 break;
141 }
142 }
143 else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
144 {
145 switch (orient)
146 {
147 case E_GADGET_SITE_ORIENT_HORIZONTAL:
148 s = "bottom_left";
149 break;
150 case E_GADGET_SITE_ORIENT_VERTICAL:
151 s = "left_bottom";
152 break;
153 case E_GADGET_SITE_ORIENT_NONE:
154 s = "left_bottom";
155 break;
156 }
157 }
158 else
159 s = "left";
160 }
161 else if (anchor & E_GADGET_SITE_ANCHOR_RIGHT)
162 {
163 if (anchor & E_GADGET_SITE_ANCHOR_TOP)
164 {
165 switch (orient)
166 {
167 case E_GADGET_SITE_ORIENT_HORIZONTAL:
168 s = "top_right";
169 break;
170 case E_GADGET_SITE_ORIENT_VERTICAL:
171 s = "right_top";
172 break;
173 case E_GADGET_SITE_ORIENT_NONE:
174 s = "right_top";
175 break;
176 }
177 }
178 else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
179 {
180 switch (orient)
181 {
182 case E_GADGET_SITE_ORIENT_HORIZONTAL:
183 s = "bottom_right";
184 break;
185 case E_GADGET_SITE_ORIENT_VERTICAL:
186 s = "right_bottom";
187 break;
188 case E_GADGET_SITE_ORIENT_NONE:
189 s = "right_bottom";
190 break;
191 }
192 }
193 else
194 s = "right";
195 }
196 else if (anchor & E_GADGET_SITE_ANCHOR_TOP)
197 s = "top";
198 else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
199 s = "bottom";
200 else
201 {
202 switch (orient)
203 {
204 case E_GADGET_SITE_ORIENT_HORIZONTAL:
205 s = "horizontal";
206 break;
207 case E_GADGET_SITE_ORIENT_VERTICAL:
208 s = "vertical";
209 break;
210 default: break;
211 }
212 }
213 snprintf(buf, sizeof(buf), "e,state,orientation,%s", s);
214 elm_object_text_set(lbl, buf);
215}
216
217static void
218anchor_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
219{
220 ganchor = (uintptr_t)event_info;
221 update_anchor_orient(data, gorient, ganchor);
222}
223
224static void
225orient_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
226{
227 gorient = (uintptr_t)event_info;
228 update_anchor_orient(data, gorient, ganchor);
229}
230
231static void
232on_click(void *data, Evas_Object *obj, void *event_info)
233{
234 evas_object_del(data);
235}
236
237EAPI_MAIN int
238elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
239{
240 Evas_Object *win, *box, *lbl, *icon, *btn;
241 int gadget =0, id_num = 0;
242 char buf[16];
243
244 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
245
246 if (getenv("E_GADGET_ID"))
247 {
248 gadget = 1;
249 snprintf(buf, sizeof(buf), "%s", getenv("E_GADGET_ID"));
250 id_num = atoi(buf);
251 }
252
253 win = elm_win_add(NULL, "Main", ELM_WIN_BASIC);
254 elm_win_title_set(win, "Hello, World!");
255 elm_win_autodel_set(win, EINA_TRUE);
256
257 if (gadget) elm_win_alpha_set(win, EINA_TRUE);
258
259 box = elm_box_add(win);
260 elm_box_horizontal_set(box, EINA_FALSE);
261 evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
262 evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
263 elm_win_resize_object_add(win, box);
264 evas_object_show(box);
265
266 if (gadget && id_num == -1)
267 {
268 icon = elm_icon_add(box);
269 elm_icon_standard_set(icon, "start-here");
270 evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
271 evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
272 elm_box_pack_end(box, icon);
273 evas_object_show(icon);
274 }
275 else
276 {
277 lbl = elm_label_add(box);
278 evas_object_size_hint_weight_set(lbl, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
279 elm_box_pack_end(box, lbl);
280 evas_object_show(lbl);
281
282 btn = elm_button_add(box);
283 elm_object_text_set(btn, "Goodbye Cruel World");
284 elm_box_pack_end(box, btn);
285 evas_object_smart_callback_add(btn, "clicked", on_click, win);
286 evas_object_show(btn);
287 }
288 if (gadget && id_num > -1)
289 {
290 evas_object_smart_callback_add(win, "gadget_site_anchor", anchor_change, lbl);
291 evas_object_smart_callback_add(win, "gadget_site_orient", orient_change, lbl);
292 }
293 evas_object_show(win);
294
295 elm_run();
296
297 return 0;
298}
299ELM_MAIN()
300```
301
302Two smart callbacks are added if the application is in gadget mode, and a new ``#include`` was added for ``e_gadget_types.h``. This header gives the anchor and orientation enumerations that are needed to describe the position of the gadget. These enumerations consist of ``E_GADGET_SITE_ANCHOR_*`` and ``E_GADGET_SITE_ORIENT_*``. The anchor sites are ``TOP``, ``BOTTOM``, ``LEFT``, and ``RIGHT`` and describe the position on the screen edge where the gadget is to be located.
303
304The orientation of the site is ``HORIZONTAL``, ``VERTICAL`` or ``NONE`` and describe the layout of the gadget site. Since gadget sites can have multiple gadgets this is important for noting that gadgets are going to be stacked horizontally or vertically. The ``NONE`` orientation is used when the gadget site is the desktop, which doesn't have a defined orientation.
305
306## Displaying Popups and Additional Windows in Gadgets ##
307
308In the limitations section of this guide the problem with spawning popups and windows directly from the gadget were outlined. The sandbox, however, will take new windows that are spawned and show them as popups or ``ctxpopups`` based on the window type. If the window type is set to ``ELM_WIN_BASIC`` an ``elm_popup`` will be used. If the window type is set to ``ELM_WIN_POPUP_MENU`` a ``ctxpopup`` will be used. These windows will then be rendered outside of the gadget's visual.
309
310In the original Hello World application a callback exists to close the window when the button is clicked. Gadgets, however, are designed to be persistent and not close in that manner. For the purposes of this example, the callback is changed to create a popup.
311
312```c
313#include <Elementary.h>
314#include <e_gadget_types.h>
315
316static E_Gadget_Site_Orient gorient;
317static E_Gadget_Site_Anchor ganchor;
318static Evas_Object *popup;
319
320static void
321popup_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
322{
323 evas_object_del(obj);
324}
325
326static void
327on_click(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
328{
329 Evas_Object *win = data, *box, *lbl;
330
331 if (popup)
332 {
333 evas_object_del(popup);
334 popup = NULL;
335 return;
336 }
337 popup = elm_win_add(win, "Popup", ELM_WIN_BASIC);
338 elm_win_alpha_set(popup, 1);
339 evas_object_event_callback_add(popup, EVAS_CALLBACK_HIDE, popup_del, NULL);
340
341 box = elm_box_add(popup);
342 elm_box_horizontal_set(box, EINA_FALSE);
343 evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
344 evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
345 elm_win_resize_object_add(popup, box);
346 evas_object_show(box);
347
348 lbl = elm_label_add(box);
349 elm_object_text_set(lbl, "Goodbye Cruel World!");
350 evas_object_size_hint_weight_set(lbl, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
351 elm_box_pack_end(box, lbl);
352 evas_object_show(lbl);
353
354 evas_object_show(popup);
355}
356
357static void
358update_anchor_orient(void *data, E_Gadget_Site_Orient orient, E_Gadget_Site_Anchor anchor)
359{
360 char buf[4096];
361 const char *s = "float";
362 Evas_Object *lbl = data;
363
364 if (anchor & E_GADGET_SITE_ANCHOR_LEFT)
365 {
366 if (anchor & E_GADGET_SITE_ANCHOR_TOP)
367 {
368 switch (orient)
369 {
370 case E_GADGET_SITE_ORIENT_HORIZONTAL:
371 s = "top_left";
372 break;
373 case E_GADGET_SITE_ORIENT_VERTICAL:
374 s = "left_top";
375 break;
376 case E_GADGET_SITE_ORIENT_NONE:
377 s = "left_top";
378 break;
379 }
380 }
381 else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
382 {
383 switch (orient)
384 {
385 case E_GADGET_SITE_ORIENT_HORIZONTAL:
386 s = "bottom_left";
387 break;
388 case E_GADGET_SITE_ORIENT_VERTICAL:
389 s = "left_bottom";
390 break;
391 case E_GADGET_SITE_ORIENT_NONE:
392 s = "left_bottom";
393 break;
394 }
395 }
396 else
397 s = "left";
398 }
399 else if (anchor & E_GADGET_SITE_ANCHOR_RIGHT)
400 {
401 if (anchor & E_GADGET_SITE_ANCHOR_TOP)
402 {
403 switch (orient)
404 {
405 case E_GADGET_SITE_ORIENT_HORIZONTAL:
406 s = "top_right";
407 break;
408 case E_GADGET_SITE_ORIENT_VERTICAL:
409 s = "right_top";
410 break;
411 case E_GADGET_SITE_ORIENT_NONE:
412 s = "right_top";
413 break;
414 }
415 }
416 else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
417 {
418 switch (orient)
419 {
420 case E_GADGET_SITE_ORIENT_HORIZONTAL:
421 s = "bottom_right";
422 break;
423 case E_GADGET_SITE_ORIENT_VERTICAL:
424 s = "right_bottom";
425 break;
426 case E_GADGET_SITE_ORIENT_NONE:
427 s = "right_bottom";
428 break;
429 } }
430 else
431 s = "right";
432 }
433 else if (anchor & E_GADGET_SITE_ANCHOR_TOP)
434 s = "top";
435 else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
436 s = "bottom";
437 else
438 {
439 switch (orient)
440 {
441 case E_GADGET_SITE_ORIENT_HORIZONTAL:
442 s = "horizontal";
443 break;
444 case E_GADGET_SITE_ORIENT_VERTICAL:
445 s = "vertical";
446 break;
447 default: break;
448 }
449 }
450 snprintf(buf, sizeof(buf), "e,state,orientation,%s", s);
451 elm_object_text_set(lbl, buf);
452}
453
454static void
455anchor_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
456{
457 ganchor = (uintptr_t)event_info;
458 update_anchor_orient(data, gorient, ganchor);
459}
460
461static void
462orient_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
463{
464 gorient = (uintptr_t)event_info;
465 update_anchor_orient(data, gorient, ganchor);
466}
467
468EAPI_MAIN int
469elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
470{
471 Evas_Object *win, *box, *lbl, *icon, *btn;
472 int gadget = 0, id_num = 0;
473 char buf[16];
474
475 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
476
477 if (getenv("E_GADGET_ID"))
478 {
479 gadget = 1;
480 snprintf(buf, sizeof(buf), "%s", getenv("E_GADGET_ID"));
481 id_num = atoi(buf);
482 }
483
484 win = elm_win_add(NULL, "Main", ELM_WIN_BASIC);
485 elm_win_title_set(win, "Hello, World!");
486 elm_win_autodel_set(win, EINA_TRUE);
487
488 if (gadget) elm_win_alpha_set(win, EINA_TRUE);
489
490 box = elm_box_add(win);
491 elm_box_horizontal_set(box, EINA_FALSE);
492 evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
493 evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
494 elm_win_resize_object_add(win, box);
495 evas_object_show(box);
496
497 if (gadget && id_num == -1)
498 {
499 icon = elm_icon_add(box);
500 elm_icon_standard_set(icon, "start-here");
501 evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
502 evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
503 elm_box_pack_end(box, icon);
504 evas_object_show(icon);
505 }
506 else
507 {
508 lbl = elm_label_add(box);
509 evas_object_size_hint_weight_set(lbl, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
510 elm_box_pack_end(box, lbl);
511 evas_object_show(lbl);
512
513 btn = elm_button_add(box);
514 elm_object_text_set(btn, "This is a popup");
515 elm_box_pack_end(box, btn);
516 evas_object_smart_callback_add(btn, "clicked", on_click, win);
517 evas_object_show(btn);
518 }
519 if (gadget && id_num > -1)
520 {
521 evas_object_smart_callback_add(win, "gadget_site_anchor", anchor_change, lbl);
522 evas_object_smart_callback_add(win, "gadget_site_orient", orient_change, lbl);
523 }
524 evas_object_show(win);
525
526 elm_run();
527
528 return 0;
529}
530ELM_MAIN()
531```
532
533The ``on_clicked`` function has been changed from the original Hello World application to show a popup that says "This is a popup". If the popup already exists, clicking the gadget closes the popup.
534
535The ``popup_del`` function has been added to make sure when the gadget popup is hidden it is properly destroyed.
536
537## Installing Gadgets ##
538
539Create the following three files, all in the same directory:
540
541* meson.build
542* helloworld.desktop.in
543* helloworld.c
544
545"helloworld.c" must contain the example code provided earlier in this guide.
546
547Create "helloworld.desktop.in" with the following contents:
548
549```
550[Desktop Entry]
551Type=Application
552Name=helloworld
553Exec=@GADGET_DIR@/helloworld/e_gadget_helloworld
554Icon=start-here
555X-Gadget-Version=1.0
556X-Gadget-Bugreport=https://www.enlightenment.org/contrib/report-bug
557```
558Note the required line ``X-Gadget-Version`` must be there for Enlightenment to recognize the gadget.
559
560You can also specify if you want your gadget to only be accessible to horizontal, vertical, or desktop layouts by using the following line in the "helloworld.desktop.in" file:
561```
562X-Gadget-Orientation=None,Horizontal,Vertical
563```
564
565Create "meson.build" with the following contents:
566
567```
568project('helloworld', 'c',
569 version: '1',
570 license: 'BSD 2 clause',
571 default_options: [ 'c_std=gnu99', 'warning_level=2' ],
572 meson_version: '>= 0.40.0')
573pkgconfig = import('pkgconfig')
574cc = meson.get_compiler('c')
575
576dep_e = dependency('enlightenment')
577deps = [
578 dep_e,
579 dependency('elementary')
580]
581release = dep_e.get_pkgconfig_variable('release')
582host_os = host_machine.system()
583if host_os == 'linux'
584 if cc.has_header_symbol('features.h', '__UCLIBC__')
585 host_os = 'linux-uclibc'
586 elif cc.has_header_symbol('features.h', '__dietlibc__')
587 host_os = 'linux-dietlibc'
588 else
589 host_os = 'linux-gnu'
590 endif
591endif
592module_arch = '@0@-@1@-@2@'.format(host_os, host_machine.cpu_family(), release)
593dir_prefix = get_option('prefix')
594dir_lib = join_paths(dir_prefix, get_option('libdir'))
595dir_gadgets = join_paths([dir_lib, 'enlightenment/gadgets', module_arch])
596build_files = [
597 'helloworld.c'
598]
599executable('e_gadget_helloworld',
600 build_files,
601 dependencies: deps,
602 c_args : ['-fPIE', '-fPIC'],
603 link_args : ['-rdynamic', '-pie'],
604 install_dir: join_paths([dir_gadgets, 'helloworld']),
605 install: true)
606
607desktop_data = configuration_data()
608 desktop_data.set('GADGET_DIR', dir_gadgets)
609configure_file(input: 'helloworld.desktop.in',
610 output: 'helloworld.desktop',
611 install: true,
612 install_dir: join_paths([dir_gadgets, 'helloworld']),
613 configuration: desktop_data)
614```
615This "meson.build" file determines the location Enlightenment will look for gadgets. This location is Enlightenment's library folder, followed by a sub directory string consisting of "gadgets/os-processor-enlightenmentversion". Once the location is determined, the meson file will install the "helloworld" binary and "helloworld.desktop" files to that location. Keep in mind when installing the ".desktop" file to Enlightenment's gadget directory that the file must have the same name as the directory to which it is being installed. In this case that is "helloworld/helloworld.desktop". Remember that the desktop is the crucial part of sandbox gadgets, as it is the means by which Enlightenment determines available gadgets. Enlightenment can only determine the location of gadgets by looking in its library directory. Note these two lines in the executable section of the meson.build are required:
616```
617 c_args : ['-fPIE', '-fPIC'],
618 link_args : ['-rdynamic', '-pie'],
619```
620
621Run the following commands in order, from the directory where you placed the three files, to install the gadget:
622
623```bash
624meson build && cd build
625ninja
626sudo ninja install
627```
628
629## Conclusion ##
630The "helloworld" gadget is now installed and can be placed on a gadget site. To place it on a Bryce, hold the Alt key and right-click the Bryce then click "Gadgets". To place it on the desktop, left-click the desktop, click "Desktop" then click "Add Gadgets to Desktop".
631
632Remember that gadgets are standalone, so the "helloworld" gadget can be run as a standalone application simply by directly executing the installed binary.
633
634The essentials for Enlightenment gadgets are follows:
635
636* Enlightenment sets an environment variable with a unique ID for gadgets.
637* Enlightenment determines available gadgets based on identified ".desktop" files in the Enlightenment gadget folder.
638* Gadget communication with the application is two-way and occurs through the use of smart callbacks.
639
640## Further Reading ##
641[Ephoto](http://git.enlightenment.org/apps/ephoto)
642: Ephoto, an application used as both a standalone app and a gadget.
643
644[Wireless Gadget](http://git.enlightenment.org/enlightenment/gadgets/wireless)
645: Source code for the Enlightenment Wireless Gadget.
646
647[Meson](http://mesonbuild.com/Reference-manual.html)
648: Meson documentation.
649
650[FDO Desktop Entry](https://standards.freedesktop.org/desktop-entry-spec/latest/)
651: Documentation for the ".desktop" file specification. \ No newline at end of file