David @ Tokyo
Perspective from Japan on whaling and whale meat, a spot of gourmet news, and monthly updates of whale meat stockpile statistics
12/07/2007
Japanese IM setup in Enlightenment 17
After fiddling around with im-switch I got my
Japanese input method to work as expected, but immediately after having got this working I found a much easier way for me, being an E17 user.
Here are the steps:
1) Get the packages
$ sudo aptitude install scim scim-anthy
This part is of course the same, get scim and scim-anthy to get what you need (aptitude may pull im-switch here too, even though it's not actually needed, as we see below).
2) Next, open up the E17 Configuration Panel.
3) Scroll down to the "Language" category and select it.
4) The Items includes "Input Method Settings". Select this.
5) Click Advanced
6) Select "System" (we are going to use a scim configuration file for E17 that is provided with E17 by default).
7) The list should contain a "scim" option - select it. This will make scim your input method. Apply / OK or whatever to close the configuration menu.
8) Remove what is junk for us E17 users (only if you already have im-switch set up)
$ rm -f ~/.xinput.d; sudo aptitude purge im-switch
9) Restart X, and you will have E17 running scim for you on start up.
Labels: enlightenment, input method
11/08/2007
e17 build on debian
More notes for linux users (more specifically enlightenment fans)
On Debian lenny, additional packages that need to be installed to successfully do a ...
1) eet build:
zlib1g-dev
libjpeg62-dev
autoconf automake1.7 autotools-dev
libltdl3 libltdl3-dev libtool
2) evas build
pkg-config
libfreetype6-dev
libxrender-dev x11proto-render-dev
(also be sure to get this anyway, as e17 requires PNG support):
libpng12-dev
UPDATE 2008/07/20
libxext-dev(need this to get evas to find Xext when linking... dunno when this changed)
3) e17 build
libx11-dev libxau-dev libxdmcp-dev libxext-dev x11proto-core-dev
x11proto-input-dev x11proto-kb-dev x11proto-xext-dev xtrans-dev
UPDATE: 12/18
... an addition to the e17 build requirements - an optional one. If you want to use the System -> Lock Screen function, you need pam support detected and built in. The debian lenny package that contains this is:
libpam0g-dev
Labels: enlightenment, linux
12/08/2005
E17: Moon clock in screenshot
This guy I was chatting to on IRC happens to be running the little moon module that I made.
Here is a screenshot of his current desktop.
It's nice to have had positive feedback on the moon module port, and see other people using it - so far no bugs reported which is also good o(^_^)o
As well as my
own site, the moon module is it is also being hosted at
get-e.org as well.
Labels: enlightenment
11/26/2005
E17: Module Internationalization
Enlightenment DR17 has had internationalization support for the best part of a year now. Thus, providing a appropriate translation is available, it's possible to have the entire window manager's interface displayed in almost any given language.
However, due to the underlying gettext-based implementation that e17's internationalization support is built on, there are issues for module developers wishing to include internationalization as a feature of their 3rd party modules.
First a quick word about how the gettext-based internationalization support works.
1) Strings throughout the e17 code base that require translation are marked accordingly. Enlightenment uses a common method of wrapping strings to be translated in _(). For example:
e_dialog_title_set(exit_dialog, _("Are you sure you want to exit?"));
e_dialog_text_set(exit_dialog,
_("You requested to exit Enlightenment.<br>"
"<br>"
"Are you sure you want to exit?"
));
2) This _() technique isn't magic of course - it's actually a macro, which is defined in e17/apps/e/src/bin/e_intl.h as follows:
#include <libintl.h>
#define _(str) gettext(str)
#define d_(str, dom) dgettext(PACKAGE dom, str)
So when the C pre-processor runs over the code before compiliation, all those _("string") occurances are replaced with gettext("string") calls. gettext and other related functions (like dgettext, which we'll see more of later) are declared in libintl.h.
What does gettext do? It takes the input string, and uses it as a key to search in a message catalog for a translation. Which catalog is searched in is determined by the users locale / language environment settings. If it doesn't find a translation, then it just returns the key string as the result.
3) How are the message catalogs created? There are three steps:
a) When the autogen.sh script runs it executes the command xgettext to extract all the marked strings from the source code out in to a message catalog template.
b) Next, a translator copies the template, and creates a PO file, and does the translation exercise
c) When make is run to build e, msgfmt is used to compile the text based translation catalog into a binary format for use during run-time.
4) This isn't quite enough yet. In a basic program, the following needs to be done to trigger gettext operations.
setlocale (LC_ALL, "");
bindtextdomain (domain-name, path);
textdomain (domain-name);
Enlightenment actually does things a bit differently (see e_intl.c) but basically there has to be a setlocale call of some kind. The next two function calls are more interesting for module writers. bindtextdomain is used to specify the base directory for which message catalogs should be searched from, for a given domain (or namespace). For Enlightenment the domain would be "enlightenment", and for a module, we would just use whatever our module is called, i.e., "mymodule".
The path specified should be the path up to "locale". For example, Enlightenment would use "<prefix>/lib/locale"
The binary message catalogs are later to be installed to <path>/<locale>/LC_MESSAGES/domain-name.mo
For example, a Japanese (locale = ja) catalog for the "moon" module, installed to the user's home directory would be located under ~/.e/e/locale/ja/LC_MESSAGES/moon.mo
The final function, textdomain sets the domain-name as the domain to be used for all subsequent calls to the gettext function. Using this saves the programmer from having to specify the domain to be used for every single gettext call throughout the entire source code.
So how do modules fit in?
Issue 1: As 3rd party modules are developed, maintained and distributed independently of e17 itself, they can't be translated in the same message catalog as what enlightenment itself uses. Modules therefore will have to use their own message catalogs.
-> Modules must include a call to bindtextdomain to specify the path where the modules' message catalogs are stored
Issue 2: As 3rd party modules can't use enlightenment's message catalog, but the modules are dynamically loaded as part of the enlightenment, modules can't use textdomain and gettext. If they do, all the message translations in enlightenment that rely on the default domain being "enlightenment" will stop working. This would not be a popular module!
-> Modules must use dgettext, which is the same as gettext except that the domain is specified explicitly along with the string to translate.
Now for an example of module internationalization, using the moon module.
NOTE THAT THIS IS JUST "Proof of concept" QUALITY, NOT THE FINAL VERSION
$ cd ~/src/moon/trunk
$ mkdir po
$ cp ~/src/e17/apps/e/po/Makefile.am po
$ vi Makefile.am
--- Makefile.am ( 31)
+++ Makefile.am (篏キ)
@@ -1,4 +1,4 @@
-SUBDIRS = src data
+SUBDIRS = src data po
$ vi configure.ac
--- configure.ac ( 31)
+++ configure.ac (篏キ)
@@ -18,6 +18,15 @@
fi
AC_PROG_LIBTOOL
+ALL_LINGUAS="ja"
+AC_SUBST(ALL_LINGUAS)
+
+AM_GNU_GETTEXT([external])
+AM_GNU_GETTEXT_VERSION(0.12.1)
+if test "x$LIBINTL" = "x"; then
+ LIBINTL="$INTLLIBS"
+fi
+
# Checks for libraries.
AC_PATH_GENERIC(eet, 0.9.10, [
AC_SUBST(eet_libs)
@@ -110,5 +119,6 @@
data/Makefile
data/themes/Makefile
data/themes/images/Makefile
- src/Makefile])
+ src/Makefile
+ po/Makefile])
AC_OUTPUT
$ vi autogen.sh
--- autogen.sh ( 31)
+++ autogen.sh (篏キ)
@@ -11,6 +11,22 @@
echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
+echo "Generating gettext moon.pot template";
+xgettext +--output moon.pot +--output-dir=po +--language=C +--add-location +--keyword=d_ +--indent +--sort-by-file +--copyright-holder="Your N. Here" +--foreign-user +`find . -name "*.[ch]" -print` || exit 1
+
if [ -z "$NOCONFIGURE" ]; then
./configure "$@"
fi
$ vi src/e_mod_main.c
--- src/e_mod_main.c ( 31)
+++ src/e_mod_main.c (篏キ)
@@ -43,9 +43,12 @@
{
Moon *moon;
+ bindtextdomain(PACKAGE, "/home//.e/e/modules/share/locale");
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
moon = _moon_new(module);
@@ -89,8 +92,8 @@
/*
* FIXME - need to gettextise this properly
*/
- e_module_dialog_show("Moon Clock Module",
- "Display current phase of the moon ala e16 E-MoonClock");
+ e_module_dialog_show(d_("Moon Clock Module", ""),
+ d_("Display current phase of the moon ala e16 E-MoonClock", ""));
return 1;
}
$ cp ~/src/e17/apps/e/ABOUT-NLS .
$ ./autogen.sh
$ cp po/moon.pot po/ja.po
$ vi po/ja.po
--- po/moon.pot 2005-11-26 17:47:09.903525000 +0900
+++ po/ja.po 2005-11-26 17:54:37.469484632 +0900
@@ -11,16 +11,16 @@
"Last-Translator: FULL NAME <email address="">\n"
"Language-Team: LANGUAGE <ll org="">\n"
"MIME-Version: 1.0\n"
- "Content-Type: text/plain; charset=CHARSET\n"
+ "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/e_mod_main.c:95
msgid "Moon Clock Module"
-msgstr ""
+msgstr "月の相モジュール"
#: src/e_mod_main.c:96
msgid "Display current phase of the moon ala e16 E-MoonClock"
-msgstr ""
+msgstr "e16のE-MoonClockのように月の満ち欠け状態を表示します"
$ make
...
$ make install
$ enlightenment_remote -module-load moon
$ enlightenment_remote -module-enable moon
And now if we pull up the About menu for the module...

