File: CONTRIBUTING.md

package info (click to toggle)
labwc 0.9.4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,020 kB
  • sloc: ansic: 35,102; perl: 5,837; xml: 814; sh: 162; python: 131; makefile: 12
file content (512 lines) | stat: -rw-r--r-- 18,079 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
- [1. How to Contribute](#how-to-contribute)
- [2. Debugging](#debugging)
  - [2.1 Backtraces](#backtraces)
  - [2.2 Debug Logs](#debug-logs)
  - [2.3 Output](#output)
  - [2.4 Input](#input)
- [3. Packaging](#packaging)
- [4. Coding Style](#coding-style)
  - [4.1 Linux Kernel Style Basics](#linux-kernel-style-basics)
  - [4.2 Devault Deviations](#devault-deviations)
  - [4.3 Labwc Specifics](#labwc-specifics)
    - [4.3.1 API](#api)
    - [4.3.2 The Use of GLib](#the-use-of-glib)
    - [4.3.3 The Use of GNU Extensions](#the-use-of-gnu-extensions)
    - [4.3.4 Naming Conventions](#naming-conventions)
    - [4.3.5 Switch Statements with Variable Declarations](#switch-statements-with-variable-declarations)
    - [4.3.6 Order of #includes](#order-of-includes)
- [5. Commit Messages](#commit-messages)
- [6. Unit Tests](#unit-tests)
- [7. Submitting Patches](#submitting-patches)
- [8. Native Language Support](#native-language-support)
- [9. Upversion](#upversion)

# How to Contribute

1. Report bugs as GitHub issues. We use a template prompting you to provide
   some sensible information such as what happened, what you expected to happen
   and steps to reproduce. If applicable try with default configuration. If
   you are able to, try debugging (guidelines below).

2. Submit patches as GitHub pull requests. If you wish to introduce significant
   changes or new features, consult the [scope document], discuss on IRC or via
   a GitHub issue first.

# Debugging

There is no one-way-fits-all method for debugging, so you have to use your
antennae and do some detective work.

This section contains some approaches which may prove useful.

## Backtraces

If the compositor crashes, a good starting point is to produce a backtrace by
building with ASAN/UBSAN:

```
meson setup -Db_sanitize=address,undefined build/
meson compile -C build/
```

## Debug Logs

Get debug log with `labwc -d`. The log can be directed to a file with `labwc -d
2>log.txt`

To see what is happening on the wayland protocol for a specific client, run it
with environment variable `WAYLAND_DEBUG` set to 1, for example `WAYLAND_DEBUG=1
foot`.

To see what the compositor is doing on the protocol run `labwc` nested (i.e.
start labwc from a terminal in another instance of labwc or some other
compositor) with `WAYLAND_DEBUG=server`. This filters out anything from clients.

For wayland clients, you can get a live view of some useful info using [wlhax].

## Output

If you think you've got a damage issue, you can run labwc like this:
`WLR_SCENE_DEBUG_DAMAGE=highlight labwc` to get a visual indication of damage
regions.

To emulate multiple outputs (even if you only have one physical monitor), run
with `WLR_WL_OUTPUTS=2 labwc` or similar. See [`wlroots/docs/env_vars.md`] for
more options.

For some types of bugs, it might be useful to find out which mesa driver (.so)
you are using. This can be done with `EGL_LOG_LEVEL=debug labwc 2>&1 | grep
MESA-LOADER`

To rule out driver issues you can run with `WLR_RENDERER=pixman labwc`

You can also get some useful system info with [drm_info].

## Input

Use `sudo libinput debug-events` to show input events.

From a terminal you can use `xev -event keyboard` and `wev -f wl_keyboard:key`
to analyse keyboard events

# Packaging

Some distributions carry labwc in their repositories or user repositories.

- @ptrcnull (Alpine)
- @ptr1337 (Arch)
- @b1rger (Debian)
- @jbeich (FreeBSD)
- @epsilon-0 (Gentoo)
- @spl237 (Raspberry Pi OS)
- @adcdam (Slackware)
- @bdantas (Tiny Core Linux)
- @Visone-Selektah (Venom Linux)
- @tranzystorekk (Void Linux)

kindly maintain the packages in their respective distro.

Let's keep them informed of new releases and any changes that relate to
packaging.  If you are maintaining a labwc package for another distro feel free
to open an issue so we can add you to this list.

# Coding Style

labwc is written in the [Linux kernel coding style] with a small number of
deviations to align with [Drew Devault's preferred coding style] namely:

1. [Function Declaration](https://git.sr.ht/~sircmpwn/cstyle#function-declarations)
2. [Braces for one-line statement](https://git.sr.ht/~sircmpwn/cstyle#brace-placement)
3. [Organisation of header #include statements](https://git.sr.ht/~sircmpwn/cstyle#header-files)
4. [Breaking of long lines](https://git.sr.ht/~sircmpwn/cstyle#splitting-long-lines)

The reasons for specifying a style is not that we enjoy creating rules, but
because it makes reading/maintaining the code and spotting problems much easier.

If you are new to this style and want to get going quickly, either just imitate
the style around you, or read the summary below and use `./scripts/check` to run
some formatting checks.

## Linux Kernel Style Basics

The preferred line length limit is 80 columns, although this is a bit soft.

Tabs are 8 columns wide. Indentation with spaces is not used.

Opening braces go on the same line, except for function definitions.

Put `*` with the identifier when defining pointers, for example `char *foo`

Spaces are placed around binary operators but not unary, like this:

```
int x = y * (2 + z);
foo(--a, -b);
```

`sizeof(*foo)` is preferred over `sizeof(struct foo)`

Use `if (!p)` instead of `if (p == 0)` or `if (p == NULL)`

Comments are written as follows:

```
/* This is a single-line comment */

/*
 * This is a multi-line comment which is much much much much much much
 * longer.
 */
```

When documenting functions in header files we use the [kernel-doc format]:

```
/**
 * function_name() - Brief description of function.
 * @arg1: Describe the first argument.
 * @arg2: Describe the second argument.
 *        One can provide multiple line descriptions
 *        for arguments.
 *
 * A longer description, with more discussion of the function function_name()
 * that might be useful to those using or modifying it. Begins with an
 * empty comment line, and may include additional embedded empty
 * comment lines.
 *
 * The longer description may have multiple paragraphs.
 *
 * Return: Describe the return value of function_name.
 *
 * The return value description can also have multiple paragraphs, and should
 * be placed at the end of the comment block.
 */
```

## Devault Deviations

Functions are defined as below with `name` on a new line:

```
return type
name(parameters...)
{
	body
}
```

Braces are mandatory even for one-line statements.

```
if (cond) {
	...
}
```

`#include` statements at the top of the file are organized by locality (`<>`
first, then `""`), then alphabetized.

When breaking a statement onto several lines, indent the subsequent lines once.
If the statement declares a `{}` block, indent twice instead. Also, place
operators (for example `&&`) on the next line.

```
	if (seat->pressed.surface && ctx->surface != seat->pressed.surface
			&& !update_pressed_surface(seat, ctx)
			&& !seat->drag_icon) {
		if (cursor_has_moved) {
			process_cursor_motion_out_of_surface(server, time_msec);
		}
		return;
	}
```

## Labwc Specifics

### API

We have a very small, modest API and encourage you to use it.

1. `znew()` - as a shorthand for calloc(1, sizeof()) with type checking
   [common/mem.h]

2. `zfree()` to zero after free - [common/mem.h]

3. `wl_list_append()` to add elements at end of lists - [common/list.h]

4. `wl_array_len()` to get number of elements in a `wl_array` [common/array.h]

5. `ARRAY_SIZE()` to get number of elements in visible array
   [common/macros.h]

[common/mem.h]: https://github.com/labwc/labwc/blob/master/include/common/mem.h
[common/list.h]: https://github.com/labwc/labwc/blob/master/include/common/list.h
[common/array.h]: https://github.com/labwc/labwc/blob/master/include/common/array.h
[common/macros.h]: https://github.com/labwc/labwc/blob/master/include/common/macros.h

### The Use of GLib

We try to keep the use of GLib pretty minimal for the following reasons:

- The use of GLib has been known to make AddressSanitiser diagnose false
  positives and negatives.
- Log messages coming from GLib functions look inconsistent.
- The use of GLib functions, naming-conventions and iterators in a codebase
  that is predominantly ANSI C creates a clash which makes readability and
  maintainability harder.
- Mixing gmalloc()/malloc() and respective free()s can create problems with
  memory pools [^1]

Having said that, with our use of cairo and pango we depend on glib-2.0 anyway,
so linking with it and making use of some of its helper functions comes for free,
and can keep the code simpler.

For example, if we were going to carry out extensive string manipulation,
GString and utf8 helpers would be okay. Some functions such as
`g_utf8_casefold()` would be pretty hard to write from scratch and are fine to
use. Having said that, labwc does not do much string-mangling.

The following functions are used today and are deemed acceptable by the core
devs:

- `g_shell_parse_argv()`
- `g_strsplit()`
- `g_pattern_match_simple()`

When using these types of functions it is often desirable to support with some
GLib code, which is okay provided it is kept local and self-contained. See
example from `src/theme.c`:

```
static bool
match(const gchar *pattern, const gchar *string)
{
	GString *p = g_string_new(pattern);
	g_string_ascii_down(p);
	bool ret = (bool)g_pattern_match_simple(p->str, string);
	g_string_free(p, true);
	return ret;
}
```

### The Use of GNU Extensions

We avoid [GNU C extensions] because we want to fit into the ecosystem
(wayland and wlroots) we live in.

We do use `__typeof__` which strictly speaking is a GNU C extension (`typeof`)
but through the use of `__` is supported by gcc and clang without defining
`_GNU_SOURCE`. The justification for this is that Wayland uses it, for example
in the [`wl_container_of()`] macro which is needed in `wl_list*` and it
does provide pretty big benefits in terms of type safety.

We compile with `-std=c11` because that's what 'wlroots' uses, and we do not
want to increase the entry-level for OSs without good reason (and currently
we can't think of one).

### Naming Conventions

There are three types of coordinate systems: surface, output, and layout — for
which the variables (sx, sy), (ox, oy) and (lx, ly) are used respectively in
line with wlroots.

With the introduction of the scene-graph API, some wlroots functions also use
node coordinates (nx, ny), but we prefer (sx, sy) where possible.

We do not worry about namespace issues too much and we try to not make the code
a pain to use just to uniquify names. If we were writing a library we would
prefix public functions and structs with `lab_`, but we are not. We do however
prefix public function names with the filename of the translation unit.  For
example, public functions in `view.c` begin with `view_`.

We do start enums with `LAB_`

We use the prefix `handle_` for signal-handler-functions in order to be
consistent with sway and rootston. For example
`view->request_resize.notify = handle_request_resize`

### Switch Statements with Variable Declarations

Unlike many modern languages, C doesn't create a new scope after `case FOO:`.
Therefore, we wrap codes following `case FOO:` that include variable
declarations with braces (`{..}`) to reduce variable scopes. For example:

```
switch (x) {
case FOO: {
	int y = 1;
	break;
}
case BAR: {
	do_something();
	int z = 1;
	break;
}
case BAZ:
	do_something();
	break;
}
```

But please also consider refactoring the code into a separate function if it
becomes lengthy.

### Order of #includes

In new files, please order `#include` lines as follows:

- In each `.c` file, first include the matching `.h` file, if there is
  one. For example, `#include "common/font.h"` should come first in
  `src/common/font.c`. This practice helps to ensure that each header
  compiles cleanly on its own, without implicit dependencies on other
  headers being included first.

- Then list any "system" headers (those not part of labwc) in alphabetical
  order, using angle brackets. This includes 3rd-party library headers
  such as `<cairo.h>`, as well as wlroots headers.

- Then list any other labwc headers in alphabetical order, using quotation
  marks and relative to the `include/` folder. Subfolders below `include/`,
  such as `common/`, should be specified even when including one header
  from another in the same folder (for example, `#include "common/buf.h"`
  from `include/common/grab-file.h`).

# Commit Messages

The log messages that explain changes are just as important as the changes
themselves. Try to describe the 'why' to help future developers.

Write [commit messages] like so, keeping the top line to this sort of syntax:

```
cursor: add special feature
```

This first line should:

- Be a short description
- In most cases be prefixed with "area: " where area refers to a filename
  or identifier for the general area of the code being modified.
- Not capitalize the first word following the "area: " prefix, unless
  it's a name, acronym, or similar.
- Skip the full stop

And please wrap the commit message at max 74 characters, otherwise `git log`
and similar look very weird. URLs and other references are exempt.

# Unit Tests

## Introduction

The tests live in the `t/` directory.

In the bigger scheme of validating that the compositor meets users' needs, unit
tests do not contribute a great deal. However, they have a role to play in
providing some verification that stand-alone functions behave as expected.

On this project, writing unit-tests is not compulsory, nor do we measure
coverage. The inclusion of the t/ directory does not signify a move towards
test-driven development. We intend to use unit tests sparingly, and only when
devs find them useful.

## Usage

From repo top level directory:

    meson setup -Dtest=enabled build
    meson compile -C build/
    meson test --verbose -C build/

# Submitting patches

Base both bugfixes and new features on `master`.

# Native Language Support

## Translators

### Weblate Instance

Translators can create an account at [LXQt Weblate](https://translate.lxqt-project.org/projects/labwc/labwc/)
and use the web interface. Adding new languages should work, otherwise the
administrators can be contacted. Suggestions for improving existing translations
can be added without account.

### GitHub Pull Request

Translators can add their `MY_LOCALE.po` files to the `po` directory
based on `po/labwc.pot`, and issue a pull request. To do this they can
generate their `MY_LOCALE.po` file in a few steps:

1. Edit the `po/LINGUAS` file to add their locale code in English
   alphabetical order to the field of locale codes.
2. Copy the `po/labwc.pot` to `po/MY_LOCALE.po`
3. Edit the newly generated `MY_LOCALE.po` file with some of their
contact and locale details in the header of the file. Then, add the
translation strings under each English string.

[See this tutorial for further guidance](https://www.labri.fr/perso/fleury/posts/programming/a-quick-gettext-tutorial.html)

## Coders

Code contributors may need to update relevant files if their additions
affect UI elements (at the moment only `src/menu/menu.c` and
`src/config/rcxml.c`). In this case the `po/labwc.pot` file needs to be
updated so that translators can update their translations. Remember,
many translators are _not_ coders!

The process is fairly trivial however does involve some manual steps.

1. After adding and testing your code additions to satisfaction, backup
`po/labwc.pot`. You need the custom header from that file for the newly
generated .pot file in the next step.

2. From the root of the repository run this:

```
xgettext --keyword=_ --language=C --add-comments -o po/labwc.pot src/menu/menu.c src/config/rcxml.c
```

This generates a new pot file at `po/labwc.pot`

3. Copy the header from the original `labwc.pot` to the new one, keeping
the newly generated dates, check for sanity and commit.

# Upversion

It is generally only the lead-maintainer who will upversion, but in order
not to forget any key step or in case someone else needs to do it, here
follow the steps to be taken:

1. If appropriate, update `revision` in `subprojects/wlroots.wrap` and run
   `git commit -m 'wlroots.wrap: use A.B.C'`
2. Update `NEWS.md` with the release details and run
   `git commit -m 'NEWS.md: update notes for X.Y.Z'`
   Note: If new dependencies are needed, make this clear.
3. In `meson.build`, update the version, and (if required) the wlroots
   dependency version. Then run `git commit -m 'build: bump version to X.Y.Z'`
4. Run `git tag -a X.Y.Z`. The first line of the commit message should be
   "labwc X.Y.Z" and the body should be the `NEWS.md` additions removing
   hash characters (#) from the headings as these will otherwise be
   ignored by git.
5. On GitHub, create a 'Release' as some distros use this as a trigger. Set it
   as 'latest release'.

[scope document]: https://github.com/labwc/labwc-scope#readme
[`wlroots/docs/env_vars.md`]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/docs/env_vars.md
[wlhax]: https://git.sr.ht/~kennylevinsen/wlhax
[drm_info]: https://github.com/ascent12/drm_info
[Drew Devault's preferred coding style]: https://git.sr.ht/~sircmpwn/cstyle
[Linux kernel coding style]: https://www.kernel.org/doc/html/v4.10/process/coding-style.html
[kernel-doc format]: https://docs.kernel.org/doc-guide/kernel-doc.html
[commit messages]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/CONTRIBUTING.md#commit-messages
[GNU C extensions]: https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
[`wl_container_of()`]: https://github.com/wayland-project/wayland/blob/985ab55d59db45ea62795c76dff5949343e86b2f/src/wayland-util.h#L409

[^1]: The reference documentation for GLib notes that:
      "It's important to match g_malloc() with g_free(), plain malloc() with
      free(), and (if you're using C++) new with delete and new[] with
      delete[]. Otherwise bad things can happen, since these allocators may use
      different memory pools (and new/delete call constructors and
      destructors)."
      See: https://docs.gtk.org/glib/memory.html