How to Create an EFL Gadget Sandbox

The new gadget API and infrastructure for Enlightenment continue to undergo heavy development. In addition to improving and extending the base gadget UI, work has recently begun on creating a gadget provider with the new API to provide sandboxing and allow gadgets to be written as regular applications that don’t have or require access to compositor internals.

The primary enabler of the new sandboxing system is the efl-wl compositor widget. This allows the compositor to launch applications in isolation, and also provides the ability to add protocol extensions for only that specific instance of the compositor widget. Using these features, it becomes possible to add gadget-specific protocols and utilities on the compositor side that are passed through transparently to the client gadget application.

Currently, there is one base protocol in use: the e-gadget protocol, which looks like this:



  
    
      
      
      
    
    
      
      
      
      
      
      
    
    
      
      
      
      
      
    
    
      
    
    
      
    
    
      
    
  


The purpose of this is to mimic the gadget API. Applications can choose to listen for events on the window object with the listed event name and receive the corresponding property value. This is made possible because of a shared library that is preloaded into applications by the gadget provider using the LD_PRELOAD environment variable. This preloaded library intercepts calls to create EFL window objects and converts Wayland protocol events into callbacks on the window object. Gadget application developers can then write applications without the need to concern themselves with anything related to Wayland.

Example EFL Gadget Sandbox

An example sandbox gadget written in EFL reads something like this:

#include < Elementary.h >
static Evas_Object * popup;
static Evas_Object * child;

static void
popup_del(void * data EINA_UNUSED, Evas * e EINA_UNUSED, Evas_Object * obj EINA_UNUSED, void * event_info EINA_UNUSED)
{
  popup = NULL;
}

static void
child_del(void * data EINA_UNUSED, Evas * e EINA_UNUSED, Evas_Object * obj EINA_UNUSED, void * event_info EINA_UNUSED)
{
  child = NULL;
}

static void
popup_unfocus(void * data EINA_UNUSED, Evas * e EINA_UNUSED, Evas_Object * obj, void * event_info EINA_UNUSED)
{
  evas_object_del(obj);
}

static void
mouse_button(void * data EINA_UNUSED, Evas * e EINA_UNUSED, Evas_Object * obj, void * event_info)
{
  Evas_Object * ic;
  Evas_Event_Mouse_Down * ev = event_info;
  char buf[PATH_MAX];
  int w, h;
  Evas_Object * win;
  Elm_Win_Type type = ELM_WIN_POPUP_MENU;
  if ((ev - > button != 1) && (ev - > button != 3)) return;
  if (ev - > button == 3)
  {
    type = ELM_WIN_BASIC;
    if (child)
    {
      evas_object_del(child);
      return;
    }
  } else
  {
    if (popup)
    {
      evas_object_del(popup);
      return;
    }
  }
  win = elm_win_add(elm_win_get(obj), "win", type);
  elm_win_alpha_set(win, 1);
  if (ev - > button == 3)
  {
    child = win;
    evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, child_del, NULL);
  } else
  {
    popup = win;
    evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, popup_del, NULL);
  }
  if (ev - > button == 3)
    evas_object_event_callback_add(win, EVAS_CALLBACK_FOCUS_OUT, popup_unfocus, NULL);
  ic = elm_icon_add(win);
  snprintf(buf, sizeof(buf), "%s/images/bubble.png", elm_app_data_dir_get());
  elm_image_file_set(ic, buf, NULL);
  elm_image_object_size_get(ic, & w, & h);
  evas_object_size_hint_aspect_set(win, EVAS_ASPECT_CONTROL_BOTH, w, h);
  if (ev - > button == 1)
  {
    elm_image_resizable_set(ic, EINA_FALSE, EINA_FALSE);
    elm_image_no_scale_set(ic, EINA_TRUE);
  }
  evas_object_size_hint_weight_set(ic, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  evas_object_size_hint_fill_set(ic, 0.5, 0.5);
  evas_object_size_hint_min_set(ic, 100, 100);
  elm_win_resize_object_add(win, ic);
  evas_object_show(ic);
  evas_object_show(win);
}

