In this mini-guide I'll try to explain how does my program works. Reading this is not so useful as read the comments in the source code.

Sorry if my english is not good, I'm not a native english speaker. A spanish version of this document is also available.

The openbox config file (rc.xml/lxde.xml)

First of all, lets have a look to the openbox config file (*~/.config/openbox/rc.xml*)

<?xml version="1.0" encoding="UTF-8"?>
<openbox_config>
 <resistance>
   (...)
 </resistance>
 <focus>
   (...)
 </focus>
 <placement>
   (...)
 </placement>
 <theme>
   (...)
 </theme>
 <desktops>
   (...)
 </desktops>
 <resize>
   (...)
 </resize>
 <margins>
   (...)
 </margins>
 <dock>
   (...)
 </dock>
 <keyboard>
   (...)
 </keyboard>
 <mouse>
   (...)
 </mouse>
 <menu>
   (...)
 </menu>
 <applications>
   (...)
 </applications>
</openbox_config>

Ok, the section that I'm interested in is <keyboard> , inside <openbox_config> .

Inside the <keyboard> element there are a lot of <keybind> elements. There are some examples:

<keyboard>

 <keybind key="C-A-Left">
   <action name="DesktopLeft"><dialog>no</dialog><wrap>no</wrap></action>
 </keybind>

 <keybind key="W-F1">
   <action name="Desktop"><desktop>1</desktop></action>
 </keybind>

 <keybind key="W-d">
   <action name="ToggleShowDesktop"/>
 </keybind>

 <keybind key="A-Escape">
   <action name="Lower"/>
   <action name="FocusToBottom"/>
   <action name="Unfocus"/>
 </keybind>

 <keybind key="W-e">
   <action name="Execute">
     <startupnotify>
       <enabled>true</enabled>
       <name>Konqueror</name>
     </startupnotify>
     <command>kfmclient openProfile filemanagement</command>
   </action>
 </keybind>


   <keybind key="C-A-Tab">
     <action name="NextWindow">
       <panels>true</panels>
       <desktop>true</desktop>
       <dialog>true</dialog>
       <bar>true</bar>
       <raise>false</raise>
       <allDesktops>false</allDesktops>
       <linear>false</linear>
       <finalactions>
         <action name="Focus" />
         <action name="Raise" />
         <action name="Unshade" />
       </finalactions>
     </action>
   </keybind>

</keyboard>

KeyBinds

A <keybind> element represents a key combination that will launch at least one action. As you can see, every <keybind> element has the key property. This is the key combination that activate the keybind.

A <keybind> may have one or more elements <action> or <keybind> inside.

A <keybind> inside another <keybind> is a keychain .

Actions

An <action> element represents an action that the window manager will execute. For example close a window, change the desktop, or run a command. Every <action> has a name property, that represent the action type. Some action types have parameters, for example:
   <action name="DesktopLeft"><dialog>no</dialog><wrap>no</wrap></action>
This action have 2 parameters ( <dialog> and <wrap> ), and its type is "DesktopLeft"

Some actions also have a <finalactions> element. This is a list of actions that will be executed after the main action.

Parameters

There are five parameter types:

Boolean

on/off, yes/no, true/false
<wrap>no</wrap>

Numeric

An integer (positive or negative)
<desktop>1</desktop>

String

<command>kfmclient openProfile filemanagement</command>

Startup notify

(Used only for Execute action). This is a bit more complex, because it has 4 "subparameters" :
       <startupnotify>
         <enabled>true</enabled>
         <wmclass>window class</wmclass>
         <name>start network services</name>
         <icon>/usr/share/icons/Crux/24x24/places/network.png</icon>
       </startupnotify>

Edge

(Used only for Resize action). It can take one of the next values:

Final actions list

Some actions have a <finalactions> element. This is a list of actions that will be executed after the main action.
       <finalactions>
         <action name="Focus" />
         <action name="Raise" />
         <action name="Unshade" />
       </finalactions>

Ok, now that we know about the XML config file structure, let's start with the program design.

The Container class (Container.cpp)

The config file is a XML tree. So the first that I wrote was a class to represent a tree structure. A Container can store any type of data, including other Container s. For example, a <keybind> Container can store some <action> Containers. Those <action> Containers can store Parameters.

The Container class is defined in the file "Container.cpp". A Container have methods for insert elements, remove elements, set (and read, of course) a name for the Container, and set (and read, of course) a type for every single element. Let's see an example code:

Container *keybind;
Container *action;
Parameter *dialog;

dialog = new Parameter("dialog", FALSE); //Create a parameter <dialog>false</dialog>

action = new Container(); //Create a Container that represents an action
action->setName( (void*) "DesktopLeft" ); //Set the action name
action->insertElement(TYPE_PARAMETER, (void*) dialog); //Insert the Parameter into the action

keybind = new Container(); //Create a keybind
keybind->setName( (void*) "C-A-Left" ); //set the key="C-A-Left" property (The setName() method is useful for that)
keybind->insertElement(TYPE_ACTION, (void*) action ); //Insert the action into the keybind

NOTES:

Keybinder Core (keybinder_core.cpp/.h)

All the classes and methods to store, create, delete, and modify elements (like KeyBinds, Actions, etc) are defined in the file keybinder_core.cpp, and its header file, keybinder_core.h. In these files there is no GUI related code.