Labels: enlightenment
11/14/2005
E17: やった!僕の翻訳は使われている!
Enlightenment 17 ウィンドウマネージャのために作ってきた和訳は少なくとももう一人に
使われているようだ。リンク先で見えるスクリーンショットで日本語のメニューが見えているのですが、それは僕が訳した。ネイティブスピーカーじゃないので、改善できるところはいっぱいあると思うけど。今後E17がリリースに向かって行くとともに日本でも興味のある人が増えて行くといいな。
Labels: enlightenment
11/06/2005
E17: Creation of a Moonclock module - Part 1
This article has been posted
HERE at
edevelop.org, and will be maintained at that location going forward. This article remains here for historical purposes (^_^)
What this is:These are my notes about the creation of a module for e17, gathered together in an attempt to provide a semi-tutorial. This is not a step by step instruction guide on how to make a module - just points that I found pertinent while doing so myself. I do have a background in software (BSc Computer Science) and experience with C (in a kickass 3rd year networking paper), and expect anyone reading this and hoping to find this informative would have some C knowledge as well. In this article our focus is on the C source code for a module - we won't be going into the details of makefiles or edc's for edjes this time.
Also note that this is not the article of a seasoned e17-pro, just someone doing this in his free time for a bit of fun. Don't take anything written here as 100% truth.
Everything in this article with regard to CVS is up-to-date at the time of writing (to the best of my knowledge), but as development progresses this article will possibly fall out of date.
Finally, anything that happens to your computer as a result of your reading and using this information is your responsibility, not mine! If you start fiddling with your module source code it's quite likely that you'll crash the whole window manager and any open apps if you do something silly - I've done this numerous times myself :-)
That's the disclaimer out of the way...
Motivation:After my
initial pathetic contribution to E17, an actually
useful patch more recently, as well as
Japanese interface translation, I've now read enough cvs commits and emails to have a bit of a clue about how enlightenment 17 works. Thus I decided it was high time I hacked up a module of some sort to learn some more, and maybe even contribute something somebody else might like to use.
But what should I make?
The first time I used
Enlightenment would have been around 2 and half years ago when I was trying out a range of "light weight" linux distros on a crappy old half (now almost completely) broken Pentium 166 with maybe 32Mb of RAM. My favourite distro at the time (visually, at least) was
Peanut Linux (now aLinux) and that was due entirely to it having Enlightment 16 as it's default window manager. One of e16's features are small little mini applications known as "epplets", and my favourite was and still is E-MoonClock. All it does it sit on your desktop and display the current phase of the moon. Very simple, and pretty useless really, but I like it and happily grant it some of my RAM and CPU cycles.