int
main(int argc, char * argv[])
{
  Evas_Object * win, * ic;
  char buf[PATH_MAX];
  int w, h;
  elm_init(argc, (char * * ) argv);
  elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
  elm_app_info_set(main, "elementary", "images/logo.png");
  win = elm_win_add(NULL, "icon-transparent", ELM_WIN_BASIC);
  elm_win_title_set(win, "Icon Transparent");
  elm_win_autodel_set(win, EINA_TRUE);
  elm_win_alpha_set(win, EINA_TRUE);
  ic = elm_icon_add(win);
  snprintf(buf, sizeof(buf), "%s/images/logo.png", elm_app_data_dir_get());
  elm_image_file_set(ic, buf, NULL);
  elm_image_object_size_get(ic, & w, & h);
  evas_object_size_hint_aspect_set(win, EVAS_ASPECT_CONTROL_BOTH, w, h);
  if (argc > 1)
  {
    elm_image_resizable_set(ic, EINA_FALSE, EINA_FALSE);
    elm_image_no_scale_set(ic, EINA_TRUE);
  }
  evas_object_size_hint_weight_set(ic, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  evas_object_size_hint_fill_set(ic, 0.5, 0.5);
  evas_object_size_hint_min_set(ic, 100, 100);
  elm_win_resize_object_add(win, ic);
  evas_object_show(ic);
  evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_DOWN, mouse_button, NULL);
  evas_object_show(win);
  ecore_main_loop_begin();
  return 0;
}

This code results in an E logo gadget like this:

How to Create an EFL Gadget Sandbox - gadget_sandbox1.png

Left clicking creates a popup window (xdg_popup) which the gadget provider extracts from the compositor widget to display like a normal gadget contextual popup.

How to Create an EFL Gadget Sandbox - gadget_sandbox2

Right clicking creates a child window (xdg_toplevel with parent) which the gadget provider extracts from the compositor widget to display like a standard gadget popup.

How to Create an EFL Gadget Sandbox - gadget_sandbox3

There are no toolkit or language restrictions for gadget applications using this functionality. The only requirement is that interacting with the compositor in any way, such as receiving the gadget properties, requires use of the Wayland protocol. Even without that, any framework or toolkit that has Wayland support can now have fully functional gadgets running inside Enlightenment.

The sandbox infrastructure can currently be found in the desksanity module, and is scheduled to be merged into the main tree after the E22 release.

Satisfying Enlightenment’s Launcher Appetite with Luncher

Ibar has been Enlightenment’s primary launcher for at least a decade. What it lacked in features it gained in simplicity. However, as Enlightenment has grown, ibar has seemingly stayed stagnant. I wasn’t surprised when Mike Blumenkrantz informed me this would be one of the focuses of my internship. From the depths of Enlightenment’s growling, starving stomach, Luncher was born.

Satisfying Enlightenments Launcher Appetite with Luncher - luncher
The Outdated ibar Widget

In my previous post, I gave an introduction to developing gadgets for Enlightenment using the new gadget API; I did so by converting an existing module to the API, and this preparation was one of the first steps in creating Luncher. Mike and I spent weeks on end discussing ideas for Luncher including both necessary and wishlist features. We kicked around ideas and shared visuals of what we would like Luncher to be, and we identified weakness in ibar that must be improved for Luncher. In the end, we determined a simple launcher bar with elegant window previews and more aware code for complete taskbar management would be the focus of Luncher. Add in a catchy interface and smooth effects for iconifying applications, and the recipe was complete. All of this was happening while I was learning the new gadget API with pager, which was a measured approach to hit the ground running with Luncher, and hit the the ground running I did.

Being well prepared with the gadget API, I got the basics of luncher created in no time: create a gadget site, create a box to hold icons, and display icons. The next step was executing applications when icons were clicked, and this too was very easy. You can see in the following video how the gadget was coming together early on.

Everything past this point became more challenging. The most difficult task was writing the window previews popup. This involves keeping a list of open windows and matching them with their icon in the Luncher. As you can see, it always takes trial and error, and I was certainly not having fun.

Satisfying Enlightenments Launcher Appetite with Luncher - previewHowever, persistence is key when developing software, especially when visual appeal is important. After much trial and error, I managed to get the window previews into a state that Mike and I both liked (A Hallelujiah! might have been heard from my office).

Satisfying Enlightenments Launcher Appetite with Luncher - preview_final
The Finished Launcher Gadget