Adapted Containers

Adapted Containers are child classes of Container class.

Every AdaptedContainers has the method writeXML() . This method write the XML output to the openbox config file.

Every AdaptedContainers (except Keyboard) when is deleted removes itself from its parent in the XML tree.

The children classes of AdaptedContainer are:

Keyboard class

This is a Object that represent a <keyboard> element

To create a Keyboard, you have to specify a path to the config file, for example:

Keyboard *k = new Keyboard((char*)"/home/user/.config/openbox/rc.xml");
It will automatically read this file, and create all the children KeyBinds

KeyBind class

This is a Object that represent a <keybind> element

If it was created by a Keyboard object, it will create automatically all children KeyBinds (keychains) and Actions

Also, it can be created specifying its key combination and parent

KeyBind *keybind = new KeyBind((char*)"C-F3", parent); //Example

Action class

This is a Object that represent an <action> element

If it was created by a KeyBind object, it will create automatically all children Parameters, and FinalActionsList.

Also, it can be created specifing its action type and parent

Action *action = new Action((char*)"Close", parent ); //Example

FinalActionsList class

This is a Object that represent a <finalactions> element

If it was created by an Action object, it will create automatically all children Actions.

Also it's possible to create an empty one.

action->finalActionsList = new FinalActionsList();

Parameters

The parameter are the lower level in the XML tree. They represent a setting/option for an Action. There are several constructors to create them:

Parameter(char *name_, char *value_, Container *parent_); //String Parameter
Parameter(char *name_, int value_, Container *parent_); //Numeric Parameter
Parameter(char *name_, EdgeType value_, Container *parent_); // Edge Parameter
Parameter(char *name_, Boolean value_, Container *parent_); //Boolean Parameter
Parameter(xmlDocPtr doc, xmlNodePtr node, Container *parent_); //This constructor will be called automatically by its parent Action

Like an AdaptedContainer, a Parameter has a writeXML() method, and when it is deleted, its destructor removes itself from its parent in the XML tree.

StartupNotify

StartupNotify is a class for a special Parameter type. (See the explanation in the "Openbox config file" section)

Keybinder GUI (keybinder_GUI.cpp/.h)

All the GUI related code is in keybinder_GUI.cpp and keybinder_GUI.h files. All the GUI related class has the GUI_ prefix.

Drawings

A Drawing is a class used to draw an AdaptedContainer. There are three Drawing classes:

Note: The Parameters and FinalActionsList haven't a Drawing class because they are not shown in the main window. They can be managed in an Editor window.

GUI_KeyboardDrawing

This is a class used for draw a Keyboard. It has a scrolled window with GUI_KeyBindDrawings inside, and buttons "Add", "Apply" and "Clear" for manage its children. Its constructor is:
GUI_KeyboardDrawing::GUI_KeyboardDrawing(Keyboard *keyboard_, GtkWidget *embedIn);

When a GUI_KeyboardDrawing is created, it automatically creates all children GUI_KeyBindDrawings, and stores it in the subKeyBindDrawings Container.

GUI_KeyBindDrawing

This is a class used for draw a KeyBind. It has a header (buttons that represents the key combination), and a GtkExpander, in which will be drawn its children GUI_ActionDrawings or GUI_KeyBindDrawings

When a GUI_KeyBindDrawing is created, it automatically creates all children GUI_KeyBindDrawings (keychains) and GUI_ActionDrawings, and stores them in subKeyBindDrawings and subActionDrawings Containers.

When a GUI_KeyBindDrawing is destroyed, it destroys its children drawings, KeyBind and Editor, and removes itself from its parent Drawing (GUI_KeyboardDrawing, or GUI_KeyBindDrawing if is a keychain)

GUI_ActionDrawing

This is a class used for draw an Action. It has a "settings" button and a label with the Action description.

When a GUI_ActionDrawing is destroyed, it destroys its children drawings, Action and Editor, and removes itself from its parent Drawing (GUI_KeyBindDrawing, or GUI_ActionEditor if is a final action )

Editors

Editors are a classes for draw a window used for edit an KeyBind (keys combination) or an Action (Its Parameters and final actions). When a Editor window is closed, the KeyBind or Action is updated. The constructors needs an Drawing as argument.

There are two editor classes:

GUI_KeyBindEditor

The window shows buttons for enable/disable the modifier keys (ctrl, alt, shift, win), and a combobox for select a key. It should be rewritten for add direct keyboard input support.

GUI_ActionEditor

The window shows widgets for editing the Action Parameters, and a editable list of final actions.

Menus

KeyBindMenu

ActionMenu

ActionSelectorMenu

Action Models (keybinder_actionModel.h)

In keybinder_actionModel.h is defined a "database array" that stores the allowed Action types, their descriptions, default Parameters (and respective descriptions), and default final actions.

For understanding its format, see this example line:

{"SendToDesktop", "Send the window to another desktop", "N desktop 1| B follow T", "desktop: Desktop number| follow: Change to desktop", NULL},

A '|' character, followed by an space is a separator.

Use NULL for leave an entry undefined. (Like in example)

Definitions:

Signal Handlers (signal_handlers.cpp/.h)

In the file signal_handlers.cpp are defined the functions used for handle the Gtk events.