Alas, e17 doesn't have it's own moonclock. Yet with the source to e16's E-MoonClock
available, plus a ready made
set of phased moon images, there would be few modules simpler to slap together than this one. So, let's go.
The e17 moon clock module source:Whether you plan to read this article or not, the source for the e17 moon clock module that I'm writing about in this article can be obtained from here:
http://www.geocities.jp/david_at_tokyo/e17/moon/1) Prerequisite: The Enlightenment 17 Module APIEnlightenment 17 has a pre-defined interface consisting of five C functions which modules are required to provide the definition for. This interface is very simple:
EAPI void *e_modapi_init (E_Module *m);
EAPI int e_modapi_shutdown (E_Module *m);
EAPI int e_modapi_save (E_Module *m);
EAPI int e_modapi_info (E_Module *m);
EAPI int e_modapi_about (E_Module *m);An introduction to implementing the bare minimum for a module is
available here at essiene's
"Exploring E17 Modules - Part 1". Since the basic module API has good coverage at that tutorial already, I'm not going to write any more about it. If you haven't read that article already, you probably should before reading this one, unless you are happy just to plagarise these function definitions from an existing module.
2) The User Interface - Edje (display only)I'd been reading about the concept of
Edje based applications prior to commencing the e17 module fun, and found the concepts very appealing, so much so that I wanted to give it a blast for myself. The Edje library makes it possible to seperate your application's user interface from the less visible application code, rather than having them tightly integrated together. With Edje you have the freedom to ship details of the way your interface looks and behaves into an independant source file, which is made up of details of the interface layout, images, and mini programs to control what the interface does. To be honest I got sick of building interfaces when using Delphi previously, prefering to work on non-user visible internal source code, but so far the Edje learning experience has been enjoyable. Anyway, my goal was to try the Edje library out for myself, and see how the separation of UI details from the real source went.
3) How to make a moonclock tickBut that left the problem of figuring out what the phase of the moon is at a given instant... any takers? OK! I don't have a clue about how to calculate the current phase of the moon, and I'm guessing the majority of people who will read this aren't astronomers either. Thankfully, on brief examination of the
E-MoonClock source, I found that in fact it's author had in turn borrowed a chunk of source code from a prior moonclock author, who was rightly credited with doing all the real work. Likewise, I am equally indebted, but let's continue.
To create the moonclock all one needs to do is set up a couple of time & date arguments, call a
library function, then use the resulting floating point value (between 0.0 and 1.0) to decide which moon image to display (and repeat the process periodically to keep the moon image up to date). The original E-MoonClock does all of this in one function (very simple).
Images however are a feature of the user interface with nothing to do with the application code, and in the spirit of Edje, we'll be doing things a bit differently. E-MoonClock has 60 smallish moon images (and the epplet source code is specific to having 60 images), but if someone else out there had a larger set of higher quality images available that they wish to use, they'd have to recompile the entire source to do so. That's not cool - ideally we want to maintain the separation of moon phase calculation and other stuff from the UI details. So the ultimate goal is to slap together the C code for the module, define the interface details in an Edje source file (EDC) and somehow have the application code inform the Edje of the current phase of the moon as represented by a floating point value. Other than this floating point value, there's nothing else the Edje needs to determine how to represent the moon phase information on screen.
4) Plagarising the skeletonSo into the C code we go. But where to start? There's a saying about lazy programmers (and this whole module is a fine example), and in that tradition I went looking for a module that was similar enough to my own. Basically I just want to create a square moon clock like that in e16 - in some respects very similar to the e17's default clock module. Like the clock, the moon module just needs to sit there on the screen, maintaining it's aspect and so on, with the addition of sending moon phase information to the moon modules' Edje (this is the main difference to clock, and we'll cover how to make our module do this later). So, I followed the clock module source closely, copying stuff that I needed (and in some cases copying stuff just to figure out what it actually does). If you haven't read the
e17 clock source before, now's a good time to open it up and have a squizz.
The definitions of the moon module's five module API functions were basically copy and pastes of the clock module code with a few changes to refer to moons instead of clocks.
The init function is the only function that does much in my case: the actual creation of a "Moon" data structure, which I eventually separated out into a helper function, "_moon_new" ala the clock module.
5) The Moon data structure, _moon_new and _moon_freeThe Moon data structure in src/e_mod_main.h only contains three things:
typedef struct _Moon Moon;
struct _Moon
{
Evas_List *faces;
E_Menu *config_menu;
Ecore_Timer *moon_check_timer;
};
a) A list of moon "faces".
The "Moon_Face" data structure holds information about which canvas it's to be included on etc. The Moon data structure has a list of these, as Enlightenment doesn't assume that you have only one screen for your computer (I only have one myself, so haven't bothered myself with the details, and could be only 50% on the mark about this - hopefully someone will confirm or correct me)
b) A menu data structure.
All modules have an entry in the "Modules" menu, so why not have one for the Moon module as well? We'll have a familiar use for this later anyway: configuration - but not in this article. At the time of writing the configuration menu in the e_modapi_init function is also disabled since we aren't using it yet.
c) An Ecore_Timer.
We need to periodically check the current phase of the moon so that we can keep our UI Edje up to date with the latest information. Rather than get dirty with SIGALRM's, the Ecore library already provides a simple and easy to use timer mechanism for us to take advantage of. The Ecore_Timer allows our module to receive a callback from the underlying Enlightenment infrastructure after a certain amount of time has expired. Callback's (often abbreviated as "cb"s) are something that pop up all over the place in Enlightenment - these are just event listeners. e17 overall follows an event-driven model. The EFL Cookbook
has an example of one of how to use Ecore_Timers if you need some more detail, but in this case we are going to do this:
moon->moon_check_timer = ecore_timer_add(60.0, _moon_cb_check, moon);
This sets up our Ecore_Timer to call us (the moon) back via the _moon_cb_check function, every 60.0 seconds. I'll talk more about the _moon_cb_check function later, but for now I'll just note that the function
must return a value of 1 in order for the timer to be renewed after each call to the callback function (or so I hear).
The _moon_new function sets up these three items, and since this is C, we also write an accompanying shutdown function (_moon_free) to make sure we free'd all the memory we allocated in _moon_new.
If you compare these moon functions with those in the clock, you'll notice the moon functions are simpler - first off I just want to get this thing working, so there is no code to save configuration information yet, and the Ecore_Timer time value is hardcoded to go off once every minute. Later on (not in this article though), we'll make this configurable, but for now once a minute should be acceptable.
6) _moon_face_new and _moon_face_freeThe _moon_face_new function is more interesting than what we've seen already, with a range of EFL and Enlightenment functions being invoked. This time we're setting up a Moon_Face data structure that is defined something like this:
typedef struct _Moon_Face Moon_Face;
struct _Moon_Face
{
E_Container *con;
Evas_Object *moon_object;
E_Gadman_Client *gmc;
};
The first thing we do is allocate memory for the moon_face structure, and then assign the structure's Container value with the container that the moon_face is going to be added to. At this stage we don't actually need to record this container in the object, but (I think) we'll find it useful later when we add some configuration save / load code.
Next up it's time to setup our moon's Edje object! This involves carving out a chunk of space on the background canvas for the moon module to display it's interface in. It's worth noting here that with the Enlightenment Foundation Libraries and evas in particular, the model used is of a "canvas" containing objects, which can then be manipulated (moved, resized etc). This is what we have with visual modules in E17 - they are basically objects etched into the desktop background. This is about as far as my rudimentary knowledge of evas goes, but as we'll soon see it's enough to get our module working.
I presume there's a good reason for it, but we start this activity by first calling
evas_event_freeze, passing the background canvas of the Container that this face will be added to as the required argument. At the end of the function, once we've finished setting up the Moon's interface, we'll call the corresponding function
evas_event_thaw again specifying the same background canvas.
evas_event_freeze(con->bg_evas);
// make changes to background canvas (i.e., add new object to represent moon etc)
evas_event_thaw(con->bg_evas);
After calling evas_event_freeze and until evas_event_thaw is called, the background canvas specified puts all event processing on ice. This is the time to make changes to the canvas, that is, adding edje object's to it, positioning them and so forth (see below). Presumably bad unpredictable stuff could happen if the evas is processing events (maybe objects moving about etc) while we are making our own changes to the canvas at the same time - the mind boggles! I'm not sure about exactly what scenarios this functionality prevents - hopefully I'll get some more detail on this later, but for now, as the clock and various modules do this, we will too.
Now that the events from the background canvas are on hold, we
add a new edje object (our moon's "face" on the desktop) to the background:
o = edje_object_add(con->bg_evas);
face->moon_object = o;
We then tell the new Evas object which user interface file to use. For the moon module we'll be using a file called "moon.edj", but we'll not be getting to that until we've finished writing the C code. In the meantime, let's just assume we have a dummy "moon.edc" file, which will be compiled into "moon.edj". Later on we need to write "moon.edc" properly so that it'll display moon images, but for starters we'll just use a plain black rectangle:
collections {
group {
name: "moon/main";
parts {
part {
name: "dummy";
type: RECT;
description {
state: "default" 0.0;
color: 0 0 0 255;
rel1 {
relative: 0.0 0.0;
}
rel2 {
relative: 1.0 1.0;
}
}
}
}
}
}
}
We use
edje_object_file_set to specify that the object we added to the background canvas should use the "moon.edj" file. If you look at other modules, you'll see them using a semi hardcoded path name to the edje file here. If you mimic such modules, you'll probably come up with something like:
edje_object_file_set(face->moon_object, PACKAGE_LIB_DIR "/e_modules/moon/moon.edj", "moon/main");
This is pretty bad actually (as I discovered myself), because we don't know that the module is going to be installed under "e_modules". e17 currently supports modules that have been installed into user home directories at ~/.e/e/modules/
as well. If the user chooses to install there instead of under the e_modules tree, when the user enables the module and it tries to load it's edje, it will not be able to find it, and will choke up errors all over your standard output. So, we really want to find our moon.edj object in a more dynamic fashion. The good news is that (as usual with e17 and the EFL) the hard work has already been done - there's a function in e_module.h that does exactly what we need:
EAPI const char *e_module_dir_get(E_Module *m);
With this function in our arsenal, we just need to have the E_Module available to get the path to where the module will be installed. As per esseine's tutorial you will recall that this infomation is passed to us when the e_modapi_init function is called, so I've just passed the E_Module to the _moon_face_new function as an argument:
static Moon_Face *
_moon_face_new(E_Container *con, E_Module *module)
{
char edje_path[PATH_MAX];
...
snprintf(edje_path, sizeof(edje_path),
"%s/moon.edj", e_module_dir_get(module));
edje_object_file_set(face->moon_object, edje_path, "moon/main");
...
That's better! Now we're only hardcoding the "moon.edj" name and the "moon/main" values, but for now we have no way of changing these, even if we wanted to, so it's sufficient for now (^_^).
Next and importantly - we need to call
evas_object_show with the new edje object as the argument. This is the function call that will actually make the edje visible on the screen.
evas_object_show(face->moon_object);
Subsequent to this I have some calls which I basically copied from the clock module:
evas_object_resize(face->moon_object, 96, 96);
edje_object_calc_force(face->moon_object);
edje_object_part_geometry_get(face->moon_object, "moon", &x, &amp;amp;amp;amp;amp;y, &w, &h);
// blah blah
The first of these,
evas_object_resize, obviously resizes the moon_object to be 96 wide by 96 high. Using this function ensures that our module starts off with a reasonable size.
The next call,
edje_object_calc_force, somewhat
less obviously forces the edje to recalculate it's layout (although at least with this module I've not seen the interface display itself incorrectly after resizing - I may be missing the point with this...)
Thirdly we are grabbing the geometry of our edje object's "moon" part - but we haven't even discussed parts or edjes yet, so this is best skipped for now (and it's not actually required anyway).
Now, we could stop here, but if we did so, our Moon module (displaying it's dummy black rectangle interface) would be stuck at a fixed location on our dekstop background. The user wouldn't be able to move or resize the moon module to their personal liking, as they can for other modules like the clock:

That's not cool either. This is where we need to get our module set up as an client of the e_gadget manager.
The e_gadget manager component of the e17 window manager will be familiar to anyone who's bothered to re-arrange the layout of modules on their desktop. By setting our module up as a gadget manager client we'll get all the nice animated module resizing / relocating capabilities for free. The e_gadman_client function calls are actually pretty self explanatory, and what you do here will depend on the characteristics of your particular module, so I'm not going to go into any great details on that. Suffice it to say we set various properties of our client, which will affect how the interface can be resized and moved. But at a minimum we need to create the E_Gadman_Client, create a "change" event handler callback that defines how our client will respond to move / resize actions from the user, and finally tell it to load.
face->gmc = e_gadman_client_new(con->gadman);
...
e_gadman_client_change_func_set(face->gmc, _moon_face_cb_gmc_change, face);
e_gadman_client_load(face->gmc);
In the case of the moon module, the callback function (_moon_face_cb_gmc_change) is basically identical to that of the clock module. This function gets called in response to the user moving or resizing the module while the gadget edit mode is on. After setting up our gadman client, now look what we can do:

Wheeee! Our module now has all the shiny whizbangs available for resizing, and it's also relocatable now. Even our dummy edje looks pretty good with it registered with the gadget manager (^_^). This concludes the set up of a Moon_Face.
Finally, after all this excitement in the _moon_face_new function, we teardown everything we've done / deallocate memory in the _moon_face_free function.
7) And now back to that timer callback...So now we have plonked a module on the desktop. In fact, at this point you can't see it if you load and enable it as the user interface still doesn't exist yet. But, if you turn on the gadget edit mode, you'll see a empty border on your screen - this will be the moon's space.
But before getting ahead of ourselves, we need to fill out the details of the _moon_cb_check callback for the Moon object that we defined back up in the _moon_new function. The Ecore_Timer is going to go off every 60 seconds, and when that happens we need the function we defined to calculate the current moon phase, and then somehow inform our yet to be created user interface what the value is.
The callback is simple though because, as I mentioned earlier, the work has already been done for us previously in e16's E-MoonClock epplet and prior moon clock implementations. Here I created a new helper function, _moon_phase_calc, to return the moon phase. This helper function mimics the e16 epplet code, just cutting out some stuff that we don't need, and reformatting to my taste.
static double
_moon_phase_calc()
{
...
... (blah blah blah, read the source if you are interested in astronomy!)
...
return c.MoonPhase;
}
Now that we have the value representing the moon phase, we have to get this information to the edje of our moon_face (or faces, if you have a flasher setup than me).
Hmmmmmmmm! This is about the first original thing we've had to do in this module - pretty much everything else we have done so far is plagarise from clock and other modules. So how do we get our moon phase value to our edje? Rest assured,
the Rasterman has this base covered too.
8) Application -> Edje communicationsSo, we need our application code to be able to pass a message to our Edje interface, containing the float information representing the current phase of the moon.
After some poking around here and there, I discovered that Edje has a message queue interface, allowing applications to send data of various types to their interfaces. This is of course exactly what is required for the moon module. The API call of particular interest here is this one (
from Edje.h - currently undocumented other than in the source, although I'm going see what I can do about that):
EAPI void edje_object_message_send (Evas_Object *obj, Edje_Message_Type type, int id, void *msg);
To use this, first you need to determine what you want to send to your Edje. The various types currently available are declared in
Edje.h:
typedef struct _Edje_Message_String Edje_Message_String;
typedef struct _Edje_Message_Int Edje_Message_Int;
typedef struct _Edje_Message_Float Edje_Message_Float;
typedef struct _Edje_Message_String_Set Edje_Message_String_Set;
typedef struct _Edje_Message_Int_Set Edje_Message_Int_Set;
typedef struct _Edje_Message_Float_Set Edje_Message_Float_Set;
typedef struct _Edje_Message_String_Int Edje_Message_String_Int;
typedef struct _Edje_Message_String_Float Edje_Message_String_Float;
typedef struct _Edje_Message_String_Int_Set Edje_Message_String_Int_Set;
typedef struct _Edje_Message_String_Float_Set Edje_Message_String_Float_Set;
In this case we'll assume we're happy to just send a single floating point value to our Edje, so we'll use Edje_Message_Float. The struct for one of these is ultra simple:
struct _Edje_Message_Float
{
double val;
};
This is self-explanatory - Edje_Message_Float has just one element, a value, which we're going to assign to hold our moon phase information:
Edje_Message_Float msg;
...
msg.val = _moon_phase_calc();
...
edje_object_message_send(face->moon_object, EDJE_MESSAGE_FLOAT, 1, &msg)
But there's two more args defined there - EDJE_MESSAGE_FLOAT is also defined in a enum in Edje.h, but the '1' argument is less obvious. Later on when we look at how the Edje receives these messages, the use of this argument will become clear - but in brief, the problem is that the messaging interface doesn't cater for arbitrary function names to be called - there is only one function name. Additionally, it's only able to handle the predefined data types shown above. Now if you imagine that you had a module where you wanted to send two different messages containing two completely unrelated pieces of information - yet perhaps those different pieces of information were both represented using the same
type of value (say float), the Edje needs a way to distinguish one float message from the next. This numeric id provides a means of making such a distinguishment between different messages that use the same Edje Message Type. In our example, we only have one float, so this id value doesn't actually matter for us, and thus we'll just choose '1' as our value - we could choose anything else though.
With that, we're done with everything of interest in src/e_mod_main.h and src/e_mod_main.c.
9) Next timeIn the second part of this article (under construction!) we'll take a look at the EDC for the moon, how it receives this floating point value from the application. and bring everything together by displaying appropriate moon images on screen. We'll also take a look at the embedded embyro scripting functionality as well.
Labels: enlightenment
11/01/2005
E17: Creation of a Moonclock module - Part 2
10/25/2005
E17: Learnings (6) Embyro snprintf limitations
This one's a "gotcha" ("gotme")...
I wanted to use snprintf in an Embryo script in my EDC to format a floating point value to 2 decimal places. Unfortunately Embryo doesn't support complex print formats (yet?)
From
e17/libs/embryo/include/default.inc:
/* same as snprintf, except only supports %%, %c, %i, %d, %f, %x, %X, %s, \n and \t */
native snprintf(dst[], dstn, fmt[], ...);
Ok, so I worked around this by setting the string value in my C code and then sending that to my module using the edje messaging system. I'll be writing more about that later...
Labels: enlightenment
10/24/2005
E17: Learnings (5) Embyro language syntax
As mentioned at the
Enlightenment homepage, Embryo provides the scripting functionality in Edje EDC's.
The language Embyro is based on was originally known as "
SMALL", but recently due to non-Googlable nature of that name, has been rebranded as "
PAWN" (be sure you spell it out when you tell your mates about it).
There's solid coverage of the language here in "
Pawn - The Language" (PDF format) at the
Compuphase homepage. Yet more reading!
Labels: enlightenment
10/22/2005
E17: Learnings (4) EDC and alignment
Today: Alignment in EDC