Once the previews were finished, the rest of development focused on stability and usability. Mike and I used the gadget extensively to make tweaks where we thought it would improve the user experience. When working on this stage, little things happen that might never seem apparent to the user. We move an image one pixel to the left or to the right, shift a box to align a different way, determine the best size for certain objects, etc. While this stage of the development may seem easy, it’s one of the most time consuming and involves constant rebuilding and testing only to rebuild and test again, over and over until things are just right. It involves a lot of tiny changes such as a single number or word, so the rebuild takes longer than the changes take to make. Then, the testing takes all of 5 seconds before the next tiny change is found. This is the cycle of the final stage of development, I recommend a lot of coffee.

Completing a project like this is always rewarding and is also the gift that keeps on giving as you get to use it in your own work. Luncher is now available in Enlightenment git repo. Stay tuned for further developments as I work on a grid version of Luncher as well as system info gadgets!

Samsung OSG Intern Profile: Michaël Bouchaud

My name is Michaël Bouchaud, and over the years I’ve been a software developer with several companies; I’ve now become the most recent intern in the Samsung Open Source Group internship program. In this post, I’ll share my new activities, but first, I’ll introduce myself.

How I Got My Start

I’ve used Enlightenment since E16 was my desktop window manager while I was in high school. What attracted me to this environment the most is the fact that it’s lightweight and sits on the side of the interface, allowing it to be effective on both mobile and desktop. I was always a rather good math student, and I studied computer science, mathematics, physics and chemistry at university. At the end of my studies, I looked for work primarily in a Linux environment; the search was not easy, but I came across Substantiel, a little French company that works with Debian. It was exactly what I was looking for: creating graphical applications in a UNIX environment. This company develops Ordissimo, an operating system targeted at beginner computer users. When I arrived, a first version of this operating system already existed but it was aging; during my time with the company we undertook a major job to rewrite the entire operating system. My task was to make a window manager that was adapted to our needs; for this, I used Enlightenment. The applications also needed to be rewritten, resulting in us using EFL since I was already active in the community.

I enabled my developer team to utilize EFL while also acting as a point of communication to the open source community. Nearly all of the applications were made using Elementary, but one of the biggest problems we encountered was that Elementary was very young at the time so we ran into a lot of bugs as well as a general lack of widgets. With that said, it enabled us to strip the graphical interface of the product down to simplify its use, while remaining very close to a standard PC environment. While this didn’t provide access to all of the capabilities of Linux, it did provide easy access for our customers.

Here’s a quick video that demonstrates the resulting interface.

After leaving Substantiel I went to work for Thales where I introduced EFL to several of the company’s projects. I’ve also spent a considerable amount of my free time contributing to EFL; my first contribution was the progress bar widget in Elementary. Since then, I have written entrance: a login manager and libekbd: a virtual keyboard library. I hope to eventually integrate libekbd into EFL and use it in the weekeyboard module that’s present in Enlightenment today.

What I’ll be Contributing on Behalf of Samsung

Now, my role in Samsung is to write an API for managing application volume in Enlightenment; this is possible through PulseAudio. I will take advantage of this API to create controls in a handful of places in Enlightenment so users can enjoy it. We’ve also noticed that the keyboard layout setting for Enlightenment is painful and unintuitive. I will propose an alternative solution to simplify its interface and provide a more natural configuration.

Mike Blumenkrantz introduced the new Enlightenment Gadget API in E 21, as well as a new gadget container named Bryce. I will make a Bryce migration wizard that makes it easier for users to move from the old configuration. Finally, I will also make two new gadgets: A post-it to quickly create notes on the desktop, and a weather gadget.

I really enjoy the opportunity given to me to work with other open source enthusiasts, and I can’t wait to bring my experience and motivation to this project!

Ecore_Drm2: How to Use Atomic Modesetting

In a previous article, I briefly discussed how the Ecore_Drm2 library came into being. This article will expand on that article and provide a brief introduction to the Atomic Modesetting and Nuclear Pageflip features inside the new Ecore_Drm2 library.

What Makes Atomic Modesetting and Nuclear Pageflip so Great?

