An atom in X11
, is of type Atom
, which is defined in the <X11/Xatom.h>
header, as :
typedef unsigned long Atom; /* Also in Xdefs.h */
An atom is 32
bits, the reason, that long
was chosen, is because the C
standard, defines it, as having a minimum length of 32
bits. This being said, an atom is used, as a way, to identify a string, to be, or which is stored, at the server.
The process of storing a string on the server, and getting back an atom for it, is called interning.
Table of Contents
Interning an atom
There are two functions, which can do atom interning , which in other words is, getting an identifier, for a string stored on a server, and they are : XInternAtom
and XInternAtoms
.
The XInternAtom
function, has the following signature:
Atom XInternAtom (Display* display, char *atom_string_name, Bool only_if_exists );
So the function, takes as arguments: the display, which is simply a reference to a connection, established with the X
server, a string, which can be thought of, as the name of the atom, and a boolean value, named only_if_exists
. The function returns an atom, identifying the passed string.
if only_if_exists
, is set to true, this means, that if the string does not already exist on the server, it is not going to be stored there, so this function will return a None
value.
if only_if_exists
, is set to false, and the string does not exist on the server, then it is going to be stored, and an atom is returned for that string. if the string does exist, then the atom identifying it, is returned.
The value of None
, is defined in the <X11/Xatom.h>
header, as :
#define None 0L /* universal null resource or null atom */
The XInternAtoms
function, has the following signature:
Status XInternAtoms (Display* display, char** atom_string_names, int count, Bool only_if_exists, Atom* atoms_return );
The passed in arguments, are the display, which is a reference, to a connection to the server, atom_string_names
, which is a pointer to a C
string , count, which is the number of strings, pointed to by, atom_string_names
, only_if_exists
, which has the same meaning, as the one described, in the XInternAtom
function, and finally atoms_return
, which is an array, which will be filled, with the atoms, identifying each passed string.
If not all passed strings, have an atom allocated to them, then the value of the returned Status
, is a zero value, which symbolizes error, otherwise, and if each passed string, had an atom allocated to it, then the Status
, has a non zero value.
Both of XInternAtom
and XInternAtoms
functions, can cause a BadAlloc
error, if the server, was not able to allocate memory, and they can cause a BadValue
error, which happens, if an argument numerical value, is outside of the range, accepted by the server.
The allocated atom, will remain defined, until all the connections, to the server are closed, even if the client who has created this atom, exits.
An example of using both the XInternAtom
and XInternAtoms
functions is:
#include <X11/Xlib.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> int main (int argc , char* argv[ ] ){ Display* display; char* connection_string = NULL; display = XOpenDisplay (connection_string ); if (display == NULL ){ fprintf (stderr, "Error: XOpenDisplay (%s )\n", connection_string == NULL ? "NULL" : connection_string ); exit (EXIT_FAILURE );} char* string_life = "Life is cool"; Atom atom_life; atom_life = XInternAtom (display, string_life, false ); printf ("atom_life is : %lu\n", atom_life ); int num_string =3; char* strings [ ] = {"First string", "Second string", "Third string" }; Atom atom [num_string ]; int status = XInternAtoms (display, //The connection strings, //The strings num_string, // count of strings false, // only_if_exists atom ); if (status == 0 ){ fprintf (stderr, "Error: XInternAtoms \n" ); exit (EXIT_FAILURE );} for (int i = 0; i < num_string; i++ ) printf ("atom [%d ] is %lu\n", i, atom [i ] ); exit (EXIT_SUCCESS ); } /* Output: atom_life is : 343 atom [0 ] is 344 atom [1 ] is 345 atom [2 ] is 346 */
Getting an atom string value
As explained earlier, an atom is simply an integral value, with which a server has associated a string, so you can think of the string, as the atom name.
This being said, what if we wanted to do the inverse, so having an atom, we want its name. Well to do that, there are two functions, that can be used : XGetAtomName
and XGetAtomNames
.
The signature of the XGetAtomName
function is :
char* XGetAtomName (Display* display, Atom atom );
The arguments to the the XGetAtomName
function, are the display, which is just a reference , to the connection to the server, and the atom, for which you want its name returned.
The function returns, the string associated with the passed in atom. This string can be freed, once done using it, by using the XFree
function.
The XGetAtomNames
function, has the following signature:
Status XGetAtomNames (Display* display, Atom* atoms, int count, char** names_return );
The arguments are, the display, which is a reference, to the connection to the server, atoms
, which is a pointer to an Atom
, so this is a pointer to the atoms, that you wish, to get their string representations, count, which is the number of atoms, pointed by atoms
, names_return
, which is a pointer to an array of strings, in which the gotten atom names, are stored.
The value returned by XGetAtomNames
, is non zero, if the function was able to get a name, for each of the passed in atoms, and a zero value is returned, if the function, was not able to get a name, for each of the passed in atoms.
Both of the XGetAtomName
, and XGetAtomNames
functions, can cause a BadAtom
error, if an atom pointed by atoms
, is not recognized by the server, as referring to a name, stored on the server.
An example of using both the XGetAtomName
, and XGetAtomNames
functions, is:
#include <X11/Xlib.h> #include <X11/Xatom.h> #include <stdio.h> #include <stdlib.h> int main (int argc , char* argv[ ] ){ Display* display; char* connection_string = NULL; display = XOpenDisplay (connection_string ); if (display == NULL ){ fprintf (stderr, "Error: XOpenDisplay (%s )\n", connection_string == NULL ? "NULL" : connection_string ); exit (EXIT_FAILURE );} char* atom_name; atom_name = XGetAtomName (display, XA_PRIMARY ); printf ("Name of atom XA_PRIMARY %lu is : %s\n", XA_PRIMARY, atom_name ); XFree (atom_name ); int num_atoms = 3; char* atom_names [num_atoms ]; Atom atoms [ ] = {XA_STRING, XA_COLORMAP, XA_WM_SIZE_HINTS }; int status = XGetAtomNames (display, atoms, num_atoms, atom_names ); if (status == 0 ){ fprintf (stderr, "Error: XGetAtomNames \n" ); exit (EXIT_FAILURE );} printf ("Name of atom XA_STRING %lu is : %s\n", XA_STRING, atom_names [0 ] ); printf ("Name of atom XA_COLORMAP %lu is : %s\n", XA_COLORMAP, atom_names [1 ] ); printf ("Name of atom XA_WM_SIZE_HINTS %lu is : %s\n", XA_WM_SIZE_HINTS, atom_names [2 ] ); exit (EXIT_SUCCESS );} /* Output: Name of atom XA_PRIMARY 1 is : PRIMARY Name of atom XA_STRING 31 is : STRING Name of atom XA_COLORMAP 7 is : COLORMAP Name of atom XA_WM_SIZE_HINTS 41 is : WM_SIZE_HINTS */
In the previous example, some predefined atoms, in the <X11/Xatom.h>
header, were used, these are just some atoms, to which the server associates some names.
For the predefined atoms, instead of using the XGetAtomName
, or XGetAtomNames
functions, to get their associated strings, you could just remove, the XA_
part, to guess what the associated string is.
So for example, if the atom was defined in <X11/Xatom.h>
, as XA_COLORMAP
, then the string associated with it, would be COLORMAP
.