The default clock theme included with e17 has an option to turn on a digital display. I'm pretty useless at looking at the clock hands and figuring out which one is shortest, longest, moving fastest in an instant, so I like the digital option.
However, annoyingly for me, the digital time string is aligned to the left, not to the center. It just doesn't look right on the left :-)
Obviously, we need to modify the EDC group for the clock appropriately. All the EDCs for the enlightenment 17 default themes are stored at
e17/apps/e/data/themes. In this case, the file to modify is
default_clock.edc.
Way towards to end of the file is the definition for the "digital" TEXT part. This is the part that displays the text string that you see in the clock snapshot to the upper left. Here's how the file looks right now (revision 1.8):
part {
name: "digital";
type: TEXT;
effect: SOFT_SHADOW;
description {
state: "default" 0.0;
rel1 {
to: "digital_bg_area";
offset: 3 4;
}
rel2 {
to: "digital_bg_area";
offset: -2 -2;
}
color: 255 255 255 255;
color3: 0 0 0 32;
text {
text: "00:00:00 AM";
font: "Edje-Vera";
size: 15;
fit: 0 1;
align: 0.0 0.5;
}
}
...
}
Today we want to fix the alignment, so it's obvious at least which line to modify - the one that says "align" - but how? As we can see, the align value for the text time description specifies two values: 0.0 and 0.5.
These alignment values represent how the text part should be aligned with respect to the part it is specified to be positioned relative to. In this case, the "digital" text part is relative to the "digital_bg_area" (see rel1 and rel2). But this post isn't about part relativity, the rel1 / rel2 keywords aren't obvious in meaning, so let's just skip that this time!
The first value, 0.0 here, represents how the text part should be aligned horizontally, and the second, 0.5 is the vertical alignment.
- In the horizontal context (first value) 0.0 means "left aligned", and 1.0 means "right aligned"
- In the vertical context (second value) 0.0 means "top aligned" and 1.0 means "bottom aligned"
- Legal values range between 0.0 and 1.0
- The value represents a ratio for alignment along the respective x and y axises
Thus, what the "align: 0.0 0.5;" means is to left align and vertically center the text part relative to the "digital_bg_area" part (as denoted by the rel1 / rel2 values - a different blog entry as I said)
Back to my problem: I want to horizontally center the text string, not left align it. If I'm any good at all an explaining this, the change we need to make is simply as follows:
diff -u -u -r1.8 default_clock.edc
--- e17/apps/e/data/themes/default_clock.edc 24 Sep 2005 01:15:23 -0000 1.8
+++ e17/apps/e/data/themes/default_clock.edc 21 Oct 2005 18:07:00 -0000
@@ -693,7 +693,7 @@
font: "Edje-Vera";
size: 15;
fit: 0 1;
- align: 0.0 0.5;
+ align: 0.5 0.5;
}
}
description {
And below is the end result (^_^)

This works nicely with both 24 hour and 12 hour + AM/PM format options provided in the clock module configuration.
Finally, as I believe is the case for the the
min and max values that I covered last time, the align keyword can be used to align part types other than TEXT.
Labels: enlightenment
10/16/2005
E17: Learnings (3) Restricting edje text size
OK, and now for an even simpler one...
Issue: You want to ensure that a text part in your edje object never goes below a certain minimum size.
SImply add the "min" (or max if that's your aim) attribute into the description of the text part.
part
{
name: "text";
type: TEXT;
description {
state: "default" 0.0;
min: 16 16;
rel1 {
...
}
rel2 {
...
}
color: 120 120 120 167;
text {
...
}
} // text part
}
You're saying here that the text part can be no less than 16 pixels in width, and no less than 16 pixels in height. With settings of 16 and 16 it seems that the height setting (latter of the two) makes the width setting pretty useless with horizontal text, as you'll usually have a string of more than 1 character. As you make your edje object size smaller, the height restriction kicks in before the width one does.
min and max could be used for any type of part, not just text - but it's obviously useful here if you want to ensure that your text remains readable.
Labels: enlightenment
E17: Learnings (2) Restricting module size
Continuing my notes on e17 functions learnt before I forget them...
Issue: You want to restrict the size of a module on your e17 background canvas, because it will just look stupid and ugly at any other size.
E17's gadget manager enables modules to be moved and resized around your desktop. The module doesn't need to worry about this at all, other than to tell the gadman about itself when created.
In your module's .edc file you can define the maximum and minimum width and height for the module's interface. Say you have a group of parts called "main" like yay:
group
{
name: "main";
min: 10 10;
max: 256 256;
... (definition of the parts of the interface) ...
}
Here we are describing the interface's name and it's min and max dimensions, but that alone doesn't do anything useful. To actually get e17's gadget manager to honour these size restrictions you'll need to (gasp!) tell the gadman about it, in addition to the other setup.
The
e_gadman_client_{min | max}_size_set functions are the ones you need to call to do this, and to extract the min and max values out of your edje (compiled from your .edc) you use the
edje_object_size_{min | max}_get functions:
Evas_Coord w, h;
...
edje_object_size_min_get(face->edje_object, &w, &h);
e_gadman_client_min_size_set(face->gmc, w, h);
edje_object_size_max_get(face->edje_object, &w, &h);
e_gadman_client_max_size_set(face->gmc, w, h);
Now when you try to resize your module it'll be kept within the sane range of sizes that you defined for it.
Labels: enlightenment
10/10/2005
E17: Learnings (1) up to date EDC info
Currently I'm working on a module for Enlightenment 17 (similar to the
clock that you see on the top right hand of my desktop.
My module is still under wraps at this stage, but I'm going to be jotting down notes about various stuff I am learning and not wanting to forget straight away as I progress. I'll probably find better places to find the same information later on, but for now these are just my notes. You can skip them!
Today:
"Building Interfaces with Edje" is a useful resource as it attempts to explain the EDC format for interfaces, but it's a bit dated now. This source file gives some clues about additions to the format since that doc was written:
e17/libs/edje/src/bin/edje_cc_handlers.c
The function st_collections_group_parts_part_type shows that we now have the following part types available to us:
NONE
RECT
TEXT
IMAGE
SWALLOW
TEXTBLOCK
Labels: enlightenment
9/25/2005
E17 Japanese update
With the Autumn Equinox holiday on Friday and some pretty bad weather, I did an update to the Japanese translation for Enlightenment 17. Still no native speakers interested in doing this it seems! Here's a screenie (click for the fullsize version) with some of the Japanese menus displayed. These particular menus are all going to get sucked out into the Enlightenment Configuration panel eventually I think.

Labels: enlightenment
9/22/2005
Yay, another patch in Enlightenment DR 17
This time I spotted a bug with the E17 window shading function, and the fix got added o(^_^)o
For you Windows users, "shading" is when you double-click in a window's title bar and roll up the window into the title bar like rolling up a window shade. You double-click and the window displays again. Basically similar to iconifying a window. There was a small bug where if you double-click but then double-click again before the window has finished shading, it goes a little wierd.
Here's my patch... (again very trivial but a little bit better than
last time!)
UPDATE: My
message to the listdavid@Debian:~$ cat shadefix.diff
Index: e17/apps/e/src/bin/e_border.c
===================================================================
RCS file: /cvsroot/enlightenment/e17/apps/e/src/bin/e_border.c,v
retrieving revision 1.400
diff -u -r1.400 e_border.c
--- e17/apps/e/src/bin/e_border.c 21 Sep 2005 04:53:12 -0000 1.400
+++ e17/apps/e/src/bin/e_border.c 21 Sep 2005 14:12:29 -0000
@@ -1246,7 +1246,7 @@
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
- if ((bd->fullscreen) || (bd->maximized)) return;
+ if ((bd->fullscreen) || (bd->maximized) || (bd->shading)) return;
if (!strcmp("borderless", bd->client.border.name)) return;
if (!bd->shaded)
{
@@ -1332,7 +1332,7 @@
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
- if ((bd->fullscreen) || (bd->maximized)) return;
+ if ((bd->fullscreen) || (bd->maximized) || (bd->shading)) return;
if (bd->shaded)
{
// printf("UNSHADE!\n");
david@Debian:~$
And here it
goes into CVS:
Enlightenment CVS committal
Author : sebastid
Project : e17
Module : apps/e
Dir : e17/apps/e/src/bin
Modified Files:
e_border.c
Log Message:
Don't allow to shade/unshade while shading.
===================================================================
RCS file: /cvsroot/enlightenment/e17/apps/e/src/bin/e_border.c,v
retrieving revision 1.400
retrieving revision 1.401
diff -u -3 -r1.400 -r1.401
--- e_border.c 21 Sep 2005 04:53:12 -0000 1.400
+++ e_border.c 21 Sep 2005 15:54:02 -0000 1.401
@@ -1246,7 +1246,7 @@
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
- if ((bd->fullscreen) || (bd->maximized)) return;
+ if ((bd->fullscreen) || (bd->maximized) || (bd->shading)) return;
if (!strcmp("borderless", bd->client.border.name)) return;
if (!bd->shaded)
{
@@ -1332,7 +1332,7 @@
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
- if ((bd->fullscreen) || (bd->maximized)) return;
+ if ((bd->fullscreen) || (bd->maximized) || (bd->shading)) return;
if (bd->shaded)
{
// printf("UNSHADE!\n");
- Show quoted text -
Labels: enlightenment
4/02/2005
CVS: FInding out what files changed
In my adventures with Enlightenment I find myself wanting to look at what changes the development team have made to the source since I last bult the software. If anything interesting changed, then I want to rebuild and check it out.
At first I was trying to use
$ cvs diff -u
but it didn't seem to be giving me the right output. So instead I have been using :
$ cvs update -dP
which gives some useful output while it updates my working copy. But I just I found this command:
$ cvs -n -q update
The -n option makes no actual changes, resulting in exactly the output I need. Noting here so that I don't forget!
Labels: enlightenment
3/27/2005
Enlightenment 17 user guide translation
To give life a little more spice, I have volunteered to translate the
Unofficial Enlightenment DR17 User Guide into Japanese in my free time. It has been keeping me busy. But tonight I am taking a break to catch up on some email etc and other stuff. Who knows, I might even boot into Windows...
Labels: enlightenment
3/17/2005
Enlightenment 16 screenshot 1

Here is my desktop now (I have rearranged things a little). In the top left hand corner there is a moon clock (yup, it seems to be in phase with the moon!), and a standard old-style clock (These are little programs for Enlightenment 16 called epplets by the way). The third box below the two clocks has a big blue flame in it. This epplet is illustrating my CPU usage. At the time I was going through my initial attempt at building the Enlightenment 17 foundation libraries from the anonymous CVS repository online. Maybe I need more CPU :-)

Labels: enlightenment
Enlightenment 16 screenshot 2

This is how my Enlightenment 16 workspace looked about 8 days ago. On the left is "gkrellm", a stack of various system monitors. I had just found a plugin for it that enables the user to take screenshots. This was my test!

Labels: enlightenment
3/12/2005
Enlightenment 17 CVS
My little bit of fun for the weekend (although I have to go to work in 13 minutes - it's a Saturday) is going to be getting all the source code for
Enlightenment 17 on to my machine, and hopefully building it.
This is how I am apparently supposed to
do it:
Gotta learn a few CVS commands it seems. That will be a first, but I've used Microsoft Visual SourceSafe before, so how hard can it be :-)
Labels: enlightenment
Archives
June 2004
July 2004
August 2004
September 2004
October 2004
November 2004
December 2004
January 2005
March 2005
April 2005
May 2005
June 2005
July 2005
August 2005
September 2005
October 2005
November 2005
December 2005
January 2006
February 2006
March 2006
April 2006
May 2006
June 2006
July 2006
August 2006
September 2006
October 2006
November 2006
December 2006
January 2007
February 2007
March 2007
April 2007
May 2007
June 2007
July 2007
August 2007
September 2007
October 2007
November 2007
December 2007
January 2008
February 2008
April 2008
May 2008
June 2008
July 2008
August 2008
September 2008
October 2008
November 2008
December 2008
January 2009
February 2009
March 2009
April 2009
May 2009
June 2009
July 2009
August 2009
September 2009
October 2009
November 2009
January 2010
February 2010
April 2010
May 2010
June 2010
July 2010
August 2010
September 2010
February 2011
March 2011
May 2013
June 2013
