Skip to content
This repository has been archived by the owner on Nov 12, 2023. It is now read-only.

Latest commit

 

History

History
162 lines (136 loc) · 7.3 KB

CONTRIBUTING.md

File metadata and controls

162 lines (136 loc) · 7.3 KB

GitHub pull requests Issues CI status

License: MPL-2.0 Documentation (dev build) XRB GitHub project

Contributing to XRB

First of all, thank you for looking into contributing to XRB. XRB is an ambitious project, designed to be community-driven from the beginning. Both users and contributors are the heart of any community-driven project, and while XRB might not yet be ready for users, contributions can help bring that goal much closer!

Ask questions!

If you ever have any questions about contributing, whether that be about the X11 protocol, about Rust, about how to submit contributions, or anything else, please feel free to ask! You can ask questions by either creating a discussion here on GitHub, or by asking in the #xrb-dev-chat channel in the Discord server!

Interpreting the X11 protocol

Since XRB is an implementation of the messages, types, and data structures found in the X11 protocol, you're probably going to need to understand the protocol for many areas of working on XRB. That's where this section comes in.

Firstly, the X11 protocol has a glossary section at the end which explains many of the terms used both throughout the protocol and throughout XRB.

Note that there are some terms which we have opted to rename in XRB to make them clearer, especially for modern conventions and jargon. One such example is that in the X11 protocol, 'pointer' refers to what we would now call the cursor, while 'cursor' refers to the appearance of the cursor on the screen.

The protocol encoding section of the X11 protocol is one of the most important sections relevant to the development of XRB. It defines the encoding of various types used throughout the X11 protocol in bytes. It does, however, make some rather... odd... choices, at times, with how these types are encoded, as well as how that encoding is presented.

Components

'Component' refers to something encoded. That might be a field, or it might be some other data, such as the length of a message, the code uniquely identifying its type of message, etc.

In the protocol encoding section, each component's encoding is written like so:

N	TYPE	component_name

...unless that component has a numeric value which can be determined from the rest of the components, or is a constant, in which case it is written as:

N	value	component_name

In these examples, N refers to the number of bytes the component takes up, TYPE refers to the type of the data, and value refers to an expression to determine the data. component_name refers to the name of the component.

Typically, in the macro syntax used in XRB, the former represent fields, and the latter represent 'let elements'. For example, this:

4	WINDOW	parent

is converted to a field in the macro syntax:

pub parent: Window,

While this:

4       m               number of CHARINFOs in char-infos
12m     LISTofCHARINFO  char-infos

is converted into:

let charinfos_len: u32 = charinfos => charinfos.len() as u32,

#[context(charinfos_len => *charinfos_len as usize)]
pub charinfos: Vec<CharInfo>,

The protocol encoding section is a complex topic to cover, as is the use of the macro syntax, so this section of the contributing guide is yet to be fleshed out. For now, you can look at types in the protocol encoding section and try to find their equivalents in XRB's codebase. Some of the best examples would be comparing the events in the events section of the protocol encoding section to the events defined in x11::event.

Code style

Placement of attributes

Many types and fields in XRB use attributes. To keep the source code consistent and easily readable, attributes should be put after doc comments.

For example, do this:

/// A foo which does bar.
#[doc(alias = "baz")]
#[derive(Debug, Hash, X11Size)]
pub struct Foo {
	/// Data which represents xyz.
	#[custom_attribute]
	pub data: Any,

	/// The other field within this `Foo`.
	pub other_field: Any,
}

But not this:

#[derive(Debug, Hash, X11Size)]
/// A foo which does bar.
#[doc(alias = "baz")]
pub struct DoNotDoThis {
	#[custom_attribute]
	/// Data which represents xyz.
	pub data: Any,

	/// The other field within this `DoNotDoThis`.
	pub other_field: Any,
}

This consistently groups related syntax together - you know you'll always find the attributes after the documentation, if the documentation is quite long for example, and that you're looking at all of the attributes at once.

Useful resources