Skip to content

Latest commit

 

History

History
192 lines (145 loc) · 6.8 KB

HACKING

File metadata and controls

192 lines (145 loc) · 6.8 KB

HACKING

If you want to contribute to herbstluftwm, this file is for you!

Contributing

Beside writing code you can help herbstluftwm by testing, reporting bugs, writing/fixing documentation (e.g. by fixing spelling mistakes) or packaging it for distributions.

Coding style

The coding style is similar to the Linux-kernel style with some changes:

  • Use 4 spaces instead of tabs.

  • Do not add any trailing spaces at the end of a line.

  • Data type names are CamelCase

  • Globals must be prefixed with g_

  • If a function returns success or failure, then encode it in a bool (from stdbool.h). Only use main()-like exit codes (0 = success, non zero = failure) for commands.

  • Always typedef struct, e.g.:

    typedef struct {
        int         first_member;
        long long   other_member;
    } MyStruct;

Build system

The build system mainly is one Makefile. To check which source files depend on which header files it uses dependency files src/.d and ipc-client/.d (one for each C source file) which are generated by default.

Note: If you switch a branch, the dependency files are not marked as dirty! This may cause unresolvable dependencies e.g. if you switch from a branch with a new header file to a branch without it. So after switching the branch, you always should remove dependency files by running:

make cleandeps

Alternate build system: CMake

CMake has been included as an alternative build-system, that has some advantages including:

  • Project file generation for IDEs.

  • Flexible configuration.

  • Multiple out of source builds (debug, release…​ etc).

You can use CMake with the following commands (assuming you’re in the herbstluftwm repository root):

mkdir build
cd build
cmake ..
make
make install

The choice of build here is arbitrary, you can put your build directory(s) wherever you like.

Note that CMake support is currently experimental.

Sending patches

You can use git to make commits and create patches from them via the command git format-patch. Always specify your full name and a valid e-mail address in the author field. The commit description must consist two parts, separated by an empty line:

  • A mandatory short description in imperative form, e.g.: "Do things in this or that way". The description must not exceed 50 characters.

  • An optional longer description consisting of full sentences. This is only needed if the commit introduces non-trivial changes.

When introducing new features, always

  • add documentation for it in doc/herbstluftwm.txt (or doc/herbstclient.txt).

  • document the change (e.g. "new command …​") in the NEWS file.

You can send those patches to the mailing list[1] or via the irc[2].

[1] hlwm@lists.herbstluftwm.org
[2] #herbstluftwm on irc.freenode.net

Mailing list

The main mailing list for general development, discussion, release announcements is:

hlwm@lists.herbstluftwm.org

You can subscribe by sending a mail with subscribe in the subject to

hlwm-request@lists.herbstluftwm.org

or by using the web interface at:

https://lists.schokokeks.org/mailman/listinfo.cgi/hlwm

Debugging with valgrind

If you use tools like valgrind, then it is needed to turn of the memory optimization settings for glib. So export this before running herbstluftwm within valgrind:

export G_SLICE=always-malloc
export G_DEBUG=gc-friendly
valgrind --leak-check=full ./herbstluftwm  -c share/autostart

Internal structure

The main modules (i.e. source file + header file) communicate like this if a key is pressed or if a command is called via herbstclient:

      X11
       |
       V
   +--------+  key  +-----+ call  +---------+
   |  main  |------>| key |------>| command |
   +--------+ event +-----+       +---------+
       \                    output /  ^
IPC-Call\      +------------+<----'  / Execute
 -Window `---->| ipc-server |-------'  IPC-Call
   -Event      +------------+
                      |
                      V
                     X11

herbstclient is rather simple:

Command-Line-   +------+
  Arguments --->| main |----.
                |      |   X11
   stdout  <----|      |<---'
                +------+

Objects

There is one tree of objects in herbstluftwm to provide an easy access for the user to many options. The usage is similar to kobjects known from the Linux kernel. The most important functions are:

  • HSObject* hsobject_create_and_link(HSObject* parent, char* name): Create a new child object under parent. If name already exists it will be replaced.

  • void hsobject_unlink_and_destroy(HSObject* parent, HSObject* child): Remove all child entries at the parent object and destroys the object afterwards.

  • HSObject* hsobject_root(): Return the root node of the object tree.

  • void hsobject_set_attributes(HSObject* obj, HSAttribute* attributes): Set the attributes of an object, attributes is an array terminated by ATTRIBUTE_LAST.

For a full list see src/object.h. Each object has a certain set of attributes. Each attribute has a type, which is defined by the according constructor:

  • ATTRIBUTE_BOOL(N, V, CHANGE): accords to bool

  • ATTRIBUTE_INT(N, V, CHANGE): accords to int

  • ATTRIBUTE_UINT(N, V, CHANGE): accords to unsigned int

  • ATTRIBUTE_STRING(N, V, CHANGE): accords to GString*

  • ATTRIBUTE_CUSTOM(N, V, CHANGE): accords to HSAttributeCustom

  • ATTRIBUTE_CUSTOM_INT(N, V, CHANGE): accords to HSAttributeCustomInt

N is the name of the attribute as displayed to the user, V is the value in the struct; the macro automatically prepends a & to it to get the pointer. To check if attributes are changed properly (or to do certain actions after a change), the callback CHANGE is definied:

GString* (*on_change)  (struct HSAttribute* attr);

It is called after the attribute is changed by the user. If this function returns something != NULL, this string is put as an error message to the user and the original value is restored. To mark a attribute as read-only for the user, give ATTR_READ_ONLY as CHANGE.

The "custom" attributes do not give a pointer to a variable but give a function that returns the variable. HSAttributeCustom returns a GString, HSAttributeCustomInt an int.

typedef void (*HSAttributeCustom)(void* data, GString* output);
typedef int (*HSAttributeCustomInt)(void* data);

They both get a data-pointer, it is exactly the data-pointer you can give as the data-member of the HSObject struct. For an example see, add_tag(char*) in src/tag.c, it covers most cases.