For those that are unaware of what “modesetting” is, you may read more about it here. Atomic Modesetting is a feature that allows for output modes (resolutions, refresh rate, etc) to be tested in advance on a single screen or on multiple outputs. A benefit of this feature is that the given mode may be tested prior to being applied. If the test of a given output mode fails, the screen image doesn’t need to be changed to confirm a given mode works or not, thus reducing screen flickering.

Atomic/Nuclear Pageflipping allows for a given scanout framebuffer object and/or one or more hardware plane framebuffers to be updated in a single atomic operation. This means that updates to the screen output, whether they be updates of a given hardware plane, updates to a CRTC framebuffer, or even updates to rotation can happen in a single vblank interrupt. For the end user, this provides a much more friendly screen update by reducing redraws and flicker.

One of the things we strive to do with EFL is to keep our API simple to use. With that in mind, you will not notice any new API functions related to using Atomic Modesetting or Nuclear Pageflipping inside the Ecore_Drm2 library. You may be asking yourself right now: “Well, how do I make use of this then?” I have great news, you may already be using it :-). Rather than add new API functions, which need to be explicitly called for these features, I decided early that these benefits should come without any cost so that existing applications can make use of them without having to be modified.

The Technical Details

Inside the Ecore_Drm2 library there are various API functions that allow for setting output modes, or even sending a framebuffer object to scanout. These existing API functions have been modified to make use of Atomic Modesetting/Nuclear Pageflipping automatically where applicable. This means applications that are already using the various APIs of the Ecore_Drm2 library do not need to be changed.

Behind the scenes, the usage of Atomic Modesetting/Pageflipping is determined at runtime. This means that when the Ecore_Drm2 library gets initialized, it will make some checks to see if atomic usage is supported. Currently, these features are only supported on an Intel (i915) graphics card with a linux kernel version >= 4.8.0. If the Ecore_Drm2 initialization finds the proper driver and kernel version, it will then attempt to enable DRM_CLIENT_CAP_ATOMIC to support Atomic Modesetting/Pageflipping. If the client capability is successfully set, it will then attempt to enable DRM_CLIENT_CAP_UNIVERSAL_PLANES in order to enable hardware plane support.

Assuming all of the internal checks pass and the client capabilities are set successfully, the application will gain the added benefits of these features without any added work :-). There is one more thing that May be needed on some systems to get this working: it has been my experience that some boxes still need kernel boot-time options enabled for atomic to function. The necessary options (if required) are: drm.atomic=1, and i915.nuclear_pageflip=1.

While these features may not yet be available for all end-users to enjoy, the benefits they provide should be something that everyone can look forward to. With the continued hard work of linux kernel developers and graphics driver developers, we may all be able to enjoy these redraws soon :-)

Samsung OSG Internship Program: Marcel Hollerbach

My name is Marcel Hollerbach, and I’m the second intern to join the Samsung OSG as a part of their Enlightenment internship program. I wanted to take a moment to introduce myself and provide some background about how I got started in EFL development, and I’ll also explain what I’ll be doing as a part of this internship.

My Path Towards EFL Development

Currently, I’m studying Computer Science at the University of Karlsruhe, but I learned programming a while back by starting with Java. My interest eventually brought me to C and C++, and in 2011 I was first introduced to Enlightenment and EFL. A year later I discovered terminology: a great EFL-based terminal emulator; this led to me making the decision to learn to code with EFL.

I began by attempting to write the wallpaper settings for Terminology, which is essentially a screen that can be used to select background images for the terminal emulator. Carsten Haitzler (Rasterman) guided me through the process of writing the code for this project. After a few days of coding and learning EFL, the first version of the wallpaper settings was complete. The friendliness of the active EFL community on freenode convinced me to stay, and I began to do work on other areas, including entrance, the tiling module, and a few other minor things in Enlightenment and EFL.

Discovering a New Opportunity Through Open Source Contributions

Two years ago, I started to write an Elementary-based file manager. It was quite easy to build applications with elementary, and at some point I was happy with the functionality the file manager provided. I decided to make it more friendly to special use cases, such as exclusive keyboard or mouse users. Improving the file manager for mouse users worked quite well, but improving the experience for keyboard users didn’t go quite as well.

For starters, there was no way to revert an action; for example, when a user realizes they didn’t want to move the focus to another widget by using the right key, they might try to revert the action by pressing the left key. Currently, there is absolutely no assertion this will happen. Another problematic use case is when using a rather huge UI: there is a high chance of a certain set of widgets being inaccessible, but due to Elementary’s architecture, there is no way of checking if they can be used. No too long ago, Cedric Bail asked if I wanted to improve the current situation, and so I ended up here.

The primary function of my internship is to cleanup and fix widget focus management. So, considering the given problems, what do we need? First, we need a solution that is easy to debug to make it possible to more precisely understand the widgets and their relationships. Additionally, there should be one central data structure that carries all focusable widgets to make it possible to check if a specific widget is accessible or not. These are the two primary areas I will focus on for my initial work, and in my next blog posts I’ll go into detail about how I’m going to solve the problems described here.


Marcel Hollerbach lives in Germany where he is studying Computer Science at the Universtiy of Karlsruhe. He has been a user of EFL for more than 5 years and has authored a file manager application based on EFL. He also works with Wayland and the X window manager, and he is a participant in the Samsung OSG internship program.

Introducing the New & Improved Ecore_Drm2 Library

In the early days of developing Wayland support in EFL/Enlightenment, it was quickly apparent that EFL would need an abstraction library to interface with libdrm. We wanted users of EFL to be able to call simple functions without having to know about the underlying internals of libdrm, thus the original Ecore_Drm library was born. First, efforts to develop this library were undertaken with much enthusiasm and little fan-fare. After the birth of Ecore_Drm, we then proceeded to integrate it’s usage into some new Evas and Ecore_Evas engines so that the Enlightenment Desktop Shell could make use of it and render our first standalone Wayland desktop implementation.

After kicking the tires of our Wayland desktop for a while, we came to realize some shortcomings of the existing Ecore_Drm implementation. For starters, it would create it’s own Ecore_Drm_Device structure when launching the Enlightenment Wayland desktop (this structure was a representation of the physical connection to the /dev/dri card used in rendering). Along with this structure came lists of outputs, inputs, seats, planes, etc. In short, this structure was not very light and memory was being used up needlessly. Other shortcomings of the Ecore_Drm library included things such as structures being declared in public headers that couldn’t be easily changed, input device handling, systemd/logind support being coded directly into the library, and several other issues.

Redesigning From the Ground up

The community came to the easy decision that a better implementation was needed, thus we started efforts to create a new implementation and the Ecore_Drm2 library was born. This new library was developed slowly, while taking into account the shortcomings of the first iteration because we didn’t want to repeat the mistakes of the past. To help avoid these mistakes, the Ecore_Drm2 library API is currently marked as a ‘beta’ API which means it’s susceptible to changes at any time until the beta API marking is removed.

After several months of careful development and several months of testing, Ecore_Drm2 was deemed stable and complete enough to be pushed upstream. Efforts then ensued to modify the existing Evas and Ecore_Evas engines to use this shiny new library.

The new Ecore_Drm2 library fixes all of the shortcomings of the previous library. The community decided at inception that input handling should reside in it’s own library (thus the elput library was created). This removed a lot of internal overhead inside the Ecore_Drm2 library while also removing the need for the library itself to interface with systemd/logind. Public structures exposed via the Ecore_Drm2 library now have their actual implementations kept private so that changes could be made in the future if necessary. Internally, the size of the Ecore_Drm2_Device structure has been greatly reduced, saving memory.

While many improvements have been made to this new library (compared to the old one), one of the greatest overall improvements came as a result of it’s existence. With the new version of this library, we realized that the Evas and Ecore_Evas drm engines were also ripe for improvement. These rendering improvements did not happen by accident, but rather are the result of some great efforts, led by Derek Foreman, that provided tangible benefits by reducing tearing, decreasing time to first frame, improving rendering speed, and reducing memory usage. We believe we will see many more improvements just like this as a result of Ecore_Drm2.

Building Technical Talent in the Enlightenment Community by Solving Bugs

The past week or so has seen a significant amount of progress in the gadget backend of Enlightenment, due in no small part to the constant poking and prodding from Stephen Houston: our newest Samsung OSG Intern. As he mentioned in his post, we’ve known each other for quite some time now, so mentoring him has allowed both of us to skip over most of the pleasantries and get down to the code.

Establishing a Mutually-Beneficial Partnership

This type of internship is certainly new to me; seldom do I get the opportunity to sponsor and mentor a member of the community who has already been a contributor for such a long time. Given that I’d been the only one to use the new gadget API released in Enlightenment v21, I was curious to see what others would think after spending some time developing on top of it; soliciting feedback on the API during its development, as I did during my initial development work, hardly substitutes for the experience of spending time working with it in depth.

Before starting on his main gadget projects, Stephen decided he would try to adapt an existing gadget to the new API to test it out. We discussed this for a bit, and agreed it was a sound idea, so he set off to work. I think the first time I heard back from him was a few days after (keep in mind that he only works on this part-time in addition to his real job), and he was nearly done. He had found the new API to be satisfactory and easy to use, which was certainly a relief to me! This was, however, the point at which he brought up the sizing issue he posted a video of. We managed to work through it after a brief discussion of the problem, and he went on to tackle the last aspect of the gadget conversion: drag-n-drop (DND).

Solving Technical Problems While Growing Community Talent

Anyone who knows me or my past blogging knows that DND is not one of my favorite things to work on. While I typically have some choice words to describe it, the fact is that it’s a challenging subsystem to work within due to the necessary message passing between the drag initiator (the user) and the drop receiver. This leads to multiple places requiring debugging and testing anytime problems occur, adding to the complexity of solving problems. Solving DND bugs in a given area, however, is something like a rite of passage, and the tasks can only get easier from there… usually.

The DND issues here were numerous, and it turned out they were all either gadget infrastructure bugs or internal compositor bugs; in other words, I should be solving them to allow Stephen to continue progressing with his own work. I believe this is one of the great benefits of the way we’re running the internship program: in addition to sponsoring community members to continue doing the great work they have difficulty finding time for, we’re also providing the manpower behind the scenes to support that work and allow them to progress at their own pace, minimally hindered by any bugs outside the direct scope of their projects.

At this point, testing has been completed and Stephen’s new pager gadget has been merged into the upstream repository and is available for general use. He’s now already quite deep into the brand new launcher gadget, and I think we’ll have some exciting info to post about that soon. Stay tuned for more updates, as we have some new members of the Samsung OSG Internship program starting their projects within the next couple weeks!

A Venture Into Enlightenment’s Gadget API

In my last post, I mentioned that my internship would revolve around creating gadgets using the new Enlightenment gadget API. After several conversations with Mike Blumenkrantz, the creator of the gadget API and my mentor for this internship, we determined the Pager module is in a state that requires minimal work to be converted to the new gadget API. Therefore, converting Pager to the new API would allow me to focus on learning how the new gadget system works better than writing a gadget from the ground up.

A Venture Into Enlightenments Gadget API - pager_higher_res
The Pager Enlightenment Module

Mentors are a Great Resource for Learning Something New

Before I continue with details about the Pager API conversion, I think it would be prudent to explain how this internship works behind the scenes. Mike and I have known each other for quite a while as we’ve both worked on Enlightenment and EFL for years. In fact, when Mike joined the project, I was one of the first to welcome him and encourage his development, and he has quickly rose to the top of the project by bringing creative ideas and elegant code. This relationship is what my internship is all about: I get to work with people within the community that I’ve already spent considerable time with. Additionally, I get to build new relationships in the open source industry and meet mentors who are well adjusted to how open source development works.

Rarely do you find internships that are more of a partnership, but that’s what the Open Source Group’s internship offers. Mike and I keep an open line to each other to frequently discuss ideas, project directions, and bugs that we have found in both my own code as well as his. The ability to get in touch with a mentor quickly to solve problems and keep development moving is extremely valuable, and I get to play an active role in the decision making process.

Converting Pager to the New Gadget API

Now that I’ve provided context, I’ll explain one of the first things I’ve worked on as a part of this internship. The rest of this article will provide a brief overview of the process of converting Pager to the new gadget API. If you have any experience with GUI application development, then you will feel like you already know the new gadget API. It works the way most graphic toolkits do: create an object, tell the object how it should be laid out, and let the backend do the actual layout, sizing, and event handling. There are exceptions, of course, where size or events need to be handled manually; the gadget API makes this seamless with simple set/get functions and event callbacks.

Pager creates a simple table and packs layout objects that mimic virtual desktops into the table. The objects are packed based on the virtual desktop layout, and sizing is based on a gadget site. You can think of a gadget site as a container, or parent, for the object. Pager handles sizing based on the orientation of its parent gadget site. This orientation can be determined from a simple get function. If the gadget site has a horizontal orientation, then Pager will create a layout based on the height of the gadget site. If the gadget site has a vertical orientation, then Pager will create a layout based on the width of the gadget site. Let’s use Pager as an example of how sizing can be handled in a gadget.

Once the height or width (depending on your orientation) has been determined, you can use that size, the aspect ratio of the desktop, and the number of virtual desktops. Let’s assume the desktop has an aspect ratio of 16:9 and there are 4 virtual desktops. These virtual desktops are laid out horizontally in a row. The gadget site (parent of the Pager) has a horizontal orientation and height of 49 pixels. We can use a simple equation where we solve for x to determine what the width of the Pager should be: x = (aspect width / aspect height) * gadget height. This formula is a simple version of 16/9 = x/y where x is your desired width and y is your desired height. Since we already know the desired height is 49, plug 49 into the equation for gadget height. We also know the aspect width is 16 and the aspect height is 9, so we can plug those numbers into the formula as well. That gives us x = (16/9)*49. Solving for x = 87 pixels (rounded). You now know that each virtual desktop layout in the Pager will need to be 87 pixels wide and 49 pixels tall. Since there are four virtual desktops, and they are laid out horizontally, you can determine that 4 * 87, or 348 pixels, will be the width of the Pager, and 49 pixels will be the height. Obviously the math gets slightly more complicated if you have virtual desktops laid out in two directions, both horizontally and vertically, but the principle is the same. If the gadget site is resized, or the number of virtual desktops changes, the size of the Pager is updated simply using the formula we just established.

Once you have the hang of how sizing and orientation works with the gadget API, you can then begin to work on the contents of your actual gadget. Remember, learning new things take some trial and error, and no one is perfect. Sizing can be tricky, but the new gadget API makes it as easy as possible. If you don’t believe me, watch the following video and you can see that even I didn’t get sizing correct the first go around. Notice the Pager jumping around because it is constantly changing sizes.

Furthermore, remember that any issues you may find are not necessarily your fault because the gadget API is new. One of the biggest roadblocks I faced when completing the Pager conversion was correcting drag n drop. I spent a lot of time debugging my own code and asking Mike to debug his as well. Finally, Mike found a bug in the way the gadget code handles layering. He promptly made the fix and I was able to continue working to complete the Pager. It’s rare as an intern to get to ask your mentor to fix HIS bugs! :-).

Once the Pager was working well, the final touch was to create a configuration popup. In the past, Enlightenment modules have used window dialogs to handle configuration. The idea with the new gadgets is to have a simple popup that appears when a gadget is right clicked.

A Venture Into Enlightenments Gadget API - pager_popup
The Pager gadget configuration popup

The end result that is now available via git in Enlightenment can be seen in the following video:

Converting Pager to the new gadget API was a great primer for me to learn and prepare myself for the rest of my projects in this internship. The next project I will be working on is creating a new launcher for the enlightenment desktop. I will be writing this gadget from scratch and it will serve not only as a launcher, but also as a taskbar with the ability to handle iconified windows. Keep an eye out for updates regarding my progress!

Introducing Stephen Houston: Our Newest Intern

As the newest developer to have the privilege of taking part in Samsung’s Open Source Group internship program, I would like to give a brief introduction of myself, my experience, and my focus with Samsung.

I am a software developer and analyst who holds a bachelor’s degree in Computer Information Systems, and I’m currently working towards a Master of Business Administration. I’ve been an open source developer since I was 16 (a long time ago), and I have spent the majority of my time writing code related to the Enlightenment project. When I first stumbled across Enlightenment 17 in the early 2000’s, there was a widget library at the time called Ewl. The creator of Ewl, Nathan Ingersoll, took me under his wing and began teaching me C and how to use Ewl and other Enlightenment Foundation Libraries (EFL). I used this knowledge to create and develop Ephoto: an EFL based image viewer. I have made many contributions to the EFL including work that can be seen on Enlightenment’s file manager and file selector, Elementary widgets including gengrid, and Eio’s asynchronous file operations.

Ephoto is a fast, visually appealing image viewer that has many features. It allows users to view their images by a thumbnail grid, one by one, or in a moving slideshow. Ephoto also has editing filters that include auto equalization, gaussian blur, difference of gaussian sharpening, Floyd Steinberg dithering, Sobel edge detection, embossing, red eye removal, posterizing, sketching, and more. Brightness, contrast, gamma, hue, saturation, and value levels can all be adjusted on images as well. Ephoto is currently experiencing it’s first release cycle after over a decade of development (Sound familiar? Perhaps like E17?).

As part of my work with the Samsung Open Source Group I’ll be using my experience and expertise with the Enlightenment project to create gadgets using the new gadget API Mike Blumenkrantz introduced in the Enlightenment 21 release. My primary focus will be to create new modules that will be compatible with Bryce, a container infrastructure that Mike wrote for the new gadget system. Specifically, these gadgets will include a new launcher for Enlightenment, as well as gadgets for system information. The new launcher gadget will also have taskbar functionality, popup window previews, and .desktop context action menus. The system info gadgets will cover an array of information including battery percentage, power saving options, temperature, CPU frequency, CPU load, memory usage, and network upload/download statistics. All of the new gadgets will provide an intuitive, elegant interface, with configuration options presented in a popup rather than a dialog so they are consistent with the other gadgets that currently use the new API. My goal is to create these gadgets in a manner that is easily replicated in order to encourage others to get involved and create more gadgets. When I am finished, there will be enough stable modules to make Bryce a legitimate replacement for the current shelf system.

It is my pleasure to be given this internship to work with other open source enthusiasts and spend more time on a project that I have poured myself into for the last decade. I look forward to communicating with all of you as we work on these projects and work with the open source community. Long live open source development!

How to Create an Enlightenment Module

Module writing is one of the primary ways to expand the functionality of Enlightenment. By dynamically loading modules, the compositor is able to import code that has access to most Enlightenment internals. This allows developers to modify the desktop environment in nearly any way they can imagine, from new gadgets to compositor effects. This article will take a look at the basics of creating an Enlightenment module.

The first part of creating a module is setting up a .desktop file for it. This allows the module to be visible for users within the module configuration dialog. An example file looks something like this:

[Desktop Entry]
Type=Link
Name=My Module
Icon=e-module-mymodule
Comment=This is the description visible to the user
X-Enlightenment-ModuleType=Category

The ‘Name’ is the user-visible name of your module, and the ‘Icon’ is the filename of the .edj file which accompanies the module. The ‘Comment’ field provides supplementary information to the user that describes the functionality of the module. ‘Category’ is the category under which the module will be listed in the module configuration. With all of these fields provided the module will be displayed to the user with all possible information available.

Next up are the required hooks in the module code. These are namespaced symbols the compositor looks for when attempting to load a module. The first such symbol is the module API declaration:

E_API E_Module_Api e_modapi =
{
   E_MODULE_API_VERSION,
   "My Module"
};

The version here is used to ensure that the module has been compiled against a compatible version of Enlightenment; older modules will be prevented from loading to avoid crashes and other unintended behaviors resulting from ABI breakages. The second member of the struct is the module’s name.

Additionally, there are three function hooks which a module provides. The first one, the init function, is mandatory:

E_API void *(*e_modapi_init)(E_Module *m);

This function runs the necessary setup calls for the module, returning a non-null value that will be attached to the module object as its data pointer. If this function returns null, the module is considered to have failed to load and appropriate error messages will be displayed automatically to the user.

Modules also have access to a special function for saving data:

E_API int (*e_modapi_shutdown)(E_Module *m EINA_UNUSED);

This function is optional. When provided, it’s called whenever Enlightenment saves its configuration so that the module may also save its own configuration. The code for this function could be as simple as:

e_config_domain_save("module.mymodule", myconfig_eet_data_descriptor_struct, myconfig_struct);

This function returns 1 for success and 0 for failure, though the value is never checked.

Lastly, modules are able to have an optional shutdown function that is called whenever the module is unloaded:

E_API int (*e_modapi_shutdown)(E_Module *m EINA_UNUSED);

If this exists, it will trigger just prior to removing the module from configuration. This function can be used to clean up any persisting data structures or objects and it returns 1 on success and 0 on failure, but this value is never used.

That concludes the basics of Enlightenment module development. For some examples of existing module code, check out the repository category on git!